diff --git a/.travis.yml b/.travis.yml index 3b8d0dc0c..add6c0eac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,30 @@ sudo: required before_script: - sudo apt-get -qq update - - sudo apt-get install -qq build-essential cmake libfftw3-dev libmbedtls-dev libpcsclite-dev libboost-program-options-dev libconfig++-dev libsctp-dev + - sudo apt-get install -qq build-essential cmake libfftw3-dev libmbedtls-dev libpcsclite-dev libboost-program-options-dev libconfig++-dev libsctp-dev colordiff language: cpp + +addons: + apt: + sources: + - llvm-toolchain-trusty-8 + - key_url: 'http://apt.llvm.org/llvm-snapshot.gpg.key' + packages: + - clang-format-8 + script: + - sudo ln -s /usr/bin/clang-format-diff-8 /usr/bin/clang-format-diff + - git remote set-branches --add origin master + - git fetch + - | + if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then + # Run only for PRs because target branch is needed to do the clang-format check + echo "Checking clang-format between TRAVIS_BRANCH=$TRAVIS_BRANCH and TRAVIS_PULL_REQUEST_BRANCH=$TRAVIS_PULL_REQUEST_BRANCH" + ./run-clang-format-diff.sh "$TRAVIS_BRANCH" "$TRAVIS_PULL_REQUEST_BRANCH" + else + echo "Skipping clang-format check" + fi - mkdir build - cd build - cmake -DRF_FOUND=True .. diff --git a/CHANGELOG b/CHANGELOG index 0f231f634..deec9f582 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,17 @@ Change Log for Releases ============================== +## 19.09 + * Add initial support for NR in MAC/RLC/PDCP + * Add sync code for NB-IoT + * Add support for EIA3/EEA3 (i.e. ZUC) + * Add support for CSFB in srsENB + * Add adaptation layer to run TTCN-3 conformance tests for srsUE + * Add High Speed Train model to channel simulator + * Rework RRC and NAS layer and make them non-blocking + * Fixes in ZMQ, bladeRF and Soapy RF modules + * Other bug-fixes and improved stability and performance in all parts + ## 19.06 * Add QAM256 support in srsUE * Add QoS support in srsUE diff --git a/CMakeLists.txt b/CMakeLists.txt index 73c3613cb..f38e8b807 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,7 @@ set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") # Generate CMake to include build information configure_file( - ${CMAKE_SOURCE_DIR}/cmake/modules/SRSLTEbuildinfo.cmake.in + ${PROJECT_SOURCE_DIR}/cmake/modules/SRSLTEbuildinfo.cmake.in ${CMAKE_BINARY_DIR}/SRSLTEbuildinfo.cmake ) @@ -74,6 +74,8 @@ option(ENABLE_SOAPYSDR "Enable SoapySDR" ON) option(ENABLE_ZEROMQ "Enable ZeroMQ" ON) option(ENABLE_HARDSIM "Enable support for SIM cards" ON) +option(ENABLE_TTCN3 "Enable TTCN3 test binaries" OFF) + option(BUILD_STATIC "Attempt to statically link external deps" OFF) option(RPATH "Enable RPATH" OFF) option(ENABLE_ASAN "Enable gcc/clang address sanitizer" OFF) @@ -194,28 +196,33 @@ else(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND OR ZEROMQ_FOUND) endif(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND OR ZEROMQ_FOUND) # Boost -if(ENABLE_SRSUE OR ENABLE_SRSENB OR ENABLE_SRSEPC) - if(BUILD_STATIC) - set(Boost_USE_STATIC_LIBS ON) - endif(BUILD_STATIC) +if(BUILD_STATIC) + set(Boost_USE_STATIC_LIBS ON) +endif(BUILD_STATIC) - set(BOOST_REQUIRED_COMPONENTS - program_options - ) - if(UNIX AND EXISTS "/usr/lib64") - list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix - endif(UNIX AND EXISTS "/usr/lib64") - set(Boost_ADDITIONAL_VERSIONS - "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" - "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" - "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" - "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" - "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" - "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" - "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" - ) - find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) -endif(ENABLE_SRSUE OR ENABLE_SRSENB OR ENABLE_SRSEPC) +set(BOOST_REQUIRED_COMPONENTS + program_options +) +if(UNIX AND EXISTS "/usr/lib64") + list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix +endif(UNIX AND EXISTS "/usr/lib64") +set(Boost_ADDITIONAL_VERSIONS + "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" + "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" + "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" + "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" + "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" + "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" + "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" +) +find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) + +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + link_directories(${Boost_LIBRARY_DIRS}) +else(Boost_FOUND) + message(FATAL_ERROR "Boost required to build srsLTE") +endif (Boost_FOUND) # srsGUI if(ENABLE_GUI) @@ -227,6 +234,14 @@ if(ENABLE_GUI) endif(SRSGUI_FOUND) endif(ENABLE_GUI) +if (ENABLE_TTCN3) + find_package(RapidJSON REQUIRED) + add_definitions(-DENABLE_TTCN3) + include_directories(${RAPIDJSON_INCLUDE_DIRS}) + link_directories(${RAPIDJSON_LIBRARY_DIRS}) + message(STATUS "Building with TTCN3 binaries") +endif (ENABLE_TTCN3) + ######################################################################## # Install Dirs ######################################################################## @@ -248,7 +263,7 @@ set(DATA_DIR share/${CPACK_PACKAGE_NAME}) # Auto-generate config install helper and mark for installation configure_file( - ${CMAKE_SOURCE_DIR}/cmake/modules/SRSLTE_install_configs.sh.in + ${PROJECT_SOURCE_DIR}/cmake/modules/SRSLTE_install_configs.sh.in ${CMAKE_BINARY_DIR}/srslte_install_configs.sh ) install(PROGRAMS ${CMAKE_BINARY_DIR}/srslte_install_configs.sh DESTINATION ${RUNTIME_DIR}) @@ -372,6 +387,13 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_SHARED_LINKER_FLAGS "-undefined dynamic_lookup") endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +# Add -Werror to C/C++ flags for newer compilers +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") +endif() + message(STATUS "CMAKE_C_FLAGS is ${CMAKE_C_FLAGS}") message(STATUS "CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}") diff --git a/cmake/modules/FindLibConfig.cmake b/cmake/modules/FindLibConfig.cmake index 49bed9d26..51a908221 100644 --- a/cmake/modules/FindLibConfig.cmake +++ b/cmake/modules/FindLibConfig.cmake @@ -14,31 +14,37 @@ FIND_PATH(LIBCONFIG_INCLUDE_DIR libconfig.h /usr/local/include /usr/include + /usr/lib/x86_64-linux-gnu/ ) FIND_PATH(LIBCONFIGPP_INCLUDE_DIR libconfig.h++ /usr/local/include /usr/include + /usr/lib/x86_64-linux-gnu/ ) FIND_LIBRARY(LIBCONFIG_LIBRARY config /usr/local/lib /usr/lib + /usr/lib/x86_64-linux-gnu/ ) FIND_LIBRARY(LIBCONFIGPP_LIBRARY config++ /usr/local/lib /usr/lib + /usr/lib/x86_64-linux-gnu/ ) FIND_LIBRARY(LIBCONFIG_STATIC_LIBRARY "libconfig${CMAKE_STATIC_LIBRARY_SUFFIX}" /usr/local/lib /usr/lib + /usr/lib/x86_64-linux-gnu/ ) FIND_LIBRARY(LIBCONFIGPP_STATIC_LIBRARY "libconfig++${CMAKE_STATIC_LIBRARY_SUFFIX}" - /usr/local/lib - /usr/lib + /usr/local/lib + /usr/lib + /usr/lib/x86_64-linux-gnu/ ) diff --git a/cmake/modules/FindRapidJSON.cmake b/cmake/modules/FindRapidJSON.cmake new file mode 100644 index 000000000..1b2fd6919 --- /dev/null +++ b/cmake/modules/FindRapidJSON.cmake @@ -0,0 +1,97 @@ +# Copyright (c) 2011 Milo Yip (miloyip@gmail.com) +# Copyright (c) 2013 Rafal Jeczalik (rjeczalik@gmail.com) +# Distributed under the MIT License (see license.txt file) + +# ----------------------------------------------------------------------------------- +# +# Finds the rapidjson library +# +# ----------------------------------------------------------------------------------- +# +# Variables used by this module, they can change the default behaviour. +# Those variables need to be either set before calling find_package +# or exported as environment variables before running CMake: +# +# RAPIDJSON_INCLUDEDIR - Set custom include path, useful when rapidjson headers are +# outside system paths +# RAPIDJSON_USE_SSE2 - Configure rapidjson to take advantage of SSE2 capabilities +# RAPIDJSON_USE_SSE42 - Configure rapidjson to take advantage of SSE4.2 capabilities +# +# ----------------------------------------------------------------------------------- +# +# Variables defined by this module: +# +# RAPIDJSON_FOUND - True if rapidjson was found +# RAPIDJSON_INCLUDE_DIRS - Path to rapidjson include directory +# RAPIDJSON_CXX_FLAGS - Extra C++ flags required for compilation with rapidjson +# +# ----------------------------------------------------------------------------------- +# +# Example usage: +# +# set(RAPIDJSON_USE_SSE2 ON) +# set(RAPIDJSON_INCLUDEDIR "/opt/github.com/rjeczalik/rapidjson/include") +# +# find_package(rapidjson REQUIRED) +# +# include_directories("${RAPIDJSON_INCLUDE_DIRS}") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RAPIDJSON_CXX_FLAGS}") +# add_executable(foo foo.cc) +# +# ----------------------------------------------------------------------------------- + +foreach(opt RAPIDJSON_INCLUDEDIR RAPIDJSON_USE_SSE2 RAPIDJSON_USE_SSE42) + if(${opt} AND DEFINED ENV{${opt}} AND NOT ${opt} STREQUAL "$ENV{${opt}}") + message(WARNING "Conflicting ${opt} values: ignoring environment variable and using CMake cache entry.") + elseif(DEFINED ENV{${opt}} AND NOT ${opt}) + set(${opt} "$ENV{${opt}}") + endif() +endforeach() + +find_path( + RAPIDJSON_INCLUDE_DIRS + NAMES rapidjson/rapidjson.h + PATHS ${RAPIDJSON_INCLUDEDIR} + DOC "Include directory for the rapidjson library." +) + +mark_as_advanced(RAPIDJSON_INCLUDE_DIRS) + +if(RAPIDJSON_INCLUDE_DIRS) + set(RAPIDJSON_FOUND TRUE) +endif() + +mark_as_advanced(RAPIDJSON_FOUND) + +if(RAPIDJSON_USE_SSE42) + set(RAPIDJSON_CXX_FLAGS "-DRAPIDJSON_SSE42") + if(MSVC) + set(RAPIDJSON_CXX_FLAGS "${RAPIDJSON_CXX_FLAGS} /arch:SSE4.2") + else() + set(RAPIDJSON_CXX_FLAGS "${RAPIDJSON_CXX_FLAGS} -msse4.2") + endif() +else() + if(RAPIDJSON_USE_SSE2) + set(RAPIDJSON_CXX_FLAGS "-DRAPIDJSON_SSE2") + if(MSVC) + set(RAPIDJSON_CXX_FLAGS "${RAPIDJSON_CXX_FLAGS} /arch:SSE2") + else() + set(RAPIDJSON_CXX_FLAGS "${RAPIDJSON_CXX_FLAGS} -msse2") + endif() + endif() +endif() + +mark_as_advanced(RAPIDJSON_CXX_FLAGS) + +if(RAPIDJSON_FOUND) + if(NOT rapidjson_FIND_QUIETLY) + message(STATUS "Found rapidjson header files in ${RAPIDJSON_INCLUDE_DIRS}") + if(DEFINED RAPIDJSON_CXX_FLAGS) + message(STATUS "Found rapidjson C++ extra compilation flags: ${RAPIDJSON_CXX_FLAGS}") + endif() + endif() +elseif(RapidJSON_FIND_REQUIRED) + message(FATAL_ERROR "Could not find rapidjson") +else() + message(STATUS "Optional package rapidjson was not found") +endif() diff --git a/cmake/modules/FindSCTP.cmake b/cmake/modules/FindSCTP.cmake index 1ce75edff..1c5ca66a5 100644 --- a/cmake/modules/FindSCTP.cmake +++ b/cmake/modules/FindSCTP.cmake @@ -28,6 +28,7 @@ FIND_LIBRARY( /usr/local/lib64 /usr/lib /usr/lib64 + /usr/lib/x86_64-linux-gnu/ ) message(STATUS "SCTP LIBRARIES: " ${SCTP_LIBRARIES}) diff --git a/cmake/modules/SRSLTEVersion.cmake b/cmake/modules/SRSLTEVersion.cmake index 72b61c706..8ac3006fa 100644 --- a/cmake/modules/SRSLTEVersion.cmake +++ b/cmake/modules/SRSLTEVersion.cmake @@ -19,6 +19,6 @@ # SET(SRSLTE_VERSION_MAJOR 19) -SET(SRSLTE_VERSION_MINOR 6) +SET(SRSLTE_VERSION_MINOR 9) SET(SRSLTE_VERSION_PATCH 0) SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}") diff --git a/cmake/modules/SRSLTEbuildinfo.cmake.in b/cmake/modules/SRSLTEbuildinfo.cmake.in index d8715afbc..3087e84c9 100644 --- a/cmake/modules/SRSLTEbuildinfo.cmake.in +++ b/cmake/modules/SRSLTEbuildinfo.cmake.in @@ -2,20 +2,20 @@ cmake_minimum_required(VERSION 2.6) execute_process( COMMAND git rev-parse --abbrev-ref HEAD -WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@" +WORKING_DIRECTORY "@PROJECT_SOURCE_DIR@" OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND git log -1 --format=%h -WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@" +WORKING_DIRECTORY "@PROJECT_SOURCE_DIR@" OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) message(STATUS "Generating build_info.h") configure_file( - @CMAKE_SOURCE_DIR@/lib/include/srslte/build_info.h.in + @PROJECT_SOURCE_DIR@/lib/include/srslte/build_info.h.in @CMAKE_BINARY_DIR@/lib/include/srslte/build_info.h ) diff --git a/debian/changelog b/debian/changelog index 98bd2ea61..d5bf44d47 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,50 @@ -srslte (19.03-0ubuntu1) bionic; urgency=medium +srslte (19.06-0ubuntu1~srslte1~19.04) disco; urgency=medium - * Update to srsLTE 19.03 + * Update to srsLTE 19.06 (Ubuntu Disco) - -- srsLTE Packagers Mon, 13 May 2019 16:50:00 +0200 + -- Pedro Alvarez Fri, 30 August 2019 11:00:03 +0000 + +srslte (19.06-0ubuntu1~srslte1~18.10) cosmic; urgency=medium + + * Update to srsLTE 19.06 (Ubuntu Cosmic) + + -- Pedro Alvarez Fri, 30 August 2019 10:40:03 +0000 + +srslte (19.06-0ubuntu1~srslte1~18.04) bionic; urgency=medium + + * Update to srsLTE 19.06 (Ubuntu Bionic) + + -- Pedro Alvarez Fri, 30 August 2019 09:53:03 +0000 + +srslte (19.06-0ubuntu1~srslte1~16.04) xenial; urgency=medium + + * Update to srsLTE 19.06 (Ubuntu Xenial) + + -- Pedro Alvarez Thu, 29 August 2019 15:00:03 +0000 + +srslte (19.03-0ubuntu1~srslte1~16.04) xenial; urgency=medium + + * Update to srsLTE 19.03 (Ubuntu Xenial) + + -- Pedro Alvarez Tue, 14 May 2019 17:27:03 +0000 + +srslte (19.03-0ubuntu1~srslte1~19.04) disco; urgency=medium + + * Update to srsLTE 19.03 (Ubuntu Disco) + + -- Pedro Alvarez Tue, 14 May 2019 17:27:03 +0000 + +srslte (19.03-0ubuntu1~srslte1~18.10) cosmic; urgency=medium + + * Update to srsLTE 19.03 (Ubuntu Cosmic) + + -- Pedro Alvarez Tue, 14 May 2019 17:27:03 +0000 + +srslte (19.03-0ubuntu1~srslte1~18.04) bionic; urgency=medium + + * Update to srsLTE 19.03 (Ubuntu Bionic) + + -- Pedro Alvarez Tue, 14 May 2019 17:27:03 +0000 srslte (18.12-0ubuntu1) bionic; urgency=medium diff --git a/debian/packager.sh b/debian/packager.sh new file mode 100755 index 000000000..23ae9cdde --- /dev/null +++ b/debian/packager.sh @@ -0,0 +1,44 @@ +#!/bin/bash +################################################################### +# +# This file is part of srsLTE. +# +# srsLTE 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. +# +# srsLTE 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/. +# +################################################################### + +RELEASE=19.06 +DISTRO=disco +COMMIT=eda7ca69a09933526e9318bcf553af0dc0b81598 +REL_FLAG=releases + +echo 'Packaging srsLTE release' $RELEASE 'for Ubuntu' $DISTRO + +# Make build dir for the package +BUILD_DIR=~/build-area/srslte_$RELEASE/$REL_FLAG/$DISTRO +mkdir -p $BUILD_DIR + +# Make tarball of the package source +pushd ~/srsLTE +git archive $COMMIT -o $BUILD_DIR/srslte_$DISTRO.tar.gz +popd + +# Copy original tarball +cp ~/build-area/srslte_$RELEASE/$REL_FLAG/srslte_$RELEASE.orig.tar.gz $BUILD_DIR + +mkdir $BUILD_DIR/srsLTE +pushd $BUILD_DIR/srsLTE +tar -vxzf ../srslte_$DISTRO.tar.gz +popd diff --git a/lib/examples/cell_search.c b/lib/examples/cell_search.c index 094445f22..72b73af43 100644 --- a/lib/examples/cell_search.c +++ b/lib/examples/cell_search.c @@ -164,8 +164,6 @@ int main(int argc, char **argv) { srslte_rf_set_rx_gain(&rf, 50); } - srslte_rf_set_master_clock_rate(&rf, 30.72e6); - // Supress RF messages srslte_rf_suppress_stdout(&rf); @@ -202,7 +200,6 @@ int main(int argc, char **argv) { /* set rf_freq */ srslte_rf_set_rx_freq(&rf, 0, (double)channels[freq].fd * MHZ); - srslte_rf_rx_wait_lo_locked(&rf); INFO("Set rf_freq to %.3f MHz\n", (double) channels[freq].fd * MHZ/1000000); printf( @@ -226,7 +223,7 @@ int main(int argc, char **argv) { exit(-1); } else if (n > 0) { for (int i=0;i<3;i++) { - if (found_cells[i].psr > 10.0) { + if (found_cells[i].psr > 2.0) { srslte_cell_t cell; cell.id = found_cells[i].cell_id; cell.cp = found_cells[i].cp; @@ -244,7 +241,7 @@ int main(int argc, char **argv) { results[n_found_cells].power = found_cells[i].peak; n_found_cells++; } - } + } } } } diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index 5f6a95c92..42e56581d 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -785,11 +785,6 @@ int main(int argc, char **argv) { int srate = srslte_sampling_freq_hz(cell.nof_prb); if (srate != -1) { - if (srate < 10e6) { - srslte_rf_set_master_clock_rate(&rf, 4*srate); - } else { - srslte_rf_set_master_clock_rate(&rf, srate); - } printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000); float srate_rf = srslte_rf_set_tx_srate(&rf, (double)srate); if (srate_rf != srate) { diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index a9800d3c0..d6223ca74 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -474,12 +474,9 @@ int main(int argc, char **argv) { sigprocmask(SIG_UNBLOCK, &sigset, NULL); signal(SIGINT, sig_int_handler); - srslte_rf_set_master_clock_rate(&rf, 30.72e6); - /* set receiver frequency */ printf("Tunning receiver to %.3f MHz\n", (prog_args.rf_freq + prog_args.file_offset_freq) / 1000000); srslte_rf_set_rx_freq(&rf, prog_args.rf_nof_rx_ant, prog_args.rf_freq + prog_args.file_offset_freq); - srslte_rf_rx_wait_lo_locked(&rf); uint32_t ntrial = 0; do { @@ -501,11 +498,6 @@ int main(int argc, char **argv) { /* set sampling frequency */ int srate = srslte_sampling_freq_hz(cell.nof_prb); if (srate != -1) { - if (srate < 10e6) { - srslte_rf_set_master_clock_rate(&rf, 4 * srate); - } else { - srslte_rf_set_master_clock_rate(&rf, srate); - } printf("Setting sampling rate %.2f MHz\n", (float)srate / 1000000); float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate); if (srate_rf != srate) { @@ -606,13 +598,13 @@ int main(int argc, char **argv) { dl_sf.tdd_config.configured = true; } - srslte_chest_dl_cfg_t chest_pdsch_cfg; + srslte_chest_dl_cfg_t chest_pdsch_cfg = {}; chest_pdsch_cfg.cfo_estimate_enable = prog_args.enable_cfo_ref; chest_pdsch_cfg.cfo_estimate_sf_mask = 1023; chest_pdsch_cfg.interpolate_subframe = !prog_args.average_subframe; // Special configuration for MBSFN channel estimation - srslte_chest_dl_cfg_t chest_mbsfn_cfg; + srslte_chest_dl_cfg_t chest_mbsfn_cfg = {}; chest_mbsfn_cfg.filter_type = SRSLTE_CHEST_FILTER_TRIANGLE; chest_mbsfn_cfg.filter_coef[0] = 0.1; chest_mbsfn_cfg.interpolate_subframe = true; @@ -789,7 +781,7 @@ int main(int argc, char **argv) { dl_sf.tti = tti; dl_sf.sf_type = sf_type; ue_dl_cfg.cfg.tm = (srslte_tm_t)tm; - ue_dl_cfg.pdsch_use_tbs_index_alt = prog_args.enable_256qam; + ue_dl_cfg.cfg.pdsch.use_tbs_index_alt = prog_args.enable_256qam; if ((ue_dl_cfg.cfg.tm == SRSLTE_TM1 && cell.nof_ports == 1) || (ue_dl_cfg.cfg.tm > SRSLTE_TM1 && cell.nof_ports > 1)) { diff --git a/lib/examples/synch_file.c b/lib/examples/synch_file.c index eac52d2e9..204b8ff27 100644 --- a/lib/examples/synch_file.c +++ b/lib/examples/synch_file.c @@ -158,7 +158,7 @@ int main(int argc, char **argv) { * a) requries more memory but has less latency and is paralellizable. */ for (N_id_2=0;N_id_2<3;N_id_2++) { - if (srslte_pss_init(&pss[N_id_2], frame_length)) { + if (srslte_pss_init_fft(&pss[N_id_2], frame_length, symbol_sz)) { ERROR("Error initializing PSS object\n"); exit(-1); } @@ -166,7 +166,7 @@ int main(int argc, char **argv) { ERROR("Error initializing N_id_2\n"); exit(-1); } - if (srslte_sss_init(&sss[N_id_2], 128)) { + if (srslte_sss_init(&sss[N_id_2], symbol_sz)) { ERROR("Error initializing SSS object\n"); exit(-1); } @@ -220,10 +220,15 @@ int main(int argc, char **argv) { cfo[frame_cnt] = srslte_pss_cfo_compute(&pss[N_id_2], &input[peak_pos[N_id_2]-128]); printf("\t%d\t%d\t%d\t%d\t%.3f\t\t%3d\t%d\t%d\t%.3f\n", - frame_cnt,N_id_2, srslte_sss_N_id_1(&sss[N_id_2], m0, m1), - srslte_sss_subframe(m0, m1), peak_value[N_id_2], - peak_pos[N_id_2], m0, m1, - cfo[frame_cnt]); + frame_cnt, + N_id_2, + srslte_sss_N_id_1(&sss[N_id_2], m0, m1, m1_value + m0_value), + srslte_sss_subframe(m0, m1), + peak_value[N_id_2], + peak_pos[N_id_2], + m0, + m1, + cfo[frame_cnt]); } } gettimeofday(&tdata[2], NULL); diff --git a/lib/examples/usrp_capture.c b/lib/examples/usrp_capture.c index 1fba5b075..38d79fd69 100644 --- a/lib/examples/usrp_capture.c +++ b/lib/examples/usrp_capture.c @@ -123,7 +123,6 @@ int main(int argc, char **argv) { ERROR("Error opening rf\n"); exit(-1); } - srslte_rf_set_master_clock_rate(&rf, 30.72e6); sigset_t sigset; sigemptyset(&sigset); @@ -134,11 +133,6 @@ int main(int argc, char **argv) { printf("Set RX gain: %.2f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain)); float srate = srslte_rf_set_rx_srate(&rf, rf_rate); if (srate != rf_rate) { - if (srate < 10e6) { - srslte_rf_set_master_clock_rate(&rf, 4*rf_rate); - } else { - srslte_rf_set_master_clock_rate(&rf, rf_rate); - } srate = srslte_rf_set_rx_srate(&rf, rf_rate); if (srate != rf_rate) { ERROR("Error setting samplign frequency %.2f MHz\n", rf_rate * 1e-6); @@ -147,7 +141,6 @@ int main(int argc, char **argv) { } printf("Correctly RX rate: %.2f MHz\n", srate*1e-6); - srslte_rf_rx_wait_lo_locked(&rf); srslte_rf_start_rx_stream(&rf, false); diff --git a/lib/examples/usrp_capture_sync.c b/lib/examples/usrp_capture_sync.c index e668119b4..d77a99975 100644 --- a/lib/examples/usrp_capture_sync.c +++ b/lib/examples/usrp_capture_sync.c @@ -100,7 +100,11 @@ void parse_args(int argc, char **argv) { int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) { DEBUG(" ---- Receive %d samples ---- \n", nsamples); - return srslte_rf_recv_with_time_multi(h, (void**)data[0], nsamples, true, NULL, NULL); + void* ptr[SRSLTE_MAX_PORTS]; + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + ptr[i] = data[i]; + } + return srslte_rf_recv_with_time_multi(h, ptr, nsamples, true, NULL, NULL); } int main(int argc, char **argv) { @@ -122,7 +126,6 @@ int main(int argc, char **argv) { ERROR("Error opening rf\n"); exit(-1); } - srslte_rf_set_master_clock_rate(&rf, 30.72e6); for (int i = 0; i < nof_rx_antennas; i++) { buffer[i] = srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(100)); @@ -137,11 +140,6 @@ int main(int argc, char **argv) { printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain)); int srate = srslte_sampling_freq_hz(nof_prb); if (srate != -1) { - if (srate < 10e6) { - srslte_rf_set_master_clock_rate(&rf, 4*srate); - } else { - srslte_rf_set_master_clock_rate(&rf, srate); - } printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000); float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate); if (srate_rf != srate) { @@ -152,7 +150,6 @@ int main(int argc, char **argv) { ERROR("Invalid number of PRB %d\n", nof_prb); exit(-1); } - srslte_rf_rx_wait_lo_locked(&rf); srslte_rf_start_rx_stream(&rf, false); cell.cp = SRSLTE_CP_NORM; diff --git a/lib/examples/usrp_txrx.c b/lib/examples/usrp_txrx.c index cfc3b52dd..3f6800ac9 100644 --- a/lib/examples/usrp_txrx.c +++ b/lib/examples/usrp_txrx.c @@ -136,14 +136,8 @@ int main(int argc, char **argv) { ERROR("Error opening rf\n"); exit(-1); } - srslte_rf_set_master_clock_rate(&rf, 30.72e6); - - int srate = srslte_sampling_freq_hz(nof_prb); - if (srate < 10e6) { - srslte_rf_set_master_clock_rate(&rf, 4*srate); - } else { - srslte_rf_set_master_clock_rate(&rf, srate); - } + + int srate = srslte_sampling_freq_hz(nof_prb); srslte_rf_set_rx_srate(&rf, (double) srate); srslte_rf_set_tx_srate(&rf, (double) srate); diff --git a/lib/include/srslte/asn1/asn1_utils.h b/lib/include/srslte/asn1/asn1_utils.h index c69d89534..835e63fb0 100644 --- a/lib/include/srslte/asn1/asn1_utils.h +++ b/lib/include/srslte/asn1/asn1_utils.h @@ -23,6 +23,7 @@ #define SRSASN_COMMON_UTILS_H #include +#include #include #include #include @@ -80,8 +81,13 @@ ValOrError unpack_bits(uint8_t*& ptr, uint8_t& offset, uint8_t* max_ptr, uint32_ class bit_ref { public: - bit_ref(); - bit_ref(uint8_t* start_ptr_, uint32_t max_size_); + bit_ref() = default; + bit_ref(uint8_t* start_ptr_, uint32_t max_size_) : + ptr(start_ptr_), + start_ptr(start_ptr_), + max_ptr(max_size_ + start_ptr_) + { + } int distance(const bit_ref& other) const; int distance(uint8_t* ref_ptr) const; @@ -90,6 +96,7 @@ public: int distance_bytes() const; SRSASN_CODE pack(uint32_t val, uint32_t n_bits); + SRSASN_CODE pack_bytes(const uint8_t* buf, uint32_t n_bytes); template SRSASN_CODE unpack(T& val, uint32_t n_bits) { @@ -97,15 +104,17 @@ public: val = ret.val; return ret.code; } + SRSASN_CODE unpack_bytes(uint8_t* buf, uint32_t n_bytes); SRSASN_CODE align_bytes(); SRSASN_CODE align_bytes_zero(); + SRSASN_CODE advance_bits(uint32_t n_bits); void set(uint8_t* start_ptr_, uint32_t max_size_); private: - uint8_t* ptr; - uint8_t offset; - uint8_t* start_ptr; - uint8_t* max_ptr; + uint8_t* ptr = nullptr; + uint8_t offset = 0; + uint8_t* start_ptr = nullptr; + uint8_t* max_ptr = nullptr; }; /********************* @@ -116,7 +125,7 @@ class dyn_array { public: typedef T item_type; - dyn_array() : data_(NULL), size_(0), cap_(0) {} + dyn_array() = default; dyn_array(uint32_t new_size) : size_(new_size), cap_(new_size) { data_ = new T[size_]; } dyn_array(const dyn_array& other) { @@ -183,8 +192,9 @@ public: const T* data() const { return &data_[0]; } private: - T* data_; - uint32_t size_, cap_; + T* data_ = nullptr; + uint32_t size_ = 0; + uint32_t cap_ = 0; }; template @@ -219,24 +229,6 @@ private: uint32_t current_size; }; -template -class fixed_array -{ -public: - typedef T item_type; - static uint32_t size() { return N; } - T& operator[](uint32_t idx) { return data_[idx]; } - const T& operator[](uint32_t idx) const { return data_[idx]; } - bool operator==(const fixed_array& other) const { return std::equal(data_, data_ + size(), other.data_); } - T& back() { return data_[size() - 1]; } - const T& back() const { return data_[size() - 1]; } - T* data() { return &data_[0]; } - const T* data() const { return &data_[0]; } - -private: - T data_[N]; -}; - /********************* ext packing *********************/ @@ -341,22 +333,21 @@ template SRSASN_CODE unpack_unalign_integer(IntType& n, bit_ref& bref, IntType lb, IntType ub); template struct UnalignedIntegerPacker { - UnalignedIntegerPacker(IntType, IntType); - IntType lb; - IntType ub; - SRSASN_CODE pack(bit_ref& bref, IntType n) const; - SRSASN_CODE unpack(IntType& n, bit_ref& bref) const; + UnalignedIntegerPacker(IntType lb_, IntType ub_) : lb(lb_), ub(ub_) {} + const IntType lb; + const IntType ub; + SRSASN_CODE pack(bit_ref& bref, IntType n) const; + SRSASN_CODE unpack(IntType& n, bit_ref& bref) const; }; template struct unaligned_integer { - IntType value; - const UnalignedIntegerPacker packer; - unaligned_integer() : packer(lb, ub) {} - unaligned_integer(IntType value_) : value(value_), packer(lb, ub) {} + IntType value; + unaligned_integer() = default; + unaligned_integer(IntType value_) : value(value_) {} operator IntType() { return value; } - SRSASN_CODE pack(bit_ref& bref) const { return packer.pack(bref, value); } - SRSASN_CODE unpack(bit_ref& bref) { return packer.unpack(value, bref); } + SRSASN_CODE pack(bit_ref& bref) const { return pack_unalign_integer(bref, value, lb, ub); } + SRSASN_CODE unpack(bit_ref& bref) { return unpack_unalign_integer(value, bref, lb, ub); } }; template @@ -486,7 +477,7 @@ public: SRSASN_CODE unpack(bit_ref& bref); private: - fixed_array octets_; + std::array octets_; }; template @@ -520,7 +511,7 @@ SRSASN_CODE fixed_octstring::unpack(bit_ref& bref) class dyn_octstring { public: - dyn_octstring() {} + dyn_octstring() = default; dyn_octstring(uint32_t new_size) : octets_(new_size) {} const uint8_t& operator[](uint32_t idx) const { return octets_[idx]; } @@ -621,7 +612,7 @@ public: SRSASN_CODE unpack(bit_ref& bref, bool& ext) { return unpack_fixed_bitstring(data(), ext, bref, N); } private: - fixed_array octets_; // ceil(N/8.0) + std::array octets_; // ceil(N/8.0) }; /********************* @@ -874,16 +865,15 @@ template class copy_ptr { public: - copy_ptr() : ptr(NULL) {} - explicit copy_ptr(T* ptr_) : + explicit copy_ptr(T* ptr_ = nullptr) : ptr(ptr_) {} // it takes hold of the pointer (including destruction). You should use make_copy_ptr() in most cases - // instead of this ctor - copy_ptr(const copy_ptr& other) { ptr = other.make_obj_(); } // it allocates new memory for the new object + // instead of this ctor + copy_ptr(const copy_ptr& other) { ptr = (other.ptr == nullptr) ? nullptr : new T(*other.ptr); } ~copy_ptr() { destroy_(); } copy_ptr& operator=(const copy_ptr& other) { if (this != &other) { - acquire(other.make_obj_()); + reset((other.ptr == nullptr) ? nullptr : new T(*other.ptr)); } return *this; } @@ -897,15 +887,23 @@ public: T* release() { T* ret = ptr; - ptr = NULL; + ptr = nullptr; return ret; } - void acquire(T* ptr_) + void reset(T* ptr_ = nullptr) { destroy_(); ptr = ptr_; } - void reset() { acquire(NULL); } + void set_present(bool flag = true) + { + if (flag) { + reset(new T()); + } else { + reset(); + } + } + bool is_present() const { return get() != nullptr; } private: void destroy_() @@ -914,7 +912,6 @@ private: delete ptr; } } - T* make_obj_() const { return (ptr == NULL) ? NULL : new T(*ptr); } T* ptr; }; @@ -928,23 +925,31 @@ copy_ptr make_copy_ptr(const T& t) ext group *********************/ -class ext_groups_header +class ext_groups_packer_guard { public: - ext_groups_header(uint32_t max_nof_groups, uint32_t nof_nogroups_ = 0); - bool& operator[](uint32_t idx); - - SRSASN_CODE pack_nof_groups(bit_ref& bref) const; - SRSASN_CODE pack_group_flags(bit_ref& bref) const; + bool& operator[](uint32_t idx); SRSASN_CODE pack(bit_ref& bref) const; - SRSASN_CODE unpack_nof_groups(bit_ref& bref); - SRSASN_CODE unpack_group_flags(bit_ref& bref); + +private: + bounded_array groups; +}; + +class ext_groups_unpacker_guard +{ +public: + explicit ext_groups_unpacker_guard(uint32_t nof_supported_groups_); + ~ext_groups_unpacker_guard(); + + void resize(uint32_t new_size); + bool& operator[](uint32_t idx); SRSASN_CODE unpack(bit_ref& bref); private: - mutable uint32_t nof_groups; - const uint32_t nof_nogroups; bounded_array groups; + const uint32_t nof_supported_groups; + uint32_t nof_unpacked_groups = 0; + bit_ref* bref_tracker = nullptr; }; /********************* diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 74e7ce015..abf275a16 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -2939,6 +2939,8 @@ typedef struct { } LIBLTE_MME_ID_RESPONSE_MSG_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_identity_response_msg(LIBLTE_MME_ID_RESPONSE_MSG_STRUCT* id_resp, + uint8 sec_hdr_type, + uint32 count, LIBLTE_BYTE_MSG_STRUCT* msg); LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_response_msg(LIBLTE_BYTE_MSG_STRUCT* msg, LIBLTE_MME_ID_RESPONSE_MSG_STRUCT* id_resp); diff --git a/lib/include/srslte/asn1/rrc_asn1.h b/lib/include/srslte/asn1/rrc_asn1.h index 23ac222a4..fef6f53ee 100644 --- a/lib/include/srslte/asn1/rrc_asn1.h +++ b/lib/include/srslte/asn1/rrc_asn1.h @@ -19,6 +19,12 @@ * */ +/******************************************************************************* + * + * 3GPP TS ASN1 RRC v15.4.0 (2018-12) + * + ******************************************************************************/ + #ifndef SRSASN1_RRC_H #define SRSASN1_RRC_H @@ -30,8 +36,8 @@ namespace asn1 { namespace rrc { /******************************************************************************* -/* Functions for external logging -/******************************************************************************/ + * Functions for external logging + ******************************************************************************/ static log_handler_t log_handler; static void* callback_ctx = NULL; @@ -103,8 +109,8 @@ ItemType convert_enum_idx(ItemType* array, uint32_t nof_types, uint32_t enum_val } /******************************************************************************* -/* Constant Definitions -/******************************************************************************/ + * Constant Definitions + ******************************************************************************/ #define ASN1_RRC_MAX_ACCESS_CAT_MINUS1_R15 63 #define ASN1_RRC_MAX_ACDC_CAT_R13 16 @@ -291,8 +297,8 @@ ItemType convert_enum_idx(ItemType* array, uint32_t nof_types, uint32_t enum_val #define ASN1_RRC_MAX_SI_MSG_NB_R13 8 /******************************************************************************* -/* Struct Definitions -/******************************************************************************/ + * Struct Definitions + ******************************************************************************/ // PHICH-Config ::= SEQUENCE struct phich_cfg_s { @@ -419,7 +425,7 @@ struct gnss_id_r15_s { }; // MCC ::= SEQUENCE (SIZE (3)) OF INTEGER -typedef fixed_array mcc_l; +using mcc_l = std::array; // MNC ::= SEQUENCE (SIZE (2..3)) OF INTEGER typedef bounded_array mnc_l; @@ -1192,8 +1198,6 @@ struct sl_pssch_tx_cfg_r14_s { sl_pssch_tx_params_r14_s params_below_thres_r14; // ... // group 0 - bool params_above_thres_v1530_present = false; - bool params_below_thres_v1530_present = false; copy_ptr params_above_thres_v1530; copy_ptr params_below_thres_v1530; @@ -1734,8 +1738,6 @@ struct sl_comm_res_pool_v2x_r14_s { sl_restrict_res_reserv_period_list_r14_l restrict_res_reserv_period_r14; // ... // group 0 - bool sl_min_t2_value_list_r15_present = false; - bool cbr_pssch_tx_cfg_list_v1530_present = false; copy_ptr sl_min_t2_value_list_r15; copy_ptr cbr_pssch_tx_cfg_list_v1530; @@ -1833,7 +1835,7 @@ struct sl_tf_res_cfg_r12_s { }; // SL-ThresPSSCH-RSRP-List-r14 ::= SEQUENCE (SIZE (64)) OF INTEGER -typedef fixed_array sl_thres_pssch_rsrp_list_r14_l; +using sl_thres_pssch_rsrp_list_r14_l = std::array; // SystemInformationBlockType1-v1430-IEs ::= SEQUENCE struct sib_type1_v1430_ies_s { @@ -2270,14 +2272,10 @@ struct sl_disc_res_pool_r12_s { rx_params_r12_s_ rx_params_r12; // ... // group 0 - bool disc_period_v1310_present = false; - bool rx_params_add_neigh_freq_r13_present = false; - bool tx_params_add_neigh_freq_r13_present = false; copy_ptr disc_period_v1310; copy_ptr rx_params_add_neigh_freq_r13; copy_ptr tx_params_add_neigh_freq_r13; // group 1 - bool tx_params_add_neigh_freq_v1370_present = false; copy_ptr tx_params_add_neigh_freq_v1370; // sequence methods @@ -3076,7 +3074,6 @@ struct rach_ce_level_info_r13_s { rar_hop_cfg_r13_e_ rar_hop_cfg_r13; // ... // group 0 - bool edt_params_r15_present = false; copy_ptr edt_params_r15; // sequence methods @@ -3110,7 +3107,7 @@ typedef bounded_array, 16> sl_dest_info_list_r12_l; typedef dyn_array sl_disc_rx_pool_list_r12_l; // SL-DiscTxPowerInfoList-r12 ::= SEQUENCE (SIZE (maxSL-DiscPowerClass-r12)) OF SL-DiscTxPowerInfo-r12 -typedef fixed_array sl_disc_tx_pwr_info_list_r12_l; +using sl_disc_tx_pwr_info_list_r12_l = std::array; // SL-DiscTxResourcesInterFreq-r13 ::= CHOICE struct sl_disc_tx_res_inter_freq_r13_c { @@ -4279,10 +4276,8 @@ struct sl_inter_freq_info_v2x_r14_s { sl_v2x_ue_cfg_list_r14_l v2x_ue_cfg_list_r14; // ... // group 0 - bool add_spec_emission_v2x_r14_present = false; copy_ptr add_spec_emission_v2x_r14; // group 1 - bool v2x_freq_sel_cfg_list_r15_present = false; copy_ptr v2x_freq_sel_cfg_list_r15; // sequence methods @@ -4867,7 +4862,6 @@ struct carrier_freq_utra_fdd_s { int8_t q_qual_min = -24; // ... // group 0 - bool thresh_x_q_r9_present = false; copy_ptr thresh_x_q_r9; // sequence methods @@ -5378,7 +5372,6 @@ struct inter_freq_carrier_freq_info_s { // ... // group 0 bool q_qual_min_r9_present = false; - bool thresh_x_q_r9_present = false; int8_t q_qual_min_r9 = -34; copy_ptr thresh_x_q_r9; // group 1 @@ -5653,7 +5646,6 @@ struct mbsfn_area_info_r9_s { mcch_cfg_r9_s_ mcch_cfg_r9; // ... // group 0 - bool mcch_cfg_r14_present = false; bool subcarrier_spacing_mbms_r14_present = false; copy_ptr mcch_cfg_r14; subcarrier_spacing_mbms_r14_e_ subcarrier_spacing_mbms_r14; @@ -6321,8 +6313,7 @@ struct rach_cfg_common_s { uint8_t max_harq_msg3_tx = 1; // ... // group 0 - bool preamb_trans_max_ce_r13_present = false; - bool rach_ce_level_info_list_r13_present = false; + bool preamb_trans_max_ce_r13_present = false; preamb_trans_max_e preamb_trans_max_ce_r13; copy_ptr rach_ce_level_info_list_r13; // group 1 @@ -6616,7 +6607,6 @@ struct sl_comm_res_pool_r12_s { tx_params_r12_s_ tx_params_r12; // ... // group 0 - bool prio_list_r13_present = false; copy_ptr prio_list_r13; // sequence methods @@ -6843,7 +6833,7 @@ struct uac_barr_info_set_r15_s { // UAC-BarringPerPLMN-r15 ::= SEQUENCE struct uac_barr_per_plmn_r15_s { struct uac_ac_barr_list_type_r15_c_ { - typedef fixed_array uac_implicit_ac_barr_list_r15_l_; + using uac_implicit_ac_barr_list_r15_l_ = std::array; struct types_opts { enum options { uac_implicit_ac_barr_list_r15, uac_explicit_ac_barr_list_r15, nulltype } value; @@ -7432,22 +7422,12 @@ struct rr_cfg_common_sib_s { ul_cp_len_e ul_cp_len; // ... // group 0 - bool ul_pwr_ctrl_common_v1020_present = false; copy_ptr ul_pwr_ctrl_common_v1020; // group 1 - bool rach_cfg_common_v1250_present = false; copy_ptr rach_cfg_common_v1250; // group 2 - bool pusch_cfg_common_v1270_present = false; copy_ptr pusch_cfg_common_v1270; // group 3 - bool bcch_cfg_v1310_present = false; - bool pcch_cfg_v1310_present = false; - bool freq_hop_params_r13_present = false; - bool pdsch_cfg_common_v1310_present = false; - bool pusch_cfg_common_v1310_present = false; - bool prach_cfg_common_v1310_present = false; - bool pucch_cfg_common_v1310_present = false; copy_ptr bcch_cfg_v1310; copy_ptr pcch_cfg_v1310; copy_ptr freq_hop_params_r13; @@ -7456,17 +7436,10 @@ struct rr_cfg_common_sib_s { copy_ptr prach_cfg_common_v1310; copy_ptr pucch_cfg_common_v1310; // group 4 - bool high_speed_cfg_r14_present = false; - bool prach_cfg_v1430_present = false; - bool pucch_cfg_common_v1430_present = false; copy_ptr high_speed_cfg_r14; copy_ptr prach_cfg_v1430; copy_ptr pucch_cfg_common_v1430; // group 5 - bool prach_cfg_v1530_present = false; - bool ce_rss_cfg_r15_present = false; - bool wus_cfg_r15_present = false; - bool high_speed_cfg_v1530_present = false; copy_ptr prach_cfg_v1530; copy_ptr ce_rss_cfg_r15; copy_ptr wus_cfg_r15; @@ -8407,7 +8380,6 @@ struct sib_type13_r9_s { dyn_octstring late_non_crit_ext; // ... // group 0 - bool notif_cfg_v1430_present = false; copy_ptr notif_cfg_v1430; // sequence methods @@ -8513,11 +8485,8 @@ struct sib_type15_r11_s { dyn_octstring late_non_crit_ext; // ... // group 0 - bool mbms_sai_inter_freq_list_v1140_present = false; copy_ptr mbms_sai_inter_freq_list_v1140; // group 1 - bool mbms_intra_freq_carrier_type_r14_present = false; - bool mbms_inter_freq_carrier_type_list_r14_present = false; copy_ptr mbms_intra_freq_carrier_type_r14; copy_ptr mbms_inter_freq_carrier_type_list_r14; @@ -8548,7 +8517,6 @@ struct sib_type16_r11_s { dyn_octstring late_non_crit_ext; // ... // group 0 - bool time_ref_info_r15_present = false; copy_ptr time_ref_info_r15; // sequence methods @@ -8596,9 +8564,8 @@ struct sib_type18_r12_s { dyn_octstring late_non_crit_ext; // ... // group 0 - bool comm_tx_pool_normal_common_ext_r13_present = false; - bool comm_tx_res_uc_req_allowed_r13_present = false; - bool comm_tx_allow_relay_common_r13_present = false; + bool comm_tx_res_uc_req_allowed_r13_present = false; + bool comm_tx_allow_relay_common_r13_present = false; copy_ptr comm_tx_pool_normal_common_ext_r13; // sequence methods @@ -8647,9 +8614,6 @@ struct sib_type19_r12_s { dyn_octstring late_non_crit_ext; // ... // group 0 - bool disc_cfg_v1310_present = false; - bool disc_cfg_relay_r13_present = false; - bool disc_cfg_ps_minus13_present = false; copy_ptr disc_cfg_v1310; copy_ptr disc_cfg_relay_r13; copy_ptr disc_cfg_ps_minus13; @@ -8702,42 +8666,31 @@ struct sib_type2_s { bool late_non_crit_ext_present = false; dyn_octstring late_non_crit_ext; // group 0 - bool ssac_barr_for_mmtel_voice_r9_present = false; - bool ssac_barr_for_mmtel_video_r9_present = false; copy_ptr ssac_barr_for_mmtel_voice_r9; copy_ptr ssac_barr_for_mmtel_video_r9; // group 1 - bool ac_barr_for_csfb_r10_present = false; copy_ptr ac_barr_for_csfb_r10; // group 2 bool ac_barr_skip_for_mmtel_voice_r12_present = false; bool ac_barr_skip_for_mmtel_video_r12_present = false; bool ac_barr_skip_for_sms_r12_present = false; - bool ac_barr_per_plmn_list_r12_present = false; copy_ptr ac_barr_per_plmn_list_r12; // group 3 bool voice_service_cause_ind_r12_present = false; // group 4 - bool acdc_barr_for_common_r13_present = false; - bool acdc_barr_per_plmn_list_r13_present = false; copy_ptr acdc_barr_for_common_r13; copy_ptr acdc_barr_per_plmn_list_r13; // group 5 - bool udt_restricting_for_common_r13_present = false; - bool udt_restricting_per_plmn_list_r13_present = false; - bool c_io_t_eps_optim_info_r13_present = false; - bool use_full_resume_id_r13_present = false; + bool use_full_resume_id_r13_present = false; copy_ptr udt_restricting_for_common_r13; copy_ptr udt_restricting_per_plmn_list_r13; copy_ptr c_io_t_eps_optim_info_r13; // group 6 bool unicast_freq_hop_ind_r13_present = false; // group 7 - bool mbsfn_sf_cfg_list_v1430_present = false; bool video_service_cause_ind_r14_present = false; copy_ptr mbsfn_sf_cfg_list_v1430; // group 8 - bool plmn_info_list_r15_present = false; copy_ptr plmn_info_list_r15; // group 9 bool cp_edt_r15_present = false; @@ -8948,8 +8901,6 @@ struct sib_type20_r13_s { dyn_octstring late_non_crit_ext; // ... // group 0 - bool br_bcch_cfg_r14_present = false; - bool sc_mcch_sched_info_r14_present = false; bool pdsch_max_num_repeat_cemode_a_sc_mtch_r14_present = false; bool pdsch_max_num_repeat_cemode_b_sc_mtch_r14_present = false; copy_ptr br_bcch_cfg_r14; @@ -9210,8 +9161,6 @@ struct sib_type3_s { bool late_non_crit_ext_present = false; dyn_octstring late_non_crit_ext; // group 0 - bool s_intra_search_v920_present = false; - bool s_non_intra_search_v920_present = false; bool q_qual_min_r9_present = false; bool thresh_serving_low_q_r9_present = false; copy_ptr s_intra_search_v920; @@ -9225,26 +9174,18 @@ struct sib_type3_s { bool q_qual_min_rsrq_on_all_symbols_r12_present = false; int8_t q_qual_min_rsrq_on_all_symbols_r12 = -34; // group 3 - bool cell_resel_serving_freq_info_v1310_present = false; - bool redist_serving_info_r13_present = false; - bool cell_sel_info_ce_r13_present = false; - bool t_resel_eutra_ce_r13_present = false; + bool t_resel_eutra_ce_r13_present = false; copy_ptr cell_resel_serving_freq_info_v1310; copy_ptr redist_serving_info_r13; copy_ptr cell_sel_info_ce_r13; uint8_t t_resel_eutra_ce_r13 = 0; // group 4 - bool cell_sel_info_ce1_r13_present = false; copy_ptr cell_sel_info_ce1_r13; // group 5 - bool cell_sel_info_ce1_v1360_present = false; copy_ptr cell_sel_info_ce1_v1360; // group 6 - bool cell_resel_info_common_v1460_present = false; copy_ptr cell_resel_info_common_v1460; // group 7 - bool cell_resel_info_hsdn_r15_present = false; - bool cell_sel_info_ce_v1530_present = false; bool crs_intf_mitig_neigh_cells_ce_r15_present = false; copy_ptr cell_resel_info_hsdn_r15; copy_ptr cell_sel_info_ce_v1530; @@ -9269,7 +9210,6 @@ struct sib_type4_s { bool late_non_crit_ext_present = false; dyn_octstring late_non_crit_ext; // group 0 - bool intra_freq_neigh_hsdn_cell_list_r15_present = false; copy_ptr intra_freq_neigh_hsdn_cell_list_r15; // sequence methods @@ -9287,33 +9227,22 @@ struct sib_type5_s { bool late_non_crit_ext_present = false; dyn_octstring late_non_crit_ext; // group 0 - bool inter_freq_carrier_freq_list_v1250_present = false; - bool inter_freq_carrier_freq_list_ext_r12_present = false; copy_ptr inter_freq_carrier_freq_list_v1250; copy_ptr inter_freq_carrier_freq_list_ext_r12; // group 1 - bool inter_freq_carrier_freq_list_ext_v1280_present = false; copy_ptr inter_freq_carrier_freq_list_ext_v1280; // group 2 - bool inter_freq_carrier_freq_list_v1310_present = false; - bool inter_freq_carrier_freq_list_ext_v1310_present = false; copy_ptr inter_freq_carrier_freq_list_v1310; copy_ptr inter_freq_carrier_freq_list_ext_v1310; // group 3 - bool inter_freq_carrier_freq_list_v1350_present = false; - bool inter_freq_carrier_freq_list_ext_v1350_present = false; copy_ptr inter_freq_carrier_freq_list_v1350; copy_ptr inter_freq_carrier_freq_list_ext_v1350; // group 4 - bool inter_freq_carrier_freq_list_ext_v1360_present = false; copy_ptr inter_freq_carrier_freq_list_ext_v1360; // group 5 bool scptm_freq_offset_r14_present = false; uint8_t scptm_freq_offset_r14 = 1; // group 6 - bool inter_freq_carrier_freq_list_v1530_present = false; - bool inter_freq_carrier_freq_list_ext_v1530_present = false; - bool meas_idle_cfg_sib_r15_present = false; copy_ptr inter_freq_carrier_freq_list_v1530; copy_ptr inter_freq_carrier_freq_list_ext_v1530; copy_ptr meas_idle_cfg_sib_r15; @@ -9342,10 +9271,6 @@ struct sib_type6_s { bool late_non_crit_ext_present = false; dyn_octstring late_non_crit_ext; // group 0 - bool carrier_freq_list_utra_fdd_v1250_present = false; - bool carrier_freq_list_utra_tdd_v1250_present = false; - bool carrier_freq_list_utra_fdd_ext_r12_present = false; - bool carrier_freq_list_utra_tdd_ext_r12_present = false; copy_ptr carrier_freq_list_utra_fdd_v1250; copy_ptr carrier_freq_list_utra_tdd_v1250; copy_ptr carrier_freq_list_utra_fdd_ext_r12; @@ -9409,10 +9334,6 @@ struct sib_type8_s { dyn_octstring late_non_crit_ext; // group 0 bool csfb_support_for_dual_rx_ues_r9_present = false; - bool cell_resel_params_hrpd_v920_present = false; - bool cell_resel_params1_xrtt_v920_present = false; - bool csfb_regist_param1_xrtt_v920_present = false; - bool ac_barr_cfg1_xrtt_r9_present = false; bool csfb_support_for_dual_rx_ues_r9 = false; copy_ptr cell_resel_params_hrpd_v920; copy_ptr cell_resel_params1_xrtt_v920; @@ -9421,7 +9342,6 @@ struct sib_type8_s { // group 1 bool csfb_dual_rx_tx_support_r10_present = false; // group 2 - bool sib8_per_plmn_list_r11_present = false; copy_ptr sib8_per_plmn_list_r11; // sequence methods @@ -11282,7 +11202,6 @@ struct csi_rs_cfg_nzp_r11_s { uint8_t tx_comb_r14 = 0; nzp_freq_density_r14_e freq_density_r14; // group 2 - bool mbsfn_sf_cfg_list_v1430_present = false; copy_ptr mbsfn_sf_cfg_list_v1430; // sequence methods @@ -12244,7 +12163,6 @@ struct cqi_report_periodic_proc_ext_r11_s { csi_cfg_idx_r11_c_ csi_cfg_idx_r11; // ... // group 0 - bool cri_report_cfg_r13_present = false; copy_ptr cri_report_cfg_r13; // group 1 bool periodicity_factor_wb_r13_present = false; @@ -12437,30 +12355,21 @@ struct csi_process_r11_s { // ... // group 0 bool alternative_codebook_enabled_for4_tx_proc_r12_present = false; - bool csi_im_cfg_id_list_r12_present = false; - bool cqi_report_aperiodic_proc2_r12_present = false; copy_ptr csi_im_cfg_id_list_r12; copy_ptr cqi_report_aperiodic_proc2_r12; // group 1 - bool cqi_report_aperiodic_proc_v1310_present = false; - bool cqi_report_aperiodic_proc2_v1310_present = false; - bool e_mimo_type_r13_present = false; copy_ptr cqi_report_aperiodic_proc_v1310; copy_ptr cqi_report_aperiodic_proc2_v1310; copy_ptr e_mimo_type_r13; // group 2 - bool dummy_present = false; - bool e_mimo_hybrid_r14_present = false; bool advanced_codebook_enabled_r14_present = false; copy_ptr dummy; copy_ptr e_mimo_hybrid_r14; bool advanced_codebook_enabled_r14 = false; // group 3 - bool e_mimo_type_v1480_present = false; copy_ptr e_mimo_type_v1480; // group 4 bool fe_comp_csi_enabled_v1530_present = false; - bool e_mimo_type_v1530_present = false; bool fe_comp_csi_enabled_v1530 = false; copy_ptr e_mimo_type_v1530; @@ -14458,11 +14367,8 @@ struct epdcch_set_cfg_r11_s { uint8_t re_map_qcl_cfg_id_r11 = 1; // ... // group 0 - bool csi_rs_cfg_zp_id2_r12_present = false; copy_ptr csi_rs_cfg_zp_id2_r12; // group 1 - bool num_prb_pairs_v1310_present = false; - bool mpdcch_cfg_r13_present = false; copy_ptr num_prb_pairs_v1310; copy_ptr mpdcch_cfg_r13; @@ -14748,9 +14654,6 @@ struct lc_ch_cfg_s { bool laa_ul_allowed_r14 = false; bit_rate_query_prohibit_timer_r14_e_ bit_rate_query_prohibit_timer_r14; // group 3 - bool allowed_tti_lens_r15_present = false; - bool lc_ch_sr_restrict_r15_present = false; - bool chl_access_prio_r15_present = false; bool lch_cell_restrict_r15_present = false; copy_ptr allowed_tti_lens_r15; copy_ptr lc_ch_sr_restrict_r15; @@ -14943,10 +14846,8 @@ struct pdsch_re_map_qcl_cfg_r11_s { uint8_t qcl_csi_rs_cfg_nzp_id_r11 = 1; // ... // group 0 - bool mbsfn_sf_cfg_list_v1430_present = false; copy_ptr mbsfn_sf_cfg_list_v1430; // group 1 - bool codeword_one_cfg_v1530_present = false; copy_ptr codeword_one_cfg_v1530; // sequence methods @@ -15663,7 +15564,6 @@ struct crs_assist_info_r11_s { mbsfn_sf_cfg_list_l mbsfn_sf_cfg_list_r11; // ... // group 0 - bool mbsfn_sf_cfg_list_v1430_present = false; copy_ptr mbsfn_sf_cfg_list_v1430; // sequence methods @@ -15691,7 +15591,6 @@ struct crs_assist_info_r13_s { mbsfn_sf_cfg_list_l mbsfn_sf_cfg_list_r13; // ... // group 0 - bool mbsfn_sf_cfg_list_v1430_present = false; copy_ptr mbsfn_sf_cfg_list_v1430; // sequence methods @@ -16629,19 +16528,13 @@ struct pdcp_cfg_s { bool ul_data_split_drb_via_scg_r12 = false; t_reordering_r12_e_ t_reordering_r12; // group 3 - bool ul_data_split_thres_r13_present = false; - bool pdcp_sn_size_v1310_present = false; - bool status_feedback_r13_present = false; + bool pdcp_sn_size_v1310_present = false; copy_ptr ul_data_split_thres_r13; copy_ptr status_feedback_r13; // group 4 - bool ul_lwa_cfg_r14_present = false; - bool ul_only_hdr_compress_r14_present = false; copy_ptr ul_lwa_cfg_r14; copy_ptr ul_only_hdr_compress_r14; // group 5 - bool ul_data_compress_r15_present = false; - bool pdcp_dupl_cfg_r15_present = false; copy_ptr ul_data_compress_r15; copy_ptr pdcp_dupl_cfg_r15; @@ -17279,7 +17172,6 @@ struct sps_cfg_ul_c { p0_persistent_s_ p0_persistent; // ... // group 0 - bool p0_persistent_sf_set2_r12_present = false; copy_ptr p0_persistent_sf_set2_r12; // group 1 bool nof_conf_ul_sps_processes_r13_present = false; @@ -17294,7 +17186,6 @@ struct sps_cfg_ul_c { bool cyclic_shift_sps_r15_present = false; bool harq_proc_id_offset_r15_present = false; bool rv_sps_ul_repeats_r15_present = false; - bool tpc_pdcch_cfg_pusch_sps_r15_present = false; bool total_num_pusch_sps_ul_repeats_r15_present = false; bool sps_cfg_idx_r15_present = false; cyclic_shift_sps_r15_e_ cyclic_shift_sps_r15; @@ -18496,8 +18387,8 @@ struct cfi_cfg_r15_s { // CFI-PatternConfig-r15 ::= SEQUENCE struct cfi_pattern_cfg_r15_s { - typedef fixed_array cfi_pattern_sf_r15_l_; - typedef fixed_array cfi_pattern_slot_subslot_r15_l_; + using cfi_pattern_sf_r15_l_ = std::array; + using cfi_pattern_slot_subslot_r15_l_ = std::array; // member variables bool cfi_pattern_sf_r15_present = false; @@ -18635,17 +18526,14 @@ struct drb_to_add_mod_s { // ... // group 0 bool drb_type_change_r12_present = false; - bool rlc_cfg_v1250_present = false; copy_ptr rlc_cfg_v1250; // group 1 - bool rlc_cfg_v1310_present = false; bool drb_type_lwa_r13_present = false; bool drb_type_lwip_r13_present = false; copy_ptr rlc_cfg_v1310; bool drb_type_lwa_r13 = false; drb_type_lwip_r13_e_ drb_type_lwip_r13; // group 2 - bool rlc_cfg_v1430_present = false; bool lwip_ul_aggregation_r14_present = false; bool lwip_dl_aggregation_r14_present = false; bool lwa_wlan_ac_r14_present = false; @@ -18654,12 +18542,9 @@ struct drb_to_add_mod_s { bool lwip_dl_aggregation_r14 = false; lwa_wlan_ac_r14_e_ lwa_wlan_ac_r14; // group 3 - bool rlc_cfg_v1510_present = false; copy_ptr rlc_cfg_v1510; // group 4 - bool rlc_cfg_v1530_present = false; - bool rlc_bearer_cfg_dupl_r15_present = false; - bool lc_ch_id_r15_present = false; + bool lc_ch_id_r15_present = false; copy_ptr rlc_cfg_v1530; copy_ptr rlc_bearer_cfg_dupl_r15; uint8_t lc_ch_id_r15 = 32; @@ -19891,8 +19776,8 @@ struct pucch_cfg_ded_r13_s { n1_pucch_an_cs_r13_c_ n1_pucch_an_cs_r13; }; struct format4_r13_s_ { - typedef fixed_array format4_res_cfg_r13_l_; - typedef dyn_array format4_multi_csi_res_cfg_r13_l_; + using format4_res_cfg_r13_l_ = std::array; + typedef dyn_array format4_multi_csi_res_cfg_r13_l_; // member variables bool format4_multi_csi_res_cfg_r13_present = false; @@ -19900,7 +19785,7 @@ struct pucch_cfg_ded_r13_s { format4_multi_csi_res_cfg_r13_l_ format4_multi_csi_res_cfg_r13; }; struct format5_r13_s_ { - typedef fixed_array format5_res_cfg_r13_l_; + using format5_res_cfg_r13_l_ = std::array; // member variables bool format5_multi_csi_res_cfg_r13_present = false; @@ -21207,7 +21092,6 @@ struct sps_cfg_dl_c { n1_pucch_an_persistent_list_l n1_pucch_an_persistent_list; // ... // group 0 - bool two_ant_port_activ_r10_present = false; copy_ptr two_ant_port_activ_r10; // sequence methods @@ -21354,10 +21238,8 @@ struct srb_to_add_mod_s { lc_ch_cfg_c_ lc_ch_cfg; // ... // group 0 - bool pdcp_ver_change_r15_present = false; - bool rlc_cfg_v1530_present = false; - bool rlc_bearer_cfg_dupl_r15_present = false; - bool srb_id_v1530_present = false; + bool pdcp_ver_change_r15_present = false; + bool srb_id_v1530_present = false; copy_ptr rlc_cfg_v1530; copy_ptr rlc_bearer_cfg_dupl_r15; uint8_t srb_id_v1530 = 4; @@ -22678,43 +22560,30 @@ struct mac_main_cfg_s { bool sr_prohibit_timer_r9_present = false; uint8_t sr_prohibit_timer_r9 = 0; // group 1 - bool mac_main_cfg_v1020_present = false; copy_ptr mac_main_cfg_v1020; // group 2 - bool stag_to_release_list_r11_present = false; - bool stag_to_add_mod_list_r11_present = false; - bool drx_cfg_v1130_present = false; copy_ptr stag_to_release_list_r11; copy_ptr stag_to_add_mod_list_r11; copy_ptr drx_cfg_v1130; // group 3 bool e_harq_pattern_r12_present = false; - bool dual_connect_phr_present = false; - bool lc_ch_sr_cfg_r12_present = false; bool e_harq_pattern_r12 = false; copy_ptr dual_connect_phr; copy_ptr lc_ch_sr_cfg_r12; // group 4 - bool drx_cfg_v1310_present = false; - bool extended_phr2_r13_present = false; - bool e_drx_cfg_cycle_start_offset_r13_present = false; + bool extended_phr2_r13_present = false; copy_ptr drx_cfg_v1310; bool extended_phr2_r13 = false; copy_ptr e_drx_cfg_cycle_start_offset_r13; // group 5 - bool drx_cfg_r13_present = false; copy_ptr drx_cfg_r13; // group 6 - bool skip_ul_tx_r14_present = false; - bool data_inactivity_timer_cfg_r14_present = false; copy_ptr skip_ul_tx_r14; copy_ptr data_inactivity_timer_cfg_r14; // group 7 bool rai_activation_r14_present = false; // group 8 - bool short_tti_and_spt_r15_present = false; bool mpdcch_ul_harq_ack_feedback_cfg_r15_present = false; - bool dormant_state_timers_r15_present = false; copy_ptr short_tti_and_spt_r15; bool mpdcch_ul_harq_ack_feedback_cfg_r15 = false; copy_ptr dormant_state_timers_r15; @@ -23350,22 +23219,10 @@ struct phys_cfg_ded_s { sched_request_cfg_c sched_request_cfg; // ... // group 0 - bool cqi_report_cfg_v920_present = false; - bool ant_info_v920_present = false; copy_ptr cqi_report_cfg_v920; copy_ptr ant_info_v920; // group 1 - bool ant_info_r10_present = false; - bool ant_info_ul_r10_present = false; - bool cif_presence_r10_present = false; - bool cqi_report_cfg_r10_present = false; - bool csi_rs_cfg_r10_present = false; - bool pucch_cfg_ded_v1020_present = false; - bool pusch_cfg_ded_v1020_present = false; - bool sched_request_cfg_v1020_present = false; - bool srs_ul_cfg_ded_v1020_present = false; - bool srs_ul_cfg_ded_aperiodic_r10_present = false; - bool ul_pwr_ctrl_ded_v1020_present = false; + bool cif_presence_r10_present = false; copy_ptr ant_info_r10; copy_ptr ant_info_ul_r10; bool cif_presence_r10 = false; @@ -23378,19 +23235,8 @@ struct phys_cfg_ded_s { copy_ptr srs_ul_cfg_ded_aperiodic_r10; copy_ptr ul_pwr_ctrl_ded_v1020; // group 2 - bool add_spec_emission_ca_r10_present = false; copy_ptr add_spec_emission_ca_r10; // group 3 - bool csi_rs_cfg_nzp_to_release_list_r11_present = false; - bool csi_rs_cfg_nzp_to_add_mod_list_r11_present = false; - bool csi_rs_cfg_zp_to_release_list_r11_present = false; - bool csi_rs_cfg_zp_to_add_mod_list_r11_present = false; - bool epdcch_cfg_r11_present = false; - bool pdsch_cfg_ded_v1130_present = false; - bool cqi_report_cfg_v1130_present = false; - bool pucch_cfg_ded_v1130_present = false; - bool pusch_cfg_ded_v1130_present = false; - bool ul_pwr_ctrl_ded_v1130_present = false; copy_ptr csi_rs_cfg_nzp_to_release_list_r11; copy_ptr csi_rs_cfg_nzp_to_add_mod_list_r11; copy_ptr csi_rs_cfg_zp_to_release_list_r11; @@ -23402,14 +23248,6 @@ struct phys_cfg_ded_s { copy_ptr pusch_cfg_ded_v1130; copy_ptr ul_pwr_ctrl_ded_v1130; // group 4 - bool ant_info_v1250_present = false; - bool eimta_main_cfg_r12_present = false; - bool eimta_main_cfg_pcell_r12_present = false; - bool pucch_cfg_ded_v1250_present = false; - bool cqi_report_cfg_pcell_v1250_present = false; - bool ul_pwr_ctrl_ded_v1250_present = false; - bool pusch_cfg_ded_v1250_present = false; - bool csi_rs_cfg_v1250_present = false; copy_ptr ant_info_v1250; copy_ptr eimta_main_cfg_r12; copy_ptr eimta_main_cfg_pcell_r12; @@ -23419,22 +23257,8 @@ struct phys_cfg_ded_s { copy_ptr pusch_cfg_ded_v1250; copy_ptr csi_rs_cfg_v1250; // group 5 - bool pdsch_cfg_ded_v1280_present = false; copy_ptr pdsch_cfg_ded_v1280; // group 6 - bool pdsch_cfg_ded_v1310_present = false; - bool pucch_cfg_ded_r13_present = false; - bool pusch_cfg_ded_r13_present = false; - bool pdcch_candidate_reductions_r13_present = false; - bool cqi_report_cfg_v1310_present = false; - bool srs_ul_cfg_ded_v1310_present = false; - bool srs_ul_cfg_ded_up_pts_ext_r13_present = false; - bool srs_ul_cfg_ded_aperiodic_v1310_present = false; - bool srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present = false; - bool csi_rs_cfg_v1310_present = false; - bool ce_mode_r13_present = false; - bool csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present = false; - bool csi_rs_cfg_nzp_to_release_list_ext_r13_present = false; copy_ptr pdsch_cfg_ded_v1310; copy_ptr pucch_cfg_ded_r13; copy_ptr pusch_cfg_ded_r13; @@ -23449,25 +23273,10 @@ struct phys_cfg_ded_s { copy_ptr csi_rs_cfg_nzp_to_add_mod_list_ext_r13; copy_ptr csi_rs_cfg_nzp_to_release_list_ext_r13; // group 7 - bool cqi_report_cfg_v1320_present = false; copy_ptr cqi_report_cfg_v1320; // group 8 - bool type_a_srs_tpc_pdcch_group_r14_present = false; - bool must_cfg_r14_present = false; - bool pusch_enhance_cfg_r14_present = false; - bool ce_pdsch_pusch_enhancement_cfg_r14_present = false; - bool ant_info_v1430_present = false; - bool pucch_cfg_ded_v1430_present = false; - bool pdsch_cfg_ded_v1430_present = false; - bool pusch_cfg_ded_v1430_present = false; - bool srs_ul_periodic_cfg_ded_list_r14_present = false; - bool srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present = false; - bool srs_ul_aperiodic_cfg_ded_list_r14_present = false; - bool srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present = false; - bool csi_rs_cfg_v1430_present = false; - bool csi_rs_cfg_zp_ap_list_r14_present = false; - bool cqi_report_cfg_v1430_present = false; - bool semi_open_loop_r14_present = false; + bool ce_pdsch_pusch_enhancement_cfg_r14_present = false; + bool semi_open_loop_r14_present = false; copy_ptr type_a_srs_tpc_pdcch_group_r14; copy_ptr must_cfg_r14; copy_ptr pusch_enhance_cfg_r14; @@ -23484,18 +23293,8 @@ struct phys_cfg_ded_s { copy_ptr cqi_report_cfg_v1430; bool semi_open_loop_r14 = false; // group 9 - bool csi_rs_cfg_v1480_present = false; copy_ptr csi_rs_cfg_v1480; // group 10 - bool phys_cfg_ded_stti_r15_present = false; - bool pdsch_cfg_ded_v1530_present = false; - bool pusch_cfg_ded_v1530_present = false; - bool cqi_report_cfg_v1530_present = false; - bool ant_info_v1530_present = false; - bool csi_rs_cfg_v1530_present = false; - bool ul_pwr_ctrl_ded_v1530_present = false; - bool semi_static_cfi_cfg_r15_present = false; - bool blind_pdsch_repeat_cfg_r15_present = false; copy_ptr phys_cfg_ded_stti_r15; copy_ptr pdsch_cfg_ded_v1530; copy_ptr pusch_cfg_ded_v1530; @@ -23735,7 +23534,7 @@ struct sps_cfg_v1530_s { }; // SRB-ToAddModExtList-r15 ::= SEQUENCE (SIZE (1)) OF SRB-ToAddMod -typedef fixed_array srb_to_add_mod_ext_list_r15_l; +using srb_to_add_mod_ext_list_r15_l = std::array; // SRB-ToAddModList ::= SEQUENCE (SIZE (1..2)) OF SRB-ToAddMod typedef dyn_array srb_to_add_mod_list_l; @@ -23772,15 +23571,11 @@ struct idle_mode_mob_ctrl_info_s { t320_e_ t320; // ... // group 0 - bool freq_prio_list_ext_eutra_r12_present = false; copy_ptr freq_prio_list_ext_eutra_r12; // group 1 - bool freq_prio_list_eutra_v1310_present = false; - bool freq_prio_list_ext_eutra_v1310_present = false; copy_ptr freq_prio_list_eutra_v1310; copy_ptr freq_prio_list_ext_eutra_v1310; // group 2 - bool freq_prio_list_nr_r15_present = false; copy_ptr freq_prio_list_nr_r15; // sequence methods @@ -23987,34 +23782,20 @@ struct rr_cfg_ded_s { phys_cfg_ded_s phys_cfg_ded; // ... // group 0 - bool rlf_timers_and_consts_r9_present = false; copy_ptr rlf_timers_and_consts_r9; // group 1 - bool meas_sf_pattern_pcell_r10_present = false; copy_ptr meas_sf_pattern_pcell_r10; // group 2 - bool neigh_cells_crs_info_r11_present = false; copy_ptr neigh_cells_crs_info_r11; // group 3 - bool naics_info_r12_present = false; copy_ptr naics_info_r12; // group 4 - bool neigh_cells_crs_info_r13_present = false; - bool rlf_timers_and_consts_r13_present = false; copy_ptr neigh_cells_crs_info_r13; copy_ptr rlf_timers_and_consts_r13; // group 5 - bool sps_cfg_v1430_present = false; copy_ptr sps_cfg_v1430; // group 6 - bool srb_to_add_mod_ext_list_r15_present = false; - bool srb_to_release_ext_list_r15_present = false; - bool sps_cfg_v1530_present = false; - bool crs_intf_mitig_cfg_r15_present = false; - bool neigh_cells_crs_info_r15_present = false; - bool drb_to_add_mod_list_r15_present = false; - bool drb_to_release_list_r15_present = false; - bool srb_to_release_list_dupl_r15_present = false; + bool srb_to_release_ext_list_r15_present = false; copy_ptr srb_to_add_mod_ext_list_r15; uint8_t srb_to_release_ext_list_r15 = 4; copy_ptr sps_cfg_v1530; @@ -26658,15 +26439,6 @@ struct phys_cfg_ded_scell_r10_s { ul_cfg_r10_s_ ul_cfg_r10; // ... // group 0 - bool csi_rs_cfg_nzp_to_release_list_r11_present = false; - bool csi_rs_cfg_nzp_to_add_mod_list_r11_present = false; - bool csi_rs_cfg_zp_to_release_list_r11_present = false; - bool csi_rs_cfg_zp_to_add_mod_list_r11_present = false; - bool epdcch_cfg_r11_present = false; - bool pdsch_cfg_ded_v1130_present = false; - bool cqi_report_cfg_v1130_present = false; - bool pusch_cfg_ded_v1130_present = false; - bool ul_pwr_ctrl_ded_scell_v1130_present = false; copy_ptr csi_rs_cfg_nzp_to_release_list_r11; copy_ptr csi_rs_cfg_nzp_to_add_mod_list_r11; copy_ptr csi_rs_cfg_zp_to_release_list_r11; @@ -26677,34 +26449,15 @@ struct phys_cfg_ded_scell_r10_s { copy_ptr pusch_cfg_ded_v1130; copy_ptr ul_pwr_ctrl_ded_scell_v1130; // group 1 - bool ant_info_v1250_present = false; - bool eimta_main_cfg_scell_r12_present = false; - bool cqi_report_cfg_scell_v1250_present = false; - bool ul_pwr_ctrl_ded_scell_v1250_present = false; - bool csi_rs_cfg_v1250_present = false; copy_ptr ant_info_v1250; copy_ptr eimta_main_cfg_scell_r12; copy_ptr cqi_report_cfg_scell_v1250; copy_ptr ul_pwr_ctrl_ded_scell_v1250; copy_ptr csi_rs_cfg_v1250; // group 2 - bool pdsch_cfg_ded_v1280_present = false; copy_ptr pdsch_cfg_ded_v1280; // group 3 - bool pucch_cell_r13_present = false; - bool pucch_scell_present = false; - bool cross_carrier_sched_cfg_r13_present = false; - bool pdcch_cfg_scell_r13_present = false; - bool cqi_report_cfg_v1310_present = false; - bool pdsch_cfg_ded_v1310_present = false; - bool srs_ul_cfg_ded_v1310_present = false; - bool srs_ul_cfg_ded_up_pts_ext_r13_present = false; - bool srs_ul_cfg_ded_aperiodic_v1310_present = false; - bool srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present = false; - bool csi_rs_cfg_v1310_present = false; - bool laa_scell_cfg_r13_present = false; - bool csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present = false; - bool csi_rs_cfg_nzp_to_release_list_ext_r13_present = false; + bool pucch_cell_r13_present = false; copy_ptr pucch_scell; copy_ptr cross_carrier_sched_cfg_r13; copy_ptr pdcch_cfg_scell_r13; @@ -26719,23 +26472,9 @@ struct phys_cfg_ded_scell_r10_s { copy_ptr csi_rs_cfg_nzp_to_add_mod_list_ext_r13; copy_ptr csi_rs_cfg_nzp_to_release_list_ext_r13; // group 4 - bool cqi_report_cfg_v1320_present = false; copy_ptr cqi_report_cfg_v1320; // group 5 - bool laa_scell_cfg_v1430_present = false; - bool type_b_srs_tpc_pdcch_cfg_r14_present = false; - bool ul_pusch_less_pwr_ctrl_ded_v1430_present = false; - bool srs_ul_periodic_cfg_ded_list_r14_present = false; - bool srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present = false; - bool srs_ul_aperiodic_cfg_ded_list_r14_present = false; - bool srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present = false; - bool must_cfg_r14_present = false; - bool pusch_cfg_ded_v1430_present = false; - bool csi_rs_cfg_v1430_present = false; - bool csi_rs_cfg_zp_ap_list_r14_present = false; - bool cqi_report_cfg_v1430_present = false; - bool semi_open_loop_r14_present = false; - bool pdsch_cfg_ded_scell_v1430_present = false; + bool semi_open_loop_r14_present = false; copy_ptr laa_scell_cfg_v1430; copy_ptr type_b_srs_tpc_pdcch_cfg_r14; copy_ptr ul_pusch_less_pwr_ctrl_ded_v1430; @@ -26751,20 +26490,8 @@ struct phys_cfg_ded_scell_r10_s { bool semi_open_loop_r14 = false; copy_ptr pdsch_cfg_ded_scell_v1430; // group 6 - bool csi_rs_cfg_v1480_present = false; copy_ptr csi_rs_cfg_v1480; // group 7 - bool phys_cfg_ded_stti_r15_present = false; - bool pdsch_cfg_ded_v1530_present = false; - bool cqi_report_cfg_v1530_present = false; - bool cqi_report_cfg_scell_r15_present = false; - bool cqi_short_cfg_scell_r15_present = false; - bool csi_rs_cfg_v1530_present = false; - bool ul_pwr_ctrl_ded_scell_v1530_present = false; - bool laa_scell_cfg_v1530_present = false; - bool pusch_cfg_ded_v1530_present = false; - bool semi_static_cfi_cfg_r15_present = false; - bool blind_pdsch_repeat_cfg_r15_present = false; copy_ptr phys_cfg_ded_stti_r15; copy_ptr pdsch_cfg_ded_v1530; copy_ptr cqi_report_cfg_v1530; @@ -27095,37 +26822,25 @@ struct rr_cfg_common_scell_r10_s { bool ul_carrier_freq_v1090_present = false; uint32_t ul_carrier_freq_v1090 = 65536; // group 1 - bool rach_cfg_common_scell_r11_present = false; - bool prach_cfg_scell_r11_present = false; - bool tdd_cfg_v1130_present = false; - bool ul_pwr_ctrl_common_scell_v1130_present = false; copy_ptr rach_cfg_common_scell_r11; copy_ptr prach_cfg_scell_r11; copy_ptr tdd_cfg_v1130; copy_ptr ul_pwr_ctrl_common_scell_v1130; // group 2 - bool pusch_cfg_common_v1270_present = false; copy_ptr pusch_cfg_common_v1270; // group 3 - bool pucch_cfg_common_r13_present = false; - bool ul_pwr_ctrl_common_scell_v1310_present = false; copy_ptr pucch_cfg_common_r13; copy_ptr ul_pwr_ctrl_common_scell_v1310; // group 4 - bool high_speed_cfg_scell_r14_present = false; - bool prach_cfg_v1430_present = false; - bool ul_cfg_r14_present = false; - bool harq_ref_cfg_r14_present = false; - bool srs_flex_timing_r14_present = false; + bool harq_ref_cfg_r14_present = false; + bool srs_flex_timing_r14_present = false; copy_ptr high_speed_cfg_scell_r14; copy_ptr prach_cfg_v1430; copy_ptr ul_cfg_r14; harq_ref_cfg_r14_e_ harq_ref_cfg_r14; // group 5 - bool mbsfn_sf_cfg_list_v1430_present = false; copy_ptr mbsfn_sf_cfg_list_v1430; // group 6 - bool ul_pwr_ctrl_common_scell_v1530_present = false; copy_ptr ul_pwr_ctrl_common_scell_v1530; // sequence methods @@ -27142,21 +26857,15 @@ struct rr_cfg_ded_scell_r10_s { phys_cfg_ded_scell_r10_s phys_cfg_ded_scell_r10; // ... // group 0 - bool mac_main_cfg_scell_r11_present = false; copy_ptr mac_main_cfg_scell_r11; // group 1 - bool naics_info_r12_present = false; copy_ptr naics_info_r12; // group 2 - bool neigh_cells_crs_info_scell_r13_present = false; copy_ptr neigh_cells_crs_info_scell_r13; // group 3 - bool phys_cfg_ded_scell_v1370_present = false; copy_ptr phys_cfg_ded_scell_v1370; // group 4 bool crs_intf_mitig_enabled_r15_present = false; - bool neigh_cells_crs_info_r15_present = false; - bool sps_cfg_v1530_present = false; bool crs_intf_mitig_enabled_r15 = false; copy_ptr neigh_cells_crs_info_r15; copy_ptr sps_cfg_v1530; @@ -27380,13 +27089,10 @@ struct drb_to_add_mod_scg_r12_s { lc_ch_cfg_s lc_ch_cfg_scg_r12; // ... // group 0 - bool rlc_cfg_v1430_present = false; copy_ptr rlc_cfg_v1430; // group 1 - bool lc_ch_id_scg_r15_present = false; - bool rlc_cfg_v1530_present = false; - bool rlc_bearer_cfg_dupl_r15_present = false; - uint8_t lc_ch_id_scg_r15 = 32; + bool lc_ch_id_scg_r15_present = false; + uint8_t lc_ch_id_scg_r15 = 32; copy_ptr rlc_cfg_v1530; copy_ptr rlc_bearer_cfg_dupl_r15; @@ -28045,10 +27751,8 @@ struct rr_cfg_common_ps_cell_r12_s { ul_pwr_ctrl_common_ps_cell_r12_s ul_pwr_ctrl_common_ps_cell_r12; // ... // group 0 - bool ul_pwr_ctrl_common_ps_cell_v1310_present = false; copy_ptr ul_pwr_ctrl_common_ps_cell_v1310; // group 1 - bool ul_pwr_ctrl_common_ps_cell_v1530_present = false; copy_ptr ul_pwr_ctrl_common_ps_cell_v1530; // sequence methods @@ -28091,15 +27795,11 @@ struct rr_cfg_ded_ps_cell_r12_s { naics_assist_info_r12_c naics_info_r12; // ... // group 0 - bool neigh_cells_crs_info_ps_cell_r13_present = false; copy_ptr neigh_cells_crs_info_ps_cell_r13; // group 1 - bool sps_cfg_v1430_present = false; copy_ptr sps_cfg_v1430; // group 2 - bool sps_cfg_v1530_present = false; bool crs_intf_mitig_enabled_r15_present = false; - bool neigh_cells_crs_info_r15_present = false; copy_ptr sps_cfg_v1530; bool crs_intf_mitig_enabled_r15 = false; copy_ptr neigh_cells_crs_info_r15; @@ -28150,7 +27850,6 @@ struct scell_to_add_mod_r10_s { bool dl_carrier_freq_v1090_present = false; uint32_t dl_carrier_freq_v1090 = 65536; // group 1 - bool ant_info_ded_scell_v10i0_present = false; copy_ptr ant_info_ded_scell_v10i0; // group 2 bool srs_switch_from_serv_cell_idx_r14_present = false; @@ -28436,7 +28135,6 @@ struct wlan_mob_cfg_r13_s { association_timer_r13_e_ association_timer_r13; // ... // group 0 - bool wlan_suspend_cfg_r14_present = false; copy_ptr wlan_suspend_cfg_r14; // sequence methods @@ -28511,7 +28209,6 @@ struct mob_ctrl_info_scg_r12_s { // ... // group 0 bool make_before_break_scg_r14_present = false; - bool rach_skip_scg_r14_present = false; copy_ptr rach_skip_scg_r14; // sequence methods @@ -28545,13 +28242,11 @@ struct ps_cell_to_add_mod_r12_s { rr_cfg_ded_ps_cell_r12_s rr_cfg_ded_ps_cell_r12; // ... // group 0 - bool ant_info_ded_ps_cell_v1280_present = false; copy_ptr ant_info_ded_ps_cell_v1280; // group 1 bool s_cell_idx_r13_present = false; uint8_t s_cell_idx_r13 = 1; // group 2 - bool rr_cfg_ded_ps_cell_v1370_present = false; copy_ptr rr_cfg_ded_ps_cell_v1370; // sequence methods @@ -28748,7 +28443,6 @@ struct rr_cfg_ded_scg_r12_s { rlf_timers_and_consts_scg_r12_c rlf_timers_and_consts_scg_r12; // ... // group 0 - bool drb_to_add_mod_list_scg_r15_present = false; copy_ptr drb_to_add_mod_list_scg_r15; // sequence methods @@ -29061,10 +28755,7 @@ struct sl_v2x_cfg_ded_r14_s { sl_cbr_common_tx_cfg_list_r14_s cbr_ded_tx_cfg_list_r14; // ... // group 0 - bool comm_tx_res_v1530_present = false; - bool v2x_packet_dupl_cfg_r15_present = false; - bool sync_freq_list_r15_present = false; - bool slss_tx_multi_freq_r15_present = false; + bool slss_tx_multi_freq_r15_present = false; copy_ptr comm_tx_res_v1530; copy_ptr v2x_packet_dupl_cfg_r15; copy_ptr sync_freq_list_r15; @@ -29349,19 +29040,13 @@ struct scg_cfg_part_scg_r12_s { mob_ctrl_info_scg_r12_s mob_ctrl_info_scg_r12; // ... // group 0 - bool s_cell_to_release_list_scg_ext_r13_present = false; - bool s_cell_to_add_mod_list_scg_ext_r13_present = false; copy_ptr s_cell_to_release_list_scg_ext_r13; copy_ptr s_cell_to_add_mod_list_scg_ext_r13; // group 1 - bool s_cell_to_add_mod_list_scg_ext_v1370_present = false; copy_ptr s_cell_to_add_mod_list_scg_ext_v1370; // group 2 - bool p_scell_to_add_mod_v1440_present = false; copy_ptr p_scell_to_add_mod_v1440; // group 3 - bool s_cell_group_to_release_list_scg_r15_present = false; - bool s_cell_group_to_add_mod_list_scg_r15_present = false; copy_ptr s_cell_group_to_release_list_scg_r15; copy_ptr s_cell_group_to_add_mod_list_scg_r15; @@ -29952,7 +29637,6 @@ struct sl_comm_cfg_r12_s { comm_tx_res_r12_c_ comm_tx_res_r12; // ... // group 0 - bool comm_tx_res_v1310_present = false; bool comm_tx_allow_relay_ded_r13_present = false; copy_ptr comm_tx_res_v1310; bool comm_tx_allow_relay_ded_r13 = false; @@ -30340,15 +30024,9 @@ struct sl_disc_cfg_r12_s { disc_tx_res_r12_c_ disc_tx_res_r12; // ... // group 0 - bool disc_tf_idx_list_v1260_present = false; copy_ptr disc_tf_idx_list_v1260; // group 1 - bool disc_tx_res_ps_r13_present = false; - bool disc_tx_inter_freq_info_r13_present = false; - bool gap_requests_allowed_ded_r13_present = false; - bool disc_rx_gap_cfg_r13_present = false; - bool disc_tx_gap_cfg_r13_present = false; - bool disc_sys_info_to_report_cfg_r13_present = false; + bool gap_requests_allowed_ded_r13_present = false; copy_ptr disc_tx_res_ps_r13; copy_ptr disc_tx_inter_freq_info_r13; bool gap_requests_allowed_ded_r13 = false; @@ -32017,7 +31695,6 @@ struct idc_cfg_r11_s { // group 1 bool idc_hardware_sharing_ind_r13_present = false; // group 2 - bool idc_ind_mrdc_r15_present = false; copy_ptr idc_ind_mrdc_r15; // sequence methods @@ -32139,42 +31816,31 @@ struct meas_obj_eutra_s { uint16_t cell_for_which_to_report_cgi = 0; // ... // group 0 - bool meas_cycle_scell_r10_present = false; - bool meas_sf_pattern_cfg_neigh_r10_present = false; + bool meas_cycle_scell_r10_present = false; meas_cycle_scell_r10_e meas_cycle_scell_r10; copy_ptr meas_sf_pattern_cfg_neigh_r10; // group 1 bool wideband_rsrq_meas_r11_present = false; bool wideband_rsrq_meas_r11 = false; // group 2 - bool alt_ttt_cells_to_rem_list_r12_present = false; - bool alt_ttt_cells_to_add_mod_list_r12_present = false; - bool t312_r12_present = false; - bool reduced_meas_performance_r12_present = false; - bool meas_ds_cfg_r12_present = false; + bool reduced_meas_performance_r12_present = false; copy_ptr alt_ttt_cells_to_rem_list_r12; copy_ptr alt_ttt_cells_to_add_mod_list_r12; copy_ptr t312_r12; bool reduced_meas_performance_r12 = false; copy_ptr meas_ds_cfg_r12; // group 3 - bool white_cells_to_rem_list_r13_present = false; - bool white_cells_to_add_mod_list_r13_present = false; - bool rmtc_cfg_r13_present = false; - bool carrier_freq_r13_present = false; + bool carrier_freq_r13_present = false; copy_ptr white_cells_to_rem_list_r13; copy_ptr white_cells_to_add_mod_list_r13; copy_ptr rmtc_cfg_r13; uint32_t carrier_freq_r13 = 65536; // group 4 - bool tx_res_pool_to_rem_list_r14_present = false; - bool tx_res_pool_to_add_list_r14_present = false; - bool fembms_mixed_carrier_r14_present = false; + bool fembms_mixed_carrier_r14_present = false; copy_ptr tx_res_pool_to_rem_list_r14; copy_ptr tx_res_pool_to_add_list_r14; bool fembms_mixed_carrier_r14 = false; // group 5 - bool meas_sensing_cfg_r15_present = false; copy_ptr meas_sensing_cfg_r15; // sequence methods @@ -32269,8 +31935,6 @@ struct meas_obj_nr_r15_s { // group 0 bool cell_for_which_to_report_cgi_r15_present = false; bool derive_ssb_idx_from_cell_r15_present = false; - bool ss_rssi_meas_r15_present = false; - bool band_nr_r15_present = false; uint16_t cell_for_which_to_report_cgi_r15 = 0; bool derive_ssb_idx_from_cell_r15 = false; copy_ptr ss_rssi_meas_r15; @@ -32410,7 +32074,6 @@ struct meas_obj_utra_s { cell_for_which_to_report_cgi_c_ cell_for_which_to_report_cgi; // ... // group 0 - bool csg_allowed_report_cells_v930_present = false; copy_ptr csg_allowed_report_cells_v930; // group 1 bool reduced_meas_performance_r12_present = false; @@ -33131,14 +32794,11 @@ struct report_cfg_eutra_s { bool include_location_info_r10_present = false; bool report_add_neigh_meas_r10_present = false; // group 2 - bool alternative_time_to_trigger_r12_present = false; - bool use_t312_r12_present = false; - bool use_ps_cell_r12_present = false; - bool a_n_thres1_v1250_present = false; - bool a5_thres2_v1250_present = false; - bool report_strongest_csi_rss_r12_present = false; - bool report_crs_meas_r12_present = false; - bool trigger_quant_csi_rs_r12_present = false; + bool use_t312_r12_present = false; + bool use_ps_cell_r12_present = false; + bool report_strongest_csi_rss_r12_present = false; + bool report_crs_meas_r12_present = false; + bool trigger_quant_csi_rs_r12_present = false; copy_ptr alternative_time_to_trigger_r12; bool use_t312_r12 = false; bool use_ps_cell_r12 = false; @@ -33149,11 +32809,8 @@ struct report_cfg_eutra_s { bool trigger_quant_csi_rs_r12 = false; // group 3 bool report_sstd_meas_r13_present = false; - bool rs_sinr_cfg_r13_present = false; bool use_white_cell_list_r13_present = false; - bool meas_rssi_report_cfg_r13_present = false; bool include_multi_band_info_r13_present = false; - bool ul_delay_cfg_r13_present = false; bool report_sstd_meas_r13 = false; copy_ptr rs_sinr_cfg_r13; bool use_white_cell_list_r13 = false; @@ -33169,8 +32826,6 @@ struct report_cfg_eutra_s { bool max_report_rs_idx_r15_present = false; uint8_t max_report_rs_idx_r15 = 0; // group 7 - bool include_bt_meas_r15_present = false; - bool include_wlan_meas_r15_present = false; bool purpose_r15_present = false; bool nof_triggering_cells_r15_present = false; bool a4_a5_report_on_leave_r15_present = false; @@ -33648,20 +33303,16 @@ struct report_cfg_inter_rat_s { bool include_location_info_r11_present = false; bool include_location_info_r11 = false; // group 3 - bool b2_thres1_v1250_present = false; copy_ptr b2_thres1_v1250; // group 4 - bool report_quant_wlan_r13_present = false; copy_ptr report_quant_wlan_r13; // group 5 bool report_any_wlan_r14_present = false; bool report_any_wlan_r14 = false; // group 6 - bool report_quant_cell_nr_r15_present = false; - bool max_report_rs_idx_r15_present = false; - bool report_quant_rs_idx_nr_r15_present = false; - bool report_rs_idx_results_nr_present = false; - bool report_sftd_meas_r15_present = false; + bool max_report_rs_idx_r15_present = false; + bool report_rs_idx_results_nr_present = false; + bool report_sftd_meas_r15_present = false; copy_ptr report_quant_cell_nr_r15; uint8_t max_report_rs_idx_r15 = 0; copy_ptr report_quant_rs_idx_nr_r15; @@ -34411,29 +34062,20 @@ struct other_cfg_r9_s { report_proximity_cfg_r9_s report_proximity_cfg_r9; // ... // group 0 - bool idc_cfg_r11_present = false; - bool pwr_pref_ind_cfg_r11_present = false; - bool obtain_location_cfg_r11_present = false; copy_ptr idc_cfg_r11; copy_ptr pwr_pref_ind_cfg_r11; copy_ptr obtain_location_cfg_r11; // group 1 - bool bw_pref_ind_timer_r14_present = false; - bool sps_assist_info_report_r14_present = false; - bool delay_budget_report_cfg_r14_present = false; - bool rlm_report_cfg_r14_present = false; + bool bw_pref_ind_timer_r14_present = false; + bool sps_assist_info_report_r14_present = false; bw_pref_ind_timer_r14_e_ bw_pref_ind_timer_r14; bool sps_assist_info_report_r14 = false; copy_ptr delay_budget_report_cfg_r14; copy_ptr rlm_report_cfg_r14; // group 2 - bool overheat_assist_cfg_r14_present = false; copy_ptr overheat_assist_cfg_r14; // group 3 - bool meas_cfg_app_layer_r15_present = false; - bool ailc_bit_cfg_r15_present = false; - bool bt_name_list_cfg_r15_present = false; - bool wlan_name_list_cfg_r15_present = false; + bool ailc_bit_cfg_r15_present = false; copy_ptr meas_cfg_app_layer_r15; bool ailc_bit_cfg_r15 = false; copy_ptr bt_name_list_cfg_r15; @@ -35582,18 +35224,13 @@ struct quant_cfg_s { quant_cfg_cdma2000_s quant_cfg_cdma2000; // ... // group 0 - bool quant_cfg_utra_v1020_present = false; copy_ptr quant_cfg_utra_v1020; // group 1 - bool quant_cfg_eutra_v1250_present = false; copy_ptr quant_cfg_eutra_v1250; // group 2 - bool quant_cfg_eutra_v1310_present = false; - bool quant_cfg_wlan_r13_present = false; copy_ptr quant_cfg_eutra_v1310; copy_ptr quant_cfg_wlan_r13; // group 3 - bool quant_cfg_nr_list_r15_present = false; copy_ptr quant_cfg_nr_list_r15; // sequence methods @@ -35806,21 +35443,12 @@ struct rr_cfg_common_s { ul_cp_len_e ul_cp_len; // ... // group 0 - bool ul_pwr_ctrl_common_v1020_present = false; copy_ptr ul_pwr_ctrl_common_v1020; // group 1 - bool tdd_cfg_v1130_present = false; copy_ptr tdd_cfg_v1130; // group 2 - bool pusch_cfg_common_v1270_present = false; copy_ptr pusch_cfg_common_v1270; // group 3 - bool prach_cfg_v1310_present = false; - bool freq_hop_params_r13_present = false; - bool pdsch_cfg_common_v1310_present = false; - bool pucch_cfg_common_v1310_present = false; - bool pusch_cfg_common_v1310_present = false; - bool ul_pwr_ctrl_common_v1310_present = false; copy_ptr prach_cfg_v1310; copy_ptr freq_hop_params_r13; copy_ptr pdsch_cfg_common_v1310; @@ -35828,20 +35456,13 @@ struct rr_cfg_common_s { copy_ptr pusch_cfg_common_v1310; copy_ptr ul_pwr_ctrl_common_v1310; // group 4 - bool high_speed_cfg_r14_present = false; - bool prach_cfg_v1430_present = false; - bool pucch_cfg_common_v1430_present = false; - bool tdd_cfg_v1430_present = false; copy_ptr high_speed_cfg_r14; copy_ptr prach_cfg_v1430; copy_ptr pucch_cfg_common_v1430; copy_ptr tdd_cfg_v1430; // group 5 - bool tdd_cfg_v1450_present = false; copy_ptr tdd_cfg_v1450; // group 6 - bool ul_pwr_ctrl_common_v1530_present = false; - bool high_speed_cfg_v1530_present = false; copy_ptr ul_pwr_ctrl_common_v1530; copy_ptr high_speed_cfg_v1530; @@ -36331,32 +35952,22 @@ struct meas_cfg_s { speed_state_pars_c_ speed_state_pars; // ... // group 0 - bool meas_obj_to_add_mod_list_v9e0_present = false; copy_ptr meas_obj_to_add_mod_list_v9e0; // group 1 bool allow_interruptions_r11_present = false; bool allow_interruptions_r11 = false; // group 2 - bool meas_scale_factor_r12_present = false; - bool meas_id_to_rem_list_ext_r12_present = false; - bool meas_id_to_add_mod_list_ext_r12_present = false; - bool meas_rsrq_on_all_symbols_r12_present = false; + bool meas_rsrq_on_all_symbols_r12_present = false; copy_ptr meas_scale_factor_r12; copy_ptr meas_id_to_rem_list_ext_r12; copy_ptr meas_id_to_add_mod_list_ext_r12; bool meas_rsrq_on_all_symbols_r12 = false; // group 3 - bool meas_obj_to_rem_list_ext_r13_present = false; - bool meas_obj_to_add_mod_list_ext_r13_present = false; - bool meas_id_to_add_mod_list_v1310_present = false; - bool meas_id_to_add_mod_list_ext_v1310_present = false; copy_ptr meas_obj_to_rem_list_ext_r13; copy_ptr meas_obj_to_add_mod_list_ext_r13; copy_ptr meas_id_to_add_mod_list_v1310; copy_ptr meas_id_to_add_mod_list_ext_v1310; // group 4 - bool meas_gap_cfg_per_cc_list_r14_present = false; - bool meas_gap_sharing_cfg_r14_present = false; copy_ptr meas_gap_cfg_per_cc_list_r14; copy_ptr meas_gap_sharing_cfg_r14; // group 5 @@ -36365,8 +35976,6 @@ struct meas_cfg_s { bool fr1_gap_r15 = false; bool mgta_r15 = false; // group 6 - bool meas_gap_cfg_dense_prs_r15_present = false; - bool height_thresh_ref_r15_present = false; copy_ptr meas_gap_cfg_dense_prs_r15; copy_ptr height_thresh_ref_r15; @@ -36409,15 +36018,12 @@ struct mob_ctrl_info_s { rach_cfg_ded_s rach_cfg_ded; // ... // group 0 - bool carrier_freq_v9e0_present = false; copy_ptr carrier_freq_v9e0; // group 1 bool drb_continue_rohc_r11_present = false; // group 2 - bool mob_ctrl_info_v2x_r14_present = false; bool ho_without_wt_change_r14_present = false; bool make_before_break_r14_present = false; - bool rach_skip_r14_present = false; bool same_sfn_ind_r14_present = false; copy_ptr mob_ctrl_info_v2x_r14; ho_without_wt_change_r14_e_ ho_without_wt_change_r14; @@ -42276,7 +41882,6 @@ struct meas_result_eutra_s { uint8_t rsrq_result = 0; // ... // group 0 - bool add_si_info_r9_present = false; copy_ptr add_si_info_r9; // group 1 bool primary_plmn_suitable_r12_present = false; @@ -42284,14 +41889,12 @@ struct meas_result_eutra_s { int8_t meas_result_v1250 = -30; // group 2 bool rs_sinr_result_r13_present = false; - bool cgi_info_v1310_present = false; uint8_t rs_sinr_result_r13 = 0; copy_ptr cgi_info_v1310; // group 3 bool meas_result_v1360_present = false; int8_t meas_result_v1360 = -17; // group 4 - bool cgi_info_minus5_gc_r15_present = false; copy_ptr cgi_info_minus5_gc_r15; // sequence methods @@ -42413,7 +42016,6 @@ struct meas_result_utra_s { uint8_t utra_ec_n0 = 0; // ... // group 0 - bool add_si_info_r9_present = false; copy_ptr add_si_info_r9; // group 1 bool primary_plmn_suitable_r12_present = false; @@ -42724,7 +42326,6 @@ struct location_info_r10_s { dyn_octstring gnss_tod_msec_r10; // ... // group 0 - bool vertical_velocity_info_r15_present = false; copy_ptr vertical_velocity_info_r15; // sequence methods @@ -43452,13 +43053,9 @@ struct log_meas_info_r10_s { meas_result_neigh_cells_r10_s_ meas_result_neigh_cells_r10; // ... // group 0 - bool meas_result_list_eutra_v1090_present = false; copy_ptr meas_result_list_eutra_v1090; // group 1 - bool meas_result_list_mbsfn_r12_present = false; - bool meas_result_serv_cell_v1250_present = false; - bool serv_cell_rsrq_type_r12_present = false; - bool meas_result_list_eutra_v1250_present = false; + bool meas_result_serv_cell_v1250_present = false; copy_ptr meas_result_list_mbsfn_r12; int8_t meas_result_serv_cell_v1250 = -30; copy_ptr serv_cell_rsrq_type_r12; @@ -43469,8 +43066,6 @@ struct log_meas_info_r10_s { bool meas_result_serv_cell_v1360_present = false; int8_t meas_result_serv_cell_v1360 = -17; // group 4 - bool log_meas_result_list_bt_r15_present = false; - bool log_meas_result_list_wlan_r15_present = false; copy_ptr log_meas_result_list_bt_r15; copy_ptr log_meas_result_list_wlan_r15; @@ -43505,7 +43100,6 @@ struct meas_result_cell_nr_r15_s { meas_result_ssb_idx_list_r15_l meas_result_rs_idx_list_r15; // ... // group 0 - bool cgi_info_r15_present = false; copy_ptr cgi_info_r15; // sequence methods @@ -43647,8 +43241,6 @@ struct conn_est_fail_report_r11_s { // ... // group 0 bool meas_result_failed_cell_v1250_present = false; - bool failed_cell_rsrq_type_r12_present = false; - bool meas_result_list_eutra_v1250_present = false; int8_t meas_result_failed_cell_v1250 = -30; copy_ptr failed_cell_rsrq_type_r12; copy_ptr meas_result_list_eutra_v1250; @@ -43656,8 +43248,6 @@ struct conn_est_fail_report_r11_s { bool meas_result_failed_cell_v1360_present = false; int8_t meas_result_failed_cell_v1360 = -17; // group 2 - bool log_meas_result_list_bt_r15_present = false; - bool log_meas_result_list_wlan_r15_present = false; copy_ptr log_meas_result_list_bt_r15; copy_ptr log_meas_result_list_wlan_r15; @@ -44075,8 +43665,6 @@ struct meas_result_serv_freq_r10_s { int8_t meas_result_scell_v1250 = -30; int8_t meas_result_best_neigh_cell_v1250 = -30; // group 1 - bool meas_result_scell_v1310_present = false; - bool meas_result_best_neigh_cell_v1310_present = false; copy_ptr meas_result_scell_v1310; copy_ptr meas_result_best_neigh_cell_v1310; @@ -44117,7 +43705,6 @@ struct meas_result_serv_freq_r13_s { meas_result_best_neigh_cell_r13_s_ meas_result_best_neigh_cell_r13; // ... // group 0 - bool meas_result_best_neigh_cell_v1360_present = false; copy_ptr meas_result_best_neigh_cell_v1360; // sequence methods @@ -44341,7 +43928,6 @@ struct sl_disc_sys_info_report_r13_s { int8_t ref_sig_pwr_r13 = -60; // ... // group 0 - bool freq_info_v1370_present = false; copy_ptr freq_info_v1370; // sequence methods @@ -45263,7 +44849,6 @@ struct rstd_inter_freq_info_r10_s { bool carrier_freq_v1090_present = false; uint32_t carrier_freq_v1090 = 65536; // group 1 - bool meas_prs_offset_r15_present = false; copy_ptr meas_prs_offset_r15; // sequence methods @@ -45500,7 +45085,6 @@ struct fail_report_scg_r12_s { // group 0 bool fail_type_v1290_present = false; // group 1 - bool meas_result_serv_freq_list_ext_r13_present = false; copy_ptr meas_result_serv_freq_list_ext_r13; // sequence methods @@ -45682,27 +45266,17 @@ struct meas_results_s { meas_result_neigh_cells_c_ meas_result_neigh_cells; // ... // group 0 - bool meas_result_for_ecid_r9_present = false; copy_ptr meas_result_for_ecid_r9; // group 1 - bool location_info_r10_present = false; - bool meas_result_serv_freq_list_r10_present = false; copy_ptr location_info_r10; copy_ptr meas_result_serv_freq_list_r10; // group 2 - bool meas_id_v1250_present = false; - bool meas_result_pcell_v1250_present = false; - bool meas_result_csi_rs_list_r12_present = false; - uint8_t meas_id_v1250 = 33; - int8_t meas_result_pcell_v1250 = -30; + bool meas_id_v1250_present = false; + bool meas_result_pcell_v1250_present = false; + uint8_t meas_id_v1250 = 33; + int8_t meas_result_pcell_v1250 = -30; copy_ptr meas_result_csi_rs_list_r12; // group 3 - bool meas_result_for_rssi_r13_present = false; - bool meas_result_serv_freq_list_ext_r13_present = false; - bool meas_result_sstd_r13_present = false; - bool meas_result_pcell_v1310_present = false; - bool ul_pdcp_delay_result_list_r13_present = false; - bool meas_result_list_wlan_r13_present = false; copy_ptr meas_result_for_rssi_r13; copy_ptr meas_result_serv_freq_list_ext_r13; copy_ptr meas_result_sstd_r13; @@ -45713,20 +45287,13 @@ struct meas_results_s { bool meas_result_pcell_v1360_present = false; int8_t meas_result_pcell_v1360 = -17; // group 5 - bool meas_result_list_cbr_r14_present = false; - bool meas_result_list_wlan_r14_present = false; copy_ptr meas_result_list_cbr_r14; copy_ptr meas_result_list_wlan_r14; // group 6 - bool meas_result_serv_freq_list_nr_r15_present = false; - bool meas_result_cell_list_sftd_r15_present = false; copy_ptr meas_result_serv_freq_list_nr_r15; copy_ptr meas_result_cell_list_sftd_r15; // group 7 - bool log_meas_result_list_bt_r15_present = false; - bool log_meas_result_list_wlan_r15_present = false; - bool meas_result_sensing_r15_present = false; - bool height_ue_r15_present = false; + bool height_ue_r15_present = false; copy_ptr log_meas_result_list_bt_r15; copy_ptr log_meas_result_list_wlan_r15; copy_ptr meas_result_sensing_r15; @@ -46007,12 +45574,8 @@ struct rlf_report_r9_s { meas_result_neigh_cells_r9_s_ meas_result_neigh_cells_r9; // ... // group 0 - bool location_info_r10_present = false; - bool failed_pcell_id_r10_present = false; - bool reest_cell_id_r10_present = false; - bool time_conn_fail_r10_present = false; - bool conn_fail_type_r10_present = false; - bool prev_pcell_id_r10_present = false; + bool time_conn_fail_r10_present = false; + bool conn_fail_type_r10_present = false; copy_ptr location_info_r10; copy_ptr failed_pcell_id_r10; copy_ptr reest_cell_id_r10; @@ -46020,20 +45583,13 @@ struct rlf_report_r9_s { conn_fail_type_r10_e_ conn_fail_type_r10; copy_ptr prev_pcell_id_r10; // group 1 - bool failed_pcell_id_v1090_present = false; copy_ptr failed_pcell_id_v1090; // group 2 - bool basic_fields_r11_present = false; - bool prev_utra_cell_id_r11_present = false; - bool sel_utra_cell_id_r11_present = false; copy_ptr basic_fields_r11; copy_ptr prev_utra_cell_id_r11; copy_ptr sel_utra_cell_id_r11; // group 3 - bool failed_pcell_id_v1250_present = false; bool meas_result_last_serv_cell_v1250_present = false; - bool last_serv_cell_rsrq_type_r12_present = false; - bool meas_result_list_eutra_v1250_present = false; copy_ptr failed_pcell_id_v1250; int8_t meas_result_last_serv_cell_v1250 = -30; copy_ptr last_serv_cell_rsrq_type_r12; @@ -46044,8 +45600,6 @@ struct rlf_report_r9_s { bool meas_result_last_serv_cell_v1360_present = false; int8_t meas_result_last_serv_cell_v1360 = -17; // group 6 - bool log_meas_result_list_bt_r15_present = false; - bool log_meas_result_list_wlan_r15_present = false; copy_ptr log_meas_result_list_bt_r15; copy_ptr log_meas_result_list_wlan_r15; @@ -54547,7 +54101,6 @@ struct ue_eutra_cap_add_xdd_mode_v1060_s { irat_params_utra_tdd_v1020_s inter_rat_params_utra_tdd_v1060; // ... // group 0 - bool otdoa_positioning_capabilities_r10_present = false; copy_ptr otdoa_positioning_capabilities_r10; // sequence methods @@ -54937,13 +54490,10 @@ struct as_cfg_s { dyn_octstring source_sib_type1_ext; copy_ptr source_other_cfg_r9; // group 1 - bool source_scell_cfg_list_r10_present = false; copy_ptr source_scell_cfg_list_r10; // group 2 - bool source_cfg_scg_r12_present = false; copy_ptr source_cfg_scg_r12; // group 3 - bool as_cfg_nr_r15_present = false; copy_ptr as_cfg_nr_r15; // sequence methods @@ -55160,9 +54710,8 @@ struct cell_to_add_mod_r12_s { meas_result_cell_to_add_r12_s_ meas_result_cell_to_add_r12; // ... // group 0 - bool s_cell_idx_r13_present = false; - bool meas_result_cell_to_add_v1310_present = false; - uint8_t s_cell_idx_r13 = 1; + bool s_cell_idx_r13_present = false; + uint8_t s_cell_idx_r13 = 1; copy_ptr meas_result_cell_to_add_v1310; // sequence methods @@ -55707,10 +55256,8 @@ struct rrm_cfg_s { ue_inactive_time_e_ ue_inactive_time; // ... // group 0 - bool candidate_cell_info_list_r10_present = false; copy_ptr candidate_cell_info_list_r10; // group 1 - bool candidate_cell_info_list_nr_r15_present = false; copy_ptr candidate_cell_info_list_nr_r15; // sequence methods @@ -55939,9 +55486,8 @@ struct meas_result_serv_cell_scg_r12_s { meas_result_scell_r12_s_ meas_result_scell_r12; // ... // group 0 - bool serv_cell_id_r13_present = false; - bool meas_result_scell_v1310_present = false; - uint8_t serv_cell_id_r13 = 0; + bool serv_cell_id_r13_present = false; + uint8_t serv_cell_id_r13 = 0; copy_ptr meas_result_scell_v1310; // sequence methods @@ -56258,7 +55804,6 @@ struct sl_precfg_comm_pool_r12_s { dyn_bitstring trpt_subset_r12; // ... // group 0 - bool prio_list_r13_present = false; copy_ptr prio_list_r13; // sequence methods @@ -56512,8 +56057,6 @@ struct sl_v2x_precfg_comm_pool_r14_s { sl_restrict_res_reserv_period_list_r14_l restrict_res_reserv_period_r14; // ... // group 0 - bool sl_min_t2_value_list_r15_present = false; - bool cbr_pssch_tx_cfg_list_v1530_present = false; copy_ptr sl_min_t2_value_list_r15; copy_ptr cbr_pssch_tx_cfg_list_v1530; @@ -56602,9 +56145,6 @@ struct sl_precfg_r12_s { sl_precfg_comm_pool_list4_r12_l precfg_comm_r12; // ... // group 0 - bool precfg_comm_v1310_present = false; - bool precfg_disc_r13_present = false; - bool precfg_relay_r13_present = false; copy_ptr precfg_comm_v1310; copy_ptr precfg_disc_r13; copy_ptr precfg_relay_r13; @@ -56643,7 +56183,6 @@ struct sl_v2x_precfg_freq_info_r14_s { uint16_t offset_dfn_r14 = 0; // ... // group 0 - bool v2x_freq_sel_cfg_list_r15_present = false; copy_ptr v2x_freq_sel_cfg_list_r15; // sequence methods @@ -56679,10 +56218,7 @@ struct sl_v2x_precfg_r14_s { sl_cbr_precfg_tx_cfg_list_r14_s cbr_precfg_list_r14; // ... // group 0 - bool v2x_packet_dupl_cfg_r15_present = false; - bool sync_freq_list_r15_present = false; - bool slss_tx_multi_freq_r15_present = false; - bool v2x_tx_profile_list_r15_present = false; + bool slss_tx_multi_freq_r15_present = false; copy_ptr v2x_packet_dupl_cfg_r15; copy_ptr sync_freq_list_r15; copy_ptr v2x_tx_profile_list_r15; diff --git a/lib/include/srslte/asn1/rrc_asn1_utils.h b/lib/include/srslte/asn1/rrc_asn1_utils.h index 566e65b8d..5c9a30aa4 100644 --- a/lib/include/srslte/asn1/rrc_asn1_utils.h +++ b/lib/include/srslte/asn1/rrc_asn1_utils.h @@ -34,6 +34,23 @@ struct plmn_id_s; struct s_tmsi_s; struct rlc_cfg_c; struct srb_to_add_mod_s; +struct sched_request_cfg_c; +struct mac_main_cfg_s; +struct rach_cfg_common_s; +struct time_align_timer_opts; +struct phys_cfg_ded_s; +struct prach_cfg_info_s; +struct pdsch_cfg_common_s; +struct pusch_cfg_common_s; +struct pucch_cfg_common_s; +struct srs_ul_cfg_common_c; +struct ul_pwr_ctrl_common_s; +struct scell_to_add_mod_r10_s; +struct mbms_notif_cfg_r9_s; +struct mbsfn_area_info_r9_s; +struct mbsfn_sf_cfg_s; +struct mcch_msg_s; +struct sib_type13_r9_s; } // namespace rrc } // namespace asn1 @@ -49,9 +66,41 @@ void to_asn1(asn1::rrc::plmn_id_s* asn1_type, const plmn_id_t& cfg); s_tmsi_t make_s_tmsi_t(const asn1::rrc::s_tmsi_s& asn1_type); void to_asn1(asn1::rrc::s_tmsi_s* asn1_type, const s_tmsi_t& cfg); +/*************************** + * RLC Config + **************************/ rlc_config_t make_rlc_config_t(const asn1::rrc::rlc_cfg_c& asn1_type); rlc_config_t make_rlc_config_t(const asn1::rrc::srb_to_add_mod_s& asn1_type); void to_asn1(asn1::rrc::rlc_cfg_c* asn1_type, const rlc_config_t& cfg); -} + +/*************************** + * MAC Config + **************************/ +void set_mac_cfg_t_sched_request_cfg(mac_cfg_t* cfg, const asn1::rrc::sched_request_cfg_c& asn1_type); +void set_mac_cfg_t_main_cfg(mac_cfg_t* cfg, const asn1::rrc::mac_main_cfg_s& asn1_type); +void set_mac_cfg_t_rach_cfg_common(mac_cfg_t* cfg, const asn1::rrc::rach_cfg_common_s& asn1_type); +void set_mac_cfg_t_time_alignment(mac_cfg_t* cfg, const asn1::rrc::time_align_timer_opts asn1_type); + +/*************************** + * PHY Config + **************************/ +void set_phy_cfg_t_dedicated_cfg(phy_cfg_t* cfg, const asn1::rrc::phys_cfg_ded_s& asn1_type); +void set_phy_cfg_t_common_prach(phy_cfg_t* cfg, const asn1::rrc::prach_cfg_info_s* asn1_type, uint32_t root_seq_idx); +void set_phy_cfg_t_common_pdsch(phy_cfg_t* cfg, const asn1::rrc::pdsch_cfg_common_s& asn1_type); +void set_phy_cfg_t_common_pusch(phy_cfg_t* cfg, const asn1::rrc::pusch_cfg_common_s& asn1_type); +void set_phy_cfg_t_common_pucch(phy_cfg_t* cfg, const asn1::rrc::pucch_cfg_common_s& asn1_type); +void set_phy_cfg_t_common_srs(phy_cfg_t* cfg, const asn1::rrc::srs_ul_cfg_common_c& asn1_type); +void set_phy_cfg_t_common_pwr_ctrl(phy_cfg_t* cfg, const asn1::rrc::ul_pwr_ctrl_common_s& asn1_type); +void set_phy_cfg_t_scell_config(phy_cfg_t* cfg, const asn1::rrc::scell_to_add_mod_r10_s& asn1_type); +void set_phy_cfg_t_enable_64qam(phy_cfg_t* cfg, const bool enabled); + +// mbms +mbms_notif_cfg_t make_mbms_notif_cfg(const asn1::rrc::mbms_notif_cfg_r9_s& asn1_type); +mbsfn_area_info_t make_mbsfn_area_info(const asn1::rrc::mbsfn_area_info_r9_s& asn1_type); +mbsfn_sf_cfg_t make_mbsfn_sf_cfg(const asn1::rrc::mbsfn_sf_cfg_s& sf_cfg); +mcch_msg_t make_mcch_msg(const asn1::rrc::mcch_msg_s& asn1_type); +sib13_t make_sib13(const asn1::rrc::sib_type13_r9_s& asn1_type); + +} // namespace srslte #endif // SRSLTE_RRC_ASN1_UTILS_H diff --git a/lib/include/srslte/common/bcd_helpers.h b/lib/include/srslte/common/bcd_helpers.h index 04dc6392f..d05216aa5 100644 --- a/lib/include/srslte/common/bcd_helpers.h +++ b/lib/include/srslte/common/bcd_helpers.h @@ -156,14 +156,12 @@ inline bool bytes_to_mnc(const uint8_t* bytes, uint16_t* mnc, uint8_t len) if (len != 3 && len != 2) { *mnc = 0; return false; - } - if (len == 3) { + } else if (len == 3) { *mnc = 0xF000; *mnc |= ((uint16_t)bytes[0]) << 8u; *mnc |= ((uint16_t)bytes[1]) << 4u; *mnc |= ((uint16_t)bytes[2]) << 0u; - } - if (len == 2) { + } else if (len == 2) { *mnc = 0xFF00; *mnc |= ((uint16_t)bytes[0]) << 4u; *mnc |= ((uint16_t)bytes[1]) << 0u; diff --git a/lib/include/srslte/common/buffer_pool.h b/lib/include/srslte/common/buffer_pool.h index 85d94f962..b3fe76bc7 100644 --- a/lib/include/srslte/common/buffer_pool.h +++ b/lib/include/srslte/common/buffer_pool.h @@ -242,6 +242,6 @@ allocate_unique_buffer(byte_buffer_pool& pool, const char* debug_name, bool bloc return std::move(unique_byte_buffer_t(pool.allocate(debug_name, blocking), byte_buffer_deleter(&pool))); } -} // namespace srsue +} // namespace srslte #endif // SRSLTE_BUFFER_POOL_H diff --git a/lib/include/srslte/common/int_helpers.h b/lib/include/srslte/common/int_helpers.h index 074e572c0..ea7e180ac 100644 --- a/lib/include/srslte/common/int_helpers.h +++ b/lib/include/srslte/common/int_helpers.h @@ -28,15 +28,12 @@ namespace srslte { * Safe conversions between byte buffers and integer types. * Note: these don't perform endian conversion - use e.g. htonl/ntohl if required *****************************************************************************/ -inline void uint8_to_uint32(uint8_t *buf, uint32_t *i) +inline void uint8_to_uint32(uint8_t* buf, uint32_t* i) { - *i = (uint32_t)buf[0] << 24 | - (uint32_t)buf[1] << 16 | - (uint32_t)buf[2] << 8 | - (uint32_t)buf[3]; + *i = (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16 | (uint32_t)buf[2] << 8 | (uint32_t)buf[3]; } -inline void uint32_to_uint8(uint32_t i, uint8_t *buf) +inline void uint32_to_uint8(uint32_t i, uint8_t* buf) { buf[0] = (i >> 24) & 0xFF; buf[1] = (i >> 16) & 0xFF; @@ -44,18 +41,28 @@ inline void uint32_to_uint8(uint32_t i, uint8_t *buf) buf[3] = i & 0xFF; } -inline void uint8_to_uint16(uint8_t *buf, uint16_t *i) +inline void uint8_to_uint16(uint8_t* buf, uint16_t* i) { - *i = (uint32_t)buf[0] << 8 | - (uint32_t)buf[1]; + *i = (uint32_t)buf[0] << 8 | (uint32_t)buf[1]; } -inline void uint16_to_uint8(uint16_t i, uint8_t *buf) +inline void uint16_to_uint8(uint16_t i, uint8_t* buf) { buf[0] = (i >> 8) & 0xFF; buf[1] = i & 0xFF; } -}; //namespace +inline void uint8_to_uint24(uint8_t* buf, uint32_t* i) +{ + *i = (uint32_t)buf[0] << 16 | (uint32_t)buf[1] << 8 | (uint32_t)buf[2]; +} + +inline void uint24_to_uint8(uint32_t i, uint8_t* buf) +{ + buf[0] = (i >> 16) & 0xFF; + buf[1] = (i >> 8) & 0xFF; + buf[2] = i & 0xFF; +} +} // namespace srslte #endif // SRSLTE_INT_HELPERS_H diff --git a/lib/include/srslte/common/interfaces_common.h b/lib/include/srslte/common/interfaces_common.h index 118ad0953..88d8177ac 100644 --- a/lib/include/srslte/common/interfaces_common.h +++ b/lib/include/srslte/common/interfaces_common.h @@ -67,22 +67,36 @@ public: uint32_t lcid; }; +const uint8_t PDCP_SN_LEN_5 = 5; +const uint8_t PDCP_SN_LEN_7 = 7; +const uint8_t PDCP_SN_LEN_12 = 12; +const uint8_t PDCP_SN_LEN_18 = 18; -class srslte_pdcp_config_t +typedef enum { PDCP_RB_IS_SRB, PDCP_RB_IS_DRB } pdcp_rb_type_t; + +class pdcp_config_t { public: - srslte_pdcp_config_t(uint8_t bearer_id_ = 0, bool is_control_ = false, bool is_data_ = false, uint8_t direction_ = SECURITY_DIRECTION_UPLINK) - :bearer_id(bearer_id_) - ,direction(direction_) - ,is_control(is_control_) - ,is_data(is_data_) - ,sn_len(12) {} - - uint32_t bearer_id; - uint8_t direction; - bool is_control; - bool is_data; - uint8_t sn_len; + pdcp_config_t(uint8_t bearer_id_, + pdcp_rb_type_t rb_type_, + security_direction_t tx_direction_, + security_direction_t rx_direction_, + uint8_t sn_len_) : + bearer_id(bearer_id_), + rb_type(rb_type_), + tx_direction(tx_direction_), + rx_direction(rx_direction_), + sn_len(sn_len_) + { + hdr_len_bytes = ceil((float)sn_len / 8); + } + + uint8_t bearer_id = 1; + pdcp_rb_type_t rb_type = PDCP_RB_IS_DRB; + security_direction_t tx_direction = SECURITY_DIRECTION_DOWNLINK; + security_direction_t rx_direction = SECURITY_DIRECTION_UPLINK; + uint8_t sn_len = PDCP_SN_LEN_12; + uint8_t hdr_len_bytes = 2; // TODO: Support the following configurations // bool do_rohc; diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index 5c5ba0794..f7d2ad8c5 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -103,6 +103,7 @@ typedef enum { LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0 = 0, LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA1, LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA2, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA3, LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_N_ITEMS, } LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM; static const char liblte_security_ciphering_algorithm_id_text[LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_N_ITEMS][20] = { @@ -111,6 +112,7 @@ typedef enum { LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_EIA0 = 0, LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA1, LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA2, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_128_EIA3, LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_N_ITEMS, } LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM; static const char liblte_security_integrity_algorithm_id_text[LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = { @@ -177,6 +179,8 @@ LIBLTE_ERROR_ENUM liblte_security_128_eia2( uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* msg, uint32 msg_len, uint8* mac); LIBLTE_ERROR_ENUM liblte_security_128_eia2( uint8* key, uint32 count, uint8 bearer, uint8 direction, LIBLTE_BIT_MSG_STRUCT* msg, uint8* mac); +LIBLTE_ERROR_ENUM liblte_security_128_eia3( + uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* msg, uint32 msg_len, uint8* mac); /********************************************************************* Name: liblte_security_encryption_eea1 @@ -224,6 +228,12 @@ LIBLTE_ERROR_ENUM liblte_security_encryption_eea2( LIBLTE_ERROR_ENUM liblte_security_decryption_eea2( uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* ct, uint32 ct_len, uint8* out); +LIBLTE_ERROR_ENUM liblte_security_encryption_eea3( + uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* msg, uint32 msg_len, uint8* out); + +LIBLTE_ERROR_ENUM liblte_security_decryption_eea3( + uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* msg, uint32 msg_len, uint8* out); + /********************************************************************* Name: liblte_security_milenage_f1 diff --git a/lib/include/srslte/common/log.h b/lib/include/srslte/common/log.h index 35147095b..0bb876446 100644 --- a/lib/include/srslte/common/log.h +++ b/lib/include/srslte/common/log.h @@ -65,9 +65,7 @@ public: tti = 0; level = LOG_LEVEL_NONE; hex_limit = 0; - show_layer_en = true; add_string_en = false; - level_text_short = true; } log(std::string service_name_) { @@ -75,9 +73,7 @@ public: tti = 0; level = LOG_LEVEL_NONE; hex_limit = 0; - show_layer_en = true; add_string_en = false; - level_text_short = true; } virtual ~log() {}; @@ -131,12 +127,6 @@ public: int get_hex_limit() { return hex_limit; } - void set_log_level_short(bool enable) { - level_text_short = enable; - } - void show_layer(bool enable) { - show_layer_en = enable; - } // Pure virtual methods for logging virtual void console(const char * message, ...) __attribute__ ((format (printf, 2, 3))) = 0; @@ -144,6 +134,7 @@ public: virtual void warning(const char * message, ...) __attribute__ ((format (printf, 2, 3))) = 0; virtual void info(const char * message, ...) __attribute__ ((format (printf, 2, 3))) = 0; virtual void debug(const char * message, ...) __attribute__ ((format (printf, 2, 3))) = 0; + virtual void debug_long(const char* message, ...) __attribute__((format(printf, 2, 3))) = 0; // Same with hex dump virtual void error_hex(const uint8_t *, int, const char *, ...) __attribute__((format (printf, 4, 5))) @@ -162,8 +153,6 @@ protected: int hex_limit; std::string service_name; - bool show_layer_en; - bool level_text_short; bool add_string_en; std::string add_string_val; }; diff --git a/lib/include/srslte/common/log_filter.h b/lib/include/srslte/common/log_filter.h index 2cb113cb8..ff86cae0f 100644 --- a/lib/include/srslte/common/log_filter.h +++ b/lib/include/srslte/common/log_filter.h @@ -58,6 +58,7 @@ public: void warning(const char * message, ...) __attribute__ ((format (printf, 2, 3))); void info(const char * message, ...) __attribute__ ((format (printf, 2, 3))); void debug(const char * message, ...) __attribute__ ((format (printf, 2, 3))); + void debug_long(const char* message, ...) __attribute__((format(printf, 2, 3))); void error_hex(const uint8_t *hex, int size, const char * message, ...) __attribute__((format (printf, 4, 5))); void warning_hex(const uint8_t *hex, int size, const char * message, ...) __attribute__((format (printf, 4, 5))); @@ -82,18 +83,24 @@ protected: logger *logger_h; bool do_tti; + static const int char_buff_size = logger::preallocated_log_str_size - 64 * 3; + time_itf *time_src; time_format_t time_format; logger_stdout def_logger_stdout; - void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, const char *msg); - void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, const char *msg, const uint8_t *hex, int size); - void all_log_line(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, char *msg); - std::string now_time(); + void all_log(srslte::LOG_LEVEL_ENUM level, + uint32_t tti, + const char* msg, + const uint8_t* hex = nullptr, + int size = 0, + bool long_msg = false); + void now_time(char* buffer, const uint32_t buffer_len); + void get_tti_str(const uint32_t tti_, char* buffer, const uint32_t buffer_len); std::string hex_string(const uint8_t *hex, int size); }; -} // namespace srsue +} // namespace srslte #endif // SRSLTE_LOG_FILTER_H diff --git a/lib/include/srslte/common/logger.h b/lib/include/srslte/common/logger.h index bafd05f17..0b5da301b 100644 --- a/lib/include/srslte/common/logger.h +++ b/lib/include/srslte/common/logger.h @@ -27,6 +27,8 @@ #ifndef SRSLTE_LOGGER_H #define SRSLTE_LOGGER_H +#include "buffer_pool.h" +#include #include #include @@ -35,7 +37,70 @@ namespace srslte { class logger { public: - virtual void log(std::string *msg) = 0; + const static uint32_t preallocated_log_str_size = 1024; + + logger() : pool(16 * 1024) {} + + class log_str + { + public: + log_str(const char* msg_ = nullptr, uint32_t size_ = 0) + { + size = size_ ? size_ : preallocated_log_str_size; + msg = new char[size]; + if (msg_) { + strncpy(msg, msg_, size); + } else { + msg[0] = '\0'; + } + } + log_str(const log_str&) = delete; + log_str& operator=(const log_str&) = delete; + ~log_str() { delete[] msg; } + void reset() { msg[0] = '\0'; } + char* str() { return msg; } + uint32_t get_buffer_size() { return size; } + + private: + uint32_t size; + char* msg; + }; + + typedef buffer_pool log_str_pool_t; + + class log_str_deleter + { + public: + explicit log_str_deleter(log_str_pool_t* pool_ = nullptr) : pool(pool_) {} + void operator()(log_str* buf) + { + if (buf) { + if (pool) { + buf->reset(); + pool->deallocate(buf); + } else { + delete buf; + } + } + } + + private: + log_str_pool_t* pool; + }; + typedef std::unique_ptr unique_log_str_t; + + void log_char(const char* msg) { log(std::move(unique_log_str_t(new log_str(msg), log_str_deleter()))); } + + virtual void log(unique_log_str_t msg) = 0; + + log_str_pool_t& get_pool() { return pool; } + unique_log_str_t allocate_unique_log_str() + { + return unique_log_str_t(pool.allocate(), logger::log_str_deleter(&pool)); + } + +private: + log_str_pool_t pool; }; } // namespace srslte diff --git a/lib/include/srslte/common/logger_file.h b/lib/include/srslte/common/logger_file.h index 17f08ef5e..ed4457659 100644 --- a/lib/include/srslte/common/logger_file.h +++ b/lib/include/srslte/common/logger_file.h @@ -47,9 +47,9 @@ public: logger_file(std::string file); ~logger_file(); void init(std::string file, int max_length = -1); + void stop(); // Implementation of log_out - void log(str_ptr msg); - void log(const char *msg); + void log(unique_log_str_t msg); private: void run_thread(); @@ -63,7 +63,8 @@ private: std::string filename; pthread_cond_t not_empty; pthread_mutex_t mutex; - std::deque buffer; + + std::deque buffer; }; } // namespace srslte diff --git a/lib/include/srslte/common/logger_stdout.h b/lib/include/srslte/common/logger_stdout.h index 7cdc9323b..04055eaf7 100644 --- a/lib/include/srslte/common/logger_stdout.h +++ b/lib/include/srslte/common/logger_stdout.h @@ -36,12 +36,7 @@ namespace srslte { class logger_stdout : public logger { public: - void log(std::string *msg) { - if (msg) { - fprintf(stdout, "%s", msg->c_str()); - delete msg; - } - } + void log(unique_log_str_t log_str) { fprintf(stdout, "%s", log_str->str()); } }; } // namespace srslte diff --git a/lib/include/srslte/common/mac_nr_pcap.h b/lib/include/srslte/common/mac_nr_pcap.h new file mode 100644 index 000000000..02babae63 --- /dev/null +++ b/lib/include/srslte/common/mac_nr_pcap.h @@ -0,0 +1,65 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_MAC_NR_PCAP_H +#define SRSLTE_MAC_NR_PCAP_H + +#include "srslte/common/pcap.h" +#include +#include + +namespace srslte { + +class mac_nr_pcap +{ +public: + mac_nr_pcap(); + ~mac_nr_pcap(); + void enable(const bool& enable_); + void open(const std::string& filename, const uint16_t& ue_id = 0); + void close(); + + void set_ue_id(const uint16_t& ue_id); + + void write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint8_t harqid, uint32_t tti); + void write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti); + void write_dl_ra_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti); + void write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti); + void write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti); + void write_dl_si_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti); + +private: + bool enable_write = false; + std::string filename; + FILE* pcap_file = nullptr; + uint32_t ue_id = 0; + void pack_and_write(uint8_t* pdu, + uint32_t pdu_len_bytes, + uint32_t tti, + uint16_t crnti_, + uint8_t harqid, + uint8_t direction, + uint8_t rnti_type); +}; + +} // namespace srslte + +#endif // SRSLTE_MAC_NR_PCAP_H diff --git a/lib/include/srslte/common/mac_nr_pdu.h b/lib/include/srslte/common/mac_nr_pdu.h new file mode 100644 index 000000000..f073f8bad --- /dev/null +++ b/lib/include/srslte/common/mac_nr_pdu.h @@ -0,0 +1,118 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_MAC_NR_PDU_H +#define SRSLTE_MAC_NR_PDU_H + +#include "srslte/common/common.h" +#include +#include +#include + +namespace srslte { + +class mac_nr_sch_pdu; + +class mac_nr_sch_subpdu +{ +public: + // 3GPP 38.321 v15.3.0 Combined Tables 6.2.1-1, 6.2.1-2 + typedef enum { + // Values for DL-SCH + DRX_CMD = 0b111100, + TA_CMD = 0b111101, + CON_RES_ID = 0b111110, + + // Values for UL-SCH + CRNTI = 0b111010, + SHORT_TRUNC_BSR = 0b111011, + LONG_TRUNC_BSR = 0b111100, + + SHORT_BSR = 0b111101, + LONG_BSR = 0b111110, + + // Common + CCCH = 0b000000, + PADDING = 0b111111, + } nr_lcid_sch_t; + + mac_nr_sch_subpdu(mac_nr_sch_pdu* parent_); + + nr_lcid_sch_t get_type(); + bool is_sdu(); + bool is_var_len_ce(); + + uint32_t read_subheader(const uint8_t* ptr); + uint32_t get_total_length(); + uint32_t get_sdu_length(); + uint32_t get_lcid(); + uint8_t* get_sdu(); + + void set_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_); + + void set_padding(const uint32_t len_); + + uint32_t write_subpdu(const uint8_t* start_); + +private: + uint32_t sizeof_ce(uint32_t lcid, bool is_ul); + + // protected: + uint32_t lcid = 0; + int header_length = 0; + int sdu_length = 0; + bool F_bit = false; + uint8_t* sdu = nullptr; + + mac_nr_sch_pdu* parent = nullptr; +}; + +class mac_nr_sch_pdu +{ +public: + mac_nr_sch_pdu(bool ulsch_ = false) : ulsch(ulsch_) {} + + void pack(); + void unpack(const uint8_t* payload, const uint32_t& len); + uint32_t get_num_subpdus(); + const mac_nr_sch_subpdu& get_subpdu(const uint32_t& index); + bool is_ulsch(); + + void init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool is_ulsch_ = false); + + uint32_t add_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_); + + uint32_t get_remaing_len(); + +private: + uint32_t size_header_sdu(const uint32_t nbytes); + + bool ulsch = false; + std::vector subpdus; + + byte_buffer_t* buffer = nullptr; + uint32_t pdu_len = 0; + uint32_t remaining_len = 0; +}; + +} // namespace srslte + +#endif // SRSLTE_MAC_NR_PDU_H diff --git a/lib/include/srslte/common/multiqueue.h b/lib/include/srslte/common/multiqueue.h new file mode 100644 index 000000000..32e26beb9 --- /dev/null +++ b/lib/include/srslte/common/multiqueue.h @@ -0,0 +1,230 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +/****************************************************************************** + * File: multiqueue.h + * Description: General-purpose non-blocking multiqueue. It behaves as a list + * of bounded/unbounded queues. + *****************************************************************************/ + +#ifndef SRSLTE_MULTIQUEUE_H +#define SRSLTE_MULTIQUEUE_H + +#include +#include +#include +#include +#include + +namespace srslte { + +template +class multiqueue_handler +{ + // NOTE: needed to create a queue wrapper to make its move ctor noexcept. + // otherwise we couldnt use the resize method of std::vector> if myobj is move-only + class queue_wrapper : private std::queue + { + public: + queue_wrapper() = default; + queue_wrapper(queue_wrapper&& other) noexcept : std::queue(std::move(other)) {} + using std::queue::push; + using std::queue::pop; + using std::queue::size; + using std::queue::empty; + using std::queue::front; + + std::condition_variable cv_full; + bool active = true; + }; + +public: + explicit multiqueue_handler(uint32_t capacity_ = std::numeric_limits::max()) : capacity(capacity_) {} + ~multiqueue_handler() { reset(); } + + void reset() + { + std::unique_lock lock(mutex); + running = false; + while (nof_threads_waiting > 0) { + uint32_t size = queues.size(); + lock.unlock(); + cv_empty.notify_one(); + for (uint32_t i = 0; i < size; ++i) { + queues[i].cv_full.notify_all(); + } + lock.lock(); + // wait for all threads to unblock + cv_exit.wait(lock); + } + queues.clear(); + } + + int add_queue() + { + uint32_t qidx = 0; + std::lock_guard lock(mutex); + if (not running) { + return -1; + } + for (; qidx < queues.size() and queues[qidx].active; ++qidx) + ; + if (qidx == queues.size()) { + // create new queue + queues.emplace_back(); + } else { + queues[qidx].active = true; + } + return (int)qidx; + } + + int nof_queues() + { + std::lock_guard lock(mutex); + uint32_t count = 0; + for (uint32_t i = 0; i < queues.size(); ++i) { + count += queues[i].active ? 1 : 0; + } + return count; + } + + template + void push(int q_idx, FwdRef&& value) + { + { + std::unique_lock lock(mutex); + while (is_queue_active_(q_idx) and queues[q_idx].size() >= capacity) { + nof_threads_waiting++; + queues[q_idx].cv_full.wait(lock); + nof_threads_waiting--; + } + if (not is_queue_active_(q_idx)) { + cv_exit.notify_one(); + return; + } + queues[q_idx].push(std::forward(value)); + } + cv_empty.notify_one(); + } + + bool try_push(int q_idx, const myobj& value) + { + { + std::lock_guard lock(mutex); + if (not is_queue_active_(q_idx) or queues[q_idx].size() >= capacity) { + return false; + } + queues[q_idx].push(value); + } + cv_empty.notify_one(); + return true; + } + + std::pair try_push(int q_idx, myobj&& value) + { + { + std::lock_guard lck(mutex); + if (not is_queue_active_(q_idx) or queues[q_idx].size() >= capacity) { + return {false, std::move(value)}; + } + queues[q_idx].push(std::move(value)); + } + cv_empty.notify_one(); + return {true, std::move(value)}; + } + + int wait_pop(myobj* value) + { + std::unique_lock lock(mutex); + while (running) { + // Round-robin for all queues + for (const queue_wrapper& q : queues) { + spin_idx = (spin_idx + 1) % queues.size(); + if (is_queue_active_(spin_idx) and not queues[spin_idx].empty()) { + if (value) { + *value = std::move(queues[spin_idx].front()); + } + queues[spin_idx].pop(); + if (nof_threads_waiting > 0) { + lock.unlock(); + queues[spin_idx].cv_full.notify_one(); + } + return spin_idx; + } + } + nof_threads_waiting++; + cv_empty.wait(lock); + nof_threads_waiting--; + } + cv_exit.notify_one(); + return -1; + } + + bool empty(int qidx) + { + std::lock_guard lck(mutex); + return queues[qidx].empty(); + } + + size_t size(int qidx) + { + std::lock_guard lck(mutex); + return queues[qidx].size(); + } + + const myobj& front(int qidx) + { + std::lock_guard lck(mutex); + return queues[qidx].front(); + } + + void erase_queue(int qidx) + { + std::lock_guard lck(mutex); + if (is_queue_active_(qidx)) { + queues[qidx].active = false; + while (not queues[qidx].empty()) { + queues[qidx].pop(); + } + } + } + + bool is_queue_active(int qidx) + { + std::lock_guard lck(mutex); + return is_queue_active_(qidx); + } + +private: + bool is_queue_active_(int qidx) const { return running and queues[qidx].active; } + + std::mutex mutex; + std::condition_variable cv_empty, cv_exit; + uint32_t spin_idx = 0; + bool running = true; + std::vector queues; + uint32_t capacity = 0; + uint32_t nof_threads_waiting = 0; +}; + +} // namespace srslte + +#endif // SRSLTE_MULTIQUEUE_H diff --git a/lib/include/srslte/common/netsource_handler.h b/lib/include/srslte/common/netsource_handler.h new file mode 100644 index 000000000..ba6a383f4 --- /dev/null +++ b/lib/include/srslte/common/netsource_handler.h @@ -0,0 +1,77 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +/*! \brief Base class for implementing socket handlers using + * the netsource object. + * + */ + +#ifndef SRSLTE_NETSOURE_HANDLER_H +#define SRSLTE_NETSOURE_HANDLER_H + +#include "srslte/common/log.h" +#include "srslte/common/threads.h" +#include "srslte/phy/io/netsource.h" +#include +#include +#include + +class netsource_handler : public thread +{ +public: + netsource_handler(const std::string name_) : thread(name_) { rx_buf = unique_byte_array_t(new byte_array_t); } + + ~netsource_handler(){}; + + void stop() + { + run_enable = false; + int cnt = 0; + while (running && cnt < 100) { + usleep(10000); + cnt++; + } + if (running) { + thread_cancel(); + } + wait_thread_finish(); + } + + virtual void run_thread() = 0; + + bool run_enable = true; + bool running = false; + bool initialized = false; + + std::string net_ip = "0.0.0.0"; + uint32_t net_port = 0; + + const static uint32_t RX_BUF_SIZE = 1024 * 1024; + typedef std::array byte_array_t; + typedef std::unique_ptr unique_byte_array_t; + unique_byte_array_t rx_buf; + + srslte_netsource_t net_source; + + srslte::log* log = nullptr; +}; + +#endif // SRSLTE_NETSOURE_HANDLER_H diff --git a/lib/include/srslte/common/pcap.h b/lib/include/srslte/common/pcap.h index 0395a1e8c..03c721f46 100644 --- a/lib/include/srslte/common/pcap.h +++ b/lib/include/srslte/common/pcap.h @@ -29,7 +29,7 @@ #define MAC_LTE_DLT 147 #define NAS_LTE_DLT 148 -#define RLC_LTE_DLT 149 // UDP needs to be selected as protocol +#define UDP_DLT 149 // UDP needs to be selected as protocol #define S1AP_LTE_DLT 150 /* This structure gets written to the start of the file */ @@ -102,6 +102,25 @@ typedef struct NAS_Context_Info_s { // No Context yet } NAS_Context_Info_t; +#define MAC_NR_START_STRING "mac-nr" +#define MAC_NR_PHR_TYPE2_OTHERCELL_TAG 0x05 +#define MAC_NR_HARQID 0x06 + +/* Context information for every MAC NR PDU that will be logged */ +typedef struct { + uint8_t radioType; + uint8_t direction; + uint8_t rntiType; + uint16_t rnti; + uint16_t ueid; + uint8_t harqid; + + uint8_t phr_type2_othercell; + + uint16_t system_frame_number; + uint8_t sub_frame_number; + uint16_t length; +} mac_nr_context_info_t; /* RLC-LTE disector */ @@ -437,4 +456,93 @@ inline int LTE_PCAP_S1AP_WritePDU(FILE *fd, S1AP_Context_Info_t *context, return 1; } +/************************************************************************** + * API functions for writing MAC-NR PCAP files * + **************************************************************************/ + +/* Write an individual NR MAC PDU (PCAP packet header + UDP header + nr-mac-context + mac-pdu) */ +inline int NR_PCAP_MAC_WritePDU(FILE* fd, mac_nr_context_info_t* context, const unsigned char* PDU, unsigned int length) +{ + char context_header[256] = {}; + int offset = 0; + + /* Can't write if file wasn't successfully opened */ + if (fd == NULL) { + printf("Error: Can't write to empty file handle\n"); + return 0; + } + + // Add dummy UDP header, start with src and dest port + context_header[offset++] = 0xde; + context_header[offset++] = 0xad; + context_header[offset++] = 0xbe; + context_header[offset++] = 0xef; + // length + uint16_t tmp16 = htons(length + 31); + memcpy(context_header + offset, &tmp16, 2); + offset += 2; + // dummy CRC + context_header[offset++] = 0xde; + context_header[offset++] = 0xad; + + // Start magic string + memcpy(&context_header[offset], MAC_NR_START_STRING, strlen(MAC_NR_START_STRING)); + offset += strlen(MAC_NR_START_STRING); + + /*****************************************************************/ + /* Context information (same as written by UDP heuristic clients */ + context_header[offset++] = context->radioType; + context_header[offset++] = context->direction; + context_header[offset++] = context->rntiType; + + /* RNTI */ + context_header[offset++] = MAC_LTE_RNTI_TAG; + tmp16 = htons(context->rnti); + memcpy(context_header + offset, &tmp16, 2); + offset += 2; + + /* UEId */ + context_header[offset++] = MAC_LTE_UEID_TAG; + tmp16 = htons(context->ueid); + memcpy(context_header + offset, &tmp16, 2); + offset += 2; + + /* HARQID */ + context_header[offset++] = MAC_NR_HARQID; + context_header[offset++] = context->harqid; + + /* PHR Type2 other cell */ + context_header[offset++] = MAC_NR_PHR_TYPE2_OTHERCELL_TAG; + context_header[offset++] = context->phr_type2_othercell; + + /* Subframe Number and System Frame Number */ + /* SFN is stored in 12 MSB and SF in 4 LSB */ + context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG; + tmp16 = (context->system_frame_number << 4) | context->sub_frame_number; + tmp16 = htons(tmp16); + memcpy(context_header + offset, &tmp16, 2); + offset += 2; + + /* Data tag immediately preceding PDU */ + context_header[offset++] = MAC_LTE_PAYLOAD_TAG; + + /****************************************************************/ + /* PCAP Header */ + struct timeval t; + gettimeofday(&t, NULL); + pcaprec_hdr_t packet_header; + packet_header.ts_sec = t.tv_sec; + packet_header.ts_usec = t.tv_usec; + packet_header.incl_len = offset + length; + packet_header.orig_len = offset + length; + + /***************************************************************/ + /* Now write everything to the file */ + fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd); + fwrite(context_header, 1, offset, fd); + fwrite(PDU, 1, length, fd); + + return 1; +} + #endif // SRSLTE_PCAP_H diff --git a/lib/include/srslte/common/pdu.h b/lib/include/srslte/common/pdu.h index 2a66d696a..2562a5f7f 100644 --- a/lib/include/srslte/common/pdu.h +++ b/lib/include/srslte/common/pdu.h @@ -136,7 +136,16 @@ public: ret = subheaders[nof_subheaders].read_subheader(&ptr); nof_subheaders++; } - } while (ret && (nof_subheaders + 1) < (int)max_subheaders); + + if (ret && (ptr - init_ptr) >= pdu_len) { + // stop processing last subheader indicates another one but all bytes are consume + nof_subheaders = 0; + INFO("Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)\n", pdu_len); + if (log) { + log->info_hex(init_ptr, pdu_len, "Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)\n", pdu_len); + } + } + } while (ret && (nof_subheaders + 1) < (int)max_subheaders && pdu_len > (ptr - init_ptr)); for (int i = 0; i < nof_subheaders; i++) { subheaders[i].read_payload(&ptr); diff --git a/lib/include/srslte/common/rlc_pcap.h b/lib/include/srslte/common/rlc_pcap.h index 6166a1f66..dffa01b50 100644 --- a/lib/include/srslte/common/rlc_pcap.h +++ b/lib/include/srslte/common/rlc_pcap.h @@ -55,6 +55,6 @@ private: uint16_t channel_id); }; -} // namespace srsue +} // namespace srslte #endif // RLCPCAP_H diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index 69a06e7b1..37c7ac24c 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -29,36 +29,38 @@ #include "srslte/common/common.h" - -#define SECURITY_DIRECTION_UPLINK 0 -#define SECURITY_DIRECTION_DOWNLINK 1 - namespace srslte { -typedef enum{ - CIPHERING_ALGORITHM_ID_EEA0 = 0, - CIPHERING_ALGORITHM_ID_128_EEA1, - CIPHERING_ALGORITHM_ID_128_EEA2, - CIPHERING_ALGORITHM_ID_N_ITEMS, -}CIPHERING_ALGORITHM_ID_ENUM; -static const char ciphering_algorithm_id_text[CIPHERING_ALGORITHM_ID_N_ITEMS][20] = {"EEA0", - "128-EEA1", - "128-EEA2"}; -typedef enum{ - INTEGRITY_ALGORITHM_ID_EIA0 = 0, - INTEGRITY_ALGORITHM_ID_128_EIA1, - INTEGRITY_ALGORITHM_ID_128_EIA2, - INTEGRITY_ALGORITHM_ID_N_ITEMS, -}INTEGRITY_ALGORITHM_ID_ENUM; -static const char integrity_algorithm_id_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"EIA0", - "128-EIA1", - "128-EIA2"}; - +typedef enum { + CIPHERING_ALGORITHM_ID_EEA0 = 0, + CIPHERING_ALGORITHM_ID_128_EEA1, + CIPHERING_ALGORITHM_ID_128_EEA2, + CIPHERING_ALGORITHM_ID_128_EEA3, + CIPHERING_ALGORITHM_ID_N_ITEMS, +} CIPHERING_ALGORITHM_ID_ENUM; +static const char ciphering_algorithm_id_text[CIPHERING_ALGORITHM_ID_N_ITEMS][20] = { + "EEA0", "128-EEA1", "128-EEA2", "128-EEA3"}; + +typedef enum { + INTEGRITY_ALGORITHM_ID_EIA0 = 0, + INTEGRITY_ALGORITHM_ID_128_EIA1, + INTEGRITY_ALGORITHM_ID_128_EIA2, + INTEGRITY_ALGORITHM_ID_128_EIA3, + INTEGRITY_ALGORITHM_ID_N_ITEMS, +} INTEGRITY_ALGORITHM_ID_ENUM; +static const char integrity_algorithm_id_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = { + "EIA0", "128-EIA1", "128-EIA2", "128-EIA3"}; + +typedef enum { + SECURITY_DIRECTION_UPLINK = 0, + SECURITY_DIRECTION_DOWNLINK = 1, + SECURITY_DIRECTION_N_ITEMS, +} security_direction_t; +static const char security_direction_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"Uplink", "Downlink"}; /****************************************************************************** * Key Generation *****************************************************************************/ - uint8_t security_generate_k_asme( uint8_t *ck, uint8_t *ik, uint8_t *ak, @@ -101,83 +103,45 @@ uint8_t security_generate_k_up( uint8_t *k_enb, /****************************************************************************** * Integrity Protection *****************************************************************************/ +uint8_t security_128_eia1( + uint8_t* key, uint32_t count, uint32_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac); -uint8_t security_128_eia1( uint8_t *key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t *msg, - uint32_t msg_len, - uint8_t *mac); +uint8_t security_128_eia2( + uint8_t* key, uint32_t count, uint32_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac); -uint8_t security_128_eia2( uint8_t *key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t *msg, - uint32_t msg_len, - uint8_t *mac); - -uint8_t security_md5(const uint8_t *input, - size_t len, - uint8_t *output); +uint8_t security_128_eia3( + uint8_t* key, uint32_t count, uint32_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac); +uint8_t security_md5(const uint8_t* input, size_t len, uint8_t* output); /****************************************************************************** * Encryption / Decryption *****************************************************************************/ +uint8_t security_128_eea1( + uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out); + +uint8_t security_128_eea2( + uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out); -uint8_t security_128_eea1( uint8_t *key, - uint32_t count, - uint8_t bearer, - uint8_t direction, - uint8_t *msg, - uint32_t msg_len, - uint8_t *msg_out); - -uint8_t security_128_eea2(uint8_t *key, - uint32_t count, - uint8_t bearer, - uint8_t direction, - uint8_t *msg, - uint32_t msg_len, - uint8_t *msg_out); +uint8_t security_128_eea3( + uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out); /****************************************************************************** * Authentication *****************************************************************************/ -uint8_t compute_opc( uint8_t *k, - uint8_t *op, - uint8_t *opc); - -uint8_t security_milenage_f1( uint8_t *k, - uint8_t *op, - uint8_t *rand, - uint8_t *sqn, - uint8_t *amf, - uint8_t *mac_a); - -uint8_t security_milenage_f1_star( uint8_t *k, - uint8_t *op, - uint8_t *rand, - uint8_t *sqn, - uint8_t *amf, - uint8_t *mac_s); - -uint8_t security_milenage_f2345( uint8_t *k, - uint8_t *op, - uint8_t *rand, - uint8_t *res, - uint8_t *ck, - uint8_t *ik, - uint8_t *ak); +uint8_t compute_opc(uint8_t* k, uint8_t* op, uint8_t* opc); + +uint8_t security_milenage_f1(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* sqn, uint8_t* amf, uint8_t* mac_a); + +uint8_t security_milenage_f1_star(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* sqn, uint8_t* amf, uint8_t* mac_s); + +uint8_t +security_milenage_f2345(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* res, uint8_t* ck, uint8_t* ik, uint8_t* ak); uint8_t security_milenage_f5_star( uint8_t *k, uint8_t *op, uint8_t *rand, uint8_t *ak); - } // namespace srslte - #endif // SRSLTE_SECURITY_H diff --git a/lib/include/srslte/common/stack_procedure.h b/lib/include/srslte/common/stack_procedure.h new file mode 100644 index 000000000..2fda0e7dc --- /dev/null +++ b/lib/include/srslte/common/stack_procedure.h @@ -0,0 +1,317 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include + +#ifndef SRSLTE_RESUMABLE_PROCEDURES_H +#define SRSLTE_RESUMABLE_PROCEDURES_H + +namespace srslte { + +enum class proc_state_t { on_going, success, error, inactive }; +enum class proc_outcome_t { repeat, yield, success, error }; + +/************************************************************************************** + * class: proc_impl_t + * Provides an polymorphic interface for resumable procedures. This base can then be used + * by a task dispatch queue via the method "run()". + * Every procedure starts in inactive state, and finishes with success or error. + * With methods: + * - run() - executes a procedure, returning true if the procedure is still running + * or false, if it has completed + * - step() - method overriden by child class that will be called by run(). step() + * executes a procedure "action" based on its current internal state, + * and return a proc_outcome_t variable with possible values: + * - yield - the procedure performed the action but hasn't completed yet. + * - repeat - the same as yield, but explicitly asking that run() should + * recall step() again (probably the procedure state has changed) + * - error - the procedure has finished unsuccessfully + * - success - the procedure has completed successfully + * - stop() - called automatically when a procedure has finished. Useful for actions + * upon procedure completion, like sending back a response. + * - set_proc_state() / is_#() - setter and getters for current procedure state + ************************************************************************************/ +class proc_impl_t +{ +public: + proc_impl_t() : proc_state(proc_state_t::inactive) {} + virtual ~proc_impl_t() = default; + virtual proc_outcome_t step() = 0; + virtual void stop() {} // may be overloaded + + bool run() + { + proc_outcome_t outcome = proc_outcome_t::repeat; + while (is_running() and outcome == proc_outcome_t::repeat) { + outcome = step(); + if (outcome == proc_outcome_t::error) { + set_proc_state(proc_state_t::error); + } else if (outcome == proc_outcome_t::success) { + set_proc_state(proc_state_t::success); + } + } + return is_running(); + } + + void set_proc_state(proc_state_t new_state) + { + proc_state = new_state; + if (proc_state == proc_state_t::error or proc_state == proc_state_t::success) { + stop(); + } + } + bool is_error() const { return proc_state == proc_state_t::error; } + bool is_success() const { return proc_state == proc_state_t::success; } + bool is_running() const { return proc_state == proc_state_t::on_going; } + bool is_complete() const { return is_success() or is_error(); } + bool is_active() const { return proc_state != proc_state_t::inactive; } + +private: + proc_state_t proc_state; +}; + +/************************************************************************************** + * class: proc_t + * Handles the lifetime, of a procedure T that derives from proc_impl_t, including + * its alloc, initialization, and reset back to initial state once the procedure has been + * completed and the user has extracted its results. + * Can only be re-launched when a procedure T becomes inactive. + * It uses a unique_ptr to allow the use of procedures that are forward declared. + * It provides the following methods: + * - run() - calls proc_impl_t::run(). See above. + * - launch() - initializes the procedure T by calling T::init(...). Handles the case + * of failed initialization, and forbids the initialization of procedures + * that are already active. + * - pop() - extracts the result of the procedure if it has finished, and sets + * proc_t back to inactive + * - trigger_event(Event) - used for handling external events. The procedure T will + * have to define a method "trigger_event(Event)" as well, + * specifying how each event type should be handled. + ************************************************************************************/ +template +class proc_t +{ +public: + explicit proc_t() : proc_impl_ptr(new T()) {} + T* get() { return proc_impl_ptr.get(); } + bool is_active() const { return proc_impl_ptr->is_active(); } + bool is_complete() const { return proc_impl_ptr->is_complete(); } + T* release() { return proc_impl_ptr.release(); } + bool run() { return proc_impl_ptr->run(); } + void clear() + { + // Destructs the current object, and calls default ctor (which sets proc back to inactive and ready for another run) + proc_impl_ptr->~T(); + new (proc_impl_ptr.get()) T(); + } + + template + void trigger_event(Event&& e) + { + if (proc_impl_ptr->is_running()) { + proc_outcome_t outcome = proc_impl_ptr->trigger_event(std::forward(e)); + if (outcome == proc_outcome_t::error) { + proc_impl_ptr->set_proc_state(proc_state_t::error); + } else if (outcome == proc_outcome_t::success) { + proc_impl_ptr->set_proc_state(proc_state_t::success); + } + } + } + + T pop() + { + if (not proc_impl_ptr->is_complete()) { + return T(); + } + T ret(std::move(*proc_impl_ptr)); + clear(); + return ret; + } + + template + bool launch(Args&&... args) + { + if (is_active()) { + // if already active + return false; + } + proc_impl_ptr->set_proc_state(proc_state_t::on_going); + proc_outcome_t init_ret = proc_impl_ptr->init(std::forward(args)...); + switch (init_ret) { + case proc_outcome_t::error: + proc_impl_ptr->set_proc_state(proc_state_t::error); // call stop as an error + clear(); + return false; + case proc_outcome_t::success: + proc_impl_ptr->set_proc_state(proc_state_t::success); + break; + case proc_outcome_t::repeat: + run(); // call run right away + break; + case proc_outcome_t::yield: + break; + } + return true; + } + +private: + std::unique_ptr proc_impl_ptr; +}; + +/************************************************************************************** + * class: func_proc_t + * A proc_impl_t used to store lambda functions and other function pointers as a step() + * method, avoiding this way, always having to create a new class per procedure. + ************************************************************************************/ +class func_proc_t : public proc_impl_t +{ +public: + proc_outcome_t init(std::function step_func_) + { + step_func = std::move(step_func_); + return proc_outcome_t::yield; + } + + proc_outcome_t step() final { return step_func(); } + +private: + std::function step_func; +}; + +/************************************************************************************** + * class: func_proc_t + * A helper proc_impl_t whose step()/stop() are no op, but has a trigger_event() that + * signals that the method has finished and store a result of type OutcomeType. + ************************************************************************************/ +template +class query_proc_t : public proc_impl_t +{ +public: + proc_outcome_t init() { return proc_outcome_t::yield; } + proc_outcome_t step() final { return proc_outcome_t::yield; } + + proc_outcome_t trigger_event(const OutcomeType& outcome_) + { + outcome = outcome_; + return proc_outcome_t::success; + } + + const OutcomeType& result() const { return outcome; } + +private: + OutcomeType outcome; +}; + +/************************************************************************************** + * class: callback_list_t + * Stores procedures that derive from proc_impl_t. Its run() method calls sequentially + * all the stored procedures run() method, and removes the procedures if they have + * completed. + * There are different ways to add a procedure to the list: + * - add_proc(...) - adds a proc_t, and once the procedure has completed, takes it + * out of the container without resetting it back to its initial state + * or deleting. This is useful, if the user wants to extract the + * procedure result via proc_t::pop() + * - consume_proc(...) - receives a proc_t as a rvalue, and calls the proc_t + * destructor once the procedure has ended. Useful, for procedures + * for which the user is not interested in the result, or reusing + * - defer_proc(...) - same as add_proc(...), but once the procedure has finished, it + * automatically sets the procedure back to its initial state. + * Useful if the user is not interested in handling the result + * - defer_task(...) - same as consume_proc(...) but takes a function pointer that + * specifies a proc_impl_t step() function + ************************************************************************************/ +class callback_list_t +{ +public: + typedef std::function proc_deleter_t; + typedef std::unique_ptr callback_obj_t; + template + struct recycle_deleter_t { + void operator()(proc_impl_t* p) + { + if (p != nullptr) { + T* Tp = static_cast(p); + Tp->~T(); + new (Tp) T(); + } + } + }; + + template + void add_proc(proc_t& proc) + { + if (proc.is_complete()) { + return; + } + callback_obj_t ptr(proc.get(), [](proc_impl_t* p) { /* do nothing */ }); + callbacks.push_back(std::move(ptr)); + } + + template + void consume_proc(proc_t&& proc) + { + if (proc.is_complete()) { + return; + } + callback_obj_t ptr(proc.release(), std::default_delete()); + callbacks.push_back(std::move(ptr)); + } + + template + void defer_proc(proc_t& proc) + { + if (proc.is_complete()) { + proc.pop(); + return; + } + callback_obj_t ptr(proc.get(), recycle_deleter_t()); + callbacks.push_back(std::move(ptr)); + } + + bool defer_task(std::function step_func) + { + proc_t proc; + if (not proc.launch(std::move(step_func))) { + return false; + } + consume_proc(std::move(proc)); + return true; + } + + void run() + { + // Calls run for all callbacks. Remove the ones that have finished. The proc dtor is called. + callbacks.remove_if([](callback_obj_t& elem) { return not elem->run(); }); + } + + size_t size() const { return callbacks.size(); } + +private: + std::list callbacks; +}; + +} // namespace srslte + +#endif // SRSLTE_RESUMABLE_PROCEDURES_H diff --git a/lib/include/srslte/common/thread_pool.h b/lib/include/srslte/common/thread_pool.h index b439918f0..d4177e4c9 100644 --- a/lib/include/srslte/common/thread_pool.h +++ b/lib/include/srslte/common/thread_pool.h @@ -29,10 +29,15 @@ #ifndef SRSLTE_THREAD_POOL_H #define SRSLTE_THREAD_POOL_H +#include +#include +#include +#include +#include +#include #include #include #include -#include #include "srslte/common/threads.h" @@ -94,8 +99,50 @@ private: std::vector status; std::vector cvar; std::vector mutex; - std::stack available_workers; + std::stack available_workers; }; -} - + +class task_thread_pool +{ + using task_t = std::function; + +public: + explicit task_thread_pool(uint32_t nof_workers); + ~task_thread_pool(); + void start(int32_t prio = -1, uint32_t mask = 255); + void stop(); + + void push_task(const task_t& task); + void push_task(task_t&& task); + uint32_t nof_pending_tasks(); + +private: + class worker_t : public thread + { + public: + explicit worker_t(task_thread_pool* parent_, uint32_t id); + void stop(); + void setup(int32_t prio, uint32_t mask); + bool is_running() const { return running; } + uint32_t id() const { return id_; } + + void run_thread() override; + + private: + bool wait_task(task_t* task); + + task_thread_pool* parent = nullptr; + uint32_t id_ = 0; + bool running = false; + }; + + std::queue pending_tasks; + std::vector workers; + std::mutex queue_mutex; + std::condition_variable cv_empty; + bool running; +}; + +} // namespace srslte + #endif // SRSLTE_THREAD_POOL_H diff --git a/lib/include/srslte/common/threads.h b/lib/include/srslte/common/threads.h index 7313ed1d1..e47e9c070 100644 --- a/lib/include/srslte/common/threads.h +++ b/lib/include/srslte/common/threads.h @@ -50,9 +50,11 @@ class thread { public: thread(const std::string& name_) : _thread(0), name(name_) {} - bool start(int prio = -1) { - return threads_new_rt_prio(&_thread, thread_function_entry, this, prio); - } + thread(const thread&) = delete; + thread(thread&&) noexcept = default; + thread& operator=(const thread&) = delete; + thread& operator=(thread&&) noexcept = default; + bool start(int prio = -1) { return threads_new_rt_prio(&_thread, thread_function_entry, this, prio); } bool start_cpu(int prio, int cpu) { return threads_new_rt_cpu(&_thread, thread_function_entry, this, cpu, prio); } diff --git a/lib/include/srslte/common/timers.h b/lib/include/srslte/common/timers.h index f2029acd1..8b557a34a 100644 --- a/lib/include/srslte/common/timers.h +++ b/lib/include/srslte/common/timers.h @@ -92,20 +92,21 @@ public: private: timer_callback *callback; uint32_t timeout; - uint32_t counter; - bool running; + uint32_t counter; + bool running; }; - - timers(uint32_t nof_timers_) : timer_list(nof_timers_),used_timers(nof_timers_) { - nof_timers = nof_timers_; - next_timer = 0; + + timers(uint32_t nof_timers_) : timer_list(nof_timers_), used_timers(nof_timers_) + { + nof_timers = nof_timers_; + next_timer = 0; nof_used_timers = 0; - for (uint32_t i=0;istep(); @@ -169,5 +170,5 @@ private: }; } // namespace srslte - + #endif // SRSLTE_TIMERS_H diff --git a/lib/include/srslte/common/tti_sync.h b/lib/include/srslte/common/tti_sync.h index b73acb342..1f91dcf75 100644 --- a/lib/include/srslte/common/tti_sync.h +++ b/lib/include/srslte/common/tti_sync.h @@ -68,8 +68,8 @@ class tti_sync uint32_t modulus; uint32_t producer_cntr; uint32_t consumer_cntr; -}; +}; -} // namespace srsue +} // namespace srslte #endif // SRSLTE_TTI_SYNC_H diff --git a/lib/include/srslte/common/zuc.h b/lib/include/srslte/common/zuc.h new file mode 100644 index 000000000..7385ea601 --- /dev/null +++ b/lib/include/srslte/common/zuc.h @@ -0,0 +1,48 @@ +/*--------------------------------------------------------- + + zuc.h + Adapted from ETSI/SAGE specifications: + "Specification of the 3GPP Confidentiality + and Integrity Algorithms 128-EEA3 & 128-EIA3. + Document 2: ZUC Specification" + +---------------------------------------------------------*/ + +#ifndef SRSLTE_ZUC_H +#define SRSLTE_ZUC_H + +typedef unsigned char u8; +typedef unsigned int u32; + +/* the state registers of LFSR */ +typedef struct { + u32 LFSR_S0; + u32 LFSR_S1; + u32 LFSR_S2; + u32 LFSR_S3; + u32 LFSR_S4; + u32 LFSR_S5; + u32 LFSR_S6; + u32 LFSR_S7; + u32 LFSR_S8; + u32 LFSR_S9; + u32 LFSR_S10; + u32 LFSR_S11; + u32 LFSR_S12; + u32 LFSR_S13; + u32 LFSR_S14; + u32 LFSR_S15; + /* the registers of F */ + u32 F_R1; + u32 F_R2; + /* the outputs of BitReorganization */ + u32 BRC_X0; + u32 BRC_X1; + u32 BRC_X2; + u32 BRC_X3; +} zuc_state_t; + +void zuc_initialize(zuc_state_t* state, u8* k, u8* iv); +void zuc_generate_keystream(zuc_state_t* state, int key_stream_len, u32* p_keystream); + +#endif // SRSLTE_ZUC_H diff --git a/lib/include/srslte/interfaces/common_interfaces.h b/lib/include/srslte/interfaces/common_interfaces.h index b183b924a..c5587e149 100644 --- a/lib/include/srslte/interfaces/common_interfaces.h +++ b/lib/include/srslte/interfaces/common_interfaces.h @@ -57,17 +57,18 @@ public: virtual void set_rx_srate(const uint32_t& radio_idx, const double& srate) = 0; // getter - virtual float get_rx_gain(const uint32_t& radio_idx) = 0; - virtual double get_freq_offset() = 0; - virtual double get_tx_freq(const uint32_t& radio_idx) = 0; - virtual double get_rx_freq(const uint32_t& radio_idx) = 0; - virtual float get_max_tx_power() = 0; - virtual float get_tx_gain_offset() = 0; - virtual float get_rx_gain_offset() = 0; - virtual bool is_continuous_tx() = 0; - virtual bool is_init() = 0; - virtual void reset() = 0; - virtual srslte_rf_info_t* get_info(const uint32_t& radio_idx) = 0; + virtual float get_rx_gain(const uint32_t& radio_idx) = 0; + virtual double get_freq_offset() = 0; + virtual double get_tx_freq(const uint32_t& radio_idx) = 0; + virtual double get_rx_freq(const uint32_t& radio_idx) = 0; + virtual float get_max_tx_power() = 0; + virtual float get_tx_gain_offset() = 0; + virtual float get_rx_gain_offset() = 0; + virtual bool is_continuous_tx() = 0; + virtual bool get_is_start_of_burst(const uint32_t& radio_idx) = 0; + virtual bool is_init() = 0; + virtual void reset() = 0; + virtual srslte_rf_info_t* get_info(const uint32_t& radio_idx) = 0; }; class phy_interface_radio diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index bd844fcc0..743d838b8 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -194,6 +194,7 @@ public: virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::rlc_config_t cnfg) = 0; virtual void add_bearer_mrb(uint16_t rnti, uint32_t lcid) = 0; virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0; + virtual bool has_bearer(uint16_t rnti, uint32_t lcid) = 0; }; // PDCP interface for GTPU @@ -207,20 +208,20 @@ public: class pdcp_interface_rrc { public: - virtual void reset(uint16_t rnti) = 0; - virtual void add_user(uint16_t rnti) = 0; - virtual void rem_user(uint16_t rnti) = 0; + virtual void reset(uint16_t rnti) = 0; + virtual void add_user(uint16_t rnti) = 0; + virtual void rem_user(uint16_t rnti) = 0; virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0; - virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cnfg) = 0; - virtual void config_security(uint16_t rnti, - uint32_t lcid, - uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, - uint8_t *k_up_enc_, + virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) = 0; + virtual void config_security(uint16_t rnti, + uint32_t lcid, + uint8_t* k_rrc_enc_, + uint8_t* k_rrc_int_, + uint8_t* k_up_enc_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; - virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0; - virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; + virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0; + virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0; }; // PDCP interface for RLC diff --git a/lib/include/srslte/interfaces/rrc_interface_types.h b/lib/include/srslte/interfaces/rrc_interface_types.h index caaa532a1..000e95477 100644 --- a/lib/include/srslte/interfaces/rrc_interface_types.h +++ b/lib/include/srslte/interfaces/rrc_interface_types.h @@ -24,6 +24,7 @@ #include "srslte/common/bcd_helpers.h" #include "srslte/config.h" +#include "srslte/srslte.h" #include /************************ @@ -124,6 +125,7 @@ struct plmn_id_t { struct s_tmsi_t { uint8_t mmec = 0; uint32_t m_tmsi = 0; + bool operator==(const s_tmsi_t& other) const { return mmec == other.mmec and m_tmsi == other.m_tmsi; } }; /*************************** @@ -180,6 +182,18 @@ inline uint16_t to_number(const rlc_umd_sn_size_t& sn_size) return enum_to_number(options, (uint32_t)rlc_mode_t::nulltype, (uint32_t)sn_size); } +enum class rlc_um_nr_sn_size_t { size6bits, size12bits, nulltype }; +inline std::string to_string(const rlc_um_nr_sn_size_t& sn_size) +{ + constexpr static const char* options[] = {"6 bits", "12 bits"}; + return enum_to_text(options, (uint32_t)rlc_mode_t::nulltype, (uint32_t)sn_size); +} +inline uint16_t to_number(const rlc_um_nr_sn_size_t& sn_size) +{ + constexpr static uint16_t options[] = {6, 12}; + return enum_to_number(options, (uint32_t)rlc_mode_t::nulltype, (uint32_t)sn_size); +} + struct rlc_am_config_t { /**************************************************************************** * Configurable parameters @@ -213,22 +227,49 @@ struct rlc_um_config_t { bool is_mrb; // Whether this is a multicast bearer }; +struct rlc_um_nr_config_t { + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 38.322 v15.3.0 Section 7 + ***************************************************************************/ + + rlc_um_nr_sn_size_t sn_field_length; // Number of bits used for sequence number + uint32_t UM_Window_Size; + uint32_t mod; // Rx/Tx counter modulus +}; + #define RLC_TX_QUEUE_LEN (128) +enum class rlc_type_t { lte, nr, nulltype }; +inline std::string to_string(const rlc_type_t& type) +{ + constexpr static const char* options[] = {"LTE", "NR"}; + return enum_to_text(options, (uint32_t)rlc_type_t::nulltype, (uint32_t)type); +} + class rlc_config_t { public: + rlc_type_t type; rlc_mode_t rlc_mode; rlc_am_config_t am; rlc_um_config_t um; + rlc_um_nr_config_t um_nr; uint32_t tx_queue_length; - rlc_config_t() : rlc_mode(rlc_mode_t::tm), am(), um(), tx_queue_length(RLC_TX_QUEUE_LEN){}; + rlc_config_t() : + type(rlc_type_t::lte), + rlc_mode(rlc_mode_t::tm), + am(), + um(), + um_nr(), + tx_queue_length(RLC_TX_QUEUE_LEN){}; // Factory for MCH static rlc_config_t mch_config() { - rlc_config_t cfg; + rlc_config_t cfg = {}; + cfg.type = rlc_type_t::lte; cfg.rlc_mode = rlc_mode_t::um; cfg.um.t_reordering = 45; cfg.um.rx_sn_field_length = rlc_umd_sn_size_t::size5bits; @@ -246,7 +287,8 @@ public: return {}; } // SRB1 and SRB2 are AM - rlc_config_t rlc_cfg; + rlc_config_t rlc_cfg = {}; + rlc_cfg.type = rlc_type_t::lte; rlc_cfg.rlc_mode = rlc_mode_t::am; rlc_cfg.am.t_poll_retx = 45; rlc_cfg.am.poll_pdu = -1; @@ -258,7 +300,8 @@ public: } static rlc_config_t default_rlc_um_config(uint32_t sn_size = 10) { - rlc_config_t cnfg; + rlc_config_t cnfg = {}; + cnfg.type = rlc_type_t::lte; cnfg.rlc_mode = rlc_mode_t::um; cnfg.um.t_reordering = 5; if (sn_size == 10) { @@ -280,7 +323,8 @@ public: } static rlc_config_t default_rlc_am_config() { - rlc_config_t rlc_cnfg; + rlc_config_t rlc_cnfg = {}; + rlc_cnfg.type = rlc_type_t::lte; rlc_cnfg.rlc_mode = rlc_mode_t::am; rlc_cnfg.am.t_reordering = 5; rlc_cnfg.am.t_status_prohibit = 5; @@ -290,7 +334,306 @@ public: rlc_cnfg.am.t_poll_retx = 5; return rlc_cnfg; } + static rlc_config_t default_rlc_um_nr_config(uint32_t sn_size = 6) + { + rlc_config_t cnfg = {}; + cnfg.type = rlc_type_t::nr; + cnfg.rlc_mode = rlc_mode_t::um; + if (sn_size == 6) { + cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size6bits; + cnfg.um_nr.UM_Window_Size = 32; + cnfg.um_nr.mod = 64; + } else if (sn_size == 12) { + cnfg.um_nr.sn_field_length = rlc_um_nr_sn_size_t::size12bits; + cnfg.um_nr.UM_Window_Size = 2048; + cnfg.um_nr.mod = 64; + } else { + return {}; + } + return cnfg; + } +}; + +/*************************** + * MAC Config + **************************/ +struct bsr_cfg_t { + int periodic_timer; + int retx_timer; + bsr_cfg_t() { reset(); } + void reset() + { + periodic_timer = -1; + retx_timer = 2560; + } +}; + +struct phr_cfg_t { + bool enabled; + int periodic_timer; + int prohibit_timer; + int db_pathloss_change; + bool extended; + phr_cfg_t() { reset(); } + void reset() + { + enabled = false; + periodic_timer = -1; + prohibit_timer = -1; + db_pathloss_change = -1; + extended = false; + } +}; + +struct sr_cfg_t { + bool enabled; + int dsr_transmax; + sr_cfg_t() { reset(); } + void reset() + { + enabled = false; + dsr_transmax = 0; + } +}; + +struct ul_harq_cfg_t { + uint32_t max_harq_msg3_tx; + uint32_t max_harq_tx; + ul_harq_cfg_t() { reset(); } + void reset() + { + max_harq_msg3_tx = 5; + max_harq_tx = 5; + } +}; + +struct rach_cfg_t { + bool enabled; + uint32_t nof_preambles; + uint32_t nof_groupA_preambles; + int32_t messagePowerOffsetGroupB; + uint32_t messageSizeGroupA; + uint32_t responseWindowSize; + uint32_t powerRampingStep; + uint32_t preambleTransMax; + int32_t iniReceivedTargetPower; + uint32_t contentionResolutionTimer; + uint32_t new_ra_msg_len; + rach_cfg_t() { reset(); } + void reset() + { + enabled = false; + nof_preambles = 0; + nof_groupA_preambles = 0; + messagePowerOffsetGroupB = 0; + messageSizeGroupA = 0; + responseWindowSize = 0; + powerRampingStep = 0; + preambleTransMax = 0; + iniReceivedTargetPower = 0; + contentionResolutionTimer = 0; + new_ra_msg_len = 0; + } +}; + +struct mac_cfg_t { + // Default constructor with default values as in 36.331 9.2.2 + mac_cfg_t() { set_defaults(); } + + void set_defaults() + { + rach_cfg.reset(); + set_mac_main_cfg_default(); + } + + void set_mac_main_cfg_default() + { + bsr_cfg.reset(); + phr_cfg.reset(); + sr_cfg.reset(); + harq_cfg.reset(); + time_alignment_timer = -1; + } + + bsr_cfg_t bsr_cfg; + phr_cfg_t phr_cfg; + sr_cfg_t sr_cfg; + rach_cfg_t rach_cfg; + ul_harq_cfg_t harq_cfg; + int time_alignment_timer; +}; + +/*************************** + * PHY Config + **************************/ + +struct phy_cfg_t { + phy_cfg_t() { set_defaults(); } + + void set_defaults() + { + ZERO_OBJECT(ul_cfg); + ZERO_OBJECT(dl_cfg); + ZERO_OBJECT(prach_cfg); + + // CommonConfig defaults for non-zero values + ul_cfg.pucch.delta_pucch_shift = 1; + ul_cfg.power_ctrl.delta_f_pucch[0] = 0; + ul_cfg.power_ctrl.delta_f_pucch[1] = 1; + ul_cfg.power_ctrl.delta_f_pucch[2] = 0; + ul_cfg.power_ctrl.delta_f_pucch[3] = 0; + ul_cfg.power_ctrl.delta_f_pucch[4] = 0; + + set_defaults_dedicated(); + } + + // 36.331 9.2.4 + void set_defaults_dedicated() + { + dl_cfg.tm = SRSLTE_TM1; + + dl_cfg.pdsch.use_tbs_index_alt = false; + dl_cfg.pdsch.p_a = 0; + + dl_cfg.cqi_report.periodic_configured = false; + dl_cfg.cqi_report.aperiodic_configured = false; + + ul_cfg.pucch.tdd_ack_multiplex = false; + + ul_cfg.pusch.uci_offset.I_offset_ack = 10; + ul_cfg.pusch.uci_offset.I_offset_ri = 12; + ul_cfg.pusch.uci_offset.I_offset_cqi = 15; + + ul_cfg.power_ctrl.p0_nominal_pusch = 0; + ul_cfg.power_ctrl.delta_mcs_based = false; + ul_cfg.power_ctrl.acc_enabled = true; + ul_cfg.power_ctrl.p0_nominal_pucch = 0; + ul_cfg.power_ctrl.p_srs_offset = 7; + + ul_cfg.srs.dedicated_enabled = false; + + ul_cfg.pucch.sr_configured = false; + } + + srslte_dl_cfg_t dl_cfg; + srslte_ul_cfg_t ul_cfg; + srslte_prach_cfg_t prach_cfg; +}; + +struct mbsfn_sf_cfg_t { + enum class alloc_period_t { n1, n2, n4, n8, n16, n32, nulltype }; + alloc_period_t radioframe_alloc_period; + uint8_t radioframe_alloc_offset = 0; + enum class sf_alloc_type_t { one_frame, four_frames, nulltype }; + sf_alloc_type_t nof_alloc_subfrs; + uint32_t sf_alloc; }; +inline uint16_t enum_to_number(const mbsfn_sf_cfg_t::alloc_period_t& radioframe_period) +{ + constexpr static uint16_t options[] = {1, 2, 4, 8, 16, 32}; + return enum_to_number(options, (uint32_t)mbsfn_sf_cfg_t::alloc_period_t::nulltype, (uint32_t)radioframe_period); +} + +struct mbms_notif_cfg_t { + enum class coeff_t { n2, n4 }; + coeff_t notif_repeat_coeff = coeff_t::n2; + uint8_t notif_offset = 0; + uint8_t notif_sf_idx = 1; +}; + +// MBSFN-AreaInfo-r9 ::= SEQUENCE +struct mbsfn_area_info_t { + uint8_t mbsfn_area_id = 0; + enum class region_len_t { s1, s2, nulltype } non_mbsfn_region_len; + uint8_t notif_ind = 0; + struct mcch_cfg_t { + enum class repeat_period_t { rf32, rf64, rf128, rf256, nulltype } mcch_repeat_period; + uint8_t mcch_offset = 0; + enum class mod_period_t { rf512, rf1024 } mcch_mod_period; + uint8_t sf_alloc_info = 0; + enum class sig_mcs_t { n2, n7, n13, n19, nulltype } sig_mcs; + } mcch_cfg; +}; +inline uint16_t enum_to_number(const mbsfn_area_info_t::region_len_t& region_len) +{ + constexpr static uint16_t options[] = {1, 2}; + return enum_to_number(options, (uint32_t)mbsfn_area_info_t::region_len_t::nulltype, (uint32_t)region_len); +} +inline uint16_t enum_to_number(const mbsfn_area_info_t::mcch_cfg_t::repeat_period_t& repeat_period) +{ + constexpr static uint16_t options[] = {32, 64, 128, 256}; + return enum_to_number( + options, (uint32_t)mbsfn_area_info_t::mcch_cfg_t::repeat_period_t::nulltype, (uint32_t)repeat_period); +} +inline uint16_t enum_to_number(const mbsfn_area_info_t::mcch_cfg_t::sig_mcs_t& sig_mcs) +{ + constexpr static uint16_t options[] = {2, 7, 13, 19}; + return enum_to_number(options, (uint32_t)mbsfn_area_info_t::mcch_cfg_t::sig_mcs_t::nulltype, (uint32_t)sig_mcs); +} + +// TMGI-r9 +struct tmgi_t { + enum class plmn_id_type_t { plmn_idx, explicit_value } plmn_id_type; + union choice { + uint8_t plmn_idx; + plmn_id_t explicit_value; + choice() : plmn_idx(0) {} + } plmn_id; + uint8_t serviced_id[3]; + tmgi_t() : plmn_id_type(plmn_id_type_t::plmn_idx) {} +}; + +struct pmch_info_t { + // pmch_cfg_t + uint16_t sf_alloc_end = 0; + uint8_t data_mcs = 0; + enum class mch_sched_period_t { rf8, rf16, rf32, rf64, rf128, rf256, rf512, rf1024, nulltype } mch_sched_period; + // mbms_session_info_list + struct mbms_session_info_t { + bool session_id_present = false; + tmgi_t tmgi; + uint8_t session_id; + uint8_t lc_ch_id = 0; + }; + uint32_t nof_mbms_session_info; + static const uint32_t max_session_per_pmch = 29; + mbms_session_info_t mbms_session_info_list[max_session_per_pmch]; +}; +inline uint16_t enum_to_number(const pmch_info_t::mch_sched_period_t& mch_period) +{ + constexpr static uint16_t options[] = {8, 16, 32, 64, 128, 256, 512, 1024}; + return enum_to_number(options, (uint32_t)pmch_info_t::mch_sched_period_t::nulltype, (uint32_t)mch_period); +} + +struct mcch_msg_t { + uint32_t nof_common_sf_alloc = 0; + mbsfn_sf_cfg_t common_sf_alloc[8]; + enum class common_sf_alloc_period_t { rf4, rf8, rf16, rf32, rf64, rf128, rf256, nulltype } common_sf_alloc_period; + uint32_t nof_pmch_info; + pmch_info_t pmch_info_list[15]; + // mbsfn_area_cfg_v930_ies non crit ext OPTIONAL +}; +inline uint16_t enum_to_number(const mcch_msg_t::common_sf_alloc_period_t& alloc_period) +{ + constexpr static uint16_t options[] = {4, 8, 16, 32, 64, 128, 256}; + return enum_to_number(options, (uint32_t)mcch_msg_t::common_sf_alloc_period_t::nulltype, (uint32_t)alloc_period); +} + +struct phy_cfg_mbsfn_t { + mbsfn_sf_cfg_t mbsfn_subfr_cnfg; + mbms_notif_cfg_t mbsfn_notification_cnfg; + mbsfn_area_info_t mbsfn_area_info; + mcch_msg_t mcch; +}; + +// SystemInformationBlockType13-r9 +struct sib13_t { + static const uint32_t max_mbsfn_area = 8; + uint32_t nof_mbsfn_area_info = 0; + mbsfn_area_info_t mbsfn_area_info_list[max_mbsfn_area]; + mbms_notif_cfg_t notif_cfg; +}; + } // namespace srslte #endif // SRSLTE_RRC_INTERFACE_TYPES_H diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 9f8261209..cfccd9b82 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -32,10 +32,11 @@ #include "rrc_interface_types.h" #include "srslte/asn1/liblte_mme.h" -#include "srslte/asn1/rrc_asn1.h" #include "srslte/common/common.h" #include "srslte/common/interfaces_common.h" #include "srslte/common/security.h" +#include "srslte/common/stack_procedure.h" +#include "srslte/interfaces/rrc_interface_types.h" #include "srslte/phy/channel/channel.h" #include "srslte/phy/rf/rf.h" @@ -118,43 +119,6 @@ public: virtual void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0; }; -// NAS interface for RRC -class nas_interface_rrc -{ -public: - typedef enum { - BARRING_NONE = 0, - BARRING_MO_DATA, - BARRING_MO_SIGNALLING, - BARRING_MT, - BARRING_ALL - } barring_t; - virtual void leave_connected() = 0; - virtual void set_barring(barring_t barring) = 0; - virtual void paging(srslte::s_tmsi_t* ue_identity) = 0; - virtual bool is_attached() = 0; - virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0; - virtual uint32_t get_k_enb_count() = 0; - virtual bool get_k_asme(uint8_t* k_asme_, uint32_t n) = 0; - virtual uint32_t get_ipv4_addr() = 0; - virtual bool get_ipv6_addr(uint8_t* ipv6_addr) = 0; -}; - -// NAS interface for UE -class nas_interface_ue -{ -public: - virtual bool attach_request() = 0; - virtual bool detach_request() = 0; -}; - -// NAS interface for UE -class nas_interface_gw -{ -public: - virtual bool attach_request() = 0; -}; - // RRC interface for MAC class rrc_interface_mac_common { @@ -193,12 +157,13 @@ public: virtual uint16_t get_mcc() = 0; virtual uint16_t get_mnc() = 0; virtual void enable_capabilities() = 0; - virtual int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) = 0; + virtual bool plmn_search() = 0; virtual void plmn_select(srslte::plmn_id_t plmn_id) = 0; virtual bool connection_request(srslte::establishment_cause_t cause, srslte::unique_byte_buffer_t dedicatedInfoNAS) = 0; virtual void set_ue_identity(srslte::s_tmsi_t s_tmsi) = 0; virtual bool is_connected() = 0; + virtual void paging_completed(bool outcome) = 0; virtual std::string get_rb_name(uint32_t lcid) = 0; virtual uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) = 0; }; @@ -212,44 +177,69 @@ public: virtual void write_pdu_bcch_dlsch(srslte::unique_byte_buffer_t pdu) = 0; virtual void write_pdu_pcch(srslte::unique_byte_buffer_t pdu) = 0; virtual void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0; - virtual std::string get_rb_name(uint32_t lcid) = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; }; // RRC interface for RLC class rrc_interface_rlc { public: - virtual void max_retx_attempted() = 0; - virtual std::string get_rb_name(uint32_t lcid) = 0; + virtual void max_retx_attempted() = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0; }; +// NAS interface for RRC +class nas_interface_rrc +{ +public: + typedef enum { BARRING_NONE = 0, BARRING_MO_DATA, BARRING_MO_SIGNALLING, BARRING_MT, BARRING_ALL } barring_t; + virtual void left_rrc_connected() = 0; + virtual void set_barring(barring_t barring) = 0; + virtual void paging(srslte::s_tmsi_t* ue_identity) = 0; + virtual bool is_attached() = 0; + virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0; + virtual uint32_t get_k_enb_count() = 0; + virtual bool get_k_asme(uint8_t* k_asme_, uint32_t n) = 0; + virtual uint32_t get_ipv4_addr() = 0; + virtual bool get_ipv6_addr(uint8_t* ipv6_addr) = 0; + virtual void plmn_search_completed(rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS], + int nof_plmns) = 0; + virtual bool connection_request_completed(bool outcome) = 0; + virtual void run_tti(uint32_t tti) = 0; +}; + +// NAS interface for UE +class nas_interface_ue +{ +public: + virtual void start_attach_request(srslte::proc_state_t* proc_result) = 0; + virtual bool detach_request(const bool switch_off) = 0; +}; // PDCP interface for RRC class pdcp_interface_rrc { public: - virtual void reestablish() = 0; - virtual void reestablish(uint32_t lcid) = 0; - virtual void reset() = 0; - virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true) = 0; - virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0; - virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; - virtual void config_security(uint32_t lcid, - uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, - uint8_t *k_up_enc_, + virtual void reestablish() = 0; + virtual void reestablish(uint32_t lcid) = 0; + virtual void reset() = 0; + virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true) = 0; + virtual void add_bearer(uint32_t lcid, srslte::pdcp_config_t cnfg) = 0; + virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; + virtual void config_security(uint32_t lcid, + uint8_t* k_rrc_enc_, + uint8_t* k_rrc_int_, + uint8_t* k_up_enc_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; - virtual void config_security_all(uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, - uint8_t *k_up_enc_, + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; + virtual void config_security_all(uint8_t* k_rrc_enc_, + uint8_t* k_rrc_int_, + uint8_t* k_up_enc_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; - virtual void enable_integrity(uint32_t lcid) = 0; - virtual void enable_encryption(uint32_t lcid) = 0; - virtual uint32_t get_dl_count(uint32_t lcid) = 0; - virtual uint32_t get_ul_count(uint32_t lcid) = 0; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; + virtual void enable_integrity(uint32_t lcid) = 0; + virtual void enable_encryption(uint32_t lcid) = 0; }; // PDCP interface for RLC @@ -325,30 +315,6 @@ public: virtual void write_pdu_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) = 0; }; - -//BSR interface for MUX -class bsr_interface_mux -{ -public: - typedef enum { - LONG_BSR, - SHORT_BSR, - TRUNC_BSR - } bsr_format_t; - - typedef struct { - bsr_format_t format; - uint32_t buff_size[4]; - } bsr_t; - - /* MUX calls BSR to check if it can fit a BSR into PDU */ - virtual bool need_to_send_bsr_on_ul_grant(uint32_t grant_size, bsr_t *bsr) = 0; - - /* MUX calls BSR to let it generate a padding BSR if there is space in PDU */ - virtual bool generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t *bsr) = 0; -}; - - /** MAC interface * */ @@ -372,6 +338,7 @@ public: uint32_t pid; uint16_t rnti; bool is_sps_release; + uint32_t tti; } mac_grant_dl_t; typedef struct { @@ -380,6 +347,7 @@ public: uint16_t rnti; bool phich_available; bool hi_value; + uint32_t tti_tx; } mac_grant_ul_t; typedef struct { @@ -449,196 +417,12 @@ public: uint64_t contention_id; } ue_rnti_t; - typedef struct ul_harq_cfg_t { - uint32_t max_harq_msg3_tx; - uint32_t max_harq_tx; - ul_harq_cfg_t() { reset(); } - void reset() - { - max_harq_msg3_tx = 5; - max_harq_tx = 5; - } - } ul_harq_cfg_t; }; /* Interface RRC -> MAC */ class mac_interface_rrc : public mac_interface_rrc_common { public: - typedef struct bsr_cfg_t { - int periodic_timer; - int retx_timer; - bsr_cfg_t() { reset(); } - void reset() - { - periodic_timer = -1; - retx_timer = 2560; - } - } bsr_cfg_t; - - typedef struct phr_cfg_t { - bool enabled; - int periodic_timer; - int prohibit_timer; - int db_pathloss_change; - bool extended; - phr_cfg_t() { reset(); } - void reset() - { - enabled = false; - periodic_timer = -1; - prohibit_timer = -1; - db_pathloss_change = -1; - extended = false; - } - } phr_cfg_t; - - typedef struct sr_cfg_t { - bool enabled; - int dsr_transmax; - sr_cfg_t() { reset(); } - void reset() - { - enabled = false; - dsr_transmax = 0; - } - } sr_cfg_t; - - typedef struct rach_cfg_t { - bool enabled; - uint32_t nof_preambles; - uint32_t nof_groupA_preambles; - int32_t messagePowerOffsetGroupB; - uint32_t messageSizeGroupA; - uint32_t responseWindowSize; - uint32_t powerRampingStep; - uint32_t preambleTransMax; - int32_t iniReceivedTargetPower; - uint32_t contentionResolutionTimer; - uint32_t new_ra_msg_len; - rach_cfg_t() { reset(); } - void reset() - { - enabled = false; - nof_preambles = 0; - nof_groupA_preambles = 0; - messagePowerOffsetGroupB = 0; - messageSizeGroupA = 0; - responseWindowSize = 0; - powerRampingStep = 0; - preambleTransMax = 0; - iniReceivedTargetPower = 0; - contentionResolutionTimer = 0; - new_ra_msg_len = 0; - } - } rach_cfg_t; - - class mac_cfg_t - { - public: - // Default constructor with default values as in 36.331 9.2.2 - mac_cfg_t() { set_defaults(); } - - void set_defaults() - { - rach_cfg.reset(); - set_mac_main_cfg_default(); - } - - void set_mac_main_cfg_default() - { - bsr_cfg.reset(); - phr_cfg.reset(); - sr_cfg.reset(); - harq_cfg.reset(); - time_alignment_timer = -1; - } - - // Called only if section is present - void set_sched_request_cfg(asn1::rrc::sched_request_cfg_c& cfg) - { - sr_cfg.enabled = cfg.type() == asn1::rrc::setup_e::setup; - if (sr_cfg.enabled) { - sr_cfg.dsr_transmax = cfg.setup().dsr_trans_max.to_number(); - } - } - - // MAC-MainConfig section is always present - void set_mac_main_cfg(asn1::rrc::mac_main_cfg_s& cfg) - { - // Update values only if each section is present - if (cfg.phr_cfg_present) { - phr_cfg.enabled = cfg.phr_cfg.type() == asn1::rrc::setup_e::setup; - if (phr_cfg.enabled) { - phr_cfg.prohibit_timer = cfg.phr_cfg.setup().prohibit_phr_timer.to_number(); - phr_cfg.periodic_timer = cfg.phr_cfg.setup().periodic_phr_timer.to_number(); - phr_cfg.db_pathloss_change = cfg.phr_cfg.setup().dl_pathloss_change.to_number(); - } - } - if (cfg.mac_main_cfg_v1020_present) { - typedef asn1::rrc::mac_main_cfg_s::mac_main_cfg_v1020_s_ mac_main_cfg_v1020_t; - mac_main_cfg_v1020_t* mac_main_cfg_v1020 = cfg.mac_main_cfg_v1020.get(); - phr_cfg.extended = mac_main_cfg_v1020->extended_phr_r10_present; - } - if (cfg.ul_sch_cfg_present) { - bsr_cfg.periodic_timer = cfg.ul_sch_cfg.periodic_bsr_timer.to_number(); - bsr_cfg.retx_timer = cfg.ul_sch_cfg.retx_bsr_timer.to_number(); - if (cfg.ul_sch_cfg.max_harq_tx_present) { - harq_cfg.max_harq_tx = cfg.ul_sch_cfg.max_harq_tx.to_number(); - } - } - // TimeAlignmentDedicated overwrites Common?? - time_alignment_timer = cfg.time_align_timer_ded.to_number(); - } - - // RACH-Common section is always present - void set_rach_cfg_common(asn1::rrc::rach_cfg_common_s& cfg) - { - - // Preamble info - rach_cfg.nof_preambles = cfg.preamb_info.nof_ra_preambs.to_number(); - if (cfg.preamb_info.preambs_group_a_cfg_present) { - rach_cfg.nof_groupA_preambles = cfg.preamb_info.preambs_group_a_cfg.size_of_ra_preambs_group_a.to_number(); - rach_cfg.messageSizeGroupA = cfg.preamb_info.preambs_group_a_cfg.msg_size_group_a.to_number(); - rach_cfg.messagePowerOffsetGroupB = cfg.preamb_info.preambs_group_a_cfg.msg_pwr_offset_group_b.to_number(); - } else { - rach_cfg.nof_groupA_preambles = 0; - } - - // Power ramping - rach_cfg.powerRampingStep = cfg.pwr_ramp_params.pwr_ramp_step.to_number(); - rach_cfg.iniReceivedTargetPower = cfg.pwr_ramp_params.preamb_init_rx_target_pwr.to_number(); - - // Supervision info - rach_cfg.preambleTransMax = cfg.ra_supervision_info.preamb_trans_max.to_number(); - rach_cfg.responseWindowSize = cfg.ra_supervision_info.ra_resp_win_size.to_number(); - rach_cfg.contentionResolutionTimer = cfg.ra_supervision_info.mac_contention_resolution_timer.to_number(); - - // HARQ Msg3 - harq_cfg.max_harq_msg3_tx = cfg.max_harq_msg3_tx; - } - - void set_time_alignment(asn1::rrc::time_align_timer_e time_alignment_timer) - { - this->time_alignment_timer = time_alignment_timer.to_number(); - } - - bsr_cfg_t& get_bsr_cfg() { return bsr_cfg; } - phr_cfg_t& get_phr_cfg() { return phr_cfg; } - rach_cfg_t& get_rach_cfg() { return rach_cfg; } - sr_cfg_t& get_sr_cfg() { return sr_cfg; } - ul_harq_cfg_t& get_harq_cfg() { return harq_cfg; } - int get_time_alignment_timer() { return time_alignment_timer; } - - private: - bsr_cfg_t bsr_cfg; - phr_cfg_t phr_cfg; - sr_cfg_t sr_cfg; - rach_cfg_t rach_cfg; - ul_harq_cfg_t harq_cfg; - int time_alignment_timer; - }; - virtual void clear_rntis() = 0; /* Instructs the MAC to start receiving BCCH */ @@ -656,7 +440,7 @@ public: virtual uint32_t get_current_tti() = 0; - virtual void set_config(mac_cfg_t& mac_cfg) = 0; + virtual void set_config(srslte::mac_cfg_t& mac_cfg) = 0; virtual void get_rntis(ue_rnti_t *rntis) = 0; virtual void set_contention_id(uint64_t uecri) = 0; @@ -791,45 +575,21 @@ public: class phy_interface_rrc_lte { public: - struct phy_cfg_common_t { - asn1::rrc::prach_cfg_sib_s prach_cnfg; - asn1::rrc::pdsch_cfg_common_s pdsch_cnfg; - asn1::rrc::pusch_cfg_common_s pusch_cnfg; - asn1::rrc::phich_cfg_s phich_cnfg; - asn1::rrc::pucch_cfg_common_s pucch_cnfg; - asn1::rrc::srs_ul_cfg_common_c srs_ul_cnfg; - asn1::rrc::ul_pwr_ctrl_common_s ul_pwr_ctrl; - asn1::rrc::tdd_cfg_s tdd_cnfg; - asn1::rrc::srs_ant_port_e ant_info; - bool rrc_enable_64qam; - }; - - struct phy_cfg_mbsfn_t { - asn1::rrc::mbsfn_sf_cfg_s mbsfn_subfr_cnfg; - asn1::rrc::mbms_notif_cfg_r9_s mbsfn_notification_cnfg; - asn1::rrc::mbsfn_area_info_r9_s mbsfn_area_info; - asn1::rrc::mcch_msg_s mcch; - }; - - typedef struct { - asn1::rrc::phys_cfg_ded_s dedicated; - phy_cfg_common_t common; - phy_cfg_mbsfn_t mbsfn; - } phy_cfg_t; - - virtual void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL) = 0; - virtual uint32_t get_current_earfcn() = 0; - virtual uint32_t get_current_pci() = 0; - - virtual void set_config(phy_cfg_t* config) = 0; - virtual void set_config_scell(asn1::rrc::scell_to_add_mod_r10_s* scell_config) = 0; - virtual void set_config_tdd(asn1::rrc::tdd_cfg_s* tdd) = 0; - virtual void set_config_mbsfn_sib2(asn1::rrc::sib_type2_s* sib2) = 0; - virtual void set_config_mbsfn_sib13(asn1::rrc::sib_type13_r9_s* sib13) = 0; - virtual void set_config_mbsfn_mcch(asn1::rrc::mcch_msg_s* mcch) = 0; + virtual void get_current_cell(srslte_cell_t* cell, uint32_t* current_earfcn = NULL) = 0; + virtual uint32_t get_current_earfcn() = 0; + virtual uint32_t get_current_pci() = 0; + + virtual void set_config(srslte::phy_cfg_t& config, + uint32_t cc_idx = 0, + uint32_t earfcn = 0, + srslte_cell_t* cell_info = nullptr) = 0; + virtual void set_config_tdd(srslte_tdd_config_t& tdd_config) = 0; + virtual void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) = 0; + virtual void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) = 0; + virtual void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) = 0; /* Measurements interface */ - virtual void meas_reset() = 0; + virtual void meas_reset() = 0; virtual int meas_start(uint32_t earfcn, int pci = -1) = 0; virtual int meas_stop(uint32_t earfcn, int pci = -1) = 0; @@ -864,6 +624,21 @@ class gw_interface_stack : public gw_interface_nas, public gw_interface_rrc, pub { }; +// STACK interface for MAC +class stack_interface_mac +{ +public: + virtual void process_pdus() = 0; + virtual void wait_ra_completion(uint16_t rnti) = 0; +}; + +// STACK interface for RRC +class stack_interface_rrc +{ +public: + virtual void start_cell_search() = 0; +}; + // Combined interface for PHY to access stack (MAC and RRC) class stack_interface_phy_lte : public mac_interface_phy_lte, public rrc_interface_phy_lte { diff --git a/lib/include/srslte/phy/ch_estimation/refsignal_ul.h b/lib/include/srslte/phy/ch_estimation/refsignal_ul.h index f972fed79..37f1a6b97 100644 --- a/lib/include/srslte/phy/ch_estimation/refsignal_ul.h +++ b/lib/include/srslte/phy/ch_estimation/refsignal_ul.h @@ -64,6 +64,8 @@ typedef struct SRSLTE_API { uint32_t I_srs; uint32_t k_tc; uint32_t n_rrc; + bool dedicated_enabled; + bool common_enabled; bool configured; } srslte_refsignal_srs_cfg_t; diff --git a/lib/include/srslte/phy/channel/channel.h b/lib/include/srslte/phy/channel/channel.h index 31fb35a1e..6bc15ad5d 100644 --- a/lib/include/srslte/phy/channel/channel.h +++ b/lib/include/srslte/phy/channel/channel.h @@ -24,10 +24,10 @@ #include "delay.h" #include "fading.h" +#include "hst.h" #include "rlf.h" #include -#include -#include +#include #include namespace srslte { @@ -43,11 +43,18 @@ public: bool fading_enable = false; std::string fading_model = "none"; + // High Speed Train options + bool hst_enable = false; + float hst_fd_hz = 750.0f; + float hst_period_s = 7.2f; + float hst_init_time_s = 0.0f; + // Delay options - bool delay_enable = false; - float delay_min_us = 10; - float delay_max_us = 100; - uint32_t delay_period_s = 3600; + bool delay_enable = false; + float delay_min_us = 10; + float delay_max_us = 100; + float delay_period_s = 3600; + float delay_init_time_s = 0; // RLF options bool rlf_enable = false; @@ -57,15 +64,18 @@ public: channel(const args_t& channel_args, uint32_t _nof_ports); ~channel(); + void set_logger(log_filter* _log_h); void set_srate(uint32_t srate); void run(cf_t* in[SRSLTE_MAX_PORTS], cf_t* out[SRSLTE_MAX_PORTS], uint32_t len, const srslte_timestamp_t& t); private: srslte_channel_fading_t* fading[SRSLTE_MAX_PORTS] = {}; srslte_channel_delay_t* delay[SRSLTE_MAX_PORTS] = {}; + srslte_channel_hst_t* hst = nullptr; // HST has no buffers / no multiple instance is required srslte_channel_rlf_t* rlf = nullptr; // RLF has no buffers / no multiple instance is required cf_t* buffer_in = nullptr; cf_t* buffer_out = nullptr; + log_filter* log_h = nullptr; uint32_t nof_ports = 0; uint32_t current_srate = 0; args_t args = {}; diff --git a/lib/include/srslte/phy/channel/delay.h b/lib/include/srslte/phy/channel/delay.h index c98e7e44f..d6130c4b9 100644 --- a/lib/include/srslte/phy/channel/delay.h +++ b/lib/include/srslte/phy/channel/delay.h @@ -22,16 +22,17 @@ #ifndef SRSLTE_DELAY_H #define SRSLTE_DELAY_H -#include -#include -#include +#include typedef struct { float delay_min_us; float delay_max_us; - uint32_t period_s; + float period_s; + float init_time_s; uint32_t srate_max_hz; uint32_t srate_hz; + float delay_us; + float delay_nsamples; srslte_ringbuffer_t rb; cf_t* zero_buffer; @@ -41,8 +42,12 @@ typedef struct { extern "C" { #endif -SRSLTE_API int srslte_channel_delay_init( - srslte_channel_delay_t* q, float delay_min_ns, float delay_max_ns, uint32_t period_s, uint32_t srate_max_hz); +SRSLTE_API int srslte_channel_delay_init(srslte_channel_delay_t* q, + float delay_min_us, + float delay_max_us, + float period_s, + float init_time_s, + uint32_t srate_max_hz); SRSLTE_API void srslte_channel_delay_update_srate(srslte_channel_delay_t* q, uint32_t srate_hz); diff --git a/lib/include/srslte/phy/channel/fading.h b/lib/include/srslte/phy/channel/fading.h index 37a6b2708..fda3b26d3 100644 --- a/lib/include/srslte/phy/channel/fading.h +++ b/lib/include/srslte/phy/channel/fading.h @@ -22,8 +22,8 @@ #ifndef SRSLTE_FADING_H #define SRSLTE_FADING_H -#include "srslte/phy/dft/dft.h" #include +#include #define SRSLTE_CHANNEL_FADING_MAXTAPS 9 diff --git a/lib/include/srslte/phy/channel/hst.h b/lib/include/srslte/phy/channel/hst.h new file mode 100644 index 000000000..315a2114c --- /dev/null +++ b/lib/include/srslte/phy/channel/hst.h @@ -0,0 +1,59 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_HST_H_ +#define SRSLTE_HST_H_ + +#include + +typedef struct { + // System parameters + uint32_t srate_hz; // Sampling rate + + // Model Parameters + float fd_hz; // Maximum Doppler Frequency + float ds_m; // eNb distance [m] + float dmin_m; // eNb Rail-track distance [m] + float period_s; // 2 * Ds / speed [s] + float init_time_s; // Time offset [s] + + // State + float fs_hz; // Last doppler dispersion [Hz] +} srslte_channel_hst_t; + +#ifdef __cplusplus +extern "C" { +#endif + +SRSLTE_API int srslte_channel_hst_init(srslte_channel_hst_t* q, float fd_hz, float period_d, float init_time_s); + +SRSLTE_API void srslte_channel_hst_update_srate(srslte_channel_hst_t* q, uint32_t srate); + +SRSLTE_API void +srslte_channel_hst_execute(srslte_channel_hst_t* q, cf_t* in, cf_t* out, uint32_t len, const srslte_timestamp_t* ts); + +SRSLTE_API void srslte_channel_hst_free(srslte_channel_hst_t* q); + +#ifdef __cplusplus +} +#endif + +#endif // SRSLTE_HST_H_ diff --git a/lib/include/srslte/phy/channel/rlf.h b/lib/include/srslte/phy/channel/rlf.h index 36e3ee836..48b1e7f45 100644 --- a/lib/include/srslte/phy/channel/rlf.h +++ b/lib/include/srslte/phy/channel/rlf.h @@ -22,8 +22,7 @@ #ifndef SRSLTE_RLF_H #define SRSLTE_RLF_H -#include -#include +#include typedef struct { uint32_t t_on_ms; diff --git a/lib/include/srslte/phy/common/phy_common.h b/lib/include/srslte/phy/common/phy_common.h index 920c44323..828015f67 100644 --- a/lib/include/srslte/phy/common/phy_common.h +++ b/lib/include/srslte/phy/common/phy_common.h @@ -258,6 +258,9 @@ typedef enum { SRSLTE_DCI_FORMAT2B, // SRSLTE_DCI_FORMAT3, // SRSLTE_DCI_FORMAT3A, + SRSLTE_DCI_FORMATN0, + SRSLTE_DCI_FORMATN1, + SRSLTE_DCI_FORMATN2, SRSLTE_DCI_NOF_FORMATS } srslte_dci_format_t; @@ -283,6 +286,43 @@ enum band_geographical_area { SRSLTE_BAND_GEO_AREA_NA }; +// NB-IoT specific structs +typedef enum { + SRSLTE_NBIOT_MODE_INBAND_SAME_PCI = 0, + SRSLTE_NBIOT_MODE_INBAND_DIFFERENT_PCI, + SRSLTE_NBIOT_MODE_GUARDBAND, + SRSLTE_NBIOT_MODE_STANDALONE, + SRSLTE_NBIOT_MODE_N_ITEMS, +} srslte_nbiot_mode_t; + +typedef struct SRSLTE_API { + srslte_cell_t base; // the umbrella or super cell + uint32_t nbiot_prb; // the index of the NB-IoT PRB within the cell + uint32_t n_id_ncell; + uint32_t nof_ports; // The number of antenna ports for NB-IoT + bool is_r14; // Whether the cell is a R14 cell + srslte_nbiot_mode_t mode; +} srslte_nbiot_cell_t; + +#define SRSLTE_NBIOT_MAX_PORTS 2 +#define SRSLTE_NBIOT_MAX_CODEWORDS SRSLTE_MAX_CODEWORDS + +#define SRSLTE_SF_LEN_PRB_NBIOT (SRSLTE_SF_LEN_PRB(1)) + +#define SRSLTE_SF_LEN_RE_NBIOT (SRSLTE_SF_LEN_RE(1, SRSLTE_CP_NORM)) + +#define SRSLTE_NBIOT_FFT_SIZE 128 +#define SRSLTE_NBIOT_FREQ_SHIFT_FACTOR ((float)-0.5) +#define SRSLTE_NBIOT_NUM_RX_ANTENNAS 1 +#define SRSLTE_NBIOT_MAX_PRB 1 + +#define SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL 1 +#define SRSLTE_NBIOT_DEFAULT_PRB_OFFSET 0 + +#define SRSLTE_DEFAULT_MAX_FRAMES_NPBCH 500 +#define SRSLTE_DEFAULT_MAX_FRAMES_NPSS 20 +#define SRSLTE_DEFAULT_NOF_VALID_NPSS_FRAMES 20 + SRSLTE_API bool srslte_cell_isvalid(srslte_cell_t *cell); SRSLTE_API void srslte_cell_fprint(FILE *stream, @@ -386,4 +426,10 @@ SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2); SRSLTE_API uint32_t srslte_print_check(char* s, size_t max_len, uint32_t cur_len, const char* format, ...); +SRSLTE_API bool srslte_nbiot_cell_isvalid(srslte_nbiot_cell_t* cell); +SRSLTE_API bool srslte_nbiot_portid_isvalid(uint32_t port_id); +SRSLTE_API float srslte_band_fu_nbiot(uint32_t ul_earfcn, const float m_ul); + +SRSLTE_API char* srslte_nbiot_mode_string(srslte_nbiot_mode_t mode); + #endif // SRSLTE_PHY_COMMON_H diff --git a/lib/include/srslte/phy/io/filesink.h b/lib/include/srslte/phy/io/filesink.h index 460a967f0..b18ba967b 100644 --- a/lib/include/srslte/phy/io/filesink.h +++ b/lib/include/srslte/phy/io/filesink.h @@ -33,6 +33,7 @@ #define SRSLTE_FILESINK_H #include +#include #include #include "srslte/config.h" diff --git a/lib/include/srslte/phy/io/netsource.h b/lib/include/srslte/phy/io/netsource.h index 24eeef85e..5ce3d29e5 100644 --- a/lib/include/srslte/phy/io/netsource.h +++ b/lib/include/srslte/phy/io/netsource.h @@ -67,6 +67,8 @@ SRSLTE_API int srslte_netsource_read(srslte_netsource_t *q, void *buffer, int nof_bytes); +SRSLTE_API int srslte_netsource_write(srslte_netsource_t* q, void* buffer, int nbytes); + SRSLTE_API int srslte_netsource_set_timeout(srslte_netsource_t *q, uint32_t microseconds); diff --git a/lib/include/srslte/phy/phch/dci.h b/lib/include/srslte/phy/phch/dci.h index 3353becb6..aa9dd56ae 100644 --- a/lib/include/srslte/phy/phch/dci.h +++ b/lib/include/srslte/phy/phch/dci.h @@ -52,6 +52,7 @@ typedef struct { bool multiple_csi_request_enabled; bool cif_enabled; + bool cif_present; bool srs_request_enabled; bool ra_format_enabled; } srslte_dci_cfg_t; @@ -160,8 +161,9 @@ typedef struct SRSLTE_API { // Release 10 uint32_t cif; bool cif_present; + uint8_t multiple_csi_request; bool multiple_csi_request_present; - uint32_t srs_request; + bool srs_request; bool srs_request_present; srslte_ra_type_t ra_type; bool ra_type_present; diff --git a/lib/include/srslte/phy/phch/pdsch_cfg.h b/lib/include/srslte/phy/phch/pdsch_cfg.h index d00813648..f70ada223 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg.h @@ -60,6 +60,7 @@ typedef struct SRSLTE_API { float rs_power; bool power_scale; bool csi_enable; + bool use_tbs_index_alt; union { srslte_softbuffer_tx_t* tx[SRSLTE_MAX_CODEWORDS]; diff --git a/lib/include/srslte/phy/phch/pucch_cfg.h b/lib/include/srslte/phy/phch/pucch_cfg.h index b69e9282b..443edd89a 100644 --- a/lib/include/srslte/phy/phch/pucch_cfg.h +++ b/lib/include/srslte/phy/phch/pucch_cfg.h @@ -62,9 +62,8 @@ typedef struct SRSLTE_API { uint32_t n_pucch_2; uint32_t n_pucch_sr; bool simul_cqi_ack; - bool tdd_ack_bundle; // if false, multiplex + bool tdd_ack_multiplex; // if false, bundle bool sps_enabled; - uint32_t tpc_for_pucch; // Release 10 CA specific srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode; diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index 9d43af238..9ee92a93b 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -127,6 +127,10 @@ SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t* cfg, uint32_t nof_bits, bool is_ri); +SRSLTE_API uint32_t srslte_uci_cfg_total_ack(srslte_uci_cfg_t* uci_cfg); + +SRSLTE_API void srslte_uci_data_reset(srslte_uci_data_t* uci_data); + SRSLTE_API int srslte_uci_data_info(srslte_uci_cfg_t* uci_cfg, srslte_uci_value_t* uci_data, char* str, diff --git a/lib/include/srslte/phy/phch/uci_cfg.h b/lib/include/srslte/phy/phch/uci_cfg.h index 83b7cf2dd..bdb1aeeb5 100644 --- a/lib/include/srslte/phy/phch/uci_cfg.h +++ b/lib/include/srslte/phy/phch/uci_cfg.h @@ -39,12 +39,13 @@ typedef struct SRSLTE_API { uint32_t N_bundle; uint32_t tdd_ack_M; uint32_t tdd_ack_m; - bool tdd_is_bundling; - bool has_scell_ack; + bool tdd_is_multiplex; + uint32_t tpc_for_pucch; + uint32_t grant_cc_idx; } srslte_uci_cfg_ack_t; typedef struct SRSLTE_API { - srslte_uci_cfg_ack_t ack; + srslte_uci_cfg_ack_t ack[SRSLTE_MAX_CARRIERS]; srslte_cqi_cfg_t cqi; bool is_scheduling_request_tti; } srslte_uci_cfg_t; diff --git a/lib/include/srslte/phy/rf/rf.h b/lib/include/srslte/phy/rf/rf.h index d9d5222d8..260558802 100644 --- a/lib/include/srslte/phy/rf/rf.h +++ b/lib/include/srslte/phy/rf/rf.h @@ -92,17 +92,9 @@ SRSLTE_API void srslte_rf_flush_buffer(srslte_rf_t *h); SRSLTE_API bool srslte_rf_has_rssi(srslte_rf_t *h); -SRSLTE_API float srslte_rf_get_rssi(srslte_rf_t *h); +SRSLTE_API float srslte_rf_get_rssi(srslte_rf_t* h); -SRSLTE_API bool srslte_rf_rx_wait_lo_locked(srslte_rf_t *h); - -SRSLTE_API void srslte_rf_set_master_clock_rate(srslte_rf_t *h, - double rate); - -SRSLTE_API bool srslte_rf_is_master_clock_dynamic(srslte_rf_t *h); - -SRSLTE_API double srslte_rf_set_rx_srate(srslte_rf_t *h, - double freq); +SRSLTE_API double srslte_rf_set_rx_srate(srslte_rf_t* h, double freq); SRSLTE_API double srslte_rf_set_rx_gain(srslte_rf_t *h, double gain); diff --git a/lib/include/srslte/phy/sync/npss.h b/lib/include/srslte/phy/sync/npss.h new file mode 100644 index 000000000..58fa1dfc7 --- /dev/null +++ b/lib/include/srslte/phy/sync/npss.h @@ -0,0 +1,123 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +/****************************************************************************** + * File: npss.h + * + * Description: Narrowband Primary synchronization signal (NPSS) generation and detection. + * + * The srslte_npss_synch_t object provides functions for fast + * computation of the crosscorrelation between the NPSS and received + * signal and CFO estimation. Also, the function srslte_npss_synch_tperiodic() + * is designed to be called periodically every subframe, taking + * care of the correct data alignment with respect to the NPSS sequence. + * + * The object is designed to work with signals sampled at ?.? Mhz + * centered at the carrier frequency. Thus, downsampling is required + * if the signal is sampled at higher frequencies. + * + * Reference: 3GPP TS 36.211 version 13.2.0 Release 13 Sec. 10.x.x + *****************************************************************************/ + +#ifndef SRSLTE_NPSS_H +#define SRSLTE_NPSS_H + +#include +#include + +#include "srslte/config.h" +#include "srslte/phy/common/phy_common.h" +#include "srslte/phy/utils/convolution.h" + +#define CONVOLUTION_FFT + +#define SRSLTE_NPSS_RETURN_PSR + +#define SRSLTE_NPSS_LEN 11 +#define SRSLTE_NPSS_NUM_OFDM_SYMS 11 +#define SRSLTE_NPSS_TOT_LEN (SRSLTE_NPSS_LEN * SRSLTE_NPSS_NUM_OFDM_SYMS) + +#define SRSLTE_NPSS_CORR_FILTER_LEN \ + ((SRSLTE_NPSS_NUM_OFDM_SYMS * SRSLTE_NBIOT_FFT_SIZE) + \ + (SRSLTE_NPSS_NUM_OFDM_SYMS - 1) * SRSLTE_CP_LEN_NORM(1, SRSLTE_NBIOT_FFT_SIZE) + \ + SRSLTE_CP_LEN_NORM(0, SRSLTE_NBIOT_FFT_SIZE)) + +// The below value corresponds to the time-domain representation of the first +// three OFDM-symbols plus cyclic prefix that are not transmitted in the sub-frame +// carrying the NPSS +#define SRSLTE_NPSS_CORR_OFFSET (SRSLTE_SF_LEN(SRSLTE_NBIOT_FFT_SIZE) - SRSLTE_NPSS_CORR_FILTER_LEN) + +// CFO estimation based on the NPSS is done using the second slot of the sub-frame +#define SRSLTE_NPSS_CFO_OFFSET (SRSLTE_SF_LEN(SRSLTE_NBIOT_FFT_SIZE) / 2 - SRSLTE_NPSS_CORR_OFFSET) +#define SRSLTE_NPSS_CFO_NUM_SYMS 6 // number of symbols for CFO estimation +#define SRSLTE_NPSS_CFO_NUM_SAMPS \ + ((SRSLTE_NPSS_CFO_NUM_SYMS * SRSLTE_NBIOT_FFT_SIZE) + \ + (SRSLTE_NPSS_CFO_NUM_SYMS - 1) * SRSLTE_CP_LEN_NORM(1, SRSLTE_NBIOT_FFT_SIZE) + \ + SRSLTE_CP_LEN_NORM(0, SRSLTE_NBIOT_FFT_SIZE)) // resulting number of samples + +// NPSS processing options +#define SRSLTE_NPSS_ACCUMULATE_ABS // If enabled, accumulates the correlation absolute value on consecutive calls to + // srslte_pss_synch_find_pss + +#define SRSLTE_NPSS_ABS_SQUARE // If enabled, compute abs square, otherwise computes absolute value only + +#define SRSLTE_NPSS_RETURN_PSR // If enabled returns peak to side-lobe ratio, otherwise returns absolute peak value + +/* Low-level API */ +typedef struct SRSLTE_API { +#ifdef CONVOLUTION_FFT + srslte_conv_fft_cc_t conv_fft; +#endif + + uint32_t frame_size, max_frame_size; + uint32_t fft_size, max_fft_size; + + cf_t* npss_signal_time; + cf_t* tmp_input; + cf_t* conv_output; + float* conv_output_abs; + float ema_alpha; + float* conv_output_avg; + float peak_value; +} srslte_npss_synch_t; + +// Basic functionality +SRSLTE_API int srslte_npss_synch_init(srslte_npss_synch_t* q, uint32_t frame_size, uint32_t fft_size); + +SRSLTE_API void srslte_npss_synch_reset(srslte_npss_synch_t* q); + +SRSLTE_API int srslte_npss_synch_resize(srslte_npss_synch_t* q, uint32_t frame_size, uint32_t fft_size); + +SRSLTE_API void srslte_npss_synch_set_ema_alpha(srslte_npss_synch_t* q, float alpha); + +SRSLTE_API void srslte_npss_synch_free(srslte_npss_synch_t* q); + +SRSLTE_API int srslte_npss_sync_find(srslte_npss_synch_t* q, cf_t* input, float* corr_peak_value); + +// Internal functions +SRSLTE_API int srslte_npss_corr_init(cf_t* npss_signal_time, uint32_t fft_size, uint32_t frame_size); + +SRSLTE_API int srslte_npss_generate(cf_t* signal); + +SRSLTE_API void srslte_npss_put_subframe( + srslte_npss_synch_t* q, cf_t* npss_signal, cf_t* sf, const uint32_t nof_prb, const uint32_t nbiot_prb_offset); + +#endif // SRSLTE_NPSS_H diff --git a/lib/include/srslte/phy/sync/nsss.h b/lib/include/srslte/phy/sync/nsss.h new file mode 100644 index 000000000..fb7582ccc --- /dev/null +++ b/lib/include/srslte/phy/sync/nsss.h @@ -0,0 +1,116 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +/****************************************************************************** + * File: nsss.h + * + * Description: Narrowband secondary synchronization signal (NSSS) + * generation and detection. + * + * + * Reference: 3GPP TS 36.211 version 13.2.0 Release 13 Sec. 10.2.7.2 + *****************************************************************************/ + +#ifndef SRSLTE_NSSS_H +#define SRSLTE_NSSS_H + +#include +#include +#include + +#include "srslte/config.h" +#include "srslte/phy/common/phy_common.h" +#include "srslte/phy/dft/dft.h" +#include "srslte/phy/utils/convolution.h" + +#define SRSLTE_NSSS_NSYMB 11 +#define SRSLTE_NSSS_NSC 12 +#define SRSLTE_NSSS_LEN (SRSLTE_NSSS_NSYMB * SRSLTE_NSSS_NSC) +#define SRSLTE_NSSS_NUM_SEQ 4 +#define SRSLTE_NSSS_TOT_LEN (SRSLTE_NSSS_NUM_SEQ * SRSLTE_NSSS_LEN) + +#define SRSLTE_NSSS_CORR_FILTER_LEN 1508 +#define SRSLTE_NSSS_CORR_OFFSET 412 + +#define SRSLTE_NUM_PCI 504 + +#define SRSLTE_NSSS_PERIOD 2 +#define SRSLTE_NSSS_NUM_SF_DETECT (SRSLTE_NSSS_PERIOD) + +// b_q_m table from 3GPP TS 36.211 v13.2.0 table 10.2.7.2.1-1 +static const int b_q_m[SRSLTE_NSSS_NUM_SEQ][128] = { + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, + 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, + 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, + 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1}, + {1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, + -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, + -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, + -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, + 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1}, + {1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, + -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, + -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, + 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, + -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1}}; + +/* Low-level API */ +typedef struct SRSLTE_API { + uint32_t input_size; + uint32_t subframe_sz; + uint32_t fft_size, max_fft_size; + srslte_conv_fft_cc_t conv_fft; + + cf_t* nsss_signal_time[SRSLTE_NUM_PCI]; + cf_t* tmp_input; + cf_t* conv_output; + float* conv_output_abs; + float peak_values[SRSLTE_NUM_PCI]; + float corr_peak_threshold; +} srslte_nsss_synch_t; + +SRSLTE_API int srslte_nsss_synch_init(srslte_nsss_synch_t* q, uint32_t input_size, uint32_t fft_size); + +SRSLTE_API void srslte_nsss_synch_free(srslte_nsss_synch_t* q); + +SRSLTE_API int srslte_nsss_synch_resize(srslte_nsss_synch_t* q, uint32_t fft_size); + +SRSLTE_API int srslte_nsss_sync_find( + srslte_nsss_synch_t* q, cf_t* input, float* corr_peak_value, uint32_t* cell_id, uint32_t* sfn_partial); + +void srslte_nsss_sync_find_pci(srslte_nsss_synch_t* q, cf_t* input, uint32_t cell_id); + +SRSLTE_API int srslte_nsss_corr_init(srslte_nsss_synch_t* q); + +SRSLTE_API void srslte_nsss_generate(cf_t* signal, uint32_t cell_id); + +SRSLTE_API void srslte_nsss_put_subframe(srslte_nsss_synch_t* q, + cf_t* nsss, + cf_t* subframe, + const int nf, + const uint32_t nof_prb, + const uint32_t nbiot_prb_offset); + +#endif // SRSLTE_NSSS_H \ No newline at end of file diff --git a/lib/include/srslte/phy/sync/refsignal_dl_sync.h b/lib/include/srslte/phy/sync/refsignal_dl_sync.h new file mode 100644 index 000000000..368e8776e --- /dev/null +++ b/lib/include/srslte/phy/sync/refsignal_dl_sync.h @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_REFSIGNAL_DL_SYNC_H_ +#define SRSLTE_REFSIGNAL_DL_SYNC_H_ + +#include +#include +#include + +typedef struct { + srslte_refsignal_t refsignal; + srslte_ofdm_t ifft; + cf_t* ifft_buffer_in; + cf_t* ifft_buffer_out; + cf_t* sequences[SRSLTE_NOF_SF_X_FRAME]; + cf_t* correlation; + srslte_conv_fft_cc_t conv_fft_cc; + + // Results + bool found; + float rsrp_dBfs; + float rssi_dBfs; + float rsrq_dB; + float cfo_Hz; + uint32_t peak_index; +} srslte_refsignal_dl_sync_t; + +SRSLTE_API int srslte_refsignal_dl_sync_init(srslte_refsignal_dl_sync_t* q); + +SRSLTE_API int srslte_refsignal_dl_sync_set_cell(srslte_refsignal_dl_sync_t* q, srslte_cell_t cell); + +SRSLTE_API void srslte_refsignal_dl_sync_free(srslte_refsignal_dl_sync_t* q); + +SRSLTE_API void srslte_refsignal_dl_sync_run(srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t nsamples); + +SRSLTE_API void srslte_refsignal_dl_sync_measure_sf( + srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t sf_idx, float* rsrp, float* rssi, float* cfo); + +#endif // SRSLTE_REFSIGNAL_DL_SYNC_H_ diff --git a/lib/include/srslte/phy/sync/sss.h b/lib/include/srslte/phy/sync/sss.h index 40249f687..2ed8066ee 100644 --- a/lib/include/srslte/phy/sync/sss.h +++ b/lib/include/srslte/phy/sync/sss.h @@ -131,9 +131,7 @@ SRSLTE_API int srslte_sss_m0m1_diff(srslte_sss_t *q, SRSLTE_API uint32_t srslte_sss_subframe(uint32_t m0, uint32_t m1); -SRSLTE_API int srslte_sss_N_id_1(srslte_sss_t *q, - uint32_t m0, - uint32_t m1); +SRSLTE_API int srslte_sss_N_id_1(srslte_sss_t* q, uint32_t m0, uint32_t m1, float corr); SRSLTE_API int srslte_sss_frame(srslte_sss_t *q, cf_t *input, diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index ba1b1539e..27bcf3fbf 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -118,6 +118,7 @@ typedef struct SRSLTE_API { bool sss_generated; bool sss_detected; bool sss_available; + float sss_corr; srslte_dft_plan_t idftp_sss; cf_t sss_recv[SRSLTE_SYMBOL_SZ_MAX]; cf_t sss_signal[2][SRSLTE_SYMBOL_SZ_MAX]; @@ -242,6 +243,8 @@ SRSLTE_API srslte_pss_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q); SRSLTE_API bool srslte_sync_sss_detected(srslte_sync_t *q); +SRSLTE_API float srslte_sync_sss_correlation_peak(srslte_sync_t* q); + SRSLTE_API bool srslte_sync_sss_available(srslte_sync_t* q); /* Enables/Disables CP detection */ diff --git a/lib/include/srslte/phy/sync/sync_nbiot.h b/lib/include/srslte/phy/sync/sync_nbiot.h new file mode 100644 index 000000000..430b9a1ec --- /dev/null +++ b/lib/include/srslte/phy/sync/sync_nbiot.h @@ -0,0 +1,125 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +/****************************************************************************** + * File: sync_nbiot.h + * + * Description: Time and frequency synchronization using the NPSS and NSSS signals. + * + * The object is designed to work with signals sampled at 1.92 Mhz + * centered at the carrier frequency. Thus, downsampling is required + * if the signal is sampled at higher frequencies. + * + * Correlation peak is detected comparing the maximum at the output + * of the correlator with a threshold. + * + * Reference: 3GPP TS 36.211 version 13.2.0 Release 13 + *****************************************************************************/ + +#ifndef SRSLTE_SYNC_NBIOT_H +#define SRSLTE_SYNC_NBIOT_H + +#include +#include + +#include "srslte/config.h" +#include "srslte/phy/sync/npss.h" +#include "srslte/phy/sync/nsss.h" +#include "srslte/phy/sync/sync.h" +#include "srslte/phy/ue/ue_sync.h" + +#define MAX_NUM_CFO_CANDITATES 50 + +typedef struct SRSLTE_API { + srslte_npss_synch_t npss; + srslte_nsss_synch_t nsss; + srslte_cp_synch_t cp_synch; + uint32_t n_id_ncell; + + float threshold; + float peak_value; + uint32_t fft_size; + uint32_t frame_size; + uint32_t max_frame_size; + uint32_t max_offset; + bool enable_cfo_estimation; + bool enable_cfo_cand_test; + float cfo_cand[MAX_NUM_CFO_CANDITATES]; + int cfo_num_cand; + int cfo_cand_idx; + float mean_cfo; + float current_cfo_tol; + cf_t* shift_buffer; + cf_t* cfo_output; + int cfo_i; + bool find_cfo_i; + bool find_cfo_i_initiated; + float cfo_ema_alpha; + uint32_t nof_symbols; + uint32_t cp_len; + srslte_cfo_t cfocorr; + srslte_cp_t cp; +} srslte_sync_nbiot_t; + +SRSLTE_API int +srslte_sync_nbiot_init(srslte_sync_nbiot_t* q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size); + +SRSLTE_API void srslte_sync_nbiot_free(srslte_sync_nbiot_t* q); + +SRSLTE_API int +srslte_sync_nbiot_resize(srslte_sync_nbiot_t* q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size); + +SRSLTE_API srslte_sync_find_ret_t srslte_sync_nbiot_find(srslte_sync_nbiot_t* q, + cf_t* input, + uint32_t find_offset, + uint32_t* peak_position); + +SRSLTE_API float cfo_estimate_nbiot(srslte_sync_nbiot_t* q, cf_t* input); + +SRSLTE_API void srslte_sync_nbiot_set_threshold(srslte_sync_nbiot_t* q, float threshold); + +SRSLTE_API void srslte_sync_nbiot_set_cfo_enable(srslte_sync_nbiot_t* q, bool enable); + +SRSLTE_API void srslte_sync_nbiot_set_cfo_cand_test_enable(srslte_sync_nbiot_t* q, bool enable); + +SRSLTE_API int srslte_sync_nbiot_set_cfo_cand(srslte_sync_nbiot_t* q, const float* cand, const int num); + +SRSLTE_API void srslte_sync_nbiot_set_cfo_tol(srslte_sync_nbiot_t* q, float tol); + +SRSLTE_API void srslte_sync_nbiot_set_cfo_ema_alpha(srslte_sync_nbiot_t* q, float alpha); + +SRSLTE_API void srslte_sync_nbiot_set_npss_ema_alpha(srslte_sync_nbiot_t* q, float alpha); + +SRSLTE_API int srslte_sync_nbiot_find_cell_id(srslte_sync_nbiot_t* q, cf_t* input); + +SRSLTE_API int srslte_sync_nbiot_get_cell_id(srslte_sync_nbiot_t* q); + +SRSLTE_API float srslte_sync_nbiot_get_cfo(srslte_sync_nbiot_t* q); + +SRSLTE_API void srslte_sync_nbiot_set_cfo(srslte_sync_nbiot_t* q, float cfo); + +SRSLTE_API bool srslte_sync_nbiot_nsss_detected(srslte_sync_nbiot_t* q); + +SRSLTE_API float srslte_sync_nbiot_get_peak_value(srslte_sync_nbiot_t* q); + +SRSLTE_API void srslte_sync_nbiot_reset(srslte_sync_nbiot_t* q); + +#endif // SRSLTE_SYNC_NBIOT_H diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 6e74107dd..ed43ab149 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -112,21 +112,22 @@ typedef struct SRSLTE_API { typedef struct SRSLTE_API { srslte_cqi_report_cfg_t cqi_report; srslte_pdsch_cfg_t pdsch; + srslte_dci_cfg_t dci; srslte_tm_t tm; } srslte_dl_cfg_t; typedef struct SRSLTE_API { srslte_dl_cfg_t cfg; srslte_chest_dl_cfg_t chest_cfg; - srslte_dci_cfg_t dci_cfg; uint32_t last_ri; float snr_to_cqi_offset; - bool pdsch_use_tbs_index_alt; } srslte_ue_dl_cfg_t; typedef struct { uint32_t v_dai_dl; uint32_t n_cce; + uint32_t grant_cc_idx; + uint32_t tpc_for_pucch; } srslte_pdsch_ack_resource_t; typedef struct { @@ -149,7 +150,7 @@ typedef struct { srslte_ack_nack_feedback_mode_t ack_nack_feedback_mode; bool is_grant_available; bool is_pusch_available; - bool tdd_ack_bundle; + bool tdd_ack_multiplex; bool simul_cqi_ack; } srslte_pdsch_ack_t; @@ -182,13 +183,13 @@ SRSLTE_API int srslte_ue_dl_decode_fft_estimate_noguru(srslte_ue_dl_t* q, /* Finds UL/DL DCI in the signal processed in a previous call to decode_fft_estimate() */ SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, - srslte_ue_dl_cfg_t* cfg, + srslte_ue_dl_cfg_t* dl_cfg, uint16_t rnti, srslte_dci_ul_t dci_msg[SRSLTE_MAX_DCI_MSG]); SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, - srslte_ue_dl_cfg_t* cfg, + srslte_ue_dl_cfg_t* dl_cfg, uint16_t rnti, srslte_dci_dl_t dci_msg[SRSLTE_MAX_DCI_MSG]); diff --git a/lib/include/srslte/phy/utils/ringbuffer.h b/lib/include/srslte/phy/utils/ringbuffer.h index 83a9715d2..247369a04 100644 --- a/lib/include/srslte/phy/utils/ringbuffer.h +++ b/lib/include/srslte/phy/utils/ringbuffer.h @@ -35,7 +35,8 @@ typedef struct { int wpm; int rpm; pthread_mutex_t mutex; - pthread_cond_t cvar; + pthread_cond_t write_cvar; + pthread_cond_t read_cvar; } srslte_ringbuffer_t; #ifdef __cplusplus @@ -54,6 +55,8 @@ SRSLTE_API int srslte_ringbuffer_space(srslte_ringbuffer_t *q); SRSLTE_API int srslte_ringbuffer_write(srslte_ringbuffer_t* q, void* ptr, int nof_bytes); +SRSLTE_API int srslte_ringbuffer_write_timed(srslte_ringbuffer_t* q, void* ptr, int nof_bytes, uint32_t timeout_ms); + SRSLTE_API int srslte_ringbuffer_read(srslte_ringbuffer_t* q, void* ptr, int nof_bytes); SRSLTE_API int srslte_ringbuffer_read_timed(srslte_ringbuffer_t* q, void* p, int nof_bytes, uint32_t timeout_ms); diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 4fa0e848e..d154a34a7 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -49,7 +49,6 @@ class radio { burst_preamble_samples = 0; burst_preamble_time_rounded = 0; - master_clock_rate = 0; cur_tx_srate = 0; tx_adv_sec = 0; tx_adv_nsamples = 0; @@ -92,6 +91,7 @@ class radio { bool tx_single(cf_t* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); bool tx(cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); void tx_end(); + bool get_is_start_of_burst(); bool rx_now(cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time); bool rx_at(cf_t* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); @@ -99,7 +99,6 @@ class radio { void set_rx_gain(float gain); void set_tx_rx_gain_offset(float offset); double set_rx_gain_th(float gain); - void set_master_clock_rate(double rate); void set_freq_offset(double freq); void set_tx_freq(uint32_t chan, double freq); @@ -138,7 +137,6 @@ class radio { uint32_t burst_preamble_samples; double burst_preamble_time_rounded; // preamble time rounded to sample time cf_t* zeros; - double master_clock_rate; double cur_tx_srate; double tx_adv_sec; // Transmission time advance to compensate for antenna->timestamp delay diff --git a/lib/include/srslte/radio/radio_multi.h b/lib/include/srslte/radio/radio_multi.h index 93aa34371..04453b2ae 100644 --- a/lib/include/srslte/radio/radio_multi.h +++ b/lib/include/srslte/radio/radio_multi.h @@ -57,6 +57,10 @@ public: bool is_init() override { return radios.at(0)->is_init(); } void reset() override { return radios.at(0)->reset(); } bool is_continuous_tx() override { return radios.at(0)->is_continuous_tx(); } + bool get_is_start_of_burst(const uint32_t& radio_idx) override + { + return radios.at(radio_idx)->get_is_start_of_burst(); + } bool tx(const uint32_t& radio_idx, cf_t* buffer[SRSLTE_MAX_PORTS], const uint32_t& nof_samples, @@ -64,7 +68,13 @@ public: { return radios.at(radio_idx)->tx(buffer, nof_samples, tx_time); } - void tx_end() override { return radios.at(0)->tx_end(); } + void tx_end() override + { + // Send Tx exd to all radios + for (auto& r : radios) { + r->tx_end(); + } + } bool rx_now(const uint32_t& radio_idx, cf_t* buffer[SRSLTE_MAX_PORTS], diff --git a/lib/include/srslte/srslte.h b/lib/include/srslte/srslte.h index 67fc07896..e7886118a 100644 --- a/lib/include/srslte/srslte.h +++ b/lib/include/srslte/srslte.h @@ -114,12 +114,13 @@ extern "C" { #include "srslte/phy/scrambling/scrambling.h" +#include "srslte/phy/sync/cfo.h" +#include "srslte/phy/sync/cp.h" #include "srslte/phy/sync/pss.h" +#include "srslte/phy/sync/refsignal_dl_sync.h" #include "srslte/phy/sync/sfo.h" #include "srslte/phy/sync/sss.h" #include "srslte/phy/sync/sync.h" -#include "srslte/phy/sync/cfo.h" -#include "srslte/phy/sync/cp.h" #ifdef __cplusplus } diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index dc13dbce3..3950805d4 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -22,17 +22,14 @@ #ifndef SRSLTE_PDCP_H #define SRSLTE_PDCP_H -#include "srslte/common/log.h" #include "srslte/common/common.h" +#include "srslte/common/log.h" #include "srslte/interfaces/ue_interfaces.h" -#include "srslte/upper/pdcp_entity.h" +#include "srslte/upper/pdcp_entity_lte.h" namespace srslte { -class pdcp - :public srsue::pdcp_interface_gw - ,public srsue::pdcp_interface_rlc - ,public srsue::pdcp_interface_rrc +class pdcp : public srsue::pdcp_interface_rlc, public srsue::pdcp_interface_rrc { public: pdcp(log* log_); @@ -45,29 +42,27 @@ public: // RRC interface void reestablish(); - void reestablish(uint32_t lcid); + void reestablish(uint32_t lcid); void reset(); - void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true); - void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu); - void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); - void add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); + void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true); + void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu); + void add_bearer(uint32_t lcid, pdcp_config_t cnfg); + void add_bearer_mrb(uint32_t lcid, pdcp_config_t cnfg); void del_bearer(uint32_t lcid); void change_lcid(uint32_t old_lcid, uint32_t new_lcid); - void config_security(uint32_t lcid, - uint8_t *k_rrc_enc, - uint8_t *k_rrc_int, - uint8_t *k_up_enc, + void config_security(uint32_t lcid, + uint8_t* k_rrc_enc, + uint8_t* k_rrc_int, + uint8_t* k_up_enc, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo); - void config_security_all(uint8_t *k_rrc_enc, - uint8_t *k_rrc_int, - uint8_t *k_up_enc, + void config_security_all(uint8_t* k_rrc_enc, + uint8_t* k_rrc_int, + uint8_t* k_up_enc, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo); void enable_integrity(uint32_t lcid); void enable_encryption(uint32_t lcid); - uint32_t get_dl_count(uint32_t lcid); - uint32_t get_ul_count(uint32_t lcid); // RLC interface void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu); @@ -81,11 +76,11 @@ private: srsue::rrc_interface_pdcp* rrc = nullptr; srsue::gw_interface_pdcp* gw = nullptr; - typedef std::map pdcp_map_t; - typedef std::pair pdcp_map_pair_t; + typedef std::map pdcp_map_t; + typedef std::pair pdcp_map_pair_t; log* pdcp_log = nullptr; - pdcp_map_t pdcp_array, pdcp_array_mrb; + pdcp_map_t pdcp_array, pdcp_array_mrb; pthread_rwlock_t rwlock; bool valid_lcid(uint32_t lcid); @@ -93,6 +88,4 @@ private: }; } // namespace srslte - - #endif // SRSLTE_PDCP_H diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h deleted file mode 100644 index 986d797f9..000000000 --- a/lib/include/srslte/upper/pdcp_entity.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2013-2019 Software Radio Systems Limited - * - * This file is part of srsLTE. - * - * srsLTE 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. - * - * srsLTE 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/. - * - */ - -#ifndef SRSLTE_PDCP_ENTITY_H -#define SRSLTE_PDCP_ENTITY_H - -#include "srslte/common/buffer_pool.h" -#include "srslte/common/log.h" -#include "srslte/common/common.h" -#include "srslte/interfaces/ue_interfaces.h" -#include "srslte/common/security.h" -#include "srslte/common/threads.h" -#include "pdcp_interface.h" - - -namespace srslte { - -/**************************************************************************** - * Structs and Defines - * Ref: 3GPP TS 36.323 v10.1.0 - ***************************************************************************/ - -#define PDCP_CONTROL_MAC_I 0x00000000 - -#define PDCP_PDU_TYPE_PDCP_STATUS_REPORT 0x0 -#define PDCP_PDU_TYPE_INTERSPERSED_ROHC_FEEDBACK_PACKET 0x1 - -typedef enum{ - PDCP_D_C_CONTROL_PDU = 0, - PDCP_D_C_DATA_PDU, - PDCP_D_C_N_ITEMS, -}pdcp_d_c_t; -static const char pdcp_d_c_text[PDCP_D_C_N_ITEMS][20] = {"Control PDU", - "Data PDU"}; - -/**************************************************************************** - * PDCP Entity interface - * Common interface for all PDCP entities - ***************************************************************************/ -class pdcp_entity : public pdcp_entity_interface -{ -public: - pdcp_entity(); - ~pdcp_entity(); - void init(srsue::rlc_interface_pdcp *rlc_, - srsue::rrc_interface_pdcp *rrc_, - srsue::gw_interface_pdcp *gw_, - srslte::log *log_, - uint32_t lcid_, - srslte_pdcp_config_t cfg_); - void reset(); - void reestablish(); - - bool is_active(); - - // RRC interface - void write_sdu(unique_byte_buffer_t sdu, bool blocking); - void config_security(uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, - uint8_t *k_up_enc_, - CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, - INTEGRITY_ALGORITHM_ID_ENUM integ_algo_); - void enable_integrity(); - void enable_encryption(); - uint32_t get_dl_count(); - uint32_t get_ul_count(); - - // RLC interface - void write_pdu(unique_byte_buffer_t pdu); - -private: - byte_buffer_pool* pool = byte_buffer_pool::get_instance(); - srslte::log* log = nullptr; - - srsue::rlc_interface_pdcp* rlc = nullptr; - srsue::rrc_interface_pdcp* rrc = nullptr; - srsue::gw_interface_pdcp* gw = nullptr; - - bool active = false; - uint32_t lcid = 0; - srslte_pdcp_config_t cfg = {}; - uint8_t sn_len_bytes = 0; - bool do_integrity = false; - bool do_encryption = false; - - uint32_t rx_count = 0; - uint32_t tx_count = 0; - uint8_t k_rrc_enc[32] = {}; - uint8_t k_rrc_int[32] = {}; - uint8_t k_up_enc[32] = {}; - - uint32_t rx_hfn = 0; - uint32_t next_pdcp_rx_sn = 0; - uint32_t reordering_window = 0; - uint32_t last_submitted_pdcp_rx_sn = 0; - uint32_t maximum_pdcp_sn = 0; - - CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0; - INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0; - - pthread_mutex_t mutex; - - void handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu); - void handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu); - - void integrity_generate(uint8_t* msg, uint32_t msg_len, uint8_t* mac); - bool integrity_verify(uint8_t* msg, uint32_t count, uint32_t msg_len, uint8_t* mac); - void cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint8_t* ct); - void cipher_decrypt(uint8_t* ct, uint32_t count, uint32_t ct_len, uint8_t* msg); -}; - -/**************************************************************************** - * Pack/Unpack helper functions - * Ref: 3GPP TS 36.323 v10.1.0 - ***************************************************************************/ - -void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu); -void pdcp_unpack_control_pdu(byte_buffer_t *sdu, uint32_t *sn); - -void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t *sdu); -void pdcp_unpack_data_pdu_short_sn(byte_buffer_t *sdu, uint32_t *sn); -void pdcp_pack_data_pdu_long_sn(uint32_t sn, byte_buffer_t *sdu); -void pdcp_unpack_data_pdu_long_sn(byte_buffer_t *sdu, uint32_t *sn); - -} // namespace srslte -#endif // SRSLTE_PDCP_ENTITY_H diff --git a/lib/include/srslte/upper/pdcp_entity_base.h b/lib/include/srslte/upper/pdcp_entity_base.h new file mode 100644 index 000000000..0d51f2eca --- /dev/null +++ b/lib/include/srslte/upper/pdcp_entity_base.h @@ -0,0 +1,133 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_PDCP_ENTITY_BASE_H +#define SRSLTE_PDCP_ENTITY_BASE_H + +#include "srslte/common/buffer_pool.h" +#include "srslte/common/common.h" +#include "srslte/common/log.h" +#include "srslte/common/security.h" +#include "srslte/common/threads.h" +#include "srslte/interfaces/ue_interfaces.h" +#include + +namespace srslte { + +/**************************************************************************** + * Structs and Defines common to both LTE and NR + * Ref: 3GPP TS 36.323 v10.1.0 and TS 38.323 v15.2.0 + ***************************************************************************/ + +#define PDCP_PDU_TYPE_PDCP_STATUS_REPORT 0x0 +#define PDCP_PDU_TYPE_INTERSPERSED_ROHC_FEEDBACK_PACKET 0x1 + +// Maximum supported PDCP SDU size is 9000 bytes. +// See TS 38.323 v15.2.0, section 4.3.1 +#define PDCP_MAX_SDU_SIZE 9000 + +typedef enum { + PDCP_D_C_CONTROL_PDU = 0, + PDCP_D_C_DATA_PDU, + PDCP_D_C_N_ITEMS, +} pdcp_d_c_t; +static const char pdcp_d_c_text[PDCP_D_C_N_ITEMS][20] = {"Control PDU", "Data PDU"}; + +/**************************************************************************** + * PDCP Entity interface + * Common interface for LTE and NR PDCP entities + ***************************************************************************/ +class pdcp_entity_base +{ +public: + pdcp_entity_base(); + virtual ~pdcp_entity_base(); + virtual void reset() = 0; + virtual void reestablish() = 0; + + bool is_active() { return active; } + bool is_srb() { return cfg.rb_type == PDCP_RB_IS_SRB; } + bool is_drb() { return cfg.rb_type == PDCP_RB_IS_DRB; } + + // RRC interface + void enable_integrity() { do_integrity = true; } + void enable_encryption() { do_encryption = true; } + + void config_security(uint8_t* k_rrc_enc_, + uint8_t* k_rrc_int_, + uint8_t* k_up_enc_, + uint8_t* k_up_int_, // NR Only, pass nullptr in LTE + CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, + INTEGRITY_ALGORITHM_ID_ENUM integ_algo_); + + // GW/SDAP/RRC interface + void write_sdu(unique_byte_buffer_t sdu, bool blocking); + + // RLC interface + void write_pdu(unique_byte_buffer_t pdu); + + // COUNT, HFN and SN helpers + uint32_t HFN(uint32_t count); + uint32_t SN(uint32_t count); + uint32_t COUNT(uint32_t hfn, uint32_t sn); + +protected: + srslte::log* log = nullptr; + + bool active = false; + uint32_t lcid = 0; + bool do_integrity = false; + bool do_encryption = false; + + pdcp_config_t cfg = {1, PDCP_RB_IS_DRB, SECURITY_DIRECTION_DOWNLINK, SECURITY_DIRECTION_UPLINK, PDCP_SN_LEN_12}; + + std::mutex mutex; + + uint8_t k_rrc_enc[32] = {}; + uint8_t k_rrc_int[32] = {}; + uint8_t k_up_enc[32] = {}; + uint8_t k_up_int[32] = {}; + + CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0; + INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0; + + void integrity_generate(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* mac); + bool integrity_verify(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* mac); + void cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* ct); + void cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t count, uint8_t* msg); +}; + +inline uint32_t pdcp_entity_base::HFN(uint32_t count) +{ + return (count >> cfg.sn_len); +} + +inline uint32_t pdcp_entity_base::SN(uint32_t count) +{ + return count & (0xFFFFFFFF >> (32 - cfg.sn_len)); +} + +inline uint32_t pdcp_entity_base::COUNT(uint32_t hfn, uint32_t sn) +{ + return (hfn << cfg.sn_len) | sn; +} +} // namespace srslte +#endif // SRSLTE_PDCP_ENTITY_BASE_H diff --git a/lib/include/srslte/upper/pdcp_entity_lte.h b/lib/include/srslte/upper/pdcp_entity_lte.h new file mode 100644 index 000000000..a6df1f52a --- /dev/null +++ b/lib/include/srslte/upper/pdcp_entity_lte.h @@ -0,0 +1,101 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_PDCP_ENTITY_LTE_H +#define SRSLTE_PDCP_ENTITY_LTE_H + +#include "srslte/common/buffer_pool.h" +#include "srslte/common/common.h" +#include "srslte/common/log.h" +#include "srslte/common/security.h" +#include "srslte/common/threads.h" +#include "srslte/interfaces/ue_interfaces.h" +#include "srslte/upper/pdcp_entity_base.h" + +namespace srslte { + +/**************************************************************************** + * Structs and Defines + * Ref: 3GPP TS 36.323 v10.1.0 + ***************************************************************************/ + +#define PDCP_CONTROL_MAC_I 0x00000000 + +/**************************************************************************** + * LTE PDCP Entity + * Class for LTE PDCP entities + ***************************************************************************/ +class pdcp_entity_lte final : public pdcp_entity_base +{ +public: + pdcp_entity_lte(); + ~pdcp_entity_lte(); + void init(srsue::rlc_interface_pdcp* rlc_, + srsue::rrc_interface_pdcp* rrc_, + srsue::gw_interface_pdcp* gw_, + srslte::log* log_, + uint32_t lcid_, + pdcp_config_t cfg_); + void reset(); + void reestablish(); + + // GW/RRC interface + void write_sdu(unique_byte_buffer_t sdu, bool blocking); + + uint32_t get_dl_count(); + uint32_t get_ul_count(); + + // RLC interface + void write_pdu(unique_byte_buffer_t pdu); + +private: + srsue::rlc_interface_pdcp* rlc = nullptr; + srsue::rrc_interface_pdcp* rrc = nullptr; + srsue::gw_interface_pdcp* gw = nullptr; + + uint32_t rx_count = 0; + uint32_t tx_count = 0; + + uint32_t rx_hfn = 0; + uint32_t next_pdcp_rx_sn = 0; + uint32_t reordering_window = 0; + uint32_t last_submitted_pdcp_rx_sn = 0; + uint32_t maximum_pdcp_sn = 0; + + void handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu); + void handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu); +}; + +/**************************************************************************** + * Pack/Unpack helper functions + * Ref: 3GPP TS 36.323 v10.1.0 + ***************************************************************************/ + +void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t* sdu); +void pdcp_unpack_control_pdu(byte_buffer_t* sdu, uint32_t* sn); + +void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t* sdu); +void pdcp_unpack_data_pdu_short_sn(byte_buffer_t* sdu, uint32_t* sn); +void pdcp_pack_data_pdu_long_sn(uint32_t sn, byte_buffer_t* sdu); +void pdcp_unpack_data_pdu_long_sn(byte_buffer_t* sdu, uint32_t* sn); + +} // namespace srslte +#endif // SRSLTE_PDCP_ENTITY_LTE_H diff --git a/lib/include/srslte/upper/pdcp_entity_nr.h b/lib/include/srslte/upper/pdcp_entity_nr.h new file mode 100644 index 000000000..d5e783f7b --- /dev/null +++ b/lib/include/srslte/upper/pdcp_entity_nr.h @@ -0,0 +1,84 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_PDCP_ENTITY_NR_H +#define SRSLTE_PDCP_ENTITY_NR_H + +#include "pdcp_entity_base.h" +#include "srslte/common/buffer_pool.h" +#include "srslte/common/common.h" +#include "srslte/common/interfaces_common.h" +#include "srslte/common/log.h" +#include "srslte/common/security.h" +#include "srslte/common/threads.h" + +namespace srslte { + +/**************************************************************************** + * NR PDCP Entity + * PDCP entity for 5G NR + ***************************************************************************/ +class pdcp_entity_nr : public pdcp_entity_base +{ +public: + pdcp_entity_nr(); + ~pdcp_entity_nr(); + void init(srsue::rlc_interface_pdcp* rlc_, + srsue::rrc_interface_pdcp* rrc_, + srsue::gw_interface_pdcp* gw_, + srslte::log* log_, + uint32_t lcid_, + pdcp_config_t cfg_); + void reset(); + void reestablish(); + + // RRC interface + void write_sdu(unique_byte_buffer_t sdu, bool blocking); + + uint32_t get_dl_count(); + uint32_t get_ul_count(); + + // RLC interface + void write_pdu(unique_byte_buffer_t pdu); + +private: + srsue::rlc_interface_pdcp* rlc = nullptr; + srsue::rrc_interface_pdcp* rrc = nullptr; + srsue::gw_interface_pdcp* gw = nullptr; + + // State variables: 3GPP TS 38.323 v15.2.0, section 7.1 + uint32_t tx_next = 0; // COUNT value of next SDU to be transmitted. + uint32_t rx_next = 0; // COUNT value of next SDU expected to be received. + uint32_t rx_deliv = 0; // COUNT value of first SDU not delivered to upper layers, but still waited for. + uint32_t rx_reord = 0; // COUNT value following the COUNT value of PDCP Data PDU which triggered t-Reordering. + + // Constants: 3GPP TS 38.323 v15.2.0, section 7.2 + uint32_t window_size = 0; + + // Packing/Unpacking Helper functions + uint32_t read_data_header(const unique_byte_buffer_t& sdu); + void write_data_header(const unique_byte_buffer_t& sdu, uint32_t sn); + void extract_mac(const unique_byte_buffer_t& sdu, uint8_t* mac); + void append_mac(const unique_byte_buffer_t& sdu, uint8_t* mac); +}; + +} // namespace srslte +#endif // SRSLTE_PDCP_ENTITY_NR_H diff --git a/lib/include/srslte/upper/pdcp_interface.h b/lib/include/srslte/upper/pdcp_interface.h deleted file mode 100644 index 1cbec9a00..000000000 --- a/lib/include/srslte/upper/pdcp_interface.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2013-2019 Software Radio Systems Limited - * - * This file is part of srsLTE. - * - * srsLTE 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. - * - * srsLTE 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/. - * - */ - -#ifndef SRSLTE_PDCP_INTERFACE_H -#define SRSLTE_PDCP_INTERFACE_H - -#include "srslte/common/buffer_pool.h" -#include "srslte/common/log.h" -#include "srslte/common/common.h" -#include "srslte/interfaces/ue_interfaces.h" -#include "srslte/common/security.h" -#include "srslte/common/threads.h" - - -namespace srslte { - -/**************************************************************************** - * Virtual PDCP interface common for all PDCP entities - ***************************************************************************/ -class pdcp_entity_interface -{ -public: - virtual ~pdcp_entity_interface() {}; - virtual void init(srsue::rlc_interface_pdcp *rlc_, - srsue::rrc_interface_pdcp *rrc_, - srsue::gw_interface_pdcp *gw_, - srslte::log *log_, - uint32_t lcid_, - srslte_pdcp_config_t cfg_) = 0; - virtual void reset() = 0; - virtual void reestablish() = 0; - virtual bool is_active() = 0; - - // RRC interface - virtual void write_sdu(unique_byte_buffer_t sdu, bool blocking) = 0; - virtual void config_security(uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, - uint8_t *k_up_enc_, - CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, - INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; - virtual void enable_integrity() = 0; - virtual void enable_encryption() = 0; - virtual uint32_t get_dl_count() = 0; - virtual uint32_t get_ul_count() = 0; - - // RLC interface - virtual void write_pdu(unique_byte_buffer_t pdu) = 0; -}; - -} // namespace srslte - - -#endif // SRSLTE_PDCP_INTERFACE_H diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 48457a1ef..9bd4a28da 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -45,13 +45,10 @@ class rlc public: rlc(log* rlc_log_); virtual ~rlc(); - void init(srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - mac_interface_timers* mac_timers_, - uint32_t lcid_); + void init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srslte::timers* timers_, uint32_t lcid_); void stop(); - void get_metrics(rlc_metrics_t &m); + void get_metrics(rlc_metrics_t& m); // PDCP interface void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true); @@ -92,9 +89,9 @@ private: srslte::log* rlc_log = nullptr; srsue::pdcp_interface_rlc* pdcp = nullptr; srsue::rrc_interface_rlc* rrc = nullptr; - srslte::mac_interface_timers* mac_timers = nullptr; + srslte::timers* timers = nullptr; - typedef std::map rlc_map_t; + typedef std::map rlc_map_t; typedef std::pair rlc_map_pair_t; rlc_map_t rlc_array, rlc_array_mrb; @@ -109,7 +106,6 @@ private: bool valid_lcid_mrb(uint32_t lcid); }; -} // namespace srsue - +} // namespace srslte #endif // SRSLTE_RLC_H diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index e41a3d70a..103aaa3d3 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -64,12 +64,11 @@ struct rlc_amd_retx_t{ class rlc_am : public rlc_common { public: - rlc_am(srslte::log* log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srslte::mac_interface_timers* mac_timers_); - ~rlc_am(); + rlc_am(srslte::log* log_, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srslte::timers* timers_); bool configure(rlc_config_t cfg_); void reestablish(); void stop(); @@ -223,7 +222,7 @@ private: void handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_header_t &header); void handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_header_t &header); void reassemble_rx_sdus(); - bool inside_rx_window(uint16_t sn); + bool inside_rx_window(const int16_t sn); void debug_state(); void print_rx_segments(); bool add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pdu_t *segment); @@ -276,13 +275,13 @@ private: }; // Common variables needed/provided by parent class - srsue::rrc_interface_rlc* rrc = nullptr; - srslte::log* log = nullptr; - srsue::pdcp_interface_rlc* pdcp = nullptr; - mac_interface_timers* mac_timers = nullptr; - uint32_t lcid = 0; - rlc_config_t cfg = {}; - std::string rb_name; + srsue::rrc_interface_rlc* rrc = nullptr; + srslte::log* log = nullptr; + srsue::pdcp_interface_rlc* pdcp = nullptr; + srslte::timers* timers = nullptr; + uint32_t lcid = 0; + rlc_config_t cfg = {}; + std::string rb_name; static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested @@ -307,6 +306,7 @@ int rlc_am_write_status_pdu(rlc_status_pdu_t *status, uint8_t *payload); uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t *header); uint32_t rlc_am_packed_length(rlc_status_pdu_t *status); uint32_t rlc_am_packed_length(rlc_amd_retx_t retx); +bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status); bool rlc_am_is_control_pdu(byte_buffer_t *pdu); bool rlc_am_is_control_pdu(uint8_t *payload); bool rlc_am_is_pdu_segment(uint8_t *payload); @@ -319,5 +319,4 @@ bool rlc_am_not_start_aligned(const uint8_t fi); } // namespace srslte - #endif // SRSLTE_RLC_AM_H diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index 4ab308fe5..1b3875552 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -48,6 +48,28 @@ static const char rlc_fi_field_text[RLC_FI_FIELD_N_ITEMS][32] = {"Start and end "Not start aligned", "Not start or end aligned"}; +enum class rlc_nr_si_field_t : unsigned { + full_sdu = 0b00, + first_segment = 0b01, + last_segment = 0b10, + neither_first_nor_last_segment = 0b11, + nulltype +}; +inline std::string to_string(const rlc_nr_si_field_t& si) +{ + constexpr static const char* options[] = {"Data field contains full SDU", + "Data field contains first segment of SDU", + "Data field contains last segment of SDU", + "Data field contains neither first nor last segment of SDU"}; + return enum_to_text(options, (uint32_t)rlc_nr_si_field_t::nulltype, (uint32_t)si); +} + +static inline uint8_t operator&(rlc_nr_si_field_t lhs, int rhs) +{ + return static_cast(static_cast::type>(lhs) & + static_cast::type>(rhs)); +} + typedef enum{ RLC_DC_FIELD_CONTROL_PDU = 0, RLC_DC_FIELD_DATA_PDU, @@ -65,6 +87,13 @@ typedef struct{ uint16_t li[RLC_AM_WINDOW_SIZE]; // Array of length indicators }rlc_umd_pdu_header_t; +typedef struct { + rlc_nr_si_field_t si; // Segmentation info + rlc_um_nr_sn_size_t sn_size; // Sequence number size (6 or 12 bits) + uint16_t sn; // Sequence number + uint16_t so; // Sequence offset +} rlc_um_nr_pdu_header_t; + // AMD PDU Header struct rlc_amd_pdu_header_t{ rlc_dc_field_t dc; // Data or control @@ -125,7 +154,7 @@ struct rlc_status_nack_t{ // STATUS PDU struct rlc_status_pdu_t{ - uint16_t ack_sn; + uint16_t ack_sn; // SN of the next not received RLC Data PDU uint32_t N_nack; rlc_status_nack_t nacks[RLC_AM_WINDOW_SIZE]; diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index 107b1310b..4a39ec122 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -34,12 +34,12 @@ namespace srslte { class rlc_tm : public rlc_common { public: - rlc_tm(srslte::log* log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srslte::mac_interface_timers* mac_timers_, - uint32_t queue_len = 16); + rlc_tm(srslte::log* log_, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srslte::timers* timers_, + uint32_t queue_len = 16); ~rlc_tm(); bool configure(rlc_config_t cnfg); void stop(); @@ -78,7 +78,6 @@ private: rlc_tx_queue ul_queue; }; -} // namespace srsue - +} // namespace srslte #endif // SRSLTE_RLC_TM_H diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index 26cc41f70..0171d50b8 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -23,13 +23,14 @@ #define SRSLTE_RLC_UM_H #include "srslte/common/buffer_pool.h" -#include "srslte/common/log.h" #include "srslte/common/common.h" +#include "srslte/common/log.h" #include "srslte/interfaces/ue_interfaces.h" -#include "srslte/upper/rlc_tx_queue.h" #include "srslte/upper/rlc_common.h" -#include +#include "srslte/upper/rlc_tx_queue.h" #include +#include +#include #include namespace srslte { @@ -39,6 +40,11 @@ struct rlc_umd_pdu_t{ unique_byte_buffer_t buf; }; +typedef struct { + rlc_um_nr_pdu_header_t header; + unique_byte_buffer_t buf; +} rlc_umd_pdu_nr_t; + class rlc_um :public rlc_common { @@ -47,7 +53,7 @@ public: uint32_t lcid_, srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, - mac_interface_timers* mac_timers_); + srslte::timers* timers_); ~rlc_um(); bool configure(rlc_config_t cnfg); void reestablish(); @@ -73,14 +79,13 @@ public: void reset_metrics(); private: - - // Transmitter sub-class - class rlc_um_tx + // Transmitter sub-class base + class rlc_um_tx_base { public: - rlc_um_tx(srslte::log* log_); - ~rlc_um_tx(); - bool configure(rlc_config_t cfg, std::string rb_name); + rlc_um_tx_base(srslte::log* log_); + virtual ~rlc_um_tx_base(); + virtual bool configure(rlc_config_t cfg, std::string rb_name) = 0; int build_data_pdu(uint8_t *payload, uint32_t nof_bytes); void stop(); void reestablish(); @@ -92,7 +97,7 @@ private: bool has_data(); uint32_t get_buffer_state(); - private: + protected: byte_buffer_pool* pool = nullptr; srslte::log* log = nullptr; std::string rb_name; @@ -101,41 +106,71 @@ private: * Configurable parameters * Ref: 3GPP TS 36.322 v10.0.0 Section 7 ***************************************************************************/ - rlc_um_config_t cfg = {}; + rlc_config_t cfg = {}; // TX SDU buffers rlc_tx_queue tx_sdu_queue; unique_byte_buffer_t tx_sdu; + // Mutexes + std::mutex mutex; + + bool tx_enabled = false; + + uint32_t num_tx_bytes = 0; + + virtual int build_data_pdu(unique_byte_buffer_t pdu, uint8_t* payload, uint32_t nof_bytes) = 0; + + // helper functions + virtual void debug_state() = 0; + const char* get_rb_name(); + }; + + // Transmitter sub-class for LTE + class rlc_um_tx : public rlc_um_tx_base + { + public: + rlc_um_tx(srslte::log* log_); + + bool configure(rlc_config_t cfg, std::string rb_name); + int build_data_pdu(unique_byte_buffer_t pdu, uint8_t* payload, uint32_t nof_bytes); + + private: /**************************************************************************** * State variables and counters * Ref: 3GPP TS 36.322 v10.0.0 Section 7 ***************************************************************************/ uint32_t vt_us = 0; // Send state. SN to be assigned for next PDU. - // Mutexes - pthread_mutex_t mutex; + void debug_state(); + }; - bool tx_enabled = false; + // Transmitter sub-class for NR + class rlc_um_tx_nr : public rlc_um_tx_base + { + public: + rlc_um_tx_nr(srslte::log* log_); - uint32_t num_tx_bytes = 0; + bool configure(rlc_config_t cfg, std::string rb_name); + int build_data_pdu(unique_byte_buffer_t pdu, uint8_t* payload, uint32_t nof_bytes); + + private: + uint32_t TX_Next = 0; // send state as defined in TS 38.322 v15.3 Section 7 - // helper functions void debug_state(); - const char* get_rb_name(); }; // Receiver sub-class class rlc_um_rx : public timer_callback { public: - rlc_um_rx(srslte::log* log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srslte::mac_interface_timers* mac_timers_); + rlc_um_rx(srslte::log* log_, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srslte::timers* timers_); ~rlc_um_rx(); - void stop(); - void reestablish(); + void stop(); + void reestablish(); bool configure(rlc_config_t cfg, std::string rb_name); void handle_data_pdu(uint8_t *payload, uint32_t nof_bytes); void reassemble_rx_sdus(); @@ -150,16 +185,16 @@ private: private: void reset(); - byte_buffer_pool* pool = nullptr; - srslte::log* log = nullptr; - mac_interface_timers* mac_timers = nullptr; - std::string rb_name; + byte_buffer_pool* pool = nullptr; + srslte::log* log = nullptr; + srslte::timers* timers = nullptr; + std::string rb_name; /**************************************************************************** * Configurable parameters * Ref: 3GPP TS 36.322 v10.0.0 Section 7 ***************************************************************************/ - rlc_um_config_t cfg = {}; + rlc_config_t cfg = {}; // Rx window std::map rx_window; @@ -182,7 +217,7 @@ private: uint32_t lcid = 0; // Mutexes - pthread_mutex_t mutex; + std::mutex mutex; bool rx_enabled = false; @@ -209,7 +244,7 @@ private: std::string get_rb_name(srsue::rrc_interface_rlc *rrc, uint32_t lcid, bool is_mrb); // Rx and Tx objects - rlc_um_tx tx; + std::unique_ptr tx; rlc_um_rx rx; }; @@ -225,7 +260,23 @@ uint32_t rlc_um_packed_length(rlc_umd_pdu_header_t *header); bool rlc_um_start_aligned(uint8_t fi); bool rlc_um_end_aligned(uint8_t fi); -} // namespace srsue +/**************************************************************************** + * Header pack/unpack helper functions for NR + * Ref: 3GPP TS 38.322 v15.3.0 Section 6.2.2.3 + ***************************************************************************/ +uint32_t rlc_um_nr_read_data_pdu_header(const byte_buffer_t* pdu, + const rlc_um_nr_sn_size_t sn_size, + rlc_um_nr_pdu_header_t* header); + +uint32_t rlc_um_nr_read_data_pdu_header(const uint8_t* payload, + const uint32_t nof_bytes, + const rlc_um_nr_sn_size_t sn_size, + rlc_um_nr_pdu_header_t* header); + +uint32_t rlc_um_nr_write_data_pdu_header(const rlc_um_nr_pdu_header_t& header, byte_buffer_t* pdu); + +uint32_t rlc_um_nr_packed_length(const rlc_um_nr_pdu_header_t& header); +} // namespace srslte #endif // SRSLTE_RLC_UM_H diff --git a/lib/src/asn1/asn1_utils.cc b/lib/src/asn1/asn1_utils.cc index 18ca4800a..d9b1da4d1 100644 --- a/lib/src/asn1/asn1_utils.cc +++ b/lib/src/asn1/asn1_utils.cc @@ -83,16 +83,6 @@ void log_error_code(SRSASN_CODE code, const char* filename, int line) bit_ref *********************/ -bit_ref::bit_ref() : ptr(NULL), offset(0), start_ptr(NULL), max_ptr(NULL) {} - -bit_ref::bit_ref(uint8_t* start_ptr_, uint32_t max_size_) : - ptr(start_ptr_), - offset(0), - start_ptr(start_ptr_), - max_ptr(max_size_ + start_ptr_) -{ -} - int bit_ref::distance(const bit_ref& other) const { return ((int)offset - (int)other.offset) + 8 * ((int)(ptr - other.ptr)); @@ -116,6 +106,10 @@ int bit_ref::distance_bytes() const SRSASN_CODE bit_ref::pack(uint32_t val, uint32_t n_bits) { + if (n_bits >= 32) { + srsasn_log_print(LOG_LEVEL_ERROR, "This method only supports packing up to 32 bits\n"); + return SRSASN_ERROR_ENCODE_FAIL; + } uint32_t mask; while (n_bits > 0) { if (ptr >= max_ptr) { @@ -141,8 +135,33 @@ SRSASN_CODE bit_ref::pack(uint32_t val, uint32_t n_bits) return SRSASN_SUCCESS; } +SRSASN_CODE bit_ref::pack_bytes(const uint8_t* buf, uint32_t n_bytes) +{ + if (n_bytes == 0) { + return SRSASN_SUCCESS; + } + if (ptr + n_bytes >= max_ptr) { + srsasn_log_print(LOG_LEVEL_ERROR, "Buffer size limit was achieved\n"); + return SRSASN_ERROR_ENCODE_FAIL; + } + if (offset == 0) { + // Aligned case + memcpy(ptr, buf, n_bytes); + ptr += n_bytes; + } else { + for (uint32_t i = 0; i < n_bytes; ++i) { + pack(buf[i], 8); + } + } + return SRSASN_SUCCESS; +} + ValOrError unpack_bits(uint8_t*& ptr, uint8_t& offset, uint8_t* max_ptr, uint32_t n_bits) { + if (n_bits > 32) { + srsasn_log_print(LOG_LEVEL_ERROR, "This method only supports unpacking up to 32 bits\n"); + return {0, SRSASN_ERROR_DECODE_FAIL}; + } uint32_t val = 0; while (n_bits > 0) { if (ptr >= max_ptr) { @@ -165,6 +184,27 @@ ValOrError unpack_bits(uint8_t*& ptr, uint8_t& offset, uint8_t* max_ptr, uint32_ return ValOrError(val, SRSASN_SUCCESS); } +SRSASN_CODE bit_ref::unpack_bytes(uint8_t* buf, uint32_t n_bytes) +{ + if (n_bytes == 0) { + return SRSASN_SUCCESS; + } + if (ptr + n_bytes >= max_ptr) { + srsasn_log_print(LOG_LEVEL_ERROR, "Buffer size limit was achieved\n"); + return SRSASN_ERROR_DECODE_FAIL; + } + if (offset == 0) { + // Aligned case + memcpy(buf, ptr, n_bytes); + ptr += n_bytes; + } else { + for (uint32_t i = 0; i < n_bytes; ++i) { + unpack(buf[i], 8); + } + } + return SRSASN_SUCCESS; +} + SRSASN_CODE bit_ref::align_bytes() { if (offset == 0) @@ -193,6 +233,21 @@ SRSASN_CODE bit_ref::align_bytes_zero() return SRSASN_SUCCESS; } +SRSASN_CODE bit_ref::advance_bits(uint32_t n_bits) +{ + uint32_t extra_bits = (offset + n_bits) % 8; + uint32_t bytes_required = ceilf((offset + n_bits) / 8.0f); + uint32_t bytes_offset = floorf((offset + n_bits) / 8.0f); + + if (ptr + bytes_required >= max_ptr) { + srsasn_log_print(LOG_LEVEL_ERROR, "Buffer size limit was achieved\n"); + return SRSASN_ERROR_DECODE_FAIL; + } + ptr += bytes_offset; + offset = extra_bits; + return SRSASN_SUCCESS; +} + void bit_ref::set(uint8_t* start_ptr_, uint32_t max_size_) { ptr = start_ptr_; @@ -370,10 +425,6 @@ template SRSASN_CODE unpack_unalign_integer(uint16_t& n, bit_ref& bref template SRSASN_CODE unpack_unalign_integer(uint32_t& n, bit_ref& bref, uint32_t lb, uint32_t ub); template SRSASN_CODE unpack_unalign_integer(uint64_t& n, bit_ref& bref, uint64_t lb, uint64_t ub); -template -UnalignedIntegerPacker::UnalignedIntegerPacker(IntType lb_, IntType ub_) : lb(lb_), ub(ub_) -{ -} template SRSASN_CODE UnalignedIntegerPacker::pack(bit_ref& bref, IntType n) const { @@ -921,86 +972,83 @@ void log_invalid_choice_id(uint32_t val, const char* choice_type) ext group *********************/ -ext_groups_header::ext_groups_header(uint32_t max_nof_groups, uint32_t nof_nogroups_) : nof_nogroups(nof_nogroups_) +bool& ext_groups_packer_guard::operator[](uint32_t idx) { - if (max_nof_groups > 20) { - srsasn_log_print(LOG_LEVEL_ERROR, "increase the size of ext group packer/unpacker\n"); - } - groups.resize(max_nof_groups); - for (uint32_t i = 0; i < groups.size(); ++i) { - groups[i] = false; + if (idx >= groups.size()) { + uint32_t prev_size = groups.size(); + groups.resize(idx + 1); + std::fill(&groups[prev_size], &groups[groups.size()], false); } - nof_groups = groups.size() + 1; // unset -} - -bool& ext_groups_header::operator[](uint32_t idx) -{ return groups[idx]; } -SRSASN_CODE ext_groups_header::pack_nof_groups(bit_ref& bref) const +SRSASN_CODE ext_groups_packer_guard::pack(asn1::bit_ref& bref) const { - nof_groups = 0; - for (uint32_t i = 0; i < groups.size(); ++i) { + // pack number of groups + int32_t i = groups.size() - 1; + for (; i >= 0; --i) { if (groups[i]) { - nof_groups = i + 1; + break; } } - if (nof_groups > groups.size()) { - srsasn_log_print(LOG_LEVEL_ERROR, "Exceeded maximum number of groups (%d>%d)\n", nof_groups, groups.size()); - return SRSASN_ERROR_ENCODE_FAIL; + uint32_t nof_groups = (uint32_t)i + 1u; + HANDLE_CODE(pack_norm_small_integer(bref, nof_groups - 1)); + + // pack each group presence flag + for (uint32_t j = 0; j < nof_groups; ++j) { + HANDLE_CODE(bref.pack(groups[j], 1)); } - HANDLE_CODE(pack_norm_small_integer(bref, nof_groups + nof_nogroups - 1)); return SRSASN_SUCCESS; } -SRSASN_CODE ext_groups_header::pack_group_flags(bit_ref& bref) const +ext_groups_unpacker_guard::ext_groups_unpacker_guard(uint32_t nof_supported_groups_) : + nof_supported_groups(nof_supported_groups_) { - if (nof_groups > groups.size()) { - srsasn_log_print(LOG_LEVEL_ERROR, "Exceeded maximum number of groups (%d>%d)\n", nof_groups, groups.size()); - return SRSASN_ERROR_ENCODE_FAIL; - } - for (uint32_t i = 0; i < nof_groups; ++i) { - HANDLE_CODE(bref.pack(groups[i], 1)); + resize(nof_supported_groups); +} + +bool& ext_groups_unpacker_guard::operator[](uint32_t idx) +{ + if (idx >= groups.size()) { + // only resizes for unknown extensions + resize(idx + 1); } - return SRSASN_SUCCESS; + return groups[idx]; } -SRSASN_CODE ext_groups_header::pack(bit_ref& bref) const +void ext_groups_unpacker_guard::resize(uint32_t new_size) { - HANDLE_CODE(pack_nof_groups(bref)); - return pack_group_flags(bref); + // always grows + uint32_t prev_size = groups.size(); + groups.resize(std::max(new_size, nof_supported_groups)); + std::fill(&groups[prev_size], &groups[groups.size()], false); } -SRSASN_CODE ext_groups_header::unpack_nof_groups(bit_ref& bref) +ext_groups_unpacker_guard::~ext_groups_unpacker_guard() { - HANDLE_CODE(unpack_norm_small_integer(nof_groups, bref)); - nof_groups += 1 - nof_nogroups; - if (nof_groups > groups.size()) { - srsasn_log_print(LOG_LEVEL_ERROR, "Exceeded maximum number of groups (%d>%d)\n", nof_groups, groups.size()); - return SRSASN_ERROR_DECODE_FAIL; + // consume all the unknown extensions + for (uint32_t i = nof_supported_groups; i < nof_unpacked_groups; ++i) { + if (groups[i]) { + varlength_field_unpack_guard scope(*bref_tracker); + } } - return SRSASN_SUCCESS; } -SRSASN_CODE ext_groups_header::unpack_group_flags(bit_ref& bref) +SRSASN_CODE ext_groups_unpacker_guard::unpack(bit_ref& bref) { - if (nof_groups > groups.size()) { - srsasn_log_print(LOG_LEVEL_ERROR, "Exceeded maximum number of groups (%d>%d)\n", nof_groups, groups.size()); - return SRSASN_ERROR_DECODE_FAIL; - } - for (uint32_t i = 0; i < nof_groups; ++i) { + bref_tracker = &bref; + // unpack nof of ext groups + HANDLE_CODE(unpack_norm_small_integer(nof_unpacked_groups, bref)); + nof_unpacked_groups += 1; + resize(nof_unpacked_groups); + + // unpack each group presence flag + for (uint32_t i = 0; i < nof_unpacked_groups; ++i) { HANDLE_CODE(bref.unpack(groups[i], 1)); } return SRSASN_SUCCESS; } -SRSASN_CODE ext_groups_header::unpack(bit_ref& bref) -{ - HANDLE_CODE(unpack_nof_groups(bref)); - return unpack_group_flags(bref); -} - /********************* Open Field *********************/ diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 24dfe48bf..d7b06ae77 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -6433,12 +6433,27 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_request_msg(LIBLTE_BYTE_MSG_STRUCT* Document Reference: 24.301 v10.2.0 Section 8.2.19 *********************************************************************/ LIBLTE_ERROR_ENUM liblte_mme_pack_identity_response_msg(LIBLTE_MME_ID_RESPONSE_MSG_STRUCT* id_resp, + uint8 sec_hdr_type, + uint32 count, LIBLTE_BYTE_MSG_STRUCT* msg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8* msg_ptr = msg->msg; if (id_resp != NULL && msg != NULL) { + if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + // Protocol Discriminator and Security Header Type *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); msg_ptr++; diff --git a/lib/src/asn1/rrc_asn1.cc b/lib/src/asn1/rrc_asn1.cc index e7e866018..05b60823b 100644 --- a/lib/src/asn1/rrc_asn1.cc +++ b/lib/src/asn1/rrc_asn1.cc @@ -26,8 +26,8 @@ using namespace asn1; using namespace asn1::rrc; /******************************************************************************* -/* Helper Functions -/******************************************************************************/ + * Helper Functions + ******************************************************************************/ #define rrc_asn1_warn_assert(cond, file, line) \ if ((cond)) { \ @@ -40,8 +40,8 @@ static void log_invalid_choice_id(uint32_t val, const char* choice_type) } /******************************************************************************* -/* Struct Methods -/******************************************************************************/ + * Struct Methods + ******************************************************************************/ // PHICH-Config ::= SEQUENCE SRSASN_CODE phich_cfg_s::pack(bit_ref& bref) const @@ -1366,24 +1366,20 @@ SRSASN_CODE sl_pssch_tx_cfg_r14_s::pack(bit_ref& bref) const HANDLE_CODE(params_below_thres_r14.pack(bref)); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - params_above_thres_v1530_present != (params_above_thres_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= params_above_thres_v1530_present; - rrc_asn1_warn_assert( - params_below_thres_v1530_present != (params_below_thres_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= params_below_thres_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= params_above_thres_v1530.is_present(); + group_flags[0] |= params_below_thres_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(params_above_thres_v1530_present, 1)); - HANDLE_CODE(bref.pack(params_below_thres_v1530_present, 1)); - if (params_above_thres_v1530_present) { + HANDLE_CODE(bref.pack(params_above_thres_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(params_below_thres_v1530.is_present(), 1)); + if (params_above_thres_v1530.is_present()) { HANDLE_CODE(params_above_thres_v1530->pack(bref)); } - if (params_below_thres_v1530_present) { + if (params_below_thres_v1530.is_present()) { HANDLE_CODE(params_below_thres_v1530->pack(bref)); } } @@ -1403,20 +1399,22 @@ SRSASN_CODE sl_pssch_tx_cfg_r14_s::unpack(bit_ref& bref) HANDLE_CODE(params_below_thres_r14.unpack(bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool params_above_thres_v1530_present; HANDLE_CODE(bref.unpack(params_above_thres_v1530_present, 1)); + params_above_thres_v1530.set_present(params_above_thres_v1530_present); + bool params_below_thres_v1530_present; HANDLE_CODE(bref.unpack(params_below_thres_v1530_present, 1)); - if (params_above_thres_v1530_present) { - params_above_thres_v1530 = make_copy_ptr(sl_pssch_tx_params_v1530_s()); + params_below_thres_v1530.set_present(params_below_thres_v1530_present); + if (params_above_thres_v1530.is_present()) { HANDLE_CODE(params_above_thres_v1530->unpack(bref)); } - if (params_below_thres_v1530_present) { - params_below_thres_v1530 = make_copy_ptr(sl_pssch_tx_params_v1530_s()); + if (params_below_thres_v1530.is_present()) { HANDLE_CODE(params_below_thres_v1530->unpack(bref)); } } @@ -1435,15 +1433,11 @@ void sl_pssch_tx_cfg_r14_s::to_json(json_writer& j) const j.write_fieldname("parametersBelowThres-r14"); params_below_thres_r14.to_json(j); if (ext) { - rrc_asn1_warn_assert( - params_above_thres_v1530_present != (params_above_thres_v1530.get() != NULL), __FILE__, __LINE__); - if (params_above_thres_v1530_present) { + if (params_above_thres_v1530.is_present()) { j.write_fieldname("parametersAboveThres-v1530"); params_above_thres_v1530->to_json(j); } - rrc_asn1_warn_assert( - params_below_thres_v1530_present != (params_below_thres_v1530.get() != NULL), __FILE__, __LINE__); - if (params_below_thres_v1530_present) { + if (params_below_thres_v1530.is_present()) { j.write_fieldname("parametersBelowThres-v1530"); params_below_thres_v1530->to_json(j); } @@ -2179,24 +2173,20 @@ SRSASN_CODE sl_comm_res_pool_v2x_r14_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - sl_min_t2_value_list_r15_present != (sl_min_t2_value_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= sl_min_t2_value_list_r15_present; - rrc_asn1_warn_assert( - cbr_pssch_tx_cfg_list_v1530_present != (cbr_pssch_tx_cfg_list_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cbr_pssch_tx_cfg_list_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= sl_min_t2_value_list_r15.is_present(); + group_flags[0] |= cbr_pssch_tx_cfg_list_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(sl_min_t2_value_list_r15_present, 1)); - HANDLE_CODE(bref.pack(cbr_pssch_tx_cfg_list_v1530_present, 1)); - if (sl_min_t2_value_list_r15_present) { + HANDLE_CODE(bref.pack(sl_min_t2_value_list_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(cbr_pssch_tx_cfg_list_v1530.is_present(), 1)); + if (sl_min_t2_value_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *sl_min_t2_value_list_r15, 1, 8)); } - if (cbr_pssch_tx_cfg_list_v1530_present) { + if (cbr_pssch_tx_cfg_list_v1530.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *cbr_pssch_tx_cfg_list_v1530, 1, 8)); } } @@ -2262,20 +2252,22 @@ SRSASN_CODE sl_comm_res_pool_v2x_r14_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool sl_min_t2_value_list_r15_present; HANDLE_CODE(bref.unpack(sl_min_t2_value_list_r15_present, 1)); + sl_min_t2_value_list_r15.set_present(sl_min_t2_value_list_r15_present); + bool cbr_pssch_tx_cfg_list_v1530_present; HANDLE_CODE(bref.unpack(cbr_pssch_tx_cfg_list_v1530_present, 1)); - if (sl_min_t2_value_list_r15_present) { - sl_min_t2_value_list_r15 = make_copy_ptr(sl_min_t2_value_list_r15_l()); + cbr_pssch_tx_cfg_list_v1530.set_present(cbr_pssch_tx_cfg_list_v1530_present); + if (sl_min_t2_value_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*sl_min_t2_value_list_r15, bref, 1, 8)); } - if (cbr_pssch_tx_cfg_list_v1530_present) { - cbr_pssch_tx_cfg_list_v1530 = make_copy_ptr(sl_cbr_pppp_tx_cfg_list_v1530_l()); + if (cbr_pssch_tx_cfg_list_v1530.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*cbr_pssch_tx_cfg_list_v1530, bref, 1, 8)); } } @@ -2344,18 +2336,14 @@ void sl_comm_res_pool_v2x_r14_s::to_json(json_writer& j) const j.end_array(); } if (ext) { - rrc_asn1_warn_assert( - sl_min_t2_value_list_r15_present != (sl_min_t2_value_list_r15.get() != NULL), __FILE__, __LINE__); - if (sl_min_t2_value_list_r15_present) { + if (sl_min_t2_value_list_r15.is_present()) { j.start_array("sl-MinT2ValueList-r15"); for (uint32_t i1 = 0; i1 < sl_min_t2_value_list_r15->size(); ++i1) { ((*sl_min_t2_value_list_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - cbr_pssch_tx_cfg_list_v1530_present != (cbr_pssch_tx_cfg_list_v1530.get() != NULL), __FILE__, __LINE__); - if (cbr_pssch_tx_cfg_list_v1530_present) { + if (cbr_pssch_tx_cfg_list_v1530.is_present()) { j.start_array("cbr-pssch-TxConfigList-v1530"); for (uint32_t i1 = 0; i1 < cbr_pssch_tx_cfg_list_v1530->size(); ++i1) { ((*cbr_pssch_tx_cfg_list_v1530)[i1]).to_json(j); @@ -2416,7 +2404,7 @@ SRSASN_CODE sl_sync_cfg_nfreq_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); + ext_groups_packer_guard group_flags; group_flags[0] |= sync_offset_ind_v1430_present; group_flags[0] |= gnss_sync_r14_present; group_flags[1] |= sync_offset_ind2_r14_present; @@ -2425,7 +2413,7 @@ SRSASN_CODE sl_sync_cfg_nfreq_r13_s::pack(bit_ref& bref) const group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sync_offset_ind_v1430_present, 1)); HANDLE_CODE(bref.pack(gnss_sync_r14_present, 1)); @@ -2434,7 +2422,7 @@ SRSASN_CODE sl_sync_cfg_nfreq_r13_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sync_offset_ind2_r14_present, 1)); HANDLE_CODE(bref.pack(sync_offset_ind3_r14_present, 1)); @@ -2446,7 +2434,7 @@ SRSASN_CODE sl_sync_cfg_nfreq_r13_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(slss_tx_disabled_r15_present, 1)); } @@ -2479,11 +2467,11 @@ SRSASN_CODE sl_sync_cfg_nfreq_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sync_offset_ind_v1430_present, 1)); HANDLE_CODE(bref.unpack(gnss_sync_r14_present, 1)); @@ -2492,7 +2480,7 @@ SRSASN_CODE sl_sync_cfg_nfreq_r13_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sync_offset_ind2_r14_present, 1)); HANDLE_CODE(bref.unpack(sync_offset_ind3_r14_present, 1)); @@ -2504,7 +2492,7 @@ SRSASN_CODE sl_sync_cfg_nfreq_r13_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(slss_tx_disabled_r15_present, 1)); } @@ -2813,7 +2801,6 @@ SRSASN_CODE sl_comm_tx_pool_sensing_cfg_r14_s::unpack(bit_ref& bref) HANDLE_CODE(bref.unpack(sl_reselect_after_r14_present, 1)); HANDLE_CODE(unpack_dyn_seq_of(pssch_tx_cfg_list_r14, bref, 1, 16)); - thres_pssch_rsrp_list_r14 = make_copy_ptr(sl_thres_pssch_rsrp_list_r14_l()); HANDLE_CODE(unpack_fixed_seq_of(&(*thres_pssch_rsrp_list_r14)[0], bref, thres_pssch_rsrp_list_r14->size(), @@ -2895,41 +2882,34 @@ SRSASN_CODE sl_disc_res_pool_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(disc_period_v1310_present != (disc_period_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= disc_period_v1310_present; - rrc_asn1_warn_assert( - rx_params_add_neigh_freq_r13_present != (rx_params_add_neigh_freq_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rx_params_add_neigh_freq_r13_present; - rrc_asn1_warn_assert( - tx_params_add_neigh_freq_r13_present != (tx_params_add_neigh_freq_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= tx_params_add_neigh_freq_r13_present; - rrc_asn1_warn_assert( - tx_params_add_neigh_freq_v1370_present != (tx_params_add_neigh_freq_v1370.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= tx_params_add_neigh_freq_v1370_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= disc_period_v1310.is_present(); + group_flags[0] |= rx_params_add_neigh_freq_r13.is_present(); + group_flags[0] |= tx_params_add_neigh_freq_r13.is_present(); + group_flags[1] |= tx_params_add_neigh_freq_v1370.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(disc_period_v1310_present, 1)); - HANDLE_CODE(bref.pack(rx_params_add_neigh_freq_r13_present, 1)); - HANDLE_CODE(bref.pack(tx_params_add_neigh_freq_r13_present, 1)); - if (disc_period_v1310_present) { + HANDLE_CODE(bref.pack(disc_period_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(rx_params_add_neigh_freq_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(tx_params_add_neigh_freq_r13.is_present(), 1)); + if (disc_period_v1310.is_present()) { HANDLE_CODE(disc_period_v1310->pack(bref)); } - if (rx_params_add_neigh_freq_r13_present) { + if (rx_params_add_neigh_freq_r13.is_present()) { HANDLE_CODE(rx_params_add_neigh_freq_r13->pack(bref)); } - if (tx_params_add_neigh_freq_r13_present) { + if (tx_params_add_neigh_freq_r13.is_present()) { HANDLE_CODE(tx_params_add_neigh_freq_r13->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(tx_params_add_neigh_freq_v1370_present, 1)); - if (tx_params_add_neigh_freq_v1370_present) { + HANDLE_CODE(bref.pack(tx_params_add_neigh_freq_v1370.is_present(), 1)); + if (tx_params_add_neigh_freq_v1370.is_present()) { HANDLE_CODE(tx_params_add_neigh_freq_v1370->pack(bref)); } } @@ -2964,34 +2944,38 @@ SRSASN_CODE sl_disc_res_pool_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool disc_period_v1310_present; HANDLE_CODE(bref.unpack(disc_period_v1310_present, 1)); + disc_period_v1310.set_present(disc_period_v1310_present); + bool rx_params_add_neigh_freq_r13_present; HANDLE_CODE(bref.unpack(rx_params_add_neigh_freq_r13_present, 1)); + rx_params_add_neigh_freq_r13.set_present(rx_params_add_neigh_freq_r13_present); + bool tx_params_add_neigh_freq_r13_present; HANDLE_CODE(bref.unpack(tx_params_add_neigh_freq_r13_present, 1)); - if (disc_period_v1310_present) { - disc_period_v1310 = make_copy_ptr(disc_period_v1310_c_()); + tx_params_add_neigh_freq_r13.set_present(tx_params_add_neigh_freq_r13_present); + if (disc_period_v1310.is_present()) { HANDLE_CODE(disc_period_v1310->unpack(bref)); } - if (rx_params_add_neigh_freq_r13_present) { - rx_params_add_neigh_freq_r13 = make_copy_ptr(rx_params_add_neigh_freq_r13_c_()); + if (rx_params_add_neigh_freq_r13.is_present()) { HANDLE_CODE(rx_params_add_neigh_freq_r13->unpack(bref)); } - if (tx_params_add_neigh_freq_r13_present) { - tx_params_add_neigh_freq_r13 = make_copy_ptr(tx_params_add_neigh_freq_r13_c_()); + if (tx_params_add_neigh_freq_r13.is_present()) { HANDLE_CODE(tx_params_add_neigh_freq_r13->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool tx_params_add_neigh_freq_v1370_present; HANDLE_CODE(bref.unpack(tx_params_add_neigh_freq_v1370_present, 1)); - if (tx_params_add_neigh_freq_v1370_present) { - tx_params_add_neigh_freq_v1370 = make_copy_ptr(tx_params_add_neigh_freq_v1370_c_()); + tx_params_add_neigh_freq_v1370.set_present(tx_params_add_neigh_freq_v1370_present); + if (tx_params_add_neigh_freq_v1370.is_present()) { HANDLE_CODE(tx_params_add_neigh_freq_v1370->unpack(bref)); } } @@ -3033,26 +3017,19 @@ void sl_disc_res_pool_r12_s::to_json(json_writer& j) const j.end_obj(); } if (ext) { - rrc_asn1_warn_assert(disc_period_v1310_present != (disc_period_v1310.get() != NULL), __FILE__, __LINE__); - if (disc_period_v1310_present) { + if (disc_period_v1310.is_present()) { j.write_fieldname("discPeriod-v1310"); disc_period_v1310->to_json(j); } - rrc_asn1_warn_assert( - rx_params_add_neigh_freq_r13_present != (rx_params_add_neigh_freq_r13.get() != NULL), __FILE__, __LINE__); - if (rx_params_add_neigh_freq_r13_present) { + if (rx_params_add_neigh_freq_r13.is_present()) { j.write_fieldname("rxParamsAddNeighFreq-r13"); rx_params_add_neigh_freq_r13->to_json(j); } - rrc_asn1_warn_assert( - tx_params_add_neigh_freq_r13_present != (tx_params_add_neigh_freq_r13.get() != NULL), __FILE__, __LINE__); - if (tx_params_add_neigh_freq_r13_present) { + if (tx_params_add_neigh_freq_r13.is_present()) { j.write_fieldname("txParamsAddNeighFreq-r13"); tx_params_add_neigh_freq_r13->to_json(j); } - rrc_asn1_warn_assert( - tx_params_add_neigh_freq_v1370_present != (tx_params_add_neigh_freq_v1370.get() != NULL), __FILE__, __LINE__); - if (tx_params_add_neigh_freq_v1370_present) { + if (tx_params_add_neigh_freq_v1370.is_present()) { j.write_fieldname("txParamsAddNeighFreq-v1370"); tx_params_add_neigh_freq_v1370->to_json(j); } @@ -4696,16 +4673,15 @@ SRSASN_CODE rach_ce_level_info_r13_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, rar_hop_cfg_r13)); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(edt_params_r15_present != (edt_params_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= edt_params_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= edt_params_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(edt_params_r15_present, 1)); - if (edt_params_r15_present) { + HANDLE_CODE(bref.pack(edt_params_r15.is_present(), 1)); + if (edt_params_r15.is_present()) { HANDLE_CODE(bref.pack(edt_params_r15->mac_contention_resolution_timer_r15_present, 1)); HANDLE_CODE(pack_unalign_integer(bref, edt_params_r15->edt_last_preamb_r15, (uint8_t)0, (uint8_t)63)); HANDLE_CODE(bref.pack(edt_params_r15->edt_small_tbs_enabled_r15, 1)); @@ -4728,15 +4704,16 @@ SRSASN_CODE rach_ce_level_info_r13_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(rar_hop_cfg_r13, bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool edt_params_r15_present; HANDLE_CODE(bref.unpack(edt_params_r15_present, 1)); - if (edt_params_r15_present) { - edt_params_r15 = make_copy_ptr(edt_params_r15_s_()); + edt_params_r15.set_present(edt_params_r15_present); + if (edt_params_r15.is_present()) { HANDLE_CODE(bref.unpack(edt_params_r15->mac_contention_resolution_timer_r15_present, 1)); HANDLE_CODE(unpack_unalign_integer(edt_params_r15->edt_last_preamb_r15, bref, (uint8_t)0, (uint8_t)63)); HANDLE_CODE(bref.unpack(edt_params_r15->edt_small_tbs_enabled_r15, 1)); @@ -4761,8 +4738,7 @@ void rach_ce_level_info_r13_s::to_json(json_writer& j) const j.write_str("mac-ContentionResolutionTimer-r13", mac_contention_resolution_timer_r13.to_string()); j.write_str("rar-HoppingConfig-r13", rar_hop_cfg_r13.to_string()); if (ext) { - rrc_asn1_warn_assert(edt_params_r15_present != (edt_params_r15.get() != NULL), __FILE__, __LINE__); - if (edt_params_r15_present) { + if (edt_params_r15.is_present()) { j.write_fieldname("edt-Parameters-r15"); j.start_obj(); j.write_int("edt-LastPreamble-r15", edt_params_r15->edt_last_preamb_r15); @@ -6568,28 +6544,24 @@ SRSASN_CODE sl_inter_freq_info_v2x_r14_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert( - add_spec_emission_v2x_r14_present != (add_spec_emission_v2x_r14.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= add_spec_emission_v2x_r14_present; - rrc_asn1_warn_assert( - v2x_freq_sel_cfg_list_r15_present != (v2x_freq_sel_cfg_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= v2x_freq_sel_cfg_list_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= add_spec_emission_v2x_r14.is_present(); + group_flags[1] |= v2x_freq_sel_cfg_list_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(add_spec_emission_v2x_r14_present, 1)); - if (add_spec_emission_v2x_r14_present) { + HANDLE_CODE(bref.pack(add_spec_emission_v2x_r14.is_present(), 1)); + if (add_spec_emission_v2x_r14.is_present()) { HANDLE_CODE(add_spec_emission_v2x_r14->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(v2x_freq_sel_cfg_list_r15_present, 1)); - if (v2x_freq_sel_cfg_list_r15_present) { + HANDLE_CODE(bref.pack(v2x_freq_sel_cfg_list_r15.is_present(), 1)); + if (v2x_freq_sel_cfg_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *v2x_freq_sel_cfg_list_r15, 1, 8)); } } @@ -6623,24 +6595,26 @@ SRSASN_CODE sl_inter_freq_info_v2x_r14_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool add_spec_emission_v2x_r14_present; HANDLE_CODE(bref.unpack(add_spec_emission_v2x_r14_present, 1)); - if (add_spec_emission_v2x_r14_present) { - add_spec_emission_v2x_r14 = make_copy_ptr(add_spec_emission_v2x_r14_c_()); + add_spec_emission_v2x_r14.set_present(add_spec_emission_v2x_r14_present); + if (add_spec_emission_v2x_r14.is_present()) { HANDLE_CODE(add_spec_emission_v2x_r14->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool v2x_freq_sel_cfg_list_r15_present; HANDLE_CODE(bref.unpack(v2x_freq_sel_cfg_list_r15_present, 1)); - if (v2x_freq_sel_cfg_list_r15_present) { - v2x_freq_sel_cfg_list_r15 = make_copy_ptr(sl_v2x_freq_sel_cfg_list_r15_l()); + v2x_freq_sel_cfg_list_r15.set_present(v2x_freq_sel_cfg_list_r15_present); + if (v2x_freq_sel_cfg_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*v2x_freq_sel_cfg_list_r15, bref, 1, 8)); } } @@ -6676,15 +6650,11 @@ void sl_inter_freq_info_v2x_r14_s::to_json(json_writer& j) const j.end_array(); } if (ext) { - rrc_asn1_warn_assert( - add_spec_emission_v2x_r14_present != (add_spec_emission_v2x_r14.get() != NULL), __FILE__, __LINE__); - if (add_spec_emission_v2x_r14_present) { + if (add_spec_emission_v2x_r14.is_present()) { j.write_fieldname("additionalSpectrumEmissionV2X-r14"); add_spec_emission_v2x_r14->to_json(j); } - rrc_asn1_warn_assert( - v2x_freq_sel_cfg_list_r15_present != (v2x_freq_sel_cfg_list_r15.get() != NULL), __FILE__, __LINE__); - if (v2x_freq_sel_cfg_list_r15_present) { + if (v2x_freq_sel_cfg_list_r15.is_present()) { j.start_array("v2x-FreqSelectionConfigList-r15"); for (uint32_t i1 = 0; i1 < v2x_freq_sel_cfg_list_r15->size(); ++i1) { ((*v2x_freq_sel_cfg_list_r15)[i1]).to_json(j); @@ -6906,7 +6876,7 @@ SRSASN_CODE sl_sync_cfg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); + ext_groups_packer_guard group_flags; group_flags[0] |= sync_tx_periodic_r13_present; group_flags[1] |= sync_offset_ind_v1430_present; group_flags[1] |= gnss_sync_r14_present; @@ -6916,12 +6886,12 @@ SRSASN_CODE sl_sync_cfg_r12_s::pack(bit_ref& bref) const group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sync_tx_periodic_r13_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sync_offset_ind_v1430_present, 1)); HANDLE_CODE(bref.pack(gnss_sync_r14_present, 1)); @@ -6930,7 +6900,7 @@ SRSASN_CODE sl_sync_cfg_r12_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sync_offset_ind2_r14_present, 1)); HANDLE_CODE(bref.pack(sync_offset_ind3_r14_present, 1)); @@ -6942,7 +6912,7 @@ SRSASN_CODE sl_sync_cfg_r12_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(slss_tx_disabled_r15_present, 1)); } @@ -6972,16 +6942,16 @@ SRSASN_CODE sl_sync_cfg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sync_tx_periodic_r13_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sync_offset_ind_v1430_present, 1)); HANDLE_CODE(bref.unpack(gnss_sync_r14_present, 1)); @@ -6990,7 +6960,7 @@ SRSASN_CODE sl_sync_cfg_r12_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sync_offset_ind2_r14_present, 1)); HANDLE_CODE(bref.unpack(sync_offset_ind3_r14_present, 1)); @@ -7002,7 +6972,7 @@ SRSASN_CODE sl_sync_cfg_r12_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(slss_tx_disabled_r15_present, 1)); } @@ -8130,16 +8100,15 @@ SRSASN_CODE carrier_freq_utra_fdd_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, q_qual_min, (int8_t)-24, (int8_t)0)); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(thresh_x_q_r9_present != (thresh_x_q_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= thresh_x_q_r9_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= thresh_x_q_r9.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(thresh_x_q_r9_present, 1)); - if (thresh_x_q_r9_present) { + HANDLE_CODE(bref.pack(thresh_x_q_r9.is_present(), 1)); + if (thresh_x_q_r9.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, thresh_x_q_r9->thresh_x_high_q_r9, (uint8_t)0, (uint8_t)31)); HANDLE_CODE(pack_unalign_integer(bref, thresh_x_q_r9->thresh_x_low_q_r9, (uint8_t)0, (uint8_t)31)); } @@ -8163,15 +8132,16 @@ SRSASN_CODE carrier_freq_utra_fdd_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(q_qual_min, bref, (int8_t)-24, (int8_t)0)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool thresh_x_q_r9_present; HANDLE_CODE(bref.unpack(thresh_x_q_r9_present, 1)); - if (thresh_x_q_r9_present) { - thresh_x_q_r9 = make_copy_ptr(thresh_x_q_r9_s_()); + thresh_x_q_r9.set_present(thresh_x_q_r9_present); + if (thresh_x_q_r9.is_present()) { HANDLE_CODE(unpack_unalign_integer(thresh_x_q_r9->thresh_x_high_q_r9, bref, (uint8_t)0, (uint8_t)31)); HANDLE_CODE(unpack_unalign_integer(thresh_x_q_r9->thresh_x_low_q_r9, bref, (uint8_t)0, (uint8_t)31)); } @@ -8192,8 +8162,7 @@ void carrier_freq_utra_fdd_s::to_json(json_writer& j) const j.write_int("p-MaxUTRA", p_max_utra); j.write_int("q-QualMin", q_qual_min); if (ext) { - rrc_asn1_warn_assert(thresh_x_q_r9_present != (thresh_x_q_r9.get() != NULL), __FILE__, __LINE__); - if (thresh_x_q_r9_present) { + if (thresh_x_q_r9.is_present()) { j.write_fieldname("threshX-Q-r9"); j.start_obj(); j.write_int("threshX-HighQ-r9", thresh_x_q_r9->thresh_x_high_q_r9); @@ -9044,28 +9013,27 @@ SRSASN_CODE inter_freq_carrier_freq_info_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); + ext_groups_packer_guard group_flags; group_flags[0] |= q_qual_min_r9_present; - rrc_asn1_warn_assert(thresh_x_q_r9_present != (thresh_x_q_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= thresh_x_q_r9_present; + group_flags[0] |= thresh_x_q_r9.is_present(); group_flags[1] |= q_qual_min_wb_r11_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(q_qual_min_r9_present, 1)); - HANDLE_CODE(bref.pack(thresh_x_q_r9_present, 1)); + HANDLE_CODE(bref.pack(thresh_x_q_r9.is_present(), 1)); if (q_qual_min_r9_present) { HANDLE_CODE(pack_unalign_integer(bref, q_qual_min_r9, (int8_t)-34, (int8_t)-3)); } - if (thresh_x_q_r9_present) { + if (thresh_x_q_r9.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, thresh_x_q_r9->thresh_x_high_q_r9, (uint8_t)0, (uint8_t)31)); HANDLE_CODE(pack_unalign_integer(bref, thresh_x_q_r9->thresh_x_low_q_r9, (uint8_t)0, (uint8_t)31)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(q_qual_min_wb_r11_present, 1)); if (q_qual_min_wb_r11_present) { @@ -9113,25 +9081,26 @@ SRSASN_CODE inter_freq_carrier_freq_info_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(q_qual_min_r9_present, 1)); + bool thresh_x_q_r9_present; HANDLE_CODE(bref.unpack(thresh_x_q_r9_present, 1)); + thresh_x_q_r9.set_present(thresh_x_q_r9_present); if (q_qual_min_r9_present) { HANDLE_CODE(unpack_unalign_integer(q_qual_min_r9, bref, (int8_t)-34, (int8_t)-3)); } - if (thresh_x_q_r9_present) { - thresh_x_q_r9 = make_copy_ptr(thresh_x_q_r9_s_()); + if (thresh_x_q_r9.is_present()) { HANDLE_CODE(unpack_unalign_integer(thresh_x_q_r9->thresh_x_high_q_r9, bref, (uint8_t)0, (uint8_t)31)); HANDLE_CODE(unpack_unalign_integer(thresh_x_q_r9->thresh_x_low_q_r9, bref, (uint8_t)0, (uint8_t)31)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(q_qual_min_wb_r11_present, 1)); if (q_qual_min_wb_r11_present) { @@ -9183,8 +9152,7 @@ void inter_freq_carrier_freq_info_s::to_json(json_writer& j) const if (q_qual_min_r9_present) { j.write_int("q-QualMin-r9", q_qual_min_r9); } - rrc_asn1_warn_assert(thresh_x_q_r9_present != (thresh_x_q_r9.get() != NULL), __FILE__, __LINE__); - if (thresh_x_q_r9_present) { + if (thresh_x_q_r9.is_present()) { j.write_fieldname("threshX-Q-r9"); j.start_obj(); j.write_int("threshX-HighQ-r9", thresh_x_q_r9->thresh_x_high_q_r9); @@ -9735,18 +9703,17 @@ SRSASN_CODE mbsfn_area_info_r9_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, mcch_cfg_r9.sig_mcs_r9)); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(mcch_cfg_r14_present != (mcch_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= mcch_cfg_r14_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= mcch_cfg_r14.is_present(); group_flags[0] |= subcarrier_spacing_mbms_r14_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mcch_cfg_r14_present, 1)); + HANDLE_CODE(bref.pack(mcch_cfg_r14.is_present(), 1)); HANDLE_CODE(bref.pack(subcarrier_spacing_mbms_r14_present, 1)); - if (mcch_cfg_r14_present) { + if (mcch_cfg_r14.is_present()) { HANDLE_CODE(bref.pack(mcch_cfg_r14->mcch_repeat_period_v1430_present, 1)); HANDLE_CODE(bref.pack(mcch_cfg_r14->mcch_mod_period_v1430_present, 1)); if (mcch_cfg_r14->mcch_repeat_period_v1430_present) { @@ -9776,16 +9743,17 @@ SRSASN_CODE mbsfn_area_info_r9_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(mcch_cfg_r9.sig_mcs_r9, bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mcch_cfg_r14_present; HANDLE_CODE(bref.unpack(mcch_cfg_r14_present, 1)); + mcch_cfg_r14.set_present(mcch_cfg_r14_present); HANDLE_CODE(bref.unpack(subcarrier_spacing_mbms_r14_present, 1)); - if (mcch_cfg_r14_present) { - mcch_cfg_r14 = make_copy_ptr(mcch_cfg_r14_s_()); + if (mcch_cfg_r14.is_present()) { HANDLE_CODE(bref.unpack(mcch_cfg_r14->mcch_repeat_period_v1430_present, 1)); HANDLE_CODE(bref.unpack(mcch_cfg_r14->mcch_mod_period_v1430_present, 1)); if (mcch_cfg_r14->mcch_repeat_period_v1430_present) { @@ -9817,8 +9785,7 @@ void mbsfn_area_info_r9_s::to_json(json_writer& j) const j.write_str("signallingMCS-r9", mcch_cfg_r9.sig_mcs_r9.to_string()); j.end_obj(); if (ext) { - rrc_asn1_warn_assert(mcch_cfg_r14_present != (mcch_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (mcch_cfg_r14_present) { + if (mcch_cfg_r14.is_present()) { j.write_fieldname("mcch-Config-r14"); j.start_obj(); if (mcch_cfg_r14->mcch_repeat_period_v1430_present) { @@ -10752,28 +10719,26 @@ SRSASN_CODE rach_cfg_common_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, max_harq_msg3_tx, (uint8_t)1, (uint8_t)8)); if (ext) { - ext_groups_header group_flags(2); + ext_groups_packer_guard group_flags; group_flags[0] |= preamb_trans_max_ce_r13_present; - rrc_asn1_warn_assert( - rach_ce_level_info_list_r13_present != (rach_ce_level_info_list_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rach_ce_level_info_list_r13_present; + group_flags[0] |= rach_ce_level_info_list_r13.is_present(); group_flags[1] |= edt_small_tbs_subset_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(preamb_trans_max_ce_r13_present, 1)); - HANDLE_CODE(bref.pack(rach_ce_level_info_list_r13_present, 1)); + HANDLE_CODE(bref.pack(rach_ce_level_info_list_r13.is_present(), 1)); if (preamb_trans_max_ce_r13_present) { HANDLE_CODE(pack_enum(bref, preamb_trans_max_ce_r13)); } - if (rach_ce_level_info_list_r13_present) { + if (rach_ce_level_info_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *rach_ce_level_info_list_r13, 1, 4)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(edt_small_tbs_subset_r15_present, 1)); } @@ -10798,24 +10763,25 @@ SRSASN_CODE rach_cfg_common_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(max_harq_msg3_tx, bref, (uint8_t)1, (uint8_t)8)); if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(preamb_trans_max_ce_r13_present, 1)); + bool rach_ce_level_info_list_r13_present; HANDLE_CODE(bref.unpack(rach_ce_level_info_list_r13_present, 1)); + rach_ce_level_info_list_r13.set_present(rach_ce_level_info_list_r13_present); if (preamb_trans_max_ce_r13_present) { HANDLE_CODE(unpack_enum(preamb_trans_max_ce_r13, bref)); } - if (rach_ce_level_info_list_r13_present) { - rach_ce_level_info_list_r13 = make_copy_ptr(rach_ce_level_info_list_r13_l()); + if (rach_ce_level_info_list_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*rach_ce_level_info_list_r13, bref, 1, 4)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(edt_small_tbs_subset_r15_present, 1)); } @@ -10850,9 +10816,7 @@ void rach_cfg_common_s::to_json(json_writer& j) const if (preamb_trans_max_ce_r13_present) { j.write_str("preambleTransMax-CE-r13", preamb_trans_max_ce_r13.to_string()); } - rrc_asn1_warn_assert( - rach_ce_level_info_list_r13_present != (rach_ce_level_info_list_r13.get() != NULL), __FILE__, __LINE__); - if (rach_ce_level_info_list_r13_present) { + if (rach_ce_level_info_list_r13.is_present()) { j.start_array("rach-CE-LevelInfoList-r13"); for (uint32_t i1 = 0; i1 < rach_ce_level_info_list_r13->size(); ++i1) { ((*rach_ce_level_info_list_r13)[i1]).to_json(j); @@ -11248,16 +11212,15 @@ SRSASN_CODE sl_comm_res_pool_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(prio_list_r13_present != (prio_list_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= prio_list_r13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= prio_list_r13.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(prio_list_r13_present, 1)); - if (prio_list_r13_present) { + HANDLE_CODE(bref.pack(prio_list_r13.is_present(), 1)); + if (prio_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *prio_list_r13, 1, 8, UnalignedIntegerPacker(1, 8))); } } @@ -11296,15 +11259,16 @@ SRSASN_CODE sl_comm_res_pool_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool prio_list_r13_present; HANDLE_CODE(bref.unpack(prio_list_r13_present, 1)); - if (prio_list_r13_present) { - prio_list_r13 = make_copy_ptr(sl_prio_list_r13_l()); + prio_list_r13.set_present(prio_list_r13_present); + if (prio_list_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*prio_list_r13, bref, 1, 8, UnalignedIntegerPacker(1, 8))); } } @@ -11351,8 +11315,7 @@ void sl_comm_res_pool_r12_s::to_json(json_writer& j) const j.end_obj(); } if (ext) { - rrc_asn1_warn_assert(prio_list_r13_present != (prio_list_r13.get() != NULL), __FILE__, __LINE__); - if (prio_list_r13_present) { + if (prio_list_r13.is_present()) { j.start_array("priorityList-r13"); for (uint32_t i1 = 0; i1 < prio_list_r13->size(); ++i1) { j.write_int(((*prio_list_r13)[i1])); @@ -12645,133 +12608,115 @@ SRSASN_CODE rr_cfg_common_sib_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, ul_cp_len)); if (ext) { - ext_groups_header group_flags(6); - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1020_present != (ul_pwr_ctrl_common_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ul_pwr_ctrl_common_v1020_present; - rrc_asn1_warn_assert(rach_cfg_common_v1250_present != (rach_cfg_common_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= rach_cfg_common_v1250_present; - rrc_asn1_warn_assert(pusch_cfg_common_v1270_present != (pusch_cfg_common_v1270.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= pusch_cfg_common_v1270_present; - rrc_asn1_warn_assert(bcch_cfg_v1310_present != (bcch_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= bcch_cfg_v1310_present; - rrc_asn1_warn_assert(pcch_cfg_v1310_present != (pcch_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pcch_cfg_v1310_present; - rrc_asn1_warn_assert(freq_hop_params_r13_present != (freq_hop_params_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= freq_hop_params_r13_present; - rrc_asn1_warn_assert(pdsch_cfg_common_v1310_present != (pdsch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pdsch_cfg_common_v1310_present; - rrc_asn1_warn_assert(pusch_cfg_common_v1310_present != (pusch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pusch_cfg_common_v1310_present; - rrc_asn1_warn_assert(prach_cfg_common_v1310_present != (prach_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= prach_cfg_common_v1310_present; - rrc_asn1_warn_assert(pucch_cfg_common_v1310_present != (pucch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pucch_cfg_common_v1310_present; - rrc_asn1_warn_assert(high_speed_cfg_r14_present != (high_speed_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= high_speed_cfg_r14_present; - rrc_asn1_warn_assert(prach_cfg_v1430_present != (prach_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= prach_cfg_v1430_present; - rrc_asn1_warn_assert(pucch_cfg_common_v1430_present != (pucch_cfg_common_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= pucch_cfg_common_v1430_present; - rrc_asn1_warn_assert(prach_cfg_v1530_present != (prach_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= prach_cfg_v1530_present; - rrc_asn1_warn_assert(ce_rss_cfg_r15_present != (ce_rss_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= ce_rss_cfg_r15_present; - rrc_asn1_warn_assert(wus_cfg_r15_present != (wus_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= wus_cfg_r15_present; - rrc_asn1_warn_assert(high_speed_cfg_v1530_present != (high_speed_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= high_speed_cfg_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= ul_pwr_ctrl_common_v1020.is_present(); + group_flags[1] |= rach_cfg_common_v1250.is_present(); + group_flags[2] |= pusch_cfg_common_v1270.is_present(); + group_flags[3] |= bcch_cfg_v1310.is_present(); + group_flags[3] |= pcch_cfg_v1310.is_present(); + group_flags[3] |= freq_hop_params_r13.is_present(); + group_flags[3] |= pdsch_cfg_common_v1310.is_present(); + group_flags[3] |= pusch_cfg_common_v1310.is_present(); + group_flags[3] |= prach_cfg_common_v1310.is_present(); + group_flags[3] |= pucch_cfg_common_v1310.is_present(); + group_flags[4] |= high_speed_cfg_r14.is_present(); + group_flags[4] |= prach_cfg_v1430.is_present(); + group_flags[4] |= pucch_cfg_common_v1430.is_present(); + group_flags[5] |= prach_cfg_v1530.is_present(); + group_flags[5] |= ce_rss_cfg_r15.is_present(); + group_flags[5] |= wus_cfg_r15.is_present(); + group_flags[5] |= high_speed_cfg_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1020_present, 1)); - if (ul_pwr_ctrl_common_v1020_present) { + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1020.is_present(), 1)); + if (ul_pwr_ctrl_common_v1020.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1020->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rach_cfg_common_v1250_present, 1)); - if (rach_cfg_common_v1250_present) { + HANDLE_CODE(bref.pack(rach_cfg_common_v1250.is_present(), 1)); + if (rach_cfg_common_v1250.is_present()) { HANDLE_CODE(rach_cfg_common_v1250->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(pusch_cfg_common_v1270_present, 1)); - if (pusch_cfg_common_v1270_present) { + HANDLE_CODE(bref.pack(pusch_cfg_common_v1270.is_present(), 1)); + if (pusch_cfg_common_v1270.is_present()) { HANDLE_CODE(pusch_cfg_common_v1270->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(bcch_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(pcch_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(freq_hop_params_r13_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_common_v1310_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_common_v1310_present, 1)); - HANDLE_CODE(bref.pack(prach_cfg_common_v1310_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_common_v1310_present, 1)); - if (bcch_cfg_v1310_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(bcch_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(pcch_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(freq_hop_params_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_common_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_common_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(prach_cfg_common_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_common_v1310.is_present(), 1)); + if (bcch_cfg_v1310.is_present()) { HANDLE_CODE(bcch_cfg_v1310->pack(bref)); } - if (pcch_cfg_v1310_present) { + if (pcch_cfg_v1310.is_present()) { HANDLE_CODE(pcch_cfg_v1310->pack(bref)); } - if (freq_hop_params_r13_present) { + if (freq_hop_params_r13.is_present()) { HANDLE_CODE(freq_hop_params_r13->pack(bref)); } - if (pdsch_cfg_common_v1310_present) { + if (pdsch_cfg_common_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_common_v1310->pack(bref)); } - if (pusch_cfg_common_v1310_present) { + if (pusch_cfg_common_v1310.is_present()) { HANDLE_CODE(pusch_cfg_common_v1310->pack(bref)); } - if (prach_cfg_common_v1310_present) { + if (prach_cfg_common_v1310.is_present()) { HANDLE_CODE(prach_cfg_common_v1310->pack(bref)); } - if (pucch_cfg_common_v1310_present) { + if (pucch_cfg_common_v1310.is_present()) { HANDLE_CODE(pucch_cfg_common_v1310->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(high_speed_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(prach_cfg_v1430_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_common_v1430_present, 1)); - if (high_speed_cfg_r14_present) { + HANDLE_CODE(bref.pack(high_speed_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(prach_cfg_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_common_v1430.is_present(), 1)); + if (high_speed_cfg_r14.is_present()) { HANDLE_CODE(high_speed_cfg_r14->pack(bref)); } - if (prach_cfg_v1430_present) { + if (prach_cfg_v1430.is_present()) { HANDLE_CODE(prach_cfg_v1430->pack(bref)); } - if (pucch_cfg_common_v1430_present) { + if (pucch_cfg_common_v1430.is_present()) { HANDLE_CODE(pucch_cfg_common_v1430->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(prach_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(ce_rss_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(wus_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(high_speed_cfg_v1530_present, 1)); - if (prach_cfg_v1530_present) { + HANDLE_CODE(bref.pack(prach_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(ce_rss_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(wus_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(high_speed_cfg_v1530.is_present(), 1)); + if (prach_cfg_v1530.is_present()) { HANDLE_CODE(prach_cfg_v1530->pack(bref)); } - if (ce_rss_cfg_r15_present) { + if (ce_rss_cfg_r15.is_present()) { HANDLE_CODE(ce_rss_cfg_r15->pack(bref)); } - if (wus_cfg_r15_present) { + if (wus_cfg_r15.is_present()) { HANDLE_CODE(wus_cfg_r15->pack(bref)); } - if (high_speed_cfg_v1530_present) { + if (high_speed_cfg_v1530.is_present()) { HANDLE_CODE(high_speed_cfg_v1530->pack(bref)); } } @@ -12793,115 +12738,132 @@ SRSASN_CODE rr_cfg_common_sib_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(ul_cp_len, bref)); if (ext) { - ext_groups_header group_flags(6); + ext_groups_unpacker_guard group_flags(6); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_pwr_ctrl_common_v1020_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_v1020_present, 1)); - if (ul_pwr_ctrl_common_v1020_present) { - ul_pwr_ctrl_common_v1020 = make_copy_ptr(ul_pwr_ctrl_common_v1020_s()); + ul_pwr_ctrl_common_v1020.set_present(ul_pwr_ctrl_common_v1020_present); + if (ul_pwr_ctrl_common_v1020.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1020->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rach_cfg_common_v1250_present; HANDLE_CODE(bref.unpack(rach_cfg_common_v1250_present, 1)); - if (rach_cfg_common_v1250_present) { - rach_cfg_common_v1250 = make_copy_ptr(rach_cfg_common_v1250_s()); + rach_cfg_common_v1250.set_present(rach_cfg_common_v1250_present); + if (rach_cfg_common_v1250.is_present()) { HANDLE_CODE(rach_cfg_common_v1250->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool pusch_cfg_common_v1270_present; HANDLE_CODE(bref.unpack(pusch_cfg_common_v1270_present, 1)); - if (pusch_cfg_common_v1270_present) { - pusch_cfg_common_v1270 = make_copy_ptr(pusch_cfg_common_v1270_s()); + pusch_cfg_common_v1270.set_present(pusch_cfg_common_v1270_present); + if (pusch_cfg_common_v1270.is_present()) { HANDLE_CODE(pusch_cfg_common_v1270->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool bcch_cfg_v1310_present; HANDLE_CODE(bref.unpack(bcch_cfg_v1310_present, 1)); + bcch_cfg_v1310.set_present(bcch_cfg_v1310_present); + bool pcch_cfg_v1310_present; HANDLE_CODE(bref.unpack(pcch_cfg_v1310_present, 1)); + pcch_cfg_v1310.set_present(pcch_cfg_v1310_present); + bool freq_hop_params_r13_present; HANDLE_CODE(bref.unpack(freq_hop_params_r13_present, 1)); + freq_hop_params_r13.set_present(freq_hop_params_r13_present); + bool pdsch_cfg_common_v1310_present; HANDLE_CODE(bref.unpack(pdsch_cfg_common_v1310_present, 1)); + pdsch_cfg_common_v1310.set_present(pdsch_cfg_common_v1310_present); + bool pusch_cfg_common_v1310_present; HANDLE_CODE(bref.unpack(pusch_cfg_common_v1310_present, 1)); + pusch_cfg_common_v1310.set_present(pusch_cfg_common_v1310_present); + bool prach_cfg_common_v1310_present; HANDLE_CODE(bref.unpack(prach_cfg_common_v1310_present, 1)); + prach_cfg_common_v1310.set_present(prach_cfg_common_v1310_present); + bool pucch_cfg_common_v1310_present; HANDLE_CODE(bref.unpack(pucch_cfg_common_v1310_present, 1)); - if (bcch_cfg_v1310_present) { - bcch_cfg_v1310 = make_copy_ptr(bcch_cfg_v1310_s()); + pucch_cfg_common_v1310.set_present(pucch_cfg_common_v1310_present); + if (bcch_cfg_v1310.is_present()) { HANDLE_CODE(bcch_cfg_v1310->unpack(bref)); } - if (pcch_cfg_v1310_present) { - pcch_cfg_v1310 = make_copy_ptr(pcch_cfg_v1310_s()); + if (pcch_cfg_v1310.is_present()) { HANDLE_CODE(pcch_cfg_v1310->unpack(bref)); } - if (freq_hop_params_r13_present) { - freq_hop_params_r13 = make_copy_ptr(freq_hop_params_r13_s()); + if (freq_hop_params_r13.is_present()) { HANDLE_CODE(freq_hop_params_r13->unpack(bref)); } - if (pdsch_cfg_common_v1310_present) { - pdsch_cfg_common_v1310 = make_copy_ptr(pdsch_cfg_common_v1310_s()); + if (pdsch_cfg_common_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_common_v1310->unpack(bref)); } - if (pusch_cfg_common_v1310_present) { - pusch_cfg_common_v1310 = make_copy_ptr(pusch_cfg_common_v1310_s()); + if (pusch_cfg_common_v1310.is_present()) { HANDLE_CODE(pusch_cfg_common_v1310->unpack(bref)); } - if (prach_cfg_common_v1310_present) { - prach_cfg_common_v1310 = make_copy_ptr(prach_cfg_sib_v1310_s()); + if (prach_cfg_common_v1310.is_present()) { HANDLE_CODE(prach_cfg_common_v1310->unpack(bref)); } - if (pucch_cfg_common_v1310_present) { - pucch_cfg_common_v1310 = make_copy_ptr(pucch_cfg_common_v1310_s()); + if (pucch_cfg_common_v1310.is_present()) { HANDLE_CODE(pucch_cfg_common_v1310->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool high_speed_cfg_r14_present; HANDLE_CODE(bref.unpack(high_speed_cfg_r14_present, 1)); + high_speed_cfg_r14.set_present(high_speed_cfg_r14_present); + bool prach_cfg_v1430_present; HANDLE_CODE(bref.unpack(prach_cfg_v1430_present, 1)); + prach_cfg_v1430.set_present(prach_cfg_v1430_present); + bool pucch_cfg_common_v1430_present; HANDLE_CODE(bref.unpack(pucch_cfg_common_v1430_present, 1)); - if (high_speed_cfg_r14_present) { - high_speed_cfg_r14 = make_copy_ptr(high_speed_cfg_r14_s()); + pucch_cfg_common_v1430.set_present(pucch_cfg_common_v1430_present); + if (high_speed_cfg_r14.is_present()) { HANDLE_CODE(high_speed_cfg_r14->unpack(bref)); } - if (prach_cfg_v1430_present) { - prach_cfg_v1430 = make_copy_ptr(prach_cfg_v1430_s()); + if (prach_cfg_v1430.is_present()) { HANDLE_CODE(prach_cfg_v1430->unpack(bref)); } - if (pucch_cfg_common_v1430_present) { - pucch_cfg_common_v1430 = make_copy_ptr(pucch_cfg_common_v1430_s()); + if (pucch_cfg_common_v1430.is_present()) { HANDLE_CODE(pucch_cfg_common_v1430->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool prach_cfg_v1530_present; HANDLE_CODE(bref.unpack(prach_cfg_v1530_present, 1)); + prach_cfg_v1530.set_present(prach_cfg_v1530_present); + bool ce_rss_cfg_r15_present; HANDLE_CODE(bref.unpack(ce_rss_cfg_r15_present, 1)); + ce_rss_cfg_r15.set_present(ce_rss_cfg_r15_present); + bool wus_cfg_r15_present; HANDLE_CODE(bref.unpack(wus_cfg_r15_present, 1)); + wus_cfg_r15.set_present(wus_cfg_r15_present); + bool high_speed_cfg_v1530_present; HANDLE_CODE(bref.unpack(high_speed_cfg_v1530_present, 1)); - if (prach_cfg_v1530_present) { - prach_cfg_v1530 = make_copy_ptr(prach_cfg_sib_v1530_s()); + high_speed_cfg_v1530.set_present(high_speed_cfg_v1530_present); + if (prach_cfg_v1530.is_present()) { HANDLE_CODE(prach_cfg_v1530->unpack(bref)); } - if (ce_rss_cfg_r15_present) { - ce_rss_cfg_r15 = make_copy_ptr(rss_cfg_r15_s()); + if (ce_rss_cfg_r15.is_present()) { HANDLE_CODE(ce_rss_cfg_r15->unpack(bref)); } - if (wus_cfg_r15_present) { - wus_cfg_r15 = make_copy_ptr(wus_cfg_r15_s()); + if (wus_cfg_r15.is_present()) { HANDLE_CODE(wus_cfg_r15->unpack(bref)); } - if (high_speed_cfg_v1530_present) { - high_speed_cfg_v1530 = make_copy_ptr(high_speed_cfg_v1530_s()); + if (high_speed_cfg_v1530.is_present()) { HANDLE_CODE(high_speed_cfg_v1530->unpack(bref)); } } @@ -12931,89 +12893,71 @@ void rr_cfg_common_sib_s::to_json(json_writer& j) const ul_pwr_ctrl_common.to_json(j); j.write_str("ul-CyclicPrefixLength", ul_cp_len.to_string()); if (ext) { - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1020_present != (ul_pwr_ctrl_common_v1020.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_common_v1020_present) { + if (ul_pwr_ctrl_common_v1020.is_present()) { j.write_fieldname("uplinkPowerControlCommon-v1020"); ul_pwr_ctrl_common_v1020->to_json(j); } - rrc_asn1_warn_assert(rach_cfg_common_v1250_present != (rach_cfg_common_v1250.get() != NULL), __FILE__, __LINE__); - if (rach_cfg_common_v1250_present) { + if (rach_cfg_common_v1250.is_present()) { j.write_fieldname("rach-ConfigCommon-v1250"); rach_cfg_common_v1250->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_common_v1270_present != (pusch_cfg_common_v1270.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_common_v1270_present) { + if (pusch_cfg_common_v1270.is_present()) { j.write_fieldname("pusch-ConfigCommon-v1270"); pusch_cfg_common_v1270->to_json(j); } - rrc_asn1_warn_assert(bcch_cfg_v1310_present != (bcch_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (bcch_cfg_v1310_present) { + if (bcch_cfg_v1310.is_present()) { j.write_fieldname("bcch-Config-v1310"); bcch_cfg_v1310->to_json(j); } - rrc_asn1_warn_assert(pcch_cfg_v1310_present != (pcch_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (pcch_cfg_v1310_present) { + if (pcch_cfg_v1310.is_present()) { j.write_fieldname("pcch-Config-v1310"); pcch_cfg_v1310->to_json(j); } - rrc_asn1_warn_assert(freq_hop_params_r13_present != (freq_hop_params_r13.get() != NULL), __FILE__, __LINE__); - if (freq_hop_params_r13_present) { + if (freq_hop_params_r13.is_present()) { j.write_fieldname("freqHoppingParameters-r13"); freq_hop_params_r13->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_common_v1310_present != (pdsch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_common_v1310_present) { + if (pdsch_cfg_common_v1310.is_present()) { j.write_fieldname("pdsch-ConfigCommon-v1310"); pdsch_cfg_common_v1310->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_common_v1310_present != (pusch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_common_v1310_present) { + if (pusch_cfg_common_v1310.is_present()) { j.write_fieldname("pusch-ConfigCommon-v1310"); pusch_cfg_common_v1310->to_json(j); } - rrc_asn1_warn_assert(prach_cfg_common_v1310_present != (prach_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - if (prach_cfg_common_v1310_present) { + if (prach_cfg_common_v1310.is_present()) { j.write_fieldname("prach-ConfigCommon-v1310"); prach_cfg_common_v1310->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_common_v1310_present != (pucch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_common_v1310_present) { + if (pucch_cfg_common_v1310.is_present()) { j.write_fieldname("pucch-ConfigCommon-v1310"); pucch_cfg_common_v1310->to_json(j); } - rrc_asn1_warn_assert(high_speed_cfg_r14_present != (high_speed_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (high_speed_cfg_r14_present) { + if (high_speed_cfg_r14.is_present()) { j.write_fieldname("highSpeedConfig-r14"); high_speed_cfg_r14->to_json(j); } - rrc_asn1_warn_assert(prach_cfg_v1430_present != (prach_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (prach_cfg_v1430_present) { + if (prach_cfg_v1430.is_present()) { j.write_fieldname("prach-Config-v1430"); prach_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_common_v1430_present != (pucch_cfg_common_v1430.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_common_v1430_present) { + if (pucch_cfg_common_v1430.is_present()) { j.write_fieldname("pucch-ConfigCommon-v1430"); pucch_cfg_common_v1430->to_json(j); } - rrc_asn1_warn_assert(prach_cfg_v1530_present != (prach_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (prach_cfg_v1530_present) { + if (prach_cfg_v1530.is_present()) { j.write_fieldname("prach-Config-v1530"); prach_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert(ce_rss_cfg_r15_present != (ce_rss_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (ce_rss_cfg_r15_present) { + if (ce_rss_cfg_r15.is_present()) { j.write_fieldname("ce-RSS-Config-r15"); ce_rss_cfg_r15->to_json(j); } - rrc_asn1_warn_assert(wus_cfg_r15_present != (wus_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (wus_cfg_r15_present) { + if (wus_cfg_r15.is_present()) { j.write_fieldname("wus-Config-r15"); wus_cfg_r15->to_json(j); } - rrc_asn1_warn_assert(high_speed_cfg_v1530_present != (high_speed_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (high_speed_cfg_v1530_present) { + if (high_speed_cfg_v1530.is_present()) { j.write_fieldname("highSpeedConfig-v1530"); high_speed_cfg_v1530->to_json(j); } @@ -14101,7 +14045,7 @@ SRSASN_CODE ue_timers_and_consts_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, n311)); if (ext) { - ext_groups_header group_flags(3); + ext_groups_packer_guard group_flags; group_flags[0] |= t300_v1310_present; group_flags[0] |= t301_v1310_present; group_flags[1] |= t310_v1330_present; @@ -14109,7 +14053,7 @@ SRSASN_CODE ue_timers_and_consts_s::pack(bit_ref& bref) const group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(t300_v1310_present, 1)); HANDLE_CODE(bref.pack(t301_v1310_present, 1)); @@ -14121,7 +14065,7 @@ SRSASN_CODE ue_timers_and_consts_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(t310_v1330_present, 1)); if (t310_v1330_present) { @@ -14129,7 +14073,7 @@ SRSASN_CODE ue_timers_and_consts_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(t300_r15_present, 1)); if (t300_r15_present) { @@ -14150,11 +14094,11 @@ SRSASN_CODE ue_timers_and_consts_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(n311, bref)); if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(t300_v1310_present, 1)); HANDLE_CODE(bref.unpack(t301_v1310_present, 1)); @@ -14166,7 +14110,7 @@ SRSASN_CODE ue_timers_and_consts_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(t310_v1330_present, 1)); if (t310_v1330_present) { @@ -14174,7 +14118,7 @@ SRSASN_CODE ue_timers_and_consts_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(t300_r15_present, 1)); if (t300_r15_present) { @@ -14597,12 +14541,12 @@ SRSASN_CODE sib_type12_r9_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= warning_area_coordinates_segment_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(warning_area_coordinates_segment_r15_present, 1)); if (warning_area_coordinates_segment_r15_present) { @@ -14631,11 +14575,11 @@ SRSASN_CODE sib_type12_r9_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(warning_area_coordinates_segment_r15_present, 1)); if (warning_area_coordinates_segment_r15_present) { @@ -14680,16 +14624,15 @@ SRSASN_CODE sib_type13_r9_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(notif_cfg_v1430_present != (notif_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= notif_cfg_v1430_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= notif_cfg_v1430.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(notif_cfg_v1430_present, 1)); - if (notif_cfg_v1430_present) { + HANDLE_CODE(bref.pack(notif_cfg_v1430.is_present(), 1)); + if (notif_cfg_v1430.is_present()) { HANDLE_CODE(notif_cfg_v1430->pack(bref)); } } @@ -14708,15 +14651,16 @@ SRSASN_CODE sib_type13_r9_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool notif_cfg_v1430_present; HANDLE_CODE(bref.unpack(notif_cfg_v1430_present, 1)); - if (notif_cfg_v1430_present) { - notif_cfg_v1430 = make_copy_ptr(mbms_notif_cfg_v1430_s()); + notif_cfg_v1430.set_present(notif_cfg_v1430_present); + if (notif_cfg_v1430.is_present()) { HANDLE_CODE(notif_cfg_v1430->unpack(bref)); } } @@ -14737,8 +14681,7 @@ void sib_type13_r9_s::to_json(json_writer& j) const j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } if (ext) { - rrc_asn1_warn_assert(notif_cfg_v1430_present != (notif_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (notif_cfg_v1430_present) { + if (notif_cfg_v1430.is_present()) { j.write_fieldname("notificationConfig-v1430"); notif_cfg_v1430->to_json(j); } @@ -14761,12 +14704,12 @@ SRSASN_CODE sib_type14_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= eab_per_rsrp_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(eab_per_rsrp_r15_present, 1)); if (eab_per_rsrp_r15_present) { @@ -14790,11 +14733,11 @@ SRSASN_CODE sib_type14_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(eab_per_rsrp_r15_present, 1)); if (eab_per_rsrp_r15_present) { @@ -14964,38 +14907,29 @@ SRSASN_CODE sib_type15_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert( - mbms_sai_inter_freq_list_v1140_present != (mbms_sai_inter_freq_list_v1140.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= mbms_sai_inter_freq_list_v1140_present; - rrc_asn1_warn_assert(mbms_intra_freq_carrier_type_r14_present != (mbms_intra_freq_carrier_type_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= mbms_intra_freq_carrier_type_r14_present; - rrc_asn1_warn_assert(mbms_inter_freq_carrier_type_list_r14_present != - (mbms_inter_freq_carrier_type_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= mbms_inter_freq_carrier_type_list_r14_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= mbms_sai_inter_freq_list_v1140.is_present(); + group_flags[1] |= mbms_intra_freq_carrier_type_r14.is_present(); + group_flags[1] |= mbms_inter_freq_carrier_type_list_r14.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbms_sai_inter_freq_list_v1140_present, 1)); - if (mbms_sai_inter_freq_list_v1140_present) { + HANDLE_CODE(bref.pack(mbms_sai_inter_freq_list_v1140.is_present(), 1)); + if (mbms_sai_inter_freq_list_v1140.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *mbms_sai_inter_freq_list_v1140, 1, 8)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbms_intra_freq_carrier_type_r14_present, 1)); - HANDLE_CODE(bref.pack(mbms_inter_freq_carrier_type_list_r14_present, 1)); - if (mbms_intra_freq_carrier_type_r14_present) { + HANDLE_CODE(bref.pack(mbms_intra_freq_carrier_type_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(mbms_inter_freq_carrier_type_list_r14.is_present(), 1)); + if (mbms_intra_freq_carrier_type_r14.is_present()) { HANDLE_CODE(mbms_intra_freq_carrier_type_r14->pack(bref)); } - if (mbms_inter_freq_carrier_type_list_r14_present) { + if (mbms_inter_freq_carrier_type_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *mbms_inter_freq_carrier_type_list_r14, 1, 8)); } } @@ -15020,29 +14954,32 @@ SRSASN_CODE sib_type15_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mbms_sai_inter_freq_list_v1140_present; HANDLE_CODE(bref.unpack(mbms_sai_inter_freq_list_v1140_present, 1)); - if (mbms_sai_inter_freq_list_v1140_present) { - mbms_sai_inter_freq_list_v1140 = make_copy_ptr(mbms_sai_inter_freq_list_v1140_l()); + mbms_sai_inter_freq_list_v1140.set_present(mbms_sai_inter_freq_list_v1140_present); + if (mbms_sai_inter_freq_list_v1140.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*mbms_sai_inter_freq_list_v1140, bref, 1, 8)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mbms_intra_freq_carrier_type_r14_present; HANDLE_CODE(bref.unpack(mbms_intra_freq_carrier_type_r14_present, 1)); + mbms_intra_freq_carrier_type_r14.set_present(mbms_intra_freq_carrier_type_r14_present); + bool mbms_inter_freq_carrier_type_list_r14_present; HANDLE_CODE(bref.unpack(mbms_inter_freq_carrier_type_list_r14_present, 1)); - if (mbms_intra_freq_carrier_type_r14_present) { - mbms_intra_freq_carrier_type_r14 = make_copy_ptr(mbms_carrier_type_r14_s()); + mbms_inter_freq_carrier_type_list_r14.set_present(mbms_inter_freq_carrier_type_list_r14_present); + if (mbms_intra_freq_carrier_type_r14.is_present()) { HANDLE_CODE(mbms_intra_freq_carrier_type_r14->unpack(bref)); } - if (mbms_inter_freq_carrier_type_list_r14_present) { - mbms_inter_freq_carrier_type_list_r14 = make_copy_ptr(mbms_inter_freq_carrier_type_list_r14_l()); + if (mbms_inter_freq_carrier_type_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*mbms_inter_freq_carrier_type_list_r14, bref, 1, 8)); } } @@ -15070,27 +15007,18 @@ void sib_type15_r11_s::to_json(json_writer& j) const j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } if (ext) { - rrc_asn1_warn_assert( - mbms_sai_inter_freq_list_v1140_present != (mbms_sai_inter_freq_list_v1140.get() != NULL), __FILE__, __LINE__); - if (mbms_sai_inter_freq_list_v1140_present) { + if (mbms_sai_inter_freq_list_v1140.is_present()) { j.start_array("mbms-SAI-InterFreqList-v1140"); for (uint32_t i1 = 0; i1 < mbms_sai_inter_freq_list_v1140->size(); ++i1) { ((*mbms_sai_inter_freq_list_v1140)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(mbms_intra_freq_carrier_type_r14_present != (mbms_intra_freq_carrier_type_r14.get() != NULL), - __FILE__, - __LINE__); - if (mbms_intra_freq_carrier_type_r14_present) { + if (mbms_intra_freq_carrier_type_r14.is_present()) { j.write_fieldname("mbms-IntraFreqCarrierType-r14"); mbms_intra_freq_carrier_type_r14->to_json(j); } - rrc_asn1_warn_assert(mbms_inter_freq_carrier_type_list_r14_present != - (mbms_inter_freq_carrier_type_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (mbms_inter_freq_carrier_type_list_r14_present) { + if (mbms_inter_freq_carrier_type_list_r14.is_present()) { j.start_array("mbms-InterFreqCarrierTypeList-r14"); for (uint32_t i1 = 0; i1 < mbms_inter_freq_carrier_type_list_r14->size(); ++i1) { ((*mbms_inter_freq_carrier_type_list_r14)[i1]).to_json(j); @@ -15128,16 +15056,15 @@ SRSASN_CODE sib_type16_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(time_ref_info_r15_present != (time_ref_info_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= time_ref_info_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= time_ref_info_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(time_ref_info_r15_present, 1)); - if (time_ref_info_r15_present) { + HANDLE_CODE(bref.pack(time_ref_info_r15.is_present(), 1)); + if (time_ref_info_r15.is_present()) { HANDLE_CODE(time_ref_info_r15->pack(bref)); } } @@ -15170,15 +15097,16 @@ SRSASN_CODE sib_type16_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool time_ref_info_r15_present; HANDLE_CODE(bref.unpack(time_ref_info_r15_present, 1)); - if (time_ref_info_r15_present) { - time_ref_info_r15 = make_copy_ptr(time_ref_info_r15_s()); + time_ref_info_r15.set_present(time_ref_info_r15_present); + if (time_ref_info_r15.is_present()) { HANDLE_CODE(time_ref_info_r15->unpack(bref)); } } @@ -15207,8 +15135,7 @@ void sib_type16_r11_s::to_json(json_writer& j) const j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } if (ext) { - rrc_asn1_warn_assert(time_ref_info_r15_present != (time_ref_info_r15.get() != NULL), __FILE__, __LINE__); - if (time_ref_info_r15_present) { + if (time_ref_info_r15.is_present()) { j.write_fieldname("timeReferenceInfo-r15"); time_ref_info_r15->to_json(j); } @@ -15290,23 +15217,19 @@ SRSASN_CODE sib_type18_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(comm_tx_pool_normal_common_ext_r13_present != - (comm_tx_pool_normal_common_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= comm_tx_pool_normal_common_ext_r13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= comm_tx_pool_normal_common_ext_r13.is_present(); group_flags[0] |= comm_tx_res_uc_req_allowed_r13_present; group_flags[0] |= comm_tx_allow_relay_common_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(comm_tx_pool_normal_common_ext_r13_present, 1)); + HANDLE_CODE(bref.pack(comm_tx_pool_normal_common_ext_r13.is_present(), 1)); HANDLE_CODE(bref.pack(comm_tx_res_uc_req_allowed_r13_present, 1)); HANDLE_CODE(bref.pack(comm_tx_allow_relay_common_r13_present, 1)); - if (comm_tx_pool_normal_common_ext_r13_present) { + if (comm_tx_pool_normal_common_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *comm_tx_pool_normal_common_ext_r13, 1, 4)); } } @@ -15339,17 +15262,18 @@ SRSASN_CODE sib_type18_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool comm_tx_pool_normal_common_ext_r13_present; HANDLE_CODE(bref.unpack(comm_tx_pool_normal_common_ext_r13_present, 1)); + comm_tx_pool_normal_common_ext_r13.set_present(comm_tx_pool_normal_common_ext_r13_present); HANDLE_CODE(bref.unpack(comm_tx_res_uc_req_allowed_r13_present, 1)); HANDLE_CODE(bref.unpack(comm_tx_allow_relay_common_r13_present, 1)); - if (comm_tx_pool_normal_common_ext_r13_present) { - comm_tx_pool_normal_common_ext_r13 = make_copy_ptr(sl_comm_tx_pool_list_ext_r13_l()); + if (comm_tx_pool_normal_common_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*comm_tx_pool_normal_common_ext_r13, bref, 1, 4)); } } @@ -15394,11 +15318,7 @@ void sib_type18_r12_s::to_json(json_writer& j) const j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } if (ext) { - rrc_asn1_warn_assert(comm_tx_pool_normal_common_ext_r13_present != - (comm_tx_pool_normal_common_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (comm_tx_pool_normal_common_ext_r13_present) { + if (comm_tx_pool_normal_common_ext_r13.is_present()) { j.start_array("commTxPoolNormalCommonExt-r13"); for (uint32_t i1 = 0; i1 < comm_tx_pool_normal_common_ext_r13->size(); ++i1) { ((*comm_tx_pool_normal_common_ext_r13)[i1]).to_json(j); @@ -15447,33 +15367,30 @@ SRSASN_CODE sib_type19_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(disc_cfg_v1310_present != (disc_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= disc_cfg_v1310_present; - rrc_asn1_warn_assert(disc_cfg_relay_r13_present != (disc_cfg_relay_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= disc_cfg_relay_r13_present; - rrc_asn1_warn_assert(disc_cfg_ps_minus13_present != (disc_cfg_ps_minus13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= disc_cfg_ps_minus13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= disc_cfg_v1310.is_present(); + group_flags[0] |= disc_cfg_relay_r13.is_present(); + group_flags[0] |= disc_cfg_ps_minus13.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(disc_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(disc_cfg_relay_r13_present, 1)); - HANDLE_CODE(bref.pack(disc_cfg_ps_minus13_present, 1)); - if (disc_cfg_v1310_present) { + HANDLE_CODE(bref.pack(disc_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(disc_cfg_relay_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(disc_cfg_ps_minus13.is_present(), 1)); + if (disc_cfg_v1310.is_present()) { HANDLE_CODE(bref.pack(disc_cfg_v1310->disc_inter_freq_list_v1310_present, 1)); HANDLE_CODE(bref.pack(disc_cfg_v1310->gap_requests_allowed_common_present, 1)); if (disc_cfg_v1310->disc_inter_freq_list_v1310_present) { HANDLE_CODE(pack_dyn_seq_of(bref, disc_cfg_v1310->disc_inter_freq_list_v1310, 1, 8)); } } - if (disc_cfg_relay_r13_present) { + if (disc_cfg_relay_r13.is_present()) { HANDLE_CODE(disc_cfg_relay_r13->relay_ue_cfg_r13.pack(bref)); HANDLE_CODE(disc_cfg_relay_r13->remote_ue_cfg_r13.pack(bref)); } - if (disc_cfg_ps_minus13_present) { + if (disc_cfg_ps_minus13.is_present()) { HANDLE_CODE(bref.pack(disc_cfg_ps_minus13->disc_tx_pool_ps_common_r13_present, 1)); HANDLE_CODE(pack_dyn_seq_of(bref, disc_cfg_ps_minus13->disc_rx_pool_ps_r13, 1, 16)); if (disc_cfg_ps_minus13->disc_tx_pool_ps_common_r13_present) { @@ -15515,30 +15432,33 @@ SRSASN_CODE sib_type19_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool disc_cfg_v1310_present; HANDLE_CODE(bref.unpack(disc_cfg_v1310_present, 1)); + disc_cfg_v1310.set_present(disc_cfg_v1310_present); + bool disc_cfg_relay_r13_present; HANDLE_CODE(bref.unpack(disc_cfg_relay_r13_present, 1)); + disc_cfg_relay_r13.set_present(disc_cfg_relay_r13_present); + bool disc_cfg_ps_minus13_present; HANDLE_CODE(bref.unpack(disc_cfg_ps_minus13_present, 1)); - if (disc_cfg_v1310_present) { - disc_cfg_v1310 = make_copy_ptr(disc_cfg_v1310_s_()); + disc_cfg_ps_minus13.set_present(disc_cfg_ps_minus13_present); + if (disc_cfg_v1310.is_present()) { HANDLE_CODE(bref.unpack(disc_cfg_v1310->disc_inter_freq_list_v1310_present, 1)); HANDLE_CODE(bref.unpack(disc_cfg_v1310->gap_requests_allowed_common_present, 1)); if (disc_cfg_v1310->disc_inter_freq_list_v1310_present) { HANDLE_CODE(unpack_dyn_seq_of(disc_cfg_v1310->disc_inter_freq_list_v1310, bref, 1, 8)); } } - if (disc_cfg_relay_r13_present) { - disc_cfg_relay_r13 = make_copy_ptr(disc_cfg_relay_r13_s_()); + if (disc_cfg_relay_r13.is_present()) { HANDLE_CODE(disc_cfg_relay_r13->relay_ue_cfg_r13.unpack(bref)); HANDLE_CODE(disc_cfg_relay_r13->remote_ue_cfg_r13.unpack(bref)); } - if (disc_cfg_ps_minus13_present) { - disc_cfg_ps_minus13 = make_copy_ptr(disc_cfg_ps_minus13_s_()); + if (disc_cfg_ps_minus13.is_present()) { HANDLE_CODE(bref.unpack(disc_cfg_ps_minus13->disc_tx_pool_ps_common_r13_present, 1)); HANDLE_CODE(unpack_dyn_seq_of(disc_cfg_ps_minus13->disc_rx_pool_ps_r13, bref, 1, 16)); if (disc_cfg_ps_minus13->disc_tx_pool_ps_common_r13_present) { @@ -15594,8 +15514,7 @@ void sib_type19_r12_s::to_json(json_writer& j) const j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } if (ext) { - rrc_asn1_warn_assert(disc_cfg_v1310_present != (disc_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (disc_cfg_v1310_present) { + if (disc_cfg_v1310.is_present()) { j.write_fieldname("discConfig-v1310"); j.start_obj(); if (disc_cfg_v1310->disc_inter_freq_list_v1310_present) { @@ -15610,8 +15529,7 @@ void sib_type19_r12_s::to_json(json_writer& j) const } j.end_obj(); } - rrc_asn1_warn_assert(disc_cfg_relay_r13_present != (disc_cfg_relay_r13.get() != NULL), __FILE__, __LINE__); - if (disc_cfg_relay_r13_present) { + if (disc_cfg_relay_r13.is_present()) { j.write_fieldname("discConfigRelay-r13"); j.start_obj(); j.write_fieldname("relayUE-Config-r13"); @@ -15620,8 +15538,7 @@ void sib_type19_r12_s::to_json(json_writer& j) const disc_cfg_relay_r13->remote_ue_cfg_r13.to_json(j); j.end_obj(); } - rrc_asn1_warn_assert(disc_cfg_ps_minus13_present != (disc_cfg_ps_minus13.get() != NULL), __FILE__, __LINE__); - if (disc_cfg_ps_minus13_present) { + if (disc_cfg_ps_minus13.is_present()) { j.write_fieldname("discConfigPS-13"); j.start_obj(); j.start_array("discRxPoolPS-r13"); @@ -15677,147 +15594,126 @@ SRSASN_CODE sib_type2_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, time_align_timer_common)); if (ext) { - ext_groups_header group_flags(10, 1); - rrc_asn1_warn_assert( - ssac_barr_for_mmtel_voice_r9_present != (ssac_barr_for_mmtel_voice_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ssac_barr_for_mmtel_voice_r9_present; - rrc_asn1_warn_assert( - ssac_barr_for_mmtel_video_r9_present != (ssac_barr_for_mmtel_video_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ssac_barr_for_mmtel_video_r9_present; - rrc_asn1_warn_assert(ac_barr_for_csfb_r10_present != (ac_barr_for_csfb_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ac_barr_for_csfb_r10_present; - group_flags[2] |= ac_barr_skip_for_mmtel_voice_r12_present; - group_flags[2] |= ac_barr_skip_for_mmtel_video_r12_present; - group_flags[2] |= ac_barr_skip_for_sms_r12_present; - rrc_asn1_warn_assert( - ac_barr_per_plmn_list_r12_present != (ac_barr_per_plmn_list_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= ac_barr_per_plmn_list_r12_present; - group_flags[3] |= voice_service_cause_ind_r12_present; - rrc_asn1_warn_assert( - acdc_barr_for_common_r13_present != (acdc_barr_for_common_r13.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= acdc_barr_for_common_r13_present; - rrc_asn1_warn_assert( - acdc_barr_per_plmn_list_r13_present != (acdc_barr_per_plmn_list_r13.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= acdc_barr_per_plmn_list_r13_present; - rrc_asn1_warn_assert( - udt_restricting_for_common_r13_present != (udt_restricting_for_common_r13.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= udt_restricting_for_common_r13_present; - rrc_asn1_warn_assert(udt_restricting_per_plmn_list_r13_present != (udt_restricting_per_plmn_list_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[5] |= udt_restricting_per_plmn_list_r13_present; - rrc_asn1_warn_assert( - c_io_t_eps_optim_info_r13_present != (c_io_t_eps_optim_info_r13.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= c_io_t_eps_optim_info_r13_present; - group_flags[5] |= use_full_resume_id_r13_present; - group_flags[6] |= unicast_freq_hop_ind_r13_present; - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= mbsfn_sf_cfg_list_v1430_present; - group_flags[7] |= video_service_cause_ind_r14_present; - rrc_asn1_warn_assert(plmn_info_list_r15_present != (plmn_info_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= plmn_info_list_r15_present; - group_flags[9] |= cp_edt_r15_present; - group_flags[9] |= up_edt_r15_present; - group_flags[9] |= idle_mode_meass_r15_present; - group_flags[9] |= reduced_cp_latency_enabled_r15_present; - group_flags.pack_nof_groups(bref); - HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); - group_flags.pack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.pack(bref)); - } + ext_groups_packer_guard group_flags; + group_flags[0] |= late_non_crit_ext_present; + group_flags[1] |= ssac_barr_for_mmtel_voice_r9.is_present(); + group_flags[1] |= ssac_barr_for_mmtel_video_r9.is_present(); + group_flags[2] |= ac_barr_for_csfb_r10.is_present(); + group_flags[3] |= ac_barr_skip_for_mmtel_voice_r12_present; + group_flags[3] |= ac_barr_skip_for_mmtel_video_r12_present; + group_flags[3] |= ac_barr_skip_for_sms_r12_present; + group_flags[3] |= ac_barr_per_plmn_list_r12.is_present(); + group_flags[4] |= voice_service_cause_ind_r12_present; + group_flags[5] |= acdc_barr_for_common_r13.is_present(); + group_flags[5] |= acdc_barr_per_plmn_list_r13.is_present(); + group_flags[6] |= udt_restricting_for_common_r13.is_present(); + group_flags[6] |= udt_restricting_per_plmn_list_r13.is_present(); + group_flags[6] |= c_io_t_eps_optim_info_r13.is_present(); + group_flags[6] |= use_full_resume_id_r13_present; + group_flags[7] |= unicast_freq_hop_ind_r13_present; + group_flags[8] |= mbsfn_sf_cfg_list_v1430.is_present(); + group_flags[8] |= video_service_cause_ind_r14_present; + group_flags[9] |= plmn_info_list_r15.is_present(); + group_flags[10] |= cp_edt_r15_present; + group_flags[10] |= up_edt_r15_present; + group_flags[10] |= idle_mode_meass_r15_present; + group_flags[10] |= reduced_cp_latency_enabled_r15_present; + group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ssac_barr_for_mmtel_voice_r9_present, 1)); - HANDLE_CODE(bref.pack(ssac_barr_for_mmtel_video_r9_present, 1)); - if (ssac_barr_for_mmtel_voice_r9_present) { + HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(ssac_barr_for_mmtel_voice_r9.is_present(), 1)); + HANDLE_CODE(bref.pack(ssac_barr_for_mmtel_video_r9.is_present(), 1)); + if (ssac_barr_for_mmtel_voice_r9.is_present()) { HANDLE_CODE(ssac_barr_for_mmtel_voice_r9->pack(bref)); } - if (ssac_barr_for_mmtel_video_r9_present) { + if (ssac_barr_for_mmtel_video_r9.is_present()) { HANDLE_CODE(ssac_barr_for_mmtel_video_r9->pack(bref)); } } - if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + if (group_flags[2]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ac_barr_for_csfb_r10_present, 1)); - if (ac_barr_for_csfb_r10_present) { + HANDLE_CODE(bref.pack(ac_barr_for_csfb_r10.is_present(), 1)); + if (ac_barr_for_csfb_r10.is_present()) { HANDLE_CODE(ac_barr_for_csfb_r10->pack(bref)); } } - if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + if (group_flags[3]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(ac_barr_skip_for_mmtel_voice_r12_present, 1)); HANDLE_CODE(bref.pack(ac_barr_skip_for_mmtel_video_r12_present, 1)); HANDLE_CODE(bref.pack(ac_barr_skip_for_sms_r12_present, 1)); - HANDLE_CODE(bref.pack(ac_barr_per_plmn_list_r12_present, 1)); - if (ac_barr_per_plmn_list_r12_present) { + HANDLE_CODE(bref.pack(ac_barr_per_plmn_list_r12.is_present(), 1)); + if (ac_barr_per_plmn_list_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *ac_barr_per_plmn_list_r12, 1, 6)); } } - if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + if (group_flags[4]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(voice_service_cause_ind_r12_present, 1)); } - if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + if (group_flags[5]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(acdc_barr_for_common_r13_present, 1)); - HANDLE_CODE(bref.pack(acdc_barr_per_plmn_list_r13_present, 1)); - if (acdc_barr_for_common_r13_present) { + HANDLE_CODE(bref.pack(acdc_barr_for_common_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(acdc_barr_per_plmn_list_r13.is_present(), 1)); + if (acdc_barr_for_common_r13.is_present()) { HANDLE_CODE(acdc_barr_for_common_r13->pack(bref)); } - if (acdc_barr_per_plmn_list_r13_present) { + if (acdc_barr_per_plmn_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *acdc_barr_per_plmn_list_r13, 1, 6)); } } - if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + if (group_flags[6]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(udt_restricting_for_common_r13_present, 1)); - HANDLE_CODE(bref.pack(udt_restricting_per_plmn_list_r13_present, 1)); - HANDLE_CODE(bref.pack(c_io_t_eps_optim_info_r13_present, 1)); + HANDLE_CODE(bref.pack(udt_restricting_for_common_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(udt_restricting_per_plmn_list_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(c_io_t_eps_optim_info_r13.is_present(), 1)); HANDLE_CODE(bref.pack(use_full_resume_id_r13_present, 1)); - if (udt_restricting_for_common_r13_present) { + if (udt_restricting_for_common_r13.is_present()) { HANDLE_CODE(udt_restricting_for_common_r13->pack(bref)); } - if (udt_restricting_per_plmn_list_r13_present) { + if (udt_restricting_per_plmn_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *udt_restricting_per_plmn_list_r13, 1, 6)); } - if (c_io_t_eps_optim_info_r13_present) { + if (c_io_t_eps_optim_info_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *c_io_t_eps_optim_info_r13, 1, 6)); } } - if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + if (group_flags[7]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(unicast_freq_hop_ind_r13_present, 1)); } - if (group_flags[7]) { - varlength_field_pack_guard packer(bref); + if (group_flags[8]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430_present, 1)); + HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430.is_present(), 1)); HANDLE_CODE(bref.pack(video_service_cause_ind_r14_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *mbsfn_sf_cfg_list_v1430, 1, 8)); } } - if (group_flags[8]) { - varlength_field_pack_guard packer(bref); + if (group_flags[9]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(plmn_info_list_r15_present, 1)); - if (plmn_info_list_r15_present) { + HANDLE_CODE(bref.pack(plmn_info_list_r15.is_present(), 1)); + if (plmn_info_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *plmn_info_list_r15, 1, 6)); } } - if (group_flags[9]) { - varlength_field_pack_guard packer(bref); + if (group_flags[10]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(cp_edt_r15_present, 1)); HANDLE_CODE(bref.pack(up_edt_r15_present, 1)); @@ -15861,115 +15757,125 @@ SRSASN_CODE sib_type2_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(time_align_timer_common, bref)); if (ext) { - ext_groups_header group_flags(10, 1); - group_flags.unpack_nof_groups(bref); - HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); - group_flags.unpack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.unpack(bref)); - } + ext_groups_unpacker_guard group_flags(11); + group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_unpack_guard varlen_scope(bref); + + bool ssac_barr_for_mmtel_voice_r9_present; HANDLE_CODE(bref.unpack(ssac_barr_for_mmtel_voice_r9_present, 1)); + ssac_barr_for_mmtel_voice_r9.set_present(ssac_barr_for_mmtel_voice_r9_present); + bool ssac_barr_for_mmtel_video_r9_present; HANDLE_CODE(bref.unpack(ssac_barr_for_mmtel_video_r9_present, 1)); - if (ssac_barr_for_mmtel_voice_r9_present) { - ssac_barr_for_mmtel_voice_r9 = make_copy_ptr(ac_barr_cfg_s()); + ssac_barr_for_mmtel_video_r9.set_present(ssac_barr_for_mmtel_video_r9_present); + if (ssac_barr_for_mmtel_voice_r9.is_present()) { HANDLE_CODE(ssac_barr_for_mmtel_voice_r9->unpack(bref)); } - if (ssac_barr_for_mmtel_video_r9_present) { - ssac_barr_for_mmtel_video_r9 = make_copy_ptr(ac_barr_cfg_s()); + if (ssac_barr_for_mmtel_video_r9.is_present()) { HANDLE_CODE(ssac_barr_for_mmtel_video_r9->unpack(bref)); } } - if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[2]) { + varlength_field_unpack_guard varlen_scope(bref); + bool ac_barr_for_csfb_r10_present; HANDLE_CODE(bref.unpack(ac_barr_for_csfb_r10_present, 1)); - if (ac_barr_for_csfb_r10_present) { - ac_barr_for_csfb_r10 = make_copy_ptr(ac_barr_cfg_s()); + ac_barr_for_csfb_r10.set_present(ac_barr_for_csfb_r10_present); + if (ac_barr_for_csfb_r10.is_present()) { HANDLE_CODE(ac_barr_for_csfb_r10->unpack(bref)); } } - if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[3]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(ac_barr_skip_for_mmtel_voice_r12_present, 1)); HANDLE_CODE(bref.unpack(ac_barr_skip_for_mmtel_video_r12_present, 1)); HANDLE_CODE(bref.unpack(ac_barr_skip_for_sms_r12_present, 1)); + bool ac_barr_per_plmn_list_r12_present; HANDLE_CODE(bref.unpack(ac_barr_per_plmn_list_r12_present, 1)); - if (ac_barr_per_plmn_list_r12_present) { - ac_barr_per_plmn_list_r12 = make_copy_ptr(ac_barr_per_plmn_list_r12_l()); + ac_barr_per_plmn_list_r12.set_present(ac_barr_per_plmn_list_r12_present); + if (ac_barr_per_plmn_list_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*ac_barr_per_plmn_list_r12, bref, 1, 6)); } } - if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[4]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(voice_service_cause_ind_r12_present, 1)); } - if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[5]) { + varlength_field_unpack_guard varlen_scope(bref); + bool acdc_barr_for_common_r13_present; HANDLE_CODE(bref.unpack(acdc_barr_for_common_r13_present, 1)); + acdc_barr_for_common_r13.set_present(acdc_barr_for_common_r13_present); + bool acdc_barr_per_plmn_list_r13_present; HANDLE_CODE(bref.unpack(acdc_barr_per_plmn_list_r13_present, 1)); - if (acdc_barr_for_common_r13_present) { - acdc_barr_for_common_r13 = make_copy_ptr(acdc_barr_for_common_r13_s()); + acdc_barr_per_plmn_list_r13.set_present(acdc_barr_per_plmn_list_r13_present); + if (acdc_barr_for_common_r13.is_present()) { HANDLE_CODE(acdc_barr_for_common_r13->unpack(bref)); } - if (acdc_barr_per_plmn_list_r13_present) { - acdc_barr_per_plmn_list_r13 = make_copy_ptr(acdc_barr_per_plmn_list_r13_l()); + if (acdc_barr_per_plmn_list_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*acdc_barr_per_plmn_list_r13, bref, 1, 6)); } } - if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[6]) { + varlength_field_unpack_guard varlen_scope(bref); + bool udt_restricting_for_common_r13_present; HANDLE_CODE(bref.unpack(udt_restricting_for_common_r13_present, 1)); + udt_restricting_for_common_r13.set_present(udt_restricting_for_common_r13_present); + bool udt_restricting_per_plmn_list_r13_present; HANDLE_CODE(bref.unpack(udt_restricting_per_plmn_list_r13_present, 1)); + udt_restricting_per_plmn_list_r13.set_present(udt_restricting_per_plmn_list_r13_present); + bool c_io_t_eps_optim_info_r13_present; HANDLE_CODE(bref.unpack(c_io_t_eps_optim_info_r13_present, 1)); + c_io_t_eps_optim_info_r13.set_present(c_io_t_eps_optim_info_r13_present); HANDLE_CODE(bref.unpack(use_full_resume_id_r13_present, 1)); - if (udt_restricting_for_common_r13_present) { - udt_restricting_for_common_r13 = make_copy_ptr(udt_restricting_r13_s()); + if (udt_restricting_for_common_r13.is_present()) { HANDLE_CODE(udt_restricting_for_common_r13->unpack(bref)); } - if (udt_restricting_per_plmn_list_r13_present) { - udt_restricting_per_plmn_list_r13 = make_copy_ptr(udt_restricting_per_plmn_list_r13_l()); + if (udt_restricting_per_plmn_list_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*udt_restricting_per_plmn_list_r13, bref, 1, 6)); } - if (c_io_t_eps_optim_info_r13_present) { - c_io_t_eps_optim_info_r13 = make_copy_ptr(ciot_eps_optim_info_r13_l()); + if (c_io_t_eps_optim_info_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*c_io_t_eps_optim_info_r13, bref, 1, 6)); } } - if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[7]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(unicast_freq_hop_ind_r13_present, 1)); } - if (group_flags[7]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[8]) { + varlength_field_unpack_guard varlen_scope(bref); + bool mbsfn_sf_cfg_list_v1430_present; HANDLE_CODE(bref.unpack(mbsfn_sf_cfg_list_v1430_present, 1)); + mbsfn_sf_cfg_list_v1430.set_present(mbsfn_sf_cfg_list_v1430_present); HANDLE_CODE(bref.unpack(video_service_cause_ind_r14_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { - mbsfn_sf_cfg_list_v1430 = make_copy_ptr(mbsfn_sf_cfg_list_v1430_l()); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*mbsfn_sf_cfg_list_v1430, bref, 1, 8)); } } - if (group_flags[8]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[9]) { + varlength_field_unpack_guard varlen_scope(bref); + bool plmn_info_list_r15_present; HANDLE_CODE(bref.unpack(plmn_info_list_r15_present, 1)); - if (plmn_info_list_r15_present) { - plmn_info_list_r15 = make_copy_ptr(plmn_info_list_r15_l()); + plmn_info_list_r15.set_present(plmn_info_list_r15_present); + if (plmn_info_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*plmn_info_list_r15, bref, 1, 6)); } } - if (group_flags[9]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[10]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(cp_edt_r15_present, 1)); HANDLE_CODE(bref.unpack(up_edt_r15_present, 1)); @@ -16022,20 +15928,15 @@ void sib_type2_s::to_json(json_writer& j) const if (late_non_crit_ext_present) { j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } - rrc_asn1_warn_assert( - ssac_barr_for_mmtel_voice_r9_present != (ssac_barr_for_mmtel_voice_r9.get() != NULL), __FILE__, __LINE__); - if (ssac_barr_for_mmtel_voice_r9_present) { + if (ssac_barr_for_mmtel_voice_r9.is_present()) { j.write_fieldname("ssac-BarringForMMTEL-Voice-r9"); ssac_barr_for_mmtel_voice_r9->to_json(j); } - rrc_asn1_warn_assert( - ssac_barr_for_mmtel_video_r9_present != (ssac_barr_for_mmtel_video_r9.get() != NULL), __FILE__, __LINE__); - if (ssac_barr_for_mmtel_video_r9_present) { + if (ssac_barr_for_mmtel_video_r9.is_present()) { j.write_fieldname("ssac-BarringForMMTEL-Video-r9"); ssac_barr_for_mmtel_video_r9->to_json(j); } - rrc_asn1_warn_assert(ac_barr_for_csfb_r10_present != (ac_barr_for_csfb_r10.get() != NULL), __FILE__, __LINE__); - if (ac_barr_for_csfb_r10_present) { + if (ac_barr_for_csfb_r10.is_present()) { j.write_fieldname("ac-BarringForCSFB-r10"); ac_barr_for_csfb_r10->to_json(j); } @@ -16048,9 +15949,7 @@ void sib_type2_s::to_json(json_writer& j) const if (ac_barr_skip_for_sms_r12_present) { j.write_str("ac-BarringSkipForSMS-r12", "true"); } - rrc_asn1_warn_assert( - ac_barr_per_plmn_list_r12_present != (ac_barr_per_plmn_list_r12.get() != NULL), __FILE__, __LINE__); - if (ac_barr_per_plmn_list_r12_present) { + if (ac_barr_per_plmn_list_r12.is_present()) { j.start_array("ac-BarringPerPLMN-List-r12"); for (uint32_t i1 = 0; i1 < ac_barr_per_plmn_list_r12->size(); ++i1) { ((*ac_barr_per_plmn_list_r12)[i1]).to_json(j); @@ -16060,40 +15959,29 @@ void sib_type2_s::to_json(json_writer& j) const if (voice_service_cause_ind_r12_present) { j.write_str("voiceServiceCauseIndication-r12", "true"); } - rrc_asn1_warn_assert( - acdc_barr_for_common_r13_present != (acdc_barr_for_common_r13.get() != NULL), __FILE__, __LINE__); - if (acdc_barr_for_common_r13_present) { + if (acdc_barr_for_common_r13.is_present()) { j.write_fieldname("acdc-BarringForCommon-r13"); acdc_barr_for_common_r13->to_json(j); } - rrc_asn1_warn_assert( - acdc_barr_per_plmn_list_r13_present != (acdc_barr_per_plmn_list_r13.get() != NULL), __FILE__, __LINE__); - if (acdc_barr_per_plmn_list_r13_present) { + if (acdc_barr_per_plmn_list_r13.is_present()) { j.start_array("acdc-BarringPerPLMN-List-r13"); for (uint32_t i1 = 0; i1 < acdc_barr_per_plmn_list_r13->size(); ++i1) { ((*acdc_barr_per_plmn_list_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - udt_restricting_for_common_r13_present != (udt_restricting_for_common_r13.get() != NULL), __FILE__, __LINE__); - if (udt_restricting_for_common_r13_present) { + if (udt_restricting_for_common_r13.is_present()) { j.write_fieldname("udt-RestrictingForCommon-r13"); udt_restricting_for_common_r13->to_json(j); } - rrc_asn1_warn_assert(udt_restricting_per_plmn_list_r13_present != (udt_restricting_per_plmn_list_r13.get() != NULL), - __FILE__, - __LINE__); - if (udt_restricting_per_plmn_list_r13_present) { + if (udt_restricting_per_plmn_list_r13.is_present()) { j.start_array("udt-RestrictingPerPLMN-List-r13"); for (uint32_t i1 = 0; i1 < udt_restricting_per_plmn_list_r13->size(); ++i1) { ((*udt_restricting_per_plmn_list_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - c_io_t_eps_optim_info_r13_present != (c_io_t_eps_optim_info_r13.get() != NULL), __FILE__, __LINE__); - if (c_io_t_eps_optim_info_r13_present) { + if (c_io_t_eps_optim_info_r13.is_present()) { j.start_array("cIoT-EPS-OptimisationInfo-r13"); for (uint32_t i1 = 0; i1 < c_io_t_eps_optim_info_r13->size(); ++i1) { ((*c_io_t_eps_optim_info_r13)[i1]).to_json(j); @@ -16106,9 +15994,7 @@ void sib_type2_s::to_json(json_writer& j) const if (unicast_freq_hop_ind_r13_present) { j.write_str("unicastFreqHoppingInd-r13", "true"); } - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - if (mbsfn_sf_cfg_list_v1430_present) { + if (mbsfn_sf_cfg_list_v1430.is_present()) { j.start_array("mbsfn-SubframeConfigList-v1430"); for (uint32_t i1 = 0; i1 < mbsfn_sf_cfg_list_v1430->size(); ++i1) { ((*mbsfn_sf_cfg_list_v1430)[i1]).to_json(j); @@ -16118,8 +16004,7 @@ void sib_type2_s::to_json(json_writer& j) const if (video_service_cause_ind_r14_present) { j.write_str("videoServiceCauseIndication-r14", "true"); } - rrc_asn1_warn_assert(plmn_info_list_r15_present != (plmn_info_list_r15.get() != NULL), __FILE__, __LINE__); - if (plmn_info_list_r15_present) { + if (plmn_info_list_r15.is_present()) { j.start_array("plmn-InfoList-r15"); for (uint32_t i1 = 0; i1 < plmn_info_list_r15->size(); ++i1) { ((*plmn_info_list_r15)[i1]).to_json(j); @@ -16161,11 +16046,9 @@ SRSASN_CODE sib_type20_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(br_bcch_cfg_r14_present != (br_bcch_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= br_bcch_cfg_r14_present; - rrc_asn1_warn_assert(sc_mcch_sched_info_r14_present != (sc_mcch_sched_info_r14.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= sc_mcch_sched_info_r14_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= br_bcch_cfg_r14.is_present(); + group_flags[0] |= sc_mcch_sched_info_r14.is_present(); group_flags[0] |= pdsch_max_num_repeat_cemode_a_sc_mtch_r14_present; group_flags[0] |= pdsch_max_num_repeat_cemode_b_sc_mtch_r14_present; group_flags[1] |= sc_mcch_repeat_period_v1470_present; @@ -16173,13 +16056,13 @@ SRSASN_CODE sib_type20_r13_s::pack(bit_ref& bref) const group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(br_bcch_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(sc_mcch_sched_info_r14_present, 1)); + HANDLE_CODE(bref.pack(br_bcch_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(sc_mcch_sched_info_r14.is_present(), 1)); HANDLE_CODE(bref.pack(pdsch_max_num_repeat_cemode_a_sc_mtch_r14_present, 1)); HANDLE_CODE(bref.pack(pdsch_max_num_repeat_cemode_b_sc_mtch_r14_present, 1)); - if (br_bcch_cfg_r14_present) { + if (br_bcch_cfg_r14.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, br_bcch_cfg_r14->mpdcch_nb_sc_mcch_r14, (uint8_t)1, (uint8_t)16)); HANDLE_CODE(pack_enum(bref, br_bcch_cfg_r14->mpdcch_num_repeat_sc_mcch_r14)); HANDLE_CODE(br_bcch_cfg_r14->mpdcch_start_sf_sc_mcch_r14.pack(bref)); @@ -16190,7 +16073,7 @@ SRSASN_CODE sib_type20_r13_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, br_bcch_cfg_r14->sc_mcch_repeat_period_br_r14)); HANDLE_CODE(pack_enum(bref, br_bcch_cfg_r14->sc_mcch_mod_period_br_r14)); } - if (sc_mcch_sched_info_r14_present) { + if (sc_mcch_sched_info_r14.is_present()) { HANDLE_CODE(sc_mcch_sched_info_r14->pack(bref)); } if (pdsch_max_num_repeat_cemode_a_sc_mtch_r14_present) { @@ -16201,7 +16084,7 @@ SRSASN_CODE sib_type20_r13_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sc_mcch_repeat_period_v1470_present, 1)); HANDLE_CODE(bref.pack(sc_mcch_mod_period_v1470_present, 1)); @@ -16227,18 +16110,21 @@ SRSASN_CODE sib_type20_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool br_bcch_cfg_r14_present; HANDLE_CODE(bref.unpack(br_bcch_cfg_r14_present, 1)); + br_bcch_cfg_r14.set_present(br_bcch_cfg_r14_present); + bool sc_mcch_sched_info_r14_present; HANDLE_CODE(bref.unpack(sc_mcch_sched_info_r14_present, 1)); + sc_mcch_sched_info_r14.set_present(sc_mcch_sched_info_r14_present); HANDLE_CODE(bref.unpack(pdsch_max_num_repeat_cemode_a_sc_mtch_r14_present, 1)); HANDLE_CODE(bref.unpack(pdsch_max_num_repeat_cemode_b_sc_mtch_r14_present, 1)); - if (br_bcch_cfg_r14_present) { - br_bcch_cfg_r14 = make_copy_ptr(br_bcch_cfg_r14_s_()); + if (br_bcch_cfg_r14.is_present()) { HANDLE_CODE(unpack_unalign_integer(br_bcch_cfg_r14->mpdcch_nb_sc_mcch_r14, bref, (uint8_t)1, (uint8_t)16)); HANDLE_CODE(unpack_enum(br_bcch_cfg_r14->mpdcch_num_repeat_sc_mcch_r14, bref)); HANDLE_CODE(br_bcch_cfg_r14->mpdcch_start_sf_sc_mcch_r14.unpack(bref)); @@ -16249,8 +16135,7 @@ SRSASN_CODE sib_type20_r13_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(br_bcch_cfg_r14->sc_mcch_repeat_period_br_r14, bref)); HANDLE_CODE(unpack_enum(br_bcch_cfg_r14->sc_mcch_mod_period_br_r14, bref)); } - if (sc_mcch_sched_info_r14_present) { - sc_mcch_sched_info_r14 = make_copy_ptr(sc_mcch_sched_info_r14_s()); + if (sc_mcch_sched_info_r14.is_present()) { HANDLE_CODE(sc_mcch_sched_info_r14->unpack(bref)); } if (pdsch_max_num_repeat_cemode_a_sc_mtch_r14_present) { @@ -16261,7 +16146,7 @@ SRSASN_CODE sib_type20_r13_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sc_mcch_repeat_period_v1470_present, 1)); HANDLE_CODE(bref.unpack(sc_mcch_mod_period_v1470_present, 1)); @@ -16283,8 +16168,7 @@ void sib_type20_r13_s::to_json(json_writer& j) const j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } if (ext) { - rrc_asn1_warn_assert(br_bcch_cfg_r14_present != (br_bcch_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (br_bcch_cfg_r14_present) { + if (br_bcch_cfg_r14.is_present()) { j.write_fieldname("br-BCCH-Config-r14"); j.start_obj(); j.write_str("dummy", "rf1"); @@ -16301,8 +16185,7 @@ void sib_type20_r13_s::to_json(json_writer& j) const j.write_str("sc-mcch-ModificationPeriod-BR-r14", br_bcch_cfg_r14->sc_mcch_mod_period_br_r14.to_string()); j.end_obj(); } - rrc_asn1_warn_assert(sc_mcch_sched_info_r14_present != (sc_mcch_sched_info_r14.get() != NULL), __FILE__, __LINE__); - if (sc_mcch_sched_info_r14_present) { + if (sc_mcch_sched_info_r14.is_present()) { j.write_fieldname("sc-mcch-SchedulingInfo-r14"); sc_mcch_sched_info_r14->to_json(j); } @@ -16872,61 +16755,43 @@ SRSASN_CODE sib_type3_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(8, 1); - rrc_asn1_warn_assert(s_intra_search_v920_present != (s_intra_search_v920.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= s_intra_search_v920_present; - rrc_asn1_warn_assert( - s_non_intra_search_v920_present != (s_non_intra_search_v920.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= s_non_intra_search_v920_present; - group_flags[0] |= q_qual_min_r9_present; - group_flags[0] |= thresh_serving_low_q_r9_present; - group_flags[1] |= q_qual_min_wb_r11_present; - group_flags[2] |= q_qual_min_rsrq_on_all_symbols_r12_present; - rrc_asn1_warn_assert(cell_resel_serving_freq_info_v1310_present != - (cell_resel_serving_freq_info_v1310.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= cell_resel_serving_freq_info_v1310_present; - rrc_asn1_warn_assert( - redist_serving_info_r13_present != (redist_serving_info_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= redist_serving_info_r13_present; - rrc_asn1_warn_assert(cell_sel_info_ce_r13_present != (cell_sel_info_ce_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= cell_sel_info_ce_r13_present; - group_flags[3] |= t_resel_eutra_ce_r13_present; - rrc_asn1_warn_assert(cell_sel_info_ce1_r13_present != (cell_sel_info_ce1_r13.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= cell_sel_info_ce1_r13_present; - rrc_asn1_warn_assert( - cell_sel_info_ce1_v1360_present != (cell_sel_info_ce1_v1360.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= cell_sel_info_ce1_v1360_present; - rrc_asn1_warn_assert( - cell_resel_info_common_v1460_present != (cell_resel_info_common_v1460.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= cell_resel_info_common_v1460_present; - rrc_asn1_warn_assert( - cell_resel_info_hsdn_r15_present != (cell_resel_info_hsdn_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= cell_resel_info_hsdn_r15_present; - rrc_asn1_warn_assert(cell_sel_info_ce_v1530_present != (cell_sel_info_ce_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= cell_sel_info_ce_v1530_present; - group_flags[7] |= crs_intf_mitig_neigh_cells_ce_r15_present; - group_flags.pack_nof_groups(bref); - HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); - group_flags.pack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.pack(bref)); - } + ext_groups_packer_guard group_flags; + group_flags[0] |= late_non_crit_ext_present; + group_flags[1] |= s_intra_search_v920.is_present(); + group_flags[1] |= s_non_intra_search_v920.is_present(); + group_flags[1] |= q_qual_min_r9_present; + group_flags[1] |= thresh_serving_low_q_r9_present; + group_flags[2] |= q_qual_min_wb_r11_present; + group_flags[3] |= q_qual_min_rsrq_on_all_symbols_r12_present; + group_flags[4] |= cell_resel_serving_freq_info_v1310.is_present(); + group_flags[4] |= redist_serving_info_r13.is_present(); + group_flags[4] |= cell_sel_info_ce_r13.is_present(); + group_flags[4] |= t_resel_eutra_ce_r13_present; + group_flags[5] |= cell_sel_info_ce1_r13.is_present(); + group_flags[6] |= cell_sel_info_ce1_v1360.is_present(); + group_flags[7] |= cell_resel_info_common_v1460.is_present(); + group_flags[8] |= cell_resel_info_hsdn_r15.is_present(); + group_flags[8] |= cell_sel_info_ce_v1530.is_present(); + group_flags[8] |= crs_intf_mitig_neigh_cells_ce_r15_present; + group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(s_intra_search_v920_present, 1)); - HANDLE_CODE(bref.pack(s_non_intra_search_v920_present, 1)); + HANDLE_CODE(bref.pack(s_intra_search_v920.is_present(), 1)); + HANDLE_CODE(bref.pack(s_non_intra_search_v920.is_present(), 1)); HANDLE_CODE(bref.pack(q_qual_min_r9_present, 1)); HANDLE_CODE(bref.pack(thresh_serving_low_q_r9_present, 1)); - if (s_intra_search_v920_present) { + if (s_intra_search_v920.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, s_intra_search_v920->s_intra_search_p_r9, (uint8_t)0, (uint8_t)31)); HANDLE_CODE(pack_unalign_integer(bref, s_intra_search_v920->s_intra_search_q_r9, (uint8_t)0, (uint8_t)31)); } - if (s_non_intra_search_v920_present) { + if (s_non_intra_search_v920.is_present()) { HANDLE_CODE( pack_unalign_integer(bref, s_non_intra_search_v920->s_non_intra_search_p_r9, (uint8_t)0, (uint8_t)31)); HANDLE_CODE( @@ -16939,76 +16804,76 @@ SRSASN_CODE sib_type3_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, thresh_serving_low_q_r9, (uint8_t)0, (uint8_t)31)); } } - if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + if (group_flags[2]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(q_qual_min_wb_r11_present, 1)); if (q_qual_min_wb_r11_present) { HANDLE_CODE(pack_unalign_integer(bref, q_qual_min_wb_r11, (int8_t)-34, (int8_t)-3)); } } - if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + if (group_flags[3]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(q_qual_min_rsrq_on_all_symbols_r12_present, 1)); if (q_qual_min_rsrq_on_all_symbols_r12_present) { HANDLE_CODE(pack_unalign_integer(bref, q_qual_min_rsrq_on_all_symbols_r12, (int8_t)-34, (int8_t)-3)); } } - if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + if (group_flags[4]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cell_resel_serving_freq_info_v1310_present, 1)); - HANDLE_CODE(bref.pack(redist_serving_info_r13_present, 1)); - HANDLE_CODE(bref.pack(cell_sel_info_ce_r13_present, 1)); + HANDLE_CODE(bref.pack(cell_resel_serving_freq_info_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(redist_serving_info_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(cell_sel_info_ce_r13.is_present(), 1)); HANDLE_CODE(bref.pack(t_resel_eutra_ce_r13_present, 1)); - if (cell_resel_serving_freq_info_v1310_present) { + if (cell_resel_serving_freq_info_v1310.is_present()) { HANDLE_CODE(cell_resel_serving_freq_info_v1310->pack(bref)); } - if (redist_serving_info_r13_present) { + if (redist_serving_info_r13.is_present()) { HANDLE_CODE(redist_serving_info_r13->pack(bref)); } - if (cell_sel_info_ce_r13_present) { + if (cell_sel_info_ce_r13.is_present()) { HANDLE_CODE(cell_sel_info_ce_r13->pack(bref)); } if (t_resel_eutra_ce_r13_present) { HANDLE_CODE(pack_unalign_integer(bref, t_resel_eutra_ce_r13, (uint8_t)0, (uint8_t)15)); } } - if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + if (group_flags[5]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cell_sel_info_ce1_r13_present, 1)); - if (cell_sel_info_ce1_r13_present) { + HANDLE_CODE(bref.pack(cell_sel_info_ce1_r13.is_present(), 1)); + if (cell_sel_info_ce1_r13.is_present()) { HANDLE_CODE(cell_sel_info_ce1_r13->pack(bref)); } } - if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + if (group_flags[6]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cell_sel_info_ce1_v1360_present, 1)); - if (cell_sel_info_ce1_v1360_present) { + HANDLE_CODE(bref.pack(cell_sel_info_ce1_v1360.is_present(), 1)); + if (cell_sel_info_ce1_v1360.is_present()) { HANDLE_CODE(cell_sel_info_ce1_v1360->pack(bref)); } } - if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + if (group_flags[7]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cell_resel_info_common_v1460_present, 1)); - if (cell_resel_info_common_v1460_present) { + HANDLE_CODE(bref.pack(cell_resel_info_common_v1460.is_present(), 1)); + if (cell_resel_info_common_v1460.is_present()) { HANDLE_CODE(cell_resel_info_common_v1460->pack(bref)); } } - if (group_flags[7]) { - varlength_field_pack_guard packer(bref); + if (group_flags[8]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cell_resel_info_hsdn_r15_present, 1)); - HANDLE_CODE(bref.pack(cell_sel_info_ce_v1530_present, 1)); + HANDLE_CODE(bref.pack(cell_resel_info_hsdn_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(cell_sel_info_ce_v1530.is_present(), 1)); HANDLE_CODE(bref.pack(crs_intf_mitig_neigh_cells_ce_r15_present, 1)); - if (cell_resel_info_hsdn_r15_present) { + if (cell_resel_info_hsdn_r15.is_present()) { HANDLE_CODE(cell_resel_info_hsdn_r15->pack(bref)); } - if (cell_sel_info_ce_v1530_present) { + if (cell_sel_info_ce_v1530.is_present()) { HANDLE_CODE(cell_sel_info_ce_v1530->pack(bref)); } } @@ -17053,29 +16918,30 @@ SRSASN_CODE sib_type3_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(8, 1); - group_flags.unpack_nof_groups(bref); - HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); - group_flags.unpack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.unpack(bref)); - } + ext_groups_unpacker_guard group_flags(9); + group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_unpack_guard varlen_scope(bref); + + bool s_intra_search_v920_present; HANDLE_CODE(bref.unpack(s_intra_search_v920_present, 1)); + s_intra_search_v920.set_present(s_intra_search_v920_present); + bool s_non_intra_search_v920_present; HANDLE_CODE(bref.unpack(s_non_intra_search_v920_present, 1)); + s_non_intra_search_v920.set_present(s_non_intra_search_v920_present); HANDLE_CODE(bref.unpack(q_qual_min_r9_present, 1)); HANDLE_CODE(bref.unpack(thresh_serving_low_q_r9_present, 1)); - if (s_intra_search_v920_present) { - s_intra_search_v920 = make_copy_ptr(s_intra_search_v920_s_()); + if (s_intra_search_v920.is_present()) { HANDLE_CODE(unpack_unalign_integer(s_intra_search_v920->s_intra_search_p_r9, bref, (uint8_t)0, (uint8_t)31)); HANDLE_CODE(unpack_unalign_integer(s_intra_search_v920->s_intra_search_q_r9, bref, (uint8_t)0, (uint8_t)31)); } - if (s_non_intra_search_v920_present) { - s_non_intra_search_v920 = make_copy_ptr(s_non_intra_search_v920_s_()); + if (s_non_intra_search_v920.is_present()) { HANDLE_CODE( unpack_unalign_integer(s_non_intra_search_v920->s_non_intra_search_p_r9, bref, (uint8_t)0, (uint8_t)31)); HANDLE_CODE( @@ -17088,84 +16954,92 @@ SRSASN_CODE sib_type3_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(thresh_serving_low_q_r9, bref, (uint8_t)0, (uint8_t)31)); } } - if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[2]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(q_qual_min_wb_r11_present, 1)); if (q_qual_min_wb_r11_present) { HANDLE_CODE(unpack_unalign_integer(q_qual_min_wb_r11, bref, (int8_t)-34, (int8_t)-3)); } } - if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[3]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(q_qual_min_rsrq_on_all_symbols_r12_present, 1)); if (q_qual_min_rsrq_on_all_symbols_r12_present) { HANDLE_CODE(unpack_unalign_integer(q_qual_min_rsrq_on_all_symbols_r12, bref, (int8_t)-34, (int8_t)-3)); } } - if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[4]) { + varlength_field_unpack_guard varlen_scope(bref); + bool cell_resel_serving_freq_info_v1310_present; HANDLE_CODE(bref.unpack(cell_resel_serving_freq_info_v1310_present, 1)); + cell_resel_serving_freq_info_v1310.set_present(cell_resel_serving_freq_info_v1310_present); + bool redist_serving_info_r13_present; HANDLE_CODE(bref.unpack(redist_serving_info_r13_present, 1)); + redist_serving_info_r13.set_present(redist_serving_info_r13_present); + bool cell_sel_info_ce_r13_present; HANDLE_CODE(bref.unpack(cell_sel_info_ce_r13_present, 1)); + cell_sel_info_ce_r13.set_present(cell_sel_info_ce_r13_present); HANDLE_CODE(bref.unpack(t_resel_eutra_ce_r13_present, 1)); - if (cell_resel_serving_freq_info_v1310_present) { - cell_resel_serving_freq_info_v1310 = make_copy_ptr(cell_resel_serving_freq_info_v1310_s()); + if (cell_resel_serving_freq_info_v1310.is_present()) { HANDLE_CODE(cell_resel_serving_freq_info_v1310->unpack(bref)); } - if (redist_serving_info_r13_present) { - redist_serving_info_r13 = make_copy_ptr(redist_serving_info_r13_s()); + if (redist_serving_info_r13.is_present()) { HANDLE_CODE(redist_serving_info_r13->unpack(bref)); } - if (cell_sel_info_ce_r13_present) { - cell_sel_info_ce_r13 = make_copy_ptr(cell_sel_info_ce_r13_s()); + if (cell_sel_info_ce_r13.is_present()) { HANDLE_CODE(cell_sel_info_ce_r13->unpack(bref)); } if (t_resel_eutra_ce_r13_present) { HANDLE_CODE(unpack_unalign_integer(t_resel_eutra_ce_r13, bref, (uint8_t)0, (uint8_t)15)); } } - if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[5]) { + varlength_field_unpack_guard varlen_scope(bref); + bool cell_sel_info_ce1_r13_present; HANDLE_CODE(bref.unpack(cell_sel_info_ce1_r13_present, 1)); - if (cell_sel_info_ce1_r13_present) { - cell_sel_info_ce1_r13 = make_copy_ptr(cell_sel_info_ce1_r13_s()); + cell_sel_info_ce1_r13.set_present(cell_sel_info_ce1_r13_present); + if (cell_sel_info_ce1_r13.is_present()) { HANDLE_CODE(cell_sel_info_ce1_r13->unpack(bref)); } } - if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[6]) { + varlength_field_unpack_guard varlen_scope(bref); + bool cell_sel_info_ce1_v1360_present; HANDLE_CODE(bref.unpack(cell_sel_info_ce1_v1360_present, 1)); - if (cell_sel_info_ce1_v1360_present) { - cell_sel_info_ce1_v1360 = make_copy_ptr(cell_sel_info_ce1_v1360_s()); + cell_sel_info_ce1_v1360.set_present(cell_sel_info_ce1_v1360_present); + if (cell_sel_info_ce1_v1360.is_present()) { HANDLE_CODE(cell_sel_info_ce1_v1360->unpack(bref)); } } - if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[7]) { + varlength_field_unpack_guard varlen_scope(bref); + bool cell_resel_info_common_v1460_present; HANDLE_CODE(bref.unpack(cell_resel_info_common_v1460_present, 1)); - if (cell_resel_info_common_v1460_present) { - cell_resel_info_common_v1460 = make_copy_ptr(cell_resel_info_common_v1460_s()); + cell_resel_info_common_v1460.set_present(cell_resel_info_common_v1460_present); + if (cell_resel_info_common_v1460.is_present()) { HANDLE_CODE(cell_resel_info_common_v1460->unpack(bref)); } } - if (group_flags[7]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[8]) { + varlength_field_unpack_guard varlen_scope(bref); + bool cell_resel_info_hsdn_r15_present; HANDLE_CODE(bref.unpack(cell_resel_info_hsdn_r15_present, 1)); + cell_resel_info_hsdn_r15.set_present(cell_resel_info_hsdn_r15_present); + bool cell_sel_info_ce_v1530_present; HANDLE_CODE(bref.unpack(cell_sel_info_ce_v1530_present, 1)); + cell_sel_info_ce_v1530.set_present(cell_sel_info_ce_v1530_present); HANDLE_CODE(bref.unpack(crs_intf_mitig_neigh_cells_ce_r15_present, 1)); - if (cell_resel_info_hsdn_r15_present) { - cell_resel_info_hsdn_r15 = make_copy_ptr(cell_resel_info_hsdn_r15_s()); + if (cell_resel_info_hsdn_r15.is_present()) { HANDLE_CODE(cell_resel_info_hsdn_r15->unpack(bref)); } - if (cell_sel_info_ce_v1530_present) { - cell_sel_info_ce_v1530 = make_copy_ptr(cell_sel_info_ce_v1530_s()); + if (cell_sel_info_ce_v1530.is_present()) { HANDLE_CODE(cell_sel_info_ce_v1530->unpack(bref)); } } @@ -17223,17 +17097,14 @@ void sib_type3_s::to_json(json_writer& j) const if (late_non_crit_ext_present) { j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } - rrc_asn1_warn_assert(s_intra_search_v920_present != (s_intra_search_v920.get() != NULL), __FILE__, __LINE__); - if (s_intra_search_v920_present) { + if (s_intra_search_v920.is_present()) { j.write_fieldname("s-IntraSearch-v920"); j.start_obj(); j.write_int("s-IntraSearchP-r9", s_intra_search_v920->s_intra_search_p_r9); j.write_int("s-IntraSearchQ-r9", s_intra_search_v920->s_intra_search_q_r9); j.end_obj(); } - rrc_asn1_warn_assert( - s_non_intra_search_v920_present != (s_non_intra_search_v920.get() != NULL), __FILE__, __LINE__); - if (s_non_intra_search_v920_present) { + if (s_non_intra_search_v920.is_present()) { j.write_fieldname("s-NonIntraSearch-v920"); j.start_obj(); j.write_int("s-NonIntraSearchP-r9", s_non_intra_search_v920->s_non_intra_search_p_r9); @@ -17252,53 +17123,38 @@ void sib_type3_s::to_json(json_writer& j) const if (q_qual_min_rsrq_on_all_symbols_r12_present) { j.write_int("q-QualMinRSRQ-OnAllSymbols-r12", q_qual_min_rsrq_on_all_symbols_r12); } - rrc_asn1_warn_assert(cell_resel_serving_freq_info_v1310_present != - (cell_resel_serving_freq_info_v1310.get() != NULL), - __FILE__, - __LINE__); - if (cell_resel_serving_freq_info_v1310_present) { + if (cell_resel_serving_freq_info_v1310.is_present()) { j.write_fieldname("cellReselectionServingFreqInfo-v1310"); cell_resel_serving_freq_info_v1310->to_json(j); } - rrc_asn1_warn_assert( - redist_serving_info_r13_present != (redist_serving_info_r13.get() != NULL), __FILE__, __LINE__); - if (redist_serving_info_r13_present) { + if (redist_serving_info_r13.is_present()) { j.write_fieldname("redistributionServingInfo-r13"); redist_serving_info_r13->to_json(j); } - rrc_asn1_warn_assert(cell_sel_info_ce_r13_present != (cell_sel_info_ce_r13.get() != NULL), __FILE__, __LINE__); - if (cell_sel_info_ce_r13_present) { + if (cell_sel_info_ce_r13.is_present()) { j.write_fieldname("cellSelectionInfoCE-r13"); cell_sel_info_ce_r13->to_json(j); } if (t_resel_eutra_ce_r13_present) { j.write_int("t-ReselectionEUTRA-CE-r13", t_resel_eutra_ce_r13); } - rrc_asn1_warn_assert(cell_sel_info_ce1_r13_present != (cell_sel_info_ce1_r13.get() != NULL), __FILE__, __LINE__); - if (cell_sel_info_ce1_r13_present) { + if (cell_sel_info_ce1_r13.is_present()) { j.write_fieldname("cellSelectionInfoCE1-r13"); cell_sel_info_ce1_r13->to_json(j); } - rrc_asn1_warn_assert( - cell_sel_info_ce1_v1360_present != (cell_sel_info_ce1_v1360.get() != NULL), __FILE__, __LINE__); - if (cell_sel_info_ce1_v1360_present) { + if (cell_sel_info_ce1_v1360.is_present()) { j.write_fieldname("cellSelectionInfoCE1-v1360"); cell_sel_info_ce1_v1360->to_json(j); } - rrc_asn1_warn_assert( - cell_resel_info_common_v1460_present != (cell_resel_info_common_v1460.get() != NULL), __FILE__, __LINE__); - if (cell_resel_info_common_v1460_present) { + if (cell_resel_info_common_v1460.is_present()) { j.write_fieldname("cellReselectionInfoCommon-v1460"); cell_resel_info_common_v1460->to_json(j); } - rrc_asn1_warn_assert( - cell_resel_info_hsdn_r15_present != (cell_resel_info_hsdn_r15.get() != NULL), __FILE__, __LINE__); - if (cell_resel_info_hsdn_r15_present) { + if (cell_resel_info_hsdn_r15.is_present()) { j.write_fieldname("cellReselectionInfoHSDN-r15"); cell_resel_info_hsdn_r15->to_json(j); } - rrc_asn1_warn_assert(cell_sel_info_ce_v1530_present != (cell_sel_info_ce_v1530.get() != NULL), __FILE__, __LINE__); - if (cell_sel_info_ce_v1530_present) { + if (cell_sel_info_ce_v1530.is_present()) { j.write_fieldname("cellSelectionInfoCE-v1530"); cell_sel_info_ce_v1530->to_json(j); } @@ -17328,25 +17184,21 @@ SRSASN_CODE sib_type4_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1, 1); - rrc_asn1_warn_assert(intra_freq_neigh_hsdn_cell_list_r15_present != - (intra_freq_neigh_hsdn_cell_list_r15.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= intra_freq_neigh_hsdn_cell_list_r15_present; - group_flags.pack_nof_groups(bref); - HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); - group_flags.pack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.pack(bref)); - } + ext_groups_packer_guard group_flags; + group_flags[0] |= late_non_crit_ext_present; + group_flags[1] |= intra_freq_neigh_hsdn_cell_list_r15.is_present(); + group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(intra_freq_neigh_hsdn_cell_list_r15_present, 1)); - if (intra_freq_neigh_hsdn_cell_list_r15_present) { + HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(intra_freq_neigh_hsdn_cell_list_r15.is_present(), 1)); + if (intra_freq_neigh_hsdn_cell_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *intra_freq_neigh_hsdn_cell_list_r15, 1, 16)); } } @@ -17371,21 +17223,21 @@ SRSASN_CODE sib_type4_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1, 1); - group_flags.unpack_nof_groups(bref); - HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); - group_flags.unpack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.unpack(bref)); - } + ext_groups_unpacker_guard group_flags(2); + group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + + HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_unpack_guard varlen_scope(bref); + bool intra_freq_neigh_hsdn_cell_list_r15_present; HANDLE_CODE(bref.unpack(intra_freq_neigh_hsdn_cell_list_r15_present, 1)); - if (intra_freq_neigh_hsdn_cell_list_r15_present) { - intra_freq_neigh_hsdn_cell_list_r15 = make_copy_ptr(intra_freq_neigh_hsdn_cell_list_r15_l()); + intra_freq_neigh_hsdn_cell_list_r15.set_present(intra_freq_neigh_hsdn_cell_list_r15_present); + if (intra_freq_neigh_hsdn_cell_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*intra_freq_neigh_hsdn_cell_list_r15, bref, 1, 16)); } } @@ -17417,11 +17269,7 @@ void sib_type4_s::to_json(json_writer& j) const if (late_non_crit_ext_present) { j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } - rrc_asn1_warn_assert(intra_freq_neigh_hsdn_cell_list_r15_present != - (intra_freq_neigh_hsdn_cell_list_r15.get() != NULL), - __FILE__, - __LINE__); - if (intra_freq_neigh_hsdn_cell_list_r15_present) { + if (intra_freq_neigh_hsdn_cell_list_r15.is_present()) { j.start_array("intraFreqNeighHSDN-CellList-r15"); for (uint32_t i1 = 0; i1 < intra_freq_neigh_hsdn_cell_list_r15->size(); ++i1) { ((*intra_freq_neigh_hsdn_cell_list_r15)[i1]).to_json(j); @@ -17439,141 +17287,100 @@ SRSASN_CODE sib_type5_s::pack(bit_ref& bref) const HANDLE_CODE(pack_dyn_seq_of(bref, inter_freq_carrier_freq_list, 1, 8)); if (ext) { - ext_groups_header group_flags(7, 1); - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1250_present != - (inter_freq_carrier_freq_list_v1250.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= inter_freq_carrier_freq_list_v1250_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_r12_present != - (inter_freq_carrier_freq_list_ext_r12.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= inter_freq_carrier_freq_list_ext_r12_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1280_present != - (inter_freq_carrier_freq_list_ext_v1280.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= inter_freq_carrier_freq_list_ext_v1280_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1310_present != - (inter_freq_carrier_freq_list_v1310.get() != NULL), - __FILE__, - __LINE__); - group_flags[2] |= inter_freq_carrier_freq_list_v1310_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1310_present != - (inter_freq_carrier_freq_list_ext_v1310.get() != NULL), - __FILE__, - __LINE__); - group_flags[2] |= inter_freq_carrier_freq_list_ext_v1310_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1350_present != - (inter_freq_carrier_freq_list_v1350.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= inter_freq_carrier_freq_list_v1350_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1350_present != - (inter_freq_carrier_freq_list_ext_v1350.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= inter_freq_carrier_freq_list_ext_v1350_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1360_present != - (inter_freq_carrier_freq_list_ext_v1360.get() != NULL), - __FILE__, - __LINE__); - group_flags[4] |= inter_freq_carrier_freq_list_ext_v1360_present; - group_flags[5] |= scptm_freq_offset_r14_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1530_present != - (inter_freq_carrier_freq_list_v1530.get() != NULL), - __FILE__, - __LINE__); - group_flags[6] |= inter_freq_carrier_freq_list_v1530_present; - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1530_present != - (inter_freq_carrier_freq_list_ext_v1530.get() != NULL), - __FILE__, - __LINE__); - group_flags[6] |= inter_freq_carrier_freq_list_ext_v1530_present; - rrc_asn1_warn_assert(meas_idle_cfg_sib_r15_present != (meas_idle_cfg_sib_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= meas_idle_cfg_sib_r15_present; - group_flags.pack_nof_groups(bref); - HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); - group_flags.pack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.pack(bref)); - } + ext_groups_packer_guard group_flags; + group_flags[0] |= late_non_crit_ext_present; + group_flags[1] |= inter_freq_carrier_freq_list_v1250.is_present(); + group_flags[1] |= inter_freq_carrier_freq_list_ext_r12.is_present(); + group_flags[2] |= inter_freq_carrier_freq_list_ext_v1280.is_present(); + group_flags[3] |= inter_freq_carrier_freq_list_v1310.is_present(); + group_flags[3] |= inter_freq_carrier_freq_list_ext_v1310.is_present(); + group_flags[4] |= inter_freq_carrier_freq_list_v1350.is_present(); + group_flags[4] |= inter_freq_carrier_freq_list_ext_v1350.is_present(); + group_flags[5] |= inter_freq_carrier_freq_list_ext_v1360.is_present(); + group_flags[6] |= scptm_freq_offset_r14_present; + group_flags[7] |= inter_freq_carrier_freq_list_v1530.is_present(); + group_flags[7] |= inter_freq_carrier_freq_list_ext_v1530.is_present(); + group_flags[7] |= meas_idle_cfg_sib_r15.is_present(); + group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1250_present, 1)); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_r12_present, 1)); - if (inter_freq_carrier_freq_list_v1250_present) { + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_r12.is_present(), 1)); + if (inter_freq_carrier_freq_list_v1250.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_v1250, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_r12_present) { + if (inter_freq_carrier_freq_list_ext_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_ext_r12, 1, 8)); } } - if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + if (group_flags[2]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1280_present, 1)); - if (inter_freq_carrier_freq_list_ext_v1280_present) { + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1280.is_present(), 1)); + if (inter_freq_carrier_freq_list_ext_v1280.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_ext_v1280, 1, 8)); } } - if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + if (group_flags[3]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1310_present, 1)); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1310_present, 1)); - if (inter_freq_carrier_freq_list_v1310_present) { + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1310.is_present(), 1)); + if (inter_freq_carrier_freq_list_v1310.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_v1310, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_v1310_present) { + if (inter_freq_carrier_freq_list_ext_v1310.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_ext_v1310, 1, 8)); } } - if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + if (group_flags[4]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1350_present, 1)); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1350_present, 1)); - if (inter_freq_carrier_freq_list_v1350_present) { + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1350.is_present(), 1)); + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1350.is_present(), 1)); + if (inter_freq_carrier_freq_list_v1350.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_v1350, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_v1350_present) { + if (inter_freq_carrier_freq_list_ext_v1350.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_ext_v1350, 1, 8)); } } - if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + if (group_flags[5]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1360_present, 1)); - if (inter_freq_carrier_freq_list_ext_v1360_present) { + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1360.is_present(), 1)); + if (inter_freq_carrier_freq_list_ext_v1360.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_ext_v1360, 1, 8)); } } - if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + if (group_flags[6]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(scptm_freq_offset_r14_present, 1)); if (scptm_freq_offset_r14_present) { HANDLE_CODE(pack_unalign_integer(bref, scptm_freq_offset_r14, (uint8_t)1, (uint8_t)8)); } } - if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + if (group_flags[7]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1530_present, 1)); - HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1530_present, 1)); - HANDLE_CODE(bref.pack(meas_idle_cfg_sib_r15_present, 1)); - if (inter_freq_carrier_freq_list_v1530_present) { + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(inter_freq_carrier_freq_list_ext_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_idle_cfg_sib_r15.is_present(), 1)); + if (inter_freq_carrier_freq_list_v1530.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_v1530, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_v1530_present) { + if (inter_freq_carrier_freq_list_ext_v1530.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *inter_freq_carrier_freq_list_ext_v1530, 1, 8)); } - if (meas_idle_cfg_sib_r15_present) { + if (meas_idle_cfg_sib_r15.is_present()) { HANDLE_CODE(meas_idle_cfg_sib_r15->pack(bref)); } } @@ -17586,99 +17393,109 @@ SRSASN_CODE sib_type5_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_dyn_seq_of(inter_freq_carrier_freq_list, bref, 1, 8)); if (ext) { - ext_groups_header group_flags(7, 1); - group_flags.unpack_nof_groups(bref); - HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); - group_flags.unpack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.unpack(bref)); - } + ext_groups_unpacker_guard group_flags(8); + group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_unpack_guard varlen_scope(bref); + + bool inter_freq_carrier_freq_list_v1250_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_v1250_present, 1)); + inter_freq_carrier_freq_list_v1250.set_present(inter_freq_carrier_freq_list_v1250_present); + bool inter_freq_carrier_freq_list_ext_r12_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_ext_r12_present, 1)); - if (inter_freq_carrier_freq_list_v1250_present) { - inter_freq_carrier_freq_list_v1250 = make_copy_ptr(inter_freq_carrier_freq_list_v1250_l()); + inter_freq_carrier_freq_list_ext_r12.set_present(inter_freq_carrier_freq_list_ext_r12_present); + if (inter_freq_carrier_freq_list_v1250.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_v1250, bref, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_r12_present) { - inter_freq_carrier_freq_list_ext_r12 = make_copy_ptr(inter_freq_carrier_freq_list_ext_r12_l()); + if (inter_freq_carrier_freq_list_ext_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_ext_r12, bref, 1, 8)); } } - if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[2]) { + varlength_field_unpack_guard varlen_scope(bref); + bool inter_freq_carrier_freq_list_ext_v1280_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_ext_v1280_present, 1)); - if (inter_freq_carrier_freq_list_ext_v1280_present) { - inter_freq_carrier_freq_list_ext_v1280 = make_copy_ptr(inter_freq_carrier_freq_list_ext_v1280_l()); + inter_freq_carrier_freq_list_ext_v1280.set_present(inter_freq_carrier_freq_list_ext_v1280_present); + if (inter_freq_carrier_freq_list_ext_v1280.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_ext_v1280, bref, 1, 8)); } } - if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[3]) { + varlength_field_unpack_guard varlen_scope(bref); + bool inter_freq_carrier_freq_list_v1310_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_v1310_present, 1)); + inter_freq_carrier_freq_list_v1310.set_present(inter_freq_carrier_freq_list_v1310_present); + bool inter_freq_carrier_freq_list_ext_v1310_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_ext_v1310_present, 1)); - if (inter_freq_carrier_freq_list_v1310_present) { - inter_freq_carrier_freq_list_v1310 = make_copy_ptr(inter_freq_carrier_freq_list_v1310_l()); + inter_freq_carrier_freq_list_ext_v1310.set_present(inter_freq_carrier_freq_list_ext_v1310_present); + if (inter_freq_carrier_freq_list_v1310.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_v1310, bref, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_v1310_present) { - inter_freq_carrier_freq_list_ext_v1310 = make_copy_ptr(inter_freq_carrier_freq_list_ext_v1310_l()); + if (inter_freq_carrier_freq_list_ext_v1310.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_ext_v1310, bref, 1, 8)); } } - if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[4]) { + varlength_field_unpack_guard varlen_scope(bref); + bool inter_freq_carrier_freq_list_v1350_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_v1350_present, 1)); + inter_freq_carrier_freq_list_v1350.set_present(inter_freq_carrier_freq_list_v1350_present); + bool inter_freq_carrier_freq_list_ext_v1350_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_ext_v1350_present, 1)); - if (inter_freq_carrier_freq_list_v1350_present) { - inter_freq_carrier_freq_list_v1350 = make_copy_ptr(inter_freq_carrier_freq_list_v1350_l()); + inter_freq_carrier_freq_list_ext_v1350.set_present(inter_freq_carrier_freq_list_ext_v1350_present); + if (inter_freq_carrier_freq_list_v1350.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_v1350, bref, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_v1350_present) { - inter_freq_carrier_freq_list_ext_v1350 = make_copy_ptr(inter_freq_carrier_freq_list_ext_v1350_l()); + if (inter_freq_carrier_freq_list_ext_v1350.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_ext_v1350, bref, 1, 8)); } } - if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[5]) { + varlength_field_unpack_guard varlen_scope(bref); + bool inter_freq_carrier_freq_list_ext_v1360_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_ext_v1360_present, 1)); - if (inter_freq_carrier_freq_list_ext_v1360_present) { - inter_freq_carrier_freq_list_ext_v1360 = make_copy_ptr(inter_freq_carrier_freq_list_ext_v1360_l()); + inter_freq_carrier_freq_list_ext_v1360.set_present(inter_freq_carrier_freq_list_ext_v1360_present); + if (inter_freq_carrier_freq_list_ext_v1360.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_ext_v1360, bref, 1, 8)); } } - if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[6]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(scptm_freq_offset_r14_present, 1)); if (scptm_freq_offset_r14_present) { HANDLE_CODE(unpack_unalign_integer(scptm_freq_offset_r14, bref, (uint8_t)1, (uint8_t)8)); } } - if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[7]) { + varlength_field_unpack_guard varlen_scope(bref); + bool inter_freq_carrier_freq_list_v1530_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_v1530_present, 1)); + inter_freq_carrier_freq_list_v1530.set_present(inter_freq_carrier_freq_list_v1530_present); + bool inter_freq_carrier_freq_list_ext_v1530_present; HANDLE_CODE(bref.unpack(inter_freq_carrier_freq_list_ext_v1530_present, 1)); + inter_freq_carrier_freq_list_ext_v1530.set_present(inter_freq_carrier_freq_list_ext_v1530_present); + bool meas_idle_cfg_sib_r15_present; HANDLE_CODE(bref.unpack(meas_idle_cfg_sib_r15_present, 1)); - if (inter_freq_carrier_freq_list_v1530_present) { - inter_freq_carrier_freq_list_v1530 = make_copy_ptr(inter_freq_carrier_freq_list_v1530_l()); + meas_idle_cfg_sib_r15.set_present(meas_idle_cfg_sib_r15_present); + if (inter_freq_carrier_freq_list_v1530.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_v1530, bref, 1, 8)); } - if (inter_freq_carrier_freq_list_ext_v1530_present) { - inter_freq_carrier_freq_list_ext_v1530 = make_copy_ptr(inter_freq_carrier_freq_list_ext_v1530_l()); + if (inter_freq_carrier_freq_list_ext_v1530.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*inter_freq_carrier_freq_list_ext_v1530, bref, 1, 8)); } - if (meas_idle_cfg_sib_r15_present) { - meas_idle_cfg_sib_r15 = make_copy_ptr(meas_idle_cfg_sib_r15_s()); + if (meas_idle_cfg_sib_r15.is_present()) { HANDLE_CODE(meas_idle_cfg_sib_r15->unpack(bref)); } } @@ -17697,88 +17514,56 @@ void sib_type5_s::to_json(json_writer& j) const if (late_non_crit_ext_present) { j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1250_present != - (inter_freq_carrier_freq_list_v1250.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_v1250_present) { + if (inter_freq_carrier_freq_list_v1250.is_present()) { j.start_array("interFreqCarrierFreqList-v1250"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_v1250->size(); ++i1) { ((*inter_freq_carrier_freq_list_v1250)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_r12_present != - (inter_freq_carrier_freq_list_ext_r12.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_ext_r12_present) { + if (inter_freq_carrier_freq_list_ext_r12.is_present()) { j.start_array("interFreqCarrierFreqListExt-r12"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_ext_r12->size(); ++i1) { ((*inter_freq_carrier_freq_list_ext_r12)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1280_present != - (inter_freq_carrier_freq_list_ext_v1280.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_ext_v1280_present) { + if (inter_freq_carrier_freq_list_ext_v1280.is_present()) { j.start_array("interFreqCarrierFreqListExt-v1280"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_ext_v1280->size(); ++i1) { ((*inter_freq_carrier_freq_list_ext_v1280)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1310_present != - (inter_freq_carrier_freq_list_v1310.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_v1310_present) { + if (inter_freq_carrier_freq_list_v1310.is_present()) { j.start_array("interFreqCarrierFreqList-v1310"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_v1310->size(); ++i1) { ((*inter_freq_carrier_freq_list_v1310)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1310_present != - (inter_freq_carrier_freq_list_ext_v1310.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_ext_v1310_present) { + if (inter_freq_carrier_freq_list_ext_v1310.is_present()) { j.start_array("interFreqCarrierFreqListExt-v1310"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_ext_v1310->size(); ++i1) { ((*inter_freq_carrier_freq_list_ext_v1310)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1350_present != - (inter_freq_carrier_freq_list_v1350.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_v1350_present) { + if (inter_freq_carrier_freq_list_v1350.is_present()) { j.start_array("interFreqCarrierFreqList-v1350"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_v1350->size(); ++i1) { ((*inter_freq_carrier_freq_list_v1350)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1350_present != - (inter_freq_carrier_freq_list_ext_v1350.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_ext_v1350_present) { + if (inter_freq_carrier_freq_list_ext_v1350.is_present()) { j.start_array("interFreqCarrierFreqListExt-v1350"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_ext_v1350->size(); ++i1) { ((*inter_freq_carrier_freq_list_ext_v1350)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1360_present != - (inter_freq_carrier_freq_list_ext_v1360.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_ext_v1360_present) { + if (inter_freq_carrier_freq_list_ext_v1360.is_present()) { j.start_array("interFreqCarrierFreqListExt-v1360"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_ext_v1360->size(); ++i1) { ((*inter_freq_carrier_freq_list_ext_v1360)[i1]).to_json(j); @@ -17788,30 +17573,21 @@ void sib_type5_s::to_json(json_writer& j) const if (scptm_freq_offset_r14_present) { j.write_int("scptm-FreqOffset-r14", scptm_freq_offset_r14); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_v1530_present != - (inter_freq_carrier_freq_list_v1530.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_v1530_present) { + if (inter_freq_carrier_freq_list_v1530.is_present()) { j.start_array("interFreqCarrierFreqList-v1530"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_v1530->size(); ++i1) { ((*inter_freq_carrier_freq_list_v1530)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(inter_freq_carrier_freq_list_ext_v1530_present != - (inter_freq_carrier_freq_list_ext_v1530.get() != NULL), - __FILE__, - __LINE__); - if (inter_freq_carrier_freq_list_ext_v1530_present) { + if (inter_freq_carrier_freq_list_ext_v1530.is_present()) { j.start_array("interFreqCarrierFreqListExt-v1530"); for (uint32_t i1 = 0; i1 < inter_freq_carrier_freq_list_ext_v1530->size(); ++i1) { ((*inter_freq_carrier_freq_list_ext_v1530)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(meas_idle_cfg_sib_r15_present != (meas_idle_cfg_sib_r15.get() != NULL), __FILE__, __LINE__); - if (meas_idle_cfg_sib_r15_present) { + if (meas_idle_cfg_sib_r15.is_present()) { j.write_fieldname("measIdleConfigSIB-r15"); meas_idle_cfg_sib_r15->to_json(j); } @@ -17839,50 +17615,36 @@ SRSASN_CODE sib_type6_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1, 1); - rrc_asn1_warn_assert(carrier_freq_list_utra_fdd_v1250_present != (carrier_freq_list_utra_fdd_v1250.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= carrier_freq_list_utra_fdd_v1250_present; - rrc_asn1_warn_assert(carrier_freq_list_utra_tdd_v1250_present != (carrier_freq_list_utra_tdd_v1250.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= carrier_freq_list_utra_tdd_v1250_present; - rrc_asn1_warn_assert(carrier_freq_list_utra_fdd_ext_r12_present != - (carrier_freq_list_utra_fdd_ext_r12.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= carrier_freq_list_utra_fdd_ext_r12_present; - rrc_asn1_warn_assert(carrier_freq_list_utra_tdd_ext_r12_present != - (carrier_freq_list_utra_tdd_ext_r12.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= carrier_freq_list_utra_tdd_ext_r12_present; - group_flags.pack_nof_groups(bref); - HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); - group_flags.pack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.pack(bref)); - } + ext_groups_packer_guard group_flags; + group_flags[0] |= late_non_crit_ext_present; + group_flags[1] |= carrier_freq_list_utra_fdd_v1250.is_present(); + group_flags[1] |= carrier_freq_list_utra_tdd_v1250.is_present(); + group_flags[1] |= carrier_freq_list_utra_fdd_ext_r12.is_present(); + group_flags[1] |= carrier_freq_list_utra_tdd_ext_r12.is_present(); + group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(carrier_freq_list_utra_fdd_v1250_present, 1)); - HANDLE_CODE(bref.pack(carrier_freq_list_utra_tdd_v1250_present, 1)); - HANDLE_CODE(bref.pack(carrier_freq_list_utra_fdd_ext_r12_present, 1)); - HANDLE_CODE(bref.pack(carrier_freq_list_utra_tdd_ext_r12_present, 1)); - if (carrier_freq_list_utra_fdd_v1250_present) { + HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(carrier_freq_list_utra_fdd_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(carrier_freq_list_utra_tdd_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(carrier_freq_list_utra_fdd_ext_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(carrier_freq_list_utra_tdd_ext_r12.is_present(), 1)); + if (carrier_freq_list_utra_fdd_v1250.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *carrier_freq_list_utra_fdd_v1250, 1, 16)); } - if (carrier_freq_list_utra_tdd_v1250_present) { + if (carrier_freq_list_utra_tdd_v1250.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *carrier_freq_list_utra_tdd_v1250, 1, 16)); } - if (carrier_freq_list_utra_fdd_ext_r12_present) { + if (carrier_freq_list_utra_fdd_ext_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *carrier_freq_list_utra_fdd_ext_r12, 1, 16)); } - if (carrier_freq_list_utra_tdd_ext_r12_present) { + if (carrier_freq_list_utra_tdd_ext_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *carrier_freq_list_utra_tdd_ext_r12, 1, 16)); } } @@ -17908,36 +17670,39 @@ SRSASN_CODE sib_type6_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1, 1); - group_flags.unpack_nof_groups(bref); - HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); - group_flags.unpack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.unpack(bref)); - } + ext_groups_unpacker_guard group_flags(2); + group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + + HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_unpack_guard varlen_scope(bref); + bool carrier_freq_list_utra_fdd_v1250_present; HANDLE_CODE(bref.unpack(carrier_freq_list_utra_fdd_v1250_present, 1)); + carrier_freq_list_utra_fdd_v1250.set_present(carrier_freq_list_utra_fdd_v1250_present); + bool carrier_freq_list_utra_tdd_v1250_present; HANDLE_CODE(bref.unpack(carrier_freq_list_utra_tdd_v1250_present, 1)); + carrier_freq_list_utra_tdd_v1250.set_present(carrier_freq_list_utra_tdd_v1250_present); + bool carrier_freq_list_utra_fdd_ext_r12_present; HANDLE_CODE(bref.unpack(carrier_freq_list_utra_fdd_ext_r12_present, 1)); + carrier_freq_list_utra_fdd_ext_r12.set_present(carrier_freq_list_utra_fdd_ext_r12_present); + bool carrier_freq_list_utra_tdd_ext_r12_present; HANDLE_CODE(bref.unpack(carrier_freq_list_utra_tdd_ext_r12_present, 1)); - if (carrier_freq_list_utra_fdd_v1250_present) { - carrier_freq_list_utra_fdd_v1250 = make_copy_ptr(carrier_freq_list_utra_fdd_v1250_l_()); + carrier_freq_list_utra_tdd_ext_r12.set_present(carrier_freq_list_utra_tdd_ext_r12_present); + if (carrier_freq_list_utra_fdd_v1250.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*carrier_freq_list_utra_fdd_v1250, bref, 1, 16)); } - if (carrier_freq_list_utra_tdd_v1250_present) { - carrier_freq_list_utra_tdd_v1250 = make_copy_ptr(carrier_freq_list_utra_tdd_v1250_l_()); + if (carrier_freq_list_utra_tdd_v1250.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*carrier_freq_list_utra_tdd_v1250, bref, 1, 16)); } - if (carrier_freq_list_utra_fdd_ext_r12_present) { - carrier_freq_list_utra_fdd_ext_r12 = make_copy_ptr(carrier_freq_list_utra_fdd_ext_r12_l()); + if (carrier_freq_list_utra_fdd_ext_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*carrier_freq_list_utra_fdd_ext_r12, bref, 1, 16)); } - if (carrier_freq_list_utra_tdd_ext_r12_present) { - carrier_freq_list_utra_tdd_ext_r12 = make_copy_ptr(carrier_freq_list_utra_tdd_ext_r12_l()); + if (carrier_freq_list_utra_tdd_ext_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*carrier_freq_list_utra_tdd_ext_r12, bref, 1, 16)); } } @@ -17970,42 +17735,28 @@ void sib_type6_s::to_json(json_writer& j) const if (late_non_crit_ext_present) { j.write_str("lateNonCriticalExtension", late_non_crit_ext.to_string()); } - rrc_asn1_warn_assert(carrier_freq_list_utra_fdd_v1250_present != (carrier_freq_list_utra_fdd_v1250.get() != NULL), - __FILE__, - __LINE__); - if (carrier_freq_list_utra_fdd_v1250_present) { + if (carrier_freq_list_utra_fdd_v1250.is_present()) { j.start_array("carrierFreqListUTRA-FDD-v1250"); for (uint32_t i1 = 0; i1 < carrier_freq_list_utra_fdd_v1250->size(); ++i1) { ((*carrier_freq_list_utra_fdd_v1250)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(carrier_freq_list_utra_tdd_v1250_present != (carrier_freq_list_utra_tdd_v1250.get() != NULL), - __FILE__, - __LINE__); - if (carrier_freq_list_utra_tdd_v1250_present) { + if (carrier_freq_list_utra_tdd_v1250.is_present()) { j.start_array("carrierFreqListUTRA-TDD-v1250"); for (uint32_t i1 = 0; i1 < carrier_freq_list_utra_tdd_v1250->size(); ++i1) { ((*carrier_freq_list_utra_tdd_v1250)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(carrier_freq_list_utra_fdd_ext_r12_present != - (carrier_freq_list_utra_fdd_ext_r12.get() != NULL), - __FILE__, - __LINE__); - if (carrier_freq_list_utra_fdd_ext_r12_present) { + if (carrier_freq_list_utra_fdd_ext_r12.is_present()) { j.start_array("carrierFreqListUTRA-FDD-Ext-r12"); for (uint32_t i1 = 0; i1 < carrier_freq_list_utra_fdd_ext_r12->size(); ++i1) { ((*carrier_freq_list_utra_fdd_ext_r12)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(carrier_freq_list_utra_tdd_ext_r12_present != - (carrier_freq_list_utra_tdd_ext_r12.get() != NULL), - __FILE__, - __LINE__); - if (carrier_freq_list_utra_tdd_ext_r12_present) { + if (carrier_freq_list_utra_tdd_ext_r12.is_present()) { j.start_array("carrierFreqListUTRA-TDD-Ext-r12"); for (uint32_t i1 = 0; i1 < carrier_freq_list_utra_tdd_ext_r12->size(); ++i1) { ((*carrier_freq_list_utra_tdd_ext_r12)[i1]).to_json(j); @@ -18124,64 +17875,56 @@ SRSASN_CODE sib_type8_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3, 1); - group_flags[0] |= csfb_support_for_dual_rx_ues_r9_present; - rrc_asn1_warn_assert( - cell_resel_params_hrpd_v920_present != (cell_resel_params_hrpd_v920.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cell_resel_params_hrpd_v920_present; - rrc_asn1_warn_assert( - cell_resel_params1_xrtt_v920_present != (cell_resel_params1_xrtt_v920.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cell_resel_params1_xrtt_v920_present; - rrc_asn1_warn_assert( - csfb_regist_param1_xrtt_v920_present != (csfb_regist_param1_xrtt_v920.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= csfb_regist_param1_xrtt_v920_present; - rrc_asn1_warn_assert(ac_barr_cfg1_xrtt_r9_present != (ac_barr_cfg1_xrtt_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ac_barr_cfg1_xrtt_r9_present; - group_flags[1] |= csfb_dual_rx_tx_support_r10_present; - rrc_asn1_warn_assert(sib8_per_plmn_list_r11_present != (sib8_per_plmn_list_r11.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= sib8_per_plmn_list_r11_present; - group_flags.pack_nof_groups(bref); - HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); - group_flags.pack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.pack(bref)); - } + ext_groups_packer_guard group_flags; + group_flags[0] |= late_non_crit_ext_present; + group_flags[1] |= csfb_support_for_dual_rx_ues_r9_present; + group_flags[1] |= cell_resel_params_hrpd_v920.is_present(); + group_flags[1] |= cell_resel_params1_xrtt_v920.is_present(); + group_flags[1] |= csfb_regist_param1_xrtt_v920.is_present(); + group_flags[1] |= ac_barr_cfg1_xrtt_r9.is_present(); + group_flags[2] |= csfb_dual_rx_tx_support_r10_present; + group_flags[3] |= sib8_per_plmn_list_r11.is_present(); + group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(csfb_support_for_dual_rx_ues_r9_present, 1)); - HANDLE_CODE(bref.pack(cell_resel_params_hrpd_v920_present, 1)); - HANDLE_CODE(bref.pack(cell_resel_params1_xrtt_v920_present, 1)); - HANDLE_CODE(bref.pack(csfb_regist_param1_xrtt_v920_present, 1)); - HANDLE_CODE(bref.pack(ac_barr_cfg1_xrtt_r9_present, 1)); + HANDLE_CODE(bref.pack(cell_resel_params_hrpd_v920.is_present(), 1)); + HANDLE_CODE(bref.pack(cell_resel_params1_xrtt_v920.is_present(), 1)); + HANDLE_CODE(bref.pack(csfb_regist_param1_xrtt_v920.is_present(), 1)); + HANDLE_CODE(bref.pack(ac_barr_cfg1_xrtt_r9.is_present(), 1)); if (csfb_support_for_dual_rx_ues_r9_present) { HANDLE_CODE(bref.pack(csfb_support_for_dual_rx_ues_r9, 1)); } - if (cell_resel_params_hrpd_v920_present) { + if (cell_resel_params_hrpd_v920.is_present()) { HANDLE_CODE(cell_resel_params_hrpd_v920->pack(bref)); } - if (cell_resel_params1_xrtt_v920_present) { + if (cell_resel_params1_xrtt_v920.is_present()) { HANDLE_CODE(cell_resel_params1_xrtt_v920->pack(bref)); } - if (csfb_regist_param1_xrtt_v920_present) { + if (csfb_regist_param1_xrtt_v920.is_present()) { HANDLE_CODE(csfb_regist_param1_xrtt_v920->pack(bref)); } - if (ac_barr_cfg1_xrtt_r9_present) { + if (ac_barr_cfg1_xrtt_r9.is_present()) { HANDLE_CODE(ac_barr_cfg1_xrtt_r9->pack(bref)); } } - if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + if (group_flags[2]) { + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(csfb_dual_rx_tx_support_r10_present, 1)); } - if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + if (group_flags[3]) { + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(sib8_per_plmn_list_r11_present, 1)); - if (sib8_per_plmn_list_r11_present) { + HANDLE_CODE(bref.pack(sib8_per_plmn_list_r11.is_present(), 1)); + if (sib8_per_plmn_list_r11.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *sib8_per_plmn_list_r11, 1, 6)); } } @@ -18225,54 +17968,58 @@ SRSASN_CODE sib_type8_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3, 1); - group_flags.unpack_nof_groups(bref); - HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); - group_flags.unpack_group_flags(bref); - - if (late_non_crit_ext_present) { - HANDLE_CODE(late_non_crit_ext.unpack(bref)); - } + ext_groups_unpacker_guard group_flags(4); + group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + + HANDLE_CODE(bref.unpack(late_non_crit_ext_present, 1)); + } + if (group_flags[1]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(csfb_support_for_dual_rx_ues_r9_present, 1)); + bool cell_resel_params_hrpd_v920_present; HANDLE_CODE(bref.unpack(cell_resel_params_hrpd_v920_present, 1)); + cell_resel_params_hrpd_v920.set_present(cell_resel_params_hrpd_v920_present); + bool cell_resel_params1_xrtt_v920_present; HANDLE_CODE(bref.unpack(cell_resel_params1_xrtt_v920_present, 1)); + cell_resel_params1_xrtt_v920.set_present(cell_resel_params1_xrtt_v920_present); + bool csfb_regist_param1_xrtt_v920_present; HANDLE_CODE(bref.unpack(csfb_regist_param1_xrtt_v920_present, 1)); + csfb_regist_param1_xrtt_v920.set_present(csfb_regist_param1_xrtt_v920_present); + bool ac_barr_cfg1_xrtt_r9_present; HANDLE_CODE(bref.unpack(ac_barr_cfg1_xrtt_r9_present, 1)); + ac_barr_cfg1_xrtt_r9.set_present(ac_barr_cfg1_xrtt_r9_present); if (csfb_support_for_dual_rx_ues_r9_present) { HANDLE_CODE(bref.unpack(csfb_support_for_dual_rx_ues_r9, 1)); } - if (cell_resel_params_hrpd_v920_present) { - cell_resel_params_hrpd_v920 = make_copy_ptr(cell_resel_params_cdma2000_v920_s()); + if (cell_resel_params_hrpd_v920.is_present()) { HANDLE_CODE(cell_resel_params_hrpd_v920->unpack(bref)); } - if (cell_resel_params1_xrtt_v920_present) { - cell_resel_params1_xrtt_v920 = make_copy_ptr(cell_resel_params_cdma2000_v920_s()); + if (cell_resel_params1_xrtt_v920.is_present()) { HANDLE_CODE(cell_resel_params1_xrtt_v920->unpack(bref)); } - if (csfb_regist_param1_xrtt_v920_present) { - csfb_regist_param1_xrtt_v920 = make_copy_ptr(csfb_regist_param1_xrtt_v920_s()); + if (csfb_regist_param1_xrtt_v920.is_present()) { HANDLE_CODE(csfb_regist_param1_xrtt_v920->unpack(bref)); } - if (ac_barr_cfg1_xrtt_r9_present) { - ac_barr_cfg1_xrtt_r9 = make_copy_ptr(ac_barr_cfg1_xrtt_r9_s()); + if (ac_barr_cfg1_xrtt_r9.is_present()) { HANDLE_CODE(ac_barr_cfg1_xrtt_r9->unpack(bref)); } } - if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[2]) { + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(csfb_dual_rx_tx_support_r10_present, 1)); } - if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + if (group_flags[3]) { + varlength_field_unpack_guard varlen_scope(bref); + bool sib8_per_plmn_list_r11_present; HANDLE_CODE(bref.unpack(sib8_per_plmn_list_r11_present, 1)); - if (sib8_per_plmn_list_r11_present) { - sib8_per_plmn_list_r11 = make_copy_ptr(sib8_per_plmn_list_r11_l()); + sib8_per_plmn_list_r11.set_present(sib8_per_plmn_list_r11_present); + if (sib8_per_plmn_list_r11.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*sib8_per_plmn_list_r11, bref, 1, 6)); } } @@ -18323,34 +18070,26 @@ void sib_type8_s::to_json(json_writer& j) const if (csfb_support_for_dual_rx_ues_r9_present) { j.write_bool("csfb-SupportForDualRxUEs-r9", csfb_support_for_dual_rx_ues_r9); } - rrc_asn1_warn_assert( - cell_resel_params_hrpd_v920_present != (cell_resel_params_hrpd_v920.get() != NULL), __FILE__, __LINE__); - if (cell_resel_params_hrpd_v920_present) { + if (cell_resel_params_hrpd_v920.is_present()) { j.write_fieldname("cellReselectionParametersHRPD-v920"); cell_resel_params_hrpd_v920->to_json(j); } - rrc_asn1_warn_assert( - cell_resel_params1_xrtt_v920_present != (cell_resel_params1_xrtt_v920.get() != NULL), __FILE__, __LINE__); - if (cell_resel_params1_xrtt_v920_present) { + if (cell_resel_params1_xrtt_v920.is_present()) { j.write_fieldname("cellReselectionParameters1XRTT-v920"); cell_resel_params1_xrtt_v920->to_json(j); } - rrc_asn1_warn_assert( - csfb_regist_param1_xrtt_v920_present != (csfb_regist_param1_xrtt_v920.get() != NULL), __FILE__, __LINE__); - if (csfb_regist_param1_xrtt_v920_present) { + if (csfb_regist_param1_xrtt_v920.is_present()) { j.write_fieldname("csfb-RegistrationParam1XRTT-v920"); csfb_regist_param1_xrtt_v920->to_json(j); } - rrc_asn1_warn_assert(ac_barr_cfg1_xrtt_r9_present != (ac_barr_cfg1_xrtt_r9.get() != NULL), __FILE__, __LINE__); - if (ac_barr_cfg1_xrtt_r9_present) { + if (ac_barr_cfg1_xrtt_r9.is_present()) { j.write_fieldname("ac-BarringConfig1XRTT-r9"); ac_barr_cfg1_xrtt_r9->to_json(j); } if (csfb_dual_rx_tx_support_r10_present) { j.write_str("csfb-DualRxTxSupport-r10", "true"); } - rrc_asn1_warn_assert(sib8_per_plmn_list_r11_present != (sib8_per_plmn_list_r11.get() != NULL), __FILE__, __LINE__); - if (sib8_per_plmn_list_r11_present) { + if (sib8_per_plmn_list_r11.is_present()) { j.start_array("sib8-PerPLMN-List-r11"); for (uint32_t i1 = 0; i1 < sib8_per_plmn_list_r11->size(); ++i1) { ((*sib8_per_plmn_list_r11)[i1]).to_json(j); @@ -21400,17 +21139,15 @@ SRSASN_CODE csi_rs_cfg_nzp_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); + ext_groups_packer_guard group_flags; group_flags[0] |= csi_rs_cfg_nzp_id_v1310_present; group_flags[1] |= tx_comb_r14_present; group_flags[1] |= freq_density_r14_present; - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= mbsfn_sf_cfg_list_v1430_present; + group_flags[2] |= mbsfn_sf_cfg_list_v1430.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_id_v1310_present, 1)); if (csi_rs_cfg_nzp_id_v1310_present) { @@ -21418,7 +21155,7 @@ SRSASN_CODE csi_rs_cfg_nzp_r11_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(tx_comb_r14_present, 1)); HANDLE_CODE(bref.pack(freq_density_r14_present, 1)); @@ -21430,10 +21167,10 @@ SRSASN_CODE csi_rs_cfg_nzp_r11_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { + HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430.is_present(), 1)); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(mbsfn_sf_cfg_list_v1430->pack(bref)); } } @@ -21460,11 +21197,11 @@ SRSASN_CODE csi_rs_cfg_nzp_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_id_v1310_present, 1)); if (csi_rs_cfg_nzp_id_v1310_present) { @@ -21472,7 +21209,7 @@ SRSASN_CODE csi_rs_cfg_nzp_r11_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(tx_comb_r14_present, 1)); HANDLE_CODE(bref.unpack(freq_density_r14_present, 1)); @@ -21484,11 +21221,12 @@ SRSASN_CODE csi_rs_cfg_nzp_r11_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mbsfn_sf_cfg_list_v1430_present; HANDLE_CODE(bref.unpack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { - mbsfn_sf_cfg_list_v1430 = make_copy_ptr(mbsfn_sf_cfg_list_v1430_c_()); + mbsfn_sf_cfg_list_v1430.set_present(mbsfn_sf_cfg_list_v1430_present); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(mbsfn_sf_cfg_list_v1430->unpack(bref)); } } @@ -21524,9 +21262,7 @@ void csi_rs_cfg_nzp_r11_s::to_json(json_writer& j) const if (freq_density_r14_present) { j.write_str("frequencyDensity-r14", freq_density_r14.to_string()); } - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - if (mbsfn_sf_cfg_list_v1430_present) { + if (mbsfn_sf_cfg_list_v1430.is_present()) { j.write_fieldname("mbsfn-SubframeConfigList-v1430"); mbsfn_sf_cfg_list_v1430->to_json(j); } @@ -21657,13 +21393,13 @@ SRSASN_CODE nzp_res_cfg_r13_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, res_cfg_r13, (uint8_t)0, (uint8_t)31)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= tx_comb_r14_present; group_flags[0] |= freq_density_r14_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(tx_comb_r14_present, 1)); HANDLE_CODE(bref.pack(freq_density_r14_present, 1)); @@ -21683,11 +21419,11 @@ SRSASN_CODE nzp_res_cfg_r13_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(res_cfg_r13, bref, (uint8_t)0, (uint8_t)31)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(tx_comb_r14_present, 1)); HANDLE_CODE(bref.unpack(freq_density_r14_present, 1)); @@ -23274,22 +23010,21 @@ SRSASN_CODE cqi_report_periodic_proc_ext_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(cri_report_cfg_r13_present != (cri_report_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cri_report_cfg_r13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= cri_report_cfg_r13.is_present(); group_flags[1] |= periodicity_factor_wb_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cri_report_cfg_r13_present, 1)); - if (cri_report_cfg_r13_present) { + HANDLE_CODE(bref.pack(cri_report_cfg_r13.is_present(), 1)); + if (cri_report_cfg_r13.is_present()) { HANDLE_CODE(cri_report_cfg_r13->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(periodicity_factor_wb_r13_present, 1)); if (periodicity_factor_wb_r13_present) { @@ -23316,20 +23051,21 @@ SRSASN_CODE cqi_report_periodic_proc_ext_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool cri_report_cfg_r13_present; HANDLE_CODE(bref.unpack(cri_report_cfg_r13_present, 1)); - if (cri_report_cfg_r13_present) { - cri_report_cfg_r13 = make_copy_ptr(cri_report_cfg_r13_c()); + cri_report_cfg_r13.set_present(cri_report_cfg_r13_present); + if (cri_report_cfg_r13.is_present()) { HANDLE_CODE(cri_report_cfg_r13->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(periodicity_factor_wb_r13_present, 1)); if (periodicity_factor_wb_r13_present) { @@ -23354,8 +23090,7 @@ void cqi_report_periodic_proc_ext_r11_s::to_json(json_writer& j) const csi_cfg_idx_r11.to_json(j); } if (ext) { - rrc_asn1_warn_assert(cri_report_cfg_r13_present != (cri_report_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (cri_report_cfg_r13_present) { + if (cri_report_cfg_r13.is_present()) { j.write_fieldname("cri-ReportConfig-r13"); cri_report_cfg_r13->to_json(j); } @@ -23577,12 +23312,12 @@ SRSASN_CODE csi_im_cfg_r11_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, sf_cfg_r11, (uint8_t)0, (uint8_t)154)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= interference_meas_restrict_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(interference_meas_restrict_r13_present, 1)); if (interference_meas_restrict_r13_present) { @@ -23600,11 +23335,11 @@ SRSASN_CODE csi_im_cfg_r11_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(sf_cfg_r11, bref, (uint8_t)0, (uint8_t)154)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(interference_meas_restrict_r13_present, 1)); if (interference_meas_restrict_r13_present) { @@ -23637,13 +23372,13 @@ SRSASN_CODE csi_im_cfg_ext_r12_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, sf_cfg_r12, (uint8_t)0, (uint8_t)154)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= interference_meas_restrict_r13_present; group_flags[0] |= csi_im_cfg_id_v1310_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(interference_meas_restrict_r13_present, 1)); HANDLE_CODE(bref.pack(csi_im_cfg_id_v1310_present, 1)); @@ -23665,11 +23400,11 @@ SRSASN_CODE csi_im_cfg_ext_r12_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(sf_cfg_r12, bref, (uint8_t)0, (uint8_t)154)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(interference_meas_restrict_r13_present, 1)); HANDLE_CODE(bref.unpack(csi_im_cfg_id_v1310_present, 1)); @@ -23723,73 +23458,60 @@ SRSASN_CODE csi_process_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(5); + ext_groups_packer_guard group_flags; group_flags[0] |= alternative_codebook_enabled_for4_tx_proc_r12_present; - rrc_asn1_warn_assert(csi_im_cfg_id_list_r12_present != (csi_im_cfg_id_list_r12.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= csi_im_cfg_id_list_r12_present; - rrc_asn1_warn_assert( - cqi_report_aperiodic_proc2_r12_present != (cqi_report_aperiodic_proc2_r12.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cqi_report_aperiodic_proc2_r12_present; - rrc_asn1_warn_assert( - cqi_report_aperiodic_proc_v1310_present != (cqi_report_aperiodic_proc_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= cqi_report_aperiodic_proc_v1310_present; - rrc_asn1_warn_assert(cqi_report_aperiodic_proc2_v1310_present != (cqi_report_aperiodic_proc2_v1310.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= cqi_report_aperiodic_proc2_v1310_present; - rrc_asn1_warn_assert(e_mimo_type_r13_present != (e_mimo_type_r13.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= e_mimo_type_r13_present; - rrc_asn1_warn_assert(dummy_present != (dummy.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= dummy_present; - rrc_asn1_warn_assert(e_mimo_hybrid_r14_present != (e_mimo_hybrid_r14.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= e_mimo_hybrid_r14_present; + group_flags[0] |= csi_im_cfg_id_list_r12.is_present(); + group_flags[0] |= cqi_report_aperiodic_proc2_r12.is_present(); + group_flags[1] |= cqi_report_aperiodic_proc_v1310.is_present(); + group_flags[1] |= cqi_report_aperiodic_proc2_v1310.is_present(); + group_flags[1] |= e_mimo_type_r13.is_present(); + group_flags[2] |= dummy.is_present(); + group_flags[2] |= e_mimo_hybrid_r14.is_present(); group_flags[2] |= advanced_codebook_enabled_r14_present; - rrc_asn1_warn_assert(e_mimo_type_v1480_present != (e_mimo_type_v1480.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= e_mimo_type_v1480_present; + group_flags[3] |= e_mimo_type_v1480.is_present(); group_flags[4] |= fe_comp_csi_enabled_v1530_present; - rrc_asn1_warn_assert(e_mimo_type_v1530_present != (e_mimo_type_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= e_mimo_type_v1530_present; + group_flags[4] |= e_mimo_type_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(alternative_codebook_enabled_for4_tx_proc_r12_present, 1)); - HANDLE_CODE(bref.pack(csi_im_cfg_id_list_r12_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_aperiodic_proc2_r12_present, 1)); - if (csi_im_cfg_id_list_r12_present) { + HANDLE_CODE(bref.pack(csi_im_cfg_id_list_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_aperiodic_proc2_r12.is_present(), 1)); + if (csi_im_cfg_id_list_r12.is_present()) { HANDLE_CODE(csi_im_cfg_id_list_r12->pack(bref)); } - if (cqi_report_aperiodic_proc2_r12_present) { + if (cqi_report_aperiodic_proc2_r12.is_present()) { HANDLE_CODE(cqi_report_aperiodic_proc2_r12->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cqi_report_aperiodic_proc_v1310_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_aperiodic_proc2_v1310_present, 1)); - HANDLE_CODE(bref.pack(e_mimo_type_r13_present, 1)); - if (cqi_report_aperiodic_proc_v1310_present) { + HANDLE_CODE(bref.pack(cqi_report_aperiodic_proc_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_aperiodic_proc2_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(e_mimo_type_r13.is_present(), 1)); + if (cqi_report_aperiodic_proc_v1310.is_present()) { HANDLE_CODE(cqi_report_aperiodic_proc_v1310->pack(bref)); } - if (cqi_report_aperiodic_proc2_v1310_present) { + if (cqi_report_aperiodic_proc2_v1310.is_present()) { HANDLE_CODE(cqi_report_aperiodic_proc2_v1310->pack(bref)); } - if (e_mimo_type_r13_present) { + if (e_mimo_type_r13.is_present()) { HANDLE_CODE(e_mimo_type_r13->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(dummy_present, 1)); - HANDLE_CODE(bref.pack(e_mimo_hybrid_r14_present, 1)); + HANDLE_CODE(bref.pack(dummy.is_present(), 1)); + HANDLE_CODE(bref.pack(e_mimo_hybrid_r14.is_present(), 1)); HANDLE_CODE(bref.pack(advanced_codebook_enabled_r14_present, 1)); - if (dummy_present) { + if (dummy.is_present()) { HANDLE_CODE(dummy->pack(bref)); } - if (e_mimo_hybrid_r14_present) { + if (e_mimo_hybrid_r14.is_present()) { HANDLE_CODE(e_mimo_hybrid_r14->pack(bref)); } if (advanced_codebook_enabled_r14_present) { @@ -23797,22 +23519,22 @@ SRSASN_CODE csi_process_r11_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(e_mimo_type_v1480_present, 1)); - if (e_mimo_type_v1480_present) { + HANDLE_CODE(bref.pack(e_mimo_type_v1480.is_present(), 1)); + if (e_mimo_type_v1480.is_present()) { HANDLE_CODE(e_mimo_type_v1480->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(fe_comp_csi_enabled_v1530_present, 1)); - HANDLE_CODE(bref.pack(e_mimo_type_v1530_present, 1)); + HANDLE_CODE(bref.pack(e_mimo_type_v1530.is_present(), 1)); if (fe_comp_csi_enabled_v1530_present) { HANDLE_CODE(bref.pack(fe_comp_csi_enabled_v1530, 1)); } - if (e_mimo_type_v1530_present) { + if (e_mimo_type_v1530.is_present()) { HANDLE_CODE(e_mimo_type_v1530->pack(bref)); } } @@ -23841,55 +23563,62 @@ SRSASN_CODE csi_process_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(5); + ext_groups_unpacker_guard group_flags(5); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(alternative_codebook_enabled_for4_tx_proc_r12_present, 1)); + bool csi_im_cfg_id_list_r12_present; HANDLE_CODE(bref.unpack(csi_im_cfg_id_list_r12_present, 1)); + csi_im_cfg_id_list_r12.set_present(csi_im_cfg_id_list_r12_present); + bool cqi_report_aperiodic_proc2_r12_present; HANDLE_CODE(bref.unpack(cqi_report_aperiodic_proc2_r12_present, 1)); - if (csi_im_cfg_id_list_r12_present) { - csi_im_cfg_id_list_r12 = make_copy_ptr(csi_im_cfg_id_list_r12_c_()); + cqi_report_aperiodic_proc2_r12.set_present(cqi_report_aperiodic_proc2_r12_present); + if (csi_im_cfg_id_list_r12.is_present()) { HANDLE_CODE(csi_im_cfg_id_list_r12->unpack(bref)); } - if (cqi_report_aperiodic_proc2_r12_present) { - cqi_report_aperiodic_proc2_r12 = make_copy_ptr(cqi_report_aperiodic_proc2_r12_c_()); + if (cqi_report_aperiodic_proc2_r12.is_present()) { HANDLE_CODE(cqi_report_aperiodic_proc2_r12->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool cqi_report_aperiodic_proc_v1310_present; HANDLE_CODE(bref.unpack(cqi_report_aperiodic_proc_v1310_present, 1)); + cqi_report_aperiodic_proc_v1310.set_present(cqi_report_aperiodic_proc_v1310_present); + bool cqi_report_aperiodic_proc2_v1310_present; HANDLE_CODE(bref.unpack(cqi_report_aperiodic_proc2_v1310_present, 1)); + cqi_report_aperiodic_proc2_v1310.set_present(cqi_report_aperiodic_proc2_v1310_present); + bool e_mimo_type_r13_present; HANDLE_CODE(bref.unpack(e_mimo_type_r13_present, 1)); - if (cqi_report_aperiodic_proc_v1310_present) { - cqi_report_aperiodic_proc_v1310 = make_copy_ptr(cqi_report_aperiodic_proc_v1310_c_()); + e_mimo_type_r13.set_present(e_mimo_type_r13_present); + if (cqi_report_aperiodic_proc_v1310.is_present()) { HANDLE_CODE(cqi_report_aperiodic_proc_v1310->unpack(bref)); } - if (cqi_report_aperiodic_proc2_v1310_present) { - cqi_report_aperiodic_proc2_v1310 = make_copy_ptr(cqi_report_aperiodic_proc2_v1310_c_()); + if (cqi_report_aperiodic_proc2_v1310.is_present()) { HANDLE_CODE(cqi_report_aperiodic_proc2_v1310->unpack(bref)); } - if (e_mimo_type_r13_present) { - e_mimo_type_r13 = make_copy_ptr(csi_rs_cfg_emimo_r13_c()); + if (e_mimo_type_r13.is_present()) { HANDLE_CODE(e_mimo_type_r13->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool dummy_present; HANDLE_CODE(bref.unpack(dummy_present, 1)); + dummy.set_present(dummy_present); + bool e_mimo_hybrid_r14_present; HANDLE_CODE(bref.unpack(e_mimo_hybrid_r14_present, 1)); + e_mimo_hybrid_r14.set_present(e_mimo_hybrid_r14_present); HANDLE_CODE(bref.unpack(advanced_codebook_enabled_r14_present, 1)); - if (dummy_present) { - dummy = make_copy_ptr(csi_rs_cfg_emimo_v1430_c()); + if (dummy.is_present()) { HANDLE_CODE(dummy->unpack(bref)); } - if (e_mimo_hybrid_r14_present) { - e_mimo_hybrid_r14 = make_copy_ptr(csi_rs_cfg_emimo_hybrid_r14_c()); + if (e_mimo_hybrid_r14.is_present()) { HANDLE_CODE(e_mimo_hybrid_r14->unpack(bref)); } if (advanced_codebook_enabled_r14_present) { @@ -23897,24 +23626,26 @@ SRSASN_CODE csi_process_r11_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool e_mimo_type_v1480_present; HANDLE_CODE(bref.unpack(e_mimo_type_v1480_present, 1)); - if (e_mimo_type_v1480_present) { - e_mimo_type_v1480 = make_copy_ptr(csi_rs_cfg_emimo_v1480_c()); + e_mimo_type_v1480.set_present(e_mimo_type_v1480_present); + if (e_mimo_type_v1480.is_present()) { HANDLE_CODE(e_mimo_type_v1480->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(fe_comp_csi_enabled_v1530_present, 1)); + bool e_mimo_type_v1530_present; HANDLE_CODE(bref.unpack(e_mimo_type_v1530_present, 1)); + e_mimo_type_v1530.set_present(e_mimo_type_v1530_present); if (fe_comp_csi_enabled_v1530_present) { HANDLE_CODE(bref.unpack(fe_comp_csi_enabled_v1530, 1)); } - if (e_mimo_type_v1530_present) { - e_mimo_type_v1530 = make_copy_ptr(csi_rs_cfg_emimo_v1530_c()); + if (e_mimo_type_v1530.is_present()) { HANDLE_CODE(e_mimo_type_v1530->unpack(bref)); } } @@ -23947,58 +23678,45 @@ void csi_process_r11_s::to_json(json_writer& j) const if (alternative_codebook_enabled_for4_tx_proc_r12_present) { j.write_str("alternativeCodebookEnabledFor4TXProc-r12", "true"); } - rrc_asn1_warn_assert(csi_im_cfg_id_list_r12_present != (csi_im_cfg_id_list_r12.get() != NULL), __FILE__, __LINE__); - if (csi_im_cfg_id_list_r12_present) { + if (csi_im_cfg_id_list_r12.is_present()) { j.write_fieldname("csi-IM-ConfigIdList-r12"); csi_im_cfg_id_list_r12->to_json(j); } - rrc_asn1_warn_assert( - cqi_report_aperiodic_proc2_r12_present != (cqi_report_aperiodic_proc2_r12.get() != NULL), __FILE__, __LINE__); - if (cqi_report_aperiodic_proc2_r12_present) { + if (cqi_report_aperiodic_proc2_r12.is_present()) { j.write_fieldname("cqi-ReportAperiodicProc2-r12"); cqi_report_aperiodic_proc2_r12->to_json(j); } - rrc_asn1_warn_assert( - cqi_report_aperiodic_proc_v1310_present != (cqi_report_aperiodic_proc_v1310.get() != NULL), __FILE__, __LINE__); - if (cqi_report_aperiodic_proc_v1310_present) { + if (cqi_report_aperiodic_proc_v1310.is_present()) { j.write_fieldname("cqi-ReportAperiodicProc-v1310"); cqi_report_aperiodic_proc_v1310->to_json(j); } - rrc_asn1_warn_assert(cqi_report_aperiodic_proc2_v1310_present != (cqi_report_aperiodic_proc2_v1310.get() != NULL), - __FILE__, - __LINE__); - if (cqi_report_aperiodic_proc2_v1310_present) { + if (cqi_report_aperiodic_proc2_v1310.is_present()) { j.write_fieldname("cqi-ReportAperiodicProc2-v1310"); cqi_report_aperiodic_proc2_v1310->to_json(j); } - rrc_asn1_warn_assert(e_mimo_type_r13_present != (e_mimo_type_r13.get() != NULL), __FILE__, __LINE__); - if (e_mimo_type_r13_present) { + if (e_mimo_type_r13.is_present()) { j.write_fieldname("eMIMO-Type-r13"); e_mimo_type_r13->to_json(j); } - rrc_asn1_warn_assert(dummy_present != (dummy.get() != NULL), __FILE__, __LINE__); - if (dummy_present) { + if (dummy.is_present()) { j.write_fieldname("dummy"); dummy->to_json(j); } - rrc_asn1_warn_assert(e_mimo_hybrid_r14_present != (e_mimo_hybrid_r14.get() != NULL), __FILE__, __LINE__); - if (e_mimo_hybrid_r14_present) { + if (e_mimo_hybrid_r14.is_present()) { j.write_fieldname("eMIMO-Hybrid-r14"); e_mimo_hybrid_r14->to_json(j); } if (advanced_codebook_enabled_r14_present) { j.write_bool("advancedCodebookEnabled-r14", advanced_codebook_enabled_r14); } - rrc_asn1_warn_assert(e_mimo_type_v1480_present != (e_mimo_type_v1480.get() != NULL), __FILE__, __LINE__); - if (e_mimo_type_v1480_present) { + if (e_mimo_type_v1480.is_present()) { j.write_fieldname("eMIMO-Type-v1480"); e_mimo_type_v1480->to_json(j); } if (fe_comp_csi_enabled_v1530_present) { j.write_bool("feCOMP-CSI-Enabled-v1530", fe_comp_csi_enabled_v1530); } - rrc_asn1_warn_assert(e_mimo_type_v1530_present != (e_mimo_type_v1530.get() != NULL), __FILE__, __LINE__); - if (e_mimo_type_v1530_present) { + if (e_mimo_type_v1530.is_present()) { j.write_fieldname("eMIMO-Type-v1530"); e_mimo_type_v1530->to_json(j); } @@ -27070,32 +26788,29 @@ SRSASN_CODE epdcch_set_cfg_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(csi_rs_cfg_zp_id2_r12_present != (csi_rs_cfg_zp_id2_r12.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= csi_rs_cfg_zp_id2_r12_present; - rrc_asn1_warn_assert(num_prb_pairs_v1310_present != (num_prb_pairs_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= num_prb_pairs_v1310_present; - rrc_asn1_warn_assert(mpdcch_cfg_r13_present != (mpdcch_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= mpdcch_cfg_r13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= csi_rs_cfg_zp_id2_r12.is_present(); + group_flags[1] |= num_prb_pairs_v1310.is_present(); + group_flags[1] |= mpdcch_cfg_r13.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(csi_rs_cfg_zp_id2_r12_present, 1)); - if (csi_rs_cfg_zp_id2_r12_present) { + HANDLE_CODE(bref.pack(csi_rs_cfg_zp_id2_r12.is_present(), 1)); + if (csi_rs_cfg_zp_id2_r12.is_present()) { HANDLE_CODE(csi_rs_cfg_zp_id2_r12->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(num_prb_pairs_v1310_present, 1)); - HANDLE_CODE(bref.pack(mpdcch_cfg_r13_present, 1)); - if (num_prb_pairs_v1310_present) { + HANDLE_CODE(bref.pack(num_prb_pairs_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(mpdcch_cfg_r13.is_present(), 1)); + if (num_prb_pairs_v1310.is_present()) { HANDLE_CODE(num_prb_pairs_v1310->pack(bref)); } - if (mpdcch_cfg_r13_present) { + if (mpdcch_cfg_r13.is_present()) { HANDLE_CODE(mpdcch_cfg_r13->pack(bref)); } } @@ -27118,29 +26833,32 @@ SRSASN_CODE epdcch_set_cfg_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool csi_rs_cfg_zp_id2_r12_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_zp_id2_r12_present, 1)); - if (csi_rs_cfg_zp_id2_r12_present) { - csi_rs_cfg_zp_id2_r12 = make_copy_ptr(csi_rs_cfg_zp_id2_r12_c_()); + csi_rs_cfg_zp_id2_r12.set_present(csi_rs_cfg_zp_id2_r12_present); + if (csi_rs_cfg_zp_id2_r12.is_present()) { HANDLE_CODE(csi_rs_cfg_zp_id2_r12->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool num_prb_pairs_v1310_present; HANDLE_CODE(bref.unpack(num_prb_pairs_v1310_present, 1)); + num_prb_pairs_v1310.set_present(num_prb_pairs_v1310_present); + bool mpdcch_cfg_r13_present; HANDLE_CODE(bref.unpack(mpdcch_cfg_r13_present, 1)); - if (num_prb_pairs_v1310_present) { - num_prb_pairs_v1310 = make_copy_ptr(num_prb_pairs_v1310_c_()); + mpdcch_cfg_r13.set_present(mpdcch_cfg_r13_present); + if (num_prb_pairs_v1310.is_present()) { HANDLE_CODE(num_prb_pairs_v1310->unpack(bref)); } - if (mpdcch_cfg_r13_present) { - mpdcch_cfg_r13 = make_copy_ptr(mpdcch_cfg_r13_c_()); + if (mpdcch_cfg_r13.is_present()) { HANDLE_CODE(mpdcch_cfg_r13->unpack(bref)); } } @@ -27163,18 +26881,15 @@ void epdcch_set_cfg_r11_s::to_json(json_writer& j) const j.write_int("re-MappingQCL-ConfigId-r11", re_map_qcl_cfg_id_r11); } if (ext) { - rrc_asn1_warn_assert(csi_rs_cfg_zp_id2_r12_present != (csi_rs_cfg_zp_id2_r12.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_zp_id2_r12_present) { + if (csi_rs_cfg_zp_id2_r12.is_present()) { j.write_fieldname("csi-RS-ConfigZPId2-r12"); csi_rs_cfg_zp_id2_r12->to_json(j); } - rrc_asn1_warn_assert(num_prb_pairs_v1310_present != (num_prb_pairs_v1310.get() != NULL), __FILE__, __LINE__); - if (num_prb_pairs_v1310_present) { + if (num_prb_pairs_v1310.is_present()) { j.write_fieldname("numberPRB-Pairs-v1310"); num_prb_pairs_v1310->to_json(j); } - rrc_asn1_warn_assert(mpdcch_cfg_r13_present != (mpdcch_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (mpdcch_cfg_r13_present) { + if (mpdcch_cfg_r13.is_present()) { j.write_fieldname("mpdcch-config-r13"); mpdcch_cfg_r13->to_json(j); } @@ -27623,27 +27338,24 @@ SRSASN_CODE lc_ch_cfg_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); + ext_groups_packer_guard group_flags; group_flags[0] |= lc_ch_sr_mask_r9_present; group_flags[1] |= lc_ch_sr_prohibit_r12_present; group_flags[2] |= laa_ul_allowed_r14_present; group_flags[2] |= bit_rate_query_prohibit_timer_r14_present; - rrc_asn1_warn_assert(allowed_tti_lens_r15_present != (allowed_tti_lens_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= allowed_tti_lens_r15_present; - rrc_asn1_warn_assert(lc_ch_sr_restrict_r15_present != (lc_ch_sr_restrict_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= lc_ch_sr_restrict_r15_present; - rrc_asn1_warn_assert(chl_access_prio_r15_present != (chl_access_prio_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= chl_access_prio_r15_present; + group_flags[3] |= allowed_tti_lens_r15.is_present(); + group_flags[3] |= lc_ch_sr_restrict_r15.is_present(); + group_flags[3] |= chl_access_prio_r15.is_present(); group_flags[3] |= lch_cell_restrict_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(lc_ch_sr_mask_r9_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(lc_ch_sr_prohibit_r12_present, 1)); if (lc_ch_sr_prohibit_r12_present) { @@ -27651,7 +27363,7 @@ SRSASN_CODE lc_ch_cfg_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(laa_ul_allowed_r14_present, 1)); HANDLE_CODE(bref.pack(bit_rate_query_prohibit_timer_r14_present, 1)); @@ -27663,19 +27375,19 @@ SRSASN_CODE lc_ch_cfg_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(allowed_tti_lens_r15_present, 1)); - HANDLE_CODE(bref.pack(lc_ch_sr_restrict_r15_present, 1)); - HANDLE_CODE(bref.pack(chl_access_prio_r15_present, 1)); + HANDLE_CODE(bref.pack(allowed_tti_lens_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(lc_ch_sr_restrict_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(chl_access_prio_r15.is_present(), 1)); HANDLE_CODE(bref.pack(lch_cell_restrict_r15_present, 1)); - if (allowed_tti_lens_r15_present) { + if (allowed_tti_lens_r15.is_present()) { HANDLE_CODE(allowed_tti_lens_r15->pack(bref)); } - if (lc_ch_sr_restrict_r15_present) { + if (lc_ch_sr_restrict_r15.is_present()) { HANDLE_CODE(lc_ch_sr_restrict_r15->pack(bref)); } - if (chl_access_prio_r15_present) { + if (chl_access_prio_r15.is_present()) { HANDLE_CODE(chl_access_prio_r15->pack(bref)); } if (lch_cell_restrict_r15_present) { @@ -27701,16 +27413,16 @@ SRSASN_CODE lc_ch_cfg_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(lc_ch_sr_mask_r9_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(lc_ch_sr_prohibit_r12_present, 1)); if (lc_ch_sr_prohibit_r12_present) { @@ -27718,7 +27430,7 @@ SRSASN_CODE lc_ch_cfg_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(laa_ul_allowed_r14_present, 1)); HANDLE_CODE(bref.unpack(bit_rate_query_prohibit_timer_r14_present, 1)); @@ -27730,22 +27442,25 @@ SRSASN_CODE lc_ch_cfg_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool allowed_tti_lens_r15_present; HANDLE_CODE(bref.unpack(allowed_tti_lens_r15_present, 1)); + allowed_tti_lens_r15.set_present(allowed_tti_lens_r15_present); + bool lc_ch_sr_restrict_r15_present; HANDLE_CODE(bref.unpack(lc_ch_sr_restrict_r15_present, 1)); + lc_ch_sr_restrict_r15.set_present(lc_ch_sr_restrict_r15_present); + bool chl_access_prio_r15_present; HANDLE_CODE(bref.unpack(chl_access_prio_r15_present, 1)); + chl_access_prio_r15.set_present(chl_access_prio_r15_present); HANDLE_CODE(bref.unpack(lch_cell_restrict_r15_present, 1)); - if (allowed_tti_lens_r15_present) { - allowed_tti_lens_r15 = make_copy_ptr(allowed_tti_lens_r15_c_()); + if (allowed_tti_lens_r15.is_present()) { HANDLE_CODE(allowed_tti_lens_r15->unpack(bref)); } - if (lc_ch_sr_restrict_r15_present) { - lc_ch_sr_restrict_r15 = make_copy_ptr(lc_ch_sr_restrict_r15_c_()); + if (lc_ch_sr_restrict_r15.is_present()) { HANDLE_CODE(lc_ch_sr_restrict_r15->unpack(bref)); } - if (chl_access_prio_r15_present) { - chl_access_prio_r15 = make_copy_ptr(chl_access_prio_r15_c_()); + if (chl_access_prio_r15.is_present()) { HANDLE_CODE(chl_access_prio_r15->unpack(bref)); } if (lch_cell_restrict_r15_present) { @@ -27782,18 +27497,15 @@ void lc_ch_cfg_s::to_json(json_writer& j) const if (bit_rate_query_prohibit_timer_r14_present) { j.write_str("bitRateQueryProhibitTimer-r14", bit_rate_query_prohibit_timer_r14.to_string()); } - rrc_asn1_warn_assert(allowed_tti_lens_r15_present != (allowed_tti_lens_r15.get() != NULL), __FILE__, __LINE__); - if (allowed_tti_lens_r15_present) { + if (allowed_tti_lens_r15.is_present()) { j.write_fieldname("allowedTTI-Lengths-r15"); allowed_tti_lens_r15->to_json(j); } - rrc_asn1_warn_assert(lc_ch_sr_restrict_r15_present != (lc_ch_sr_restrict_r15.get() != NULL), __FILE__, __LINE__); - if (lc_ch_sr_restrict_r15_present) { + if (lc_ch_sr_restrict_r15.is_present()) { j.write_fieldname("logicalChannelSR-Restriction-r15"); lc_ch_sr_restrict_r15->to_json(j); } - rrc_asn1_warn_assert(chl_access_prio_r15_present != (chl_access_prio_r15.get() != NULL), __FILE__, __LINE__); - if (chl_access_prio_r15_present) { + if (chl_access_prio_r15.is_present()) { j.write_fieldname("channellAccessPriority-r15"); chl_access_prio_r15->to_json(j); } @@ -27986,27 +27698,24 @@ SRSASN_CODE pdsch_re_map_qcl_cfg_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= mbsfn_sf_cfg_list_v1430_present; - rrc_asn1_warn_assert(codeword_one_cfg_v1530_present != (codeword_one_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= codeword_one_cfg_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= mbsfn_sf_cfg_list_v1430.is_present(); + group_flags[1] |= codeword_one_cfg_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { + HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430.is_present(), 1)); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(mbsfn_sf_cfg_list_v1430->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(codeword_one_cfg_v1530_present, 1)); - if (codeword_one_cfg_v1530_present) { + HANDLE_CODE(bref.pack(codeword_one_cfg_v1530.is_present(), 1)); + if (codeword_one_cfg_v1530.is_present()) { HANDLE_CODE(codeword_one_cfg_v1530->pack(bref)); } } @@ -28035,24 +27744,26 @@ SRSASN_CODE pdsch_re_map_qcl_cfg_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mbsfn_sf_cfg_list_v1430_present; HANDLE_CODE(bref.unpack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { - mbsfn_sf_cfg_list_v1430 = make_copy_ptr(mbsfn_sf_cfg_list_v1430_c_()); + mbsfn_sf_cfg_list_v1430.set_present(mbsfn_sf_cfg_list_v1430_present); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(mbsfn_sf_cfg_list_v1430->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool codeword_one_cfg_v1530_present; HANDLE_CODE(bref.unpack(codeword_one_cfg_v1530_present, 1)); - if (codeword_one_cfg_v1530_present) { - codeword_one_cfg_v1530 = make_copy_ptr(codeword_one_cfg_v1530_c_()); + codeword_one_cfg_v1530.set_present(codeword_one_cfg_v1530_present); + if (codeword_one_cfg_v1530.is_present()) { HANDLE_CODE(codeword_one_cfg_v1530->unpack(bref)); } } @@ -28080,14 +27791,11 @@ void pdsch_re_map_qcl_cfg_r11_s::to_json(json_writer& j) const j.write_int("qcl-CSI-RS-ConfigNZPId-r11", qcl_csi_rs_cfg_nzp_id_r11); } if (ext) { - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - if (mbsfn_sf_cfg_list_v1430_present) { + if (mbsfn_sf_cfg_list_v1430.is_present()) { j.write_fieldname("mbsfn-SubframeConfigList-v1430"); mbsfn_sf_cfg_list_v1430->to_json(j); } - rrc_asn1_warn_assert(codeword_one_cfg_v1530_present != (codeword_one_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (codeword_one_cfg_v1530_present) { + if (codeword_one_cfg_v1530.is_present()) { j.write_fieldname("codewordOneConfig-v1530"); codeword_one_cfg_v1530->to_json(j); } @@ -29383,17 +29091,15 @@ SRSASN_CODE crs_assist_info_r11_s::pack(bit_ref& bref) const HANDLE_CODE(pack_dyn_seq_of(bref, mbsfn_sf_cfg_list_r11, 1, 8)); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= mbsfn_sf_cfg_list_v1430_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= mbsfn_sf_cfg_list_v1430.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { + HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430.is_present(), 1)); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *mbsfn_sf_cfg_list_v1430, 1, 8)); } } @@ -29408,15 +29114,16 @@ SRSASN_CODE crs_assist_info_r11_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_dyn_seq_of(mbsfn_sf_cfg_list_r11, bref, 1, 8)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mbsfn_sf_cfg_list_v1430_present; HANDLE_CODE(bref.unpack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { - mbsfn_sf_cfg_list_v1430 = make_copy_ptr(mbsfn_sf_cfg_list_v1430_l()); + mbsfn_sf_cfg_list_v1430.set_present(mbsfn_sf_cfg_list_v1430_present); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*mbsfn_sf_cfg_list_v1430, bref, 1, 8)); } } @@ -29434,9 +29141,7 @@ void crs_assist_info_r11_s::to_json(json_writer& j) const } j.end_array(); if (ext) { - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - if (mbsfn_sf_cfg_list_v1430_present) { + if (mbsfn_sf_cfg_list_v1430.is_present()) { j.start_array("mbsfn-SubframeConfigList-v1430"); for (uint32_t i1 = 0; i1 < mbsfn_sf_cfg_list_v1430->size(); ++i1) { ((*mbsfn_sf_cfg_list_v1430)[i1]).to_json(j); @@ -29460,17 +29165,15 @@ SRSASN_CODE crs_assist_info_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= mbsfn_sf_cfg_list_v1430_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= mbsfn_sf_cfg_list_v1430.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { + HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430.is_present(), 1)); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *mbsfn_sf_cfg_list_v1430, 1, 8)); } } @@ -29489,15 +29192,16 @@ SRSASN_CODE crs_assist_info_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mbsfn_sf_cfg_list_v1430_present; HANDLE_CODE(bref.unpack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { - mbsfn_sf_cfg_list_v1430 = make_copy_ptr(mbsfn_sf_cfg_list_v1430_l()); + mbsfn_sf_cfg_list_v1430.set_present(mbsfn_sf_cfg_list_v1430_present); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*mbsfn_sf_cfg_list_v1430, bref, 1, 8)); } } @@ -29517,9 +29221,7 @@ void crs_assist_info_r13_s::to_json(json_writer& j) const j.end_array(); } if (ext) { - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - if (mbsfn_sf_cfg_list_v1430_present) { + if (mbsfn_sf_cfg_list_v1430.is_present()) { j.start_array("mbsfn-SubframeConfigList-v1430"); for (uint32_t i1 = 0; i1 < mbsfn_sf_cfg_list_v1430->size(); ++i1) { ((*mbsfn_sf_cfg_list_v1430)[i1]).to_json(j); @@ -30149,40 +29851,32 @@ SRSASN_CODE pdcp_cfg_s::pack(bit_ref& bref) const HANDLE_CODE(hdr_compress.pack(bref)); if (ext) { - ext_groups_header group_flags(6); + ext_groups_packer_guard group_flags; group_flags[0] |= rn_integrity_protection_r10_present; group_flags[1] |= pdcp_sn_size_v1130_present; group_flags[2] |= ul_data_split_drb_via_scg_r12_present; group_flags[2] |= t_reordering_r12_present; - rrc_asn1_warn_assert( - ul_data_split_thres_r13_present != (ul_data_split_thres_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= ul_data_split_thres_r13_present; + group_flags[3] |= ul_data_split_thres_r13.is_present(); group_flags[3] |= pdcp_sn_size_v1310_present; - rrc_asn1_warn_assert(status_feedback_r13_present != (status_feedback_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= status_feedback_r13_present; - rrc_asn1_warn_assert(ul_lwa_cfg_r14_present != (ul_lwa_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= ul_lwa_cfg_r14_present; - rrc_asn1_warn_assert( - ul_only_hdr_compress_r14_present != (ul_only_hdr_compress_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= ul_only_hdr_compress_r14_present; - rrc_asn1_warn_assert(ul_data_compress_r15_present != (ul_data_compress_r15.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= ul_data_compress_r15_present; - rrc_asn1_warn_assert(pdcp_dupl_cfg_r15_present != (pdcp_dupl_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= pdcp_dupl_cfg_r15_present; + group_flags[3] |= status_feedback_r13.is_present(); + group_flags[4] |= ul_lwa_cfg_r14.is_present(); + group_flags[4] |= ul_only_hdr_compress_r14.is_present(); + group_flags[5] |= ul_data_compress_r15.is_present(); + group_flags[5] |= pdcp_dupl_cfg_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(rn_integrity_protection_r10_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(pdcp_sn_size_v1130_present, 1)); } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(ul_data_split_drb_via_scg_r12_present, 1)); HANDLE_CODE(bref.pack(t_reordering_r12_present, 1)); @@ -30194,36 +29888,36 @@ SRSASN_CODE pdcp_cfg_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_data_split_thres_r13_present, 1)); + HANDLE_CODE(bref.pack(ul_data_split_thres_r13.is_present(), 1)); HANDLE_CODE(bref.pack(pdcp_sn_size_v1310_present, 1)); - HANDLE_CODE(bref.pack(status_feedback_r13_present, 1)); - if (ul_data_split_thres_r13_present) { + HANDLE_CODE(bref.pack(status_feedback_r13.is_present(), 1)); + if (ul_data_split_thres_r13.is_present()) { HANDLE_CODE(ul_data_split_thres_r13->pack(bref)); } - if (status_feedback_r13_present) { + if (status_feedback_r13.is_present()) { HANDLE_CODE(status_feedback_r13->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_lwa_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(ul_only_hdr_compress_r14_present, 1)); - if (ul_lwa_cfg_r14_present) { + HANDLE_CODE(bref.pack(ul_lwa_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_only_hdr_compress_r14.is_present(), 1)); + if (ul_lwa_cfg_r14.is_present()) { HANDLE_CODE(ul_lwa_cfg_r14->pack(bref)); } - if (ul_only_hdr_compress_r14_present) { + if (ul_only_hdr_compress_r14.is_present()) { HANDLE_CODE(ul_only_hdr_compress_r14->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_data_compress_r15_present, 1)); - HANDLE_CODE(bref.pack(pdcp_dupl_cfg_r15_present, 1)); - if (ul_data_compress_r15_present) { + HANDLE_CODE(bref.pack(ul_data_compress_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(pdcp_dupl_cfg_r15.is_present(), 1)); + if (ul_data_compress_r15.is_present()) { bref.pack(ul_data_compress_r15->ext, 1); HANDLE_CODE(bref.pack(ul_data_compress_r15->dictionary_r15_present, 1)); HANDLE_CODE(pack_enum(bref, ul_data_compress_r15->buffer_size_r15)); @@ -30231,7 +29925,7 @@ SRSASN_CODE pdcp_cfg_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, ul_data_compress_r15->dictionary_r15)); } } - if (pdcp_dupl_cfg_r15_present) { + if (pdcp_dupl_cfg_r15.is_present()) { HANDLE_CODE(pdcp_dupl_cfg_r15->pack(bref)); } } @@ -30257,21 +29951,21 @@ SRSASN_CODE pdcp_cfg_s::unpack(bit_ref& bref) HANDLE_CODE(hdr_compress.unpack(bref)); if (ext) { - ext_groups_header group_flags(6); + ext_groups_unpacker_guard group_flags(6); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(rn_integrity_protection_r10_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(pdcp_sn_size_v1130_present, 1)); } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(ul_data_split_drb_via_scg_r12_present, 1)); HANDLE_CODE(bref.unpack(t_reordering_r12_present, 1)); @@ -30283,41 +29977,48 @@ SRSASN_CODE pdcp_cfg_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_data_split_thres_r13_present; HANDLE_CODE(bref.unpack(ul_data_split_thres_r13_present, 1)); + ul_data_split_thres_r13.set_present(ul_data_split_thres_r13_present); HANDLE_CODE(bref.unpack(pdcp_sn_size_v1310_present, 1)); + bool status_feedback_r13_present; HANDLE_CODE(bref.unpack(status_feedback_r13_present, 1)); - if (ul_data_split_thres_r13_present) { - ul_data_split_thres_r13 = make_copy_ptr(ul_data_split_thres_r13_c_()); + status_feedback_r13.set_present(status_feedback_r13_present); + if (ul_data_split_thres_r13.is_present()) { HANDLE_CODE(ul_data_split_thres_r13->unpack(bref)); } - if (status_feedback_r13_present) { - status_feedback_r13 = make_copy_ptr(status_feedback_r13_c_()); + if (status_feedback_r13.is_present()) { HANDLE_CODE(status_feedback_r13->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_lwa_cfg_r14_present; HANDLE_CODE(bref.unpack(ul_lwa_cfg_r14_present, 1)); + ul_lwa_cfg_r14.set_present(ul_lwa_cfg_r14_present); + bool ul_only_hdr_compress_r14_present; HANDLE_CODE(bref.unpack(ul_only_hdr_compress_r14_present, 1)); - if (ul_lwa_cfg_r14_present) { - ul_lwa_cfg_r14 = make_copy_ptr(ul_lwa_cfg_r14_c_()); + ul_only_hdr_compress_r14.set_present(ul_only_hdr_compress_r14_present); + if (ul_lwa_cfg_r14.is_present()) { HANDLE_CODE(ul_lwa_cfg_r14->unpack(bref)); } - if (ul_only_hdr_compress_r14_present) { - ul_only_hdr_compress_r14 = make_copy_ptr(ul_only_hdr_compress_r14_c_()); + if (ul_only_hdr_compress_r14.is_present()) { HANDLE_CODE(ul_only_hdr_compress_r14->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_data_compress_r15_present; HANDLE_CODE(bref.unpack(ul_data_compress_r15_present, 1)); + ul_data_compress_r15.set_present(ul_data_compress_r15_present); + bool pdcp_dupl_cfg_r15_present; HANDLE_CODE(bref.unpack(pdcp_dupl_cfg_r15_present, 1)); - if (ul_data_compress_r15_present) { - ul_data_compress_r15 = make_copy_ptr(ul_data_compress_r15_s_()); + pdcp_dupl_cfg_r15.set_present(pdcp_dupl_cfg_r15_present); + if (ul_data_compress_r15.is_present()) { bref.unpack(ul_data_compress_r15->ext, 1); HANDLE_CODE(bref.unpack(ul_data_compress_r15->dictionary_r15_present, 1)); HANDLE_CODE(unpack_enum(ul_data_compress_r15->buffer_size_r15, bref)); @@ -30325,8 +30026,7 @@ SRSASN_CODE pdcp_cfg_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(ul_data_compress_r15->dictionary_r15, bref)); } } - if (pdcp_dupl_cfg_r15_present) { - pdcp_dupl_cfg_r15 = make_copy_ptr(pdcp_dupl_cfg_r15_c_()); + if (pdcp_dupl_cfg_r15.is_present()) { HANDLE_CODE(pdcp_dupl_cfg_r15->unpack(bref)); } } @@ -30366,33 +30066,26 @@ void pdcp_cfg_s::to_json(json_writer& j) const if (t_reordering_r12_present) { j.write_str("t-Reordering-r12", t_reordering_r12.to_string()); } - rrc_asn1_warn_assert( - ul_data_split_thres_r13_present != (ul_data_split_thres_r13.get() != NULL), __FILE__, __LINE__); - if (ul_data_split_thres_r13_present) { + if (ul_data_split_thres_r13.is_present()) { j.write_fieldname("ul-DataSplitThreshold-r13"); ul_data_split_thres_r13->to_json(j); } if (pdcp_sn_size_v1310_present) { j.write_str("pdcp-SN-Size-v1310", "len18bits"); } - rrc_asn1_warn_assert(status_feedback_r13_present != (status_feedback_r13.get() != NULL), __FILE__, __LINE__); - if (status_feedback_r13_present) { + if (status_feedback_r13.is_present()) { j.write_fieldname("statusFeedback-r13"); status_feedback_r13->to_json(j); } - rrc_asn1_warn_assert(ul_lwa_cfg_r14_present != (ul_lwa_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (ul_lwa_cfg_r14_present) { + if (ul_lwa_cfg_r14.is_present()) { j.write_fieldname("ul-LWA-Config-r14"); ul_lwa_cfg_r14->to_json(j); } - rrc_asn1_warn_assert( - ul_only_hdr_compress_r14_present != (ul_only_hdr_compress_r14.get() != NULL), __FILE__, __LINE__); - if (ul_only_hdr_compress_r14_present) { + if (ul_only_hdr_compress_r14.is_present()) { j.write_fieldname("uplinkOnlyHeaderCompression-r14"); ul_only_hdr_compress_r14->to_json(j); } - rrc_asn1_warn_assert(ul_data_compress_r15_present != (ul_data_compress_r15.get() != NULL), __FILE__, __LINE__); - if (ul_data_compress_r15_present) { + if (ul_data_compress_r15.is_present()) { j.write_fieldname("uplinkDataCompression-r15"); j.start_obj(); j.write_str("bufferSize-r15", ul_data_compress_r15->buffer_size_r15.to_string()); @@ -30401,8 +30094,7 @@ void pdcp_cfg_s::to_json(json_writer& j) const } j.end_obj(); } - rrc_asn1_warn_assert(pdcp_dupl_cfg_r15_present != (pdcp_dupl_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (pdcp_dupl_cfg_r15_present) { + if (pdcp_dupl_cfg_r15.is_present()) { j.write_fieldname("pdcp-DuplicationConfig-r15"); pdcp_dupl_cfg_r15->to_json(j); } @@ -31723,10 +31415,8 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); - rrc_asn1_warn_assert( - p0_persistent_sf_set2_r12_present != (p0_persistent_sf_set2_r12.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= p0_persistent_sf_set2_r12_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= p0_persistent_sf_set2_r12.is_present(); group_flags[1] |= nof_conf_ul_sps_processes_r13_present; group_flags[2] |= fixed_rv_non_adaptive_r14_present; group_flags[2] |= sps_cfg_idx_r14_present; @@ -31734,23 +31424,21 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::pack(bit_ref& bref) const group_flags[3] |= cyclic_shift_sps_r15_present; group_flags[3] |= harq_proc_id_offset_r15_present; group_flags[3] |= rv_sps_ul_repeats_r15_present; - rrc_asn1_warn_assert( - tpc_pdcch_cfg_pusch_sps_r15_present != (tpc_pdcch_cfg_pusch_sps_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= tpc_pdcch_cfg_pusch_sps_r15_present; + group_flags[3] |= tpc_pdcch_cfg_pusch_sps_r15.is_present(); group_flags[3] |= total_num_pusch_sps_ul_repeats_r15_present; group_flags[3] |= sps_cfg_idx_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(p0_persistent_sf_set2_r12_present, 1)); - if (p0_persistent_sf_set2_r12_present) { + HANDLE_CODE(bref.pack(p0_persistent_sf_set2_r12.is_present(), 1)); + if (p0_persistent_sf_set2_r12.is_present()) { HANDLE_CODE(p0_persistent_sf_set2_r12->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(nof_conf_ul_sps_processes_r13_present, 1)); if (nof_conf_ul_sps_processes_r13_present) { @@ -31758,7 +31446,7 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(fixed_rv_non_adaptive_r14_present, 1)); HANDLE_CODE(bref.pack(sps_cfg_idx_r14_present, 1)); @@ -31771,12 +31459,12 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(cyclic_shift_sps_r15_present, 1)); HANDLE_CODE(bref.pack(harq_proc_id_offset_r15_present, 1)); HANDLE_CODE(bref.pack(rv_sps_ul_repeats_r15_present, 1)); - HANDLE_CODE(bref.pack(tpc_pdcch_cfg_pusch_sps_r15_present, 1)); + HANDLE_CODE(bref.pack(tpc_pdcch_cfg_pusch_sps_r15.is_present(), 1)); HANDLE_CODE(bref.pack(total_num_pusch_sps_ul_repeats_r15_present, 1)); HANDLE_CODE(bref.pack(sps_cfg_idx_r15_present, 1)); if (cyclic_shift_sps_r15_present) { @@ -31788,7 +31476,7 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::pack(bit_ref& bref) const if (rv_sps_ul_repeats_r15_present) { HANDLE_CODE(pack_enum(bref, rv_sps_ul_repeats_r15)); } - if (tpc_pdcch_cfg_pusch_sps_r15_present) { + if (tpc_pdcch_cfg_pusch_sps_r15.is_present()) { HANDLE_CODE(tpc_pdcch_cfg_pusch_sps_r15->pack(bref)); } if (total_num_pusch_sps_ul_repeats_r15_present) { @@ -31815,20 +31503,21 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool p0_persistent_sf_set2_r12_present; HANDLE_CODE(bref.unpack(p0_persistent_sf_set2_r12_present, 1)); - if (p0_persistent_sf_set2_r12_present) { - p0_persistent_sf_set2_r12 = make_copy_ptr(p0_persistent_sf_set2_r12_c_()); + p0_persistent_sf_set2_r12.set_present(p0_persistent_sf_set2_r12_present); + if (p0_persistent_sf_set2_r12.is_present()) { HANDLE_CODE(p0_persistent_sf_set2_r12->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(nof_conf_ul_sps_processes_r13_present, 1)); if (nof_conf_ul_sps_processes_r13_present) { @@ -31836,7 +31525,7 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(fixed_rv_non_adaptive_r14_present, 1)); HANDLE_CODE(bref.unpack(sps_cfg_idx_r14_present, 1)); @@ -31849,12 +31538,14 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(cyclic_shift_sps_r15_present, 1)); HANDLE_CODE(bref.unpack(harq_proc_id_offset_r15_present, 1)); HANDLE_CODE(bref.unpack(rv_sps_ul_repeats_r15_present, 1)); + bool tpc_pdcch_cfg_pusch_sps_r15_present; HANDLE_CODE(bref.unpack(tpc_pdcch_cfg_pusch_sps_r15_present, 1)); + tpc_pdcch_cfg_pusch_sps_r15.set_present(tpc_pdcch_cfg_pusch_sps_r15_present); HANDLE_CODE(bref.unpack(total_num_pusch_sps_ul_repeats_r15_present, 1)); HANDLE_CODE(bref.unpack(sps_cfg_idx_r15_present, 1)); if (cyclic_shift_sps_r15_present) { @@ -31866,8 +31557,7 @@ SRSASN_CODE sps_cfg_ul_c::setup_s_::unpack(bit_ref& bref) if (rv_sps_ul_repeats_r15_present) { HANDLE_CODE(unpack_enum(rv_sps_ul_repeats_r15, bref)); } - if (tpc_pdcch_cfg_pusch_sps_r15_present) { - tpc_pdcch_cfg_pusch_sps_r15 = make_copy_ptr(tpc_pdcch_cfg_c()); + if (tpc_pdcch_cfg_pusch_sps_r15.is_present()) { HANDLE_CODE(tpc_pdcch_cfg_pusch_sps_r15->unpack(bref)); } if (total_num_pusch_sps_ul_repeats_r15_present) { @@ -31896,9 +31586,7 @@ void sps_cfg_ul_c::setup_s_::to_json(json_writer& j) const j.write_str("twoIntervalsConfig", "true"); } if (ext) { - rrc_asn1_warn_assert( - p0_persistent_sf_set2_r12_present != (p0_persistent_sf_set2_r12.get() != NULL), __FILE__, __LINE__); - if (p0_persistent_sf_set2_r12_present) { + if (p0_persistent_sf_set2_r12.is_present()) { j.write_fieldname("p0-PersistentSubframeSet2-r12"); p0_persistent_sf_set2_r12->to_json(j); } @@ -31923,9 +31611,7 @@ void sps_cfg_ul_c::setup_s_::to_json(json_writer& j) const if (rv_sps_ul_repeats_r15_present) { j.write_str("rv-SPS-UL-Repetitions-r15", rv_sps_ul_repeats_r15.to_string()); } - rrc_asn1_warn_assert( - tpc_pdcch_cfg_pusch_sps_r15_present != (tpc_pdcch_cfg_pusch_sps_r15.get() != NULL), __FILE__, __LINE__); - if (tpc_pdcch_cfg_pusch_sps_r15_present) { + if (tpc_pdcch_cfg_pusch_sps_r15.is_present()) { j.write_fieldname("tpc-PDCCH-ConfigPUSCH-SPS-r15"); tpc_pdcch_cfg_pusch_sps_r15->to_json(j); } @@ -34173,45 +33859,38 @@ SRSASN_CODE drb_to_add_mod_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(5); + ext_groups_packer_guard group_flags; group_flags[0] |= drb_type_change_r12_present; - rrc_asn1_warn_assert(rlc_cfg_v1250_present != (rlc_cfg_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rlc_cfg_v1250_present; - rrc_asn1_warn_assert(rlc_cfg_v1310_present != (rlc_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= rlc_cfg_v1310_present; + group_flags[0] |= rlc_cfg_v1250.is_present(); + group_flags[1] |= rlc_cfg_v1310.is_present(); group_flags[1] |= drb_type_lwa_r13_present; group_flags[1] |= drb_type_lwip_r13_present; - rrc_asn1_warn_assert(rlc_cfg_v1430_present != (rlc_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= rlc_cfg_v1430_present; + group_flags[2] |= rlc_cfg_v1430.is_present(); group_flags[2] |= lwip_ul_aggregation_r14_present; group_flags[2] |= lwip_dl_aggregation_r14_present; group_flags[2] |= lwa_wlan_ac_r14_present; - rrc_asn1_warn_assert(rlc_cfg_v1510_present != (rlc_cfg_v1510.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= rlc_cfg_v1510_present; - rrc_asn1_warn_assert(rlc_cfg_v1530_present != (rlc_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= rlc_cfg_v1530_present; - rrc_asn1_warn_assert( - rlc_bearer_cfg_dupl_r15_present != (rlc_bearer_cfg_dupl_r15.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= rlc_bearer_cfg_dupl_r15_present; + group_flags[3] |= rlc_cfg_v1510.is_present(); + group_flags[4] |= rlc_cfg_v1530.is_present(); + group_flags[4] |= rlc_bearer_cfg_dupl_r15.is_present(); group_flags[4] |= lc_ch_id_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(drb_type_change_r12_present, 1)); - HANDLE_CODE(bref.pack(rlc_cfg_v1250_present, 1)); - if (rlc_cfg_v1250_present) { + HANDLE_CODE(bref.pack(rlc_cfg_v1250.is_present(), 1)); + if (rlc_cfg_v1250.is_present()) { HANDLE_CODE(rlc_cfg_v1250->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rlc_cfg_v1310_present, 1)); + HANDLE_CODE(bref.pack(rlc_cfg_v1310.is_present(), 1)); HANDLE_CODE(bref.pack(drb_type_lwa_r13_present, 1)); HANDLE_CODE(bref.pack(drb_type_lwip_r13_present, 1)); - if (rlc_cfg_v1310_present) { + if (rlc_cfg_v1310.is_present()) { HANDLE_CODE(rlc_cfg_v1310->pack(bref)); } if (drb_type_lwa_r13_present) { @@ -34222,13 +33901,13 @@ SRSASN_CODE drb_to_add_mod_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rlc_cfg_v1430_present, 1)); + HANDLE_CODE(bref.pack(rlc_cfg_v1430.is_present(), 1)); HANDLE_CODE(bref.pack(lwip_ul_aggregation_r14_present, 1)); HANDLE_CODE(bref.pack(lwip_dl_aggregation_r14_present, 1)); HANDLE_CODE(bref.pack(lwa_wlan_ac_r14_present, 1)); - if (rlc_cfg_v1430_present) { + if (rlc_cfg_v1430.is_present()) { HANDLE_CODE(rlc_cfg_v1430->pack(bref)); } if (lwip_ul_aggregation_r14_present) { @@ -34242,23 +33921,23 @@ SRSASN_CODE drb_to_add_mod_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rlc_cfg_v1510_present, 1)); - if (rlc_cfg_v1510_present) { + HANDLE_CODE(bref.pack(rlc_cfg_v1510.is_present(), 1)); + if (rlc_cfg_v1510.is_present()) { HANDLE_CODE(rlc_cfg_v1510->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rlc_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(rlc_bearer_cfg_dupl_r15_present, 1)); + HANDLE_CODE(bref.pack(rlc_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(rlc_bearer_cfg_dupl_r15.is_present(), 1)); HANDLE_CODE(bref.pack(lc_ch_id_r15_present, 1)); - if (rlc_cfg_v1530_present) { + if (rlc_cfg_v1530.is_present()) { HANDLE_CODE(rlc_cfg_v1530->pack(bref)); } - if (rlc_bearer_cfg_dupl_r15_present) { + if (rlc_bearer_cfg_dupl_r15.is_present()) { HANDLE_CODE(rlc_bearer_cfg_dupl_r15->pack(bref)); } if (lc_ch_id_r15_present) { @@ -34295,27 +33974,29 @@ SRSASN_CODE drb_to_add_mod_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(5); + ext_groups_unpacker_guard group_flags(5); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(drb_type_change_r12_present, 1)); + bool rlc_cfg_v1250_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1250_present, 1)); - if (rlc_cfg_v1250_present) { - rlc_cfg_v1250 = make_copy_ptr(rlc_cfg_v1250_s()); + rlc_cfg_v1250.set_present(rlc_cfg_v1250_present); + if (rlc_cfg_v1250.is_present()) { HANDLE_CODE(rlc_cfg_v1250->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rlc_cfg_v1310_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1310_present, 1)); + rlc_cfg_v1310.set_present(rlc_cfg_v1310_present); HANDLE_CODE(bref.unpack(drb_type_lwa_r13_present, 1)); HANDLE_CODE(bref.unpack(drb_type_lwip_r13_present, 1)); - if (rlc_cfg_v1310_present) { - rlc_cfg_v1310 = make_copy_ptr(rlc_cfg_v1310_s()); + if (rlc_cfg_v1310.is_present()) { HANDLE_CODE(rlc_cfg_v1310->unpack(bref)); } if (drb_type_lwa_r13_present) { @@ -34326,14 +34007,15 @@ SRSASN_CODE drb_to_add_mod_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rlc_cfg_v1430_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1430_present, 1)); + rlc_cfg_v1430.set_present(rlc_cfg_v1430_present); HANDLE_CODE(bref.unpack(lwip_ul_aggregation_r14_present, 1)); HANDLE_CODE(bref.unpack(lwip_dl_aggregation_r14_present, 1)); HANDLE_CODE(bref.unpack(lwa_wlan_ac_r14_present, 1)); - if (rlc_cfg_v1430_present) { - rlc_cfg_v1430 = make_copy_ptr(rlc_cfg_v1430_c()); + if (rlc_cfg_v1430.is_present()) { HANDLE_CODE(rlc_cfg_v1430->unpack(bref)); } if (lwip_ul_aggregation_r14_present) { @@ -34347,26 +34029,29 @@ SRSASN_CODE drb_to_add_mod_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rlc_cfg_v1510_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1510_present, 1)); - if (rlc_cfg_v1510_present) { - rlc_cfg_v1510 = make_copy_ptr(rlc_cfg_v1510_s()); + rlc_cfg_v1510.set_present(rlc_cfg_v1510_present); + if (rlc_cfg_v1510.is_present()) { HANDLE_CODE(rlc_cfg_v1510->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rlc_cfg_v1530_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1530_present, 1)); + rlc_cfg_v1530.set_present(rlc_cfg_v1530_present); + bool rlc_bearer_cfg_dupl_r15_present; HANDLE_CODE(bref.unpack(rlc_bearer_cfg_dupl_r15_present, 1)); + rlc_bearer_cfg_dupl_r15.set_present(rlc_bearer_cfg_dupl_r15_present); HANDLE_CODE(bref.unpack(lc_ch_id_r15_present, 1)); - if (rlc_cfg_v1530_present) { - rlc_cfg_v1530 = make_copy_ptr(rlc_cfg_v1530_c()); + if (rlc_cfg_v1530.is_present()) { HANDLE_CODE(rlc_cfg_v1530->unpack(bref)); } - if (rlc_bearer_cfg_dupl_r15_present) { - rlc_bearer_cfg_dupl_r15 = make_copy_ptr(rlc_bearer_cfg_r15_c()); + if (rlc_bearer_cfg_dupl_r15.is_present()) { HANDLE_CODE(rlc_bearer_cfg_dupl_r15->unpack(bref)); } if (lc_ch_id_r15_present) { @@ -34402,13 +34087,11 @@ void drb_to_add_mod_s::to_json(json_writer& j) const if (drb_type_change_r12_present) { j.write_str("drb-TypeChange-r12", "toMCG"); } - rrc_asn1_warn_assert(rlc_cfg_v1250_present != (rlc_cfg_v1250.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1250_present) { + if (rlc_cfg_v1250.is_present()) { j.write_fieldname("rlc-Config-v1250"); rlc_cfg_v1250->to_json(j); } - rrc_asn1_warn_assert(rlc_cfg_v1310_present != (rlc_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1310_present) { + if (rlc_cfg_v1310.is_present()) { j.write_fieldname("rlc-Config-v1310"); rlc_cfg_v1310->to_json(j); } @@ -34418,8 +34101,7 @@ void drb_to_add_mod_s::to_json(json_writer& j) const if (drb_type_lwip_r13_present) { j.write_str("drb-TypeLWIP-r13", drb_type_lwip_r13.to_string()); } - rrc_asn1_warn_assert(rlc_cfg_v1430_present != (rlc_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1430_present) { + if (rlc_cfg_v1430.is_present()) { j.write_fieldname("rlc-Config-v1430"); rlc_cfg_v1430->to_json(j); } @@ -34432,19 +34114,15 @@ void drb_to_add_mod_s::to_json(json_writer& j) const if (lwa_wlan_ac_r14_present) { j.write_str("lwa-WLAN-AC-r14", lwa_wlan_ac_r14.to_string()); } - rrc_asn1_warn_assert(rlc_cfg_v1510_present != (rlc_cfg_v1510.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1510_present) { + if (rlc_cfg_v1510.is_present()) { j.write_fieldname("rlc-Config-v1510"); rlc_cfg_v1510->to_json(j); } - rrc_asn1_warn_assert(rlc_cfg_v1530_present != (rlc_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1530_present) { + if (rlc_cfg_v1530.is_present()) { j.write_fieldname("rlc-Config-v1530"); rlc_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert( - rlc_bearer_cfg_dupl_r15_present != (rlc_bearer_cfg_dupl_r15.get() != NULL), __FILE__, __LINE__); - if (rlc_bearer_cfg_dupl_r15_present) { + if (rlc_bearer_cfg_dupl_r15.is_present()) { j.write_fieldname("rlc-BearerConfigDupl-r15"); rlc_bearer_cfg_dupl_r15->to_json(j); } @@ -38633,16 +38311,15 @@ SRSASN_CODE sps_cfg_dl_c::setup_s_::pack(bit_ref& bref) const HANDLE_CODE(pack_dyn_seq_of(bref, n1_pucch_an_persistent_list, 1, 4, UnalignedIntegerPacker(0, 2047))); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(two_ant_port_activ_r10_present != (two_ant_port_activ_r10.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= two_ant_port_activ_r10_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= two_ant_port_activ_r10.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(two_ant_port_activ_r10_present, 1)); - if (two_ant_port_activ_r10_present) { + HANDLE_CODE(bref.pack(two_ant_port_activ_r10.is_present(), 1)); + if (two_ant_port_activ_r10.is_present()) { HANDLE_CODE(two_ant_port_activ_r10->pack(bref)); } } @@ -38657,15 +38334,16 @@ SRSASN_CODE sps_cfg_dl_c::setup_s_::unpack(bit_ref& bref) HANDLE_CODE(unpack_dyn_seq_of(n1_pucch_an_persistent_list, bref, 1, 4, UnalignedIntegerPacker(0, 2047))); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool two_ant_port_activ_r10_present; HANDLE_CODE(bref.unpack(two_ant_port_activ_r10_present, 1)); - if (two_ant_port_activ_r10_present) { - two_ant_port_activ_r10 = make_copy_ptr(two_ant_port_activ_r10_c_()); + two_ant_port_activ_r10.set_present(two_ant_port_activ_r10_present); + if (two_ant_port_activ_r10.is_present()) { HANDLE_CODE(two_ant_port_activ_r10->unpack(bref)); } } @@ -38683,8 +38361,7 @@ void sps_cfg_dl_c::setup_s_::to_json(json_writer& j) const } j.end_array(); if (ext) { - rrc_asn1_warn_assert(two_ant_port_activ_r10_present != (two_ant_port_activ_r10.get() != NULL), __FILE__, __LINE__); - if (two_ant_port_activ_r10_present) { + if (two_ant_port_activ_r10.is_present()) { j.write_fieldname("twoAntennaPortActivated-r10"); two_ant_port_activ_r10->to_json(j); } @@ -38768,27 +38445,24 @@ SRSASN_CODE srb_to_add_mod_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= pdcp_ver_change_r15_present; - rrc_asn1_warn_assert(rlc_cfg_v1530_present != (rlc_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rlc_cfg_v1530_present; - rrc_asn1_warn_assert( - rlc_bearer_cfg_dupl_r15_present != (rlc_bearer_cfg_dupl_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rlc_bearer_cfg_dupl_r15_present; + group_flags[0] |= rlc_cfg_v1530.is_present(); + group_flags[0] |= rlc_bearer_cfg_dupl_r15.is_present(); group_flags[0] |= srb_id_v1530_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(pdcp_ver_change_r15_present, 1)); - HANDLE_CODE(bref.pack(rlc_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(rlc_bearer_cfg_dupl_r15_present, 1)); + HANDLE_CODE(bref.pack(rlc_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(rlc_bearer_cfg_dupl_r15.is_present(), 1)); HANDLE_CODE(bref.pack(srb_id_v1530_present, 1)); - if (rlc_cfg_v1530_present) { + if (rlc_cfg_v1530.is_present()) { HANDLE_CODE(rlc_cfg_v1530->pack(bref)); } - if (rlc_bearer_cfg_dupl_r15_present) { + if (rlc_bearer_cfg_dupl_r15.is_present()) { HANDLE_CODE(rlc_bearer_cfg_dupl_r15->pack(bref)); } if (srb_id_v1530_present) { @@ -38813,22 +38487,24 @@ SRSASN_CODE srb_to_add_mod_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(pdcp_ver_change_r15_present, 1)); + bool rlc_cfg_v1530_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1530_present, 1)); + rlc_cfg_v1530.set_present(rlc_cfg_v1530_present); + bool rlc_bearer_cfg_dupl_r15_present; HANDLE_CODE(bref.unpack(rlc_bearer_cfg_dupl_r15_present, 1)); + rlc_bearer_cfg_dupl_r15.set_present(rlc_bearer_cfg_dupl_r15_present); HANDLE_CODE(bref.unpack(srb_id_v1530_present, 1)); - if (rlc_cfg_v1530_present) { - rlc_cfg_v1530 = make_copy_ptr(rlc_cfg_v1530_c()); + if (rlc_cfg_v1530.is_present()) { HANDLE_CODE(rlc_cfg_v1530->unpack(bref)); } - if (rlc_bearer_cfg_dupl_r15_present) { - rlc_bearer_cfg_dupl_r15 = make_copy_ptr(rlc_bearer_cfg_r15_c()); + if (rlc_bearer_cfg_dupl_r15.is_present()) { HANDLE_CODE(rlc_bearer_cfg_dupl_r15->unpack(bref)); } if (srb_id_v1530_present) { @@ -38854,14 +38530,11 @@ void srb_to_add_mod_s::to_json(json_writer& j) const if (pdcp_ver_change_r15_present) { j.write_str("pdcp-verChange-r15", "true"); } - rrc_asn1_warn_assert(rlc_cfg_v1530_present != (rlc_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1530_present) { + if (rlc_cfg_v1530.is_present()) { j.write_fieldname("rlc-Config-v1530"); rlc_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert( - rlc_bearer_cfg_dupl_r15_present != (rlc_bearer_cfg_dupl_r15.get() != NULL), __FILE__, __LINE__); - if (rlc_bearer_cfg_dupl_r15_present) { + if (rlc_bearer_cfg_dupl_r15.is_present()) { j.write_fieldname("rlc-BearerConfigDupl-r15"); rlc_bearer_cfg_dupl_r15->to_json(j); } @@ -40191,48 +39864,29 @@ SRSASN_CODE mac_main_cfg_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(9); + ext_groups_packer_guard group_flags; group_flags[0] |= sr_prohibit_timer_r9_present; - rrc_asn1_warn_assert(mac_main_cfg_v1020_present != (mac_main_cfg_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= mac_main_cfg_v1020_present; - rrc_asn1_warn_assert( - stag_to_release_list_r11_present != (stag_to_release_list_r11.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= stag_to_release_list_r11_present; - rrc_asn1_warn_assert( - stag_to_add_mod_list_r11_present != (stag_to_add_mod_list_r11.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= stag_to_add_mod_list_r11_present; - rrc_asn1_warn_assert(drx_cfg_v1130_present != (drx_cfg_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= drx_cfg_v1130_present; + group_flags[1] |= mac_main_cfg_v1020.is_present(); + group_flags[2] |= stag_to_release_list_r11.is_present(); + group_flags[2] |= stag_to_add_mod_list_r11.is_present(); + group_flags[2] |= drx_cfg_v1130.is_present(); group_flags[3] |= e_harq_pattern_r12_present; - rrc_asn1_warn_assert(dual_connect_phr_present != (dual_connect_phr.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= dual_connect_phr_present; - rrc_asn1_warn_assert(lc_ch_sr_cfg_r12_present != (lc_ch_sr_cfg_r12.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= lc_ch_sr_cfg_r12_present; - rrc_asn1_warn_assert(drx_cfg_v1310_present != (drx_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= drx_cfg_v1310_present; + group_flags[3] |= dual_connect_phr.is_present(); + group_flags[3] |= lc_ch_sr_cfg_r12.is_present(); + group_flags[4] |= drx_cfg_v1310.is_present(); group_flags[4] |= extended_phr2_r13_present; - rrc_asn1_warn_assert(e_drx_cfg_cycle_start_offset_r13_present != (e_drx_cfg_cycle_start_offset_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[4] |= e_drx_cfg_cycle_start_offset_r13_present; - rrc_asn1_warn_assert(drx_cfg_r13_present != (drx_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= drx_cfg_r13_present; - rrc_asn1_warn_assert(skip_ul_tx_r14_present != (skip_ul_tx_r14.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= skip_ul_tx_r14_present; - rrc_asn1_warn_assert( - data_inactivity_timer_cfg_r14_present != (data_inactivity_timer_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= data_inactivity_timer_cfg_r14_present; + group_flags[4] |= e_drx_cfg_cycle_start_offset_r13.is_present(); + group_flags[5] |= drx_cfg_r13.is_present(); + group_flags[6] |= skip_ul_tx_r14.is_present(); + group_flags[6] |= data_inactivity_timer_cfg_r14.is_present(); group_flags[7] |= rai_activation_r14_present; - rrc_asn1_warn_assert(short_tti_and_spt_r15_present != (short_tti_and_spt_r15.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= short_tti_and_spt_r15_present; + group_flags[8] |= short_tti_and_spt_r15.is_present(); group_flags[8] |= mpdcch_ul_harq_ack_feedback_cfg_r15_present; - rrc_asn1_warn_assert( - dormant_state_timers_r15_present != (dormant_state_timers_r15.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= dormant_state_timers_r15_present; + group_flags[8] |= dormant_state_timers_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sr_prohibit_timer_r9_present, 1)); if (sr_prohibit_timer_r9_present) { @@ -40240,10 +39894,10 @@ SRSASN_CODE mac_main_cfg_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mac_main_cfg_v1020_present, 1)); - if (mac_main_cfg_v1020_present) { + HANDLE_CODE(bref.pack(mac_main_cfg_v1020.is_present(), 1)); + if (mac_main_cfg_v1020.is_present()) { HANDLE_CODE(bref.pack(mac_main_cfg_v1020->s_cell_deactivation_timer_r10_present, 1)); HANDLE_CODE(bref.pack(mac_main_cfg_v1020->extended_bsr_sizes_r10_present, 1)); HANDLE_CODE(bref.pack(mac_main_cfg_v1020->extended_phr_r10_present, 1)); @@ -40253,91 +39907,91 @@ SRSASN_CODE mac_main_cfg_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(stag_to_release_list_r11_present, 1)); - HANDLE_CODE(bref.pack(stag_to_add_mod_list_r11_present, 1)); - HANDLE_CODE(bref.pack(drx_cfg_v1130_present, 1)); - if (stag_to_release_list_r11_present) { + HANDLE_CODE(bref.pack(stag_to_release_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(stag_to_add_mod_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(drx_cfg_v1130.is_present(), 1)); + if (stag_to_release_list_r11.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *stag_to_release_list_r11, 1, 3, UnalignedIntegerPacker(1, 3))); } - if (stag_to_add_mod_list_r11_present) { + if (stag_to_add_mod_list_r11.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *stag_to_add_mod_list_r11, 1, 3)); } - if (drx_cfg_v1130_present) { + if (drx_cfg_v1130.is_present()) { HANDLE_CODE(drx_cfg_v1130->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(e_harq_pattern_r12_present, 1)); - HANDLE_CODE(bref.pack(dual_connect_phr_present, 1)); - HANDLE_CODE(bref.pack(lc_ch_sr_cfg_r12_present, 1)); + HANDLE_CODE(bref.pack(dual_connect_phr.is_present(), 1)); + HANDLE_CODE(bref.pack(lc_ch_sr_cfg_r12.is_present(), 1)); if (e_harq_pattern_r12_present) { HANDLE_CODE(bref.pack(e_harq_pattern_r12, 1)); } - if (dual_connect_phr_present) { + if (dual_connect_phr.is_present()) { HANDLE_CODE(dual_connect_phr->pack(bref)); } - if (lc_ch_sr_cfg_r12_present) { + if (lc_ch_sr_cfg_r12.is_present()) { HANDLE_CODE(lc_ch_sr_cfg_r12->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(drx_cfg_v1310_present, 1)); + HANDLE_CODE(bref.pack(drx_cfg_v1310.is_present(), 1)); HANDLE_CODE(bref.pack(extended_phr2_r13_present, 1)); - HANDLE_CODE(bref.pack(e_drx_cfg_cycle_start_offset_r13_present, 1)); - if (drx_cfg_v1310_present) { + HANDLE_CODE(bref.pack(e_drx_cfg_cycle_start_offset_r13.is_present(), 1)); + if (drx_cfg_v1310.is_present()) { HANDLE_CODE(drx_cfg_v1310->pack(bref)); } if (extended_phr2_r13_present) { HANDLE_CODE(bref.pack(extended_phr2_r13, 1)); } - if (e_drx_cfg_cycle_start_offset_r13_present) { + if (e_drx_cfg_cycle_start_offset_r13.is_present()) { HANDLE_CODE(e_drx_cfg_cycle_start_offset_r13->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(drx_cfg_r13_present, 1)); - if (drx_cfg_r13_present) { + HANDLE_CODE(bref.pack(drx_cfg_r13.is_present(), 1)); + if (drx_cfg_r13.is_present()) { HANDLE_CODE(drx_cfg_r13->pack(bref)); } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(skip_ul_tx_r14_present, 1)); - HANDLE_CODE(bref.pack(data_inactivity_timer_cfg_r14_present, 1)); - if (skip_ul_tx_r14_present) { + HANDLE_CODE(bref.pack(skip_ul_tx_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(data_inactivity_timer_cfg_r14.is_present(), 1)); + if (skip_ul_tx_r14.is_present()) { HANDLE_CODE(skip_ul_tx_r14->pack(bref)); } - if (data_inactivity_timer_cfg_r14_present) { + if (data_inactivity_timer_cfg_r14.is_present()) { HANDLE_CODE(data_inactivity_timer_cfg_r14->pack(bref)); } } if (group_flags[7]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(rai_activation_r14_present, 1)); } if (group_flags[8]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(short_tti_and_spt_r15_present, 1)); + HANDLE_CODE(bref.pack(short_tti_and_spt_r15.is_present(), 1)); HANDLE_CODE(bref.pack(mpdcch_ul_harq_ack_feedback_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(dormant_state_timers_r15_present, 1)); - if (short_tti_and_spt_r15_present) { + HANDLE_CODE(bref.pack(dormant_state_timers_r15.is_present(), 1)); + if (short_tti_and_spt_r15.is_present()) { HANDLE_CODE(short_tti_and_spt_r15->pack(bref)); } if (mpdcch_ul_harq_ack_feedback_cfg_r15_present) { HANDLE_CODE(bref.pack(mpdcch_ul_harq_ack_feedback_cfg_r15, 1)); } - if (dormant_state_timers_r15_present) { + if (dormant_state_timers_r15.is_present()) { HANDLE_CODE(dormant_state_timers_r15->pack(bref)); } } @@ -40372,11 +40026,11 @@ SRSASN_CODE mac_main_cfg_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(9); + ext_groups_unpacker_guard group_flags(9); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sr_prohibit_timer_r9_present, 1)); if (sr_prohibit_timer_r9_present) { @@ -40384,11 +40038,12 @@ SRSASN_CODE mac_main_cfg_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mac_main_cfg_v1020_present; HANDLE_CODE(bref.unpack(mac_main_cfg_v1020_present, 1)); - if (mac_main_cfg_v1020_present) { - mac_main_cfg_v1020 = make_copy_ptr(mac_main_cfg_v1020_s_()); + mac_main_cfg_v1020.set_present(mac_main_cfg_v1020_present); + if (mac_main_cfg_v1020.is_present()) { HANDLE_CODE(bref.unpack(mac_main_cfg_v1020->s_cell_deactivation_timer_r10_present, 1)); HANDLE_CODE(bref.unpack(mac_main_cfg_v1020->extended_bsr_sizes_r10_present, 1)); HANDLE_CODE(bref.unpack(mac_main_cfg_v1020->extended_phr_r10_present, 1)); @@ -40398,103 +40053,115 @@ SRSASN_CODE mac_main_cfg_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool stag_to_release_list_r11_present; HANDLE_CODE(bref.unpack(stag_to_release_list_r11_present, 1)); + stag_to_release_list_r11.set_present(stag_to_release_list_r11_present); + bool stag_to_add_mod_list_r11_present; HANDLE_CODE(bref.unpack(stag_to_add_mod_list_r11_present, 1)); + stag_to_add_mod_list_r11.set_present(stag_to_add_mod_list_r11_present); + bool drx_cfg_v1130_present; HANDLE_CODE(bref.unpack(drx_cfg_v1130_present, 1)); - if (stag_to_release_list_r11_present) { - stag_to_release_list_r11 = make_copy_ptr(stag_to_release_list_r11_l()); + drx_cfg_v1130.set_present(drx_cfg_v1130_present); + if (stag_to_release_list_r11.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*stag_to_release_list_r11, bref, 1, 3, UnalignedIntegerPacker(1, 3))); } - if (stag_to_add_mod_list_r11_present) { - stag_to_add_mod_list_r11 = make_copy_ptr(stag_to_add_mod_list_r11_l()); + if (stag_to_add_mod_list_r11.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*stag_to_add_mod_list_r11, bref, 1, 3)); } - if (drx_cfg_v1130_present) { - drx_cfg_v1130 = make_copy_ptr(drx_cfg_v1130_s()); + if (drx_cfg_v1130.is_present()) { HANDLE_CODE(drx_cfg_v1130->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(e_harq_pattern_r12_present, 1)); + bool dual_connect_phr_present; HANDLE_CODE(bref.unpack(dual_connect_phr_present, 1)); + dual_connect_phr.set_present(dual_connect_phr_present); + bool lc_ch_sr_cfg_r12_present; HANDLE_CODE(bref.unpack(lc_ch_sr_cfg_r12_present, 1)); + lc_ch_sr_cfg_r12.set_present(lc_ch_sr_cfg_r12_present); if (e_harq_pattern_r12_present) { HANDLE_CODE(bref.unpack(e_harq_pattern_r12, 1)); } - if (dual_connect_phr_present) { - dual_connect_phr = make_copy_ptr(dual_connect_phr_c_()); + if (dual_connect_phr.is_present()) { HANDLE_CODE(dual_connect_phr->unpack(bref)); } - if (lc_ch_sr_cfg_r12_present) { - lc_ch_sr_cfg_r12 = make_copy_ptr(lc_ch_sr_cfg_r12_c_()); + if (lc_ch_sr_cfg_r12.is_present()) { HANDLE_CODE(lc_ch_sr_cfg_r12->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool drx_cfg_v1310_present; HANDLE_CODE(bref.unpack(drx_cfg_v1310_present, 1)); + drx_cfg_v1310.set_present(drx_cfg_v1310_present); HANDLE_CODE(bref.unpack(extended_phr2_r13_present, 1)); + bool e_drx_cfg_cycle_start_offset_r13_present; HANDLE_CODE(bref.unpack(e_drx_cfg_cycle_start_offset_r13_present, 1)); - if (drx_cfg_v1310_present) { - drx_cfg_v1310 = make_copy_ptr(drx_cfg_v1310_s()); + e_drx_cfg_cycle_start_offset_r13.set_present(e_drx_cfg_cycle_start_offset_r13_present); + if (drx_cfg_v1310.is_present()) { HANDLE_CODE(drx_cfg_v1310->unpack(bref)); } if (extended_phr2_r13_present) { HANDLE_CODE(bref.unpack(extended_phr2_r13, 1)); } - if (e_drx_cfg_cycle_start_offset_r13_present) { - e_drx_cfg_cycle_start_offset_r13 = make_copy_ptr(e_drx_cfg_cycle_start_offset_r13_c_()); + if (e_drx_cfg_cycle_start_offset_r13.is_present()) { HANDLE_CODE(e_drx_cfg_cycle_start_offset_r13->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool drx_cfg_r13_present; HANDLE_CODE(bref.unpack(drx_cfg_r13_present, 1)); - if (drx_cfg_r13_present) { - drx_cfg_r13 = make_copy_ptr(drx_cfg_r13_c_()); + drx_cfg_r13.set_present(drx_cfg_r13_present); + if (drx_cfg_r13.is_present()) { HANDLE_CODE(drx_cfg_r13->unpack(bref)); } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool skip_ul_tx_r14_present; HANDLE_CODE(bref.unpack(skip_ul_tx_r14_present, 1)); + skip_ul_tx_r14.set_present(skip_ul_tx_r14_present); + bool data_inactivity_timer_cfg_r14_present; HANDLE_CODE(bref.unpack(data_inactivity_timer_cfg_r14_present, 1)); - if (skip_ul_tx_r14_present) { - skip_ul_tx_r14 = make_copy_ptr(skip_ul_tx_r14_c_()); + data_inactivity_timer_cfg_r14.set_present(data_inactivity_timer_cfg_r14_present); + if (skip_ul_tx_r14.is_present()) { HANDLE_CODE(skip_ul_tx_r14->unpack(bref)); } - if (data_inactivity_timer_cfg_r14_present) { - data_inactivity_timer_cfg_r14 = make_copy_ptr(data_inactivity_timer_cfg_r14_c_()); + if (data_inactivity_timer_cfg_r14.is_present()) { HANDLE_CODE(data_inactivity_timer_cfg_r14->unpack(bref)); } } if (group_flags[7]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(rai_activation_r14_present, 1)); } if (group_flags[8]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool short_tti_and_spt_r15_present; HANDLE_CODE(bref.unpack(short_tti_and_spt_r15_present, 1)); + short_tti_and_spt_r15.set_present(short_tti_and_spt_r15_present); HANDLE_CODE(bref.unpack(mpdcch_ul_harq_ack_feedback_cfg_r15_present, 1)); + bool dormant_state_timers_r15_present; HANDLE_CODE(bref.unpack(dormant_state_timers_r15_present, 1)); - if (short_tti_and_spt_r15_present) { - short_tti_and_spt_r15 = make_copy_ptr(short_tti_and_spt_r15_c_()); + dormant_state_timers_r15.set_present(dormant_state_timers_r15_present); + if (short_tti_and_spt_r15.is_present()) { HANDLE_CODE(short_tti_and_spt_r15->unpack(bref)); } if (mpdcch_ul_harq_ack_feedback_cfg_r15_present) { HANDLE_CODE(bref.unpack(mpdcch_ul_harq_ack_feedback_cfg_r15, 1)); } - if (dormant_state_timers_r15_present) { - dormant_state_timers_r15 = make_copy_ptr(dormant_state_timers_r15_c_()); + if (dormant_state_timers_r15.is_present()) { HANDLE_CODE(dormant_state_timers_r15->unpack(bref)); } } @@ -40530,8 +40197,7 @@ void mac_main_cfg_s::to_json(json_writer& j) const if (sr_prohibit_timer_r9_present) { j.write_int("sr-ProhibitTimer-r9", sr_prohibit_timer_r9); } - rrc_asn1_warn_assert(mac_main_cfg_v1020_present != (mac_main_cfg_v1020.get() != NULL), __FILE__, __LINE__); - if (mac_main_cfg_v1020_present) { + if (mac_main_cfg_v1020.is_present()) { j.write_fieldname("mac-MainConfig-v1020"); j.start_obj(); if (mac_main_cfg_v1020->s_cell_deactivation_timer_r10_present) { @@ -40545,87 +40211,69 @@ void mac_main_cfg_s::to_json(json_writer& j) const } j.end_obj(); } - rrc_asn1_warn_assert( - stag_to_release_list_r11_present != (stag_to_release_list_r11.get() != NULL), __FILE__, __LINE__); - if (stag_to_release_list_r11_present) { + if (stag_to_release_list_r11.is_present()) { j.start_array("stag-ToReleaseList-r11"); for (uint32_t i1 = 0; i1 < stag_to_release_list_r11->size(); ++i1) { j.write_int(((*stag_to_release_list_r11)[i1])); } j.end_array(); } - rrc_asn1_warn_assert( - stag_to_add_mod_list_r11_present != (stag_to_add_mod_list_r11.get() != NULL), __FILE__, __LINE__); - if (stag_to_add_mod_list_r11_present) { + if (stag_to_add_mod_list_r11.is_present()) { j.start_array("stag-ToAddModList-r11"); for (uint32_t i1 = 0; i1 < stag_to_add_mod_list_r11->size(); ++i1) { ((*stag_to_add_mod_list_r11)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(drx_cfg_v1130_present != (drx_cfg_v1130.get() != NULL), __FILE__, __LINE__); - if (drx_cfg_v1130_present) { + if (drx_cfg_v1130.is_present()) { j.write_fieldname("drx-Config-v1130"); drx_cfg_v1130->to_json(j); } if (e_harq_pattern_r12_present) { j.write_bool("e-HARQ-Pattern-r12", e_harq_pattern_r12); } - rrc_asn1_warn_assert(dual_connect_phr_present != (dual_connect_phr.get() != NULL), __FILE__, __LINE__); - if (dual_connect_phr_present) { + if (dual_connect_phr.is_present()) { j.write_fieldname("dualConnectivityPHR"); dual_connect_phr->to_json(j); } - rrc_asn1_warn_assert(lc_ch_sr_cfg_r12_present != (lc_ch_sr_cfg_r12.get() != NULL), __FILE__, __LINE__); - if (lc_ch_sr_cfg_r12_present) { + if (lc_ch_sr_cfg_r12.is_present()) { j.write_fieldname("logicalChannelSR-Config-r12"); lc_ch_sr_cfg_r12->to_json(j); } - rrc_asn1_warn_assert(drx_cfg_v1310_present != (drx_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (drx_cfg_v1310_present) { + if (drx_cfg_v1310.is_present()) { j.write_fieldname("drx-Config-v1310"); drx_cfg_v1310->to_json(j); } if (extended_phr2_r13_present) { j.write_bool("extendedPHR2-r13", extended_phr2_r13); } - rrc_asn1_warn_assert(e_drx_cfg_cycle_start_offset_r13_present != (e_drx_cfg_cycle_start_offset_r13.get() != NULL), - __FILE__, - __LINE__); - if (e_drx_cfg_cycle_start_offset_r13_present) { + if (e_drx_cfg_cycle_start_offset_r13.is_present()) { j.write_fieldname("eDRX-Config-CycleStartOffset-r13"); e_drx_cfg_cycle_start_offset_r13->to_json(j); } - rrc_asn1_warn_assert(drx_cfg_r13_present != (drx_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (drx_cfg_r13_present) { + if (drx_cfg_r13.is_present()) { j.write_fieldname("drx-Config-r13"); drx_cfg_r13->to_json(j); } - rrc_asn1_warn_assert(skip_ul_tx_r14_present != (skip_ul_tx_r14.get() != NULL), __FILE__, __LINE__); - if (skip_ul_tx_r14_present) { + if (skip_ul_tx_r14.is_present()) { j.write_fieldname("skipUplinkTx-r14"); skip_ul_tx_r14->to_json(j); } - rrc_asn1_warn_assert( - data_inactivity_timer_cfg_r14_present != (data_inactivity_timer_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (data_inactivity_timer_cfg_r14_present) { + if (data_inactivity_timer_cfg_r14.is_present()) { j.write_fieldname("dataInactivityTimerConfig-r14"); data_inactivity_timer_cfg_r14->to_json(j); } if (rai_activation_r14_present) { j.write_str("rai-Activation-r14", "true"); } - rrc_asn1_warn_assert(short_tti_and_spt_r15_present != (short_tti_and_spt_r15.get() != NULL), __FILE__, __LINE__); - if (short_tti_and_spt_r15_present) { + if (short_tti_and_spt_r15.is_present()) { j.write_fieldname("shortTTI-AndSPT-r15"); short_tti_and_spt_r15->to_json(j); } if (mpdcch_ul_harq_ack_feedback_cfg_r15_present) { j.write_bool("mpdcch-UL-HARQ-ACK-FeedbackConfig-r15", mpdcch_ul_harq_ack_feedback_cfg_r15); } - rrc_asn1_warn_assert( - dormant_state_timers_r15_present != (dormant_state_timers_r15.get() != NULL), __FILE__, __LINE__); - if (dormant_state_timers_r15_present) { + if (dormant_state_timers_r15.is_present()) { j.write_fieldname("dormantStateTimers-r15"); dormant_state_timers_r15->to_json(j); } @@ -41648,475 +41296,364 @@ SRSASN_CODE phys_cfg_ded_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(11); - rrc_asn1_warn_assert(cqi_report_cfg_v920_present != (cqi_report_cfg_v920.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cqi_report_cfg_v920_present; - rrc_asn1_warn_assert(ant_info_v920_present != (ant_info_v920.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ant_info_v920_present; - rrc_asn1_warn_assert(ant_info_r10_present != (ant_info_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ant_info_r10_present; - rrc_asn1_warn_assert(ant_info_ul_r10_present != (ant_info_ul_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ant_info_ul_r10_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= cqi_report_cfg_v920.is_present(); + group_flags[0] |= ant_info_v920.is_present(); + group_flags[1] |= ant_info_r10.is_present(); + group_flags[1] |= ant_info_ul_r10.is_present(); group_flags[1] |= cif_presence_r10_present; - rrc_asn1_warn_assert(cqi_report_cfg_r10_present != (cqi_report_cfg_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= cqi_report_cfg_r10_present; - rrc_asn1_warn_assert(csi_rs_cfg_r10_present != (csi_rs_cfg_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= csi_rs_cfg_r10_present; - rrc_asn1_warn_assert(pucch_cfg_ded_v1020_present != (pucch_cfg_ded_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= pucch_cfg_ded_v1020_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1020_present != (pusch_cfg_ded_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= pusch_cfg_ded_v1020_present; - rrc_asn1_warn_assert( - sched_request_cfg_v1020_present != (sched_request_cfg_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= sched_request_cfg_v1020_present; - rrc_asn1_warn_assert(srs_ul_cfg_ded_v1020_present != (srs_ul_cfg_ded_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= srs_ul_cfg_ded_v1020_present; - rrc_asn1_warn_assert( - srs_ul_cfg_ded_aperiodic_r10_present != (srs_ul_cfg_ded_aperiodic_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= srs_ul_cfg_ded_aperiodic_r10_present; - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1020_present != (ul_pwr_ctrl_ded_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ul_pwr_ctrl_ded_v1020_present; - rrc_asn1_warn_assert( - add_spec_emission_ca_r10_present != (add_spec_emission_ca_r10.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= add_spec_emission_ca_r10_present; - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_r11_present != - (csi_rs_cfg_nzp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= csi_rs_cfg_nzp_to_release_list_r11_present; - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_r11_present != - (csi_rs_cfg_nzp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= csi_rs_cfg_nzp_to_add_mod_list_r11_present; - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_release_list_r11_present != (csi_rs_cfg_zp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= csi_rs_cfg_zp_to_release_list_r11_present; - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_add_mod_list_r11_present != (csi_rs_cfg_zp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= csi_rs_cfg_zp_to_add_mod_list_r11_present; - rrc_asn1_warn_assert(epdcch_cfg_r11_present != (epdcch_cfg_r11.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= epdcch_cfg_r11_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1130_present != (pdsch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pdsch_cfg_ded_v1130_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1130_present != (cqi_report_cfg_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= cqi_report_cfg_v1130_present; - rrc_asn1_warn_assert(pucch_cfg_ded_v1130_present != (pucch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pucch_cfg_ded_v1130_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1130_present != (pusch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pusch_cfg_ded_v1130_present; - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1130_present != (ul_pwr_ctrl_ded_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= ul_pwr_ctrl_ded_v1130_present; - rrc_asn1_warn_assert(ant_info_v1250_present != (ant_info_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= ant_info_v1250_present; - rrc_asn1_warn_assert(eimta_main_cfg_r12_present != (eimta_main_cfg_r12.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= eimta_main_cfg_r12_present; - rrc_asn1_warn_assert( - eimta_main_cfg_pcell_r12_present != (eimta_main_cfg_pcell_r12.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= eimta_main_cfg_pcell_r12_present; - rrc_asn1_warn_assert(pucch_cfg_ded_v1250_present != (pucch_cfg_ded_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= pucch_cfg_ded_v1250_present; - rrc_asn1_warn_assert( - cqi_report_cfg_pcell_v1250_present != (cqi_report_cfg_pcell_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= cqi_report_cfg_pcell_v1250_present; - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1250_present != (ul_pwr_ctrl_ded_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= ul_pwr_ctrl_ded_v1250_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1250_present != (pusch_cfg_ded_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= pusch_cfg_ded_v1250_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1250_present != (csi_rs_cfg_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= csi_rs_cfg_v1250_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1280_present != (pdsch_cfg_ded_v1280.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= pdsch_cfg_ded_v1280_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1310_present != (pdsch_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= pdsch_cfg_ded_v1310_present; - rrc_asn1_warn_assert(pucch_cfg_ded_r13_present != (pucch_cfg_ded_r13.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= pucch_cfg_ded_r13_present; - rrc_asn1_warn_assert(pusch_cfg_ded_r13_present != (pusch_cfg_ded_r13.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= pusch_cfg_ded_r13_present; - rrc_asn1_warn_assert( - pdcch_candidate_reductions_r13_present != (pdcch_candidate_reductions_r13.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= pdcch_candidate_reductions_r13_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1310_present != (cqi_report_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= cqi_report_cfg_v1310_present; - rrc_asn1_warn_assert(srs_ul_cfg_ded_v1310_present != (srs_ul_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= srs_ul_cfg_ded_v1310_present; - rrc_asn1_warn_assert( - srs_ul_cfg_ded_up_pts_ext_r13_present != (srs_ul_cfg_ded_up_pts_ext_r13.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= srs_ul_cfg_ded_up_pts_ext_r13_present; - rrc_asn1_warn_assert( - srs_ul_cfg_ded_aperiodic_v1310_present != (srs_ul_cfg_ded_aperiodic_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= srs_ul_cfg_ded_aperiodic_v1310_present; - rrc_asn1_warn_assert(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present != - (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[6] |= srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1310_present != (csi_rs_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= csi_rs_cfg_v1310_present; - rrc_asn1_warn_assert(ce_mode_r13_present != (ce_mode_r13.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= ce_mode_r13_present; - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present != - (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[6] |= csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present; - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_ext_r13_present != - (csi_rs_cfg_nzp_to_release_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[6] |= csi_rs_cfg_nzp_to_release_list_ext_r13_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1320_present != (cqi_report_cfg_v1320.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= cqi_report_cfg_v1320_present; - rrc_asn1_warn_assert( - type_a_srs_tpc_pdcch_group_r14_present != (type_a_srs_tpc_pdcch_group_r14.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= type_a_srs_tpc_pdcch_group_r14_present; - rrc_asn1_warn_assert(must_cfg_r14_present != (must_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= must_cfg_r14_present; - rrc_asn1_warn_assert(pusch_enhance_cfg_r14_present != (pusch_enhance_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= pusch_enhance_cfg_r14_present; + group_flags[1] |= cqi_report_cfg_r10.is_present(); + group_flags[1] |= csi_rs_cfg_r10.is_present(); + group_flags[1] |= pucch_cfg_ded_v1020.is_present(); + group_flags[1] |= pusch_cfg_ded_v1020.is_present(); + group_flags[1] |= sched_request_cfg_v1020.is_present(); + group_flags[1] |= srs_ul_cfg_ded_v1020.is_present(); + group_flags[1] |= srs_ul_cfg_ded_aperiodic_r10.is_present(); + group_flags[1] |= ul_pwr_ctrl_ded_v1020.is_present(); + group_flags[2] |= add_spec_emission_ca_r10.is_present(); + group_flags[3] |= csi_rs_cfg_nzp_to_release_list_r11.is_present(); + group_flags[3] |= csi_rs_cfg_nzp_to_add_mod_list_r11.is_present(); + group_flags[3] |= csi_rs_cfg_zp_to_release_list_r11.is_present(); + group_flags[3] |= csi_rs_cfg_zp_to_add_mod_list_r11.is_present(); + group_flags[3] |= epdcch_cfg_r11.is_present(); + group_flags[3] |= pdsch_cfg_ded_v1130.is_present(); + group_flags[3] |= cqi_report_cfg_v1130.is_present(); + group_flags[3] |= pucch_cfg_ded_v1130.is_present(); + group_flags[3] |= pusch_cfg_ded_v1130.is_present(); + group_flags[3] |= ul_pwr_ctrl_ded_v1130.is_present(); + group_flags[4] |= ant_info_v1250.is_present(); + group_flags[4] |= eimta_main_cfg_r12.is_present(); + group_flags[4] |= eimta_main_cfg_pcell_r12.is_present(); + group_flags[4] |= pucch_cfg_ded_v1250.is_present(); + group_flags[4] |= cqi_report_cfg_pcell_v1250.is_present(); + group_flags[4] |= ul_pwr_ctrl_ded_v1250.is_present(); + group_flags[4] |= pusch_cfg_ded_v1250.is_present(); + group_flags[4] |= csi_rs_cfg_v1250.is_present(); + group_flags[5] |= pdsch_cfg_ded_v1280.is_present(); + group_flags[6] |= pdsch_cfg_ded_v1310.is_present(); + group_flags[6] |= pucch_cfg_ded_r13.is_present(); + group_flags[6] |= pusch_cfg_ded_r13.is_present(); + group_flags[6] |= pdcch_candidate_reductions_r13.is_present(); + group_flags[6] |= cqi_report_cfg_v1310.is_present(); + group_flags[6] |= srs_ul_cfg_ded_v1310.is_present(); + group_flags[6] |= srs_ul_cfg_ded_up_pts_ext_r13.is_present(); + group_flags[6] |= srs_ul_cfg_ded_aperiodic_v1310.is_present(); + group_flags[6] |= srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present(); + group_flags[6] |= csi_rs_cfg_v1310.is_present(); + group_flags[6] |= ce_mode_r13.is_present(); + group_flags[6] |= csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present(); + group_flags[6] |= csi_rs_cfg_nzp_to_release_list_ext_r13.is_present(); + group_flags[7] |= cqi_report_cfg_v1320.is_present(); + group_flags[8] |= type_a_srs_tpc_pdcch_group_r14.is_present(); + group_flags[8] |= must_cfg_r14.is_present(); + group_flags[8] |= pusch_enhance_cfg_r14.is_present(); group_flags[8] |= ce_pdsch_pusch_enhancement_cfg_r14_present; - rrc_asn1_warn_assert(ant_info_v1430_present != (ant_info_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= ant_info_v1430_present; - rrc_asn1_warn_assert(pucch_cfg_ded_v1430_present != (pucch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= pucch_cfg_ded_v1430_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1430_present != (pdsch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= pdsch_cfg_ded_v1430_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1430_present != (pusch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= pusch_cfg_ded_v1430_present; - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_list_r14_present != (srs_ul_periodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[8] |= srs_ul_periodic_cfg_ded_list_r14_present; - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present != - (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[8] |= srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present; - rrc_asn1_warn_assert(srs_ul_aperiodic_cfg_ded_list_r14_present != (srs_ul_aperiodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[8] |= srs_ul_aperiodic_cfg_ded_list_r14_present; - rrc_asn1_warn_assert(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present != - (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[8] |= srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1430_present != (csi_rs_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= csi_rs_cfg_v1430_present; - rrc_asn1_warn_assert( - csi_rs_cfg_zp_ap_list_r14_present != (csi_rs_cfg_zp_ap_list_r14.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= csi_rs_cfg_zp_ap_list_r14_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1430_present != (cqi_report_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[8] |= cqi_report_cfg_v1430_present; + group_flags[8] |= ant_info_v1430.is_present(); + group_flags[8] |= pucch_cfg_ded_v1430.is_present(); + group_flags[8] |= pdsch_cfg_ded_v1430.is_present(); + group_flags[8] |= pusch_cfg_ded_v1430.is_present(); + group_flags[8] |= srs_ul_periodic_cfg_ded_list_r14.is_present(); + group_flags[8] |= srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present(); + group_flags[8] |= srs_ul_aperiodic_cfg_ded_list_r14.is_present(); + group_flags[8] |= srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present(); + group_flags[8] |= csi_rs_cfg_v1430.is_present(); + group_flags[8] |= csi_rs_cfg_zp_ap_list_r14.is_present(); + group_flags[8] |= cqi_report_cfg_v1430.is_present(); group_flags[8] |= semi_open_loop_r14_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1480_present != (csi_rs_cfg_v1480.get() != NULL), __FILE__, __LINE__); - group_flags[9] |= csi_rs_cfg_v1480_present; - rrc_asn1_warn_assert(phys_cfg_ded_stti_r15_present != (phys_cfg_ded_stti_r15.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= phys_cfg_ded_stti_r15_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1530_present != (pdsch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= pdsch_cfg_ded_v1530_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1530_present != (pusch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= pusch_cfg_ded_v1530_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1530_present != (cqi_report_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= cqi_report_cfg_v1530_present; - rrc_asn1_warn_assert(ant_info_v1530_present != (ant_info_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= ant_info_v1530_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1530_present != (csi_rs_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= csi_rs_cfg_v1530_present; - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1530_present != (ul_pwr_ctrl_ded_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= ul_pwr_ctrl_ded_v1530_present; - rrc_asn1_warn_assert( - semi_static_cfi_cfg_r15_present != (semi_static_cfi_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= semi_static_cfi_cfg_r15_present; - rrc_asn1_warn_assert( - blind_pdsch_repeat_cfg_r15_present != (blind_pdsch_repeat_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[10] |= blind_pdsch_repeat_cfg_r15_present; + group_flags[9] |= csi_rs_cfg_v1480.is_present(); + group_flags[10] |= phys_cfg_ded_stti_r15.is_present(); + group_flags[10] |= pdsch_cfg_ded_v1530.is_present(); + group_flags[10] |= pusch_cfg_ded_v1530.is_present(); + group_flags[10] |= cqi_report_cfg_v1530.is_present(); + group_flags[10] |= ant_info_v1530.is_present(); + group_flags[10] |= csi_rs_cfg_v1530.is_present(); + group_flags[10] |= ul_pwr_ctrl_ded_v1530.is_present(); + group_flags[10] |= semi_static_cfi_cfg_r15.is_present(); + group_flags[10] |= blind_pdsch_repeat_cfg_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cqi_report_cfg_v920_present, 1)); - HANDLE_CODE(bref.pack(ant_info_v920_present, 1)); - if (cqi_report_cfg_v920_present) { + HANDLE_CODE(bref.pack(cqi_report_cfg_v920.is_present(), 1)); + HANDLE_CODE(bref.pack(ant_info_v920.is_present(), 1)); + if (cqi_report_cfg_v920.is_present()) { HANDLE_CODE(cqi_report_cfg_v920->pack(bref)); } - if (ant_info_v920_present) { + if (ant_info_v920.is_present()) { HANDLE_CODE(ant_info_v920->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ant_info_r10_present, 1)); - HANDLE_CODE(bref.pack(ant_info_ul_r10_present, 1)); + HANDLE_CODE(bref.pack(ant_info_r10.is_present(), 1)); + HANDLE_CODE(bref.pack(ant_info_ul_r10.is_present(), 1)); HANDLE_CODE(bref.pack(cif_presence_r10_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_r10_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_r10_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_ded_v1020_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1020_present, 1)); - HANDLE_CODE(bref.pack(sched_request_cfg_v1020_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_v1020_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_r10_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1020_present, 1)); - if (ant_info_r10_present) { + HANDLE_CODE(bref.pack(cqi_report_cfg_r10.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_r10.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_ded_v1020.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1020.is_present(), 1)); + HANDLE_CODE(bref.pack(sched_request_cfg_v1020.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_v1020.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_r10.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1020.is_present(), 1)); + if (ant_info_r10.is_present()) { HANDLE_CODE(ant_info_r10->pack(bref)); } - if (ant_info_ul_r10_present) { + if (ant_info_ul_r10.is_present()) { HANDLE_CODE(ant_info_ul_r10->pack(bref)); } if (cif_presence_r10_present) { HANDLE_CODE(bref.pack(cif_presence_r10, 1)); } - if (cqi_report_cfg_r10_present) { + if (cqi_report_cfg_r10.is_present()) { HANDLE_CODE(cqi_report_cfg_r10->pack(bref)); } - if (csi_rs_cfg_r10_present) { + if (csi_rs_cfg_r10.is_present()) { HANDLE_CODE(csi_rs_cfg_r10->pack(bref)); } - if (pucch_cfg_ded_v1020_present) { + if (pucch_cfg_ded_v1020.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1020->pack(bref)); } - if (pusch_cfg_ded_v1020_present) { + if (pusch_cfg_ded_v1020.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1020->pack(bref)); } - if (sched_request_cfg_v1020_present) { + if (sched_request_cfg_v1020.is_present()) { HANDLE_CODE(sched_request_cfg_v1020->pack(bref)); } - if (srs_ul_cfg_ded_v1020_present) { + if (srs_ul_cfg_ded_v1020.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_v1020->pack(bref)); } - if (srs_ul_cfg_ded_aperiodic_r10_present) { + if (srs_ul_cfg_ded_aperiodic_r10.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_r10->pack(bref)); } - if (ul_pwr_ctrl_ded_v1020_present) { + if (ul_pwr_ctrl_ded_v1020.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1020->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(add_spec_emission_ca_r10_present, 1)); - if (add_spec_emission_ca_r10_present) { + HANDLE_CODE(bref.pack(add_spec_emission_ca_r10.is_present(), 1)); + if (add_spec_emission_ca_r10.is_present()) { HANDLE_CODE(add_spec_emission_ca_r10->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_r11_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_r11_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_release_list_r11_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_add_mod_list_r11_present, 1)); - HANDLE_CODE(bref.pack(epdcch_cfg_r11_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1130_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1130_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_ded_v1130_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1130_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1130_present, 1)); - if (csi_rs_cfg_nzp_to_release_list_r11_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_release_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_add_mod_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(epdcch_cfg_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_ded_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1130.is_present(), 1)); + if (csi_rs_cfg_nzp_to_release_list_r11.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *csi_rs_cfg_nzp_to_release_list_r11, 1, 3, UnalignedIntegerPacker(1, 3))); } - if (csi_rs_cfg_nzp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *csi_rs_cfg_nzp_to_add_mod_list_r11, 1, 3)); } - if (csi_rs_cfg_zp_to_release_list_r11_present) { + if (csi_rs_cfg_zp_to_release_list_r11.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *csi_rs_cfg_zp_to_release_list_r11, 1, 4, UnalignedIntegerPacker(1, 4))); } - if (csi_rs_cfg_zp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_zp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *csi_rs_cfg_zp_to_add_mod_list_r11, 1, 4)); } - if (epdcch_cfg_r11_present) { + if (epdcch_cfg_r11.is_present()) { HANDLE_CODE(epdcch_cfg_r11->pack(bref)); } - if (pdsch_cfg_ded_v1130_present) { + if (pdsch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1130->pack(bref)); } - if (cqi_report_cfg_v1130_present) { + if (cqi_report_cfg_v1130.is_present()) { HANDLE_CODE(cqi_report_cfg_v1130->pack(bref)); } - if (pucch_cfg_ded_v1130_present) { + if (pucch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1130->pack(bref)); } - if (pusch_cfg_ded_v1130_present) { + if (pusch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1130->pack(bref)); } - if (ul_pwr_ctrl_ded_v1130_present) { + if (ul_pwr_ctrl_ded_v1130.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1130->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(ant_info_v1250_present, 1)); - HANDLE_CODE(bref.pack(eimta_main_cfg_r12_present, 1)); - HANDLE_CODE(bref.pack(eimta_main_cfg_pcell_r12_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_ded_v1250_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_pcell_v1250_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1250_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1250_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1250_present, 1)); - if (ant_info_v1250_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(ant_info_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(eimta_main_cfg_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(eimta_main_cfg_pcell_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_ded_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_pcell_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1250.is_present(), 1)); + if (ant_info_v1250.is_present()) { HANDLE_CODE(ant_info_v1250->pack(bref)); } - if (eimta_main_cfg_r12_present) { + if (eimta_main_cfg_r12.is_present()) { HANDLE_CODE(eimta_main_cfg_r12->pack(bref)); } - if (eimta_main_cfg_pcell_r12_present) { + if (eimta_main_cfg_pcell_r12.is_present()) { HANDLE_CODE(eimta_main_cfg_pcell_r12->pack(bref)); } - if (pucch_cfg_ded_v1250_present) { + if (pucch_cfg_ded_v1250.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1250->pack(bref)); } - if (cqi_report_cfg_pcell_v1250_present) { + if (cqi_report_cfg_pcell_v1250.is_present()) { HANDLE_CODE(cqi_report_cfg_pcell_v1250->pack(bref)); } - if (ul_pwr_ctrl_ded_v1250_present) { + if (ul_pwr_ctrl_ded_v1250.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1250->pack(bref)); } - if (pusch_cfg_ded_v1250_present) { + if (pusch_cfg_ded_v1250.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1250->pack(bref)); } - if (csi_rs_cfg_v1250_present) { + if (csi_rs_cfg_v1250.is_present()) { HANDLE_CODE(csi_rs_cfg_v1250->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1280_present, 1)); - if (pdsch_cfg_ded_v1280_present) { + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1280.is_present(), 1)); + if (pdsch_cfg_ded_v1280.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1280->pack(bref)); } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1310_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_ded_r13_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_r13_present, 1)); - HANDLE_CODE(bref.pack(pdcch_candidate_reductions_r13_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_v1310_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_up_pts_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_v1310_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(ce_mode_r13_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_ext_r13_present, 1)); - if (pdsch_cfg_ded_v1310_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_ded_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(pdcch_candidate_reductions_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_up_pts_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(ce_mode_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_ext_r13.is_present(), 1)); + if (pdsch_cfg_ded_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1310->pack(bref)); } - if (pucch_cfg_ded_r13_present) { + if (pucch_cfg_ded_r13.is_present()) { HANDLE_CODE(pucch_cfg_ded_r13->pack(bref)); } - if (pusch_cfg_ded_r13_present) { + if (pusch_cfg_ded_r13.is_present()) { HANDLE_CODE(pusch_cfg_ded_r13->pack(bref)); } - if (pdcch_candidate_reductions_r13_present) { + if (pdcch_candidate_reductions_r13.is_present()) { HANDLE_CODE(pdcch_candidate_reductions_r13->pack(bref)); } - if (cqi_report_cfg_v1310_present) { + if (cqi_report_cfg_v1310.is_present()) { HANDLE_CODE(cqi_report_cfg_v1310->pack(bref)); } - if (srs_ul_cfg_ded_v1310_present) { + if (srs_ul_cfg_ded_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_v1310->pack(bref)); } - if (srs_ul_cfg_ded_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_up_pts_ext_r13->pack(bref)); } - if (srs_ul_cfg_ded_aperiodic_v1310_present) { + if (srs_ul_cfg_ded_aperiodic_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_v1310->pack(bref)); } - if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13->pack(bref)); } - if (csi_rs_cfg_v1310_present) { + if (csi_rs_cfg_v1310.is_present()) { HANDLE_CODE(csi_rs_cfg_v1310->pack(bref)); } - if (ce_mode_r13_present) { + if (ce_mode_r13.is_present()) { HANDLE_CODE(ce_mode_r13->pack(bref)); } - if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *csi_rs_cfg_nzp_to_add_mod_list_ext_r13, 1, 21)); } - if (csi_rs_cfg_nzp_to_release_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_release_list_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of( bref, *csi_rs_cfg_nzp_to_release_list_ext_r13, 1, 21, UnalignedIntegerPacker(4, 24))); } } if (group_flags[7]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1320_present, 1)); - if (cqi_report_cfg_v1320_present) { + HANDLE_CODE(bref.pack(cqi_report_cfg_v1320.is_present(), 1)); + if (cqi_report_cfg_v1320.is_present()) { HANDLE_CODE(cqi_report_cfg_v1320->pack(bref)); } } if (group_flags[8]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(type_a_srs_tpc_pdcch_group_r14_present, 1)); - HANDLE_CODE(bref.pack(must_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(pusch_enhance_cfg_r14_present, 1)); + HANDLE_CODE(bref.pack(type_a_srs_tpc_pdcch_group_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(must_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_enhance_cfg_r14.is_present(), 1)); HANDLE_CODE(bref.pack(ce_pdsch_pusch_enhancement_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(ant_info_v1430_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_ded_v1430_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1430_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1430_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_list_r14_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_aperiodic_cfg_ded_list_r14_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1430_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_zp_ap_list_r14_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1430_present, 1)); + HANDLE_CODE(bref.pack(ant_info_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_ded_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_aperiodic_cfg_ded_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_zp_ap_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1430.is_present(), 1)); HANDLE_CODE(bref.pack(semi_open_loop_r14_present, 1)); - if (type_a_srs_tpc_pdcch_group_r14_present) { + if (type_a_srs_tpc_pdcch_group_r14.is_present()) { HANDLE_CODE(type_a_srs_tpc_pdcch_group_r14->pack(bref)); } - if (must_cfg_r14_present) { + if (must_cfg_r14.is_present()) { HANDLE_CODE(must_cfg_r14->pack(bref)); } - if (pusch_enhance_cfg_r14_present) { + if (pusch_enhance_cfg_r14.is_present()) { HANDLE_CODE(pusch_enhance_cfg_r14->pack(bref)); } - if (ant_info_v1430_present) { + if (ant_info_v1430.is_present()) { HANDLE_CODE(ant_info_v1430->pack(bref)); } - if (pucch_cfg_ded_v1430_present) { + if (pucch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1430->pack(bref)); } - if (pdsch_cfg_ded_v1430_present) { + if (pdsch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1430->pack(bref)); } - if (pusch_cfg_ded_v1430_present) { + if (pusch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1430->pack(bref)); } - if (srs_ul_periodic_cfg_ded_list_r14_present) { + if (srs_ul_periodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_periodic_cfg_ded_list_r14, 1, 2)); } - if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present) { + if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_periodic_cfg_ded_up_pts_ext_list_r14, 1, 4)); } - if (srs_ul_aperiodic_cfg_ded_list_r14_present) { + if (srs_ul_aperiodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_aperiodic_cfg_ded_list_r14, 1, 2)); } - if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present) { + if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_cfg_ded_ap_up_pts_ext_list_r14, 1, 4)); } - if (csi_rs_cfg_v1430_present) { + if (csi_rs_cfg_v1430.is_present()) { HANDLE_CODE(csi_rs_cfg_v1430->pack(bref)); } - if (csi_rs_cfg_zp_ap_list_r14_present) { + if (csi_rs_cfg_zp_ap_list_r14.is_present()) { HANDLE_CODE(csi_rs_cfg_zp_ap_list_r14->pack(bref)); } - if (cqi_report_cfg_v1430_present) { + if (cqi_report_cfg_v1430.is_present()) { HANDLE_CODE(cqi_report_cfg_v1430->pack(bref)); } if (semi_open_loop_r14_present) { @@ -42124,50 +41661,50 @@ SRSASN_CODE phys_cfg_ded_s::pack(bit_ref& bref) const } } if (group_flags[9]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1480_present, 1)); - if (csi_rs_cfg_v1480_present) { + HANDLE_CODE(bref.pack(csi_rs_cfg_v1480.is_present(), 1)); + if (csi_rs_cfg_v1480.is_present()) { HANDLE_CODE(csi_rs_cfg_v1480->pack(bref)); } } if (group_flags[10]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(phys_cfg_ded_stti_r15_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1530_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1530_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(ant_info_v1530_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1530_present, 1)); - HANDLE_CODE(bref.pack(semi_static_cfi_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(blind_pdsch_repeat_cfg_r15_present, 1)); - if (phys_cfg_ded_stti_r15_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(phys_cfg_ded_stti_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(ant_info_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(semi_static_cfi_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(blind_pdsch_repeat_cfg_r15.is_present(), 1)); + if (phys_cfg_ded_stti_r15.is_present()) { HANDLE_CODE(phys_cfg_ded_stti_r15->pack(bref)); } - if (pdsch_cfg_ded_v1530_present) { + if (pdsch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1530->pack(bref)); } - if (pusch_cfg_ded_v1530_present) { + if (pusch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1530->pack(bref)); } - if (cqi_report_cfg_v1530_present) { + if (cqi_report_cfg_v1530.is_present()) { HANDLE_CODE(cqi_report_cfg_v1530->pack(bref)); } - if (ant_info_v1530_present) { + if (ant_info_v1530.is_present()) { HANDLE_CODE(ant_info_v1530->pack(bref)); } - if (csi_rs_cfg_v1530_present) { + if (csi_rs_cfg_v1530.is_present()) { HANDLE_CODE(csi_rs_cfg_v1530->pack(bref)); } - if (ul_pwr_ctrl_ded_v1530_present) { + if (ul_pwr_ctrl_ded_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1530->pack(bref)); } - if (semi_static_cfi_cfg_r15_present) { + if (semi_static_cfi_cfg_r15.is_present()) { HANDLE_CODE(semi_static_cfi_cfg_r15->pack(bref)); } - if (blind_pdsch_repeat_cfg_r15_present) { + if (blind_pdsch_repeat_cfg_r15.is_present()) { HANDLE_CODE(blind_pdsch_repeat_cfg_r15->pack(bref)); } } @@ -42220,351 +41757,411 @@ SRSASN_CODE phys_cfg_ded_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(11); + ext_groups_unpacker_guard group_flags(11); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool cqi_report_cfg_v920_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v920_present, 1)); + cqi_report_cfg_v920.set_present(cqi_report_cfg_v920_present); + bool ant_info_v920_present; HANDLE_CODE(bref.unpack(ant_info_v920_present, 1)); - if (cqi_report_cfg_v920_present) { - cqi_report_cfg_v920 = make_copy_ptr(cqi_report_cfg_v920_s()); + ant_info_v920.set_present(ant_info_v920_present); + if (cqi_report_cfg_v920.is_present()) { HANDLE_CODE(cqi_report_cfg_v920->unpack(bref)); } - if (ant_info_v920_present) { - ant_info_v920 = make_copy_ptr(ant_info_ded_v920_s()); + if (ant_info_v920.is_present()) { HANDLE_CODE(ant_info_v920->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ant_info_r10_present; HANDLE_CODE(bref.unpack(ant_info_r10_present, 1)); + ant_info_r10.set_present(ant_info_r10_present); + bool ant_info_ul_r10_present; HANDLE_CODE(bref.unpack(ant_info_ul_r10_present, 1)); + ant_info_ul_r10.set_present(ant_info_ul_r10_present); HANDLE_CODE(bref.unpack(cif_presence_r10_present, 1)); + bool cqi_report_cfg_r10_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_r10_present, 1)); + cqi_report_cfg_r10.set_present(cqi_report_cfg_r10_present); + bool csi_rs_cfg_r10_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_r10_present, 1)); + csi_rs_cfg_r10.set_present(csi_rs_cfg_r10_present); + bool pucch_cfg_ded_v1020_present; HANDLE_CODE(bref.unpack(pucch_cfg_ded_v1020_present, 1)); + pucch_cfg_ded_v1020.set_present(pucch_cfg_ded_v1020_present); + bool pusch_cfg_ded_v1020_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1020_present, 1)); + pusch_cfg_ded_v1020.set_present(pusch_cfg_ded_v1020_present); + bool sched_request_cfg_v1020_present; HANDLE_CODE(bref.unpack(sched_request_cfg_v1020_present, 1)); + sched_request_cfg_v1020.set_present(sched_request_cfg_v1020_present); + bool srs_ul_cfg_ded_v1020_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_v1020_present, 1)); + srs_ul_cfg_ded_v1020.set_present(srs_ul_cfg_ded_v1020_present); + bool srs_ul_cfg_ded_aperiodic_r10_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_aperiodic_r10_present, 1)); + srs_ul_cfg_ded_aperiodic_r10.set_present(srs_ul_cfg_ded_aperiodic_r10_present); + bool ul_pwr_ctrl_ded_v1020_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_ded_v1020_present, 1)); - if (ant_info_r10_present) { - ant_info_r10 = make_copy_ptr(ant_info_r10_c_()); + ul_pwr_ctrl_ded_v1020.set_present(ul_pwr_ctrl_ded_v1020_present); + if (ant_info_r10.is_present()) { HANDLE_CODE(ant_info_r10->unpack(bref)); } - if (ant_info_ul_r10_present) { - ant_info_ul_r10 = make_copy_ptr(ant_info_ul_r10_s()); + if (ant_info_ul_r10.is_present()) { HANDLE_CODE(ant_info_ul_r10->unpack(bref)); } if (cif_presence_r10_present) { HANDLE_CODE(bref.unpack(cif_presence_r10, 1)); } - if (cqi_report_cfg_r10_present) { - cqi_report_cfg_r10 = make_copy_ptr(cqi_report_cfg_r10_s()); + if (cqi_report_cfg_r10.is_present()) { HANDLE_CODE(cqi_report_cfg_r10->unpack(bref)); } - if (csi_rs_cfg_r10_present) { - csi_rs_cfg_r10 = make_copy_ptr(csi_rs_cfg_r10_s()); + if (csi_rs_cfg_r10.is_present()) { HANDLE_CODE(csi_rs_cfg_r10->unpack(bref)); } - if (pucch_cfg_ded_v1020_present) { - pucch_cfg_ded_v1020 = make_copy_ptr(pucch_cfg_ded_v1020_s()); + if (pucch_cfg_ded_v1020.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1020->unpack(bref)); } - if (pusch_cfg_ded_v1020_present) { - pusch_cfg_ded_v1020 = make_copy_ptr(pusch_cfg_ded_v1020_s()); + if (pusch_cfg_ded_v1020.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1020->unpack(bref)); } - if (sched_request_cfg_v1020_present) { - sched_request_cfg_v1020 = make_copy_ptr(sched_request_cfg_v1020_s()); + if (sched_request_cfg_v1020.is_present()) { HANDLE_CODE(sched_request_cfg_v1020->unpack(bref)); } - if (srs_ul_cfg_ded_v1020_present) { - srs_ul_cfg_ded_v1020 = make_copy_ptr(srs_ul_cfg_ded_v1020_s()); + if (srs_ul_cfg_ded_v1020.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_v1020->unpack(bref)); } - if (srs_ul_cfg_ded_aperiodic_r10_present) { - srs_ul_cfg_ded_aperiodic_r10 = make_copy_ptr(srs_ul_cfg_ded_aperiodic_r10_c()); + if (srs_ul_cfg_ded_aperiodic_r10.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_r10->unpack(bref)); } - if (ul_pwr_ctrl_ded_v1020_present) { - ul_pwr_ctrl_ded_v1020 = make_copy_ptr(ul_pwr_ctrl_ded_v1020_s()); + if (ul_pwr_ctrl_ded_v1020.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1020->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool add_spec_emission_ca_r10_present; HANDLE_CODE(bref.unpack(add_spec_emission_ca_r10_present, 1)); - if (add_spec_emission_ca_r10_present) { - add_spec_emission_ca_r10 = make_copy_ptr(add_spec_emission_ca_r10_c_()); + add_spec_emission_ca_r10.set_present(add_spec_emission_ca_r10_present); + if (add_spec_emission_ca_r10.is_present()) { HANDLE_CODE(add_spec_emission_ca_r10->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool csi_rs_cfg_nzp_to_release_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_release_list_r11_present, 1)); + csi_rs_cfg_nzp_to_release_list_r11.set_present(csi_rs_cfg_nzp_to_release_list_r11_present); + bool csi_rs_cfg_nzp_to_add_mod_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_add_mod_list_r11_present, 1)); + csi_rs_cfg_nzp_to_add_mod_list_r11.set_present(csi_rs_cfg_nzp_to_add_mod_list_r11_present); + bool csi_rs_cfg_zp_to_release_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_zp_to_release_list_r11_present, 1)); + csi_rs_cfg_zp_to_release_list_r11.set_present(csi_rs_cfg_zp_to_release_list_r11_present); + bool csi_rs_cfg_zp_to_add_mod_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_zp_to_add_mod_list_r11_present, 1)); + csi_rs_cfg_zp_to_add_mod_list_r11.set_present(csi_rs_cfg_zp_to_add_mod_list_r11_present); + bool epdcch_cfg_r11_present; HANDLE_CODE(bref.unpack(epdcch_cfg_r11_present, 1)); + epdcch_cfg_r11.set_present(epdcch_cfg_r11_present); + bool pdsch_cfg_ded_v1130_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1130_present, 1)); + pdsch_cfg_ded_v1130.set_present(pdsch_cfg_ded_v1130_present); + bool cqi_report_cfg_v1130_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1130_present, 1)); + cqi_report_cfg_v1130.set_present(cqi_report_cfg_v1130_present); + bool pucch_cfg_ded_v1130_present; HANDLE_CODE(bref.unpack(pucch_cfg_ded_v1130_present, 1)); + pucch_cfg_ded_v1130.set_present(pucch_cfg_ded_v1130_present); + bool pusch_cfg_ded_v1130_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1130_present, 1)); + pusch_cfg_ded_v1130.set_present(pusch_cfg_ded_v1130_present); + bool ul_pwr_ctrl_ded_v1130_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_ded_v1130_present, 1)); - if (csi_rs_cfg_nzp_to_release_list_r11_present) { - csi_rs_cfg_nzp_to_release_list_r11 = make_copy_ptr(csi_rs_cfg_nzp_to_release_list_r11_l()); + ul_pwr_ctrl_ded_v1130.set_present(ul_pwr_ctrl_ded_v1130_present); + if (csi_rs_cfg_nzp_to_release_list_r11.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*csi_rs_cfg_nzp_to_release_list_r11, bref, 1, 3, UnalignedIntegerPacker(1, 3))); } - if (csi_rs_cfg_nzp_to_add_mod_list_r11_present) { - csi_rs_cfg_nzp_to_add_mod_list_r11 = make_copy_ptr(csi_rs_cfg_nzp_to_add_mod_list_r11_l()); + if (csi_rs_cfg_nzp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*csi_rs_cfg_nzp_to_add_mod_list_r11, bref, 1, 3)); } - if (csi_rs_cfg_zp_to_release_list_r11_present) { - csi_rs_cfg_zp_to_release_list_r11 = make_copy_ptr(csi_rs_cfg_zp_to_release_list_r11_l()); + if (csi_rs_cfg_zp_to_release_list_r11.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*csi_rs_cfg_zp_to_release_list_r11, bref, 1, 4, UnalignedIntegerPacker(1, 4))); } - if (csi_rs_cfg_zp_to_add_mod_list_r11_present) { - csi_rs_cfg_zp_to_add_mod_list_r11 = make_copy_ptr(csi_rs_cfg_zp_to_add_mod_list_r11_l()); + if (csi_rs_cfg_zp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*csi_rs_cfg_zp_to_add_mod_list_r11, bref, 1, 4)); } - if (epdcch_cfg_r11_present) { - epdcch_cfg_r11 = make_copy_ptr(epdcch_cfg_r11_s()); + if (epdcch_cfg_r11.is_present()) { HANDLE_CODE(epdcch_cfg_r11->unpack(bref)); } - if (pdsch_cfg_ded_v1130_present) { - pdsch_cfg_ded_v1130 = make_copy_ptr(pdsch_cfg_ded_v1130_s()); + if (pdsch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1130->unpack(bref)); } - if (cqi_report_cfg_v1130_present) { - cqi_report_cfg_v1130 = make_copy_ptr(cqi_report_cfg_v1130_s()); + if (cqi_report_cfg_v1130.is_present()) { HANDLE_CODE(cqi_report_cfg_v1130->unpack(bref)); } - if (pucch_cfg_ded_v1130_present) { - pucch_cfg_ded_v1130 = make_copy_ptr(pucch_cfg_ded_v1130_s()); + if (pucch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1130->unpack(bref)); } - if (pusch_cfg_ded_v1130_present) { - pusch_cfg_ded_v1130 = make_copy_ptr(pusch_cfg_ded_v1130_s()); + if (pusch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1130->unpack(bref)); } - if (ul_pwr_ctrl_ded_v1130_present) { - ul_pwr_ctrl_ded_v1130 = make_copy_ptr(ul_pwr_ctrl_ded_v1130_s()); + if (ul_pwr_ctrl_ded_v1130.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1130->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ant_info_v1250_present; HANDLE_CODE(bref.unpack(ant_info_v1250_present, 1)); + ant_info_v1250.set_present(ant_info_v1250_present); + bool eimta_main_cfg_r12_present; HANDLE_CODE(bref.unpack(eimta_main_cfg_r12_present, 1)); + eimta_main_cfg_r12.set_present(eimta_main_cfg_r12_present); + bool eimta_main_cfg_pcell_r12_present; HANDLE_CODE(bref.unpack(eimta_main_cfg_pcell_r12_present, 1)); + eimta_main_cfg_pcell_r12.set_present(eimta_main_cfg_pcell_r12_present); + bool pucch_cfg_ded_v1250_present; HANDLE_CODE(bref.unpack(pucch_cfg_ded_v1250_present, 1)); + pucch_cfg_ded_v1250.set_present(pucch_cfg_ded_v1250_present); + bool cqi_report_cfg_pcell_v1250_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_pcell_v1250_present, 1)); + cqi_report_cfg_pcell_v1250.set_present(cqi_report_cfg_pcell_v1250_present); + bool ul_pwr_ctrl_ded_v1250_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_ded_v1250_present, 1)); + ul_pwr_ctrl_ded_v1250.set_present(ul_pwr_ctrl_ded_v1250_present); + bool pusch_cfg_ded_v1250_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1250_present, 1)); + pusch_cfg_ded_v1250.set_present(pusch_cfg_ded_v1250_present); + bool csi_rs_cfg_v1250_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1250_present, 1)); - if (ant_info_v1250_present) { - ant_info_v1250 = make_copy_ptr(ant_info_ded_v1250_s()); + csi_rs_cfg_v1250.set_present(csi_rs_cfg_v1250_present); + if (ant_info_v1250.is_present()) { HANDLE_CODE(ant_info_v1250->unpack(bref)); } - if (eimta_main_cfg_r12_present) { - eimta_main_cfg_r12 = make_copy_ptr(eimta_main_cfg_r12_c()); + if (eimta_main_cfg_r12.is_present()) { HANDLE_CODE(eimta_main_cfg_r12->unpack(bref)); } - if (eimta_main_cfg_pcell_r12_present) { - eimta_main_cfg_pcell_r12 = make_copy_ptr(eimta_main_cfg_serv_cell_r12_c()); + if (eimta_main_cfg_pcell_r12.is_present()) { HANDLE_CODE(eimta_main_cfg_pcell_r12->unpack(bref)); } - if (pucch_cfg_ded_v1250_present) { - pucch_cfg_ded_v1250 = make_copy_ptr(pucch_cfg_ded_v1250_s()); + if (pucch_cfg_ded_v1250.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1250->unpack(bref)); } - if (cqi_report_cfg_pcell_v1250_present) { - cqi_report_cfg_pcell_v1250 = make_copy_ptr(cqi_report_cfg_v1250_s()); + if (cqi_report_cfg_pcell_v1250.is_present()) { HANDLE_CODE(cqi_report_cfg_pcell_v1250->unpack(bref)); } - if (ul_pwr_ctrl_ded_v1250_present) { - ul_pwr_ctrl_ded_v1250 = make_copy_ptr(ul_pwr_ctrl_ded_v1250_s()); + if (ul_pwr_ctrl_ded_v1250.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1250->unpack(bref)); } - if (pusch_cfg_ded_v1250_present) { - pusch_cfg_ded_v1250 = make_copy_ptr(pusch_cfg_ded_v1250_s()); + if (pusch_cfg_ded_v1250.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1250->unpack(bref)); } - if (csi_rs_cfg_v1250_present) { - csi_rs_cfg_v1250 = make_copy_ptr(csi_rs_cfg_v1250_s()); + if (csi_rs_cfg_v1250.is_present()) { HANDLE_CODE(csi_rs_cfg_v1250->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool pdsch_cfg_ded_v1280_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1280_present, 1)); - if (pdsch_cfg_ded_v1280_present) { - pdsch_cfg_ded_v1280 = make_copy_ptr(pdsch_cfg_ded_v1280_s()); + pdsch_cfg_ded_v1280.set_present(pdsch_cfg_ded_v1280_present); + if (pdsch_cfg_ded_v1280.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1280->unpack(bref)); } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool pdsch_cfg_ded_v1310_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1310_present, 1)); + pdsch_cfg_ded_v1310.set_present(pdsch_cfg_ded_v1310_present); + bool pucch_cfg_ded_r13_present; HANDLE_CODE(bref.unpack(pucch_cfg_ded_r13_present, 1)); + pucch_cfg_ded_r13.set_present(pucch_cfg_ded_r13_present); + bool pusch_cfg_ded_r13_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_r13_present, 1)); + pusch_cfg_ded_r13.set_present(pusch_cfg_ded_r13_present); + bool pdcch_candidate_reductions_r13_present; HANDLE_CODE(bref.unpack(pdcch_candidate_reductions_r13_present, 1)); + pdcch_candidate_reductions_r13.set_present(pdcch_candidate_reductions_r13_present); + bool cqi_report_cfg_v1310_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1310_present, 1)); + cqi_report_cfg_v1310.set_present(cqi_report_cfg_v1310_present); + bool srs_ul_cfg_ded_v1310_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_v1310_present, 1)); + srs_ul_cfg_ded_v1310.set_present(srs_ul_cfg_ded_v1310_present); + bool srs_ul_cfg_ded_up_pts_ext_r13_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_up_pts_ext_r13_present, 1)); + srs_ul_cfg_ded_up_pts_ext_r13.set_present(srs_ul_cfg_ded_up_pts_ext_r13_present); + bool srs_ul_cfg_ded_aperiodic_v1310_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_aperiodic_v1310_present, 1)); + srs_ul_cfg_ded_aperiodic_v1310.set_present(srs_ul_cfg_ded_aperiodic_v1310_present); + bool srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present, 1)); + srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.set_present(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present); + bool csi_rs_cfg_v1310_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1310_present, 1)); + csi_rs_cfg_v1310.set_present(csi_rs_cfg_v1310_present); + bool ce_mode_r13_present; HANDLE_CODE(bref.unpack(ce_mode_r13_present, 1)); + ce_mode_r13.set_present(ce_mode_r13_present); + bool csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present, 1)); + csi_rs_cfg_nzp_to_add_mod_list_ext_r13.set_present(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present); + bool csi_rs_cfg_nzp_to_release_list_ext_r13_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_release_list_ext_r13_present, 1)); - if (pdsch_cfg_ded_v1310_present) { - pdsch_cfg_ded_v1310 = make_copy_ptr(pdsch_cfg_ded_v1310_s()); + csi_rs_cfg_nzp_to_release_list_ext_r13.set_present(csi_rs_cfg_nzp_to_release_list_ext_r13_present); + if (pdsch_cfg_ded_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1310->unpack(bref)); } - if (pucch_cfg_ded_r13_present) { - pucch_cfg_ded_r13 = make_copy_ptr(pucch_cfg_ded_r13_s()); + if (pucch_cfg_ded_r13.is_present()) { HANDLE_CODE(pucch_cfg_ded_r13->unpack(bref)); } - if (pusch_cfg_ded_r13_present) { - pusch_cfg_ded_r13 = make_copy_ptr(pusch_cfg_ded_r13_s()); + if (pusch_cfg_ded_r13.is_present()) { HANDLE_CODE(pusch_cfg_ded_r13->unpack(bref)); } - if (pdcch_candidate_reductions_r13_present) { - pdcch_candidate_reductions_r13 = make_copy_ptr(pdcch_candidate_reductions_r13_c()); + if (pdcch_candidate_reductions_r13.is_present()) { HANDLE_CODE(pdcch_candidate_reductions_r13->unpack(bref)); } - if (cqi_report_cfg_v1310_present) { - cqi_report_cfg_v1310 = make_copy_ptr(cqi_report_cfg_v1310_s()); + if (cqi_report_cfg_v1310.is_present()) { HANDLE_CODE(cqi_report_cfg_v1310->unpack(bref)); } - if (srs_ul_cfg_ded_v1310_present) { - srs_ul_cfg_ded_v1310 = make_copy_ptr(srs_ul_cfg_ded_v1310_c()); + if (srs_ul_cfg_ded_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_v1310->unpack(bref)); } - if (srs_ul_cfg_ded_up_pts_ext_r13_present) { - srs_ul_cfg_ded_up_pts_ext_r13 = make_copy_ptr(srs_ul_cfg_ded_up_pts_ext_r13_c()); + if (srs_ul_cfg_ded_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_up_pts_ext_r13->unpack(bref)); } - if (srs_ul_cfg_ded_aperiodic_v1310_present) { - srs_ul_cfg_ded_aperiodic_v1310 = make_copy_ptr(srs_ul_cfg_ded_aperiodic_v1310_c()); + if (srs_ul_cfg_ded_aperiodic_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_v1310->unpack(bref)); } - if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present) { - srs_ul_cfg_ded_aperiodic_up_pts_ext_r13 = make_copy_ptr(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_c()); + if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13->unpack(bref)); } - if (csi_rs_cfg_v1310_present) { - csi_rs_cfg_v1310 = make_copy_ptr(csi_rs_cfg_v1310_s()); + if (csi_rs_cfg_v1310.is_present()) { HANDLE_CODE(csi_rs_cfg_v1310->unpack(bref)); } - if (ce_mode_r13_present) { - ce_mode_r13 = make_copy_ptr(ce_mode_r13_c_()); + if (ce_mode_r13.is_present()) { HANDLE_CODE(ce_mode_r13->unpack(bref)); } - if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present) { - csi_rs_cfg_nzp_to_add_mod_list_ext_r13 = make_copy_ptr(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_l()); + if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*csi_rs_cfg_nzp_to_add_mod_list_ext_r13, bref, 1, 21)); } - if (csi_rs_cfg_nzp_to_release_list_ext_r13_present) { - csi_rs_cfg_nzp_to_release_list_ext_r13 = make_copy_ptr(csi_rs_cfg_nzp_to_release_list_ext_r13_l()); + if (csi_rs_cfg_nzp_to_release_list_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of( *csi_rs_cfg_nzp_to_release_list_ext_r13, bref, 1, 21, UnalignedIntegerPacker(4, 24))); } } if (group_flags[7]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool cqi_report_cfg_v1320_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1320_present, 1)); - if (cqi_report_cfg_v1320_present) { - cqi_report_cfg_v1320 = make_copy_ptr(cqi_report_cfg_v1320_s()); + cqi_report_cfg_v1320.set_present(cqi_report_cfg_v1320_present); + if (cqi_report_cfg_v1320.is_present()) { HANDLE_CODE(cqi_report_cfg_v1320->unpack(bref)); } } if (group_flags[8]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool type_a_srs_tpc_pdcch_group_r14_present; HANDLE_CODE(bref.unpack(type_a_srs_tpc_pdcch_group_r14_present, 1)); + type_a_srs_tpc_pdcch_group_r14.set_present(type_a_srs_tpc_pdcch_group_r14_present); + bool must_cfg_r14_present; HANDLE_CODE(bref.unpack(must_cfg_r14_present, 1)); + must_cfg_r14.set_present(must_cfg_r14_present); + bool pusch_enhance_cfg_r14_present; HANDLE_CODE(bref.unpack(pusch_enhance_cfg_r14_present, 1)); + pusch_enhance_cfg_r14.set_present(pusch_enhance_cfg_r14_present); HANDLE_CODE(bref.unpack(ce_pdsch_pusch_enhancement_cfg_r14_present, 1)); + bool ant_info_v1430_present; HANDLE_CODE(bref.unpack(ant_info_v1430_present, 1)); + ant_info_v1430.set_present(ant_info_v1430_present); + bool pucch_cfg_ded_v1430_present; HANDLE_CODE(bref.unpack(pucch_cfg_ded_v1430_present, 1)); + pucch_cfg_ded_v1430.set_present(pucch_cfg_ded_v1430_present); + bool pdsch_cfg_ded_v1430_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1430_present, 1)); + pdsch_cfg_ded_v1430.set_present(pdsch_cfg_ded_v1430_present); + bool pusch_cfg_ded_v1430_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1430_present, 1)); + pusch_cfg_ded_v1430.set_present(pusch_cfg_ded_v1430_present); + bool srs_ul_periodic_cfg_ded_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_periodic_cfg_ded_list_r14_present, 1)); + srs_ul_periodic_cfg_ded_list_r14.set_present(srs_ul_periodic_cfg_ded_list_r14_present); + bool srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present, 1)); + srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.set_present(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present); + bool srs_ul_aperiodic_cfg_ded_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_aperiodic_cfg_ded_list_r14_present, 1)); + srs_ul_aperiodic_cfg_ded_list_r14.set_present(srs_ul_aperiodic_cfg_ded_list_r14_present); + bool srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present, 1)); + srs_ul_cfg_ded_ap_up_pts_ext_list_r14.set_present(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present); + bool csi_rs_cfg_v1430_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1430_present, 1)); + csi_rs_cfg_v1430.set_present(csi_rs_cfg_v1430_present); + bool csi_rs_cfg_zp_ap_list_r14_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_zp_ap_list_r14_present, 1)); + csi_rs_cfg_zp_ap_list_r14.set_present(csi_rs_cfg_zp_ap_list_r14_present); + bool cqi_report_cfg_v1430_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1430_present, 1)); + cqi_report_cfg_v1430.set_present(cqi_report_cfg_v1430_present); HANDLE_CODE(bref.unpack(semi_open_loop_r14_present, 1)); - if (type_a_srs_tpc_pdcch_group_r14_present) { - type_a_srs_tpc_pdcch_group_r14 = make_copy_ptr(type_a_srs_tpc_pdcch_group_r14_c_()); + if (type_a_srs_tpc_pdcch_group_r14.is_present()) { HANDLE_CODE(type_a_srs_tpc_pdcch_group_r14->unpack(bref)); } - if (must_cfg_r14_present) { - must_cfg_r14 = make_copy_ptr(must_cfg_r14_c_()); + if (must_cfg_r14.is_present()) { HANDLE_CODE(must_cfg_r14->unpack(bref)); } - if (pusch_enhance_cfg_r14_present) { - pusch_enhance_cfg_r14 = make_copy_ptr(pusch_enhance_cfg_r14_c()); + if (pusch_enhance_cfg_r14.is_present()) { HANDLE_CODE(pusch_enhance_cfg_r14->unpack(bref)); } - if (ant_info_v1430_present) { - ant_info_v1430 = make_copy_ptr(ant_info_ded_v1430_s()); + if (ant_info_v1430.is_present()) { HANDLE_CODE(ant_info_v1430->unpack(bref)); } - if (pucch_cfg_ded_v1430_present) { - pucch_cfg_ded_v1430 = make_copy_ptr(pucch_cfg_ded_v1430_s()); + if (pucch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pucch_cfg_ded_v1430->unpack(bref)); } - if (pdsch_cfg_ded_v1430_present) { - pdsch_cfg_ded_v1430 = make_copy_ptr(pdsch_cfg_ded_v1430_s()); + if (pdsch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1430->unpack(bref)); } - if (pusch_cfg_ded_v1430_present) { - pusch_cfg_ded_v1430 = make_copy_ptr(pusch_cfg_ded_v1430_s()); + if (pusch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1430->unpack(bref)); } - if (srs_ul_periodic_cfg_ded_list_r14_present) { - srs_ul_periodic_cfg_ded_list_r14 = make_copy_ptr(srs_ul_periodic_cfg_ded_list_r14_l_()); + if (srs_ul_periodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_periodic_cfg_ded_list_r14, bref, 1, 2)); } - if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present) { - srs_ul_periodic_cfg_ded_up_pts_ext_list_r14 = make_copy_ptr(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_l_()); + if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_periodic_cfg_ded_up_pts_ext_list_r14, bref, 1, 4)); } - if (srs_ul_aperiodic_cfg_ded_list_r14_present) { - srs_ul_aperiodic_cfg_ded_list_r14 = make_copy_ptr(srs_ul_aperiodic_cfg_ded_list_r14_l_()); + if (srs_ul_aperiodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_aperiodic_cfg_ded_list_r14, bref, 1, 2)); } - if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present) { - srs_ul_cfg_ded_ap_up_pts_ext_list_r14 = make_copy_ptr(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_l_()); + if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_cfg_ded_ap_up_pts_ext_list_r14, bref, 1, 4)); } - if (csi_rs_cfg_v1430_present) { - csi_rs_cfg_v1430 = make_copy_ptr(csi_rs_cfg_v1430_s()); + if (csi_rs_cfg_v1430.is_present()) { HANDLE_CODE(csi_rs_cfg_v1430->unpack(bref)); } - if (csi_rs_cfg_zp_ap_list_r14_present) { - csi_rs_cfg_zp_ap_list_r14 = make_copy_ptr(csi_rs_cfg_zp_ap_list_r14_c()); + if (csi_rs_cfg_zp_ap_list_r14.is_present()) { HANDLE_CODE(csi_rs_cfg_zp_ap_list_r14->unpack(bref)); } - if (cqi_report_cfg_v1430_present) { - cqi_report_cfg_v1430 = make_copy_ptr(cqi_report_cfg_v1430_s()); + if (cqi_report_cfg_v1430.is_present()) { HANDLE_CODE(cqi_report_cfg_v1430->unpack(bref)); } if (semi_open_loop_r14_present) { @@ -42572,60 +42169,70 @@ SRSASN_CODE phys_cfg_ded_s::unpack(bit_ref& bref) } } if (group_flags[9]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool csi_rs_cfg_v1480_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1480_present, 1)); - if (csi_rs_cfg_v1480_present) { - csi_rs_cfg_v1480 = make_copy_ptr(csi_rs_cfg_v1480_s()); + csi_rs_cfg_v1480.set_present(csi_rs_cfg_v1480_present); + if (csi_rs_cfg_v1480.is_present()) { HANDLE_CODE(csi_rs_cfg_v1480->unpack(bref)); } } if (group_flags[10]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool phys_cfg_ded_stti_r15_present; HANDLE_CODE(bref.unpack(phys_cfg_ded_stti_r15_present, 1)); + phys_cfg_ded_stti_r15.set_present(phys_cfg_ded_stti_r15_present); + bool pdsch_cfg_ded_v1530_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1530_present, 1)); + pdsch_cfg_ded_v1530.set_present(pdsch_cfg_ded_v1530_present); + bool pusch_cfg_ded_v1530_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1530_present, 1)); + pusch_cfg_ded_v1530.set_present(pusch_cfg_ded_v1530_present); + bool cqi_report_cfg_v1530_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1530_present, 1)); + cqi_report_cfg_v1530.set_present(cqi_report_cfg_v1530_present); + bool ant_info_v1530_present; HANDLE_CODE(bref.unpack(ant_info_v1530_present, 1)); + ant_info_v1530.set_present(ant_info_v1530_present); + bool csi_rs_cfg_v1530_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1530_present, 1)); + csi_rs_cfg_v1530.set_present(csi_rs_cfg_v1530_present); + bool ul_pwr_ctrl_ded_v1530_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_ded_v1530_present, 1)); + ul_pwr_ctrl_ded_v1530.set_present(ul_pwr_ctrl_ded_v1530_present); + bool semi_static_cfi_cfg_r15_present; HANDLE_CODE(bref.unpack(semi_static_cfi_cfg_r15_present, 1)); + semi_static_cfi_cfg_r15.set_present(semi_static_cfi_cfg_r15_present); + bool blind_pdsch_repeat_cfg_r15_present; HANDLE_CODE(bref.unpack(blind_pdsch_repeat_cfg_r15_present, 1)); - if (phys_cfg_ded_stti_r15_present) { - phys_cfg_ded_stti_r15 = make_copy_ptr(phys_cfg_ded_stti_r15_c()); + blind_pdsch_repeat_cfg_r15.set_present(blind_pdsch_repeat_cfg_r15_present); + if (phys_cfg_ded_stti_r15.is_present()) { HANDLE_CODE(phys_cfg_ded_stti_r15->unpack(bref)); } - if (pdsch_cfg_ded_v1530_present) { - pdsch_cfg_ded_v1530 = make_copy_ptr(pdsch_cfg_ded_v1530_s()); + if (pdsch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1530->unpack(bref)); } - if (pusch_cfg_ded_v1530_present) { - pusch_cfg_ded_v1530 = make_copy_ptr(pusch_cfg_ded_v1530_s()); + if (pusch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1530->unpack(bref)); } - if (cqi_report_cfg_v1530_present) { - cqi_report_cfg_v1530 = make_copy_ptr(cqi_report_cfg_v1530_s()); + if (cqi_report_cfg_v1530.is_present()) { HANDLE_CODE(cqi_report_cfg_v1530->unpack(bref)); } - if (ant_info_v1530_present) { - ant_info_v1530 = make_copy_ptr(ant_info_ded_v1530_c()); + if (ant_info_v1530.is_present()) { HANDLE_CODE(ant_info_v1530->unpack(bref)); } - if (csi_rs_cfg_v1530_present) { - csi_rs_cfg_v1530 = make_copy_ptr(csi_rs_cfg_v1530_s()); + if (csi_rs_cfg_v1530.is_present()) { HANDLE_CODE(csi_rs_cfg_v1530->unpack(bref)); } - if (ul_pwr_ctrl_ded_v1530_present) { - ul_pwr_ctrl_ded_v1530 = make_copy_ptr(ul_pwr_ctrl_ded_v1530_s()); + if (ul_pwr_ctrl_ded_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_v1530->unpack(bref)); } - if (semi_static_cfi_cfg_r15_present) { - semi_static_cfi_cfg_r15 = make_copy_ptr(semi_static_cfi_cfg_r15_c_()); + if (semi_static_cfi_cfg_r15.is_present()) { HANDLE_CODE(semi_static_cfi_cfg_r15->unpack(bref)); } - if (blind_pdsch_repeat_cfg_r15_present) { - blind_pdsch_repeat_cfg_r15 = make_copy_ptr(blind_pdsch_repeat_cfg_r15_c_()); + if (blind_pdsch_repeat_cfg_r15.is_present()) { HANDLE_CODE(blind_pdsch_repeat_cfg_r15->unpack(bref)); } } @@ -42676,433 +42283,322 @@ void phys_cfg_ded_s::to_json(json_writer& j) const sched_request_cfg.to_json(j); } if (ext) { - rrc_asn1_warn_assert(cqi_report_cfg_v920_present != (cqi_report_cfg_v920.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v920_present) { + if (cqi_report_cfg_v920.is_present()) { j.write_fieldname("cqi-ReportConfig-v920"); cqi_report_cfg_v920->to_json(j); } - rrc_asn1_warn_assert(ant_info_v920_present != (ant_info_v920.get() != NULL), __FILE__, __LINE__); - if (ant_info_v920_present) { + if (ant_info_v920.is_present()) { j.write_fieldname("antennaInfo-v920"); ant_info_v920->to_json(j); } - rrc_asn1_warn_assert(ant_info_r10_present != (ant_info_r10.get() != NULL), __FILE__, __LINE__); - if (ant_info_r10_present) { + if (ant_info_r10.is_present()) { j.write_fieldname("antennaInfo-r10"); ant_info_r10->to_json(j); } - rrc_asn1_warn_assert(ant_info_ul_r10_present != (ant_info_ul_r10.get() != NULL), __FILE__, __LINE__); - if (ant_info_ul_r10_present) { + if (ant_info_ul_r10.is_present()) { j.write_fieldname("antennaInfoUL-r10"); ant_info_ul_r10->to_json(j); } if (cif_presence_r10_present) { j.write_bool("cif-Presence-r10", cif_presence_r10); } - rrc_asn1_warn_assert(cqi_report_cfg_r10_present != (cqi_report_cfg_r10.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_r10_present) { + if (cqi_report_cfg_r10.is_present()) { j.write_fieldname("cqi-ReportConfig-r10"); cqi_report_cfg_r10->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_r10_present != (csi_rs_cfg_r10.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_r10_present) { + if (csi_rs_cfg_r10.is_present()) { j.write_fieldname("csi-RS-Config-r10"); csi_rs_cfg_r10->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_ded_v1020_present != (pucch_cfg_ded_v1020.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_ded_v1020_present) { + if (pucch_cfg_ded_v1020.is_present()) { j.write_fieldname("pucch-ConfigDedicated-v1020"); pucch_cfg_ded_v1020->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1020_present != (pusch_cfg_ded_v1020.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1020_present) { + if (pusch_cfg_ded_v1020.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1020"); pusch_cfg_ded_v1020->to_json(j); } - rrc_asn1_warn_assert( - sched_request_cfg_v1020_present != (sched_request_cfg_v1020.get() != NULL), __FILE__, __LINE__); - if (sched_request_cfg_v1020_present) { + if (sched_request_cfg_v1020.is_present()) { j.write_fieldname("schedulingRequestConfig-v1020"); sched_request_cfg_v1020->to_json(j); } - rrc_asn1_warn_assert(srs_ul_cfg_ded_v1020_present != (srs_ul_cfg_ded_v1020.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_v1020_present) { + if (srs_ul_cfg_ded_v1020.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicated-v1020"); srs_ul_cfg_ded_v1020->to_json(j); } - rrc_asn1_warn_assert( - srs_ul_cfg_ded_aperiodic_r10_present != (srs_ul_cfg_ded_aperiodic_r10.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_aperiodic_r10_present) { + if (srs_ul_cfg_ded_aperiodic_r10.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicatedAperiodic-r10"); srs_ul_cfg_ded_aperiodic_r10->to_json(j); } - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1020_present != (ul_pwr_ctrl_ded_v1020.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_ded_v1020_present) { + if (ul_pwr_ctrl_ded_v1020.is_present()) { j.write_fieldname("uplinkPowerControlDedicated-v1020"); ul_pwr_ctrl_ded_v1020->to_json(j); } - rrc_asn1_warn_assert( - add_spec_emission_ca_r10_present != (add_spec_emission_ca_r10.get() != NULL), __FILE__, __LINE__); - if (add_spec_emission_ca_r10_present) { + if (add_spec_emission_ca_r10.is_present()) { j.write_fieldname("additionalSpectrumEmissionCA-r10"); add_spec_emission_ca_r10->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_r11_present != - (csi_rs_cfg_nzp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_release_list_r11_present) { + if (csi_rs_cfg_nzp_to_release_list_r11.is_present()) { j.start_array("csi-RS-ConfigNZPToReleaseList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_release_list_r11->size(); ++i1) { j.write_int(((*csi_rs_cfg_nzp_to_release_list_r11)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_r11_present != - (csi_rs_cfg_nzp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_r11.is_present()) { j.start_array("csi-RS-ConfigNZPToAddModList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_add_mod_list_r11->size(); ++i1) { ((*csi_rs_cfg_nzp_to_add_mod_list_r11)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_release_list_r11_present != (csi_rs_cfg_zp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_zp_to_release_list_r11_present) { + if (csi_rs_cfg_zp_to_release_list_r11.is_present()) { j.start_array("csi-RS-ConfigZPToReleaseList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_zp_to_release_list_r11->size(); ++i1) { j.write_int(((*csi_rs_cfg_zp_to_release_list_r11)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_add_mod_list_r11_present != (csi_rs_cfg_zp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_zp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_zp_to_add_mod_list_r11.is_present()) { j.start_array("csi-RS-ConfigZPToAddModList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_zp_to_add_mod_list_r11->size(); ++i1) { ((*csi_rs_cfg_zp_to_add_mod_list_r11)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(epdcch_cfg_r11_present != (epdcch_cfg_r11.get() != NULL), __FILE__, __LINE__); - if (epdcch_cfg_r11_present) { + if (epdcch_cfg_r11.is_present()) { j.write_fieldname("epdcch-Config-r11"); epdcch_cfg_r11->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1130_present != (pdsch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1130_present) { + if (pdsch_cfg_ded_v1130.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1130"); pdsch_cfg_ded_v1130->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1130_present != (cqi_report_cfg_v1130.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1130_present) { + if (cqi_report_cfg_v1130.is_present()) { j.write_fieldname("cqi-ReportConfig-v1130"); cqi_report_cfg_v1130->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_ded_v1130_present != (pucch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_ded_v1130_present) { + if (pucch_cfg_ded_v1130.is_present()) { j.write_fieldname("pucch-ConfigDedicated-v1130"); pucch_cfg_ded_v1130->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1130_present != (pusch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1130_present) { + if (pusch_cfg_ded_v1130.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1130"); pusch_cfg_ded_v1130->to_json(j); } - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1130_present != (ul_pwr_ctrl_ded_v1130.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_ded_v1130_present) { + if (ul_pwr_ctrl_ded_v1130.is_present()) { j.write_fieldname("uplinkPowerControlDedicated-v1130"); ul_pwr_ctrl_ded_v1130->to_json(j); } - rrc_asn1_warn_assert(ant_info_v1250_present != (ant_info_v1250.get() != NULL), __FILE__, __LINE__); - if (ant_info_v1250_present) { + if (ant_info_v1250.is_present()) { j.write_fieldname("antennaInfo-v1250"); ant_info_v1250->to_json(j); } - rrc_asn1_warn_assert(eimta_main_cfg_r12_present != (eimta_main_cfg_r12.get() != NULL), __FILE__, __LINE__); - if (eimta_main_cfg_r12_present) { + if (eimta_main_cfg_r12.is_present()) { j.write_fieldname("eimta-MainConfig-r12"); eimta_main_cfg_r12->to_json(j); } - rrc_asn1_warn_assert( - eimta_main_cfg_pcell_r12_present != (eimta_main_cfg_pcell_r12.get() != NULL), __FILE__, __LINE__); - if (eimta_main_cfg_pcell_r12_present) { + if (eimta_main_cfg_pcell_r12.is_present()) { j.write_fieldname("eimta-MainConfigPCell-r12"); eimta_main_cfg_pcell_r12->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_ded_v1250_present != (pucch_cfg_ded_v1250.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_ded_v1250_present) { + if (pucch_cfg_ded_v1250.is_present()) { j.write_fieldname("pucch-ConfigDedicated-v1250"); pucch_cfg_ded_v1250->to_json(j); } - rrc_asn1_warn_assert( - cqi_report_cfg_pcell_v1250_present != (cqi_report_cfg_pcell_v1250.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_pcell_v1250_present) { + if (cqi_report_cfg_pcell_v1250.is_present()) { j.write_fieldname("cqi-ReportConfigPCell-v1250"); cqi_report_cfg_pcell_v1250->to_json(j); } - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1250_present != (ul_pwr_ctrl_ded_v1250.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_ded_v1250_present) { + if (ul_pwr_ctrl_ded_v1250.is_present()) { j.write_fieldname("uplinkPowerControlDedicated-v1250"); ul_pwr_ctrl_ded_v1250->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1250_present != (pusch_cfg_ded_v1250.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1250_present) { + if (pusch_cfg_ded_v1250.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1250"); pusch_cfg_ded_v1250->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1250_present != (csi_rs_cfg_v1250.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1250_present) { + if (csi_rs_cfg_v1250.is_present()) { j.write_fieldname("csi-RS-Config-v1250"); csi_rs_cfg_v1250->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1280_present != (pdsch_cfg_ded_v1280.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1280_present) { + if (pdsch_cfg_ded_v1280.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1280"); pdsch_cfg_ded_v1280->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1310_present != (pdsch_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1310_present) { + if (pdsch_cfg_ded_v1310.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1310"); pdsch_cfg_ded_v1310->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_ded_r13_present != (pucch_cfg_ded_r13.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_ded_r13_present) { + if (pucch_cfg_ded_r13.is_present()) { j.write_fieldname("pucch-ConfigDedicated-r13"); pucch_cfg_ded_r13->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_r13_present != (pusch_cfg_ded_r13.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_r13_present) { + if (pusch_cfg_ded_r13.is_present()) { j.write_fieldname("pusch-ConfigDedicated-r13"); pusch_cfg_ded_r13->to_json(j); } - rrc_asn1_warn_assert( - pdcch_candidate_reductions_r13_present != (pdcch_candidate_reductions_r13.get() != NULL), __FILE__, __LINE__); - if (pdcch_candidate_reductions_r13_present) { + if (pdcch_candidate_reductions_r13.is_present()) { j.write_fieldname("pdcch-CandidateReductions-r13"); pdcch_candidate_reductions_r13->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1310_present != (cqi_report_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1310_present) { + if (cqi_report_cfg_v1310.is_present()) { j.write_fieldname("cqi-ReportConfig-v1310"); cqi_report_cfg_v1310->to_json(j); } - rrc_asn1_warn_assert(srs_ul_cfg_ded_v1310_present != (srs_ul_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_v1310_present) { + if (srs_ul_cfg_ded_v1310.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicated-v1310"); srs_ul_cfg_ded_v1310->to_json(j); } - rrc_asn1_warn_assert( - srs_ul_cfg_ded_up_pts_ext_r13_present != (srs_ul_cfg_ded_up_pts_ext_r13.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_up_pts_ext_r13.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicatedUpPTsExt-r13"); srs_ul_cfg_ded_up_pts_ext_r13->to_json(j); } - rrc_asn1_warn_assert( - srs_ul_cfg_ded_aperiodic_v1310_present != (srs_ul_cfg_ded_aperiodic_v1310.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_aperiodic_v1310_present) { + if (srs_ul_cfg_ded_aperiodic_v1310.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicatedAperiodic-v1310"); srs_ul_cfg_ded_aperiodic_v1310->to_json(j); } - rrc_asn1_warn_assert(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present != - (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13"); srs_ul_cfg_ded_aperiodic_up_pts_ext_r13->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1310_present != (csi_rs_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1310_present) { + if (csi_rs_cfg_v1310.is_present()) { j.write_fieldname("csi-RS-Config-v1310"); csi_rs_cfg_v1310->to_json(j); } - rrc_asn1_warn_assert(ce_mode_r13_present != (ce_mode_r13.get() != NULL), __FILE__, __LINE__); - if (ce_mode_r13_present) { + if (ce_mode_r13.is_present()) { j.write_fieldname("ce-Mode-r13"); ce_mode_r13->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present != - (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present()) { j.start_array("csi-RS-ConfigNZPToAddModListExt-r13"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_add_mod_list_ext_r13->size(); ++i1) { ((*csi_rs_cfg_nzp_to_add_mod_list_ext_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_ext_r13_present != - (csi_rs_cfg_nzp_to_release_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_release_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_release_list_ext_r13.is_present()) { j.start_array("csi-RS-ConfigNZPToReleaseListExt-r13"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_release_list_ext_r13->size(); ++i1) { j.write_int(((*csi_rs_cfg_nzp_to_release_list_ext_r13)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(cqi_report_cfg_v1320_present != (cqi_report_cfg_v1320.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1320_present) { + if (cqi_report_cfg_v1320.is_present()) { j.write_fieldname("cqi-ReportConfig-v1320"); cqi_report_cfg_v1320->to_json(j); } - rrc_asn1_warn_assert( - type_a_srs_tpc_pdcch_group_r14_present != (type_a_srs_tpc_pdcch_group_r14.get() != NULL), __FILE__, __LINE__); - if (type_a_srs_tpc_pdcch_group_r14_present) { + if (type_a_srs_tpc_pdcch_group_r14.is_present()) { j.write_fieldname("typeA-SRS-TPC-PDCCH-Group-r14"); type_a_srs_tpc_pdcch_group_r14->to_json(j); } - rrc_asn1_warn_assert(must_cfg_r14_present != (must_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (must_cfg_r14_present) { + if (must_cfg_r14.is_present()) { j.write_fieldname("must-Config-r14"); must_cfg_r14->to_json(j); } - rrc_asn1_warn_assert(pusch_enhance_cfg_r14_present != (pusch_enhance_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (pusch_enhance_cfg_r14_present) { + if (pusch_enhance_cfg_r14.is_present()) { j.write_fieldname("pusch-EnhancementsConfig-r14"); pusch_enhance_cfg_r14->to_json(j); } if (ce_pdsch_pusch_enhancement_cfg_r14_present) { j.write_str("ce-pdsch-pusch-EnhancementConfig-r14", "on"); } - rrc_asn1_warn_assert(ant_info_v1430_present != (ant_info_v1430.get() != NULL), __FILE__, __LINE__); - if (ant_info_v1430_present) { + if (ant_info_v1430.is_present()) { j.write_fieldname("antennaInfo-v1430"); ant_info_v1430->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_ded_v1430_present != (pucch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_ded_v1430_present) { + if (pucch_cfg_ded_v1430.is_present()) { j.write_fieldname("pucch-ConfigDedicated-v1430"); pucch_cfg_ded_v1430->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1430_present != (pdsch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1430_present) { + if (pdsch_cfg_ded_v1430.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1430"); pdsch_cfg_ded_v1430->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1430_present != (pusch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1430_present) { + if (pusch_cfg_ded_v1430.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1430"); pusch_cfg_ded_v1430->to_json(j); } - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_list_r14_present != (srs_ul_periodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_periodic_cfg_ded_list_r14_present) { + if (srs_ul_periodic_cfg_ded_list_r14.is_present()) { j.start_array("soundingRS-UL-PeriodicConfigDedicatedList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_periodic_cfg_ded_list_r14->size(); ++i1) { ((*srs_ul_periodic_cfg_ded_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present != - (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present) { + if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present()) { j.start_array("soundingRS-UL-PeriodicConfigDedicatedUpPTsExtList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_periodic_cfg_ded_up_pts_ext_list_r14->size(); ++i1) { ((*srs_ul_periodic_cfg_ded_up_pts_ext_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(srs_ul_aperiodic_cfg_ded_list_r14_present != (srs_ul_aperiodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_aperiodic_cfg_ded_list_r14_present) { + if (srs_ul_aperiodic_cfg_ded_list_r14.is_present()) { j.start_array("soundingRS-UL-AperiodicConfigDedicatedList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_aperiodic_cfg_ded_list_r14->size(); ++i1) { ((*srs_ul_aperiodic_cfg_ded_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present != - (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present) { + if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present()) { j.start_array("soundingRS-UL-ConfigDedicatedApUpPTsExtList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_cfg_ded_ap_up_pts_ext_list_r14->size(); ++i1) { ((*srs_ul_cfg_ded_ap_up_pts_ext_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_v1430_present != (csi_rs_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1430_present) { + if (csi_rs_cfg_v1430.is_present()) { j.write_fieldname("csi-RS-Config-v1430"); csi_rs_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert( - csi_rs_cfg_zp_ap_list_r14_present != (csi_rs_cfg_zp_ap_list_r14.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_zp_ap_list_r14_present) { + if (csi_rs_cfg_zp_ap_list_r14.is_present()) { j.write_fieldname("csi-RS-ConfigZP-ApList-r14"); csi_rs_cfg_zp_ap_list_r14->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1430_present != (cqi_report_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1430_present) { + if (cqi_report_cfg_v1430.is_present()) { j.write_fieldname("cqi-ReportConfig-v1430"); cqi_report_cfg_v1430->to_json(j); } if (semi_open_loop_r14_present) { j.write_bool("semiOpenLoop-r14", semi_open_loop_r14); } - rrc_asn1_warn_assert(csi_rs_cfg_v1480_present != (csi_rs_cfg_v1480.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1480_present) { + if (csi_rs_cfg_v1480.is_present()) { j.write_fieldname("csi-RS-Config-v1480"); csi_rs_cfg_v1480->to_json(j); } - rrc_asn1_warn_assert(phys_cfg_ded_stti_r15_present != (phys_cfg_ded_stti_r15.get() != NULL), __FILE__, __LINE__); - if (phys_cfg_ded_stti_r15_present) { + if (phys_cfg_ded_stti_r15.is_present()) { j.write_fieldname("physicalConfigDedicatedSTTI-r15"); phys_cfg_ded_stti_r15->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1530_present != (pdsch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1530_present) { + if (pdsch_cfg_ded_v1530.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1530"); pdsch_cfg_ded_v1530->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1530_present != (pusch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1530_present) { + if (pusch_cfg_ded_v1530.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1530"); pusch_cfg_ded_v1530->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1530_present != (cqi_report_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1530_present) { + if (cqi_report_cfg_v1530.is_present()) { j.write_fieldname("cqi-ReportConfig-v1530"); cqi_report_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert(ant_info_v1530_present != (ant_info_v1530.get() != NULL), __FILE__, __LINE__); - if (ant_info_v1530_present) { + if (ant_info_v1530.is_present()) { j.write_fieldname("antennaInfo-v1530"); ant_info_v1530->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1530_present != (csi_rs_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1530_present) { + if (csi_rs_cfg_v1530.is_present()) { j.write_fieldname("csi-RS-Config-v1530"); csi_rs_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert(ul_pwr_ctrl_ded_v1530_present != (ul_pwr_ctrl_ded_v1530.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_ded_v1530_present) { + if (ul_pwr_ctrl_ded_v1530.is_present()) { j.write_fieldname("uplinkPowerControlDedicated-v1530"); ul_pwr_ctrl_ded_v1530->to_json(j); } - rrc_asn1_warn_assert( - semi_static_cfi_cfg_r15_present != (semi_static_cfi_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (semi_static_cfi_cfg_r15_present) { + if (semi_static_cfi_cfg_r15.is_present()) { j.write_fieldname("semiStaticCFI-Config-r15"); semi_static_cfi_cfg_r15->to_json(j); } - rrc_asn1_warn_assert( - blind_pdsch_repeat_cfg_r15_present != (blind_pdsch_repeat_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (blind_pdsch_repeat_cfg_r15_present) { + if (blind_pdsch_repeat_cfg_r15.is_present()) { j.write_fieldname("blindPDSCH-Repetition-Config-r15"); blind_pdsch_repeat_cfg_r15->to_json(j); } @@ -43820,12 +43316,12 @@ SRSASN_CODE rlf_timers_and_consts_r13_c::setup_s_::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, t301_v1310)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= t310_v1330_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(t310_v1330_present, 1)); if (t310_v1330_present) { @@ -43841,11 +43337,11 @@ SRSASN_CODE rlf_timers_and_consts_r13_c::setup_s_::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(t301_v1310, bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(t310_v1330_present, 1)); if (t310_v1330_present) { @@ -44272,45 +43768,38 @@ SRSASN_CODE idle_mode_mob_ctrl_info_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); - rrc_asn1_warn_assert( - freq_prio_list_ext_eutra_r12_present != (freq_prio_list_ext_eutra_r12.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= freq_prio_list_ext_eutra_r12_present; - rrc_asn1_warn_assert( - freq_prio_list_eutra_v1310_present != (freq_prio_list_eutra_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= freq_prio_list_eutra_v1310_present; - rrc_asn1_warn_assert( - freq_prio_list_ext_eutra_v1310_present != (freq_prio_list_ext_eutra_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= freq_prio_list_ext_eutra_v1310_present; - rrc_asn1_warn_assert(freq_prio_list_nr_r15_present != (freq_prio_list_nr_r15.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= freq_prio_list_nr_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= freq_prio_list_ext_eutra_r12.is_present(); + group_flags[1] |= freq_prio_list_eutra_v1310.is_present(); + group_flags[1] |= freq_prio_list_ext_eutra_v1310.is_present(); + group_flags[2] |= freq_prio_list_nr_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(freq_prio_list_ext_eutra_r12_present, 1)); - if (freq_prio_list_ext_eutra_r12_present) { + HANDLE_CODE(bref.pack(freq_prio_list_ext_eutra_r12.is_present(), 1)); + if (freq_prio_list_ext_eutra_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *freq_prio_list_ext_eutra_r12, 1, 8)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(freq_prio_list_eutra_v1310_present, 1)); - HANDLE_CODE(bref.pack(freq_prio_list_ext_eutra_v1310_present, 1)); - if (freq_prio_list_eutra_v1310_present) { + HANDLE_CODE(bref.pack(freq_prio_list_eutra_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(freq_prio_list_ext_eutra_v1310.is_present(), 1)); + if (freq_prio_list_eutra_v1310.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *freq_prio_list_eutra_v1310, 1, 8)); } - if (freq_prio_list_ext_eutra_v1310_present) { + if (freq_prio_list_ext_eutra_v1310.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *freq_prio_list_ext_eutra_v1310, 1, 8)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(freq_prio_list_nr_r15_present, 1)); - if (freq_prio_list_nr_r15_present) { + HANDLE_CODE(bref.pack(freq_prio_list_nr_r15.is_present(), 1)); + if (freq_prio_list_nr_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *freq_prio_list_nr_r15, 1, 8)); } } @@ -44351,38 +43840,42 @@ SRSASN_CODE idle_mode_mob_ctrl_info_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool freq_prio_list_ext_eutra_r12_present; HANDLE_CODE(bref.unpack(freq_prio_list_ext_eutra_r12_present, 1)); - if (freq_prio_list_ext_eutra_r12_present) { - freq_prio_list_ext_eutra_r12 = make_copy_ptr(freq_prio_list_ext_eutra_r12_l()); + freq_prio_list_ext_eutra_r12.set_present(freq_prio_list_ext_eutra_r12_present); + if (freq_prio_list_ext_eutra_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*freq_prio_list_ext_eutra_r12, bref, 1, 8)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool freq_prio_list_eutra_v1310_present; HANDLE_CODE(bref.unpack(freq_prio_list_eutra_v1310_present, 1)); + freq_prio_list_eutra_v1310.set_present(freq_prio_list_eutra_v1310_present); + bool freq_prio_list_ext_eutra_v1310_present; HANDLE_CODE(bref.unpack(freq_prio_list_ext_eutra_v1310_present, 1)); - if (freq_prio_list_eutra_v1310_present) { - freq_prio_list_eutra_v1310 = make_copy_ptr(freq_prio_list_eutra_v1310_l()); + freq_prio_list_ext_eutra_v1310.set_present(freq_prio_list_ext_eutra_v1310_present); + if (freq_prio_list_eutra_v1310.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*freq_prio_list_eutra_v1310, bref, 1, 8)); } - if (freq_prio_list_ext_eutra_v1310_present) { - freq_prio_list_ext_eutra_v1310 = make_copy_ptr(freq_prio_list_ext_eutra_v1310_l()); + if (freq_prio_list_ext_eutra_v1310.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*freq_prio_list_ext_eutra_v1310, bref, 1, 8)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool freq_prio_list_nr_r15_present; HANDLE_CODE(bref.unpack(freq_prio_list_nr_r15_present, 1)); - if (freq_prio_list_nr_r15_present) { - freq_prio_list_nr_r15 = make_copy_ptr(freq_prio_list_nr_r15_l()); + freq_prio_list_nr_r15.set_present(freq_prio_list_nr_r15_present); + if (freq_prio_list_nr_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*freq_prio_list_nr_r15, bref, 1, 8)); } } @@ -44438,35 +43931,28 @@ void idle_mode_mob_ctrl_info_s::to_json(json_writer& j) const j.write_str("t320", t320.to_string()); } if (ext) { - rrc_asn1_warn_assert( - freq_prio_list_ext_eutra_r12_present != (freq_prio_list_ext_eutra_r12.get() != NULL), __FILE__, __LINE__); - if (freq_prio_list_ext_eutra_r12_present) { + if (freq_prio_list_ext_eutra_r12.is_present()) { j.start_array("freqPriorityListExtEUTRA-r12"); for (uint32_t i1 = 0; i1 < freq_prio_list_ext_eutra_r12->size(); ++i1) { ((*freq_prio_list_ext_eutra_r12)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - freq_prio_list_eutra_v1310_present != (freq_prio_list_eutra_v1310.get() != NULL), __FILE__, __LINE__); - if (freq_prio_list_eutra_v1310_present) { + if (freq_prio_list_eutra_v1310.is_present()) { j.start_array("freqPriorityListEUTRA-v1310"); for (uint32_t i1 = 0; i1 < freq_prio_list_eutra_v1310->size(); ++i1) { ((*freq_prio_list_eutra_v1310)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - freq_prio_list_ext_eutra_v1310_present != (freq_prio_list_ext_eutra_v1310.get() != NULL), __FILE__, __LINE__); - if (freq_prio_list_ext_eutra_v1310_present) { + if (freq_prio_list_ext_eutra_v1310.is_present()) { j.start_array("freqPriorityListExtEUTRA-v1310"); for (uint32_t i1 = 0; i1 < freq_prio_list_ext_eutra_v1310->size(); ++i1) { ((*freq_prio_list_ext_eutra_v1310)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(freq_prio_list_nr_r15_present != (freq_prio_list_nr_r15.get() != NULL), __FILE__, __LINE__); - if (freq_prio_list_nr_r15_present) { + if (freq_prio_list_nr_r15.is_present()) { j.start_array("freqPriorityListNR-r15"); for (uint32_t i1 = 0; i1 < freq_prio_list_nr_r15->size(); ++i1) { ((*freq_prio_list_nr_r15)[i1]).to_json(j); @@ -44685,133 +44171,109 @@ SRSASN_CODE rr_cfg_ded_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(7); - rrc_asn1_warn_assert( - rlf_timers_and_consts_r9_present != (rlf_timers_and_consts_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rlf_timers_and_consts_r9_present; - rrc_asn1_warn_assert( - meas_sf_pattern_pcell_r10_present != (meas_sf_pattern_pcell_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= meas_sf_pattern_pcell_r10_present; - rrc_asn1_warn_assert( - neigh_cells_crs_info_r11_present != (neigh_cells_crs_info_r11.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= neigh_cells_crs_info_r11_present; - rrc_asn1_warn_assert(naics_info_r12_present != (naics_info_r12.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= naics_info_r12_present; - rrc_asn1_warn_assert( - neigh_cells_crs_info_r13_present != (neigh_cells_crs_info_r13.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= neigh_cells_crs_info_r13_present; - rrc_asn1_warn_assert( - rlf_timers_and_consts_r13_present != (rlf_timers_and_consts_r13.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= rlf_timers_and_consts_r13_present; - rrc_asn1_warn_assert(sps_cfg_v1430_present != (sps_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= sps_cfg_v1430_present; - rrc_asn1_warn_assert( - srb_to_add_mod_ext_list_r15_present != (srb_to_add_mod_ext_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= srb_to_add_mod_ext_list_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= rlf_timers_and_consts_r9.is_present(); + group_flags[1] |= meas_sf_pattern_pcell_r10.is_present(); + group_flags[2] |= neigh_cells_crs_info_r11.is_present(); + group_flags[3] |= naics_info_r12.is_present(); + group_flags[4] |= neigh_cells_crs_info_r13.is_present(); + group_flags[4] |= rlf_timers_and_consts_r13.is_present(); + group_flags[5] |= sps_cfg_v1430.is_present(); + group_flags[6] |= srb_to_add_mod_ext_list_r15.is_present(); group_flags[6] |= srb_to_release_ext_list_r15_present; - rrc_asn1_warn_assert(sps_cfg_v1530_present != (sps_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= sps_cfg_v1530_present; - rrc_asn1_warn_assert(crs_intf_mitig_cfg_r15_present != (crs_intf_mitig_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= crs_intf_mitig_cfg_r15_present; - rrc_asn1_warn_assert( - neigh_cells_crs_info_r15_present != (neigh_cells_crs_info_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= neigh_cells_crs_info_r15_present; - rrc_asn1_warn_assert( - drb_to_add_mod_list_r15_present != (drb_to_add_mod_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= drb_to_add_mod_list_r15_present; - rrc_asn1_warn_assert( - drb_to_release_list_r15_present != (drb_to_release_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= drb_to_release_list_r15_present; - rrc_asn1_warn_assert( - srb_to_release_list_dupl_r15_present != (srb_to_release_list_dupl_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= srb_to_release_list_dupl_r15_present; + group_flags[6] |= sps_cfg_v1530.is_present(); + group_flags[6] |= crs_intf_mitig_cfg_r15.is_present(); + group_flags[6] |= neigh_cells_crs_info_r15.is_present(); + group_flags[6] |= drb_to_add_mod_list_r15.is_present(); + group_flags[6] |= drb_to_release_list_r15.is_present(); + group_flags[6] |= srb_to_release_list_dupl_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rlf_timers_and_consts_r9_present, 1)); - if (rlf_timers_and_consts_r9_present) { + HANDLE_CODE(bref.pack(rlf_timers_and_consts_r9.is_present(), 1)); + if (rlf_timers_and_consts_r9.is_present()) { HANDLE_CODE(rlf_timers_and_consts_r9->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_sf_pattern_pcell_r10_present, 1)); - if (meas_sf_pattern_pcell_r10_present) { + HANDLE_CODE(bref.pack(meas_sf_pattern_pcell_r10.is_present(), 1)); + if (meas_sf_pattern_pcell_r10.is_present()) { HANDLE_CODE(meas_sf_pattern_pcell_r10->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(neigh_cells_crs_info_r11_present, 1)); - if (neigh_cells_crs_info_r11_present) { + HANDLE_CODE(bref.pack(neigh_cells_crs_info_r11.is_present(), 1)); + if (neigh_cells_crs_info_r11.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r11->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(naics_info_r12_present, 1)); - if (naics_info_r12_present) { + HANDLE_CODE(bref.pack(naics_info_r12.is_present(), 1)); + if (naics_info_r12.is_present()) { HANDLE_CODE(naics_info_r12->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(neigh_cells_crs_info_r13_present, 1)); - HANDLE_CODE(bref.pack(rlf_timers_and_consts_r13_present, 1)); - if (neigh_cells_crs_info_r13_present) { + HANDLE_CODE(bref.pack(neigh_cells_crs_info_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(rlf_timers_and_consts_r13.is_present(), 1)); + if (neigh_cells_crs_info_r13.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r13->pack(bref)); } - if (rlf_timers_and_consts_r13_present) { + if (rlf_timers_and_consts_r13.is_present()) { HANDLE_CODE(rlf_timers_and_consts_r13->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(sps_cfg_v1430_present, 1)); - if (sps_cfg_v1430_present) { + HANDLE_CODE(bref.pack(sps_cfg_v1430.is_present(), 1)); + if (sps_cfg_v1430.is_present()) { HANDLE_CODE(sps_cfg_v1430->pack(bref)); } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(srb_to_add_mod_ext_list_r15_present, 1)); + HANDLE_CODE(bref.pack(srb_to_add_mod_ext_list_r15.is_present(), 1)); HANDLE_CODE(bref.pack(srb_to_release_ext_list_r15_present, 1)); - HANDLE_CODE(bref.pack(sps_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(crs_intf_mitig_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(neigh_cells_crs_info_r15_present, 1)); - HANDLE_CODE(bref.pack(drb_to_add_mod_list_r15_present, 1)); - HANDLE_CODE(bref.pack(drb_to_release_list_r15_present, 1)); - HANDLE_CODE(bref.pack(srb_to_release_list_dupl_r15_present, 1)); - if (srb_to_add_mod_ext_list_r15_present) { + HANDLE_CODE(bref.pack(sps_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(crs_intf_mitig_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(neigh_cells_crs_info_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(drb_to_add_mod_list_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(drb_to_release_list_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(srb_to_release_list_dupl_r15.is_present(), 1)); + if (srb_to_add_mod_ext_list_r15.is_present()) { HANDLE_CODE(pack_fixed_seq_of(bref, &(*srb_to_add_mod_ext_list_r15)[0], srb_to_add_mod_ext_list_r15->size())); } if (srb_to_release_ext_list_r15_present) { HANDLE_CODE(pack_unalign_integer(bref, srb_to_release_ext_list_r15, (uint8_t)4, (uint8_t)4)); } - if (sps_cfg_v1530_present) { + if (sps_cfg_v1530.is_present()) { HANDLE_CODE(sps_cfg_v1530->pack(bref)); } - if (crs_intf_mitig_cfg_r15_present) { + if (crs_intf_mitig_cfg_r15.is_present()) { HANDLE_CODE(crs_intf_mitig_cfg_r15->pack(bref)); } - if (neigh_cells_crs_info_r15_present) { + if (neigh_cells_crs_info_r15.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r15->pack(bref)); } - if (drb_to_add_mod_list_r15_present) { + if (drb_to_add_mod_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *drb_to_add_mod_list_r15, 1, 15)); } - if (drb_to_release_list_r15_present) { + if (drb_to_release_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *drb_to_release_list_r15, 1, 15, UnalignedIntegerPacker(1, 32))); } - if (srb_to_release_list_dupl_r15_present) { + if (srb_to_release_list_dupl_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srb_to_release_list_dupl_r15, 1, 2, UnalignedIntegerPacker(1, 2))); } } @@ -44848,108 +44310,122 @@ SRSASN_CODE rr_cfg_ded_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(7); + ext_groups_unpacker_guard group_flags(7); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rlf_timers_and_consts_r9_present; HANDLE_CODE(bref.unpack(rlf_timers_and_consts_r9_present, 1)); - if (rlf_timers_and_consts_r9_present) { - rlf_timers_and_consts_r9 = make_copy_ptr(rlf_timers_and_consts_r9_c()); + rlf_timers_and_consts_r9.set_present(rlf_timers_and_consts_r9_present); + if (rlf_timers_and_consts_r9.is_present()) { HANDLE_CODE(rlf_timers_and_consts_r9->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_sf_pattern_pcell_r10_present; HANDLE_CODE(bref.unpack(meas_sf_pattern_pcell_r10_present, 1)); - if (meas_sf_pattern_pcell_r10_present) { - meas_sf_pattern_pcell_r10 = make_copy_ptr(meas_sf_pattern_pcell_r10_c()); + meas_sf_pattern_pcell_r10.set_present(meas_sf_pattern_pcell_r10_present); + if (meas_sf_pattern_pcell_r10.is_present()) { HANDLE_CODE(meas_sf_pattern_pcell_r10->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool neigh_cells_crs_info_r11_present; HANDLE_CODE(bref.unpack(neigh_cells_crs_info_r11_present, 1)); - if (neigh_cells_crs_info_r11_present) { - neigh_cells_crs_info_r11 = make_copy_ptr(neigh_cells_crs_info_r11_c()); + neigh_cells_crs_info_r11.set_present(neigh_cells_crs_info_r11_present); + if (neigh_cells_crs_info_r11.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r11->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool naics_info_r12_present; HANDLE_CODE(bref.unpack(naics_info_r12_present, 1)); - if (naics_info_r12_present) { - naics_info_r12 = make_copy_ptr(naics_assist_info_r12_c()); + naics_info_r12.set_present(naics_info_r12_present); + if (naics_info_r12.is_present()) { HANDLE_CODE(naics_info_r12->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool neigh_cells_crs_info_r13_present; HANDLE_CODE(bref.unpack(neigh_cells_crs_info_r13_present, 1)); + neigh_cells_crs_info_r13.set_present(neigh_cells_crs_info_r13_present); + bool rlf_timers_and_consts_r13_present; HANDLE_CODE(bref.unpack(rlf_timers_and_consts_r13_present, 1)); - if (neigh_cells_crs_info_r13_present) { - neigh_cells_crs_info_r13 = make_copy_ptr(neigh_cells_crs_info_r13_c()); + rlf_timers_and_consts_r13.set_present(rlf_timers_and_consts_r13_present); + if (neigh_cells_crs_info_r13.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r13->unpack(bref)); } - if (rlf_timers_and_consts_r13_present) { - rlf_timers_and_consts_r13 = make_copy_ptr(rlf_timers_and_consts_r13_c()); + if (rlf_timers_and_consts_r13.is_present()) { HANDLE_CODE(rlf_timers_and_consts_r13->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool sps_cfg_v1430_present; HANDLE_CODE(bref.unpack(sps_cfg_v1430_present, 1)); - if (sps_cfg_v1430_present) { - sps_cfg_v1430 = make_copy_ptr(sps_cfg_v1430_s()); + sps_cfg_v1430.set_present(sps_cfg_v1430_present); + if (sps_cfg_v1430.is_present()) { HANDLE_CODE(sps_cfg_v1430->unpack(bref)); } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool srb_to_add_mod_ext_list_r15_present; HANDLE_CODE(bref.unpack(srb_to_add_mod_ext_list_r15_present, 1)); + srb_to_add_mod_ext_list_r15.set_present(srb_to_add_mod_ext_list_r15_present); HANDLE_CODE(bref.unpack(srb_to_release_ext_list_r15_present, 1)); + bool sps_cfg_v1530_present; HANDLE_CODE(bref.unpack(sps_cfg_v1530_present, 1)); + sps_cfg_v1530.set_present(sps_cfg_v1530_present); + bool crs_intf_mitig_cfg_r15_present; HANDLE_CODE(bref.unpack(crs_intf_mitig_cfg_r15_present, 1)); + crs_intf_mitig_cfg_r15.set_present(crs_intf_mitig_cfg_r15_present); + bool neigh_cells_crs_info_r15_present; HANDLE_CODE(bref.unpack(neigh_cells_crs_info_r15_present, 1)); + neigh_cells_crs_info_r15.set_present(neigh_cells_crs_info_r15_present); + bool drb_to_add_mod_list_r15_present; HANDLE_CODE(bref.unpack(drb_to_add_mod_list_r15_present, 1)); + drb_to_add_mod_list_r15.set_present(drb_to_add_mod_list_r15_present); + bool drb_to_release_list_r15_present; HANDLE_CODE(bref.unpack(drb_to_release_list_r15_present, 1)); + drb_to_release_list_r15.set_present(drb_to_release_list_r15_present); + bool srb_to_release_list_dupl_r15_present; HANDLE_CODE(bref.unpack(srb_to_release_list_dupl_r15_present, 1)); - if (srb_to_add_mod_ext_list_r15_present) { - srb_to_add_mod_ext_list_r15 = make_copy_ptr(srb_to_add_mod_ext_list_r15_l()); + srb_to_release_list_dupl_r15.set_present(srb_to_release_list_dupl_r15_present); + if (srb_to_add_mod_ext_list_r15.is_present()) { HANDLE_CODE(unpack_fixed_seq_of(&(*srb_to_add_mod_ext_list_r15)[0], bref, srb_to_add_mod_ext_list_r15->size())); } if (srb_to_release_ext_list_r15_present) { HANDLE_CODE(unpack_unalign_integer(srb_to_release_ext_list_r15, bref, (uint8_t)4, (uint8_t)4)); } - if (sps_cfg_v1530_present) { - sps_cfg_v1530 = make_copy_ptr(sps_cfg_v1530_s()); + if (sps_cfg_v1530.is_present()) { HANDLE_CODE(sps_cfg_v1530->unpack(bref)); } - if (crs_intf_mitig_cfg_r15_present) { - crs_intf_mitig_cfg_r15 = make_copy_ptr(crs_intf_mitig_cfg_r15_c_()); + if (crs_intf_mitig_cfg_r15.is_present()) { HANDLE_CODE(crs_intf_mitig_cfg_r15->unpack(bref)); } - if (neigh_cells_crs_info_r15_present) { - neigh_cells_crs_info_r15 = make_copy_ptr(neigh_cells_crs_info_r15_c()); + if (neigh_cells_crs_info_r15.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r15->unpack(bref)); } - if (drb_to_add_mod_list_r15_present) { - drb_to_add_mod_list_r15 = make_copy_ptr(drb_to_add_mod_list_r15_l()); + if (drb_to_add_mod_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*drb_to_add_mod_list_r15, bref, 1, 15)); } - if (drb_to_release_list_r15_present) { - drb_to_release_list_r15 = make_copy_ptr(drb_to_release_list_r15_l()); + if (drb_to_release_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*drb_to_release_list_r15, bref, 1, 15, UnalignedIntegerPacker(1, 32))); } - if (srb_to_release_list_dupl_r15_present) { - srb_to_release_list_dupl_r15 = make_copy_ptr(srb_to_release_list_dupl_r15_l()); + if (srb_to_release_list_dupl_r15.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*srb_to_release_list_dupl_r15, bref, 1, 2, UnalignedIntegerPacker(1, 2))); } @@ -44994,49 +44470,35 @@ void rr_cfg_ded_s::to_json(json_writer& j) const phys_cfg_ded.to_json(j); } if (ext) { - rrc_asn1_warn_assert( - rlf_timers_and_consts_r9_present != (rlf_timers_and_consts_r9.get() != NULL), __FILE__, __LINE__); - if (rlf_timers_and_consts_r9_present) { + if (rlf_timers_and_consts_r9.is_present()) { j.write_fieldname("rlf-TimersAndConstants-r9"); rlf_timers_and_consts_r9->to_json(j); } - rrc_asn1_warn_assert( - meas_sf_pattern_pcell_r10_present != (meas_sf_pattern_pcell_r10.get() != NULL), __FILE__, __LINE__); - if (meas_sf_pattern_pcell_r10_present) { + if (meas_sf_pattern_pcell_r10.is_present()) { j.write_fieldname("measSubframePatternPCell-r10"); meas_sf_pattern_pcell_r10->to_json(j); } - rrc_asn1_warn_assert( - neigh_cells_crs_info_r11_present != (neigh_cells_crs_info_r11.get() != NULL), __FILE__, __LINE__); - if (neigh_cells_crs_info_r11_present) { + if (neigh_cells_crs_info_r11.is_present()) { j.write_fieldname("neighCellsCRS-Info-r11"); neigh_cells_crs_info_r11->to_json(j); } - rrc_asn1_warn_assert(naics_info_r12_present != (naics_info_r12.get() != NULL), __FILE__, __LINE__); - if (naics_info_r12_present) { + if (naics_info_r12.is_present()) { j.write_fieldname("naics-Info-r12"); naics_info_r12->to_json(j); } - rrc_asn1_warn_assert( - neigh_cells_crs_info_r13_present != (neigh_cells_crs_info_r13.get() != NULL), __FILE__, __LINE__); - if (neigh_cells_crs_info_r13_present) { + if (neigh_cells_crs_info_r13.is_present()) { j.write_fieldname("neighCellsCRS-Info-r13"); neigh_cells_crs_info_r13->to_json(j); } - rrc_asn1_warn_assert( - rlf_timers_and_consts_r13_present != (rlf_timers_and_consts_r13.get() != NULL), __FILE__, __LINE__); - if (rlf_timers_and_consts_r13_present) { + if (rlf_timers_and_consts_r13.is_present()) { j.write_fieldname("rlf-TimersAndConstants-r13"); rlf_timers_and_consts_r13->to_json(j); } - rrc_asn1_warn_assert(sps_cfg_v1430_present != (sps_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (sps_cfg_v1430_present) { + if (sps_cfg_v1430.is_present()) { j.write_fieldname("sps-Config-v1430"); sps_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert( - srb_to_add_mod_ext_list_r15_present != (srb_to_add_mod_ext_list_r15.get() != NULL), __FILE__, __LINE__); - if (srb_to_add_mod_ext_list_r15_present) { + if (srb_to_add_mod_ext_list_r15.is_present()) { j.start_array("srb-ToAddModExtList-r15"); for (uint32_t i1 = 0; i1 < srb_to_add_mod_ext_list_r15->size(); ++i1) { ((*srb_to_add_mod_ext_list_r15)[i1]).to_json(j); @@ -45046,43 +44508,33 @@ void rr_cfg_ded_s::to_json(json_writer& j) const if (srb_to_release_ext_list_r15_present) { j.write_int("srb-ToReleaseExtList-r15", srb_to_release_ext_list_r15); } - rrc_asn1_warn_assert(sps_cfg_v1530_present != (sps_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (sps_cfg_v1530_present) { + if (sps_cfg_v1530.is_present()) { j.write_fieldname("sps-Config-v1530"); sps_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert(crs_intf_mitig_cfg_r15_present != (crs_intf_mitig_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (crs_intf_mitig_cfg_r15_present) { + if (crs_intf_mitig_cfg_r15.is_present()) { j.write_fieldname("crs-IntfMitigConfig-r15"); crs_intf_mitig_cfg_r15->to_json(j); } - rrc_asn1_warn_assert( - neigh_cells_crs_info_r15_present != (neigh_cells_crs_info_r15.get() != NULL), __FILE__, __LINE__); - if (neigh_cells_crs_info_r15_present) { + if (neigh_cells_crs_info_r15.is_present()) { j.write_fieldname("neighCellsCRS-Info-r15"); neigh_cells_crs_info_r15->to_json(j); } - rrc_asn1_warn_assert( - drb_to_add_mod_list_r15_present != (drb_to_add_mod_list_r15.get() != NULL), __FILE__, __LINE__); - if (drb_to_add_mod_list_r15_present) { + if (drb_to_add_mod_list_r15.is_present()) { j.start_array("drb-ToAddModList-r15"); for (uint32_t i1 = 0; i1 < drb_to_add_mod_list_r15->size(); ++i1) { ((*drb_to_add_mod_list_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - drb_to_release_list_r15_present != (drb_to_release_list_r15.get() != NULL), __FILE__, __LINE__); - if (drb_to_release_list_r15_present) { + if (drb_to_release_list_r15.is_present()) { j.start_array("drb-ToReleaseList-r15"); for (uint32_t i1 = 0; i1 < drb_to_release_list_r15->size(); ++i1) { j.write_int(((*drb_to_release_list_r15)[i1])); } j.end_array(); } - rrc_asn1_warn_assert( - srb_to_release_list_dupl_r15_present != (srb_to_release_list_dupl_r15.get() != NULL), __FILE__, __LINE__); - if (srb_to_release_list_dupl_r15_present) { + if (srb_to_release_list_dupl_r15.is_present()) { j.start_array("srb-ToReleaseListDupl-r15"); for (uint32_t i1 = 0; i1 < srb_to_release_list_dupl_r15->size(); ++i1) { j.write_int(((*srb_to_release_list_dupl_r15)[i1])); @@ -49544,418 +48996,318 @@ SRSASN_CODE phys_cfg_ded_scell_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(8); - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_r11_present != - (csi_rs_cfg_nzp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= csi_rs_cfg_nzp_to_release_list_r11_present; - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_r11_present != - (csi_rs_cfg_nzp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= csi_rs_cfg_nzp_to_add_mod_list_r11_present; - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_release_list_r11_present != (csi_rs_cfg_zp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= csi_rs_cfg_zp_to_release_list_r11_present; - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_add_mod_list_r11_present != (csi_rs_cfg_zp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= csi_rs_cfg_zp_to_add_mod_list_r11_present; - rrc_asn1_warn_assert(epdcch_cfg_r11_present != (epdcch_cfg_r11.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= epdcch_cfg_r11_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1130_present != (pdsch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= pdsch_cfg_ded_v1130_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1130_present != (cqi_report_cfg_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cqi_report_cfg_v1130_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1130_present != (pusch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= pusch_cfg_ded_v1130_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_ded_scell_v1130_present != (ul_pwr_ctrl_ded_scell_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ul_pwr_ctrl_ded_scell_v1130_present; - rrc_asn1_warn_assert(ant_info_v1250_present != (ant_info_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ant_info_v1250_present; - rrc_asn1_warn_assert( - eimta_main_cfg_scell_r12_present != (eimta_main_cfg_scell_r12.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= eimta_main_cfg_scell_r12_present; - rrc_asn1_warn_assert( - cqi_report_cfg_scell_v1250_present != (cqi_report_cfg_scell_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= cqi_report_cfg_scell_v1250_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_ded_scell_v1250_present != (ul_pwr_ctrl_ded_scell_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ul_pwr_ctrl_ded_scell_v1250_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1250_present != (csi_rs_cfg_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= csi_rs_cfg_v1250_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1280_present != (pdsch_cfg_ded_v1280.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= pdsch_cfg_ded_v1280_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= csi_rs_cfg_nzp_to_release_list_r11.is_present(); + group_flags[0] |= csi_rs_cfg_nzp_to_add_mod_list_r11.is_present(); + group_flags[0] |= csi_rs_cfg_zp_to_release_list_r11.is_present(); + group_flags[0] |= csi_rs_cfg_zp_to_add_mod_list_r11.is_present(); + group_flags[0] |= epdcch_cfg_r11.is_present(); + group_flags[0] |= pdsch_cfg_ded_v1130.is_present(); + group_flags[0] |= cqi_report_cfg_v1130.is_present(); + group_flags[0] |= pusch_cfg_ded_v1130.is_present(); + group_flags[0] |= ul_pwr_ctrl_ded_scell_v1130.is_present(); + group_flags[1] |= ant_info_v1250.is_present(); + group_flags[1] |= eimta_main_cfg_scell_r12.is_present(); + group_flags[1] |= cqi_report_cfg_scell_v1250.is_present(); + group_flags[1] |= ul_pwr_ctrl_ded_scell_v1250.is_present(); + group_flags[1] |= csi_rs_cfg_v1250.is_present(); + group_flags[2] |= pdsch_cfg_ded_v1280.is_present(); group_flags[3] |= pucch_cell_r13_present; - rrc_asn1_warn_assert(pucch_scell_present != (pucch_scell.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pucch_scell_present; - rrc_asn1_warn_assert( - cross_carrier_sched_cfg_r13_present != (cross_carrier_sched_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= cross_carrier_sched_cfg_r13_present; - rrc_asn1_warn_assert(pdcch_cfg_scell_r13_present != (pdcch_cfg_scell_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pdcch_cfg_scell_r13_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1310_present != (cqi_report_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= cqi_report_cfg_v1310_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1310_present != (pdsch_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pdsch_cfg_ded_v1310_present; - rrc_asn1_warn_assert(srs_ul_cfg_ded_v1310_present != (srs_ul_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= srs_ul_cfg_ded_v1310_present; - rrc_asn1_warn_assert( - srs_ul_cfg_ded_up_pts_ext_r13_present != (srs_ul_cfg_ded_up_pts_ext_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= srs_ul_cfg_ded_up_pts_ext_r13_present; - rrc_asn1_warn_assert( - srs_ul_cfg_ded_aperiodic_v1310_present != (srs_ul_cfg_ded_aperiodic_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= srs_ul_cfg_ded_aperiodic_v1310_present; - rrc_asn1_warn_assert(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present != - (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1310_present != (csi_rs_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= csi_rs_cfg_v1310_present; - rrc_asn1_warn_assert(laa_scell_cfg_r13_present != (laa_scell_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= laa_scell_cfg_r13_present; - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present != - (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present; - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_ext_r13_present != - (csi_rs_cfg_nzp_to_release_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= csi_rs_cfg_nzp_to_release_list_ext_r13_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1320_present != (cqi_report_cfg_v1320.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= cqi_report_cfg_v1320_present; - rrc_asn1_warn_assert(laa_scell_cfg_v1430_present != (laa_scell_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= laa_scell_cfg_v1430_present; - rrc_asn1_warn_assert( - type_b_srs_tpc_pdcch_cfg_r14_present != (type_b_srs_tpc_pdcch_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= type_b_srs_tpc_pdcch_cfg_r14_present; - rrc_asn1_warn_assert(ul_pusch_less_pwr_ctrl_ded_v1430_present != (ul_pusch_less_pwr_ctrl_ded_v1430.get() != NULL), - __FILE__, - __LINE__); - group_flags[5] |= ul_pusch_less_pwr_ctrl_ded_v1430_present; - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_list_r14_present != (srs_ul_periodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[5] |= srs_ul_periodic_cfg_ded_list_r14_present; - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present != - (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[5] |= srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present; - rrc_asn1_warn_assert(srs_ul_aperiodic_cfg_ded_list_r14_present != (srs_ul_aperiodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[5] |= srs_ul_aperiodic_cfg_ded_list_r14_present; - rrc_asn1_warn_assert(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present != - (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - group_flags[5] |= srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present; - rrc_asn1_warn_assert(must_cfg_r14_present != (must_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= must_cfg_r14_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1430_present != (pusch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= pusch_cfg_ded_v1430_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1430_present != (csi_rs_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= csi_rs_cfg_v1430_present; - rrc_asn1_warn_assert( - csi_rs_cfg_zp_ap_list_r14_present != (csi_rs_cfg_zp_ap_list_r14.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= csi_rs_cfg_zp_ap_list_r14_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1430_present != (cqi_report_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= cqi_report_cfg_v1430_present; + group_flags[3] |= pucch_scell.is_present(); + group_flags[3] |= cross_carrier_sched_cfg_r13.is_present(); + group_flags[3] |= pdcch_cfg_scell_r13.is_present(); + group_flags[3] |= cqi_report_cfg_v1310.is_present(); + group_flags[3] |= pdsch_cfg_ded_v1310.is_present(); + group_flags[3] |= srs_ul_cfg_ded_v1310.is_present(); + group_flags[3] |= srs_ul_cfg_ded_up_pts_ext_r13.is_present(); + group_flags[3] |= srs_ul_cfg_ded_aperiodic_v1310.is_present(); + group_flags[3] |= srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present(); + group_flags[3] |= csi_rs_cfg_v1310.is_present(); + group_flags[3] |= laa_scell_cfg_r13.is_present(); + group_flags[3] |= csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present(); + group_flags[3] |= csi_rs_cfg_nzp_to_release_list_ext_r13.is_present(); + group_flags[4] |= cqi_report_cfg_v1320.is_present(); + group_flags[5] |= laa_scell_cfg_v1430.is_present(); + group_flags[5] |= type_b_srs_tpc_pdcch_cfg_r14.is_present(); + group_flags[5] |= ul_pusch_less_pwr_ctrl_ded_v1430.is_present(); + group_flags[5] |= srs_ul_periodic_cfg_ded_list_r14.is_present(); + group_flags[5] |= srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present(); + group_flags[5] |= srs_ul_aperiodic_cfg_ded_list_r14.is_present(); + group_flags[5] |= srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present(); + group_flags[5] |= must_cfg_r14.is_present(); + group_flags[5] |= pusch_cfg_ded_v1430.is_present(); + group_flags[5] |= csi_rs_cfg_v1430.is_present(); + group_flags[5] |= csi_rs_cfg_zp_ap_list_r14.is_present(); + group_flags[5] |= cqi_report_cfg_v1430.is_present(); group_flags[5] |= semi_open_loop_r14_present; - rrc_asn1_warn_assert( - pdsch_cfg_ded_scell_v1430_present != (pdsch_cfg_ded_scell_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= pdsch_cfg_ded_scell_v1430_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1480_present != (csi_rs_cfg_v1480.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= csi_rs_cfg_v1480_present; - rrc_asn1_warn_assert(phys_cfg_ded_stti_r15_present != (phys_cfg_ded_stti_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= phys_cfg_ded_stti_r15_present; - rrc_asn1_warn_assert(pdsch_cfg_ded_v1530_present != (pdsch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= pdsch_cfg_ded_v1530_present; - rrc_asn1_warn_assert(cqi_report_cfg_v1530_present != (cqi_report_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= cqi_report_cfg_v1530_present; - rrc_asn1_warn_assert( - cqi_report_cfg_scell_r15_present != (cqi_report_cfg_scell_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= cqi_report_cfg_scell_r15_present; - rrc_asn1_warn_assert( - cqi_short_cfg_scell_r15_present != (cqi_short_cfg_scell_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= cqi_short_cfg_scell_r15_present; - rrc_asn1_warn_assert(csi_rs_cfg_v1530_present != (csi_rs_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= csi_rs_cfg_v1530_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_ded_scell_v1530_present != (ul_pwr_ctrl_ded_scell_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= ul_pwr_ctrl_ded_scell_v1530_present; - rrc_asn1_warn_assert(laa_scell_cfg_v1530_present != (laa_scell_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= laa_scell_cfg_v1530_present; - rrc_asn1_warn_assert(pusch_cfg_ded_v1530_present != (pusch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= pusch_cfg_ded_v1530_present; - rrc_asn1_warn_assert( - semi_static_cfi_cfg_r15_present != (semi_static_cfi_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= semi_static_cfi_cfg_r15_present; - rrc_asn1_warn_assert( - blind_pdsch_repeat_cfg_r15_present != (blind_pdsch_repeat_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= blind_pdsch_repeat_cfg_r15_present; + group_flags[5] |= pdsch_cfg_ded_scell_v1430.is_present(); + group_flags[6] |= csi_rs_cfg_v1480.is_present(); + group_flags[7] |= phys_cfg_ded_stti_r15.is_present(); + group_flags[7] |= pdsch_cfg_ded_v1530.is_present(); + group_flags[7] |= cqi_report_cfg_v1530.is_present(); + group_flags[7] |= cqi_report_cfg_scell_r15.is_present(); + group_flags[7] |= cqi_short_cfg_scell_r15.is_present(); + group_flags[7] |= csi_rs_cfg_v1530.is_present(); + group_flags[7] |= ul_pwr_ctrl_ded_scell_v1530.is_present(); + group_flags[7] |= laa_scell_cfg_v1530.is_present(); + group_flags[7] |= pusch_cfg_ded_v1530.is_present(); + group_flags[7] |= semi_static_cfi_cfg_r15.is_present(); + group_flags[7] |= blind_pdsch_repeat_cfg_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_r11_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_r11_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_release_list_r11_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_add_mod_list_r11_present, 1)); - HANDLE_CODE(bref.pack(epdcch_cfg_r11_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1130_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1130_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1130_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_scell_v1130_present, 1)); - if (csi_rs_cfg_nzp_to_release_list_r11_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_release_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_zp_to_add_mod_list_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(epdcch_cfg_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_scell_v1130.is_present(), 1)); + if (csi_rs_cfg_nzp_to_release_list_r11.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *csi_rs_cfg_nzp_to_release_list_r11, 1, 3, UnalignedIntegerPacker(1, 3))); } - if (csi_rs_cfg_nzp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *csi_rs_cfg_nzp_to_add_mod_list_r11, 1, 3)); } - if (csi_rs_cfg_zp_to_release_list_r11_present) { + if (csi_rs_cfg_zp_to_release_list_r11.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *csi_rs_cfg_zp_to_release_list_r11, 1, 4, UnalignedIntegerPacker(1, 4))); } - if (csi_rs_cfg_zp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_zp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *csi_rs_cfg_zp_to_add_mod_list_r11, 1, 4)); } - if (epdcch_cfg_r11_present) { + if (epdcch_cfg_r11.is_present()) { HANDLE_CODE(epdcch_cfg_r11->pack(bref)); } - if (pdsch_cfg_ded_v1130_present) { + if (pdsch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1130->pack(bref)); } - if (cqi_report_cfg_v1130_present) { + if (cqi_report_cfg_v1130.is_present()) { HANDLE_CODE(cqi_report_cfg_v1130->pack(bref)); } - if (pusch_cfg_ded_v1130_present) { + if (pusch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1130->pack(bref)); } - if (ul_pwr_ctrl_ded_scell_v1130_present) { + if (ul_pwr_ctrl_ded_scell_v1130.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_scell_v1130->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(ant_info_v1250_present, 1)); - HANDLE_CODE(bref.pack(eimta_main_cfg_scell_r12_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_scell_v1250_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_scell_v1250_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1250_present, 1)); - if (ant_info_v1250_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(ant_info_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(eimta_main_cfg_scell_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_scell_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_scell_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1250.is_present(), 1)); + if (ant_info_v1250.is_present()) { HANDLE_CODE(ant_info_v1250->pack(bref)); } - if (eimta_main_cfg_scell_r12_present) { + if (eimta_main_cfg_scell_r12.is_present()) { HANDLE_CODE(eimta_main_cfg_scell_r12->pack(bref)); } - if (cqi_report_cfg_scell_v1250_present) { + if (cqi_report_cfg_scell_v1250.is_present()) { HANDLE_CODE(cqi_report_cfg_scell_v1250->pack(bref)); } - if (ul_pwr_ctrl_ded_scell_v1250_present) { + if (ul_pwr_ctrl_ded_scell_v1250.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_scell_v1250->pack(bref)); } - if (csi_rs_cfg_v1250_present) { + if (csi_rs_cfg_v1250.is_present()) { HANDLE_CODE(csi_rs_cfg_v1250->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1280_present, 1)); - if (pdsch_cfg_ded_v1280_present) { + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1280.is_present(), 1)); + if (pdsch_cfg_ded_v1280.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1280->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(pucch_cell_r13_present, 1)); - HANDLE_CODE(bref.pack(pucch_scell_present, 1)); - HANDLE_CODE(bref.pack(cross_carrier_sched_cfg_r13_present, 1)); - HANDLE_CODE(bref.pack(pdcch_cfg_scell_r13_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1310_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_v1310_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_up_pts_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_v1310_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(laa_scell_cfg_r13_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_ext_r13_present, 1)); - if (pucch_scell_present) { + HANDLE_CODE(bref.pack(pucch_scell.is_present(), 1)); + HANDLE_CODE(bref.pack(cross_carrier_sched_cfg_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(pdcch_cfg_scell_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_up_pts_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(laa_scell_cfg_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_nzp_to_release_list_ext_r13.is_present(), 1)); + if (pucch_scell.is_present()) { HANDLE_CODE(pucch_scell->pack(bref)); } - if (cross_carrier_sched_cfg_r13_present) { + if (cross_carrier_sched_cfg_r13.is_present()) { HANDLE_CODE(cross_carrier_sched_cfg_r13->pack(bref)); } - if (pdcch_cfg_scell_r13_present) { + if (pdcch_cfg_scell_r13.is_present()) { HANDLE_CODE(pdcch_cfg_scell_r13->pack(bref)); } - if (cqi_report_cfg_v1310_present) { + if (cqi_report_cfg_v1310.is_present()) { HANDLE_CODE(cqi_report_cfg_v1310->pack(bref)); } - if (pdsch_cfg_ded_v1310_present) { + if (pdsch_cfg_ded_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1310->pack(bref)); } - if (srs_ul_cfg_ded_v1310_present) { + if (srs_ul_cfg_ded_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_v1310->pack(bref)); } - if (srs_ul_cfg_ded_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_up_pts_ext_r13->pack(bref)); } - if (srs_ul_cfg_ded_aperiodic_v1310_present) { + if (srs_ul_cfg_ded_aperiodic_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_v1310->pack(bref)); } - if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13->pack(bref)); } - if (csi_rs_cfg_v1310_present) { + if (csi_rs_cfg_v1310.is_present()) { HANDLE_CODE(csi_rs_cfg_v1310->pack(bref)); } - if (laa_scell_cfg_r13_present) { + if (laa_scell_cfg_r13.is_present()) { HANDLE_CODE(laa_scell_cfg_r13->pack(bref)); } - if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *csi_rs_cfg_nzp_to_add_mod_list_ext_r13, 1, 21)); } - if (csi_rs_cfg_nzp_to_release_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_release_list_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of( bref, *csi_rs_cfg_nzp_to_release_list_ext_r13, 1, 21, UnalignedIntegerPacker(4, 24))); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1320_present, 1)); - if (cqi_report_cfg_v1320_present) { + HANDLE_CODE(bref.pack(cqi_report_cfg_v1320.is_present(), 1)); + if (cqi_report_cfg_v1320.is_present()) { HANDLE_CODE(cqi_report_cfg_v1320->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(laa_scell_cfg_v1430_present, 1)); - HANDLE_CODE(bref.pack(type_b_srs_tpc_pdcch_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(ul_pusch_less_pwr_ctrl_ded_v1430_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_list_r14_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_aperiodic_cfg_ded_list_r14_present, 1)); - HANDLE_CODE(bref.pack(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present, 1)); - HANDLE_CODE(bref.pack(must_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1430_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1430_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_zp_ap_list_r14_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1430_present, 1)); + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(laa_scell_cfg_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(type_b_srs_tpc_pdcch_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pusch_less_pwr_ctrl_ded_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_aperiodic_cfg_ded_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(must_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_zp_ap_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1430.is_present(), 1)); HANDLE_CODE(bref.pack(semi_open_loop_r14_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_scell_v1430_present, 1)); - if (laa_scell_cfg_v1430_present) { + HANDLE_CODE(bref.pack(pdsch_cfg_ded_scell_v1430.is_present(), 1)); + if (laa_scell_cfg_v1430.is_present()) { HANDLE_CODE(laa_scell_cfg_v1430->pack(bref)); } - if (type_b_srs_tpc_pdcch_cfg_r14_present) { + if (type_b_srs_tpc_pdcch_cfg_r14.is_present()) { HANDLE_CODE(type_b_srs_tpc_pdcch_cfg_r14->pack(bref)); } - if (ul_pusch_less_pwr_ctrl_ded_v1430_present) { + if (ul_pusch_less_pwr_ctrl_ded_v1430.is_present()) { HANDLE_CODE(ul_pusch_less_pwr_ctrl_ded_v1430->pack(bref)); } - if (srs_ul_periodic_cfg_ded_list_r14_present) { + if (srs_ul_periodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_periodic_cfg_ded_list_r14, 1, 2)); } - if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present) { + if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_periodic_cfg_ded_up_pts_ext_list_r14, 1, 4)); } - if (srs_ul_aperiodic_cfg_ded_list_r14_present) { + if (srs_ul_aperiodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_aperiodic_cfg_ded_list_r14, 1, 2)); } - if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present) { + if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *srs_ul_cfg_ded_ap_up_pts_ext_list_r14, 1, 4)); } - if (must_cfg_r14_present) { + if (must_cfg_r14.is_present()) { HANDLE_CODE(must_cfg_r14->pack(bref)); } - if (pusch_cfg_ded_v1430_present) { + if (pusch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1430->pack(bref)); } - if (csi_rs_cfg_v1430_present) { + if (csi_rs_cfg_v1430.is_present()) { HANDLE_CODE(csi_rs_cfg_v1430->pack(bref)); } - if (csi_rs_cfg_zp_ap_list_r14_present) { + if (csi_rs_cfg_zp_ap_list_r14.is_present()) { HANDLE_CODE(csi_rs_cfg_zp_ap_list_r14->pack(bref)); } - if (cqi_report_cfg_v1430_present) { + if (cqi_report_cfg_v1430.is_present()) { HANDLE_CODE(cqi_report_cfg_v1430->pack(bref)); } if (semi_open_loop_r14_present) { HANDLE_CODE(bref.pack(semi_open_loop_r14, 1)); } - if (pdsch_cfg_ded_scell_v1430_present) { + if (pdsch_cfg_ded_scell_v1430.is_present()) { HANDLE_CODE(pdsch_cfg_ded_scell_v1430->pack(bref)); } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1480_present, 1)); - if (csi_rs_cfg_v1480_present) { + HANDLE_CODE(bref.pack(csi_rs_cfg_v1480.is_present(), 1)); + if (csi_rs_cfg_v1480.is_present()) { HANDLE_CODE(csi_rs_cfg_v1480->pack(bref)); } } if (group_flags[7]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(phys_cfg_ded_stti_r15_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1530_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(cqi_report_cfg_scell_r15_present, 1)); - HANDLE_CODE(bref.pack(cqi_short_cfg_scell_r15_present, 1)); - HANDLE_CODE(bref.pack(csi_rs_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_scell_v1530_present, 1)); - HANDLE_CODE(bref.pack(laa_scell_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_ded_v1530_present, 1)); - HANDLE_CODE(bref.pack(semi_static_cfi_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(blind_pdsch_repeat_cfg_r15_present, 1)); - if (phys_cfg_ded_stti_r15_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(phys_cfg_ded_stti_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_ded_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_report_cfg_scell_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(cqi_short_cfg_scell_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(csi_rs_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_ded_scell_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(laa_scell_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_ded_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(semi_static_cfi_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(blind_pdsch_repeat_cfg_r15.is_present(), 1)); + if (phys_cfg_ded_stti_r15.is_present()) { HANDLE_CODE(phys_cfg_ded_stti_r15->pack(bref)); } - if (pdsch_cfg_ded_v1530_present) { + if (pdsch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1530->pack(bref)); } - if (cqi_report_cfg_v1530_present) { + if (cqi_report_cfg_v1530.is_present()) { HANDLE_CODE(cqi_report_cfg_v1530->pack(bref)); } - if (cqi_report_cfg_scell_r15_present) { + if (cqi_report_cfg_scell_r15.is_present()) { HANDLE_CODE(cqi_report_cfg_scell_r15->pack(bref)); } - if (cqi_short_cfg_scell_r15_present) { + if (cqi_short_cfg_scell_r15.is_present()) { HANDLE_CODE(cqi_short_cfg_scell_r15->pack(bref)); } - if (csi_rs_cfg_v1530_present) { + if (csi_rs_cfg_v1530.is_present()) { HANDLE_CODE(csi_rs_cfg_v1530->pack(bref)); } - if (ul_pwr_ctrl_ded_scell_v1530_present) { + if (ul_pwr_ctrl_ded_scell_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_scell_v1530->pack(bref)); } - if (laa_scell_cfg_v1530_present) { + if (laa_scell_cfg_v1530.is_present()) { HANDLE_CODE(laa_scell_cfg_v1530->pack(bref)); } - if (pusch_cfg_ded_v1530_present) { + if (pusch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1530->pack(bref)); } - if (semi_static_cfi_cfg_r15_present) { + if (semi_static_cfi_cfg_r15.is_present()) { HANDLE_CODE(semi_static_cfi_cfg_r15->pack(bref)); } - if (blind_pdsch_repeat_cfg_r15_present) { + if (blind_pdsch_repeat_cfg_r15.is_present()) { HANDLE_CODE(blind_pdsch_repeat_cfg_r15->pack(bref)); } } @@ -50018,316 +49370,370 @@ SRSASN_CODE phys_cfg_ded_scell_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(8); + ext_groups_unpacker_guard group_flags(8); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool csi_rs_cfg_nzp_to_release_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_release_list_r11_present, 1)); + csi_rs_cfg_nzp_to_release_list_r11.set_present(csi_rs_cfg_nzp_to_release_list_r11_present); + bool csi_rs_cfg_nzp_to_add_mod_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_add_mod_list_r11_present, 1)); + csi_rs_cfg_nzp_to_add_mod_list_r11.set_present(csi_rs_cfg_nzp_to_add_mod_list_r11_present); + bool csi_rs_cfg_zp_to_release_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_zp_to_release_list_r11_present, 1)); + csi_rs_cfg_zp_to_release_list_r11.set_present(csi_rs_cfg_zp_to_release_list_r11_present); + bool csi_rs_cfg_zp_to_add_mod_list_r11_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_zp_to_add_mod_list_r11_present, 1)); + csi_rs_cfg_zp_to_add_mod_list_r11.set_present(csi_rs_cfg_zp_to_add_mod_list_r11_present); + bool epdcch_cfg_r11_present; HANDLE_CODE(bref.unpack(epdcch_cfg_r11_present, 1)); + epdcch_cfg_r11.set_present(epdcch_cfg_r11_present); + bool pdsch_cfg_ded_v1130_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1130_present, 1)); + pdsch_cfg_ded_v1130.set_present(pdsch_cfg_ded_v1130_present); + bool cqi_report_cfg_v1130_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1130_present, 1)); + cqi_report_cfg_v1130.set_present(cqi_report_cfg_v1130_present); + bool pusch_cfg_ded_v1130_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1130_present, 1)); + pusch_cfg_ded_v1130.set_present(pusch_cfg_ded_v1130_present); + bool ul_pwr_ctrl_ded_scell_v1130_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_ded_scell_v1130_present, 1)); - if (csi_rs_cfg_nzp_to_release_list_r11_present) { - csi_rs_cfg_nzp_to_release_list_r11 = make_copy_ptr(csi_rs_cfg_nzp_to_release_list_r11_l()); + ul_pwr_ctrl_ded_scell_v1130.set_present(ul_pwr_ctrl_ded_scell_v1130_present); + if (csi_rs_cfg_nzp_to_release_list_r11.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*csi_rs_cfg_nzp_to_release_list_r11, bref, 1, 3, UnalignedIntegerPacker(1, 3))); } - if (csi_rs_cfg_nzp_to_add_mod_list_r11_present) { - csi_rs_cfg_nzp_to_add_mod_list_r11 = make_copy_ptr(csi_rs_cfg_nzp_to_add_mod_list_r11_l()); + if (csi_rs_cfg_nzp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*csi_rs_cfg_nzp_to_add_mod_list_r11, bref, 1, 3)); } - if (csi_rs_cfg_zp_to_release_list_r11_present) { - csi_rs_cfg_zp_to_release_list_r11 = make_copy_ptr(csi_rs_cfg_zp_to_release_list_r11_l()); + if (csi_rs_cfg_zp_to_release_list_r11.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*csi_rs_cfg_zp_to_release_list_r11, bref, 1, 4, UnalignedIntegerPacker(1, 4))); } - if (csi_rs_cfg_zp_to_add_mod_list_r11_present) { - csi_rs_cfg_zp_to_add_mod_list_r11 = make_copy_ptr(csi_rs_cfg_zp_to_add_mod_list_r11_l()); + if (csi_rs_cfg_zp_to_add_mod_list_r11.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*csi_rs_cfg_zp_to_add_mod_list_r11, bref, 1, 4)); } - if (epdcch_cfg_r11_present) { - epdcch_cfg_r11 = make_copy_ptr(epdcch_cfg_r11_s()); + if (epdcch_cfg_r11.is_present()) { HANDLE_CODE(epdcch_cfg_r11->unpack(bref)); } - if (pdsch_cfg_ded_v1130_present) { - pdsch_cfg_ded_v1130 = make_copy_ptr(pdsch_cfg_ded_v1130_s()); + if (pdsch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1130->unpack(bref)); } - if (cqi_report_cfg_v1130_present) { - cqi_report_cfg_v1130 = make_copy_ptr(cqi_report_cfg_v1130_s()); + if (cqi_report_cfg_v1130.is_present()) { HANDLE_CODE(cqi_report_cfg_v1130->unpack(bref)); } - if (pusch_cfg_ded_v1130_present) { - pusch_cfg_ded_v1130 = make_copy_ptr(pusch_cfg_ded_v1130_s()); + if (pusch_cfg_ded_v1130.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1130->unpack(bref)); } - if (ul_pwr_ctrl_ded_scell_v1130_present) { - ul_pwr_ctrl_ded_scell_v1130 = make_copy_ptr(ul_pwr_ctrl_ded_v1130_s()); + if (ul_pwr_ctrl_ded_scell_v1130.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_scell_v1130->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ant_info_v1250_present; HANDLE_CODE(bref.unpack(ant_info_v1250_present, 1)); + ant_info_v1250.set_present(ant_info_v1250_present); + bool eimta_main_cfg_scell_r12_present; HANDLE_CODE(bref.unpack(eimta_main_cfg_scell_r12_present, 1)); + eimta_main_cfg_scell_r12.set_present(eimta_main_cfg_scell_r12_present); + bool cqi_report_cfg_scell_v1250_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_scell_v1250_present, 1)); + cqi_report_cfg_scell_v1250.set_present(cqi_report_cfg_scell_v1250_present); + bool ul_pwr_ctrl_ded_scell_v1250_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_ded_scell_v1250_present, 1)); + ul_pwr_ctrl_ded_scell_v1250.set_present(ul_pwr_ctrl_ded_scell_v1250_present); + bool csi_rs_cfg_v1250_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1250_present, 1)); - if (ant_info_v1250_present) { - ant_info_v1250 = make_copy_ptr(ant_info_ded_v1250_s()); + csi_rs_cfg_v1250.set_present(csi_rs_cfg_v1250_present); + if (ant_info_v1250.is_present()) { HANDLE_CODE(ant_info_v1250->unpack(bref)); } - if (eimta_main_cfg_scell_r12_present) { - eimta_main_cfg_scell_r12 = make_copy_ptr(eimta_main_cfg_serv_cell_r12_c()); + if (eimta_main_cfg_scell_r12.is_present()) { HANDLE_CODE(eimta_main_cfg_scell_r12->unpack(bref)); } - if (cqi_report_cfg_scell_v1250_present) { - cqi_report_cfg_scell_v1250 = make_copy_ptr(cqi_report_cfg_v1250_s()); + if (cqi_report_cfg_scell_v1250.is_present()) { HANDLE_CODE(cqi_report_cfg_scell_v1250->unpack(bref)); } - if (ul_pwr_ctrl_ded_scell_v1250_present) { - ul_pwr_ctrl_ded_scell_v1250 = make_copy_ptr(ul_pwr_ctrl_ded_v1250_s()); + if (ul_pwr_ctrl_ded_scell_v1250.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_scell_v1250->unpack(bref)); } - if (csi_rs_cfg_v1250_present) { - csi_rs_cfg_v1250 = make_copy_ptr(csi_rs_cfg_v1250_s()); + if (csi_rs_cfg_v1250.is_present()) { HANDLE_CODE(csi_rs_cfg_v1250->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool pdsch_cfg_ded_v1280_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1280_present, 1)); - if (pdsch_cfg_ded_v1280_present) { - pdsch_cfg_ded_v1280 = make_copy_ptr(pdsch_cfg_ded_v1280_s()); + pdsch_cfg_ded_v1280.set_present(pdsch_cfg_ded_v1280_present); + if (pdsch_cfg_ded_v1280.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1280->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(pucch_cell_r13_present, 1)); + bool pucch_scell_present; HANDLE_CODE(bref.unpack(pucch_scell_present, 1)); + pucch_scell.set_present(pucch_scell_present); + bool cross_carrier_sched_cfg_r13_present; HANDLE_CODE(bref.unpack(cross_carrier_sched_cfg_r13_present, 1)); + cross_carrier_sched_cfg_r13.set_present(cross_carrier_sched_cfg_r13_present); + bool pdcch_cfg_scell_r13_present; HANDLE_CODE(bref.unpack(pdcch_cfg_scell_r13_present, 1)); + pdcch_cfg_scell_r13.set_present(pdcch_cfg_scell_r13_present); + bool cqi_report_cfg_v1310_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1310_present, 1)); + cqi_report_cfg_v1310.set_present(cqi_report_cfg_v1310_present); + bool pdsch_cfg_ded_v1310_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1310_present, 1)); + pdsch_cfg_ded_v1310.set_present(pdsch_cfg_ded_v1310_present); + bool srs_ul_cfg_ded_v1310_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_v1310_present, 1)); + srs_ul_cfg_ded_v1310.set_present(srs_ul_cfg_ded_v1310_present); + bool srs_ul_cfg_ded_up_pts_ext_r13_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_up_pts_ext_r13_present, 1)); + srs_ul_cfg_ded_up_pts_ext_r13.set_present(srs_ul_cfg_ded_up_pts_ext_r13_present); + bool srs_ul_cfg_ded_aperiodic_v1310_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_aperiodic_v1310_present, 1)); + srs_ul_cfg_ded_aperiodic_v1310.set_present(srs_ul_cfg_ded_aperiodic_v1310_present); + bool srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present, 1)); + srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.set_present(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present); + bool csi_rs_cfg_v1310_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1310_present, 1)); + csi_rs_cfg_v1310.set_present(csi_rs_cfg_v1310_present); + bool laa_scell_cfg_r13_present; HANDLE_CODE(bref.unpack(laa_scell_cfg_r13_present, 1)); + laa_scell_cfg_r13.set_present(laa_scell_cfg_r13_present); + bool csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present, 1)); + csi_rs_cfg_nzp_to_add_mod_list_ext_r13.set_present(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present); + bool csi_rs_cfg_nzp_to_release_list_ext_r13_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_nzp_to_release_list_ext_r13_present, 1)); - if (pucch_scell_present) { - pucch_scell = make_copy_ptr(pucch_scell_c_()); + csi_rs_cfg_nzp_to_release_list_ext_r13.set_present(csi_rs_cfg_nzp_to_release_list_ext_r13_present); + if (pucch_scell.is_present()) { HANDLE_CODE(pucch_scell->unpack(bref)); } - if (cross_carrier_sched_cfg_r13_present) { - cross_carrier_sched_cfg_r13 = make_copy_ptr(cross_carrier_sched_cfg_r13_s()); + if (cross_carrier_sched_cfg_r13.is_present()) { HANDLE_CODE(cross_carrier_sched_cfg_r13->unpack(bref)); } - if (pdcch_cfg_scell_r13_present) { - pdcch_cfg_scell_r13 = make_copy_ptr(pdcch_cfg_scell_r13_s()); + if (pdcch_cfg_scell_r13.is_present()) { HANDLE_CODE(pdcch_cfg_scell_r13->unpack(bref)); } - if (cqi_report_cfg_v1310_present) { - cqi_report_cfg_v1310 = make_copy_ptr(cqi_report_cfg_v1310_s()); + if (cqi_report_cfg_v1310.is_present()) { HANDLE_CODE(cqi_report_cfg_v1310->unpack(bref)); } - if (pdsch_cfg_ded_v1310_present) { - pdsch_cfg_ded_v1310 = make_copy_ptr(pdsch_cfg_ded_v1310_s()); + if (pdsch_cfg_ded_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1310->unpack(bref)); } - if (srs_ul_cfg_ded_v1310_present) { - srs_ul_cfg_ded_v1310 = make_copy_ptr(srs_ul_cfg_ded_v1310_c()); + if (srs_ul_cfg_ded_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_v1310->unpack(bref)); } - if (srs_ul_cfg_ded_up_pts_ext_r13_present) { - srs_ul_cfg_ded_up_pts_ext_r13 = make_copy_ptr(srs_ul_cfg_ded_up_pts_ext_r13_c()); + if (srs_ul_cfg_ded_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_up_pts_ext_r13->unpack(bref)); } - if (srs_ul_cfg_ded_aperiodic_v1310_present) { - srs_ul_cfg_ded_aperiodic_v1310 = make_copy_ptr(srs_ul_cfg_ded_aperiodic_v1310_c()); + if (srs_ul_cfg_ded_aperiodic_v1310.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_v1310->unpack(bref)); } - if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present) { - srs_ul_cfg_ded_aperiodic_up_pts_ext_r13 = make_copy_ptr(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_c()); + if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present()) { HANDLE_CODE(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13->unpack(bref)); } - if (csi_rs_cfg_v1310_present) { - csi_rs_cfg_v1310 = make_copy_ptr(csi_rs_cfg_v1310_s()); + if (csi_rs_cfg_v1310.is_present()) { HANDLE_CODE(csi_rs_cfg_v1310->unpack(bref)); } - if (laa_scell_cfg_r13_present) { - laa_scell_cfg_r13 = make_copy_ptr(laa_scell_cfg_r13_s()); + if (laa_scell_cfg_r13.is_present()) { HANDLE_CODE(laa_scell_cfg_r13->unpack(bref)); } - if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present) { - csi_rs_cfg_nzp_to_add_mod_list_ext_r13 = make_copy_ptr(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_l()); + if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*csi_rs_cfg_nzp_to_add_mod_list_ext_r13, bref, 1, 21)); } - if (csi_rs_cfg_nzp_to_release_list_ext_r13_present) { - csi_rs_cfg_nzp_to_release_list_ext_r13 = make_copy_ptr(csi_rs_cfg_nzp_to_release_list_ext_r13_l()); + if (csi_rs_cfg_nzp_to_release_list_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of( *csi_rs_cfg_nzp_to_release_list_ext_r13, bref, 1, 21, UnalignedIntegerPacker(4, 24))); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool cqi_report_cfg_v1320_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1320_present, 1)); - if (cqi_report_cfg_v1320_present) { - cqi_report_cfg_v1320 = make_copy_ptr(cqi_report_cfg_v1320_s()); + cqi_report_cfg_v1320.set_present(cqi_report_cfg_v1320_present); + if (cqi_report_cfg_v1320.is_present()) { HANDLE_CODE(cqi_report_cfg_v1320->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool laa_scell_cfg_v1430_present; HANDLE_CODE(bref.unpack(laa_scell_cfg_v1430_present, 1)); + laa_scell_cfg_v1430.set_present(laa_scell_cfg_v1430_present); + bool type_b_srs_tpc_pdcch_cfg_r14_present; HANDLE_CODE(bref.unpack(type_b_srs_tpc_pdcch_cfg_r14_present, 1)); + type_b_srs_tpc_pdcch_cfg_r14.set_present(type_b_srs_tpc_pdcch_cfg_r14_present); + bool ul_pusch_less_pwr_ctrl_ded_v1430_present; HANDLE_CODE(bref.unpack(ul_pusch_less_pwr_ctrl_ded_v1430_present, 1)); + ul_pusch_less_pwr_ctrl_ded_v1430.set_present(ul_pusch_less_pwr_ctrl_ded_v1430_present); + bool srs_ul_periodic_cfg_ded_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_periodic_cfg_ded_list_r14_present, 1)); + srs_ul_periodic_cfg_ded_list_r14.set_present(srs_ul_periodic_cfg_ded_list_r14_present); + bool srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present, 1)); + srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.set_present(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present); + bool srs_ul_aperiodic_cfg_ded_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_aperiodic_cfg_ded_list_r14_present, 1)); + srs_ul_aperiodic_cfg_ded_list_r14.set_present(srs_ul_aperiodic_cfg_ded_list_r14_present); + bool srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present; HANDLE_CODE(bref.unpack(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present, 1)); + srs_ul_cfg_ded_ap_up_pts_ext_list_r14.set_present(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present); + bool must_cfg_r14_present; HANDLE_CODE(bref.unpack(must_cfg_r14_present, 1)); + must_cfg_r14.set_present(must_cfg_r14_present); + bool pusch_cfg_ded_v1430_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1430_present, 1)); + pusch_cfg_ded_v1430.set_present(pusch_cfg_ded_v1430_present); + bool csi_rs_cfg_v1430_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1430_present, 1)); + csi_rs_cfg_v1430.set_present(csi_rs_cfg_v1430_present); + bool csi_rs_cfg_zp_ap_list_r14_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_zp_ap_list_r14_present, 1)); + csi_rs_cfg_zp_ap_list_r14.set_present(csi_rs_cfg_zp_ap_list_r14_present); + bool cqi_report_cfg_v1430_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1430_present, 1)); + cqi_report_cfg_v1430.set_present(cqi_report_cfg_v1430_present); HANDLE_CODE(bref.unpack(semi_open_loop_r14_present, 1)); + bool pdsch_cfg_ded_scell_v1430_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_scell_v1430_present, 1)); - if (laa_scell_cfg_v1430_present) { - laa_scell_cfg_v1430 = make_copy_ptr(laa_scell_cfg_v1430_s()); + pdsch_cfg_ded_scell_v1430.set_present(pdsch_cfg_ded_scell_v1430_present); + if (laa_scell_cfg_v1430.is_present()) { HANDLE_CODE(laa_scell_cfg_v1430->unpack(bref)); } - if (type_b_srs_tpc_pdcch_cfg_r14_present) { - type_b_srs_tpc_pdcch_cfg_r14 = make_copy_ptr(srs_tpc_pdcch_cfg_r14_c()); + if (type_b_srs_tpc_pdcch_cfg_r14.is_present()) { HANDLE_CODE(type_b_srs_tpc_pdcch_cfg_r14->unpack(bref)); } - if (ul_pusch_less_pwr_ctrl_ded_v1430_present) { - ul_pusch_less_pwr_ctrl_ded_v1430 = make_copy_ptr(ul_pusch_less_pwr_ctrl_ded_v1430_s()); + if (ul_pusch_less_pwr_ctrl_ded_v1430.is_present()) { HANDLE_CODE(ul_pusch_less_pwr_ctrl_ded_v1430->unpack(bref)); } - if (srs_ul_periodic_cfg_ded_list_r14_present) { - srs_ul_periodic_cfg_ded_list_r14 = make_copy_ptr(srs_ul_periodic_cfg_ded_list_r14_l_()); + if (srs_ul_periodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_periodic_cfg_ded_list_r14, bref, 1, 2)); } - if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present) { - srs_ul_periodic_cfg_ded_up_pts_ext_list_r14 = make_copy_ptr(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_l_()); + if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_periodic_cfg_ded_up_pts_ext_list_r14, bref, 1, 4)); } - if (srs_ul_aperiodic_cfg_ded_list_r14_present) { - srs_ul_aperiodic_cfg_ded_list_r14 = make_copy_ptr(srs_ul_aperiodic_cfg_ded_list_r14_l_()); + if (srs_ul_aperiodic_cfg_ded_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_aperiodic_cfg_ded_list_r14, bref, 1, 2)); } - if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present) { - srs_ul_cfg_ded_ap_up_pts_ext_list_r14 = make_copy_ptr(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_l_()); + if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*srs_ul_cfg_ded_ap_up_pts_ext_list_r14, bref, 1, 4)); } - if (must_cfg_r14_present) { - must_cfg_r14 = make_copy_ptr(must_cfg_r14_c_()); + if (must_cfg_r14.is_present()) { HANDLE_CODE(must_cfg_r14->unpack(bref)); } - if (pusch_cfg_ded_v1430_present) { - pusch_cfg_ded_v1430 = make_copy_ptr(pusch_cfg_ded_scell_v1430_s()); + if (pusch_cfg_ded_v1430.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1430->unpack(bref)); } - if (csi_rs_cfg_v1430_present) { - csi_rs_cfg_v1430 = make_copy_ptr(csi_rs_cfg_v1430_s()); + if (csi_rs_cfg_v1430.is_present()) { HANDLE_CODE(csi_rs_cfg_v1430->unpack(bref)); } - if (csi_rs_cfg_zp_ap_list_r14_present) { - csi_rs_cfg_zp_ap_list_r14 = make_copy_ptr(csi_rs_cfg_zp_ap_list_r14_c()); + if (csi_rs_cfg_zp_ap_list_r14.is_present()) { HANDLE_CODE(csi_rs_cfg_zp_ap_list_r14->unpack(bref)); } - if (cqi_report_cfg_v1430_present) { - cqi_report_cfg_v1430 = make_copy_ptr(cqi_report_cfg_v1430_s()); + if (cqi_report_cfg_v1430.is_present()) { HANDLE_CODE(cqi_report_cfg_v1430->unpack(bref)); } if (semi_open_loop_r14_present) { HANDLE_CODE(bref.unpack(semi_open_loop_r14, 1)); } - if (pdsch_cfg_ded_scell_v1430_present) { - pdsch_cfg_ded_scell_v1430 = make_copy_ptr(pdsch_cfg_ded_scell_v1430_s()); + if (pdsch_cfg_ded_scell_v1430.is_present()) { HANDLE_CODE(pdsch_cfg_ded_scell_v1430->unpack(bref)); } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool csi_rs_cfg_v1480_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1480_present, 1)); - if (csi_rs_cfg_v1480_present) { - csi_rs_cfg_v1480 = make_copy_ptr(csi_rs_cfg_v1480_s()); + csi_rs_cfg_v1480.set_present(csi_rs_cfg_v1480_present); + if (csi_rs_cfg_v1480.is_present()) { HANDLE_CODE(csi_rs_cfg_v1480->unpack(bref)); } } if (group_flags[7]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool phys_cfg_ded_stti_r15_present; HANDLE_CODE(bref.unpack(phys_cfg_ded_stti_r15_present, 1)); + phys_cfg_ded_stti_r15.set_present(phys_cfg_ded_stti_r15_present); + bool pdsch_cfg_ded_v1530_present; HANDLE_CODE(bref.unpack(pdsch_cfg_ded_v1530_present, 1)); + pdsch_cfg_ded_v1530.set_present(pdsch_cfg_ded_v1530_present); + bool cqi_report_cfg_v1530_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_v1530_present, 1)); + cqi_report_cfg_v1530.set_present(cqi_report_cfg_v1530_present); + bool cqi_report_cfg_scell_r15_present; HANDLE_CODE(bref.unpack(cqi_report_cfg_scell_r15_present, 1)); + cqi_report_cfg_scell_r15.set_present(cqi_report_cfg_scell_r15_present); + bool cqi_short_cfg_scell_r15_present; HANDLE_CODE(bref.unpack(cqi_short_cfg_scell_r15_present, 1)); + cqi_short_cfg_scell_r15.set_present(cqi_short_cfg_scell_r15_present); + bool csi_rs_cfg_v1530_present; HANDLE_CODE(bref.unpack(csi_rs_cfg_v1530_present, 1)); + csi_rs_cfg_v1530.set_present(csi_rs_cfg_v1530_present); + bool ul_pwr_ctrl_ded_scell_v1530_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_ded_scell_v1530_present, 1)); + ul_pwr_ctrl_ded_scell_v1530.set_present(ul_pwr_ctrl_ded_scell_v1530_present); + bool laa_scell_cfg_v1530_present; HANDLE_CODE(bref.unpack(laa_scell_cfg_v1530_present, 1)); + laa_scell_cfg_v1530.set_present(laa_scell_cfg_v1530_present); + bool pusch_cfg_ded_v1530_present; HANDLE_CODE(bref.unpack(pusch_cfg_ded_v1530_present, 1)); + pusch_cfg_ded_v1530.set_present(pusch_cfg_ded_v1530_present); + bool semi_static_cfi_cfg_r15_present; HANDLE_CODE(bref.unpack(semi_static_cfi_cfg_r15_present, 1)); + semi_static_cfi_cfg_r15.set_present(semi_static_cfi_cfg_r15_present); + bool blind_pdsch_repeat_cfg_r15_present; HANDLE_CODE(bref.unpack(blind_pdsch_repeat_cfg_r15_present, 1)); - if (phys_cfg_ded_stti_r15_present) { - phys_cfg_ded_stti_r15 = make_copy_ptr(phys_cfg_ded_stti_r15_c()); + blind_pdsch_repeat_cfg_r15.set_present(blind_pdsch_repeat_cfg_r15_present); + if (phys_cfg_ded_stti_r15.is_present()) { HANDLE_CODE(phys_cfg_ded_stti_r15->unpack(bref)); } - if (pdsch_cfg_ded_v1530_present) { - pdsch_cfg_ded_v1530 = make_copy_ptr(pdsch_cfg_ded_v1530_s()); + if (pdsch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pdsch_cfg_ded_v1530->unpack(bref)); } - if (cqi_report_cfg_v1530_present) { - cqi_report_cfg_v1530 = make_copy_ptr(cqi_report_cfg_v1530_s()); + if (cqi_report_cfg_v1530.is_present()) { HANDLE_CODE(cqi_report_cfg_v1530->unpack(bref)); } - if (cqi_report_cfg_scell_r15_present) { - cqi_report_cfg_scell_r15 = make_copy_ptr(cqi_report_cfg_scell_r15_s()); + if (cqi_report_cfg_scell_r15.is_present()) { HANDLE_CODE(cqi_report_cfg_scell_r15->unpack(bref)); } - if (cqi_short_cfg_scell_r15_present) { - cqi_short_cfg_scell_r15 = make_copy_ptr(cqi_short_cfg_scell_r15_c()); + if (cqi_short_cfg_scell_r15.is_present()) { HANDLE_CODE(cqi_short_cfg_scell_r15->unpack(bref)); } - if (csi_rs_cfg_v1530_present) { - csi_rs_cfg_v1530 = make_copy_ptr(csi_rs_cfg_v1530_s()); + if (csi_rs_cfg_v1530.is_present()) { HANDLE_CODE(csi_rs_cfg_v1530->unpack(bref)); } - if (ul_pwr_ctrl_ded_scell_v1530_present) { - ul_pwr_ctrl_ded_scell_v1530 = make_copy_ptr(ul_pwr_ctrl_ded_v1530_s()); + if (ul_pwr_ctrl_ded_scell_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_ded_scell_v1530->unpack(bref)); } - if (laa_scell_cfg_v1530_present) { - laa_scell_cfg_v1530 = make_copy_ptr(laa_scell_cfg_v1530_s()); + if (laa_scell_cfg_v1530.is_present()) { HANDLE_CODE(laa_scell_cfg_v1530->unpack(bref)); } - if (pusch_cfg_ded_v1530_present) { - pusch_cfg_ded_v1530 = make_copy_ptr(pusch_cfg_ded_scell_v1530_s()); + if (pusch_cfg_ded_v1530.is_present()) { HANDLE_CODE(pusch_cfg_ded_v1530->unpack(bref)); } - if (semi_static_cfi_cfg_r15_present) { - semi_static_cfi_cfg_r15 = make_copy_ptr(semi_static_cfi_cfg_r15_c_()); + if (semi_static_cfi_cfg_r15.is_present()) { HANDLE_CODE(semi_static_cfi_cfg_r15->unpack(bref)); } - if (blind_pdsch_repeat_cfg_r15_present) { - blind_pdsch_repeat_cfg_r15 = make_copy_ptr(blind_pdsch_repeat_cfg_r15_c_()); + if (blind_pdsch_repeat_cfg_r15.is_present()) { HANDLE_CODE(blind_pdsch_repeat_cfg_r15->unpack(bref)); } } @@ -50392,355 +49798,255 @@ void phys_cfg_ded_scell_r10_s::to_json(json_writer& j) const j.end_obj(); } if (ext) { - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_r11_present != - (csi_rs_cfg_nzp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_release_list_r11_present) { + if (csi_rs_cfg_nzp_to_release_list_r11.is_present()) { j.start_array("csi-RS-ConfigNZPToReleaseList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_release_list_r11->size(); ++i1) { j.write_int(((*csi_rs_cfg_nzp_to_release_list_r11)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_r11_present != - (csi_rs_cfg_nzp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_r11.is_present()) { j.start_array("csi-RS-ConfigNZPToAddModList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_add_mod_list_r11->size(); ++i1) { ((*csi_rs_cfg_nzp_to_add_mod_list_r11)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_release_list_r11_present != (csi_rs_cfg_zp_to_release_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_zp_to_release_list_r11_present) { + if (csi_rs_cfg_zp_to_release_list_r11.is_present()) { j.start_array("csi-RS-ConfigZPToReleaseList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_zp_to_release_list_r11->size(); ++i1) { j.write_int(((*csi_rs_cfg_zp_to_release_list_r11)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_zp_to_add_mod_list_r11_present != (csi_rs_cfg_zp_to_add_mod_list_r11.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_zp_to_add_mod_list_r11_present) { + if (csi_rs_cfg_zp_to_add_mod_list_r11.is_present()) { j.start_array("csi-RS-ConfigZPToAddModList-r11"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_zp_to_add_mod_list_r11->size(); ++i1) { ((*csi_rs_cfg_zp_to_add_mod_list_r11)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(epdcch_cfg_r11_present != (epdcch_cfg_r11.get() != NULL), __FILE__, __LINE__); - if (epdcch_cfg_r11_present) { + if (epdcch_cfg_r11.is_present()) { j.write_fieldname("epdcch-Config-r11"); epdcch_cfg_r11->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1130_present != (pdsch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1130_present) { + if (pdsch_cfg_ded_v1130.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1130"); pdsch_cfg_ded_v1130->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1130_present != (cqi_report_cfg_v1130.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1130_present) { + if (cqi_report_cfg_v1130.is_present()) { j.write_fieldname("cqi-ReportConfig-v1130"); cqi_report_cfg_v1130->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1130_present != (pusch_cfg_ded_v1130.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1130_present) { + if (pusch_cfg_ded_v1130.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1130"); pusch_cfg_ded_v1130->to_json(j); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_ded_scell_v1130_present != (ul_pwr_ctrl_ded_scell_v1130.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_ded_scell_v1130_present) { + if (ul_pwr_ctrl_ded_scell_v1130.is_present()) { j.write_fieldname("uplinkPowerControlDedicatedSCell-v1130"); ul_pwr_ctrl_ded_scell_v1130->to_json(j); } - rrc_asn1_warn_assert(ant_info_v1250_present != (ant_info_v1250.get() != NULL), __FILE__, __LINE__); - if (ant_info_v1250_present) { + if (ant_info_v1250.is_present()) { j.write_fieldname("antennaInfo-v1250"); ant_info_v1250->to_json(j); } - rrc_asn1_warn_assert( - eimta_main_cfg_scell_r12_present != (eimta_main_cfg_scell_r12.get() != NULL), __FILE__, __LINE__); - if (eimta_main_cfg_scell_r12_present) { + if (eimta_main_cfg_scell_r12.is_present()) { j.write_fieldname("eimta-MainConfigSCell-r12"); eimta_main_cfg_scell_r12->to_json(j); } - rrc_asn1_warn_assert( - cqi_report_cfg_scell_v1250_present != (cqi_report_cfg_scell_v1250.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_scell_v1250_present) { + if (cqi_report_cfg_scell_v1250.is_present()) { j.write_fieldname("cqi-ReportConfigSCell-v1250"); cqi_report_cfg_scell_v1250->to_json(j); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_ded_scell_v1250_present != (ul_pwr_ctrl_ded_scell_v1250.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_ded_scell_v1250_present) { + if (ul_pwr_ctrl_ded_scell_v1250.is_present()) { j.write_fieldname("uplinkPowerControlDedicatedSCell-v1250"); ul_pwr_ctrl_ded_scell_v1250->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1250_present != (csi_rs_cfg_v1250.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1250_present) { + if (csi_rs_cfg_v1250.is_present()) { j.write_fieldname("csi-RS-Config-v1250"); csi_rs_cfg_v1250->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1280_present != (pdsch_cfg_ded_v1280.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1280_present) { + if (pdsch_cfg_ded_v1280.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1280"); pdsch_cfg_ded_v1280->to_json(j); } if (pucch_cell_r13_present) { j.write_str("pucch-Cell-r13", "true"); } - rrc_asn1_warn_assert(pucch_scell_present != (pucch_scell.get() != NULL), __FILE__, __LINE__); - if (pucch_scell_present) { + if (pucch_scell.is_present()) { j.write_fieldname("pucch-SCell"); pucch_scell->to_json(j); } - rrc_asn1_warn_assert( - cross_carrier_sched_cfg_r13_present != (cross_carrier_sched_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (cross_carrier_sched_cfg_r13_present) { + if (cross_carrier_sched_cfg_r13.is_present()) { j.write_fieldname("crossCarrierSchedulingConfig-r13"); cross_carrier_sched_cfg_r13->to_json(j); } - rrc_asn1_warn_assert(pdcch_cfg_scell_r13_present != (pdcch_cfg_scell_r13.get() != NULL), __FILE__, __LINE__); - if (pdcch_cfg_scell_r13_present) { + if (pdcch_cfg_scell_r13.is_present()) { j.write_fieldname("pdcch-ConfigSCell-r13"); pdcch_cfg_scell_r13->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1310_present != (cqi_report_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1310_present) { + if (cqi_report_cfg_v1310.is_present()) { j.write_fieldname("cqi-ReportConfig-v1310"); cqi_report_cfg_v1310->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1310_present != (pdsch_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1310_present) { + if (pdsch_cfg_ded_v1310.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1310"); pdsch_cfg_ded_v1310->to_json(j); } - rrc_asn1_warn_assert(srs_ul_cfg_ded_v1310_present != (srs_ul_cfg_ded_v1310.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_v1310_present) { + if (srs_ul_cfg_ded_v1310.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicated-v1310"); srs_ul_cfg_ded_v1310->to_json(j); } - rrc_asn1_warn_assert( - srs_ul_cfg_ded_up_pts_ext_r13_present != (srs_ul_cfg_ded_up_pts_ext_r13.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_up_pts_ext_r13.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicatedUpPTsExt-r13"); srs_ul_cfg_ded_up_pts_ext_r13->to_json(j); } - rrc_asn1_warn_assert( - srs_ul_cfg_ded_aperiodic_v1310_present != (srs_ul_cfg_ded_aperiodic_v1310.get() != NULL), __FILE__, __LINE__); - if (srs_ul_cfg_ded_aperiodic_v1310_present) { + if (srs_ul_cfg_ded_aperiodic_v1310.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicatedAperiodic-v1310"); srs_ul_cfg_ded_aperiodic_v1310->to_json(j); } - rrc_asn1_warn_assert(srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present != - (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13_present) { + if (srs_ul_cfg_ded_aperiodic_up_pts_ext_r13.is_present()) { j.write_fieldname("soundingRS-UL-ConfigDedicatedAperiodicUpPTsExt-r13"); srs_ul_cfg_ded_aperiodic_up_pts_ext_r13->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1310_present != (csi_rs_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1310_present) { + if (csi_rs_cfg_v1310.is_present()) { j.write_fieldname("csi-RS-Config-v1310"); csi_rs_cfg_v1310->to_json(j); } - rrc_asn1_warn_assert(laa_scell_cfg_r13_present != (laa_scell_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (laa_scell_cfg_r13_present) { + if (laa_scell_cfg_r13.is_present()) { j.write_fieldname("laa-SCellConfiguration-r13"); laa_scell_cfg_r13->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present != - (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_add_mod_list_ext_r13.is_present()) { j.start_array("csi-RS-ConfigNZPToAddModListExt-r13"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_add_mod_list_ext_r13->size(); ++i1) { ((*csi_rs_cfg_nzp_to_add_mod_list_ext_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(csi_rs_cfg_nzp_to_release_list_ext_r13_present != - (csi_rs_cfg_nzp_to_release_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (csi_rs_cfg_nzp_to_release_list_ext_r13_present) { + if (csi_rs_cfg_nzp_to_release_list_ext_r13.is_present()) { j.start_array("csi-RS-ConfigNZPToReleaseListExt-r13"); for (uint32_t i1 = 0; i1 < csi_rs_cfg_nzp_to_release_list_ext_r13->size(); ++i1) { j.write_int(((*csi_rs_cfg_nzp_to_release_list_ext_r13)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(cqi_report_cfg_v1320_present != (cqi_report_cfg_v1320.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1320_present) { + if (cqi_report_cfg_v1320.is_present()) { j.write_fieldname("cqi-ReportConfig-v1320"); cqi_report_cfg_v1320->to_json(j); } - rrc_asn1_warn_assert(laa_scell_cfg_v1430_present != (laa_scell_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (laa_scell_cfg_v1430_present) { + if (laa_scell_cfg_v1430.is_present()) { j.write_fieldname("laa-SCellConfiguration-v1430"); laa_scell_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert( - type_b_srs_tpc_pdcch_cfg_r14_present != (type_b_srs_tpc_pdcch_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (type_b_srs_tpc_pdcch_cfg_r14_present) { + if (type_b_srs_tpc_pdcch_cfg_r14.is_present()) { j.write_fieldname("typeB-SRS-TPC-PDCCH-Config-r14"); type_b_srs_tpc_pdcch_cfg_r14->to_json(j); } - rrc_asn1_warn_assert(ul_pusch_less_pwr_ctrl_ded_v1430_present != (ul_pusch_less_pwr_ctrl_ded_v1430.get() != NULL), - __FILE__, - __LINE__); - if (ul_pusch_less_pwr_ctrl_ded_v1430_present) { + if (ul_pusch_less_pwr_ctrl_ded_v1430.is_present()) { j.write_fieldname("uplinkPUSCH-LessPowerControlDedicated-v1430"); ul_pusch_less_pwr_ctrl_ded_v1430->to_json(j); } - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_list_r14_present != (srs_ul_periodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_periodic_cfg_ded_list_r14_present) { + if (srs_ul_periodic_cfg_ded_list_r14.is_present()) { j.start_array("soundingRS-UL-PeriodicConfigDedicatedList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_periodic_cfg_ded_list_r14->size(); ++i1) { ((*srs_ul_periodic_cfg_ded_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present != - (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14_present) { + if (srs_ul_periodic_cfg_ded_up_pts_ext_list_r14.is_present()) { j.start_array("soundingRS-UL-PeriodicConfigDedicatedUpPTsExtList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_periodic_cfg_ded_up_pts_ext_list_r14->size(); ++i1) { ((*srs_ul_periodic_cfg_ded_up_pts_ext_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(srs_ul_aperiodic_cfg_ded_list_r14_present != (srs_ul_aperiodic_cfg_ded_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_aperiodic_cfg_ded_list_r14_present) { + if (srs_ul_aperiodic_cfg_ded_list_r14.is_present()) { j.start_array("soundingRS-UL-AperiodicConfigDedicatedList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_aperiodic_cfg_ded_list_r14->size(); ++i1) { ((*srs_ul_aperiodic_cfg_ded_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present != - (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.get() != NULL), - __FILE__, - __LINE__); - if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14_present) { + if (srs_ul_cfg_ded_ap_up_pts_ext_list_r14.is_present()) { j.start_array("soundingRS-UL-ConfigDedicatedApUpPTsExtList-r14"); for (uint32_t i1 = 0; i1 < srs_ul_cfg_ded_ap_up_pts_ext_list_r14->size(); ++i1) { ((*srs_ul_cfg_ded_ap_up_pts_ext_list_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(must_cfg_r14_present != (must_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (must_cfg_r14_present) { + if (must_cfg_r14.is_present()) { j.write_fieldname("must-Config-r14"); must_cfg_r14->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1430_present != (pusch_cfg_ded_v1430.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1430_present) { + if (pusch_cfg_ded_v1430.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1430"); pusch_cfg_ded_v1430->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1430_present != (csi_rs_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1430_present) { + if (csi_rs_cfg_v1430.is_present()) { j.write_fieldname("csi-RS-Config-v1430"); csi_rs_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert( - csi_rs_cfg_zp_ap_list_r14_present != (csi_rs_cfg_zp_ap_list_r14.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_zp_ap_list_r14_present) { + if (csi_rs_cfg_zp_ap_list_r14.is_present()) { j.write_fieldname("csi-RS-ConfigZP-ApList-r14"); csi_rs_cfg_zp_ap_list_r14->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1430_present != (cqi_report_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1430_present) { + if (cqi_report_cfg_v1430.is_present()) { j.write_fieldname("cqi-ReportConfig-v1430"); cqi_report_cfg_v1430->to_json(j); } if (semi_open_loop_r14_present) { j.write_bool("semiOpenLoop-r14", semi_open_loop_r14); } - rrc_asn1_warn_assert( - pdsch_cfg_ded_scell_v1430_present != (pdsch_cfg_ded_scell_v1430.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_scell_v1430_present) { + if (pdsch_cfg_ded_scell_v1430.is_present()) { j.write_fieldname("pdsch-ConfigDedicatedSCell-v1430"); pdsch_cfg_ded_scell_v1430->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1480_present != (csi_rs_cfg_v1480.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1480_present) { + if (csi_rs_cfg_v1480.is_present()) { j.write_fieldname("csi-RS-Config-v1480"); csi_rs_cfg_v1480->to_json(j); } - rrc_asn1_warn_assert(phys_cfg_ded_stti_r15_present != (phys_cfg_ded_stti_r15.get() != NULL), __FILE__, __LINE__); - if (phys_cfg_ded_stti_r15_present) { + if (phys_cfg_ded_stti_r15.is_present()) { j.write_fieldname("physicalConfigDedicatedSTTI-r15"); phys_cfg_ded_stti_r15->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_ded_v1530_present != (pdsch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_ded_v1530_present) { + if (pdsch_cfg_ded_v1530.is_present()) { j.write_fieldname("pdsch-ConfigDedicated-v1530"); pdsch_cfg_ded_v1530->to_json(j); } - rrc_asn1_warn_assert(cqi_report_cfg_v1530_present != (cqi_report_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_v1530_present) { + if (cqi_report_cfg_v1530.is_present()) { j.write_fieldname("cqi-ReportConfig-v1530"); cqi_report_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert( - cqi_report_cfg_scell_r15_present != (cqi_report_cfg_scell_r15.get() != NULL), __FILE__, __LINE__); - if (cqi_report_cfg_scell_r15_present) { + if (cqi_report_cfg_scell_r15.is_present()) { j.write_fieldname("cqi-ReportConfigSCell-r15"); cqi_report_cfg_scell_r15->to_json(j); } - rrc_asn1_warn_assert( - cqi_short_cfg_scell_r15_present != (cqi_short_cfg_scell_r15.get() != NULL), __FILE__, __LINE__); - if (cqi_short_cfg_scell_r15_present) { + if (cqi_short_cfg_scell_r15.is_present()) { j.write_fieldname("cqi-ShortConfigSCell-r15"); cqi_short_cfg_scell_r15->to_json(j); } - rrc_asn1_warn_assert(csi_rs_cfg_v1530_present != (csi_rs_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (csi_rs_cfg_v1530_present) { + if (csi_rs_cfg_v1530.is_present()) { j.write_fieldname("csi-RS-Config-v1530"); csi_rs_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_ded_scell_v1530_present != (ul_pwr_ctrl_ded_scell_v1530.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_ded_scell_v1530_present) { + if (ul_pwr_ctrl_ded_scell_v1530.is_present()) { j.write_fieldname("uplinkPowerControlDedicatedSCell-v1530"); ul_pwr_ctrl_ded_scell_v1530->to_json(j); } - rrc_asn1_warn_assert(laa_scell_cfg_v1530_present != (laa_scell_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (laa_scell_cfg_v1530_present) { + if (laa_scell_cfg_v1530.is_present()) { j.write_fieldname("laa-SCellConfiguration-v1530"); laa_scell_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_ded_v1530_present != (pusch_cfg_ded_v1530.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_ded_v1530_present) { + if (pusch_cfg_ded_v1530.is_present()) { j.write_fieldname("pusch-ConfigDedicated-v1530"); pusch_cfg_ded_v1530->to_json(j); } - rrc_asn1_warn_assert( - semi_static_cfi_cfg_r15_present != (semi_static_cfi_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (semi_static_cfi_cfg_r15_present) { + if (semi_static_cfi_cfg_r15.is_present()) { j.write_fieldname("semiStaticCFI-Config-r15"); semi_static_cfi_cfg_r15->to_json(j); } - rrc_asn1_warn_assert( - blind_pdsch_repeat_cfg_r15_present != (blind_pdsch_repeat_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (blind_pdsch_repeat_cfg_r15_present) { + if (blind_pdsch_repeat_cfg_r15.is_present()) { j.write_fieldname("blindPDSCH-Repetition-Config-r15"); blind_pdsch_repeat_cfg_r15->to_json(j); } @@ -51621,44 +50927,26 @@ SRSASN_CODE rr_cfg_common_scell_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(7); + ext_groups_packer_guard group_flags; group_flags[0] |= ul_carrier_freq_v1090_present; - rrc_asn1_warn_assert( - rach_cfg_common_scell_r11_present != (rach_cfg_common_scell_r11.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= rach_cfg_common_scell_r11_present; - rrc_asn1_warn_assert(prach_cfg_scell_r11_present != (prach_cfg_scell_r11.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= prach_cfg_scell_r11_present; - rrc_asn1_warn_assert(tdd_cfg_v1130_present != (tdd_cfg_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= tdd_cfg_v1130_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_scell_v1130_present != (ul_pwr_ctrl_common_scell_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ul_pwr_ctrl_common_scell_v1130_present; - rrc_asn1_warn_assert(pusch_cfg_common_v1270_present != (pusch_cfg_common_v1270.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= pusch_cfg_common_v1270_present; - rrc_asn1_warn_assert(pucch_cfg_common_r13_present != (pucch_cfg_common_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pucch_cfg_common_r13_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_scell_v1310_present != (ul_pwr_ctrl_common_scell_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= ul_pwr_ctrl_common_scell_v1310_present; - rrc_asn1_warn_assert( - high_speed_cfg_scell_r14_present != (high_speed_cfg_scell_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= high_speed_cfg_scell_r14_present; - rrc_asn1_warn_assert(prach_cfg_v1430_present != (prach_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= prach_cfg_v1430_present; - rrc_asn1_warn_assert(ul_cfg_r14_present != (ul_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= ul_cfg_r14_present; + group_flags[1] |= rach_cfg_common_scell_r11.is_present(); + group_flags[1] |= prach_cfg_scell_r11.is_present(); + group_flags[1] |= tdd_cfg_v1130.is_present(); + group_flags[1] |= ul_pwr_ctrl_common_scell_v1130.is_present(); + group_flags[2] |= pusch_cfg_common_v1270.is_present(); + group_flags[3] |= pucch_cfg_common_r13.is_present(); + group_flags[3] |= ul_pwr_ctrl_common_scell_v1310.is_present(); + group_flags[4] |= high_speed_cfg_scell_r14.is_present(); + group_flags[4] |= prach_cfg_v1430.is_present(); + group_flags[4] |= ul_cfg_r14.is_present(); group_flags[4] |= harq_ref_cfg_r14_present; group_flags[4] |= srs_flex_timing_r14_present; - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= mbsfn_sf_cfg_list_v1430_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_scell_v1530_present != (ul_pwr_ctrl_common_scell_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= ul_pwr_ctrl_common_scell_v1530_present; + group_flags[5] |= mbsfn_sf_cfg_list_v1430.is_present(); + group_flags[6] |= ul_pwr_ctrl_common_scell_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(ul_carrier_freq_v1090_present, 1)); if (ul_carrier_freq_v1090_present) { @@ -51666,60 +50954,60 @@ SRSASN_CODE rr_cfg_common_scell_r10_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rach_cfg_common_scell_r11_present, 1)); - HANDLE_CODE(bref.pack(prach_cfg_scell_r11_present, 1)); - HANDLE_CODE(bref.pack(tdd_cfg_v1130_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_scell_v1130_present, 1)); - if (rach_cfg_common_scell_r11_present) { + HANDLE_CODE(bref.pack(rach_cfg_common_scell_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(prach_cfg_scell_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(tdd_cfg_v1130.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_scell_v1130.is_present(), 1)); + if (rach_cfg_common_scell_r11.is_present()) { HANDLE_CODE(rach_cfg_common_scell_r11->pack(bref)); } - if (prach_cfg_scell_r11_present) { + if (prach_cfg_scell_r11.is_present()) { HANDLE_CODE(prach_cfg_scell_r11->pack(bref)); } - if (tdd_cfg_v1130_present) { + if (tdd_cfg_v1130.is_present()) { HANDLE_CODE(tdd_cfg_v1130->pack(bref)); } - if (ul_pwr_ctrl_common_scell_v1130_present) { + if (ul_pwr_ctrl_common_scell_v1130.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_scell_v1130->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(pusch_cfg_common_v1270_present, 1)); - if (pusch_cfg_common_v1270_present) { + HANDLE_CODE(bref.pack(pusch_cfg_common_v1270.is_present(), 1)); + if (pusch_cfg_common_v1270.is_present()) { HANDLE_CODE(pusch_cfg_common_v1270->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(pucch_cfg_common_r13_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_scell_v1310_present, 1)); - if (pucch_cfg_common_r13_present) { + HANDLE_CODE(bref.pack(pucch_cfg_common_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_scell_v1310.is_present(), 1)); + if (pucch_cfg_common_r13.is_present()) { HANDLE_CODE(pucch_cfg_common_r13->pack(bref)); } - if (ul_pwr_ctrl_common_scell_v1310_present) { + if (ul_pwr_ctrl_common_scell_v1310.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_scell_v1310->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(high_speed_cfg_scell_r14_present, 1)); - HANDLE_CODE(bref.pack(prach_cfg_v1430_present, 1)); - HANDLE_CODE(bref.pack(ul_cfg_r14_present, 1)); + HANDLE_CODE(bref.pack(high_speed_cfg_scell_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(prach_cfg_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_cfg_r14.is_present(), 1)); HANDLE_CODE(bref.pack(harq_ref_cfg_r14_present, 1)); HANDLE_CODE(bref.pack(srs_flex_timing_r14_present, 1)); - if (high_speed_cfg_scell_r14_present) { + if (high_speed_cfg_scell_r14.is_present()) { HANDLE_CODE(high_speed_cfg_scell_r14->pack(bref)); } - if (prach_cfg_v1430_present) { + if (prach_cfg_v1430.is_present()) { HANDLE_CODE(prach_cfg_v1430->pack(bref)); } - if (ul_cfg_r14_present) { + if (ul_cfg_r14.is_present()) { HANDLE_CODE(bref.pack(ul_cfg_r14->p_max_r14_present, 1)); HANDLE_CODE(bref.pack(ul_cfg_r14->prach_cfg_scell_r14_present, 1)); HANDLE_CODE(bref.pack(ul_cfg_r14->ul_pwr_ctrl_common_pusch_less_cell_v1430_present, 1)); @@ -51751,18 +51039,18 @@ SRSASN_CODE rr_cfg_common_scell_r10_s::pack(bit_ref& bref) const } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { + HANDLE_CODE(bref.pack(mbsfn_sf_cfg_list_v1430.is_present(), 1)); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *mbsfn_sf_cfg_list_v1430, 1, 8)); } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_scell_v1530_present, 1)); - if (ul_pwr_ctrl_common_scell_v1530_present) { + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_scell_v1530.is_present(), 1)); + if (ul_pwr_ctrl_common_scell_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_scell_v1530->pack(bref)); } } @@ -51813,11 +51101,11 @@ SRSASN_CODE rr_cfg_common_scell_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(7); + ext_groups_unpacker_guard group_flags(7); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(ul_carrier_freq_v1090_present, 1)); if (ul_carrier_freq_v1090_present) { @@ -51825,70 +51113,80 @@ SRSASN_CODE rr_cfg_common_scell_r10_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rach_cfg_common_scell_r11_present; HANDLE_CODE(bref.unpack(rach_cfg_common_scell_r11_present, 1)); + rach_cfg_common_scell_r11.set_present(rach_cfg_common_scell_r11_present); + bool prach_cfg_scell_r11_present; HANDLE_CODE(bref.unpack(prach_cfg_scell_r11_present, 1)); + prach_cfg_scell_r11.set_present(prach_cfg_scell_r11_present); + bool tdd_cfg_v1130_present; HANDLE_CODE(bref.unpack(tdd_cfg_v1130_present, 1)); + tdd_cfg_v1130.set_present(tdd_cfg_v1130_present); + bool ul_pwr_ctrl_common_scell_v1130_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_scell_v1130_present, 1)); - if (rach_cfg_common_scell_r11_present) { - rach_cfg_common_scell_r11 = make_copy_ptr(rach_cfg_common_scell_r11_s()); + ul_pwr_ctrl_common_scell_v1130.set_present(ul_pwr_ctrl_common_scell_v1130_present); + if (rach_cfg_common_scell_r11.is_present()) { HANDLE_CODE(rach_cfg_common_scell_r11->unpack(bref)); } - if (prach_cfg_scell_r11_present) { - prach_cfg_scell_r11 = make_copy_ptr(prach_cfg_s()); + if (prach_cfg_scell_r11.is_present()) { HANDLE_CODE(prach_cfg_scell_r11->unpack(bref)); } - if (tdd_cfg_v1130_present) { - tdd_cfg_v1130 = make_copy_ptr(tdd_cfg_v1130_s()); + if (tdd_cfg_v1130.is_present()) { HANDLE_CODE(tdd_cfg_v1130->unpack(bref)); } - if (ul_pwr_ctrl_common_scell_v1130_present) { - ul_pwr_ctrl_common_scell_v1130 = make_copy_ptr(ul_pwr_ctrl_common_scell_v1130_s()); + if (ul_pwr_ctrl_common_scell_v1130.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_scell_v1130->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool pusch_cfg_common_v1270_present; HANDLE_CODE(bref.unpack(pusch_cfg_common_v1270_present, 1)); - if (pusch_cfg_common_v1270_present) { - pusch_cfg_common_v1270 = make_copy_ptr(pusch_cfg_common_v1270_s()); + pusch_cfg_common_v1270.set_present(pusch_cfg_common_v1270_present); + if (pusch_cfg_common_v1270.is_present()) { HANDLE_CODE(pusch_cfg_common_v1270->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool pucch_cfg_common_r13_present; HANDLE_CODE(bref.unpack(pucch_cfg_common_r13_present, 1)); + pucch_cfg_common_r13.set_present(pucch_cfg_common_r13_present); + bool ul_pwr_ctrl_common_scell_v1310_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_scell_v1310_present, 1)); - if (pucch_cfg_common_r13_present) { - pucch_cfg_common_r13 = make_copy_ptr(pucch_cfg_common_s()); + ul_pwr_ctrl_common_scell_v1310.set_present(ul_pwr_ctrl_common_scell_v1310_present); + if (pucch_cfg_common_r13.is_present()) { HANDLE_CODE(pucch_cfg_common_r13->unpack(bref)); } - if (ul_pwr_ctrl_common_scell_v1310_present) { - ul_pwr_ctrl_common_scell_v1310 = make_copy_ptr(ul_pwr_ctrl_common_scell_v1310_s()); + if (ul_pwr_ctrl_common_scell_v1310.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_scell_v1310->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool high_speed_cfg_scell_r14_present; HANDLE_CODE(bref.unpack(high_speed_cfg_scell_r14_present, 1)); + high_speed_cfg_scell_r14.set_present(high_speed_cfg_scell_r14_present); + bool prach_cfg_v1430_present; HANDLE_CODE(bref.unpack(prach_cfg_v1430_present, 1)); + prach_cfg_v1430.set_present(prach_cfg_v1430_present); + bool ul_cfg_r14_present; HANDLE_CODE(bref.unpack(ul_cfg_r14_present, 1)); + ul_cfg_r14.set_present(ul_cfg_r14_present); HANDLE_CODE(bref.unpack(harq_ref_cfg_r14_present, 1)); HANDLE_CODE(bref.unpack(srs_flex_timing_r14_present, 1)); - if (high_speed_cfg_scell_r14_present) { - high_speed_cfg_scell_r14 = make_copy_ptr(high_speed_cfg_scell_r14_s()); + if (high_speed_cfg_scell_r14.is_present()) { HANDLE_CODE(high_speed_cfg_scell_r14->unpack(bref)); } - if (prach_cfg_v1430_present) { - prach_cfg_v1430 = make_copy_ptr(prach_cfg_v1430_s()); + if (prach_cfg_v1430.is_present()) { HANDLE_CODE(prach_cfg_v1430->unpack(bref)); } - if (ul_cfg_r14_present) { - ul_cfg_r14 = make_copy_ptr(ul_cfg_r14_s_()); + if (ul_cfg_r14.is_present()) { HANDLE_CODE(bref.unpack(ul_cfg_r14->p_max_r14_present, 1)); HANDLE_CODE(bref.unpack(ul_cfg_r14->prach_cfg_scell_r14_present, 1)); HANDLE_CODE(bref.unpack(ul_cfg_r14->ul_pwr_ctrl_common_pusch_less_cell_v1430_present, 1)); @@ -51920,20 +51218,22 @@ SRSASN_CODE rr_cfg_common_scell_r10_s::unpack(bit_ref& bref) } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mbsfn_sf_cfg_list_v1430_present; HANDLE_CODE(bref.unpack(mbsfn_sf_cfg_list_v1430_present, 1)); - if (mbsfn_sf_cfg_list_v1430_present) { - mbsfn_sf_cfg_list_v1430 = make_copy_ptr(mbsfn_sf_cfg_list_v1430_l()); + mbsfn_sf_cfg_list_v1430.set_present(mbsfn_sf_cfg_list_v1430_present); + if (mbsfn_sf_cfg_list_v1430.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*mbsfn_sf_cfg_list_v1430, bref, 1, 8)); } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_pwr_ctrl_common_scell_v1530_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_scell_v1530_present, 1)); - if (ul_pwr_ctrl_common_scell_v1530_present) { - ul_pwr_ctrl_common_scell_v1530 = make_copy_ptr(ul_pwr_ctrl_common_v1530_s()); + ul_pwr_ctrl_common_scell_v1530.set_present(ul_pwr_ctrl_common_scell_v1530_present); + if (ul_pwr_ctrl_common_scell_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_scell_v1530->unpack(bref)); } } @@ -51997,57 +51297,43 @@ void rr_cfg_common_scell_r10_s::to_json(json_writer& j) const if (ul_carrier_freq_v1090_present) { j.write_int("ul-CarrierFreq-v1090", ul_carrier_freq_v1090); } - rrc_asn1_warn_assert( - rach_cfg_common_scell_r11_present != (rach_cfg_common_scell_r11.get() != NULL), __FILE__, __LINE__); - if (rach_cfg_common_scell_r11_present) { + if (rach_cfg_common_scell_r11.is_present()) { j.write_fieldname("rach-ConfigCommonSCell-r11"); rach_cfg_common_scell_r11->to_json(j); } - rrc_asn1_warn_assert(prach_cfg_scell_r11_present != (prach_cfg_scell_r11.get() != NULL), __FILE__, __LINE__); - if (prach_cfg_scell_r11_present) { + if (prach_cfg_scell_r11.is_present()) { j.write_fieldname("prach-ConfigSCell-r11"); prach_cfg_scell_r11->to_json(j); } - rrc_asn1_warn_assert(tdd_cfg_v1130_present != (tdd_cfg_v1130.get() != NULL), __FILE__, __LINE__); - if (tdd_cfg_v1130_present) { + if (tdd_cfg_v1130.is_present()) { j.write_fieldname("tdd-Config-v1130"); tdd_cfg_v1130->to_json(j); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_scell_v1130_present != (ul_pwr_ctrl_common_scell_v1130.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_common_scell_v1130_present) { + if (ul_pwr_ctrl_common_scell_v1130.is_present()) { j.write_fieldname("uplinkPowerControlCommonSCell-v1130"); ul_pwr_ctrl_common_scell_v1130->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_common_v1270_present != (pusch_cfg_common_v1270.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_common_v1270_present) { + if (pusch_cfg_common_v1270.is_present()) { j.write_fieldname("pusch-ConfigCommon-v1270"); pusch_cfg_common_v1270->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_common_r13_present != (pucch_cfg_common_r13.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_common_r13_present) { + if (pucch_cfg_common_r13.is_present()) { j.write_fieldname("pucch-ConfigCommon-r13"); pucch_cfg_common_r13->to_json(j); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_scell_v1310_present != (ul_pwr_ctrl_common_scell_v1310.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_common_scell_v1310_present) { + if (ul_pwr_ctrl_common_scell_v1310.is_present()) { j.write_fieldname("uplinkPowerControlCommonSCell-v1310"); ul_pwr_ctrl_common_scell_v1310->to_json(j); } - rrc_asn1_warn_assert( - high_speed_cfg_scell_r14_present != (high_speed_cfg_scell_r14.get() != NULL), __FILE__, __LINE__); - if (high_speed_cfg_scell_r14_present) { + if (high_speed_cfg_scell_r14.is_present()) { j.write_fieldname("highSpeedConfigSCell-r14"); high_speed_cfg_scell_r14->to_json(j); } - rrc_asn1_warn_assert(prach_cfg_v1430_present != (prach_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (prach_cfg_v1430_present) { + if (prach_cfg_v1430.is_present()) { j.write_fieldname("prach-Config-v1430"); prach_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert(ul_cfg_r14_present != (ul_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (ul_cfg_r14_present) { + if (ul_cfg_r14.is_present()) { j.write_fieldname("ul-Configuration-r14"); j.start_obj(); j.write_fieldname("ul-FreqInfo-r14"); @@ -52082,18 +51368,14 @@ void rr_cfg_common_scell_r10_s::to_json(json_writer& j) const if (srs_flex_timing_r14_present) { j.write_str("soundingRS-FlexibleTiming-r14", "true"); } - rrc_asn1_warn_assert( - mbsfn_sf_cfg_list_v1430_present != (mbsfn_sf_cfg_list_v1430.get() != NULL), __FILE__, __LINE__); - if (mbsfn_sf_cfg_list_v1430_present) { + if (mbsfn_sf_cfg_list_v1430.is_present()) { j.start_array("mbsfn-SubframeConfigList-v1430"); for (uint32_t i1 = 0; i1 < mbsfn_sf_cfg_list_v1430->size(); ++i1) { ((*mbsfn_sf_cfg_list_v1430)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_scell_v1530_present != (ul_pwr_ctrl_common_scell_v1530.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_common_scell_v1530_present) { + if (ul_pwr_ctrl_common_scell_v1530.is_present()) { j.write_fieldname("uplinkPowerControlCommonSCell-v1530"); ul_pwr_ctrl_common_scell_v1530->to_json(j); } @@ -52112,70 +51394,61 @@ SRSASN_CODE rr_cfg_ded_scell_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(5); - rrc_asn1_warn_assert(mac_main_cfg_scell_r11_present != (mac_main_cfg_scell_r11.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= mac_main_cfg_scell_r11_present; - rrc_asn1_warn_assert(naics_info_r12_present != (naics_info_r12.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= naics_info_r12_present; - rrc_asn1_warn_assert( - neigh_cells_crs_info_scell_r13_present != (neigh_cells_crs_info_scell_r13.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= neigh_cells_crs_info_scell_r13_present; - rrc_asn1_warn_assert( - phys_cfg_ded_scell_v1370_present != (phys_cfg_ded_scell_v1370.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= phys_cfg_ded_scell_v1370_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= mac_main_cfg_scell_r11.is_present(); + group_flags[1] |= naics_info_r12.is_present(); + group_flags[2] |= neigh_cells_crs_info_scell_r13.is_present(); + group_flags[3] |= phys_cfg_ded_scell_v1370.is_present(); group_flags[4] |= crs_intf_mitig_enabled_r15_present; - rrc_asn1_warn_assert( - neigh_cells_crs_info_r15_present != (neigh_cells_crs_info_r15.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= neigh_cells_crs_info_r15_present; - rrc_asn1_warn_assert(sps_cfg_v1530_present != (sps_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= sps_cfg_v1530_present; + group_flags[4] |= neigh_cells_crs_info_r15.is_present(); + group_flags[4] |= sps_cfg_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mac_main_cfg_scell_r11_present, 1)); - if (mac_main_cfg_scell_r11_present) { + HANDLE_CODE(bref.pack(mac_main_cfg_scell_r11.is_present(), 1)); + if (mac_main_cfg_scell_r11.is_present()) { HANDLE_CODE(mac_main_cfg_scell_r11->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(naics_info_r12_present, 1)); - if (naics_info_r12_present) { + HANDLE_CODE(bref.pack(naics_info_r12.is_present(), 1)); + if (naics_info_r12.is_present()) { HANDLE_CODE(naics_info_r12->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(neigh_cells_crs_info_scell_r13_present, 1)); - if (neigh_cells_crs_info_scell_r13_present) { + HANDLE_CODE(bref.pack(neigh_cells_crs_info_scell_r13.is_present(), 1)); + if (neigh_cells_crs_info_scell_r13.is_present()) { HANDLE_CODE(neigh_cells_crs_info_scell_r13->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(phys_cfg_ded_scell_v1370_present, 1)); - if (phys_cfg_ded_scell_v1370_present) { + HANDLE_CODE(bref.pack(phys_cfg_ded_scell_v1370.is_present(), 1)); + if (phys_cfg_ded_scell_v1370.is_present()) { HANDLE_CODE(phys_cfg_ded_scell_v1370->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(crs_intf_mitig_enabled_r15_present, 1)); - HANDLE_CODE(bref.pack(neigh_cells_crs_info_r15_present, 1)); - HANDLE_CODE(bref.pack(sps_cfg_v1530_present, 1)); + HANDLE_CODE(bref.pack(neigh_cells_crs_info_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(sps_cfg_v1530.is_present(), 1)); if (crs_intf_mitig_enabled_r15_present) { HANDLE_CODE(bref.pack(crs_intf_mitig_enabled_r15, 1)); } - if (neigh_cells_crs_info_r15_present) { + if (neigh_cells_crs_info_r15.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r15->pack(bref)); } - if (sps_cfg_v1530_present) { + if (sps_cfg_v1530.is_present()) { HANDLE_CODE(sps_cfg_v1530->pack(bref)); } } @@ -52192,60 +51465,66 @@ SRSASN_CODE rr_cfg_ded_scell_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(5); + ext_groups_unpacker_guard group_flags(5); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mac_main_cfg_scell_r11_present; HANDLE_CODE(bref.unpack(mac_main_cfg_scell_r11_present, 1)); - if (mac_main_cfg_scell_r11_present) { - mac_main_cfg_scell_r11 = make_copy_ptr(mac_main_cfg_scell_r11_s()); + mac_main_cfg_scell_r11.set_present(mac_main_cfg_scell_r11_present); + if (mac_main_cfg_scell_r11.is_present()) { HANDLE_CODE(mac_main_cfg_scell_r11->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool naics_info_r12_present; HANDLE_CODE(bref.unpack(naics_info_r12_present, 1)); - if (naics_info_r12_present) { - naics_info_r12 = make_copy_ptr(naics_assist_info_r12_c()); + naics_info_r12.set_present(naics_info_r12_present); + if (naics_info_r12.is_present()) { HANDLE_CODE(naics_info_r12->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool neigh_cells_crs_info_scell_r13_present; HANDLE_CODE(bref.unpack(neigh_cells_crs_info_scell_r13_present, 1)); - if (neigh_cells_crs_info_scell_r13_present) { - neigh_cells_crs_info_scell_r13 = make_copy_ptr(neigh_cells_crs_info_r13_c()); + neigh_cells_crs_info_scell_r13.set_present(neigh_cells_crs_info_scell_r13_present); + if (neigh_cells_crs_info_scell_r13.is_present()) { HANDLE_CODE(neigh_cells_crs_info_scell_r13->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool phys_cfg_ded_scell_v1370_present; HANDLE_CODE(bref.unpack(phys_cfg_ded_scell_v1370_present, 1)); - if (phys_cfg_ded_scell_v1370_present) { - phys_cfg_ded_scell_v1370 = make_copy_ptr(phys_cfg_ded_scell_v1370_s()); + phys_cfg_ded_scell_v1370.set_present(phys_cfg_ded_scell_v1370_present); + if (phys_cfg_ded_scell_v1370.is_present()) { HANDLE_CODE(phys_cfg_ded_scell_v1370->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(crs_intf_mitig_enabled_r15_present, 1)); + bool neigh_cells_crs_info_r15_present; HANDLE_CODE(bref.unpack(neigh_cells_crs_info_r15_present, 1)); + neigh_cells_crs_info_r15.set_present(neigh_cells_crs_info_r15_present); + bool sps_cfg_v1530_present; HANDLE_CODE(bref.unpack(sps_cfg_v1530_present, 1)); + sps_cfg_v1530.set_present(sps_cfg_v1530_present); if (crs_intf_mitig_enabled_r15_present) { HANDLE_CODE(bref.unpack(crs_intf_mitig_enabled_r15, 1)); } - if (neigh_cells_crs_info_r15_present) { - neigh_cells_crs_info_r15 = make_copy_ptr(neigh_cells_crs_info_r15_c()); + if (neigh_cells_crs_info_r15.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r15->unpack(bref)); } - if (sps_cfg_v1530_present) { - sps_cfg_v1530 = make_copy_ptr(sps_cfg_v1530_s()); + if (sps_cfg_v1530.is_present()) { HANDLE_CODE(sps_cfg_v1530->unpack(bref)); } } @@ -52260,39 +51539,30 @@ void rr_cfg_ded_scell_r10_s::to_json(json_writer& j) const phys_cfg_ded_scell_r10.to_json(j); } if (ext) { - rrc_asn1_warn_assert(mac_main_cfg_scell_r11_present != (mac_main_cfg_scell_r11.get() != NULL), __FILE__, __LINE__); - if (mac_main_cfg_scell_r11_present) { + if (mac_main_cfg_scell_r11.is_present()) { j.write_fieldname("mac-MainConfigSCell-r11"); mac_main_cfg_scell_r11->to_json(j); } - rrc_asn1_warn_assert(naics_info_r12_present != (naics_info_r12.get() != NULL), __FILE__, __LINE__); - if (naics_info_r12_present) { + if (naics_info_r12.is_present()) { j.write_fieldname("naics-Info-r12"); naics_info_r12->to_json(j); } - rrc_asn1_warn_assert( - neigh_cells_crs_info_scell_r13_present != (neigh_cells_crs_info_scell_r13.get() != NULL), __FILE__, __LINE__); - if (neigh_cells_crs_info_scell_r13_present) { + if (neigh_cells_crs_info_scell_r13.is_present()) { j.write_fieldname("neighCellsCRS-InfoSCell-r13"); neigh_cells_crs_info_scell_r13->to_json(j); } - rrc_asn1_warn_assert( - phys_cfg_ded_scell_v1370_present != (phys_cfg_ded_scell_v1370.get() != NULL), __FILE__, __LINE__); - if (phys_cfg_ded_scell_v1370_present) { + if (phys_cfg_ded_scell_v1370.is_present()) { j.write_fieldname("physicalConfigDedicatedSCell-v1370"); phys_cfg_ded_scell_v1370->to_json(j); } if (crs_intf_mitig_enabled_r15_present) { j.write_bool("crs-IntfMitigEnabled-r15", crs_intf_mitig_enabled_r15); } - rrc_asn1_warn_assert( - neigh_cells_crs_info_r15_present != (neigh_cells_crs_info_r15.get() != NULL), __FILE__, __LINE__); - if (neigh_cells_crs_info_r15_present) { + if (neigh_cells_crs_info_r15.is_present()) { j.write_fieldname("neighCellsCRS-Info-r15"); neigh_cells_crs_info_r15->to_json(j); } - rrc_asn1_warn_assert(sps_cfg_v1530_present != (sps_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (sps_cfg_v1530_present) { + if (sps_cfg_v1530.is_present()) { j.write_fieldname("sps-Config-v1530"); sps_cfg_v1530->to_json(j); } @@ -52636,38 +51906,34 @@ SRSASN_CODE drb_to_add_mod_scg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(rlc_cfg_v1430_present != (rlc_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rlc_cfg_v1430_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= rlc_cfg_v1430.is_present(); group_flags[1] |= lc_ch_id_scg_r15_present; - rrc_asn1_warn_assert(rlc_cfg_v1530_present != (rlc_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= rlc_cfg_v1530_present; - rrc_asn1_warn_assert( - rlc_bearer_cfg_dupl_r15_present != (rlc_bearer_cfg_dupl_r15.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= rlc_bearer_cfg_dupl_r15_present; + group_flags[1] |= rlc_cfg_v1530.is_present(); + group_flags[1] |= rlc_bearer_cfg_dupl_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rlc_cfg_v1430_present, 1)); - if (rlc_cfg_v1430_present) { + HANDLE_CODE(bref.pack(rlc_cfg_v1430.is_present(), 1)); + if (rlc_cfg_v1430.is_present()) { HANDLE_CODE(rlc_cfg_v1430->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(lc_ch_id_scg_r15_present, 1)); - HANDLE_CODE(bref.pack(rlc_cfg_v1530_present, 1)); - HANDLE_CODE(bref.pack(rlc_bearer_cfg_dupl_r15_present, 1)); + HANDLE_CODE(bref.pack(rlc_cfg_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(rlc_bearer_cfg_dupl_r15.is_present(), 1)); if (lc_ch_id_scg_r15_present) { HANDLE_CODE(pack_unalign_integer(bref, lc_ch_id_scg_r15, (uint8_t)32, (uint8_t)38)); } - if (rlc_cfg_v1530_present) { + if (rlc_cfg_v1530.is_present()) { HANDLE_CODE(rlc_cfg_v1530->pack(bref)); } - if (rlc_bearer_cfg_dupl_r15_present) { + if (rlc_bearer_cfg_dupl_r15.is_present()) { HANDLE_CODE(rlc_bearer_cfg_dupl_r15->pack(bref)); } } @@ -52701,33 +51967,36 @@ SRSASN_CODE drb_to_add_mod_scg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rlc_cfg_v1430_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1430_present, 1)); - if (rlc_cfg_v1430_present) { - rlc_cfg_v1430 = make_copy_ptr(rlc_cfg_v1430_c()); + rlc_cfg_v1430.set_present(rlc_cfg_v1430_present); + if (rlc_cfg_v1430.is_present()) { HANDLE_CODE(rlc_cfg_v1430->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(lc_ch_id_scg_r15_present, 1)); + bool rlc_cfg_v1530_present; HANDLE_CODE(bref.unpack(rlc_cfg_v1530_present, 1)); + rlc_cfg_v1530.set_present(rlc_cfg_v1530_present); + bool rlc_bearer_cfg_dupl_r15_present; HANDLE_CODE(bref.unpack(rlc_bearer_cfg_dupl_r15_present, 1)); + rlc_bearer_cfg_dupl_r15.set_present(rlc_bearer_cfg_dupl_r15_present); if (lc_ch_id_scg_r15_present) { HANDLE_CODE(unpack_unalign_integer(lc_ch_id_scg_r15, bref, (uint8_t)32, (uint8_t)38)); } - if (rlc_cfg_v1530_present) { - rlc_cfg_v1530 = make_copy_ptr(rlc_cfg_v1530_c()); + if (rlc_cfg_v1530.is_present()) { HANDLE_CODE(rlc_cfg_v1530->unpack(bref)); } - if (rlc_bearer_cfg_dupl_r15_present) { - rlc_bearer_cfg_dupl_r15 = make_copy_ptr(rlc_bearer_cfg_r15_c()); + if (rlc_bearer_cfg_dupl_r15.is_present()) { HANDLE_CODE(rlc_bearer_cfg_dupl_r15->unpack(bref)); } } @@ -52758,22 +52027,18 @@ void drb_to_add_mod_scg_r12_s::to_json(json_writer& j) const lc_ch_cfg_scg_r12.to_json(j); } if (ext) { - rrc_asn1_warn_assert(rlc_cfg_v1430_present != (rlc_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1430_present) { + if (rlc_cfg_v1430.is_present()) { j.write_fieldname("rlc-Config-v1430"); rlc_cfg_v1430->to_json(j); } if (lc_ch_id_scg_r15_present) { j.write_int("logicalChannelIdentitySCG-r15", lc_ch_id_scg_r15); } - rrc_asn1_warn_assert(rlc_cfg_v1530_present != (rlc_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (rlc_cfg_v1530_present) { + if (rlc_cfg_v1530.is_present()) { j.write_fieldname("rlc-Config-v1530"); rlc_cfg_v1530->to_json(j); } - rrc_asn1_warn_assert( - rlc_bearer_cfg_dupl_r15_present != (rlc_bearer_cfg_dupl_r15.get() != NULL), __FILE__, __LINE__); - if (rlc_bearer_cfg_dupl_r15_present) { + if (rlc_bearer_cfg_dupl_r15.is_present()) { j.write_fieldname("rlc-BearerConfigDupl-r15"); rlc_bearer_cfg_dupl_r15->to_json(j); } @@ -54047,30 +53312,24 @@ SRSASN_CODE rr_cfg_common_ps_cell_r12_s::pack(bit_ref& bref) const HANDLE_CODE(ul_pwr_ctrl_common_ps_cell_r12.pack(bref)); if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(ul_pwr_ctrl_common_ps_cell_v1310_present != (ul_pwr_ctrl_common_ps_cell_v1310.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= ul_pwr_ctrl_common_ps_cell_v1310_present; - rrc_asn1_warn_assert(ul_pwr_ctrl_common_ps_cell_v1530_present != (ul_pwr_ctrl_common_ps_cell_v1530.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= ul_pwr_ctrl_common_ps_cell_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= ul_pwr_ctrl_common_ps_cell_v1310.is_present(); + group_flags[1] |= ul_pwr_ctrl_common_ps_cell_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_ps_cell_v1310_present, 1)); - if (ul_pwr_ctrl_common_ps_cell_v1310_present) { + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_ps_cell_v1310.is_present(), 1)); + if (ul_pwr_ctrl_common_ps_cell_v1310.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_ps_cell_v1310->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_ps_cell_v1530_present, 1)); - if (ul_pwr_ctrl_common_ps_cell_v1530_present) { + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_ps_cell_v1530.is_present(), 1)); + if (ul_pwr_ctrl_common_ps_cell_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_ps_cell_v1530->pack(bref)); } } @@ -54086,24 +53345,26 @@ SRSASN_CODE rr_cfg_common_ps_cell_r12_s::unpack(bit_ref& bref) HANDLE_CODE(ul_pwr_ctrl_common_ps_cell_r12.unpack(bref)); if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_pwr_ctrl_common_ps_cell_v1310_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_ps_cell_v1310_present, 1)); - if (ul_pwr_ctrl_common_ps_cell_v1310_present) { - ul_pwr_ctrl_common_ps_cell_v1310 = make_copy_ptr(ul_pwr_ctrl_common_v1310_s()); + ul_pwr_ctrl_common_ps_cell_v1310.set_present(ul_pwr_ctrl_common_ps_cell_v1310_present); + if (ul_pwr_ctrl_common_ps_cell_v1310.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_ps_cell_v1310->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_pwr_ctrl_common_ps_cell_v1530_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_ps_cell_v1530_present, 1)); - if (ul_pwr_ctrl_common_ps_cell_v1530_present) { - ul_pwr_ctrl_common_ps_cell_v1530 = make_copy_ptr(ul_pwr_ctrl_common_v1530_s()); + ul_pwr_ctrl_common_ps_cell_v1530.set_present(ul_pwr_ctrl_common_ps_cell_v1530_present); + if (ul_pwr_ctrl_common_ps_cell_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_ps_cell_v1530->unpack(bref)); } } @@ -54122,17 +53383,11 @@ void rr_cfg_common_ps_cell_r12_s::to_json(json_writer& j) const j.write_fieldname("uplinkPowerControlCommonPSCell-r12"); ul_pwr_ctrl_common_ps_cell_r12.to_json(j); if (ext) { - rrc_asn1_warn_assert(ul_pwr_ctrl_common_ps_cell_v1310_present != (ul_pwr_ctrl_common_ps_cell_v1310.get() != NULL), - __FILE__, - __LINE__); - if (ul_pwr_ctrl_common_ps_cell_v1310_present) { + if (ul_pwr_ctrl_common_ps_cell_v1310.is_present()) { j.write_fieldname("uplinkPowerControlCommonPSCell-v1310"); ul_pwr_ctrl_common_ps_cell_v1310->to_json(j); } - rrc_asn1_warn_assert(ul_pwr_ctrl_common_ps_cell_v1530_present != (ul_pwr_ctrl_common_ps_cell_v1530.get() != NULL), - __FILE__, - __LINE__); - if (ul_pwr_ctrl_common_ps_cell_v1530_present) { + if (ul_pwr_ctrl_common_ps_cell_v1530.is_present()) { j.write_fieldname("uplinkPowerControlCommonPSCell-v1530"); ul_pwr_ctrl_common_ps_cell_v1530->to_json(j); } @@ -54201,50 +53456,43 @@ SRSASN_CODE rr_cfg_ded_ps_cell_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); - rrc_asn1_warn_assert(neigh_cells_crs_info_ps_cell_r13_present != (neigh_cells_crs_info_ps_cell_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= neigh_cells_crs_info_ps_cell_r13_present; - rrc_asn1_warn_assert(sps_cfg_v1430_present != (sps_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= sps_cfg_v1430_present; - rrc_asn1_warn_assert(sps_cfg_v1530_present != (sps_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= sps_cfg_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= neigh_cells_crs_info_ps_cell_r13.is_present(); + group_flags[1] |= sps_cfg_v1430.is_present(); + group_flags[2] |= sps_cfg_v1530.is_present(); group_flags[2] |= crs_intf_mitig_enabled_r15_present; - rrc_asn1_warn_assert( - neigh_cells_crs_info_r15_present != (neigh_cells_crs_info_r15.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= neigh_cells_crs_info_r15_present; + group_flags[2] |= neigh_cells_crs_info_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(neigh_cells_crs_info_ps_cell_r13_present, 1)); - if (neigh_cells_crs_info_ps_cell_r13_present) { + HANDLE_CODE(bref.pack(neigh_cells_crs_info_ps_cell_r13.is_present(), 1)); + if (neigh_cells_crs_info_ps_cell_r13.is_present()) { HANDLE_CODE(neigh_cells_crs_info_ps_cell_r13->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(sps_cfg_v1430_present, 1)); - if (sps_cfg_v1430_present) { + HANDLE_CODE(bref.pack(sps_cfg_v1430.is_present(), 1)); + if (sps_cfg_v1430.is_present()) { HANDLE_CODE(sps_cfg_v1430->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(sps_cfg_v1530_present, 1)); + HANDLE_CODE(bref.pack(sps_cfg_v1530.is_present(), 1)); HANDLE_CODE(bref.pack(crs_intf_mitig_enabled_r15_present, 1)); - HANDLE_CODE(bref.pack(neigh_cells_crs_info_r15_present, 1)); - if (sps_cfg_v1530_present) { + HANDLE_CODE(bref.pack(neigh_cells_crs_info_r15.is_present(), 1)); + if (sps_cfg_v1530.is_present()) { HANDLE_CODE(sps_cfg_v1530->pack(bref)); } if (crs_intf_mitig_enabled_r15_present) { HANDLE_CODE(bref.pack(crs_intf_mitig_enabled_r15, 1)); } - if (neigh_cells_crs_info_r15_present) { + if (neigh_cells_crs_info_r15.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r15->pack(bref)); } } @@ -54269,42 +53517,46 @@ SRSASN_CODE rr_cfg_ded_ps_cell_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool neigh_cells_crs_info_ps_cell_r13_present; HANDLE_CODE(bref.unpack(neigh_cells_crs_info_ps_cell_r13_present, 1)); - if (neigh_cells_crs_info_ps_cell_r13_present) { - neigh_cells_crs_info_ps_cell_r13 = make_copy_ptr(neigh_cells_crs_info_r13_c()); + neigh_cells_crs_info_ps_cell_r13.set_present(neigh_cells_crs_info_ps_cell_r13_present); + if (neigh_cells_crs_info_ps_cell_r13.is_present()) { HANDLE_CODE(neigh_cells_crs_info_ps_cell_r13->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool sps_cfg_v1430_present; HANDLE_CODE(bref.unpack(sps_cfg_v1430_present, 1)); - if (sps_cfg_v1430_present) { - sps_cfg_v1430 = make_copy_ptr(sps_cfg_v1430_s()); + sps_cfg_v1430.set_present(sps_cfg_v1430_present); + if (sps_cfg_v1430.is_present()) { HANDLE_CODE(sps_cfg_v1430->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool sps_cfg_v1530_present; HANDLE_CODE(bref.unpack(sps_cfg_v1530_present, 1)); + sps_cfg_v1530.set_present(sps_cfg_v1530_present); HANDLE_CODE(bref.unpack(crs_intf_mitig_enabled_r15_present, 1)); + bool neigh_cells_crs_info_r15_present; HANDLE_CODE(bref.unpack(neigh_cells_crs_info_r15_present, 1)); - if (sps_cfg_v1530_present) { - sps_cfg_v1530 = make_copy_ptr(sps_cfg_v1530_s()); + neigh_cells_crs_info_r15.set_present(neigh_cells_crs_info_r15_present); + if (sps_cfg_v1530.is_present()) { HANDLE_CODE(sps_cfg_v1530->unpack(bref)); } if (crs_intf_mitig_enabled_r15_present) { HANDLE_CODE(bref.unpack(crs_intf_mitig_enabled_r15, 1)); } - if (neigh_cells_crs_info_r15_present) { - neigh_cells_crs_info_r15 = make_copy_ptr(neigh_cells_crs_info_r15_c()); + if (neigh_cells_crs_info_r15.is_present()) { HANDLE_CODE(neigh_cells_crs_info_r15->unpack(bref)); } } @@ -54327,29 +53579,22 @@ void rr_cfg_ded_ps_cell_r12_s::to_json(json_writer& j) const naics_info_r12.to_json(j); } if (ext) { - rrc_asn1_warn_assert(neigh_cells_crs_info_ps_cell_r13_present != (neigh_cells_crs_info_ps_cell_r13.get() != NULL), - __FILE__, - __LINE__); - if (neigh_cells_crs_info_ps_cell_r13_present) { + if (neigh_cells_crs_info_ps_cell_r13.is_present()) { j.write_fieldname("neighCellsCRS-InfoPSCell-r13"); neigh_cells_crs_info_ps_cell_r13->to_json(j); } - rrc_asn1_warn_assert(sps_cfg_v1430_present != (sps_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (sps_cfg_v1430_present) { + if (sps_cfg_v1430.is_present()) { j.write_fieldname("sps-Config-v1430"); sps_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert(sps_cfg_v1530_present != (sps_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (sps_cfg_v1530_present) { + if (sps_cfg_v1530.is_present()) { j.write_fieldname("sps-Config-v1530"); sps_cfg_v1530->to_json(j); } if (crs_intf_mitig_enabled_r15_present) { j.write_bool("crs-IntfMitigEnabled-r15", crs_intf_mitig_enabled_r15); } - rrc_asn1_warn_assert( - neigh_cells_crs_info_r15_present != (neigh_cells_crs_info_r15.get() != NULL), __FILE__, __LINE__); - if (neigh_cells_crs_info_r15_present) { + if (neigh_cells_crs_info_r15.is_present()) { j.write_fieldname("neighCellsCRS-Info-r15"); neigh_cells_crs_info_r15->to_json(j); } @@ -54409,17 +53654,15 @@ SRSASN_CODE scell_to_add_mod_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); + ext_groups_packer_guard group_flags; group_flags[0] |= dl_carrier_freq_v1090_present; - rrc_asn1_warn_assert( - ant_info_ded_scell_v10i0_present != (ant_info_ded_scell_v10i0.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= ant_info_ded_scell_v10i0_present; + group_flags[1] |= ant_info_ded_scell_v10i0.is_present(); group_flags[2] |= srs_switch_from_serv_cell_idx_r14_present; group_flags[3] |= s_cell_state_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(dl_carrier_freq_v1090_present, 1)); if (dl_carrier_freq_v1090_present) { @@ -54427,15 +53670,15 @@ SRSASN_CODE scell_to_add_mod_r10_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ant_info_ded_scell_v10i0_present, 1)); - if (ant_info_ded_scell_v10i0_present) { + HANDLE_CODE(bref.pack(ant_info_ded_scell_v10i0.is_present(), 1)); + if (ant_info_ded_scell_v10i0.is_present()) { HANDLE_CODE(ant_info_ded_scell_v10i0->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(srs_switch_from_serv_cell_idx_r14_present, 1)); if (srs_switch_from_serv_cell_idx_r14_present) { @@ -54443,7 +53686,7 @@ SRSASN_CODE scell_to_add_mod_r10_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(s_cell_state_r15_present, 1)); if (s_cell_state_r15_present) { @@ -54473,11 +53716,11 @@ SRSASN_CODE scell_to_add_mod_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(dl_carrier_freq_v1090_present, 1)); if (dl_carrier_freq_v1090_present) { @@ -54485,16 +53728,17 @@ SRSASN_CODE scell_to_add_mod_r10_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ant_info_ded_scell_v10i0_present; HANDLE_CODE(bref.unpack(ant_info_ded_scell_v10i0_present, 1)); - if (ant_info_ded_scell_v10i0_present) { - ant_info_ded_scell_v10i0 = make_copy_ptr(ant_info_ded_v10i0_s()); + ant_info_ded_scell_v10i0.set_present(ant_info_ded_scell_v10i0_present); + if (ant_info_ded_scell_v10i0.is_present()) { HANDLE_CODE(ant_info_ded_scell_v10i0->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(srs_switch_from_serv_cell_idx_r14_present, 1)); if (srs_switch_from_serv_cell_idx_r14_present) { @@ -54502,7 +53746,7 @@ SRSASN_CODE scell_to_add_mod_r10_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(s_cell_state_r15_present, 1)); if (s_cell_state_r15_present) { @@ -54535,9 +53779,7 @@ void scell_to_add_mod_r10_s::to_json(json_writer& j) const if (dl_carrier_freq_v1090_present) { j.write_int("dl-CarrierFreq-v1090", dl_carrier_freq_v1090); } - rrc_asn1_warn_assert( - ant_info_ded_scell_v10i0_present != (ant_info_ded_scell_v10i0.get() != NULL), __FILE__, __LINE__); - if (ant_info_ded_scell_v10i0_present) { + if (ant_info_ded_scell_v10i0.is_present()) { j.write_fieldname("antennaInfoDedicatedSCell-v10i0"); ant_info_ded_scell_v10i0->to_json(j); } @@ -54624,12 +53866,12 @@ SRSASN_CODE scell_to_add_mod_ext_v1430_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= s_cell_state_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(s_cell_state_r15_present, 1)); if (s_cell_state_r15_present) { @@ -54649,11 +53891,11 @@ SRSASN_CODE scell_to_add_mod_ext_v1430_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(s_cell_state_r15_present, 1)); if (s_cell_state_r15_present) { @@ -54938,12 +54180,12 @@ SRSASN_CODE tunnel_cfg_lwip_r13_s::pack(bit_ref& bref) const HANDLE_CODE(ike_id_r13.pack(bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= lwip_counter_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(lwip_counter_r13_present, 1)); if (lwip_counter_r13_present) { @@ -54960,11 +54202,11 @@ SRSASN_CODE tunnel_cfg_lwip_r13_s::unpack(bit_ref& bref) HANDLE_CODE(ike_id_r13.unpack(bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(lwip_counter_r13_present, 1)); if (lwip_counter_r13_present) { @@ -55009,16 +54251,15 @@ SRSASN_CODE wlan_mob_cfg_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(wlan_suspend_cfg_r14_present != (wlan_suspend_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= wlan_suspend_cfg_r14_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= wlan_suspend_cfg_r14.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(wlan_suspend_cfg_r14_present, 1)); - if (wlan_suspend_cfg_r14_present) { + HANDLE_CODE(bref.pack(wlan_suspend_cfg_r14.is_present(), 1)); + if (wlan_suspend_cfg_r14.is_present()) { HANDLE_CODE(wlan_suspend_cfg_r14->pack(bref)); } } @@ -55044,15 +54285,16 @@ SRSASN_CODE wlan_mob_cfg_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool wlan_suspend_cfg_r14_present; HANDLE_CODE(bref.unpack(wlan_suspend_cfg_r14_present, 1)); - if (wlan_suspend_cfg_r14_present) { - wlan_suspend_cfg_r14 = make_copy_ptr(wlan_suspend_cfg_r14_s()); + wlan_suspend_cfg_r14.set_present(wlan_suspend_cfg_r14_present); + if (wlan_suspend_cfg_r14.is_present()) { HANDLE_CODE(wlan_suspend_cfg_r14->unpack(bref)); } } @@ -55083,8 +54325,7 @@ void wlan_mob_cfg_r13_s::to_json(json_writer& j) const j.write_str("successReportRequested-r13", "true"); } if (ext) { - rrc_asn1_warn_assert(wlan_suspend_cfg_r14_present != (wlan_suspend_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (wlan_suspend_cfg_r14_present) { + if (wlan_suspend_cfg_r14.is_present()) { j.write_fieldname("wlan-SuspendConfig-r14"); wlan_suspend_cfg_r14->to_json(j); } @@ -55107,12 +54348,12 @@ SRSASN_CODE lwa_cfg_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= wt_mac_address_r14_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(wt_mac_address_r14_present, 1)); if (wt_mac_address_r14_present) { @@ -55136,11 +54377,11 @@ SRSASN_CODE lwa_cfg_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(wt_mac_address_r14_present, 1)); if (wt_mac_address_r14_present) { @@ -55233,18 +54474,17 @@ SRSASN_CODE mob_ctrl_info_scg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= make_before_break_scg_r14_present; - rrc_asn1_warn_assert(rach_skip_scg_r14_present != (rach_skip_scg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= rach_skip_scg_r14_present; + group_flags[0] |= rach_skip_scg_r14.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(make_before_break_scg_r14_present, 1)); - HANDLE_CODE(bref.pack(rach_skip_scg_r14_present, 1)); - if (rach_skip_scg_r14_present) { + HANDLE_CODE(bref.pack(rach_skip_scg_r14.is_present(), 1)); + if (rach_skip_scg_r14.is_present()) { HANDLE_CODE(rach_skip_scg_r14->pack(bref)); } } @@ -55270,16 +54510,17 @@ SRSASN_CODE mob_ctrl_info_scg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(make_before_break_scg_r14_present, 1)); + bool rach_skip_scg_r14_present; HANDLE_CODE(bref.unpack(rach_skip_scg_r14_present, 1)); - if (rach_skip_scg_r14_present) { - rach_skip_scg_r14 = make_copy_ptr(rach_skip_r14_s()); + rach_skip_scg_r14.set_present(rach_skip_scg_r14_present); + if (rach_skip_scg_r14.is_present()) { HANDLE_CODE(rach_skip_scg_r14->unpack(bref)); } } @@ -55304,8 +54545,7 @@ void mob_ctrl_info_scg_r12_s::to_json(json_writer& j) const if (make_before_break_scg_r14_present) { j.write_str("makeBeforeBreakSCG-r14", "true"); } - rrc_asn1_warn_assert(rach_skip_scg_r14_present != (rach_skip_scg_r14.get() != NULL), __FILE__, __LINE__); - if (rach_skip_scg_r14_present) { + if (rach_skip_scg_r14.is_present()) { j.write_fieldname("rach-SkipSCG-r14"); rach_skip_scg_r14->to_json(j); } @@ -55334,26 +54574,22 @@ SRSASN_CODE ps_cell_to_add_mod_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); - rrc_asn1_warn_assert( - ant_info_ded_ps_cell_v1280_present != (ant_info_ded_ps_cell_v1280.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ant_info_ded_ps_cell_v1280_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= ant_info_ded_ps_cell_v1280.is_present(); group_flags[1] |= s_cell_idx_r13_present; - rrc_asn1_warn_assert( - rr_cfg_ded_ps_cell_v1370_present != (rr_cfg_ded_ps_cell_v1370.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= rr_cfg_ded_ps_cell_v1370_present; + group_flags[2] |= rr_cfg_ded_ps_cell_v1370.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ant_info_ded_ps_cell_v1280_present, 1)); - if (ant_info_ded_ps_cell_v1280_present) { + HANDLE_CODE(bref.pack(ant_info_ded_ps_cell_v1280.is_present(), 1)); + if (ant_info_ded_ps_cell_v1280.is_present()) { HANDLE_CODE(ant_info_ded_ps_cell_v1280->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(s_cell_idx_r13_present, 1)); if (s_cell_idx_r13_present) { @@ -55361,10 +54597,10 @@ SRSASN_CODE ps_cell_to_add_mod_r12_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(rr_cfg_ded_ps_cell_v1370_present, 1)); - if (rr_cfg_ded_ps_cell_v1370_present) { + HANDLE_CODE(bref.pack(rr_cfg_ded_ps_cell_v1370.is_present(), 1)); + if (rr_cfg_ded_ps_cell_v1370.is_present()) { HANDLE_CODE(rr_cfg_ded_ps_cell_v1370->pack(bref)); } } @@ -55391,20 +54627,21 @@ SRSASN_CODE ps_cell_to_add_mod_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ant_info_ded_ps_cell_v1280_present; HANDLE_CODE(bref.unpack(ant_info_ded_ps_cell_v1280_present, 1)); - if (ant_info_ded_ps_cell_v1280_present) { - ant_info_ded_ps_cell_v1280 = make_copy_ptr(ant_info_ded_v10i0_s()); + ant_info_ded_ps_cell_v1280.set_present(ant_info_ded_ps_cell_v1280_present); + if (ant_info_ded_ps_cell_v1280.is_present()) { HANDLE_CODE(ant_info_ded_ps_cell_v1280->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(s_cell_idx_r13_present, 1)); if (s_cell_idx_r13_present) { @@ -55412,11 +54649,12 @@ SRSASN_CODE ps_cell_to_add_mod_r12_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool rr_cfg_ded_ps_cell_v1370_present; HANDLE_CODE(bref.unpack(rr_cfg_ded_ps_cell_v1370_present, 1)); - if (rr_cfg_ded_ps_cell_v1370_present) { - rr_cfg_ded_ps_cell_v1370 = make_copy_ptr(rr_cfg_ded_ps_cell_v1370_s()); + rr_cfg_ded_ps_cell_v1370.set_present(rr_cfg_ded_ps_cell_v1370_present); + if (rr_cfg_ded_ps_cell_v1370.is_present()) { HANDLE_CODE(rr_cfg_ded_ps_cell_v1370->unpack(bref)); } } @@ -55443,18 +54681,14 @@ void ps_cell_to_add_mod_r12_s::to_json(json_writer& j) const rr_cfg_ded_ps_cell_r12.to_json(j); } if (ext) { - rrc_asn1_warn_assert( - ant_info_ded_ps_cell_v1280_present != (ant_info_ded_ps_cell_v1280.get() != NULL), __FILE__, __LINE__); - if (ant_info_ded_ps_cell_v1280_present) { + if (ant_info_ded_ps_cell_v1280.is_present()) { j.write_fieldname("antennaInfoDedicatedPSCell-v1280"); ant_info_ded_ps_cell_v1280->to_json(j); } if (s_cell_idx_r13_present) { j.write_int("sCellIndex-r13", s_cell_idx_r13); } - rrc_asn1_warn_assert( - rr_cfg_ded_ps_cell_v1370_present != (rr_cfg_ded_ps_cell_v1370.get() != NULL), __FILE__, __LINE__); - if (rr_cfg_ded_ps_cell_v1370_present) { + if (rr_cfg_ded_ps_cell_v1370.is_present()) { j.write_fieldname("radioResourceConfigDedicatedPSCell-v1370"); rr_cfg_ded_ps_cell_v1370->to_json(j); } @@ -55845,17 +55079,15 @@ SRSASN_CODE rr_cfg_ded_scg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - drb_to_add_mod_list_scg_r15_present != (drb_to_add_mod_list_scg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= drb_to_add_mod_list_scg_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= drb_to_add_mod_list_scg_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(drb_to_add_mod_list_scg_r15_present, 1)); - if (drb_to_add_mod_list_scg_r15_present) { + HANDLE_CODE(bref.pack(drb_to_add_mod_list_scg_r15.is_present(), 1)); + if (drb_to_add_mod_list_scg_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *drb_to_add_mod_list_scg_r15, 1, 15)); } } @@ -55880,15 +55112,16 @@ SRSASN_CODE rr_cfg_ded_scg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool drb_to_add_mod_list_scg_r15_present; HANDLE_CODE(bref.unpack(drb_to_add_mod_list_scg_r15_present, 1)); - if (drb_to_add_mod_list_scg_r15_present) { - drb_to_add_mod_list_scg_r15 = make_copy_ptr(drb_to_add_mod_list_scg_r15_l()); + drb_to_add_mod_list_scg_r15.set_present(drb_to_add_mod_list_scg_r15_present); + if (drb_to_add_mod_list_scg_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*drb_to_add_mod_list_scg_r15, bref, 1, 15)); } } @@ -55914,9 +55147,7 @@ void rr_cfg_ded_scg_r12_s::to_json(json_writer& j) const rlf_timers_and_consts_scg_r12.to_json(j); } if (ext) { - rrc_asn1_warn_assert( - drb_to_add_mod_list_scg_r15_present != (drb_to_add_mod_list_scg_r15.get() != NULL), __FILE__, __LINE__); - if (drb_to_add_mod_list_scg_r15_present) { + if (drb_to_add_mod_list_scg_r15.is_present()) { j.start_array("drb-ToAddModListSCG-r15"); for (uint32_t i1 = 0; i1 < drb_to_add_mod_list_scg_r15->size(); ++i1) { ((*drb_to_add_mod_list_scg_r15)[i1]).to_json(j); @@ -56115,31 +55346,27 @@ SRSASN_CODE sl_v2x_cfg_ded_r14_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(comm_tx_res_v1530_present != (comm_tx_res_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= comm_tx_res_v1530_present; - rrc_asn1_warn_assert( - v2x_packet_dupl_cfg_r15_present != (v2x_packet_dupl_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= v2x_packet_dupl_cfg_r15_present; - rrc_asn1_warn_assert(sync_freq_list_r15_present != (sync_freq_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= sync_freq_list_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= comm_tx_res_v1530.is_present(); + group_flags[0] |= v2x_packet_dupl_cfg_r15.is_present(); + group_flags[0] |= sync_freq_list_r15.is_present(); group_flags[0] |= slss_tx_multi_freq_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(comm_tx_res_v1530_present, 1)); - HANDLE_CODE(bref.pack(v2x_packet_dupl_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(sync_freq_list_r15_present, 1)); + HANDLE_CODE(bref.pack(comm_tx_res_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(v2x_packet_dupl_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(sync_freq_list_r15.is_present(), 1)); HANDLE_CODE(bref.pack(slss_tx_multi_freq_r15_present, 1)); - if (comm_tx_res_v1530_present) { + if (comm_tx_res_v1530.is_present()) { HANDLE_CODE(comm_tx_res_v1530->pack(bref)); } - if (v2x_packet_dupl_cfg_r15_present) { + if (v2x_packet_dupl_cfg_r15.is_present()) { HANDLE_CODE(v2x_packet_dupl_cfg_r15->pack(bref)); } - if (sync_freq_list_r15_present) { + if (sync_freq_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *sync_freq_list_r15, 1, 8, UnalignedIntegerPacker(0, 262143))); } } @@ -56172,26 +55399,29 @@ SRSASN_CODE sl_v2x_cfg_ded_r14_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool comm_tx_res_v1530_present; HANDLE_CODE(bref.unpack(comm_tx_res_v1530_present, 1)); + comm_tx_res_v1530.set_present(comm_tx_res_v1530_present); + bool v2x_packet_dupl_cfg_r15_present; HANDLE_CODE(bref.unpack(v2x_packet_dupl_cfg_r15_present, 1)); + v2x_packet_dupl_cfg_r15.set_present(v2x_packet_dupl_cfg_r15_present); + bool sync_freq_list_r15_present; HANDLE_CODE(bref.unpack(sync_freq_list_r15_present, 1)); + sync_freq_list_r15.set_present(sync_freq_list_r15_present); HANDLE_CODE(bref.unpack(slss_tx_multi_freq_r15_present, 1)); - if (comm_tx_res_v1530_present) { - comm_tx_res_v1530 = make_copy_ptr(comm_tx_res_v1530_c_()); + if (comm_tx_res_v1530.is_present()) { HANDLE_CODE(comm_tx_res_v1530->unpack(bref)); } - if (v2x_packet_dupl_cfg_r15_present) { - v2x_packet_dupl_cfg_r15 = make_copy_ptr(sl_v2x_packet_dupl_cfg_r15_s()); + if (v2x_packet_dupl_cfg_r15.is_present()) { HANDLE_CODE(v2x_packet_dupl_cfg_r15->unpack(bref)); } - if (sync_freq_list_r15_present) { - sync_freq_list_r15 = make_copy_ptr(sl_v2x_sync_freq_list_r15_l()); + if (sync_freq_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*sync_freq_list_r15, bref, 1, 8, UnalignedIntegerPacker(0, 262143))); } } @@ -56223,19 +55453,15 @@ void sl_v2x_cfg_ded_r14_s::to_json(json_writer& j) const cbr_ded_tx_cfg_list_r14.to_json(j); } if (ext) { - rrc_asn1_warn_assert(comm_tx_res_v1530_present != (comm_tx_res_v1530.get() != NULL), __FILE__, __LINE__); - if (comm_tx_res_v1530_present) { + if (comm_tx_res_v1530.is_present()) { j.write_fieldname("commTxResources-v1530"); comm_tx_res_v1530->to_json(j); } - rrc_asn1_warn_assert( - v2x_packet_dupl_cfg_r15_present != (v2x_packet_dupl_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (v2x_packet_dupl_cfg_r15_present) { + if (v2x_packet_dupl_cfg_r15.is_present()) { j.write_fieldname("v2x-PacketDuplicationConfig-r15"); v2x_packet_dupl_cfg_r15->to_json(j); } - rrc_asn1_warn_assert(sync_freq_list_r15_present != (sync_freq_list_r15.get() != NULL), __FILE__, __LINE__); - if (sync_freq_list_r15_present) { + if (sync_freq_list_r15.is_present()) { j.start_array("syncFreqList-r15"); for (uint32_t i1 = 0; i1 < sync_freq_list_r15->size(); ++i1) { j.write_int(((*sync_freq_list_r15)[i1])); @@ -57321,76 +56547,54 @@ SRSASN_CODE scg_cfg_part_scg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); - rrc_asn1_warn_assert(s_cell_to_release_list_scg_ext_r13_present != - (s_cell_to_release_list_scg_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= s_cell_to_release_list_scg_ext_r13_present; - rrc_asn1_warn_assert(s_cell_to_add_mod_list_scg_ext_r13_present != - (s_cell_to_add_mod_list_scg_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= s_cell_to_add_mod_list_scg_ext_r13_present; - rrc_asn1_warn_assert(s_cell_to_add_mod_list_scg_ext_v1370_present != - (s_cell_to_add_mod_list_scg_ext_v1370.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= s_cell_to_add_mod_list_scg_ext_v1370_present; - rrc_asn1_warn_assert( - p_scell_to_add_mod_v1440_present != (p_scell_to_add_mod_v1440.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= p_scell_to_add_mod_v1440_present; - rrc_asn1_warn_assert(s_cell_group_to_release_list_scg_r15_present != - (s_cell_group_to_release_list_scg_r15.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= s_cell_group_to_release_list_scg_r15_present; - rrc_asn1_warn_assert(s_cell_group_to_add_mod_list_scg_r15_present != - (s_cell_group_to_add_mod_list_scg_r15.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= s_cell_group_to_add_mod_list_scg_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= s_cell_to_release_list_scg_ext_r13.is_present(); + group_flags[0] |= s_cell_to_add_mod_list_scg_ext_r13.is_present(); + group_flags[1] |= s_cell_to_add_mod_list_scg_ext_v1370.is_present(); + group_flags[2] |= p_scell_to_add_mod_v1440.is_present(); + group_flags[3] |= s_cell_group_to_release_list_scg_r15.is_present(); + group_flags[3] |= s_cell_group_to_add_mod_list_scg_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(s_cell_to_release_list_scg_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(s_cell_to_add_mod_list_scg_ext_r13_present, 1)); - if (s_cell_to_release_list_scg_ext_r13_present) { + HANDLE_CODE(bref.pack(s_cell_to_release_list_scg_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(s_cell_to_add_mod_list_scg_ext_r13.is_present(), 1)); + if (s_cell_to_release_list_scg_ext_r13.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *s_cell_to_release_list_scg_ext_r13, 1, 31, UnalignedIntegerPacker(1, 31))); } - if (s_cell_to_add_mod_list_scg_ext_r13_present) { + if (s_cell_to_add_mod_list_scg_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *s_cell_to_add_mod_list_scg_ext_r13, 1, 31)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(s_cell_to_add_mod_list_scg_ext_v1370_present, 1)); - if (s_cell_to_add_mod_list_scg_ext_v1370_present) { + HANDLE_CODE(bref.pack(s_cell_to_add_mod_list_scg_ext_v1370.is_present(), 1)); + if (s_cell_to_add_mod_list_scg_ext_v1370.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *s_cell_to_add_mod_list_scg_ext_v1370, 1, 31)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(p_scell_to_add_mod_v1440_present, 1)); - if (p_scell_to_add_mod_v1440_present) { + HANDLE_CODE(bref.pack(p_scell_to_add_mod_v1440.is_present(), 1)); + if (p_scell_to_add_mod_v1440.is_present()) { HANDLE_CODE(p_scell_to_add_mod_v1440->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(s_cell_group_to_release_list_scg_r15_present, 1)); - HANDLE_CODE(bref.pack(s_cell_group_to_add_mod_list_scg_r15_present, 1)); - if (s_cell_group_to_release_list_scg_r15_present) { + HANDLE_CODE(bref.pack(s_cell_group_to_release_list_scg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(s_cell_group_to_add_mod_list_scg_r15.is_present(), 1)); + if (s_cell_group_to_release_list_scg_r15.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *s_cell_group_to_release_list_scg_r15, 1, 4, UnalignedIntegerPacker(1, 4))); } - if (s_cell_group_to_add_mod_list_scg_r15_present) { + if (s_cell_group_to_add_mod_list_scg_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *s_cell_group_to_add_mod_list_scg_r15, 1, 4)); } } @@ -57423,54 +56627,60 @@ SRSASN_CODE scg_cfg_part_scg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool s_cell_to_release_list_scg_ext_r13_present; HANDLE_CODE(bref.unpack(s_cell_to_release_list_scg_ext_r13_present, 1)); + s_cell_to_release_list_scg_ext_r13.set_present(s_cell_to_release_list_scg_ext_r13_present); + bool s_cell_to_add_mod_list_scg_ext_r13_present; HANDLE_CODE(bref.unpack(s_cell_to_add_mod_list_scg_ext_r13_present, 1)); - if (s_cell_to_release_list_scg_ext_r13_present) { - s_cell_to_release_list_scg_ext_r13 = make_copy_ptr(scell_to_release_list_ext_r13_l()); + s_cell_to_add_mod_list_scg_ext_r13.set_present(s_cell_to_add_mod_list_scg_ext_r13_present); + if (s_cell_to_release_list_scg_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of( *s_cell_to_release_list_scg_ext_r13, bref, 1, 31, UnalignedIntegerPacker(1, 31))); } - if (s_cell_to_add_mod_list_scg_ext_r13_present) { - s_cell_to_add_mod_list_scg_ext_r13 = make_copy_ptr(scell_to_add_mod_list_ext_r13_l()); + if (s_cell_to_add_mod_list_scg_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*s_cell_to_add_mod_list_scg_ext_r13, bref, 1, 31)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool s_cell_to_add_mod_list_scg_ext_v1370_present; HANDLE_CODE(bref.unpack(s_cell_to_add_mod_list_scg_ext_v1370_present, 1)); - if (s_cell_to_add_mod_list_scg_ext_v1370_present) { - s_cell_to_add_mod_list_scg_ext_v1370 = make_copy_ptr(scell_to_add_mod_list_ext_v1370_l()); + s_cell_to_add_mod_list_scg_ext_v1370.set_present(s_cell_to_add_mod_list_scg_ext_v1370_present); + if (s_cell_to_add_mod_list_scg_ext_v1370.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*s_cell_to_add_mod_list_scg_ext_v1370, bref, 1, 31)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool p_scell_to_add_mod_v1440_present; HANDLE_CODE(bref.unpack(p_scell_to_add_mod_v1440_present, 1)); - if (p_scell_to_add_mod_v1440_present) { - p_scell_to_add_mod_v1440 = make_copy_ptr(ps_cell_to_add_mod_v1440_s()); + p_scell_to_add_mod_v1440.set_present(p_scell_to_add_mod_v1440_present); + if (p_scell_to_add_mod_v1440.is_present()) { HANDLE_CODE(p_scell_to_add_mod_v1440->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool s_cell_group_to_release_list_scg_r15_present; HANDLE_CODE(bref.unpack(s_cell_group_to_release_list_scg_r15_present, 1)); + s_cell_group_to_release_list_scg_r15.set_present(s_cell_group_to_release_list_scg_r15_present); + bool s_cell_group_to_add_mod_list_scg_r15_present; HANDLE_CODE(bref.unpack(s_cell_group_to_add_mod_list_scg_r15_present, 1)); - if (s_cell_group_to_release_list_scg_r15_present) { - s_cell_group_to_release_list_scg_r15 = make_copy_ptr(scell_group_to_release_list_r15_l()); + s_cell_group_to_add_mod_list_scg_r15.set_present(s_cell_group_to_add_mod_list_scg_r15_present); + if (s_cell_group_to_release_list_scg_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of( *s_cell_group_to_release_list_scg_r15, bref, 1, 4, UnalignedIntegerPacker(1, 4))); } - if (s_cell_group_to_add_mod_list_scg_r15_present) { - s_cell_group_to_add_mod_list_scg_r15 = make_copy_ptr(scell_group_to_add_mod_list_r15_l()); + if (s_cell_group_to_add_mod_list_scg_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*s_cell_group_to_add_mod_list_scg_r15, bref, 1, 4)); } } @@ -57507,61 +56717,39 @@ void scg_cfg_part_scg_r12_s::to_json(json_writer& j) const mob_ctrl_info_scg_r12.to_json(j); } if (ext) { - rrc_asn1_warn_assert(s_cell_to_release_list_scg_ext_r13_present != - (s_cell_to_release_list_scg_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (s_cell_to_release_list_scg_ext_r13_present) { + if (s_cell_to_release_list_scg_ext_r13.is_present()) { j.start_array("sCellToReleaseListSCG-Ext-r13"); for (uint32_t i1 = 0; i1 < s_cell_to_release_list_scg_ext_r13->size(); ++i1) { j.write_int(((*s_cell_to_release_list_scg_ext_r13)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(s_cell_to_add_mod_list_scg_ext_r13_present != - (s_cell_to_add_mod_list_scg_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (s_cell_to_add_mod_list_scg_ext_r13_present) { + if (s_cell_to_add_mod_list_scg_ext_r13.is_present()) { j.start_array("sCellToAddModListSCG-Ext-r13"); for (uint32_t i1 = 0; i1 < s_cell_to_add_mod_list_scg_ext_r13->size(); ++i1) { ((*s_cell_to_add_mod_list_scg_ext_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(s_cell_to_add_mod_list_scg_ext_v1370_present != - (s_cell_to_add_mod_list_scg_ext_v1370.get() != NULL), - __FILE__, - __LINE__); - if (s_cell_to_add_mod_list_scg_ext_v1370_present) { + if (s_cell_to_add_mod_list_scg_ext_v1370.is_present()) { j.start_array("sCellToAddModListSCG-Ext-v1370"); for (uint32_t i1 = 0; i1 < s_cell_to_add_mod_list_scg_ext_v1370->size(); ++i1) { ((*s_cell_to_add_mod_list_scg_ext_v1370)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - p_scell_to_add_mod_v1440_present != (p_scell_to_add_mod_v1440.get() != NULL), __FILE__, __LINE__); - if (p_scell_to_add_mod_v1440_present) { + if (p_scell_to_add_mod_v1440.is_present()) { j.write_fieldname("pSCellToAddMod-v1440"); p_scell_to_add_mod_v1440->to_json(j); } - rrc_asn1_warn_assert(s_cell_group_to_release_list_scg_r15_present != - (s_cell_group_to_release_list_scg_r15.get() != NULL), - __FILE__, - __LINE__); - if (s_cell_group_to_release_list_scg_r15_present) { + if (s_cell_group_to_release_list_scg_r15.is_present()) { j.start_array("sCellGroupToReleaseListSCG-r15"); for (uint32_t i1 = 0; i1 < s_cell_group_to_release_list_scg_r15->size(); ++i1) { j.write_int(((*s_cell_group_to_release_list_scg_r15)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(s_cell_group_to_add_mod_list_scg_r15_present != - (s_cell_group_to_add_mod_list_scg_r15.get() != NULL), - __FILE__, - __LINE__); - if (s_cell_group_to_add_mod_list_scg_r15_present) { + if (s_cell_group_to_add_mod_list_scg_r15.is_present()) { j.start_array("sCellGroupToAddModListSCG-r15"); for (uint32_t i1 = 0; i1 < s_cell_group_to_add_mod_list_scg_r15->size(); ++i1) { ((*s_cell_group_to_add_mod_list_scg_r15)[i1]).to_json(j); @@ -58330,18 +57518,17 @@ SRSASN_CODE sl_comm_cfg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(comm_tx_res_v1310_present != (comm_tx_res_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= comm_tx_res_v1310_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= comm_tx_res_v1310.is_present(); group_flags[0] |= comm_tx_allow_relay_ded_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(comm_tx_res_v1310_present, 1)); + HANDLE_CODE(bref.pack(comm_tx_res_v1310.is_present(), 1)); HANDLE_CODE(bref.pack(comm_tx_allow_relay_ded_r13_present, 1)); - if (comm_tx_res_v1310_present) { + if (comm_tx_res_v1310.is_present()) { HANDLE_CODE(comm_tx_res_v1310->pack(bref)); } if (comm_tx_allow_relay_ded_r13_present) { @@ -58361,16 +57548,17 @@ SRSASN_CODE sl_comm_cfg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool comm_tx_res_v1310_present; HANDLE_CODE(bref.unpack(comm_tx_res_v1310_present, 1)); + comm_tx_res_v1310.set_present(comm_tx_res_v1310_present); HANDLE_CODE(bref.unpack(comm_tx_allow_relay_ded_r13_present, 1)); - if (comm_tx_res_v1310_present) { - comm_tx_res_v1310 = make_copy_ptr(comm_tx_res_v1310_c_()); + if (comm_tx_res_v1310.is_present()) { HANDLE_CODE(comm_tx_res_v1310->unpack(bref)); } if (comm_tx_allow_relay_ded_r13_present) { @@ -58388,8 +57576,7 @@ void sl_comm_cfg_r12_s::to_json(json_writer& j) const comm_tx_res_r12.to_json(j); } if (ext) { - rrc_asn1_warn_assert(comm_tx_res_v1310_present != (comm_tx_res_v1310.get() != NULL), __FILE__, __LINE__); - if (comm_tx_res_v1310_present) { + if (comm_tx_res_v1310.is_present()) { j.write_fieldname("commTxResources-v1310"); comm_tx_res_v1310->to_json(j); } @@ -58896,57 +58083,49 @@ SRSASN_CODE sl_disc_cfg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(disc_tf_idx_list_v1260_present != (disc_tf_idx_list_v1260.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= disc_tf_idx_list_v1260_present; - rrc_asn1_warn_assert(disc_tx_res_ps_r13_present != (disc_tx_res_ps_r13.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= disc_tx_res_ps_r13_present; - rrc_asn1_warn_assert( - disc_tx_inter_freq_info_r13_present != (disc_tx_inter_freq_info_r13.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= disc_tx_inter_freq_info_r13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= disc_tf_idx_list_v1260.is_present(); + group_flags[1] |= disc_tx_res_ps_r13.is_present(); + group_flags[1] |= disc_tx_inter_freq_info_r13.is_present(); group_flags[1] |= gap_requests_allowed_ded_r13_present; - rrc_asn1_warn_assert(disc_rx_gap_cfg_r13_present != (disc_rx_gap_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= disc_rx_gap_cfg_r13_present; - rrc_asn1_warn_assert(disc_tx_gap_cfg_r13_present != (disc_tx_gap_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= disc_tx_gap_cfg_r13_present; - rrc_asn1_warn_assert( - disc_sys_info_to_report_cfg_r13_present != (disc_sys_info_to_report_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= disc_sys_info_to_report_cfg_r13_present; + group_flags[1] |= disc_rx_gap_cfg_r13.is_present(); + group_flags[1] |= disc_tx_gap_cfg_r13.is_present(); + group_flags[1] |= disc_sys_info_to_report_cfg_r13.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(disc_tf_idx_list_v1260_present, 1)); - if (disc_tf_idx_list_v1260_present) { + HANDLE_CODE(bref.pack(disc_tf_idx_list_v1260.is_present(), 1)); + if (disc_tf_idx_list_v1260.is_present()) { HANDLE_CODE(disc_tf_idx_list_v1260->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(disc_tx_res_ps_r13_present, 1)); - HANDLE_CODE(bref.pack(disc_tx_inter_freq_info_r13_present, 1)); + HANDLE_CODE(bref.pack(disc_tx_res_ps_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(disc_tx_inter_freq_info_r13.is_present(), 1)); HANDLE_CODE(bref.pack(gap_requests_allowed_ded_r13_present, 1)); - HANDLE_CODE(bref.pack(disc_rx_gap_cfg_r13_present, 1)); - HANDLE_CODE(bref.pack(disc_tx_gap_cfg_r13_present, 1)); - HANDLE_CODE(bref.pack(disc_sys_info_to_report_cfg_r13_present, 1)); - if (disc_tx_res_ps_r13_present) { + HANDLE_CODE(bref.pack(disc_rx_gap_cfg_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(disc_tx_gap_cfg_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(disc_sys_info_to_report_cfg_r13.is_present(), 1)); + if (disc_tx_res_ps_r13.is_present()) { HANDLE_CODE(disc_tx_res_ps_r13->pack(bref)); } - if (disc_tx_inter_freq_info_r13_present) { + if (disc_tx_inter_freq_info_r13.is_present()) { HANDLE_CODE(disc_tx_inter_freq_info_r13->pack(bref)); } if (gap_requests_allowed_ded_r13_present) { HANDLE_CODE(bref.pack(gap_requests_allowed_ded_r13, 1)); } - if (disc_rx_gap_cfg_r13_present) { + if (disc_rx_gap_cfg_r13.is_present()) { HANDLE_CODE(disc_rx_gap_cfg_r13->pack(bref)); } - if (disc_tx_gap_cfg_r13_present) { + if (disc_tx_gap_cfg_r13.is_present()) { HANDLE_CODE(disc_tx_gap_cfg_r13->pack(bref)); } - if (disc_sys_info_to_report_cfg_r13_present) { + if (disc_sys_info_to_report_cfg_r13.is_present()) { HANDLE_CODE(disc_sys_info_to_report_cfg_r13->pack(bref)); } } @@ -58963,48 +58142,54 @@ SRSASN_CODE sl_disc_cfg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool disc_tf_idx_list_v1260_present; HANDLE_CODE(bref.unpack(disc_tf_idx_list_v1260_present, 1)); - if (disc_tf_idx_list_v1260_present) { - disc_tf_idx_list_v1260 = make_copy_ptr(disc_tf_idx_list_v1260_c_()); + disc_tf_idx_list_v1260.set_present(disc_tf_idx_list_v1260_present); + if (disc_tf_idx_list_v1260.is_present()) { HANDLE_CODE(disc_tf_idx_list_v1260->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool disc_tx_res_ps_r13_present; HANDLE_CODE(bref.unpack(disc_tx_res_ps_r13_present, 1)); + disc_tx_res_ps_r13.set_present(disc_tx_res_ps_r13_present); + bool disc_tx_inter_freq_info_r13_present; HANDLE_CODE(bref.unpack(disc_tx_inter_freq_info_r13_present, 1)); + disc_tx_inter_freq_info_r13.set_present(disc_tx_inter_freq_info_r13_present); HANDLE_CODE(bref.unpack(gap_requests_allowed_ded_r13_present, 1)); + bool disc_rx_gap_cfg_r13_present; HANDLE_CODE(bref.unpack(disc_rx_gap_cfg_r13_present, 1)); + disc_rx_gap_cfg_r13.set_present(disc_rx_gap_cfg_r13_present); + bool disc_tx_gap_cfg_r13_present; HANDLE_CODE(bref.unpack(disc_tx_gap_cfg_r13_present, 1)); + disc_tx_gap_cfg_r13.set_present(disc_tx_gap_cfg_r13_present); + bool disc_sys_info_to_report_cfg_r13_present; HANDLE_CODE(bref.unpack(disc_sys_info_to_report_cfg_r13_present, 1)); - if (disc_tx_res_ps_r13_present) { - disc_tx_res_ps_r13 = make_copy_ptr(disc_tx_res_ps_r13_c_()); + disc_sys_info_to_report_cfg_r13.set_present(disc_sys_info_to_report_cfg_r13_present); + if (disc_tx_res_ps_r13.is_present()) { HANDLE_CODE(disc_tx_res_ps_r13->unpack(bref)); } - if (disc_tx_inter_freq_info_r13_present) { - disc_tx_inter_freq_info_r13 = make_copy_ptr(disc_tx_inter_freq_info_r13_c_()); + if (disc_tx_inter_freq_info_r13.is_present()) { HANDLE_CODE(disc_tx_inter_freq_info_r13->unpack(bref)); } if (gap_requests_allowed_ded_r13_present) { HANDLE_CODE(bref.unpack(gap_requests_allowed_ded_r13, 1)); } - if (disc_rx_gap_cfg_r13_present) { - disc_rx_gap_cfg_r13 = make_copy_ptr(disc_rx_gap_cfg_r13_c_()); + if (disc_rx_gap_cfg_r13.is_present()) { HANDLE_CODE(disc_rx_gap_cfg_r13->unpack(bref)); } - if (disc_tx_gap_cfg_r13_present) { - disc_tx_gap_cfg_r13 = make_copy_ptr(disc_tx_gap_cfg_r13_c_()); + if (disc_tx_gap_cfg_r13.is_present()) { HANDLE_CODE(disc_tx_gap_cfg_r13->unpack(bref)); } - if (disc_sys_info_to_report_cfg_r13_present) { - disc_sys_info_to_report_cfg_r13 = make_copy_ptr(disc_sys_info_to_report_cfg_r13_c_()); + if (disc_sys_info_to_report_cfg_r13.is_present()) { HANDLE_CODE(disc_sys_info_to_report_cfg_r13->unpack(bref)); } } @@ -59019,38 +58204,30 @@ void sl_disc_cfg_r12_s::to_json(json_writer& j) const disc_tx_res_r12.to_json(j); } if (ext) { - rrc_asn1_warn_assert(disc_tf_idx_list_v1260_present != (disc_tf_idx_list_v1260.get() != NULL), __FILE__, __LINE__); - if (disc_tf_idx_list_v1260_present) { + if (disc_tf_idx_list_v1260.is_present()) { j.write_fieldname("discTF-IndexList-v1260"); disc_tf_idx_list_v1260->to_json(j); } - rrc_asn1_warn_assert(disc_tx_res_ps_r13_present != (disc_tx_res_ps_r13.get() != NULL), __FILE__, __LINE__); - if (disc_tx_res_ps_r13_present) { + if (disc_tx_res_ps_r13.is_present()) { j.write_fieldname("discTxResourcesPS-r13"); disc_tx_res_ps_r13->to_json(j); } - rrc_asn1_warn_assert( - disc_tx_inter_freq_info_r13_present != (disc_tx_inter_freq_info_r13.get() != NULL), __FILE__, __LINE__); - if (disc_tx_inter_freq_info_r13_present) { + if (disc_tx_inter_freq_info_r13.is_present()) { j.write_fieldname("discTxInterFreqInfo-r13"); disc_tx_inter_freq_info_r13->to_json(j); } if (gap_requests_allowed_ded_r13_present) { j.write_bool("gapRequestsAllowedDedicated-r13", gap_requests_allowed_ded_r13); } - rrc_asn1_warn_assert(disc_rx_gap_cfg_r13_present != (disc_rx_gap_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (disc_rx_gap_cfg_r13_present) { + if (disc_rx_gap_cfg_r13.is_present()) { j.write_fieldname("discRxGapConfig-r13"); disc_rx_gap_cfg_r13->to_json(j); } - rrc_asn1_warn_assert(disc_tx_gap_cfg_r13_present != (disc_tx_gap_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (disc_tx_gap_cfg_r13_present) { + if (disc_tx_gap_cfg_r13.is_present()) { j.write_fieldname("discTxGapConfig-r13"); disc_tx_gap_cfg_r13->to_json(j); } - rrc_asn1_warn_assert( - disc_sys_info_to_report_cfg_r13_present != (disc_sys_info_to_report_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (disc_sys_info_to_report_cfg_r13_present) { + if (disc_sys_info_to_report_cfg_r13.is_present()) { j.write_fieldname("discSysInfoToReportConfig-r13"); disc_sys_info_to_report_cfg_r13->to_json(j); } @@ -62236,28 +61413,27 @@ SRSASN_CODE idc_cfg_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); + ext_groups_packer_guard group_flags; group_flags[0] |= idc_ind_ul_ca_r11_present; group_flags[1] |= idc_hardware_sharing_ind_r13_present; - rrc_asn1_warn_assert(idc_ind_mrdc_r15_present != (idc_ind_mrdc_r15.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= idc_ind_mrdc_r15_present; + group_flags[2] |= idc_ind_mrdc_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(idc_ind_ul_ca_r11_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(idc_hardware_sharing_ind_r13_present, 1)); } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(idc_ind_mrdc_r15_present, 1)); - if (idc_ind_mrdc_r15_present) { + HANDLE_CODE(bref.pack(idc_ind_mrdc_r15.is_present(), 1)); + if (idc_ind_mrdc_r15.is_present()) { HANDLE_CODE(idc_ind_mrdc_r15->pack(bref)); } } @@ -62276,25 +61452,26 @@ SRSASN_CODE idc_cfg_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(idc_ind_ul_ca_r11_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(idc_hardware_sharing_ind_r13_present, 1)); } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool idc_ind_mrdc_r15_present; HANDLE_CODE(bref.unpack(idc_ind_mrdc_r15_present, 1)); - if (idc_ind_mrdc_r15_present) { - idc_ind_mrdc_r15 = make_copy_ptr(idc_ind_mrdc_r15_c_()); + idc_ind_mrdc_r15.set_present(idc_ind_mrdc_r15_present); + if (idc_ind_mrdc_r15.is_present()) { HANDLE_CODE(idc_ind_mrdc_r15->unpack(bref)); } } @@ -62322,8 +61499,7 @@ void idc_cfg_r11_s::to_json(json_writer& j) const if (idc_hardware_sharing_ind_r13_present) { j.write_str("idc-HardwareSharingIndication-r13", "setup"); } - rrc_asn1_warn_assert(idc_ind_mrdc_r15_present != (idc_ind_mrdc_r15.get() != NULL), __FILE__, __LINE__); - if (idc_ind_mrdc_r15_present) { + if (idc_ind_mrdc_r15.is_present()) { j.write_fieldname("idc-Indication-MRDC-r15"); idc_ind_mrdc_r15->to_json(j); } @@ -62592,58 +61768,39 @@ SRSASN_CODE meas_obj_eutra_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(6); + ext_groups_packer_guard group_flags; group_flags[0] |= meas_cycle_scell_r10_present; - rrc_asn1_warn_assert( - meas_sf_pattern_cfg_neigh_r10_present != (meas_sf_pattern_cfg_neigh_r10.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= meas_sf_pattern_cfg_neigh_r10_present; + group_flags[0] |= meas_sf_pattern_cfg_neigh_r10.is_present(); group_flags[1] |= wideband_rsrq_meas_r11_present; - rrc_asn1_warn_assert( - alt_ttt_cells_to_rem_list_r12_present != (alt_ttt_cells_to_rem_list_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= alt_ttt_cells_to_rem_list_r12_present; - rrc_asn1_warn_assert(alt_ttt_cells_to_add_mod_list_r12_present != (alt_ttt_cells_to_add_mod_list_r12.get() != NULL), - __FILE__, - __LINE__); - group_flags[2] |= alt_ttt_cells_to_add_mod_list_r12_present; - rrc_asn1_warn_assert(t312_r12_present != (t312_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= t312_r12_present; + group_flags[2] |= alt_ttt_cells_to_rem_list_r12.is_present(); + group_flags[2] |= alt_ttt_cells_to_add_mod_list_r12.is_present(); + group_flags[2] |= t312_r12.is_present(); group_flags[2] |= reduced_meas_performance_r12_present; - rrc_asn1_warn_assert(meas_ds_cfg_r12_present != (meas_ds_cfg_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= meas_ds_cfg_r12_present; - rrc_asn1_warn_assert( - white_cells_to_rem_list_r13_present != (white_cells_to_rem_list_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= white_cells_to_rem_list_r13_present; - rrc_asn1_warn_assert( - white_cells_to_add_mod_list_r13_present != (white_cells_to_add_mod_list_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= white_cells_to_add_mod_list_r13_present; - rrc_asn1_warn_assert(rmtc_cfg_r13_present != (rmtc_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= rmtc_cfg_r13_present; + group_flags[2] |= meas_ds_cfg_r12.is_present(); + group_flags[3] |= white_cells_to_rem_list_r13.is_present(); + group_flags[3] |= white_cells_to_add_mod_list_r13.is_present(); + group_flags[3] |= rmtc_cfg_r13.is_present(); group_flags[3] |= carrier_freq_r13_present; - rrc_asn1_warn_assert( - tx_res_pool_to_rem_list_r14_present != (tx_res_pool_to_rem_list_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= tx_res_pool_to_rem_list_r14_present; - rrc_asn1_warn_assert( - tx_res_pool_to_add_list_r14_present != (tx_res_pool_to_add_list_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= tx_res_pool_to_add_list_r14_present; + group_flags[4] |= tx_res_pool_to_rem_list_r14.is_present(); + group_flags[4] |= tx_res_pool_to_add_list_r14.is_present(); group_flags[4] |= fembms_mixed_carrier_r14_present; - rrc_asn1_warn_assert(meas_sensing_cfg_r15_present != (meas_sensing_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= meas_sensing_cfg_r15_present; + group_flags[5] |= meas_sensing_cfg_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_cycle_scell_r10_present, 1)); - HANDLE_CODE(bref.pack(meas_sf_pattern_cfg_neigh_r10_present, 1)); + HANDLE_CODE(bref.pack(meas_sf_pattern_cfg_neigh_r10.is_present(), 1)); if (meas_cycle_scell_r10_present) { HANDLE_CODE(pack_enum(bref, meas_cycle_scell_r10)); } - if (meas_sf_pattern_cfg_neigh_r10_present) { + if (meas_sf_pattern_cfg_neigh_r10.is_present()) { HANDLE_CODE(meas_sf_pattern_cfg_neigh_r10->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(wideband_rsrq_meas_r11_present, 1)); if (wideband_rsrq_meas_r11_present) { @@ -62651,44 +61808,44 @@ SRSASN_CODE meas_obj_eutra_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(alt_ttt_cells_to_rem_list_r12_present, 1)); - HANDLE_CODE(bref.pack(alt_ttt_cells_to_add_mod_list_r12_present, 1)); - HANDLE_CODE(bref.pack(t312_r12_present, 1)); + HANDLE_CODE(bref.pack(alt_ttt_cells_to_rem_list_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(alt_ttt_cells_to_add_mod_list_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(t312_r12.is_present(), 1)); HANDLE_CODE(bref.pack(reduced_meas_performance_r12_present, 1)); - HANDLE_CODE(bref.pack(meas_ds_cfg_r12_present, 1)); - if (alt_ttt_cells_to_rem_list_r12_present) { + HANDLE_CODE(bref.pack(meas_ds_cfg_r12.is_present(), 1)); + if (alt_ttt_cells_to_rem_list_r12.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *alt_ttt_cells_to_rem_list_r12, 1, 32, UnalignedIntegerPacker(1, 32))); } - if (alt_ttt_cells_to_add_mod_list_r12_present) { + if (alt_ttt_cells_to_add_mod_list_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *alt_ttt_cells_to_add_mod_list_r12, 1, 32)); } - if (t312_r12_present) { + if (t312_r12.is_present()) { HANDLE_CODE(t312_r12->pack(bref)); } if (reduced_meas_performance_r12_present) { HANDLE_CODE(bref.pack(reduced_meas_performance_r12, 1)); } - if (meas_ds_cfg_r12_present) { + if (meas_ds_cfg_r12.is_present()) { HANDLE_CODE(meas_ds_cfg_r12->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(white_cells_to_rem_list_r13_present, 1)); - HANDLE_CODE(bref.pack(white_cells_to_add_mod_list_r13_present, 1)); - HANDLE_CODE(bref.pack(rmtc_cfg_r13_present, 1)); + HANDLE_CODE(bref.pack(white_cells_to_rem_list_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(white_cells_to_add_mod_list_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(rmtc_cfg_r13.is_present(), 1)); HANDLE_CODE(bref.pack(carrier_freq_r13_present, 1)); - if (white_cells_to_rem_list_r13_present) { + if (white_cells_to_rem_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *white_cells_to_rem_list_r13, 1, 32, UnalignedIntegerPacker(1, 32))); } - if (white_cells_to_add_mod_list_r13_present) { + if (white_cells_to_add_mod_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *white_cells_to_add_mod_list_r13, 1, 32)); } - if (rmtc_cfg_r13_present) { + if (rmtc_cfg_r13.is_present()) { HANDLE_CODE(rmtc_cfg_r13->pack(bref)); } if (carrier_freq_r13_present) { @@ -62696,15 +61853,15 @@ SRSASN_CODE meas_obj_eutra_s::pack(bit_ref& bref) const } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(tx_res_pool_to_rem_list_r14_present, 1)); - HANDLE_CODE(bref.pack(tx_res_pool_to_add_list_r14_present, 1)); + HANDLE_CODE(bref.pack(tx_res_pool_to_rem_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(tx_res_pool_to_add_list_r14.is_present(), 1)); HANDLE_CODE(bref.pack(fembms_mixed_carrier_r14_present, 1)); - if (tx_res_pool_to_rem_list_r14_present) { + if (tx_res_pool_to_rem_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *tx_res_pool_to_rem_list_r14, 1, 72, UnalignedIntegerPacker(1, 72))); } - if (tx_res_pool_to_add_list_r14_present) { + if (tx_res_pool_to_add_list_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *tx_res_pool_to_add_list_r14, 1, 72, UnalignedIntegerPacker(1, 72))); } if (fembms_mixed_carrier_r14_present) { @@ -62712,10 +61869,10 @@ SRSASN_CODE meas_obj_eutra_s::pack(bit_ref& bref) const } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_sensing_cfg_r15_present, 1)); - if (meas_sensing_cfg_r15_present) { + HANDLE_CODE(bref.pack(meas_sensing_cfg_r15.is_present(), 1)); + if (meas_sensing_cfg_r15.is_present()) { HANDLE_CODE(meas_sensing_cfg_r15->pack(bref)); } } @@ -62756,24 +61913,25 @@ SRSASN_CODE meas_obj_eutra_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(6); + ext_groups_unpacker_guard group_flags(6); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_cycle_scell_r10_present, 1)); + bool meas_sf_pattern_cfg_neigh_r10_present; HANDLE_CODE(bref.unpack(meas_sf_pattern_cfg_neigh_r10_present, 1)); + meas_sf_pattern_cfg_neigh_r10.set_present(meas_sf_pattern_cfg_neigh_r10_present); if (meas_cycle_scell_r10_present) { HANDLE_CODE(unpack_enum(meas_cycle_scell_r10, bref)); } - if (meas_sf_pattern_cfg_neigh_r10_present) { - meas_sf_pattern_cfg_neigh_r10 = make_copy_ptr(meas_sf_pattern_cfg_neigh_r10_c()); + if (meas_sf_pattern_cfg_neigh_r10.is_present()) { HANDLE_CODE(meas_sf_pattern_cfg_neigh_r10->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(wideband_rsrq_meas_r11_present, 1)); if (wideband_rsrq_meas_r11_present) { @@ -62781,52 +61939,59 @@ SRSASN_CODE meas_obj_eutra_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool alt_ttt_cells_to_rem_list_r12_present; HANDLE_CODE(bref.unpack(alt_ttt_cells_to_rem_list_r12_present, 1)); + alt_ttt_cells_to_rem_list_r12.set_present(alt_ttt_cells_to_rem_list_r12_present); + bool alt_ttt_cells_to_add_mod_list_r12_present; HANDLE_CODE(bref.unpack(alt_ttt_cells_to_add_mod_list_r12_present, 1)); + alt_ttt_cells_to_add_mod_list_r12.set_present(alt_ttt_cells_to_add_mod_list_r12_present); + bool t312_r12_present; HANDLE_CODE(bref.unpack(t312_r12_present, 1)); + t312_r12.set_present(t312_r12_present); HANDLE_CODE(bref.unpack(reduced_meas_performance_r12_present, 1)); + bool meas_ds_cfg_r12_present; HANDLE_CODE(bref.unpack(meas_ds_cfg_r12_present, 1)); - if (alt_ttt_cells_to_rem_list_r12_present) { - alt_ttt_cells_to_rem_list_r12 = make_copy_ptr(cell_idx_list_l()); + meas_ds_cfg_r12.set_present(meas_ds_cfg_r12_present); + if (alt_ttt_cells_to_rem_list_r12.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*alt_ttt_cells_to_rem_list_r12, bref, 1, 32, UnalignedIntegerPacker(1, 32))); } - if (alt_ttt_cells_to_add_mod_list_r12_present) { - alt_ttt_cells_to_add_mod_list_r12 = make_copy_ptr(alt_ttt_cells_to_add_mod_list_r12_l()); + if (alt_ttt_cells_to_add_mod_list_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*alt_ttt_cells_to_add_mod_list_r12, bref, 1, 32)); } - if (t312_r12_present) { - t312_r12 = make_copy_ptr(t312_r12_c_()); + if (t312_r12.is_present()) { HANDLE_CODE(t312_r12->unpack(bref)); } if (reduced_meas_performance_r12_present) { HANDLE_CODE(bref.unpack(reduced_meas_performance_r12, 1)); } - if (meas_ds_cfg_r12_present) { - meas_ds_cfg_r12 = make_copy_ptr(meas_ds_cfg_r12_c()); + if (meas_ds_cfg_r12.is_present()) { HANDLE_CODE(meas_ds_cfg_r12->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool white_cells_to_rem_list_r13_present; HANDLE_CODE(bref.unpack(white_cells_to_rem_list_r13_present, 1)); + white_cells_to_rem_list_r13.set_present(white_cells_to_rem_list_r13_present); + bool white_cells_to_add_mod_list_r13_present; HANDLE_CODE(bref.unpack(white_cells_to_add_mod_list_r13_present, 1)); + white_cells_to_add_mod_list_r13.set_present(white_cells_to_add_mod_list_r13_present); + bool rmtc_cfg_r13_present; HANDLE_CODE(bref.unpack(rmtc_cfg_r13_present, 1)); + rmtc_cfg_r13.set_present(rmtc_cfg_r13_present); HANDLE_CODE(bref.unpack(carrier_freq_r13_present, 1)); - if (white_cells_to_rem_list_r13_present) { - white_cells_to_rem_list_r13 = make_copy_ptr(cell_idx_list_l()); + if (white_cells_to_rem_list_r13.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*white_cells_to_rem_list_r13, bref, 1, 32, UnalignedIntegerPacker(1, 32))); } - if (white_cells_to_add_mod_list_r13_present) { - white_cells_to_add_mod_list_r13 = make_copy_ptr(white_cells_to_add_mod_list_r13_l()); + if (white_cells_to_add_mod_list_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*white_cells_to_add_mod_list_r13, bref, 1, 32)); } - if (rmtc_cfg_r13_present) { - rmtc_cfg_r13 = make_copy_ptr(rmtc_cfg_r13_c()); + if (rmtc_cfg_r13.is_present()) { HANDLE_CODE(rmtc_cfg_r13->unpack(bref)); } if (carrier_freq_r13_present) { @@ -62834,18 +61999,20 @@ SRSASN_CODE meas_obj_eutra_s::unpack(bit_ref& bref) } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool tx_res_pool_to_rem_list_r14_present; HANDLE_CODE(bref.unpack(tx_res_pool_to_rem_list_r14_present, 1)); + tx_res_pool_to_rem_list_r14.set_present(tx_res_pool_to_rem_list_r14_present); + bool tx_res_pool_to_add_list_r14_present; HANDLE_CODE(bref.unpack(tx_res_pool_to_add_list_r14_present, 1)); + tx_res_pool_to_add_list_r14.set_present(tx_res_pool_to_add_list_r14_present); HANDLE_CODE(bref.unpack(fembms_mixed_carrier_r14_present, 1)); - if (tx_res_pool_to_rem_list_r14_present) { - tx_res_pool_to_rem_list_r14 = make_copy_ptr(tx_res_pool_meas_list_r14_l()); + if (tx_res_pool_to_rem_list_r14.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*tx_res_pool_to_rem_list_r14, bref, 1, 72, UnalignedIntegerPacker(1, 72))); } - if (tx_res_pool_to_add_list_r14_present) { - tx_res_pool_to_add_list_r14 = make_copy_ptr(tx_res_pool_meas_list_r14_l()); + if (tx_res_pool_to_add_list_r14.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*tx_res_pool_to_add_list_r14, bref, 1, 72, UnalignedIntegerPacker(1, 72))); } @@ -62854,11 +62021,12 @@ SRSASN_CODE meas_obj_eutra_s::unpack(bit_ref& bref) } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_sensing_cfg_r15_present; HANDLE_CODE(bref.unpack(meas_sensing_cfg_r15_present, 1)); - if (meas_sensing_cfg_r15_present) { - meas_sensing_cfg_r15 = make_copy_ptr(meas_sensing_cfg_r15_s()); + meas_sensing_cfg_r15.set_present(meas_sensing_cfg_r15_present); + if (meas_sensing_cfg_r15.is_present()) { HANDLE_CODE(meas_sensing_cfg_r15->unpack(bref)); } } @@ -62910,85 +62078,67 @@ void meas_obj_eutra_s::to_json(json_writer& j) const if (meas_cycle_scell_r10_present) { j.write_str("measCycleSCell-r10", meas_cycle_scell_r10.to_string()); } - rrc_asn1_warn_assert( - meas_sf_pattern_cfg_neigh_r10_present != (meas_sf_pattern_cfg_neigh_r10.get() != NULL), __FILE__, __LINE__); - if (meas_sf_pattern_cfg_neigh_r10_present) { + if (meas_sf_pattern_cfg_neigh_r10.is_present()) { j.write_fieldname("measSubframePatternConfigNeigh-r10"); meas_sf_pattern_cfg_neigh_r10->to_json(j); } if (wideband_rsrq_meas_r11_present) { j.write_bool("widebandRSRQ-Meas-r11", wideband_rsrq_meas_r11); } - rrc_asn1_warn_assert( - alt_ttt_cells_to_rem_list_r12_present != (alt_ttt_cells_to_rem_list_r12.get() != NULL), __FILE__, __LINE__); - if (alt_ttt_cells_to_rem_list_r12_present) { + if (alt_ttt_cells_to_rem_list_r12.is_present()) { j.start_array("altTTT-CellsToRemoveList-r12"); for (uint32_t i1 = 0; i1 < alt_ttt_cells_to_rem_list_r12->size(); ++i1) { j.write_int(((*alt_ttt_cells_to_rem_list_r12)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(alt_ttt_cells_to_add_mod_list_r12_present != (alt_ttt_cells_to_add_mod_list_r12.get() != NULL), - __FILE__, - __LINE__); - if (alt_ttt_cells_to_add_mod_list_r12_present) { + if (alt_ttt_cells_to_add_mod_list_r12.is_present()) { j.start_array("altTTT-CellsToAddModList-r12"); for (uint32_t i1 = 0; i1 < alt_ttt_cells_to_add_mod_list_r12->size(); ++i1) { ((*alt_ttt_cells_to_add_mod_list_r12)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(t312_r12_present != (t312_r12.get() != NULL), __FILE__, __LINE__); - if (t312_r12_present) { + if (t312_r12.is_present()) { j.write_fieldname("t312-r12"); t312_r12->to_json(j); } if (reduced_meas_performance_r12_present) { j.write_bool("reducedMeasPerformance-r12", reduced_meas_performance_r12); } - rrc_asn1_warn_assert(meas_ds_cfg_r12_present != (meas_ds_cfg_r12.get() != NULL), __FILE__, __LINE__); - if (meas_ds_cfg_r12_present) { + if (meas_ds_cfg_r12.is_present()) { j.write_fieldname("measDS-Config-r12"); meas_ds_cfg_r12->to_json(j); } - rrc_asn1_warn_assert( - white_cells_to_rem_list_r13_present != (white_cells_to_rem_list_r13.get() != NULL), __FILE__, __LINE__); - if (white_cells_to_rem_list_r13_present) { + if (white_cells_to_rem_list_r13.is_present()) { j.start_array("whiteCellsToRemoveList-r13"); for (uint32_t i1 = 0; i1 < white_cells_to_rem_list_r13->size(); ++i1) { j.write_int(((*white_cells_to_rem_list_r13)[i1])); } j.end_array(); } - rrc_asn1_warn_assert( - white_cells_to_add_mod_list_r13_present != (white_cells_to_add_mod_list_r13.get() != NULL), __FILE__, __LINE__); - if (white_cells_to_add_mod_list_r13_present) { + if (white_cells_to_add_mod_list_r13.is_present()) { j.start_array("whiteCellsToAddModList-r13"); for (uint32_t i1 = 0; i1 < white_cells_to_add_mod_list_r13->size(); ++i1) { ((*white_cells_to_add_mod_list_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(rmtc_cfg_r13_present != (rmtc_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (rmtc_cfg_r13_present) { + if (rmtc_cfg_r13.is_present()) { j.write_fieldname("rmtc-Config-r13"); rmtc_cfg_r13->to_json(j); } if (carrier_freq_r13_present) { j.write_int("carrierFreq-r13", carrier_freq_r13); } - rrc_asn1_warn_assert( - tx_res_pool_to_rem_list_r14_present != (tx_res_pool_to_rem_list_r14.get() != NULL), __FILE__, __LINE__); - if (tx_res_pool_to_rem_list_r14_present) { + if (tx_res_pool_to_rem_list_r14.is_present()) { j.start_array("tx-ResourcePoolToRemoveList-r14"); for (uint32_t i1 = 0; i1 < tx_res_pool_to_rem_list_r14->size(); ++i1) { j.write_int(((*tx_res_pool_to_rem_list_r14)[i1])); } j.end_array(); } - rrc_asn1_warn_assert( - tx_res_pool_to_add_list_r14_present != (tx_res_pool_to_add_list_r14.get() != NULL), __FILE__, __LINE__); - if (tx_res_pool_to_add_list_r14_present) { + if (tx_res_pool_to_add_list_r14.is_present()) { j.start_array("tx-ResourcePoolToAddList-r14"); for (uint32_t i1 = 0; i1 < tx_res_pool_to_add_list_r14->size(); ++i1) { j.write_int(((*tx_res_pool_to_add_list_r14)[i1])); @@ -62998,8 +62148,7 @@ void meas_obj_eutra_s::to_json(json_writer& j) const if (fembms_mixed_carrier_r14_present) { j.write_bool("fembms-MixedCarrier-r14", fembms_mixed_carrier_r14); } - rrc_asn1_warn_assert(meas_sensing_cfg_r15_present != (meas_sensing_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (meas_sensing_cfg_r15_present) { + if (meas_sensing_cfg_r15.is_present()) { j.write_fieldname("measSensing-Config-r15"); meas_sensing_cfg_r15->to_json(j); } @@ -63172,32 +62321,30 @@ SRSASN_CODE meas_obj_nr_r15_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= cell_for_which_to_report_cgi_r15_present; group_flags[0] |= derive_ssb_idx_from_cell_r15_present; - rrc_asn1_warn_assert(ss_rssi_meas_r15_present != (ss_rssi_meas_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ss_rssi_meas_r15_present; - rrc_asn1_warn_assert(band_nr_r15_present != (band_nr_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= band_nr_r15_present; + group_flags[0] |= ss_rssi_meas_r15.is_present(); + group_flags[0] |= band_nr_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(cell_for_which_to_report_cgi_r15_present, 1)); HANDLE_CODE(bref.pack(derive_ssb_idx_from_cell_r15_present, 1)); - HANDLE_CODE(bref.pack(ss_rssi_meas_r15_present, 1)); - HANDLE_CODE(bref.pack(band_nr_r15_present, 1)); + HANDLE_CODE(bref.pack(ss_rssi_meas_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(band_nr_r15.is_present(), 1)); if (cell_for_which_to_report_cgi_r15_present) { HANDLE_CODE(pack_unalign_integer(bref, cell_for_which_to_report_cgi_r15, (uint16_t)0, (uint16_t)1007)); } if (derive_ssb_idx_from_cell_r15_present) { HANDLE_CODE(bref.pack(derive_ssb_idx_from_cell_r15, 1)); } - if (ss_rssi_meas_r15_present) { + if (ss_rssi_meas_r15.is_present()) { HANDLE_CODE(ss_rssi_meas_r15->pack(bref)); } - if (band_nr_r15_present) { + if (band_nr_r15.is_present()) { HANDLE_CODE(band_nr_r15->pack(bref)); } } @@ -63238,28 +62385,30 @@ SRSASN_CODE meas_obj_nr_r15_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(cell_for_which_to_report_cgi_r15_present, 1)); HANDLE_CODE(bref.unpack(derive_ssb_idx_from_cell_r15_present, 1)); + bool ss_rssi_meas_r15_present; HANDLE_CODE(bref.unpack(ss_rssi_meas_r15_present, 1)); + ss_rssi_meas_r15.set_present(ss_rssi_meas_r15_present); + bool band_nr_r15_present; HANDLE_CODE(bref.unpack(band_nr_r15_present, 1)); + band_nr_r15.set_present(band_nr_r15_present); if (cell_for_which_to_report_cgi_r15_present) { HANDLE_CODE(unpack_unalign_integer(cell_for_which_to_report_cgi_r15, bref, (uint16_t)0, (uint16_t)1007)); } if (derive_ssb_idx_from_cell_r15_present) { HANDLE_CODE(bref.unpack(derive_ssb_idx_from_cell_r15, 1)); } - if (ss_rssi_meas_r15_present) { - ss_rssi_meas_r15 = make_copy_ptr(ss_rssi_meas_r15_s()); + if (ss_rssi_meas_r15.is_present()) { HANDLE_CODE(ss_rssi_meas_r15->unpack(bref)); } - if (band_nr_r15_present) { - band_nr_r15 = make_copy_ptr(band_nr_r15_c_()); + if (band_nr_r15.is_present()) { HANDLE_CODE(band_nr_r15->unpack(bref)); } } @@ -63311,13 +62460,11 @@ void meas_obj_nr_r15_s::to_json(json_writer& j) const if (derive_ssb_idx_from_cell_r15_present) { j.write_bool("deriveSSB-IndexFromCell-r15", derive_ssb_idx_from_cell_r15); } - rrc_asn1_warn_assert(ss_rssi_meas_r15_present != (ss_rssi_meas_r15.get() != NULL), __FILE__, __LINE__); - if (ss_rssi_meas_r15_present) { + if (ss_rssi_meas_r15.is_present()) { j.write_fieldname("ss-RSSI-Measurement-r15"); ss_rssi_meas_r15->to_json(j); } - rrc_asn1_warn_assert(band_nr_r15_present != (band_nr_r15.get() != NULL), __FILE__, __LINE__); - if (band_nr_r15_present) { + if (band_nr_r15.is_present()) { j.write_fieldname("bandNR-r15"); band_nr_r15->to_json(j); } @@ -63400,23 +62547,21 @@ SRSASN_CODE meas_obj_utra_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert( - csg_allowed_report_cells_v930_present != (csg_allowed_report_cells_v930.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= csg_allowed_report_cells_v930_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= csg_allowed_report_cells_v930.is_present(); group_flags[1] |= reduced_meas_performance_r12_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(csg_allowed_report_cells_v930_present, 1)); - if (csg_allowed_report_cells_v930_present) { + HANDLE_CODE(bref.pack(csg_allowed_report_cells_v930.is_present(), 1)); + if (csg_allowed_report_cells_v930.is_present()) { HANDLE_CODE(csg_allowed_report_cells_v930->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(reduced_meas_performance_r12_present, 1)); if (reduced_meas_performance_r12_present) { @@ -63449,20 +62594,21 @@ SRSASN_CODE meas_obj_utra_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool csg_allowed_report_cells_v930_present; HANDLE_CODE(bref.unpack(csg_allowed_report_cells_v930_present, 1)); - if (csg_allowed_report_cells_v930_present) { - csg_allowed_report_cells_v930 = make_copy_ptr(csg_allowed_report_cells_r9_s()); + csg_allowed_report_cells_v930.set_present(csg_allowed_report_cells_v930_present); + if (csg_allowed_report_cells_v930.is_present()) { HANDLE_CODE(csg_allowed_report_cells_v930->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(reduced_meas_performance_r12_present, 1)); if (reduced_meas_performance_r12_present) { @@ -63495,9 +62641,7 @@ void meas_obj_utra_s::to_json(json_writer& j) const cell_for_which_to_report_cgi.to_json(j); } if (ext) { - rrc_asn1_warn_assert( - csg_allowed_report_cells_v930_present != (csg_allowed_report_cells_v930.get() != NULL), __FILE__, __LINE__); - if (csg_allowed_report_cells_v930_present) { + if (csg_allowed_report_cells_v930.is_present()) { j.write_fieldname("csg-allowedReportingCells-v930"); csg_allowed_report_cells_v930->to_json(j); } @@ -64634,69 +63778,59 @@ SRSASN_CODE report_cfg_eutra_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, report_amount)); if (ext) { - ext_groups_header group_flags(8); + ext_groups_packer_guard group_flags; group_flags[0] |= si_request_for_ho_r9_present; group_flags[0] |= ue_rx_tx_time_diff_periodical_r9_present; group_flags[1] |= include_location_info_r10_present; group_flags[1] |= report_add_neigh_meas_r10_present; - rrc_asn1_warn_assert( - alternative_time_to_trigger_r12_present != (alternative_time_to_trigger_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= alternative_time_to_trigger_r12_present; + group_flags[2] |= alternative_time_to_trigger_r12.is_present(); group_flags[2] |= use_t312_r12_present; group_flags[2] |= use_ps_cell_r12_present; - rrc_asn1_warn_assert(a_n_thres1_v1250_present != (a_n_thres1_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= a_n_thres1_v1250_present; - rrc_asn1_warn_assert(a5_thres2_v1250_present != (a5_thres2_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= a5_thres2_v1250_present; + group_flags[2] |= a_n_thres1_v1250.is_present(); + group_flags[2] |= a5_thres2_v1250.is_present(); group_flags[2] |= report_strongest_csi_rss_r12_present; group_flags[2] |= report_crs_meas_r12_present; group_flags[2] |= trigger_quant_csi_rs_r12_present; group_flags[3] |= report_sstd_meas_r13_present; - rrc_asn1_warn_assert(rs_sinr_cfg_r13_present != (rs_sinr_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= rs_sinr_cfg_r13_present; + group_flags[3] |= rs_sinr_cfg_r13.is_present(); group_flags[3] |= use_white_cell_list_r13_present; - rrc_asn1_warn_assert( - meas_rssi_report_cfg_r13_present != (meas_rssi_report_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_rssi_report_cfg_r13_present; + group_flags[3] |= meas_rssi_report_cfg_r13.is_present(); group_flags[3] |= include_multi_band_info_r13_present; - rrc_asn1_warn_assert(ul_delay_cfg_r13_present != (ul_delay_cfg_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= ul_delay_cfg_r13_present; + group_flags[3] |= ul_delay_cfg_r13.is_present(); group_flags[4] |= ue_rx_tx_time_diff_periodical_tdd_r13_present; group_flags[5] |= purpose_v1430_present; group_flags[6] |= max_report_rs_idx_r15_present; - rrc_asn1_warn_assert(include_bt_meas_r15_present != (include_bt_meas_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= include_bt_meas_r15_present; - rrc_asn1_warn_assert(include_wlan_meas_r15_present != (include_wlan_meas_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= include_wlan_meas_r15_present; + group_flags[7] |= include_bt_meas_r15.is_present(); + group_flags[7] |= include_wlan_meas_r15.is_present(); group_flags[7] |= purpose_r15_present; group_flags[7] |= nof_triggering_cells_r15_present; group_flags[7] |= a4_a5_report_on_leave_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(si_request_for_ho_r9_present, 1)); HANDLE_CODE(bref.pack(ue_rx_tx_time_diff_periodical_r9_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(include_location_info_r10_present, 1)); HANDLE_CODE(bref.pack(report_add_neigh_meas_r10_present, 1)); } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(alternative_time_to_trigger_r12_present, 1)); + HANDLE_CODE(bref.pack(alternative_time_to_trigger_r12.is_present(), 1)); HANDLE_CODE(bref.pack(use_t312_r12_present, 1)); HANDLE_CODE(bref.pack(use_ps_cell_r12_present, 1)); - HANDLE_CODE(bref.pack(a_n_thres1_v1250_present, 1)); - HANDLE_CODE(bref.pack(a5_thres2_v1250_present, 1)); + HANDLE_CODE(bref.pack(a_n_thres1_v1250.is_present(), 1)); + HANDLE_CODE(bref.pack(a5_thres2_v1250.is_present(), 1)); HANDLE_CODE(bref.pack(report_strongest_csi_rss_r12_present, 1)); HANDLE_CODE(bref.pack(report_crs_meas_r12_present, 1)); HANDLE_CODE(bref.pack(trigger_quant_csi_rs_r12_present, 1)); - if (alternative_time_to_trigger_r12_present) { + if (alternative_time_to_trigger_r12.is_present()) { HANDLE_CODE(alternative_time_to_trigger_r12->pack(bref)); } if (use_t312_r12_present) { @@ -64705,10 +63839,10 @@ SRSASN_CODE report_cfg_eutra_s::pack(bit_ref& bref) const if (use_ps_cell_r12_present) { HANDLE_CODE(bref.pack(use_ps_cell_r12, 1)); } - if (a_n_thres1_v1250_present) { + if (a_n_thres1_v1250.is_present()) { HANDLE_CODE(a_n_thres1_v1250->pack(bref)); } - if (a5_thres2_v1250_present) { + if (a5_thres2_v1250.is_present()) { HANDLE_CODE(a5_thres2_v1250->pack(bref)); } if (report_strongest_csi_rss_r12_present) { @@ -64722,32 +63856,32 @@ SRSASN_CODE report_cfg_eutra_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(report_sstd_meas_r13_present, 1)); - HANDLE_CODE(bref.pack(rs_sinr_cfg_r13_present, 1)); + HANDLE_CODE(bref.pack(rs_sinr_cfg_r13.is_present(), 1)); HANDLE_CODE(bref.pack(use_white_cell_list_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_rssi_report_cfg_r13_present, 1)); + HANDLE_CODE(bref.pack(meas_rssi_report_cfg_r13.is_present(), 1)); HANDLE_CODE(bref.pack(include_multi_band_info_r13_present, 1)); - HANDLE_CODE(bref.pack(ul_delay_cfg_r13_present, 1)); + HANDLE_CODE(bref.pack(ul_delay_cfg_r13.is_present(), 1)); if (report_sstd_meas_r13_present) { HANDLE_CODE(bref.pack(report_sstd_meas_r13, 1)); } - if (rs_sinr_cfg_r13_present) { + if (rs_sinr_cfg_r13.is_present()) { HANDLE_CODE(rs_sinr_cfg_r13->pack(bref)); } if (use_white_cell_list_r13_present) { HANDLE_CODE(bref.pack(use_white_cell_list_r13, 1)); } - if (meas_rssi_report_cfg_r13_present) { + if (meas_rssi_report_cfg_r13.is_present()) { HANDLE_CODE(meas_rssi_report_cfg_r13->pack(bref)); } - if (ul_delay_cfg_r13_present) { + if (ul_delay_cfg_r13.is_present()) { HANDLE_CODE(ul_delay_cfg_r13->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(ue_rx_tx_time_diff_periodical_tdd_r13_present, 1)); if (ue_rx_tx_time_diff_periodical_tdd_r13_present) { @@ -64755,7 +63889,7 @@ SRSASN_CODE report_cfg_eutra_s::pack(bit_ref& bref) const } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(purpose_v1430_present, 1)); if (purpose_v1430_present) { @@ -64763,7 +63897,7 @@ SRSASN_CODE report_cfg_eutra_s::pack(bit_ref& bref) const } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(max_report_rs_idx_r15_present, 1)); if (max_report_rs_idx_r15_present) { @@ -64771,17 +63905,17 @@ SRSASN_CODE report_cfg_eutra_s::pack(bit_ref& bref) const } } if (group_flags[7]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(include_bt_meas_r15_present, 1)); - HANDLE_CODE(bref.pack(include_wlan_meas_r15_present, 1)); + HANDLE_CODE(bref.pack(include_bt_meas_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(include_wlan_meas_r15.is_present(), 1)); HANDLE_CODE(bref.pack(purpose_r15_present, 1)); HANDLE_CODE(bref.pack(nof_triggering_cells_r15_present, 1)); HANDLE_CODE(bref.pack(a4_a5_report_on_leave_r15_present, 1)); - if (include_bt_meas_r15_present) { + if (include_bt_meas_r15.is_present()) { HANDLE_CODE(include_bt_meas_r15->pack(bref)); } - if (include_wlan_meas_r15_present) { + if (include_wlan_meas_r15.is_present()) { HANDLE_CODE(include_wlan_meas_r15->pack(bref)); } if (nof_triggering_cells_r15_present) { @@ -64805,34 +63939,39 @@ SRSASN_CODE report_cfg_eutra_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(report_amount, bref)); if (ext) { - ext_groups_header group_flags(8); + ext_groups_unpacker_guard group_flags(8); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(si_request_for_ho_r9_present, 1)); HANDLE_CODE(bref.unpack(ue_rx_tx_time_diff_periodical_r9_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(include_location_info_r10_present, 1)); HANDLE_CODE(bref.unpack(report_add_neigh_meas_r10_present, 1)); } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool alternative_time_to_trigger_r12_present; HANDLE_CODE(bref.unpack(alternative_time_to_trigger_r12_present, 1)); + alternative_time_to_trigger_r12.set_present(alternative_time_to_trigger_r12_present); HANDLE_CODE(bref.unpack(use_t312_r12_present, 1)); HANDLE_CODE(bref.unpack(use_ps_cell_r12_present, 1)); + bool a_n_thres1_v1250_present; HANDLE_CODE(bref.unpack(a_n_thres1_v1250_present, 1)); + a_n_thres1_v1250.set_present(a_n_thres1_v1250_present); + bool a5_thres2_v1250_present; HANDLE_CODE(bref.unpack(a5_thres2_v1250_present, 1)); + a5_thres2_v1250.set_present(a5_thres2_v1250_present); HANDLE_CODE(bref.unpack(report_strongest_csi_rss_r12_present, 1)); HANDLE_CODE(bref.unpack(report_crs_meas_r12_present, 1)); HANDLE_CODE(bref.unpack(trigger_quant_csi_rs_r12_present, 1)); - if (alternative_time_to_trigger_r12_present) { - alternative_time_to_trigger_r12 = make_copy_ptr(alternative_time_to_trigger_r12_c_()); + if (alternative_time_to_trigger_r12.is_present()) { HANDLE_CODE(alternative_time_to_trigger_r12->unpack(bref)); } if (use_t312_r12_present) { @@ -64841,12 +63980,10 @@ SRSASN_CODE report_cfg_eutra_s::unpack(bit_ref& bref) if (use_ps_cell_r12_present) { HANDLE_CODE(bref.unpack(use_ps_cell_r12, 1)); } - if (a_n_thres1_v1250_present) { - a_n_thres1_v1250 = make_copy_ptr(rsrq_range_cfg_r12_c()); + if (a_n_thres1_v1250.is_present()) { HANDLE_CODE(a_n_thres1_v1250->unpack(bref)); } - if (a5_thres2_v1250_present) { - a5_thres2_v1250 = make_copy_ptr(rsrq_range_cfg_r12_c()); + if (a5_thres2_v1250.is_present()) { HANDLE_CODE(a5_thres2_v1250->unpack(bref)); } if (report_strongest_csi_rss_r12_present) { @@ -64860,35 +63997,38 @@ SRSASN_CODE report_cfg_eutra_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(report_sstd_meas_r13_present, 1)); + bool rs_sinr_cfg_r13_present; HANDLE_CODE(bref.unpack(rs_sinr_cfg_r13_present, 1)); + rs_sinr_cfg_r13.set_present(rs_sinr_cfg_r13_present); HANDLE_CODE(bref.unpack(use_white_cell_list_r13_present, 1)); + bool meas_rssi_report_cfg_r13_present; HANDLE_CODE(bref.unpack(meas_rssi_report_cfg_r13_present, 1)); + meas_rssi_report_cfg_r13.set_present(meas_rssi_report_cfg_r13_present); HANDLE_CODE(bref.unpack(include_multi_band_info_r13_present, 1)); + bool ul_delay_cfg_r13_present; HANDLE_CODE(bref.unpack(ul_delay_cfg_r13_present, 1)); + ul_delay_cfg_r13.set_present(ul_delay_cfg_r13_present); if (report_sstd_meas_r13_present) { HANDLE_CODE(bref.unpack(report_sstd_meas_r13, 1)); } - if (rs_sinr_cfg_r13_present) { - rs_sinr_cfg_r13 = make_copy_ptr(rs_sinr_cfg_r13_c_()); + if (rs_sinr_cfg_r13.is_present()) { HANDLE_CODE(rs_sinr_cfg_r13->unpack(bref)); } if (use_white_cell_list_r13_present) { HANDLE_CODE(bref.unpack(use_white_cell_list_r13, 1)); } - if (meas_rssi_report_cfg_r13_present) { - meas_rssi_report_cfg_r13 = make_copy_ptr(meas_rssi_report_cfg_r13_s()); + if (meas_rssi_report_cfg_r13.is_present()) { HANDLE_CODE(meas_rssi_report_cfg_r13->unpack(bref)); } - if (ul_delay_cfg_r13_present) { - ul_delay_cfg_r13 = make_copy_ptr(ul_delay_cfg_r13_c()); + if (ul_delay_cfg_r13.is_present()) { HANDLE_CODE(ul_delay_cfg_r13->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(ue_rx_tx_time_diff_periodical_tdd_r13_present, 1)); if (ue_rx_tx_time_diff_periodical_tdd_r13_present) { @@ -64896,7 +64036,7 @@ SRSASN_CODE report_cfg_eutra_s::unpack(bit_ref& bref) } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(purpose_v1430_present, 1)); if (purpose_v1430_present) { @@ -64904,7 +64044,7 @@ SRSASN_CODE report_cfg_eutra_s::unpack(bit_ref& bref) } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(max_report_rs_idx_r15_present, 1)); if (max_report_rs_idx_r15_present) { @@ -64912,19 +64052,21 @@ SRSASN_CODE report_cfg_eutra_s::unpack(bit_ref& bref) } } if (group_flags[7]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool include_bt_meas_r15_present; HANDLE_CODE(bref.unpack(include_bt_meas_r15_present, 1)); + include_bt_meas_r15.set_present(include_bt_meas_r15_present); + bool include_wlan_meas_r15_present; HANDLE_CODE(bref.unpack(include_wlan_meas_r15_present, 1)); + include_wlan_meas_r15.set_present(include_wlan_meas_r15_present); HANDLE_CODE(bref.unpack(purpose_r15_present, 1)); HANDLE_CODE(bref.unpack(nof_triggering_cells_r15_present, 1)); HANDLE_CODE(bref.unpack(a4_a5_report_on_leave_r15_present, 1)); - if (include_bt_meas_r15_present) { - include_bt_meas_r15 = make_copy_ptr(bt_name_list_cfg_r15_c()); + if (include_bt_meas_r15.is_present()) { HANDLE_CODE(include_bt_meas_r15->unpack(bref)); } - if (include_wlan_meas_r15_present) { - include_wlan_meas_r15 = make_copy_ptr(wlan_name_list_cfg_r15_c()); + if (include_wlan_meas_r15.is_present()) { HANDLE_CODE(include_wlan_meas_r15->unpack(bref)); } if (nof_triggering_cells_r15_present) { @@ -64960,9 +64102,7 @@ void report_cfg_eutra_s::to_json(json_writer& j) const if (report_add_neigh_meas_r10_present) { j.write_str("reportAddNeighMeas-r10", "setup"); } - rrc_asn1_warn_assert( - alternative_time_to_trigger_r12_present != (alternative_time_to_trigger_r12.get() != NULL), __FILE__, __LINE__); - if (alternative_time_to_trigger_r12_present) { + if (alternative_time_to_trigger_r12.is_present()) { j.write_fieldname("alternativeTimeToTrigger-r12"); alternative_time_to_trigger_r12->to_json(j); } @@ -64972,13 +64112,11 @@ void report_cfg_eutra_s::to_json(json_writer& j) const if (use_ps_cell_r12_present) { j.write_bool("usePSCell-r12", use_ps_cell_r12); } - rrc_asn1_warn_assert(a_n_thres1_v1250_present != (a_n_thres1_v1250.get() != NULL), __FILE__, __LINE__); - if (a_n_thres1_v1250_present) { + if (a_n_thres1_v1250.is_present()) { j.write_fieldname("aN-Threshold1-v1250"); a_n_thres1_v1250->to_json(j); } - rrc_asn1_warn_assert(a5_thres2_v1250_present != (a5_thres2_v1250.get() != NULL), __FILE__, __LINE__); - if (a5_thres2_v1250_present) { + if (a5_thres2_v1250.is_present()) { j.write_fieldname("a5-Threshold2-v1250"); a5_thres2_v1250->to_json(j); } @@ -64994,25 +64132,21 @@ void report_cfg_eutra_s::to_json(json_writer& j) const if (report_sstd_meas_r13_present) { j.write_bool("reportSSTD-Meas-r13", report_sstd_meas_r13); } - rrc_asn1_warn_assert(rs_sinr_cfg_r13_present != (rs_sinr_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (rs_sinr_cfg_r13_present) { + if (rs_sinr_cfg_r13.is_present()) { j.write_fieldname("rs-sinr-Config-r13"); rs_sinr_cfg_r13->to_json(j); } if (use_white_cell_list_r13_present) { j.write_bool("useWhiteCellList-r13", use_white_cell_list_r13); } - rrc_asn1_warn_assert( - meas_rssi_report_cfg_r13_present != (meas_rssi_report_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (meas_rssi_report_cfg_r13_present) { + if (meas_rssi_report_cfg_r13.is_present()) { j.write_fieldname("measRSSI-ReportConfig-r13"); meas_rssi_report_cfg_r13->to_json(j); } if (include_multi_band_info_r13_present) { j.write_str("includeMultiBandInfo-r13", "true"); } - rrc_asn1_warn_assert(ul_delay_cfg_r13_present != (ul_delay_cfg_r13.get() != NULL), __FILE__, __LINE__); - if (ul_delay_cfg_r13_present) { + if (ul_delay_cfg_r13.is_present()) { j.write_fieldname("ul-DelayConfig-r13"); ul_delay_cfg_r13->to_json(j); } @@ -65025,13 +64159,11 @@ void report_cfg_eutra_s::to_json(json_writer& j) const if (max_report_rs_idx_r15_present) { j.write_int("maxReportRS-Index-r15", max_report_rs_idx_r15); } - rrc_asn1_warn_assert(include_bt_meas_r15_present != (include_bt_meas_r15.get() != NULL), __FILE__, __LINE__); - if (include_bt_meas_r15_present) { + if (include_bt_meas_r15.is_present()) { j.write_fieldname("includeBT-Meas-r15"); include_bt_meas_r15->to_json(j); } - rrc_asn1_warn_assert(include_wlan_meas_r15_present != (include_wlan_meas_r15.get() != NULL), __FILE__, __LINE__); - if (include_wlan_meas_r15_present) { + if (include_wlan_meas_r15.is_present()) { j.write_fieldname("includeWLAN-Meas-r15"); include_wlan_meas_r15->to_json(j); } @@ -65312,38 +64444,32 @@ SRSASN_CODE report_cfg_inter_rat_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, report_amount)); if (ext) { - ext_groups_header group_flags(7); + ext_groups_packer_guard group_flags; group_flags[0] |= si_request_for_ho_r9_present; group_flags[1] |= report_quant_utra_fdd_r10_present; group_flags[2] |= include_location_info_r11_present; - rrc_asn1_warn_assert(b2_thres1_v1250_present != (b2_thres1_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= b2_thres1_v1250_present; - rrc_asn1_warn_assert(report_quant_wlan_r13_present != (report_quant_wlan_r13.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= report_quant_wlan_r13_present; + group_flags[3] |= b2_thres1_v1250.is_present(); + group_flags[4] |= report_quant_wlan_r13.is_present(); group_flags[5] |= report_any_wlan_r14_present; - rrc_asn1_warn_assert( - report_quant_cell_nr_r15_present != (report_quant_cell_nr_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= report_quant_cell_nr_r15_present; + group_flags[6] |= report_quant_cell_nr_r15.is_present(); group_flags[6] |= max_report_rs_idx_r15_present; - rrc_asn1_warn_assert( - report_quant_rs_idx_nr_r15_present != (report_quant_rs_idx_nr_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= report_quant_rs_idx_nr_r15_present; + group_flags[6] |= report_quant_rs_idx_nr_r15.is_present(); group_flags[6] |= report_rs_idx_results_nr_present; group_flags[6] |= report_sftd_meas_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(si_request_for_ho_r9_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(report_quant_utra_fdd_r10_present, 1)); } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(include_location_info_r11_present, 1)); if (include_location_info_r11_present) { @@ -65351,23 +64477,23 @@ SRSASN_CODE report_cfg_inter_rat_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(b2_thres1_v1250_present, 1)); - if (b2_thres1_v1250_present) { + HANDLE_CODE(bref.pack(b2_thres1_v1250.is_present(), 1)); + if (b2_thres1_v1250.is_present()) { HANDLE_CODE(b2_thres1_v1250->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(report_quant_wlan_r13_present, 1)); - if (report_quant_wlan_r13_present) { + HANDLE_CODE(bref.pack(report_quant_wlan_r13.is_present(), 1)); + if (report_quant_wlan_r13.is_present()) { HANDLE_CODE(report_quant_wlan_r13->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(report_any_wlan_r14_present, 1)); if (report_any_wlan_r14_present) { @@ -65375,20 +64501,20 @@ SRSASN_CODE report_cfg_inter_rat_s::pack(bit_ref& bref) const } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(report_quant_cell_nr_r15_present, 1)); + HANDLE_CODE(bref.pack(report_quant_cell_nr_r15.is_present(), 1)); HANDLE_CODE(bref.pack(max_report_rs_idx_r15_present, 1)); - HANDLE_CODE(bref.pack(report_quant_rs_idx_nr_r15_present, 1)); + HANDLE_CODE(bref.pack(report_quant_rs_idx_nr_r15.is_present(), 1)); HANDLE_CODE(bref.pack(report_rs_idx_results_nr_present, 1)); HANDLE_CODE(bref.pack(report_sftd_meas_r15_present, 1)); - if (report_quant_cell_nr_r15_present) { + if (report_quant_cell_nr_r15.is_present()) { HANDLE_CODE(report_quant_cell_nr_r15->pack(bref)); } if (max_report_rs_idx_r15_present) { HANDLE_CODE(pack_unalign_integer(bref, max_report_rs_idx_r15, (uint8_t)0, (uint8_t)32)); } - if (report_quant_rs_idx_nr_r15_present) { + if (report_quant_rs_idx_nr_r15.is_present()) { HANDLE_CODE(report_quant_rs_idx_nr_r15->pack(bref)); } if (report_rs_idx_results_nr_present) { @@ -65410,21 +64536,21 @@ SRSASN_CODE report_cfg_inter_rat_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(report_amount, bref)); if (ext) { - ext_groups_header group_flags(7); + ext_groups_unpacker_guard group_flags(7); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(si_request_for_ho_r9_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(report_quant_utra_fdd_r10_present, 1)); } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(include_location_info_r11_present, 1)); if (include_location_info_r11_present) { @@ -65432,25 +64558,27 @@ SRSASN_CODE report_cfg_inter_rat_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool b2_thres1_v1250_present; HANDLE_CODE(bref.unpack(b2_thres1_v1250_present, 1)); - if (b2_thres1_v1250_present) { - b2_thres1_v1250 = make_copy_ptr(b2_thres1_v1250_c_()); + b2_thres1_v1250.set_present(b2_thres1_v1250_present); + if (b2_thres1_v1250.is_present()) { HANDLE_CODE(b2_thres1_v1250->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool report_quant_wlan_r13_present; HANDLE_CODE(bref.unpack(report_quant_wlan_r13_present, 1)); - if (report_quant_wlan_r13_present) { - report_quant_wlan_r13 = make_copy_ptr(report_quant_wlan_r13_s()); + report_quant_wlan_r13.set_present(report_quant_wlan_r13_present); + if (report_quant_wlan_r13.is_present()) { HANDLE_CODE(report_quant_wlan_r13->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(report_any_wlan_r14_present, 1)); if (report_any_wlan_r14_present) { @@ -65458,22 +64586,24 @@ SRSASN_CODE report_cfg_inter_rat_s::unpack(bit_ref& bref) } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool report_quant_cell_nr_r15_present; HANDLE_CODE(bref.unpack(report_quant_cell_nr_r15_present, 1)); + report_quant_cell_nr_r15.set_present(report_quant_cell_nr_r15_present); HANDLE_CODE(bref.unpack(max_report_rs_idx_r15_present, 1)); + bool report_quant_rs_idx_nr_r15_present; HANDLE_CODE(bref.unpack(report_quant_rs_idx_nr_r15_present, 1)); + report_quant_rs_idx_nr_r15.set_present(report_quant_rs_idx_nr_r15_present); HANDLE_CODE(bref.unpack(report_rs_idx_results_nr_present, 1)); HANDLE_CODE(bref.unpack(report_sftd_meas_r15_present, 1)); - if (report_quant_cell_nr_r15_present) { - report_quant_cell_nr_r15 = make_copy_ptr(report_quant_nr_r15_s()); + if (report_quant_cell_nr_r15.is_present()) { HANDLE_CODE(report_quant_cell_nr_r15->unpack(bref)); } if (max_report_rs_idx_r15_present) { HANDLE_CODE(unpack_unalign_integer(max_report_rs_idx_r15, bref, (uint8_t)0, (uint8_t)32)); } - if (report_quant_rs_idx_nr_r15_present) { - report_quant_rs_idx_nr_r15 = make_copy_ptr(report_quant_nr_r15_s()); + if (report_quant_rs_idx_nr_r15.is_present()) { HANDLE_CODE(report_quant_rs_idx_nr_r15->unpack(bref)); } if (report_rs_idx_results_nr_present) { @@ -65504,31 +64634,25 @@ void report_cfg_inter_rat_s::to_json(json_writer& j) const if (include_location_info_r11_present) { j.write_bool("includeLocationInfo-r11", include_location_info_r11); } - rrc_asn1_warn_assert(b2_thres1_v1250_present != (b2_thres1_v1250.get() != NULL), __FILE__, __LINE__); - if (b2_thres1_v1250_present) { + if (b2_thres1_v1250.is_present()) { j.write_fieldname("b2-Threshold1-v1250"); b2_thres1_v1250->to_json(j); } - rrc_asn1_warn_assert(report_quant_wlan_r13_present != (report_quant_wlan_r13.get() != NULL), __FILE__, __LINE__); - if (report_quant_wlan_r13_present) { + if (report_quant_wlan_r13.is_present()) { j.write_fieldname("reportQuantityWLAN-r13"); report_quant_wlan_r13->to_json(j); } if (report_any_wlan_r14_present) { j.write_bool("reportAnyWLAN-r14", report_any_wlan_r14); } - rrc_asn1_warn_assert( - report_quant_cell_nr_r15_present != (report_quant_cell_nr_r15.get() != NULL), __FILE__, __LINE__); - if (report_quant_cell_nr_r15_present) { + if (report_quant_cell_nr_r15.is_present()) { j.write_fieldname("reportQuantityCellNR-r15"); report_quant_cell_nr_r15->to_json(j); } if (max_report_rs_idx_r15_present) { j.write_int("maxReportRS-Index-r15", max_report_rs_idx_r15); } - rrc_asn1_warn_assert( - report_quant_rs_idx_nr_r15_present != (report_quant_rs_idx_nr_r15.get() != NULL), __FILE__, __LINE__); - if (report_quant_rs_idx_nr_r15_present) { + if (report_quant_rs_idx_nr_r15.is_present()) { j.write_fieldname("reportQuantityRS-IndexNR-r15"); report_quant_rs_idx_nr_r15->to_json(j); } @@ -67195,94 +66319,82 @@ SRSASN_CODE other_cfg_r9_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); - rrc_asn1_warn_assert(idc_cfg_r11_present != (idc_cfg_r11.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= idc_cfg_r11_present; - rrc_asn1_warn_assert(pwr_pref_ind_cfg_r11_present != (pwr_pref_ind_cfg_r11.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= pwr_pref_ind_cfg_r11_present; - rrc_asn1_warn_assert( - obtain_location_cfg_r11_present != (obtain_location_cfg_r11.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= obtain_location_cfg_r11_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= idc_cfg_r11.is_present(); + group_flags[0] |= pwr_pref_ind_cfg_r11.is_present(); + group_flags[0] |= obtain_location_cfg_r11.is_present(); group_flags[1] |= bw_pref_ind_timer_r14_present; group_flags[1] |= sps_assist_info_report_r14_present; - rrc_asn1_warn_assert( - delay_budget_report_cfg_r14_present != (delay_budget_report_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= delay_budget_report_cfg_r14_present; - rrc_asn1_warn_assert(rlm_report_cfg_r14_present != (rlm_report_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= rlm_report_cfg_r14_present; - rrc_asn1_warn_assert( - overheat_assist_cfg_r14_present != (overheat_assist_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= overheat_assist_cfg_r14_present; - rrc_asn1_warn_assert(meas_cfg_app_layer_r15_present != (meas_cfg_app_layer_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_cfg_app_layer_r15_present; + group_flags[1] |= delay_budget_report_cfg_r14.is_present(); + group_flags[1] |= rlm_report_cfg_r14.is_present(); + group_flags[2] |= overheat_assist_cfg_r14.is_present(); + group_flags[3] |= meas_cfg_app_layer_r15.is_present(); group_flags[3] |= ailc_bit_cfg_r15_present; - rrc_asn1_warn_assert(bt_name_list_cfg_r15_present != (bt_name_list_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= bt_name_list_cfg_r15_present; - rrc_asn1_warn_assert(wlan_name_list_cfg_r15_present != (wlan_name_list_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= wlan_name_list_cfg_r15_present; + group_flags[3] |= bt_name_list_cfg_r15.is_present(); + group_flags[3] |= wlan_name_list_cfg_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(idc_cfg_r11_present, 1)); - HANDLE_CODE(bref.pack(pwr_pref_ind_cfg_r11_present, 1)); - HANDLE_CODE(bref.pack(obtain_location_cfg_r11_present, 1)); - if (idc_cfg_r11_present) { + HANDLE_CODE(bref.pack(idc_cfg_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(pwr_pref_ind_cfg_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(obtain_location_cfg_r11.is_present(), 1)); + if (idc_cfg_r11.is_present()) { HANDLE_CODE(idc_cfg_r11->pack(bref)); } - if (pwr_pref_ind_cfg_r11_present) { + if (pwr_pref_ind_cfg_r11.is_present()) { HANDLE_CODE(pwr_pref_ind_cfg_r11->pack(bref)); } - if (obtain_location_cfg_r11_present) { + if (obtain_location_cfg_r11.is_present()) { HANDLE_CODE(obtain_location_cfg_r11->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(bw_pref_ind_timer_r14_present, 1)); HANDLE_CODE(bref.pack(sps_assist_info_report_r14_present, 1)); - HANDLE_CODE(bref.pack(delay_budget_report_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(rlm_report_cfg_r14_present, 1)); + HANDLE_CODE(bref.pack(delay_budget_report_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(rlm_report_cfg_r14.is_present(), 1)); if (bw_pref_ind_timer_r14_present) { HANDLE_CODE(pack_enum(bref, bw_pref_ind_timer_r14)); } if (sps_assist_info_report_r14_present) { HANDLE_CODE(bref.pack(sps_assist_info_report_r14, 1)); } - if (delay_budget_report_cfg_r14_present) { + if (delay_budget_report_cfg_r14.is_present()) { HANDLE_CODE(delay_budget_report_cfg_r14->pack(bref)); } - if (rlm_report_cfg_r14_present) { + if (rlm_report_cfg_r14.is_present()) { HANDLE_CODE(rlm_report_cfg_r14->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(overheat_assist_cfg_r14_present, 1)); - if (overheat_assist_cfg_r14_present) { + HANDLE_CODE(bref.pack(overheat_assist_cfg_r14.is_present(), 1)); + if (overheat_assist_cfg_r14.is_present()) { HANDLE_CODE(overheat_assist_cfg_r14->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_cfg_app_layer_r15_present, 1)); + HANDLE_CODE(bref.pack(meas_cfg_app_layer_r15.is_present(), 1)); HANDLE_CODE(bref.pack(ailc_bit_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(bt_name_list_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(wlan_name_list_cfg_r15_present, 1)); - if (meas_cfg_app_layer_r15_present) { + HANDLE_CODE(bref.pack(bt_name_list_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(wlan_name_list_cfg_r15.is_present(), 1)); + if (meas_cfg_app_layer_r15.is_present()) { HANDLE_CODE(meas_cfg_app_layer_r15->pack(bref)); } if (ailc_bit_cfg_r15_present) { HANDLE_CODE(bref.pack(ailc_bit_cfg_r15, 1)); } - if (bt_name_list_cfg_r15_present) { + if (bt_name_list_cfg_r15.is_present()) { HANDLE_CODE(bt_name_list_cfg_r15->pack(bref)); } - if (wlan_name_list_cfg_r15_present) { + if (wlan_name_list_cfg_r15.is_present()) { HANDLE_CODE(wlan_name_list_cfg_r15->pack(bref)); } } @@ -67299,79 +66411,88 @@ SRSASN_CODE other_cfg_r9_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool idc_cfg_r11_present; HANDLE_CODE(bref.unpack(idc_cfg_r11_present, 1)); + idc_cfg_r11.set_present(idc_cfg_r11_present); + bool pwr_pref_ind_cfg_r11_present; HANDLE_CODE(bref.unpack(pwr_pref_ind_cfg_r11_present, 1)); + pwr_pref_ind_cfg_r11.set_present(pwr_pref_ind_cfg_r11_present); + bool obtain_location_cfg_r11_present; HANDLE_CODE(bref.unpack(obtain_location_cfg_r11_present, 1)); - if (idc_cfg_r11_present) { - idc_cfg_r11 = make_copy_ptr(idc_cfg_r11_s()); + obtain_location_cfg_r11.set_present(obtain_location_cfg_r11_present); + if (idc_cfg_r11.is_present()) { HANDLE_CODE(idc_cfg_r11->unpack(bref)); } - if (pwr_pref_ind_cfg_r11_present) { - pwr_pref_ind_cfg_r11 = make_copy_ptr(pwr_pref_ind_cfg_r11_c()); + if (pwr_pref_ind_cfg_r11.is_present()) { HANDLE_CODE(pwr_pref_ind_cfg_r11->unpack(bref)); } - if (obtain_location_cfg_r11_present) { - obtain_location_cfg_r11 = make_copy_ptr(obtain_location_cfg_r11_s()); + if (obtain_location_cfg_r11.is_present()) { HANDLE_CODE(obtain_location_cfg_r11->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(bw_pref_ind_timer_r14_present, 1)); HANDLE_CODE(bref.unpack(sps_assist_info_report_r14_present, 1)); + bool delay_budget_report_cfg_r14_present; HANDLE_CODE(bref.unpack(delay_budget_report_cfg_r14_present, 1)); + delay_budget_report_cfg_r14.set_present(delay_budget_report_cfg_r14_present); + bool rlm_report_cfg_r14_present; HANDLE_CODE(bref.unpack(rlm_report_cfg_r14_present, 1)); + rlm_report_cfg_r14.set_present(rlm_report_cfg_r14_present); if (bw_pref_ind_timer_r14_present) { HANDLE_CODE(unpack_enum(bw_pref_ind_timer_r14, bref)); } if (sps_assist_info_report_r14_present) { HANDLE_CODE(bref.unpack(sps_assist_info_report_r14, 1)); } - if (delay_budget_report_cfg_r14_present) { - delay_budget_report_cfg_r14 = make_copy_ptr(delay_budget_report_cfg_r14_c_()); + if (delay_budget_report_cfg_r14.is_present()) { HANDLE_CODE(delay_budget_report_cfg_r14->unpack(bref)); } - if (rlm_report_cfg_r14_present) { - rlm_report_cfg_r14 = make_copy_ptr(rlm_report_cfg_r14_c_()); + if (rlm_report_cfg_r14.is_present()) { HANDLE_CODE(rlm_report_cfg_r14->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool overheat_assist_cfg_r14_present; HANDLE_CODE(bref.unpack(overheat_assist_cfg_r14_present, 1)); - if (overheat_assist_cfg_r14_present) { - overheat_assist_cfg_r14 = make_copy_ptr(overheat_assist_cfg_r14_c_()); + overheat_assist_cfg_r14.set_present(overheat_assist_cfg_r14_present); + if (overheat_assist_cfg_r14.is_present()) { HANDLE_CODE(overheat_assist_cfg_r14->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_cfg_app_layer_r15_present; HANDLE_CODE(bref.unpack(meas_cfg_app_layer_r15_present, 1)); + meas_cfg_app_layer_r15.set_present(meas_cfg_app_layer_r15_present); HANDLE_CODE(bref.unpack(ailc_bit_cfg_r15_present, 1)); + bool bt_name_list_cfg_r15_present; HANDLE_CODE(bref.unpack(bt_name_list_cfg_r15_present, 1)); + bt_name_list_cfg_r15.set_present(bt_name_list_cfg_r15_present); + bool wlan_name_list_cfg_r15_present; HANDLE_CODE(bref.unpack(wlan_name_list_cfg_r15_present, 1)); - if (meas_cfg_app_layer_r15_present) { - meas_cfg_app_layer_r15 = make_copy_ptr(meas_cfg_app_layer_r15_c_()); + wlan_name_list_cfg_r15.set_present(wlan_name_list_cfg_r15_present); + if (meas_cfg_app_layer_r15.is_present()) { HANDLE_CODE(meas_cfg_app_layer_r15->unpack(bref)); } if (ailc_bit_cfg_r15_present) { HANDLE_CODE(bref.unpack(ailc_bit_cfg_r15, 1)); } - if (bt_name_list_cfg_r15_present) { - bt_name_list_cfg_r15 = make_copy_ptr(bt_name_list_cfg_r15_c()); + if (bt_name_list_cfg_r15.is_present()) { HANDLE_CODE(bt_name_list_cfg_r15->unpack(bref)); } - if (wlan_name_list_cfg_r15_present) { - wlan_name_list_cfg_r15 = make_copy_ptr(wlan_name_list_cfg_r15_c()); + if (wlan_name_list_cfg_r15.is_present()) { HANDLE_CODE(wlan_name_list_cfg_r15->unpack(bref)); } } @@ -67386,19 +66507,15 @@ void other_cfg_r9_s::to_json(json_writer& j) const report_proximity_cfg_r9.to_json(j); } if (ext) { - rrc_asn1_warn_assert(idc_cfg_r11_present != (idc_cfg_r11.get() != NULL), __FILE__, __LINE__); - if (idc_cfg_r11_present) { + if (idc_cfg_r11.is_present()) { j.write_fieldname("idc-Config-r11"); idc_cfg_r11->to_json(j); } - rrc_asn1_warn_assert(pwr_pref_ind_cfg_r11_present != (pwr_pref_ind_cfg_r11.get() != NULL), __FILE__, __LINE__); - if (pwr_pref_ind_cfg_r11_present) { + if (pwr_pref_ind_cfg_r11.is_present()) { j.write_fieldname("powerPrefIndicationConfig-r11"); pwr_pref_ind_cfg_r11->to_json(j); } - rrc_asn1_warn_assert( - obtain_location_cfg_r11_present != (obtain_location_cfg_r11.get() != NULL), __FILE__, __LINE__); - if (obtain_location_cfg_r11_present) { + if (obtain_location_cfg_r11.is_present()) { j.write_fieldname("obtainLocationConfig-r11"); obtain_location_cfg_r11->to_json(j); } @@ -67408,38 +66525,30 @@ void other_cfg_r9_s::to_json(json_writer& j) const if (sps_assist_info_report_r14_present) { j.write_bool("sps-AssistanceInfoReport-r14", sps_assist_info_report_r14); } - rrc_asn1_warn_assert( - delay_budget_report_cfg_r14_present != (delay_budget_report_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (delay_budget_report_cfg_r14_present) { + if (delay_budget_report_cfg_r14.is_present()) { j.write_fieldname("delayBudgetReportingConfig-r14"); delay_budget_report_cfg_r14->to_json(j); } - rrc_asn1_warn_assert(rlm_report_cfg_r14_present != (rlm_report_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (rlm_report_cfg_r14_present) { + if (rlm_report_cfg_r14.is_present()) { j.write_fieldname("rlm-ReportConfig-r14"); rlm_report_cfg_r14->to_json(j); } - rrc_asn1_warn_assert( - overheat_assist_cfg_r14_present != (overheat_assist_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (overheat_assist_cfg_r14_present) { + if (overheat_assist_cfg_r14.is_present()) { j.write_fieldname("overheatingAssistanceConfig-r14"); overheat_assist_cfg_r14->to_json(j); } - rrc_asn1_warn_assert(meas_cfg_app_layer_r15_present != (meas_cfg_app_layer_r15.get() != NULL), __FILE__, __LINE__); - if (meas_cfg_app_layer_r15_present) { + if (meas_cfg_app_layer_r15.is_present()) { j.write_fieldname("measConfigAppLayer-r15"); meas_cfg_app_layer_r15->to_json(j); } if (ailc_bit_cfg_r15_present) { j.write_bool("ailc-BitConfig-r15", ailc_bit_cfg_r15); } - rrc_asn1_warn_assert(bt_name_list_cfg_r15_present != (bt_name_list_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (bt_name_list_cfg_r15_present) { + if (bt_name_list_cfg_r15.is_present()) { j.write_fieldname("bt-NameListConfig-r15"); bt_name_list_cfg_r15->to_json(j); } - rrc_asn1_warn_assert(wlan_name_list_cfg_r15_present != (wlan_name_list_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (wlan_name_list_cfg_r15_present) { + if (wlan_name_list_cfg_r15.is_present()) { j.write_fieldname("wlan-NameListConfig-r15"); wlan_name_list_cfg_r15->to_json(j); } @@ -69567,52 +68676,47 @@ SRSASN_CODE quant_cfg_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); - rrc_asn1_warn_assert(quant_cfg_utra_v1020_present != (quant_cfg_utra_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= quant_cfg_utra_v1020_present; - rrc_asn1_warn_assert(quant_cfg_eutra_v1250_present != (quant_cfg_eutra_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= quant_cfg_eutra_v1250_present; - rrc_asn1_warn_assert(quant_cfg_eutra_v1310_present != (quant_cfg_eutra_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= quant_cfg_eutra_v1310_present; - rrc_asn1_warn_assert(quant_cfg_wlan_r13_present != (quant_cfg_wlan_r13.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= quant_cfg_wlan_r13_present; - rrc_asn1_warn_assert(quant_cfg_nr_list_r15_present != (quant_cfg_nr_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= quant_cfg_nr_list_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= quant_cfg_utra_v1020.is_present(); + group_flags[1] |= quant_cfg_eutra_v1250.is_present(); + group_flags[2] |= quant_cfg_eutra_v1310.is_present(); + group_flags[2] |= quant_cfg_wlan_r13.is_present(); + group_flags[3] |= quant_cfg_nr_list_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(quant_cfg_utra_v1020_present, 1)); - if (quant_cfg_utra_v1020_present) { + HANDLE_CODE(bref.pack(quant_cfg_utra_v1020.is_present(), 1)); + if (quant_cfg_utra_v1020.is_present()) { HANDLE_CODE(quant_cfg_utra_v1020->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(quant_cfg_eutra_v1250_present, 1)); - if (quant_cfg_eutra_v1250_present) { + HANDLE_CODE(bref.pack(quant_cfg_eutra_v1250.is_present(), 1)); + if (quant_cfg_eutra_v1250.is_present()) { HANDLE_CODE(quant_cfg_eutra_v1250->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(quant_cfg_eutra_v1310_present, 1)); - HANDLE_CODE(bref.pack(quant_cfg_wlan_r13_present, 1)); - if (quant_cfg_eutra_v1310_present) { + HANDLE_CODE(bref.pack(quant_cfg_eutra_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(quant_cfg_wlan_r13.is_present(), 1)); + if (quant_cfg_eutra_v1310.is_present()) { HANDLE_CODE(quant_cfg_eutra_v1310->pack(bref)); } - if (quant_cfg_wlan_r13_present) { + if (quant_cfg_wlan_r13.is_present()) { HANDLE_CODE(quant_cfg_wlan_r13->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(quant_cfg_nr_list_r15_present, 1)); - if (quant_cfg_nr_list_r15_present) { + HANDLE_CODE(bref.pack(quant_cfg_nr_list_r15.is_present(), 1)); + if (quant_cfg_nr_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *quant_cfg_nr_list_r15, 1, 2)); } } @@ -69641,47 +68745,52 @@ SRSASN_CODE quant_cfg_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool quant_cfg_utra_v1020_present; HANDLE_CODE(bref.unpack(quant_cfg_utra_v1020_present, 1)); - if (quant_cfg_utra_v1020_present) { - quant_cfg_utra_v1020 = make_copy_ptr(quant_cfg_utra_v1020_s()); + quant_cfg_utra_v1020.set_present(quant_cfg_utra_v1020_present); + if (quant_cfg_utra_v1020.is_present()) { HANDLE_CODE(quant_cfg_utra_v1020->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool quant_cfg_eutra_v1250_present; HANDLE_CODE(bref.unpack(quant_cfg_eutra_v1250_present, 1)); - if (quant_cfg_eutra_v1250_present) { - quant_cfg_eutra_v1250 = make_copy_ptr(quant_cfg_eutra_v1250_s()); + quant_cfg_eutra_v1250.set_present(quant_cfg_eutra_v1250_present); + if (quant_cfg_eutra_v1250.is_present()) { HANDLE_CODE(quant_cfg_eutra_v1250->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool quant_cfg_eutra_v1310_present; HANDLE_CODE(bref.unpack(quant_cfg_eutra_v1310_present, 1)); + quant_cfg_eutra_v1310.set_present(quant_cfg_eutra_v1310_present); + bool quant_cfg_wlan_r13_present; HANDLE_CODE(bref.unpack(quant_cfg_wlan_r13_present, 1)); - if (quant_cfg_eutra_v1310_present) { - quant_cfg_eutra_v1310 = make_copy_ptr(quant_cfg_eutra_v1310_s()); + quant_cfg_wlan_r13.set_present(quant_cfg_wlan_r13_present); + if (quant_cfg_eutra_v1310.is_present()) { HANDLE_CODE(quant_cfg_eutra_v1310->unpack(bref)); } - if (quant_cfg_wlan_r13_present) { - quant_cfg_wlan_r13 = make_copy_ptr(quant_cfg_wlan_r13_s()); + if (quant_cfg_wlan_r13.is_present()) { HANDLE_CODE(quant_cfg_wlan_r13->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool quant_cfg_nr_list_r15_present; HANDLE_CODE(bref.unpack(quant_cfg_nr_list_r15_present, 1)); - if (quant_cfg_nr_list_r15_present) { - quant_cfg_nr_list_r15 = make_copy_ptr(quant_cfg_nr_list_r15_l()); + quant_cfg_nr_list_r15.set_present(quant_cfg_nr_list_r15_present); + if (quant_cfg_nr_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*quant_cfg_nr_list_r15, bref, 1, 2)); } } @@ -69708,28 +68817,23 @@ void quant_cfg_s::to_json(json_writer& j) const quant_cfg_cdma2000.to_json(j); } if (ext) { - rrc_asn1_warn_assert(quant_cfg_utra_v1020_present != (quant_cfg_utra_v1020.get() != NULL), __FILE__, __LINE__); - if (quant_cfg_utra_v1020_present) { + if (quant_cfg_utra_v1020.is_present()) { j.write_fieldname("quantityConfigUTRA-v1020"); quant_cfg_utra_v1020->to_json(j); } - rrc_asn1_warn_assert(quant_cfg_eutra_v1250_present != (quant_cfg_eutra_v1250.get() != NULL), __FILE__, __LINE__); - if (quant_cfg_eutra_v1250_present) { + if (quant_cfg_eutra_v1250.is_present()) { j.write_fieldname("quantityConfigEUTRA-v1250"); quant_cfg_eutra_v1250->to_json(j); } - rrc_asn1_warn_assert(quant_cfg_eutra_v1310_present != (quant_cfg_eutra_v1310.get() != NULL), __FILE__, __LINE__); - if (quant_cfg_eutra_v1310_present) { + if (quant_cfg_eutra_v1310.is_present()) { j.write_fieldname("quantityConfigEUTRA-v1310"); quant_cfg_eutra_v1310->to_json(j); } - rrc_asn1_warn_assert(quant_cfg_wlan_r13_present != (quant_cfg_wlan_r13.get() != NULL), __FILE__, __LINE__); - if (quant_cfg_wlan_r13_present) { + if (quant_cfg_wlan_r13.is_present()) { j.write_fieldname("quantityConfigWLAN-r13"); quant_cfg_wlan_r13->to_json(j); } - rrc_asn1_warn_assert(quant_cfg_nr_list_r15_present != (quant_cfg_nr_list_r15.get() != NULL), __FILE__, __LINE__); - if (quant_cfg_nr_list_r15_present) { + if (quant_cfg_nr_list_r15.is_present()) { j.start_array("quantityConfigNRList-r15"); for (uint32_t i1 = 0; i1 < quant_cfg_nr_list_r15->size(); ++i1) { ((*quant_cfg_nr_list_r15)[i1]).to_json(j); @@ -70212,133 +69316,114 @@ SRSASN_CODE rr_cfg_common_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, ul_cp_len)); if (ext) { - ext_groups_header group_flags(7); - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1020_present != (ul_pwr_ctrl_common_v1020.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= ul_pwr_ctrl_common_v1020_present; - rrc_asn1_warn_assert(tdd_cfg_v1130_present != (tdd_cfg_v1130.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= tdd_cfg_v1130_present; - rrc_asn1_warn_assert(pusch_cfg_common_v1270_present != (pusch_cfg_common_v1270.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= pusch_cfg_common_v1270_present; - rrc_asn1_warn_assert(prach_cfg_v1310_present != (prach_cfg_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= prach_cfg_v1310_present; - rrc_asn1_warn_assert(freq_hop_params_r13_present != (freq_hop_params_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= freq_hop_params_r13_present; - rrc_asn1_warn_assert(pdsch_cfg_common_v1310_present != (pdsch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pdsch_cfg_common_v1310_present; - rrc_asn1_warn_assert(pucch_cfg_common_v1310_present != (pucch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pucch_cfg_common_v1310_present; - rrc_asn1_warn_assert(pusch_cfg_common_v1310_present != (pusch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= pusch_cfg_common_v1310_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1310_present != (ul_pwr_ctrl_common_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= ul_pwr_ctrl_common_v1310_present; - rrc_asn1_warn_assert(high_speed_cfg_r14_present != (high_speed_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= high_speed_cfg_r14_present; - rrc_asn1_warn_assert(prach_cfg_v1430_present != (prach_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= prach_cfg_v1430_present; - rrc_asn1_warn_assert(pucch_cfg_common_v1430_present != (pucch_cfg_common_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= pucch_cfg_common_v1430_present; - rrc_asn1_warn_assert(tdd_cfg_v1430_present != (tdd_cfg_v1430.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= tdd_cfg_v1430_present; - rrc_asn1_warn_assert(tdd_cfg_v1450_present != (tdd_cfg_v1450.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= tdd_cfg_v1450_present; - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1530_present != (ul_pwr_ctrl_common_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= ul_pwr_ctrl_common_v1530_present; - rrc_asn1_warn_assert(high_speed_cfg_v1530_present != (high_speed_cfg_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= high_speed_cfg_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= ul_pwr_ctrl_common_v1020.is_present(); + group_flags[1] |= tdd_cfg_v1130.is_present(); + group_flags[2] |= pusch_cfg_common_v1270.is_present(); + group_flags[3] |= prach_cfg_v1310.is_present(); + group_flags[3] |= freq_hop_params_r13.is_present(); + group_flags[3] |= pdsch_cfg_common_v1310.is_present(); + group_flags[3] |= pucch_cfg_common_v1310.is_present(); + group_flags[3] |= pusch_cfg_common_v1310.is_present(); + group_flags[3] |= ul_pwr_ctrl_common_v1310.is_present(); + group_flags[4] |= high_speed_cfg_r14.is_present(); + group_flags[4] |= prach_cfg_v1430.is_present(); + group_flags[4] |= pucch_cfg_common_v1430.is_present(); + group_flags[4] |= tdd_cfg_v1430.is_present(); + group_flags[5] |= tdd_cfg_v1450.is_present(); + group_flags[6] |= ul_pwr_ctrl_common_v1530.is_present(); + group_flags[6] |= high_speed_cfg_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1020_present, 1)); - if (ul_pwr_ctrl_common_v1020_present) { + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1020.is_present(), 1)); + if (ul_pwr_ctrl_common_v1020.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1020->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(tdd_cfg_v1130_present, 1)); - if (tdd_cfg_v1130_present) { + HANDLE_CODE(bref.pack(tdd_cfg_v1130.is_present(), 1)); + if (tdd_cfg_v1130.is_present()) { HANDLE_CODE(tdd_cfg_v1130->pack(bref)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(pusch_cfg_common_v1270_present, 1)); - if (pusch_cfg_common_v1270_present) { + HANDLE_CODE(bref.pack(pusch_cfg_common_v1270.is_present(), 1)); + if (pusch_cfg_common_v1270.is_present()) { HANDLE_CODE(pusch_cfg_common_v1270->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(prach_cfg_v1310_present, 1)); - HANDLE_CODE(bref.pack(freq_hop_params_r13_present, 1)); - HANDLE_CODE(bref.pack(pdsch_cfg_common_v1310_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_common_v1310_present, 1)); - HANDLE_CODE(bref.pack(pusch_cfg_common_v1310_present, 1)); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1310_present, 1)); - if (prach_cfg_v1310_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(prach_cfg_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(freq_hop_params_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(pdsch_cfg_common_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_common_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(pusch_cfg_common_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1310.is_present(), 1)); + if (prach_cfg_v1310.is_present()) { HANDLE_CODE(prach_cfg_v1310->pack(bref)); } - if (freq_hop_params_r13_present) { + if (freq_hop_params_r13.is_present()) { HANDLE_CODE(freq_hop_params_r13->pack(bref)); } - if (pdsch_cfg_common_v1310_present) { + if (pdsch_cfg_common_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_common_v1310->pack(bref)); } - if (pucch_cfg_common_v1310_present) { + if (pucch_cfg_common_v1310.is_present()) { HANDLE_CODE(pucch_cfg_common_v1310->pack(bref)); } - if (pusch_cfg_common_v1310_present) { + if (pusch_cfg_common_v1310.is_present()) { HANDLE_CODE(pusch_cfg_common_v1310->pack(bref)); } - if (ul_pwr_ctrl_common_v1310_present) { + if (ul_pwr_ctrl_common_v1310.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1310->pack(bref)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(high_speed_cfg_r14_present, 1)); - HANDLE_CODE(bref.pack(prach_cfg_v1430_present, 1)); - HANDLE_CODE(bref.pack(pucch_cfg_common_v1430_present, 1)); - HANDLE_CODE(bref.pack(tdd_cfg_v1430_present, 1)); - if (high_speed_cfg_r14_present) { + HANDLE_CODE(bref.pack(high_speed_cfg_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(prach_cfg_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(pucch_cfg_common_v1430.is_present(), 1)); + HANDLE_CODE(bref.pack(tdd_cfg_v1430.is_present(), 1)); + if (high_speed_cfg_r14.is_present()) { HANDLE_CODE(high_speed_cfg_r14->pack(bref)); } - if (prach_cfg_v1430_present) { + if (prach_cfg_v1430.is_present()) { HANDLE_CODE(prach_cfg_v1430->pack(bref)); } - if (pucch_cfg_common_v1430_present) { + if (pucch_cfg_common_v1430.is_present()) { HANDLE_CODE(pucch_cfg_common_v1430->pack(bref)); } - if (tdd_cfg_v1430_present) { + if (tdd_cfg_v1430.is_present()) { HANDLE_CODE(tdd_cfg_v1430->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(tdd_cfg_v1450_present, 1)); - if (tdd_cfg_v1450_present) { + HANDLE_CODE(bref.pack(tdd_cfg_v1450.is_present(), 1)); + if (tdd_cfg_v1450.is_present()) { HANDLE_CODE(tdd_cfg_v1450->pack(bref)); } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1530_present, 1)); - HANDLE_CODE(bref.pack(high_speed_cfg_v1530_present, 1)); - if (ul_pwr_ctrl_common_v1530_present) { + HANDLE_CODE(bref.pack(ul_pwr_ctrl_common_v1530.is_present(), 1)); + HANDLE_CODE(bref.pack(high_speed_cfg_v1530.is_present(), 1)); + if (ul_pwr_ctrl_common_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1530->pack(bref)); } - if (high_speed_cfg_v1530_present) { + if (high_speed_cfg_v1530.is_present()) { HANDLE_CODE(high_speed_cfg_v1530->pack(bref)); } } @@ -70390,114 +69475,130 @@ SRSASN_CODE rr_cfg_common_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(ul_cp_len, bref)); if (ext) { - ext_groups_header group_flags(7); + ext_groups_unpacker_guard group_flags(7); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_pwr_ctrl_common_v1020_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_v1020_present, 1)); - if (ul_pwr_ctrl_common_v1020_present) { - ul_pwr_ctrl_common_v1020 = make_copy_ptr(ul_pwr_ctrl_common_v1020_s()); + ul_pwr_ctrl_common_v1020.set_present(ul_pwr_ctrl_common_v1020_present); + if (ul_pwr_ctrl_common_v1020.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1020->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool tdd_cfg_v1130_present; HANDLE_CODE(bref.unpack(tdd_cfg_v1130_present, 1)); - if (tdd_cfg_v1130_present) { - tdd_cfg_v1130 = make_copy_ptr(tdd_cfg_v1130_s()); + tdd_cfg_v1130.set_present(tdd_cfg_v1130_present); + if (tdd_cfg_v1130.is_present()) { HANDLE_CODE(tdd_cfg_v1130->unpack(bref)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool pusch_cfg_common_v1270_present; HANDLE_CODE(bref.unpack(pusch_cfg_common_v1270_present, 1)); - if (pusch_cfg_common_v1270_present) { - pusch_cfg_common_v1270 = make_copy_ptr(pusch_cfg_common_v1270_s()); + pusch_cfg_common_v1270.set_present(pusch_cfg_common_v1270_present); + if (pusch_cfg_common_v1270.is_present()) { HANDLE_CODE(pusch_cfg_common_v1270->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool prach_cfg_v1310_present; HANDLE_CODE(bref.unpack(prach_cfg_v1310_present, 1)); + prach_cfg_v1310.set_present(prach_cfg_v1310_present); + bool freq_hop_params_r13_present; HANDLE_CODE(bref.unpack(freq_hop_params_r13_present, 1)); + freq_hop_params_r13.set_present(freq_hop_params_r13_present); + bool pdsch_cfg_common_v1310_present; HANDLE_CODE(bref.unpack(pdsch_cfg_common_v1310_present, 1)); + pdsch_cfg_common_v1310.set_present(pdsch_cfg_common_v1310_present); + bool pucch_cfg_common_v1310_present; HANDLE_CODE(bref.unpack(pucch_cfg_common_v1310_present, 1)); + pucch_cfg_common_v1310.set_present(pucch_cfg_common_v1310_present); + bool pusch_cfg_common_v1310_present; HANDLE_CODE(bref.unpack(pusch_cfg_common_v1310_present, 1)); + pusch_cfg_common_v1310.set_present(pusch_cfg_common_v1310_present); + bool ul_pwr_ctrl_common_v1310_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_v1310_present, 1)); - if (prach_cfg_v1310_present) { - prach_cfg_v1310 = make_copy_ptr(prach_cfg_v1310_s()); + ul_pwr_ctrl_common_v1310.set_present(ul_pwr_ctrl_common_v1310_present); + if (prach_cfg_v1310.is_present()) { HANDLE_CODE(prach_cfg_v1310->unpack(bref)); } - if (freq_hop_params_r13_present) { - freq_hop_params_r13 = make_copy_ptr(freq_hop_params_r13_s()); + if (freq_hop_params_r13.is_present()) { HANDLE_CODE(freq_hop_params_r13->unpack(bref)); } - if (pdsch_cfg_common_v1310_present) { - pdsch_cfg_common_v1310 = make_copy_ptr(pdsch_cfg_common_v1310_s()); + if (pdsch_cfg_common_v1310.is_present()) { HANDLE_CODE(pdsch_cfg_common_v1310->unpack(bref)); } - if (pucch_cfg_common_v1310_present) { - pucch_cfg_common_v1310 = make_copy_ptr(pucch_cfg_common_v1310_s()); + if (pucch_cfg_common_v1310.is_present()) { HANDLE_CODE(pucch_cfg_common_v1310->unpack(bref)); } - if (pusch_cfg_common_v1310_present) { - pusch_cfg_common_v1310 = make_copy_ptr(pusch_cfg_common_v1310_s()); + if (pusch_cfg_common_v1310.is_present()) { HANDLE_CODE(pusch_cfg_common_v1310->unpack(bref)); } - if (ul_pwr_ctrl_common_v1310_present) { - ul_pwr_ctrl_common_v1310 = make_copy_ptr(ul_pwr_ctrl_common_v1310_s()); + if (ul_pwr_ctrl_common_v1310.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1310->unpack(bref)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool high_speed_cfg_r14_present; HANDLE_CODE(bref.unpack(high_speed_cfg_r14_present, 1)); + high_speed_cfg_r14.set_present(high_speed_cfg_r14_present); + bool prach_cfg_v1430_present; HANDLE_CODE(bref.unpack(prach_cfg_v1430_present, 1)); + prach_cfg_v1430.set_present(prach_cfg_v1430_present); + bool pucch_cfg_common_v1430_present; HANDLE_CODE(bref.unpack(pucch_cfg_common_v1430_present, 1)); + pucch_cfg_common_v1430.set_present(pucch_cfg_common_v1430_present); + bool tdd_cfg_v1430_present; HANDLE_CODE(bref.unpack(tdd_cfg_v1430_present, 1)); - if (high_speed_cfg_r14_present) { - high_speed_cfg_r14 = make_copy_ptr(high_speed_cfg_r14_s()); + tdd_cfg_v1430.set_present(tdd_cfg_v1430_present); + if (high_speed_cfg_r14.is_present()) { HANDLE_CODE(high_speed_cfg_r14->unpack(bref)); } - if (prach_cfg_v1430_present) { - prach_cfg_v1430 = make_copy_ptr(prach_cfg_v1430_s()); + if (prach_cfg_v1430.is_present()) { HANDLE_CODE(prach_cfg_v1430->unpack(bref)); } - if (pucch_cfg_common_v1430_present) { - pucch_cfg_common_v1430 = make_copy_ptr(pucch_cfg_common_v1430_s()); + if (pucch_cfg_common_v1430.is_present()) { HANDLE_CODE(pucch_cfg_common_v1430->unpack(bref)); } - if (tdd_cfg_v1430_present) { - tdd_cfg_v1430 = make_copy_ptr(tdd_cfg_v1430_s()); + if (tdd_cfg_v1430.is_present()) { HANDLE_CODE(tdd_cfg_v1430->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool tdd_cfg_v1450_present; HANDLE_CODE(bref.unpack(tdd_cfg_v1450_present, 1)); - if (tdd_cfg_v1450_present) { - tdd_cfg_v1450 = make_copy_ptr(tdd_cfg_v1450_s()); + tdd_cfg_v1450.set_present(tdd_cfg_v1450_present); + if (tdd_cfg_v1450.is_present()) { HANDLE_CODE(tdd_cfg_v1450->unpack(bref)); } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool ul_pwr_ctrl_common_v1530_present; HANDLE_CODE(bref.unpack(ul_pwr_ctrl_common_v1530_present, 1)); + ul_pwr_ctrl_common_v1530.set_present(ul_pwr_ctrl_common_v1530_present); + bool high_speed_cfg_v1530_present; HANDLE_CODE(bref.unpack(high_speed_cfg_v1530_present, 1)); - if (ul_pwr_ctrl_common_v1530_present) { - ul_pwr_ctrl_common_v1530 = make_copy_ptr(ul_pwr_ctrl_common_v1530_s()); + high_speed_cfg_v1530.set_present(high_speed_cfg_v1530_present); + if (ul_pwr_ctrl_common_v1530.is_present()) { HANDLE_CODE(ul_pwr_ctrl_common_v1530->unpack(bref)); } - if (high_speed_cfg_v1530_present) { - high_speed_cfg_v1530 = make_copy_ptr(high_speed_cfg_v1530_s()); + if (high_speed_cfg_v1530.is_present()) { HANDLE_CODE(high_speed_cfg_v1530->unpack(bref)); } } @@ -70548,86 +69649,67 @@ void rr_cfg_common_s::to_json(json_writer& j) const } j.write_str("ul-CyclicPrefixLength", ul_cp_len.to_string()); if (ext) { - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1020_present != (ul_pwr_ctrl_common_v1020.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_common_v1020_present) { + if (ul_pwr_ctrl_common_v1020.is_present()) { j.write_fieldname("uplinkPowerControlCommon-v1020"); ul_pwr_ctrl_common_v1020->to_json(j); } - rrc_asn1_warn_assert(tdd_cfg_v1130_present != (tdd_cfg_v1130.get() != NULL), __FILE__, __LINE__); - if (tdd_cfg_v1130_present) { + if (tdd_cfg_v1130.is_present()) { j.write_fieldname("tdd-Config-v1130"); tdd_cfg_v1130->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_common_v1270_present != (pusch_cfg_common_v1270.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_common_v1270_present) { + if (pusch_cfg_common_v1270.is_present()) { j.write_fieldname("pusch-ConfigCommon-v1270"); pusch_cfg_common_v1270->to_json(j); } - rrc_asn1_warn_assert(prach_cfg_v1310_present != (prach_cfg_v1310.get() != NULL), __FILE__, __LINE__); - if (prach_cfg_v1310_present) { + if (prach_cfg_v1310.is_present()) { j.write_fieldname("prach-Config-v1310"); prach_cfg_v1310->to_json(j); } - rrc_asn1_warn_assert(freq_hop_params_r13_present != (freq_hop_params_r13.get() != NULL), __FILE__, __LINE__); - if (freq_hop_params_r13_present) { + if (freq_hop_params_r13.is_present()) { j.write_fieldname("freqHoppingParameters-r13"); freq_hop_params_r13->to_json(j); } - rrc_asn1_warn_assert(pdsch_cfg_common_v1310_present != (pdsch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - if (pdsch_cfg_common_v1310_present) { + if (pdsch_cfg_common_v1310.is_present()) { j.write_fieldname("pdsch-ConfigCommon-v1310"); pdsch_cfg_common_v1310->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_common_v1310_present != (pucch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_common_v1310_present) { + if (pucch_cfg_common_v1310.is_present()) { j.write_fieldname("pucch-ConfigCommon-v1310"); pucch_cfg_common_v1310->to_json(j); } - rrc_asn1_warn_assert(pusch_cfg_common_v1310_present != (pusch_cfg_common_v1310.get() != NULL), __FILE__, __LINE__); - if (pusch_cfg_common_v1310_present) { + if (pusch_cfg_common_v1310.is_present()) { j.write_fieldname("pusch-ConfigCommon-v1310"); pusch_cfg_common_v1310->to_json(j); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1310_present != (ul_pwr_ctrl_common_v1310.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_common_v1310_present) { + if (ul_pwr_ctrl_common_v1310.is_present()) { j.write_fieldname("uplinkPowerControlCommon-v1310"); ul_pwr_ctrl_common_v1310->to_json(j); } - rrc_asn1_warn_assert(high_speed_cfg_r14_present != (high_speed_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (high_speed_cfg_r14_present) { + if (high_speed_cfg_r14.is_present()) { j.write_fieldname("highSpeedConfig-r14"); high_speed_cfg_r14->to_json(j); } - rrc_asn1_warn_assert(prach_cfg_v1430_present != (prach_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (prach_cfg_v1430_present) { + if (prach_cfg_v1430.is_present()) { j.write_fieldname("prach-Config-v1430"); prach_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert(pucch_cfg_common_v1430_present != (pucch_cfg_common_v1430.get() != NULL), __FILE__, __LINE__); - if (pucch_cfg_common_v1430_present) { + if (pucch_cfg_common_v1430.is_present()) { j.write_fieldname("pucch-ConfigCommon-v1430"); pucch_cfg_common_v1430->to_json(j); } - rrc_asn1_warn_assert(tdd_cfg_v1430_present != (tdd_cfg_v1430.get() != NULL), __FILE__, __LINE__); - if (tdd_cfg_v1430_present) { + if (tdd_cfg_v1430.is_present()) { j.write_fieldname("tdd-Config-v1430"); tdd_cfg_v1430->to_json(j); } - rrc_asn1_warn_assert(tdd_cfg_v1450_present != (tdd_cfg_v1450.get() != NULL), __FILE__, __LINE__); - if (tdd_cfg_v1450_present) { + if (tdd_cfg_v1450.is_present()) { j.write_fieldname("tdd-Config-v1450"); tdd_cfg_v1450->to_json(j); } - rrc_asn1_warn_assert( - ul_pwr_ctrl_common_v1530_present != (ul_pwr_ctrl_common_v1530.get() != NULL), __FILE__, __LINE__); - if (ul_pwr_ctrl_common_v1530_present) { + if (ul_pwr_ctrl_common_v1530.is_present()) { j.write_fieldname("uplinkPowerControlCommon-v1530"); ul_pwr_ctrl_common_v1530->to_json(j); } - rrc_asn1_warn_assert(high_speed_cfg_v1530_present != (high_speed_cfg_v1530.get() != NULL), __FILE__, __LINE__); - if (high_speed_cfg_v1530_present) { + if (high_speed_cfg_v1530.is_present()) { j.write_fieldname("highSpeedConfig-v1530"); high_speed_cfg_v1530->to_json(j); } @@ -71411,59 +70493,35 @@ SRSASN_CODE meas_cfg_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(7); - rrc_asn1_warn_assert( - meas_obj_to_add_mod_list_v9e0_present != (meas_obj_to_add_mod_list_v9e0.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= meas_obj_to_add_mod_list_v9e0_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= meas_obj_to_add_mod_list_v9e0.is_present(); group_flags[1] |= allow_interruptions_r11_present; - rrc_asn1_warn_assert(meas_scale_factor_r12_present != (meas_scale_factor_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= meas_scale_factor_r12_present; - rrc_asn1_warn_assert( - meas_id_to_rem_list_ext_r12_present != (meas_id_to_rem_list_ext_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= meas_id_to_rem_list_ext_r12_present; - rrc_asn1_warn_assert( - meas_id_to_add_mod_list_ext_r12_present != (meas_id_to_add_mod_list_ext_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= meas_id_to_add_mod_list_ext_r12_present; + group_flags[2] |= meas_scale_factor_r12.is_present(); + group_flags[2] |= meas_id_to_rem_list_ext_r12.is_present(); + group_flags[2] |= meas_id_to_add_mod_list_ext_r12.is_present(); group_flags[2] |= meas_rsrq_on_all_symbols_r12_present; - rrc_asn1_warn_assert( - meas_obj_to_rem_list_ext_r13_present != (meas_obj_to_rem_list_ext_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_obj_to_rem_list_ext_r13_present; - rrc_asn1_warn_assert(meas_obj_to_add_mod_list_ext_r13_present != (meas_obj_to_add_mod_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= meas_obj_to_add_mod_list_ext_r13_present; - rrc_asn1_warn_assert( - meas_id_to_add_mod_list_v1310_present != (meas_id_to_add_mod_list_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_id_to_add_mod_list_v1310_present; - rrc_asn1_warn_assert(meas_id_to_add_mod_list_ext_v1310_present != (meas_id_to_add_mod_list_ext_v1310.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= meas_id_to_add_mod_list_ext_v1310_present; - rrc_asn1_warn_assert( - meas_gap_cfg_per_cc_list_r14_present != (meas_gap_cfg_per_cc_list_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= meas_gap_cfg_per_cc_list_r14_present; - rrc_asn1_warn_assert( - meas_gap_sharing_cfg_r14_present != (meas_gap_sharing_cfg_r14.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= meas_gap_sharing_cfg_r14_present; + group_flags[3] |= meas_obj_to_rem_list_ext_r13.is_present(); + group_flags[3] |= meas_obj_to_add_mod_list_ext_r13.is_present(); + group_flags[3] |= meas_id_to_add_mod_list_v1310.is_present(); + group_flags[3] |= meas_id_to_add_mod_list_ext_v1310.is_present(); + group_flags[4] |= meas_gap_cfg_per_cc_list_r14.is_present(); + group_flags[4] |= meas_gap_sharing_cfg_r14.is_present(); group_flags[5] |= fr1_gap_r15_present; group_flags[5] |= mgta_r15_present; - rrc_asn1_warn_assert( - meas_gap_cfg_dense_prs_r15_present != (meas_gap_cfg_dense_prs_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= meas_gap_cfg_dense_prs_r15_present; - rrc_asn1_warn_assert(height_thresh_ref_r15_present != (height_thresh_ref_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= height_thresh_ref_r15_present; + group_flags[6] |= meas_gap_cfg_dense_prs_r15.is_present(); + group_flags[6] |= height_thresh_ref_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_obj_to_add_mod_list_v9e0_present, 1)); - if (meas_obj_to_add_mod_list_v9e0_present) { + HANDLE_CODE(bref.pack(meas_obj_to_add_mod_list_v9e0.is_present(), 1)); + if (meas_obj_to_add_mod_list_v9e0.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_obj_to_add_mod_list_v9e0, 1, 32)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(allow_interruptions_r11_present, 1)); if (allow_interruptions_r11_present) { @@ -71471,20 +70529,20 @@ SRSASN_CODE meas_cfg_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_scale_factor_r12_present, 1)); - HANDLE_CODE(bref.pack(meas_id_to_rem_list_ext_r12_present, 1)); - HANDLE_CODE(bref.pack(meas_id_to_add_mod_list_ext_r12_present, 1)); + HANDLE_CODE(bref.pack(meas_scale_factor_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_id_to_rem_list_ext_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_id_to_add_mod_list_ext_r12.is_present(), 1)); HANDLE_CODE(bref.pack(meas_rsrq_on_all_symbols_r12_present, 1)); - if (meas_scale_factor_r12_present) { + if (meas_scale_factor_r12.is_present()) { HANDLE_CODE(meas_scale_factor_r12->pack(bref)); } - if (meas_id_to_rem_list_ext_r12_present) { + if (meas_id_to_rem_list_ext_r12.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *meas_id_to_rem_list_ext_r12, 1, 32, UnalignedIntegerPacker(33, 64))); } - if (meas_id_to_add_mod_list_ext_r12_present) { + if (meas_id_to_add_mod_list_ext_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_id_to_add_mod_list_ext_r12, 1, 32)); } if (meas_rsrq_on_all_symbols_r12_present) { @@ -71492,40 +70550,40 @@ SRSASN_CODE meas_cfg_s::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_obj_to_rem_list_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_obj_to_add_mod_list_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_id_to_add_mod_list_v1310_present, 1)); - HANDLE_CODE(bref.pack(meas_id_to_add_mod_list_ext_v1310_present, 1)); - if (meas_obj_to_rem_list_ext_r13_present) { + HANDLE_CODE(bref.pack(meas_obj_to_rem_list_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_obj_to_add_mod_list_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_id_to_add_mod_list_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_id_to_add_mod_list_ext_v1310.is_present(), 1)); + if (meas_obj_to_rem_list_ext_r13.is_present()) { HANDLE_CODE( pack_dyn_seq_of(bref, *meas_obj_to_rem_list_ext_r13, 1, 32, UnalignedIntegerPacker(33, 64))); } - if (meas_obj_to_add_mod_list_ext_r13_present) { + if (meas_obj_to_add_mod_list_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_obj_to_add_mod_list_ext_r13, 1, 32)); } - if (meas_id_to_add_mod_list_v1310_present) { + if (meas_id_to_add_mod_list_v1310.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_id_to_add_mod_list_v1310, 1, 32)); } - if (meas_id_to_add_mod_list_ext_v1310_present) { + if (meas_id_to_add_mod_list_ext_v1310.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_id_to_add_mod_list_ext_v1310, 1, 32)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_gap_cfg_per_cc_list_r14_present, 1)); - HANDLE_CODE(bref.pack(meas_gap_sharing_cfg_r14_present, 1)); - if (meas_gap_cfg_per_cc_list_r14_present) { + HANDLE_CODE(bref.pack(meas_gap_cfg_per_cc_list_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_gap_sharing_cfg_r14.is_present(), 1)); + if (meas_gap_cfg_per_cc_list_r14.is_present()) { HANDLE_CODE(meas_gap_cfg_per_cc_list_r14->pack(bref)); } - if (meas_gap_sharing_cfg_r14_present) { + if (meas_gap_sharing_cfg_r14.is_present()) { HANDLE_CODE(meas_gap_sharing_cfg_r14->pack(bref)); } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(fr1_gap_r15_present, 1)); HANDLE_CODE(bref.pack(mgta_r15_present, 1)); @@ -71537,14 +70595,14 @@ SRSASN_CODE meas_cfg_s::pack(bit_ref& bref) const } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_gap_cfg_dense_prs_r15_present, 1)); - HANDLE_CODE(bref.pack(height_thresh_ref_r15_present, 1)); - if (meas_gap_cfg_dense_prs_r15_present) { + HANDLE_CODE(bref.pack(meas_gap_cfg_dense_prs_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(height_thresh_ref_r15.is_present(), 1)); + if (meas_gap_cfg_dense_prs_r15.is_present()) { HANDLE_CODE(meas_gap_cfg_dense_prs_r15->pack(bref)); } - if (height_thresh_ref_r15_present) { + if (height_thresh_ref_r15.is_present()) { HANDLE_CODE(height_thresh_ref_r15->pack(bref)); } } @@ -71601,20 +70659,21 @@ SRSASN_CODE meas_cfg_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(7); + ext_groups_unpacker_guard group_flags(7); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_obj_to_add_mod_list_v9e0_present; HANDLE_CODE(bref.unpack(meas_obj_to_add_mod_list_v9e0_present, 1)); - if (meas_obj_to_add_mod_list_v9e0_present) { - meas_obj_to_add_mod_list_v9e0 = make_copy_ptr(meas_obj_to_add_mod_list_v9e0_l()); + meas_obj_to_add_mod_list_v9e0.set_present(meas_obj_to_add_mod_list_v9e0_present); + if (meas_obj_to_add_mod_list_v9e0.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_obj_to_add_mod_list_v9e0, bref, 1, 32)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(allow_interruptions_r11_present, 1)); if (allow_interruptions_r11_present) { @@ -71622,23 +70681,26 @@ SRSASN_CODE meas_cfg_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_scale_factor_r12_present; HANDLE_CODE(bref.unpack(meas_scale_factor_r12_present, 1)); + meas_scale_factor_r12.set_present(meas_scale_factor_r12_present); + bool meas_id_to_rem_list_ext_r12_present; HANDLE_CODE(bref.unpack(meas_id_to_rem_list_ext_r12_present, 1)); + meas_id_to_rem_list_ext_r12.set_present(meas_id_to_rem_list_ext_r12_present); + bool meas_id_to_add_mod_list_ext_r12_present; HANDLE_CODE(bref.unpack(meas_id_to_add_mod_list_ext_r12_present, 1)); + meas_id_to_add_mod_list_ext_r12.set_present(meas_id_to_add_mod_list_ext_r12_present); HANDLE_CODE(bref.unpack(meas_rsrq_on_all_symbols_r12_present, 1)); - if (meas_scale_factor_r12_present) { - meas_scale_factor_r12 = make_copy_ptr(meas_scale_factor_r12_c_()); + if (meas_scale_factor_r12.is_present()) { HANDLE_CODE(meas_scale_factor_r12->unpack(bref)); } - if (meas_id_to_rem_list_ext_r12_present) { - meas_id_to_rem_list_ext_r12 = make_copy_ptr(meas_id_to_rem_list_ext_r12_l()); + if (meas_id_to_rem_list_ext_r12.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*meas_id_to_rem_list_ext_r12, bref, 1, 32, UnalignedIntegerPacker(33, 64))); } - if (meas_id_to_add_mod_list_ext_r12_present) { - meas_id_to_add_mod_list_ext_r12 = make_copy_ptr(meas_id_to_add_mod_list_ext_r12_l()); + if (meas_id_to_add_mod_list_ext_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_id_to_add_mod_list_ext_r12, bref, 1, 32)); } if (meas_rsrq_on_all_symbols_r12_present) { @@ -71646,46 +70708,52 @@ SRSASN_CODE meas_cfg_s::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_obj_to_rem_list_ext_r13_present; HANDLE_CODE(bref.unpack(meas_obj_to_rem_list_ext_r13_present, 1)); + meas_obj_to_rem_list_ext_r13.set_present(meas_obj_to_rem_list_ext_r13_present); + bool meas_obj_to_add_mod_list_ext_r13_present; HANDLE_CODE(bref.unpack(meas_obj_to_add_mod_list_ext_r13_present, 1)); + meas_obj_to_add_mod_list_ext_r13.set_present(meas_obj_to_add_mod_list_ext_r13_present); + bool meas_id_to_add_mod_list_v1310_present; HANDLE_CODE(bref.unpack(meas_id_to_add_mod_list_v1310_present, 1)); + meas_id_to_add_mod_list_v1310.set_present(meas_id_to_add_mod_list_v1310_present); + bool meas_id_to_add_mod_list_ext_v1310_present; HANDLE_CODE(bref.unpack(meas_id_to_add_mod_list_ext_v1310_present, 1)); - if (meas_obj_to_rem_list_ext_r13_present) { - meas_obj_to_rem_list_ext_r13 = make_copy_ptr(meas_obj_to_rem_list_ext_r13_l()); + meas_id_to_add_mod_list_ext_v1310.set_present(meas_id_to_add_mod_list_ext_v1310_present); + if (meas_obj_to_rem_list_ext_r13.is_present()) { HANDLE_CODE( unpack_dyn_seq_of(*meas_obj_to_rem_list_ext_r13, bref, 1, 32, UnalignedIntegerPacker(33, 64))); } - if (meas_obj_to_add_mod_list_ext_r13_present) { - meas_obj_to_add_mod_list_ext_r13 = make_copy_ptr(meas_obj_to_add_mod_list_ext_r13_l()); + if (meas_obj_to_add_mod_list_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_obj_to_add_mod_list_ext_r13, bref, 1, 32)); } - if (meas_id_to_add_mod_list_v1310_present) { - meas_id_to_add_mod_list_v1310 = make_copy_ptr(meas_id_to_add_mod_list_v1310_l()); + if (meas_id_to_add_mod_list_v1310.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_id_to_add_mod_list_v1310, bref, 1, 32)); } - if (meas_id_to_add_mod_list_ext_v1310_present) { - meas_id_to_add_mod_list_ext_v1310 = make_copy_ptr(meas_id_to_add_mod_list_ext_v1310_l()); + if (meas_id_to_add_mod_list_ext_v1310.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_id_to_add_mod_list_ext_v1310, bref, 1, 32)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_gap_cfg_per_cc_list_r14_present; HANDLE_CODE(bref.unpack(meas_gap_cfg_per_cc_list_r14_present, 1)); + meas_gap_cfg_per_cc_list_r14.set_present(meas_gap_cfg_per_cc_list_r14_present); + bool meas_gap_sharing_cfg_r14_present; HANDLE_CODE(bref.unpack(meas_gap_sharing_cfg_r14_present, 1)); - if (meas_gap_cfg_per_cc_list_r14_present) { - meas_gap_cfg_per_cc_list_r14 = make_copy_ptr(meas_gap_cfg_per_cc_list_r14_c()); + meas_gap_sharing_cfg_r14.set_present(meas_gap_sharing_cfg_r14_present); + if (meas_gap_cfg_per_cc_list_r14.is_present()) { HANDLE_CODE(meas_gap_cfg_per_cc_list_r14->unpack(bref)); } - if (meas_gap_sharing_cfg_r14_present) { - meas_gap_sharing_cfg_r14 = make_copy_ptr(meas_gap_sharing_cfg_r14_c()); + if (meas_gap_sharing_cfg_r14.is_present()) { HANDLE_CODE(meas_gap_sharing_cfg_r14->unpack(bref)); } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(fr1_gap_r15_present, 1)); HANDLE_CODE(bref.unpack(mgta_r15_present, 1)); @@ -71697,16 +70765,18 @@ SRSASN_CODE meas_cfg_s::unpack(bit_ref& bref) } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_gap_cfg_dense_prs_r15_present; HANDLE_CODE(bref.unpack(meas_gap_cfg_dense_prs_r15_present, 1)); + meas_gap_cfg_dense_prs_r15.set_present(meas_gap_cfg_dense_prs_r15_present); + bool height_thresh_ref_r15_present; HANDLE_CODE(bref.unpack(height_thresh_ref_r15_present, 1)); - if (meas_gap_cfg_dense_prs_r15_present) { - meas_gap_cfg_dense_prs_r15 = make_copy_ptr(meas_gap_cfg_dense_prs_r15_c()); + height_thresh_ref_r15.set_present(height_thresh_ref_r15_present); + if (meas_gap_cfg_dense_prs_r15.is_present()) { HANDLE_CODE(meas_gap_cfg_dense_prs_r15->unpack(bref)); } - if (height_thresh_ref_r15_present) { - height_thresh_ref_r15 = make_copy_ptr(height_thresh_ref_r15_c_()); + if (height_thresh_ref_r15.is_present()) { HANDLE_CODE(height_thresh_ref_r15->unpack(bref)); } } @@ -71778,9 +70848,7 @@ void meas_cfg_s::to_json(json_writer& j) const speed_state_pars.to_json(j); } if (ext) { - rrc_asn1_warn_assert( - meas_obj_to_add_mod_list_v9e0_present != (meas_obj_to_add_mod_list_v9e0.get() != NULL), __FILE__, __LINE__); - if (meas_obj_to_add_mod_list_v9e0_present) { + if (meas_obj_to_add_mod_list_v9e0.is_present()) { j.start_array("measObjectToAddModList-v9e0"); for (uint32_t i1 = 0; i1 < meas_obj_to_add_mod_list_v9e0->size(); ++i1) { ((*meas_obj_to_add_mod_list_v9e0)[i1]).to_json(j); @@ -71790,23 +70858,18 @@ void meas_cfg_s::to_json(json_writer& j) const if (allow_interruptions_r11_present) { j.write_bool("allowInterruptions-r11", allow_interruptions_r11); } - rrc_asn1_warn_assert(meas_scale_factor_r12_present != (meas_scale_factor_r12.get() != NULL), __FILE__, __LINE__); - if (meas_scale_factor_r12_present) { + if (meas_scale_factor_r12.is_present()) { j.write_fieldname("measScaleFactor-r12"); meas_scale_factor_r12->to_json(j); } - rrc_asn1_warn_assert( - meas_id_to_rem_list_ext_r12_present != (meas_id_to_rem_list_ext_r12.get() != NULL), __FILE__, __LINE__); - if (meas_id_to_rem_list_ext_r12_present) { + if (meas_id_to_rem_list_ext_r12.is_present()) { j.start_array("measIdToRemoveListExt-r12"); for (uint32_t i1 = 0; i1 < meas_id_to_rem_list_ext_r12->size(); ++i1) { j.write_int(((*meas_id_to_rem_list_ext_r12)[i1])); } j.end_array(); } - rrc_asn1_warn_assert( - meas_id_to_add_mod_list_ext_r12_present != (meas_id_to_add_mod_list_ext_r12.get() != NULL), __FILE__, __LINE__); - if (meas_id_to_add_mod_list_ext_r12_present) { + if (meas_id_to_add_mod_list_ext_r12.is_present()) { j.start_array("measIdToAddModListExt-r12"); for (uint32_t i1 = 0; i1 < meas_id_to_add_mod_list_ext_r12->size(); ++i1) { ((*meas_id_to_add_mod_list_ext_r12)[i1]).to_json(j); @@ -71816,53 +70879,39 @@ void meas_cfg_s::to_json(json_writer& j) const if (meas_rsrq_on_all_symbols_r12_present) { j.write_bool("measRSRQ-OnAllSymbols-r12", meas_rsrq_on_all_symbols_r12); } - rrc_asn1_warn_assert( - meas_obj_to_rem_list_ext_r13_present != (meas_obj_to_rem_list_ext_r13.get() != NULL), __FILE__, __LINE__); - if (meas_obj_to_rem_list_ext_r13_present) { + if (meas_obj_to_rem_list_ext_r13.is_present()) { j.start_array("measObjectToRemoveListExt-r13"); for (uint32_t i1 = 0; i1 < meas_obj_to_rem_list_ext_r13->size(); ++i1) { j.write_int(((*meas_obj_to_rem_list_ext_r13)[i1])); } j.end_array(); } - rrc_asn1_warn_assert(meas_obj_to_add_mod_list_ext_r13_present != (meas_obj_to_add_mod_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (meas_obj_to_add_mod_list_ext_r13_present) { + if (meas_obj_to_add_mod_list_ext_r13.is_present()) { j.start_array("measObjectToAddModListExt-r13"); for (uint32_t i1 = 0; i1 < meas_obj_to_add_mod_list_ext_r13->size(); ++i1) { ((*meas_obj_to_add_mod_list_ext_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_id_to_add_mod_list_v1310_present != (meas_id_to_add_mod_list_v1310.get() != NULL), __FILE__, __LINE__); - if (meas_id_to_add_mod_list_v1310_present) { + if (meas_id_to_add_mod_list_v1310.is_present()) { j.start_array("measIdToAddModList-v1310"); for (uint32_t i1 = 0; i1 < meas_id_to_add_mod_list_v1310->size(); ++i1) { ((*meas_id_to_add_mod_list_v1310)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(meas_id_to_add_mod_list_ext_v1310_present != (meas_id_to_add_mod_list_ext_v1310.get() != NULL), - __FILE__, - __LINE__); - if (meas_id_to_add_mod_list_ext_v1310_present) { + if (meas_id_to_add_mod_list_ext_v1310.is_present()) { j.start_array("measIdToAddModListExt-v1310"); for (uint32_t i1 = 0; i1 < meas_id_to_add_mod_list_ext_v1310->size(); ++i1) { ((*meas_id_to_add_mod_list_ext_v1310)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_gap_cfg_per_cc_list_r14_present != (meas_gap_cfg_per_cc_list_r14.get() != NULL), __FILE__, __LINE__); - if (meas_gap_cfg_per_cc_list_r14_present) { + if (meas_gap_cfg_per_cc_list_r14.is_present()) { j.write_fieldname("measGapConfigPerCC-List-r14"); meas_gap_cfg_per_cc_list_r14->to_json(j); } - rrc_asn1_warn_assert( - meas_gap_sharing_cfg_r14_present != (meas_gap_sharing_cfg_r14.get() != NULL), __FILE__, __LINE__); - if (meas_gap_sharing_cfg_r14_present) { + if (meas_gap_sharing_cfg_r14.is_present()) { j.write_fieldname("measGapSharingConfig-r14"); meas_gap_sharing_cfg_r14->to_json(j); } @@ -71872,14 +70921,11 @@ void meas_cfg_s::to_json(json_writer& j) const if (mgta_r15_present) { j.write_bool("mgta-r15", mgta_r15); } - rrc_asn1_warn_assert( - meas_gap_cfg_dense_prs_r15_present != (meas_gap_cfg_dense_prs_r15.get() != NULL), __FILE__, __LINE__); - if (meas_gap_cfg_dense_prs_r15_present) { + if (meas_gap_cfg_dense_prs_r15.is_present()) { j.write_fieldname("measGapConfigDensePRS-r15"); meas_gap_cfg_dense_prs_r15->to_json(j); } - rrc_asn1_warn_assert(height_thresh_ref_r15_present != (height_thresh_ref_r15.get() != NULL), __FILE__, __LINE__); - if (height_thresh_ref_r15_present) { + if (height_thresh_ref_r15.is_present()) { j.write_fieldname("heightThreshRef-r15"); height_thresh_ref_r15->to_json(j); } @@ -72075,54 +71121,51 @@ SRSASN_CODE mob_ctrl_info_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(4); - rrc_asn1_warn_assert(carrier_freq_v9e0_present != (carrier_freq_v9e0.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= carrier_freq_v9e0_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= carrier_freq_v9e0.is_present(); group_flags[1] |= drb_continue_rohc_r11_present; - rrc_asn1_warn_assert(mob_ctrl_info_v2x_r14_present != (mob_ctrl_info_v2x_r14.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= mob_ctrl_info_v2x_r14_present; + group_flags[2] |= mob_ctrl_info_v2x_r14.is_present(); group_flags[2] |= ho_without_wt_change_r14_present; group_flags[2] |= make_before_break_r14_present; - rrc_asn1_warn_assert(rach_skip_r14_present != (rach_skip_r14.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= rach_skip_r14_present; + group_flags[2] |= rach_skip_r14.is_present(); group_flags[2] |= same_sfn_ind_r14_present; group_flags[3] |= mib_repeat_status_r14_present; group_flags[3] |= sched_info_sib1_br_r14_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(carrier_freq_v9e0_present, 1)); - if (carrier_freq_v9e0_present) { + HANDLE_CODE(bref.pack(carrier_freq_v9e0.is_present(), 1)); + if (carrier_freq_v9e0.is_present()) { HANDLE_CODE(carrier_freq_v9e0->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(drb_continue_rohc_r11_present, 1)); } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(mob_ctrl_info_v2x_r14_present, 1)); + HANDLE_CODE(bref.pack(mob_ctrl_info_v2x_r14.is_present(), 1)); HANDLE_CODE(bref.pack(ho_without_wt_change_r14_present, 1)); HANDLE_CODE(bref.pack(make_before_break_r14_present, 1)); - HANDLE_CODE(bref.pack(rach_skip_r14_present, 1)); + HANDLE_CODE(bref.pack(rach_skip_r14.is_present(), 1)); HANDLE_CODE(bref.pack(same_sfn_ind_r14_present, 1)); - if (mob_ctrl_info_v2x_r14_present) { + if (mob_ctrl_info_v2x_r14.is_present()) { HANDLE_CODE(mob_ctrl_info_v2x_r14->pack(bref)); } if (ho_without_wt_change_r14_present) { HANDLE_CODE(pack_enum(bref, ho_without_wt_change_r14)); } - if (rach_skip_r14_present) { + if (rach_skip_r14.is_present()) { HANDLE_CODE(rach_skip_r14->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(mib_repeat_status_r14_present, 1)); HANDLE_CODE(bref.pack(sched_info_sib1_br_r14_present, 1)); @@ -72162,45 +71205,48 @@ SRSASN_CODE mob_ctrl_info_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool carrier_freq_v9e0_present; HANDLE_CODE(bref.unpack(carrier_freq_v9e0_present, 1)); - if (carrier_freq_v9e0_present) { - carrier_freq_v9e0 = make_copy_ptr(carrier_freq_eutra_v9e0_s()); + carrier_freq_v9e0.set_present(carrier_freq_v9e0_present); + if (carrier_freq_v9e0.is_present()) { HANDLE_CODE(carrier_freq_v9e0->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(drb_continue_rohc_r11_present, 1)); } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool mob_ctrl_info_v2x_r14_present; HANDLE_CODE(bref.unpack(mob_ctrl_info_v2x_r14_present, 1)); + mob_ctrl_info_v2x_r14.set_present(mob_ctrl_info_v2x_r14_present); HANDLE_CODE(bref.unpack(ho_without_wt_change_r14_present, 1)); HANDLE_CODE(bref.unpack(make_before_break_r14_present, 1)); + bool rach_skip_r14_present; HANDLE_CODE(bref.unpack(rach_skip_r14_present, 1)); + rach_skip_r14.set_present(rach_skip_r14_present); HANDLE_CODE(bref.unpack(same_sfn_ind_r14_present, 1)); - if (mob_ctrl_info_v2x_r14_present) { - mob_ctrl_info_v2x_r14 = make_copy_ptr(mob_ctrl_info_v2x_r14_s()); + if (mob_ctrl_info_v2x_r14.is_present()) { HANDLE_CODE(mob_ctrl_info_v2x_r14->unpack(bref)); } if (ho_without_wt_change_r14_present) { HANDLE_CODE(unpack_enum(ho_without_wt_change_r14, bref)); } - if (rach_skip_r14_present) { - rach_skip_r14 = make_copy_ptr(rach_skip_r14_s()); + if (rach_skip_r14.is_present()) { HANDLE_CODE(rach_skip_r14->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(mib_repeat_status_r14_present, 1)); HANDLE_CODE(bref.unpack(sched_info_sib1_br_r14_present, 1)); @@ -72238,16 +71284,14 @@ void mob_ctrl_info_s::to_json(json_writer& j) const rach_cfg_ded.to_json(j); } if (ext) { - rrc_asn1_warn_assert(carrier_freq_v9e0_present != (carrier_freq_v9e0.get() != NULL), __FILE__, __LINE__); - if (carrier_freq_v9e0_present) { + if (carrier_freq_v9e0.is_present()) { j.write_fieldname("carrierFreq-v9e0"); carrier_freq_v9e0->to_json(j); } if (drb_continue_rohc_r11_present) { j.write_str("drb-ContinueROHC-r11", "true"); } - rrc_asn1_warn_assert(mob_ctrl_info_v2x_r14_present != (mob_ctrl_info_v2x_r14.get() != NULL), __FILE__, __LINE__); - if (mob_ctrl_info_v2x_r14_present) { + if (mob_ctrl_info_v2x_r14.is_present()) { j.write_fieldname("mobilityControlInfoV2X-r14"); mob_ctrl_info_v2x_r14->to_json(j); } @@ -72257,8 +71301,7 @@ void mob_ctrl_info_s::to_json(json_writer& j) const if (make_before_break_r14_present) { j.write_str("makeBeforeBreak-r14", "true"); } - rrc_asn1_warn_assert(rach_skip_r14_present != (rach_skip_r14.get() != NULL), __FILE__, __LINE__); - if (rach_skip_r14_present) { + if (rach_skip_r14.is_present()) { j.write_fieldname("rach-Skip-r14"); rach_skip_r14->to_json(j); } @@ -78906,12 +77949,12 @@ SRSASN_CODE pmch_cfg_r12_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, mch_sched_period_r12)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= mch_sched_period_v1430_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(mch_sched_period_v1430_present, 1)); if (mch_sched_period_v1430_present) { @@ -78929,11 +77972,11 @@ SRSASN_CODE pmch_cfg_r12_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(mch_sched_period_r12, bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(mch_sched_period_v1430_present, 1)); if (mch_sched_period_v1430_present) { @@ -81221,12 +80264,12 @@ SRSASN_CODE sc_mtch_info_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= p_a_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(p_a_r13_present, 1)); if (p_a_r13_present) { @@ -81252,11 +80295,11 @@ SRSASN_CODE sc_mtch_info_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(p_a_r13_present, 1)); if (p_a_r13_present) { @@ -83820,29 +82863,26 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(5); - rrc_asn1_warn_assert(add_si_info_r9_present != (add_si_info_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= add_si_info_r9_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= add_si_info_r9.is_present(); group_flags[1] |= primary_plmn_suitable_r12_present; group_flags[1] |= meas_result_v1250_present; group_flags[2] |= rs_sinr_result_r13_present; - rrc_asn1_warn_assert(cgi_info_v1310_present != (cgi_info_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= cgi_info_v1310_present; + group_flags[2] |= cgi_info_v1310.is_present(); group_flags[3] |= meas_result_v1360_present; - rrc_asn1_warn_assert(cgi_info_minus5_gc_r15_present != (cgi_info_minus5_gc_r15.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= cgi_info_minus5_gc_r15_present; + group_flags[4] |= cgi_info_minus5_gc_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(add_si_info_r9_present, 1)); - if (add_si_info_r9_present) { + HANDLE_CODE(bref.pack(add_si_info_r9.is_present(), 1)); + if (add_si_info_r9.is_present()) { HANDLE_CODE(add_si_info_r9->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(primary_plmn_suitable_r12_present, 1)); HANDLE_CODE(bref.pack(meas_result_v1250_present, 1)); @@ -83851,14 +82891,14 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(rs_sinr_result_r13_present, 1)); - HANDLE_CODE(bref.pack(cgi_info_v1310_present, 1)); + HANDLE_CODE(bref.pack(cgi_info_v1310.is_present(), 1)); if (rs_sinr_result_r13_present) { HANDLE_CODE(pack_unalign_integer(bref, rs_sinr_result_r13, (uint8_t)0, (uint8_t)127)); } - if (cgi_info_v1310_present) { + if (cgi_info_v1310.is_present()) { HANDLE_CODE(bref.pack(cgi_info_v1310->freq_band_ind_r13_present, 1)); HANDLE_CODE(bref.pack(cgi_info_v1310->multi_band_info_list_r13_present, 1)); HANDLE_CODE(bref.pack(cgi_info_v1310->freq_band_ind_prio_r13_present, 1)); @@ -83872,7 +82912,7 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::pack(bit_ref& bref) const } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_result_v1360_present, 1)); if (meas_result_v1360_present) { @@ -83880,10 +82920,10 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::pack(bit_ref& bref) const } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cgi_info_minus5_gc_r15_present, 1)); - if (cgi_info_minus5_gc_r15_present) { + HANDLE_CODE(bref.pack(cgi_info_minus5_gc_r15.is_present(), 1)); + if (cgi_info_minus5_gc_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *cgi_info_minus5_gc_r15, 1, 6)); } } @@ -83904,20 +82944,21 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(5); + ext_groups_unpacker_guard group_flags(5); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool add_si_info_r9_present; HANDLE_CODE(bref.unpack(add_si_info_r9_present, 1)); - if (add_si_info_r9_present) { - add_si_info_r9 = make_copy_ptr(add_si_info_r9_s()); + add_si_info_r9.set_present(add_si_info_r9_present); + if (add_si_info_r9.is_present()) { HANDLE_CODE(add_si_info_r9->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(primary_plmn_suitable_r12_present, 1)); HANDLE_CODE(bref.unpack(meas_result_v1250_present, 1)); @@ -83926,15 +82967,16 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(rs_sinr_result_r13_present, 1)); + bool cgi_info_v1310_present; HANDLE_CODE(bref.unpack(cgi_info_v1310_present, 1)); + cgi_info_v1310.set_present(cgi_info_v1310_present); if (rs_sinr_result_r13_present) { HANDLE_CODE(unpack_unalign_integer(rs_sinr_result_r13, bref, (uint8_t)0, (uint8_t)127)); } - if (cgi_info_v1310_present) { - cgi_info_v1310 = make_copy_ptr(cgi_info_v1310_s_()); + if (cgi_info_v1310.is_present()) { HANDLE_CODE(bref.unpack(cgi_info_v1310->freq_band_ind_r13_present, 1)); HANDLE_CODE(bref.unpack(cgi_info_v1310->multi_band_info_list_r13_present, 1)); HANDLE_CODE(bref.unpack(cgi_info_v1310->freq_band_ind_prio_r13_present, 1)); @@ -83948,7 +82990,7 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::unpack(bit_ref& bref) } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_result_v1360_present, 1)); if (meas_result_v1360_present) { @@ -83956,11 +82998,12 @@ SRSASN_CODE meas_result_eutra_s::meas_result_s_::unpack(bit_ref& bref) } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool cgi_info_minus5_gc_r15_present; HANDLE_CODE(bref.unpack(cgi_info_minus5_gc_r15_present, 1)); - if (cgi_info_minus5_gc_r15_present) { - cgi_info_minus5_gc_r15 = make_copy_ptr(cgi_info_minus5_gc_r15_l_()); + cgi_info_minus5_gc_r15.set_present(cgi_info_minus5_gc_r15_present); + if (cgi_info_minus5_gc_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*cgi_info_minus5_gc_r15, bref, 1, 6)); } } @@ -83977,8 +83020,7 @@ void meas_result_eutra_s::meas_result_s_::to_json(json_writer& j) const j.write_int("rsrqResult", rsrq_result); } if (ext) { - rrc_asn1_warn_assert(add_si_info_r9_present != (add_si_info_r9.get() != NULL), __FILE__, __LINE__); - if (add_si_info_r9_present) { + if (add_si_info_r9.is_present()) { j.write_fieldname("additionalSI-Info-r9"); add_si_info_r9->to_json(j); } @@ -83991,8 +83033,7 @@ void meas_result_eutra_s::meas_result_s_::to_json(json_writer& j) const if (rs_sinr_result_r13_present) { j.write_int("rs-sinr-Result-r13", rs_sinr_result_r13); } - rrc_asn1_warn_assert(cgi_info_v1310_present != (cgi_info_v1310.get() != NULL), __FILE__, __LINE__); - if (cgi_info_v1310_present) { + if (cgi_info_v1310.is_present()) { j.write_fieldname("cgi-Info-v1310"); j.start_obj(); if (cgi_info_v1310->freq_band_ind_r13_present) { @@ -84013,8 +83054,7 @@ void meas_result_eutra_s::meas_result_s_::to_json(json_writer& j) const if (meas_result_v1360_present) { j.write_int("measResult-v1360", meas_result_v1360); } - rrc_asn1_warn_assert(cgi_info_minus5_gc_r15_present != (cgi_info_minus5_gc_r15.get() != NULL), __FILE__, __LINE__); - if (cgi_info_minus5_gc_r15_present) { + if (cgi_info_minus5_gc_r15.is_present()) { j.start_array("cgi-Info-5GC-r15"); for (uint32_t i1 = 0; i1 < cgi_info_minus5_gc_r15->size(); ++i1) { ((*cgi_info_minus5_gc_r15)[i1]).to_json(j); @@ -84245,22 +83285,21 @@ SRSASN_CODE meas_result_utra_s::meas_result_s_::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert(add_si_info_r9_present != (add_si_info_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= add_si_info_r9_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= add_si_info_r9.is_present(); group_flags[1] |= primary_plmn_suitable_r12_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(add_si_info_r9_present, 1)); - if (add_si_info_r9_present) { + HANDLE_CODE(bref.pack(add_si_info_r9.is_present(), 1)); + if (add_si_info_r9.is_present()) { HANDLE_CODE(add_si_info_r9->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(primary_plmn_suitable_r12_present, 1)); } @@ -84281,20 +83320,21 @@ SRSASN_CODE meas_result_utra_s::meas_result_s_::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool add_si_info_r9_present; HANDLE_CODE(bref.unpack(add_si_info_r9_present, 1)); - if (add_si_info_r9_present) { - add_si_info_r9 = make_copy_ptr(add_si_info_r9_s()); + add_si_info_r9.set_present(add_si_info_r9_present); + if (add_si_info_r9.is_present()) { HANDLE_CODE(add_si_info_r9->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(primary_plmn_suitable_r12_present, 1)); } @@ -84311,8 +83351,7 @@ void meas_result_utra_s::meas_result_s_::to_json(json_writer& j) const j.write_int("utra-EcN0", utra_ec_n0); } if (ext) { - rrc_asn1_warn_assert(add_si_info_r9_present != (add_si_info_r9.get() != NULL), __FILE__, __LINE__); - if (add_si_info_r9_present) { + if (add_si_info_r9.is_present()) { j.write_fieldname("additionalSI-Info-r9"); add_si_info_r9->to_json(j); } @@ -84491,17 +83530,15 @@ SRSASN_CODE location_info_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - vertical_velocity_info_r15_present != (vertical_velocity_info_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= vertical_velocity_info_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= vertical_velocity_info_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(vertical_velocity_info_r15_present, 1)); - if (vertical_velocity_info_r15_present) { + HANDLE_CODE(bref.pack(vertical_velocity_info_r15.is_present(), 1)); + if (vertical_velocity_info_r15.is_present()) { HANDLE_CODE(vertical_velocity_info_r15->pack(bref)); } } @@ -84523,15 +83560,16 @@ SRSASN_CODE location_info_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool vertical_velocity_info_r15_present; HANDLE_CODE(bref.unpack(vertical_velocity_info_r15_present, 1)); - if (vertical_velocity_info_r15_present) { - vertical_velocity_info_r15 = make_copy_ptr(vertical_velocity_info_r15_c_()); + vertical_velocity_info_r15.set_present(vertical_velocity_info_r15_present); + if (vertical_velocity_info_r15.is_present()) { HANDLE_CODE(vertical_velocity_info_r15->unpack(bref)); } } @@ -84550,9 +83588,7 @@ void location_info_r10_s::to_json(json_writer& j) const j.write_str("gnss-TOD-msec-r10", gnss_tod_msec_r10.to_string()); } if (ext) { - rrc_asn1_warn_assert( - vertical_velocity_info_r15_present != (vertical_velocity_info_r15.get() != NULL), __FILE__, __LINE__); - if (vertical_velocity_info_r15_present) { + if (vertical_velocity_info_r15.is_present()) { j.write_fieldname("verticalVelocityInfo-r15"); vertical_velocity_info_r15->to_json(j); } @@ -86455,65 +85491,53 @@ SRSASN_CODE log_meas_info_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(5); - rrc_asn1_warn_assert( - meas_result_list_eutra_v1090_present != (meas_result_list_eutra_v1090.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= meas_result_list_eutra_v1090_present; - rrc_asn1_warn_assert( - meas_result_list_mbsfn_r12_present != (meas_result_list_mbsfn_r12.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= meas_result_list_mbsfn_r12_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= meas_result_list_eutra_v1090.is_present(); + group_flags[1] |= meas_result_list_mbsfn_r12.is_present(); group_flags[1] |= meas_result_serv_cell_v1250_present; - rrc_asn1_warn_assert( - serv_cell_rsrq_type_r12_present != (serv_cell_rsrq_type_r12.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= serv_cell_rsrq_type_r12_present; - rrc_asn1_warn_assert( - meas_result_list_eutra_v1250_present != (meas_result_list_eutra_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= meas_result_list_eutra_v1250_present; + group_flags[1] |= serv_cell_rsrq_type_r12.is_present(); + group_flags[1] |= meas_result_list_eutra_v1250.is_present(); group_flags[2] |= in_dev_coex_detected_r13_present; group_flags[3] |= meas_result_serv_cell_v1360_present; - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= log_meas_result_list_bt_r15_present; - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - group_flags[4] |= log_meas_result_list_wlan_r15_present; + group_flags[4] |= log_meas_result_list_bt_r15.is_present(); + group_flags[4] |= log_meas_result_list_wlan_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_list_eutra_v1090_present, 1)); - if (meas_result_list_eutra_v1090_present) { + HANDLE_CODE(bref.pack(meas_result_list_eutra_v1090.is_present(), 1)); + if (meas_result_list_eutra_v1090.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_eutra_v1090, 1, 8)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_list_mbsfn_r12_present, 1)); + HANDLE_CODE(bref.pack(meas_result_list_mbsfn_r12.is_present(), 1)); HANDLE_CODE(bref.pack(meas_result_serv_cell_v1250_present, 1)); - HANDLE_CODE(bref.pack(serv_cell_rsrq_type_r12_present, 1)); - HANDLE_CODE(bref.pack(meas_result_list_eutra_v1250_present, 1)); - if (meas_result_list_mbsfn_r12_present) { + HANDLE_CODE(bref.pack(serv_cell_rsrq_type_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_list_eutra_v1250.is_present(), 1)); + if (meas_result_list_mbsfn_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_mbsfn_r12, 1, 8)); } if (meas_result_serv_cell_v1250_present) { HANDLE_CODE(pack_unalign_integer(bref, meas_result_serv_cell_v1250, (int8_t)-30, (int8_t)46)); } - if (serv_cell_rsrq_type_r12_present) { + if (serv_cell_rsrq_type_r12.is_present()) { HANDLE_CODE(serv_cell_rsrq_type_r12->pack(bref)); } - if (meas_result_list_eutra_v1250_present) { + if (meas_result_list_eutra_v1250.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_eutra_v1250, 1, 8)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(in_dev_coex_detected_r13_present, 1)); } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_result_serv_cell_v1360_present, 1)); if (meas_result_serv_cell_v1360_present) { @@ -86521,14 +85545,14 @@ SRSASN_CODE log_meas_info_r10_s::pack(bit_ref& bref) const } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15_present, 1)); - HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { + HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15.is_present(), 1)); + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_bt_r15, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_wlan_r15, 1, 32)); } } @@ -86569,48 +85593,52 @@ SRSASN_CODE log_meas_info_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(5); + ext_groups_unpacker_guard group_flags(5); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_list_eutra_v1090_present; HANDLE_CODE(bref.unpack(meas_result_list_eutra_v1090_present, 1)); - if (meas_result_list_eutra_v1090_present) { - meas_result_list_eutra_v1090 = make_copy_ptr(meas_result_list2_eutra_v9e0_l()); + meas_result_list_eutra_v1090.set_present(meas_result_list_eutra_v1090_present); + if (meas_result_list_eutra_v1090.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_eutra_v1090, bref, 1, 8)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_list_mbsfn_r12_present; HANDLE_CODE(bref.unpack(meas_result_list_mbsfn_r12_present, 1)); + meas_result_list_mbsfn_r12.set_present(meas_result_list_mbsfn_r12_present); HANDLE_CODE(bref.unpack(meas_result_serv_cell_v1250_present, 1)); + bool serv_cell_rsrq_type_r12_present; HANDLE_CODE(bref.unpack(serv_cell_rsrq_type_r12_present, 1)); + serv_cell_rsrq_type_r12.set_present(serv_cell_rsrq_type_r12_present); + bool meas_result_list_eutra_v1250_present; HANDLE_CODE(bref.unpack(meas_result_list_eutra_v1250_present, 1)); - if (meas_result_list_mbsfn_r12_present) { - meas_result_list_mbsfn_r12 = make_copy_ptr(meas_result_list_mbsfn_r12_l()); + meas_result_list_eutra_v1250.set_present(meas_result_list_eutra_v1250_present); + if (meas_result_list_mbsfn_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_mbsfn_r12, bref, 1, 8)); } if (meas_result_serv_cell_v1250_present) { HANDLE_CODE(unpack_unalign_integer(meas_result_serv_cell_v1250, bref, (int8_t)-30, (int8_t)46)); } - if (serv_cell_rsrq_type_r12_present) { - serv_cell_rsrq_type_r12 = make_copy_ptr(rsrq_type_r12_s()); + if (serv_cell_rsrq_type_r12.is_present()) { HANDLE_CODE(serv_cell_rsrq_type_r12->unpack(bref)); } - if (meas_result_list_eutra_v1250_present) { - meas_result_list_eutra_v1250 = make_copy_ptr(meas_result_list2_eutra_v1250_l()); + if (meas_result_list_eutra_v1250.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_eutra_v1250, bref, 1, 8)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(in_dev_coex_detected_r13_present, 1)); } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_result_serv_cell_v1360_present, 1)); if (meas_result_serv_cell_v1360_present) { @@ -86618,16 +85646,18 @@ SRSASN_CODE log_meas_info_r10_s::unpack(bit_ref& bref) } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool log_meas_result_list_bt_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_bt_r15_present, 1)); + log_meas_result_list_bt_r15.set_present(log_meas_result_list_bt_r15_present); + bool log_meas_result_list_wlan_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_wlan_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { - log_meas_result_list_bt_r15 = make_copy_ptr(log_meas_result_list_bt_r15_l()); + log_meas_result_list_wlan_r15.set_present(log_meas_result_list_wlan_r15_present); + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_bt_r15, bref, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { - log_meas_result_list_wlan_r15 = make_copy_ptr(log_meas_result_list_wlan_r15_l()); + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_wlan_r15, bref, 1, 32)); } } @@ -86687,18 +85717,14 @@ void log_meas_info_r10_s::to_json(json_writer& j) const j.end_obj(); } if (ext) { - rrc_asn1_warn_assert( - meas_result_list_eutra_v1090_present != (meas_result_list_eutra_v1090.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_eutra_v1090_present) { + if (meas_result_list_eutra_v1090.is_present()) { j.start_array("measResultListEUTRA-v1090"); for (uint32_t i1 = 0; i1 < meas_result_list_eutra_v1090->size(); ++i1) { ((*meas_result_list_eutra_v1090)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_result_list_mbsfn_r12_present != (meas_result_list_mbsfn_r12.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_mbsfn_r12_present) { + if (meas_result_list_mbsfn_r12.is_present()) { j.start_array("measResultListMBSFN-r12"); for (uint32_t i1 = 0; i1 < meas_result_list_mbsfn_r12->size(); ++i1) { ((*meas_result_list_mbsfn_r12)[i1]).to_json(j); @@ -86708,15 +85734,11 @@ void log_meas_info_r10_s::to_json(json_writer& j) const if (meas_result_serv_cell_v1250_present) { j.write_int("measResultServCell-v1250", meas_result_serv_cell_v1250); } - rrc_asn1_warn_assert( - serv_cell_rsrq_type_r12_present != (serv_cell_rsrq_type_r12.get() != NULL), __FILE__, __LINE__); - if (serv_cell_rsrq_type_r12_present) { + if (serv_cell_rsrq_type_r12.is_present()) { j.write_fieldname("servCellRSRQ-Type-r12"); serv_cell_rsrq_type_r12->to_json(j); } - rrc_asn1_warn_assert( - meas_result_list_eutra_v1250_present != (meas_result_list_eutra_v1250.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_eutra_v1250_present) { + if (meas_result_list_eutra_v1250.is_present()) { j.start_array("measResultListEUTRA-v1250"); for (uint32_t i1 = 0; i1 < meas_result_list_eutra_v1250->size(); ++i1) { ((*meas_result_list_eutra_v1250)[i1]).to_json(j); @@ -86729,18 +85751,14 @@ void log_meas_info_r10_s::to_json(json_writer& j) const if (meas_result_serv_cell_v1360_present) { j.write_int("measResultServCell-v1360", meas_result_serv_cell_v1360); } - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_bt_r15_present) { + if (log_meas_result_list_bt_r15.is_present()) { j.start_array("logMeasResultListBT-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_bt_r15->size(); ++i1) { ((*log_meas_result_list_bt_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { j.start_array("logMeasResultListWLAN-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_wlan_r15->size(); ++i1) { ((*log_meas_result_list_wlan_r15)[i1]).to_json(j); @@ -86790,16 +85808,15 @@ SRSASN_CODE meas_result_cell_nr_r15_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(cgi_info_r15_present != (cgi_info_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cgi_info_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= cgi_info_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(cgi_info_r15_present, 1)); - if (cgi_info_r15_present) { + HANDLE_CODE(bref.pack(cgi_info_r15.is_present(), 1)); + if (cgi_info_r15.is_present()) { HANDLE_CODE(cgi_info_r15->pack(bref)); } } @@ -86818,15 +85835,16 @@ SRSASN_CODE meas_result_cell_nr_r15_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool cgi_info_r15_present; HANDLE_CODE(bref.unpack(cgi_info_r15_present, 1)); - if (cgi_info_r15_present) { - cgi_info_r15 = make_copy_ptr(cgi_info_nr_r15_s()); + cgi_info_r15.set_present(cgi_info_r15_present); + if (cgi_info_r15.is_present()) { HANDLE_CODE(cgi_info_r15->unpack(bref)); } } @@ -86847,8 +85865,7 @@ void meas_result_cell_nr_r15_s::to_json(json_writer& j) const j.end_array(); } if (ext) { - rrc_asn1_warn_assert(cgi_info_r15_present != (cgi_info_r15.get() != NULL), __FILE__, __LINE__); - if (cgi_info_r15_present) { + if (cgi_info_r15.is_present()) { j.write_fieldname("cgi-Info-r15"); cgi_info_r15->to_json(j); } @@ -87191,41 +86208,33 @@ SRSASN_CODE conn_est_fail_report_r11_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); + ext_groups_packer_guard group_flags; group_flags[0] |= meas_result_failed_cell_v1250_present; - rrc_asn1_warn_assert( - failed_cell_rsrq_type_r12_present != (failed_cell_rsrq_type_r12.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= failed_cell_rsrq_type_r12_present; - rrc_asn1_warn_assert( - meas_result_list_eutra_v1250_present != (meas_result_list_eutra_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= meas_result_list_eutra_v1250_present; + group_flags[0] |= failed_cell_rsrq_type_r12.is_present(); + group_flags[0] |= meas_result_list_eutra_v1250.is_present(); group_flags[1] |= meas_result_failed_cell_v1360_present; - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= log_meas_result_list_bt_r15_present; - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= log_meas_result_list_wlan_r15_present; + group_flags[2] |= log_meas_result_list_bt_r15.is_present(); + group_flags[2] |= log_meas_result_list_wlan_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_result_failed_cell_v1250_present, 1)); - HANDLE_CODE(bref.pack(failed_cell_rsrq_type_r12_present, 1)); - HANDLE_CODE(bref.pack(meas_result_list_eutra_v1250_present, 1)); + HANDLE_CODE(bref.pack(failed_cell_rsrq_type_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_list_eutra_v1250.is_present(), 1)); if (meas_result_failed_cell_v1250_present) { HANDLE_CODE(pack_unalign_integer(bref, meas_result_failed_cell_v1250, (int8_t)-30, (int8_t)46)); } - if (failed_cell_rsrq_type_r12_present) { + if (failed_cell_rsrq_type_r12.is_present()) { HANDLE_CODE(failed_cell_rsrq_type_r12->pack(bref)); } - if (meas_result_list_eutra_v1250_present) { + if (meas_result_list_eutra_v1250.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_eutra_v1250, 1, 8)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_result_failed_cell_v1360_present, 1)); if (meas_result_failed_cell_v1360_present) { @@ -87233,14 +86242,14 @@ SRSASN_CODE conn_est_fail_report_r11_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15_present, 1)); - HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { + HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15.is_present(), 1)); + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_bt_r15, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_wlan_r15, 1, 32)); } } @@ -87290,29 +86299,31 @@ SRSASN_CODE conn_est_fail_report_r11_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_result_failed_cell_v1250_present, 1)); + bool failed_cell_rsrq_type_r12_present; HANDLE_CODE(bref.unpack(failed_cell_rsrq_type_r12_present, 1)); + failed_cell_rsrq_type_r12.set_present(failed_cell_rsrq_type_r12_present); + bool meas_result_list_eutra_v1250_present; HANDLE_CODE(bref.unpack(meas_result_list_eutra_v1250_present, 1)); + meas_result_list_eutra_v1250.set_present(meas_result_list_eutra_v1250_present); if (meas_result_failed_cell_v1250_present) { HANDLE_CODE(unpack_unalign_integer(meas_result_failed_cell_v1250, bref, (int8_t)-30, (int8_t)46)); } - if (failed_cell_rsrq_type_r12_present) { - failed_cell_rsrq_type_r12 = make_copy_ptr(rsrq_type_r12_s()); + if (failed_cell_rsrq_type_r12.is_present()) { HANDLE_CODE(failed_cell_rsrq_type_r12->unpack(bref)); } - if (meas_result_list_eutra_v1250_present) { - meas_result_list_eutra_v1250 = make_copy_ptr(meas_result_list2_eutra_v1250_l()); + if (meas_result_list_eutra_v1250.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_eutra_v1250, bref, 1, 8)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_result_failed_cell_v1360_present, 1)); if (meas_result_failed_cell_v1360_present) { @@ -87320,16 +86331,18 @@ SRSASN_CODE conn_est_fail_report_r11_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool log_meas_result_list_bt_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_bt_r15_present, 1)); + log_meas_result_list_bt_r15.set_present(log_meas_result_list_bt_r15_present); + bool log_meas_result_list_wlan_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_wlan_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { - log_meas_result_list_bt_r15 = make_copy_ptr(log_meas_result_list_bt_r15_l()); + log_meas_result_list_wlan_r15.set_present(log_meas_result_list_wlan_r15_present); + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_bt_r15, bref, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { - log_meas_result_list_wlan_r15 = make_copy_ptr(log_meas_result_list_wlan_r15_l()); + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_wlan_r15, bref, 1, 32)); } } @@ -87400,15 +86413,11 @@ void conn_est_fail_report_r11_s::to_json(json_writer& j) const if (meas_result_failed_cell_v1250_present) { j.write_int("measResultFailedCell-v1250", meas_result_failed_cell_v1250); } - rrc_asn1_warn_assert( - failed_cell_rsrq_type_r12_present != (failed_cell_rsrq_type_r12.get() != NULL), __FILE__, __LINE__); - if (failed_cell_rsrq_type_r12_present) { + if (failed_cell_rsrq_type_r12.is_present()) { j.write_fieldname("failedCellRSRQ-Type-r12"); failed_cell_rsrq_type_r12->to_json(j); } - rrc_asn1_warn_assert( - meas_result_list_eutra_v1250_present != (meas_result_list_eutra_v1250.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_eutra_v1250_present) { + if (meas_result_list_eutra_v1250.is_present()) { j.start_array("measResultListEUTRA-v1250"); for (uint32_t i1 = 0; i1 < meas_result_list_eutra_v1250->size(); ++i1) { ((*meas_result_list_eutra_v1250)[i1]).to_json(j); @@ -87418,18 +86427,14 @@ void conn_est_fail_report_r11_s::to_json(json_writer& j) const if (meas_result_failed_cell_v1360_present) { j.write_int("measResultFailedCell-v1360", meas_result_failed_cell_v1360); } - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_bt_r15_present) { + if (log_meas_result_list_bt_r15.is_present()) { j.start_array("logMeasResultListBT-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_bt_r15->size(); ++i1) { ((*log_meas_result_list_bt_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { j.start_array("logMeasResultListWLAN-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_wlan_r15->size(); ++i1) { ((*log_meas_result_list_wlan_r15)[i1]).to_json(j); @@ -88072,13 +87077,13 @@ SRSASN_CODE log_meas_report_r10_s::pack(bit_ref& bref) const HANDLE_CODE(pack_dyn_seq_of(bref, log_meas_info_list_r10, 1, 520)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= log_meas_available_bt_r15_present; group_flags[0] |= log_meas_available_wlan_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(log_meas_available_bt_r15_present, 1)); HANDLE_CODE(bref.pack(log_meas_available_wlan_r15_present, 1)); @@ -88098,11 +87103,11 @@ SRSASN_CODE log_meas_report_r10_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_dyn_seq_of(log_meas_info_list_r10, bref, 1, 520)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(log_meas_available_bt_r15_present, 1)); HANDLE_CODE(bref.unpack(log_meas_available_wlan_r15_present, 1)); @@ -88318,20 +87323,15 @@ SRSASN_CODE meas_result_serv_freq_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); + ext_groups_packer_guard group_flags; group_flags[0] |= meas_result_scell_v1250_present; group_flags[0] |= meas_result_best_neigh_cell_v1250_present; - rrc_asn1_warn_assert( - meas_result_scell_v1310_present != (meas_result_scell_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= meas_result_scell_v1310_present; - rrc_asn1_warn_assert(meas_result_best_neigh_cell_v1310_present != (meas_result_best_neigh_cell_v1310.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= meas_result_best_neigh_cell_v1310_present; + group_flags[1] |= meas_result_scell_v1310.is_present(); + group_flags[1] |= meas_result_best_neigh_cell_v1310.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_result_scell_v1250_present, 1)); HANDLE_CODE(bref.pack(meas_result_best_neigh_cell_v1250_present, 1)); @@ -88343,14 +87343,14 @@ SRSASN_CODE meas_result_serv_freq_r10_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_scell_v1310_present, 1)); - HANDLE_CODE(bref.pack(meas_result_best_neigh_cell_v1310_present, 1)); - if (meas_result_scell_v1310_present) { + HANDLE_CODE(bref.pack(meas_result_scell_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_best_neigh_cell_v1310.is_present(), 1)); + if (meas_result_scell_v1310.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, meas_result_scell_v1310->rs_sinr_result_r13, (uint8_t)0, (uint8_t)127)); } - if (meas_result_best_neigh_cell_v1310_present) { + if (meas_result_best_neigh_cell_v1310.is_present()) { HANDLE_CODE(pack_unalign_integer( bref, meas_result_best_neigh_cell_v1310->rs_sinr_result_r13, (uint8_t)0, (uint8_t)127)); } @@ -88378,11 +87378,11 @@ SRSASN_CODE meas_result_serv_freq_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_result_scell_v1250_present, 1)); HANDLE_CODE(bref.unpack(meas_result_best_neigh_cell_v1250_present, 1)); @@ -88394,17 +87394,19 @@ SRSASN_CODE meas_result_serv_freq_r10_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_scell_v1310_present; HANDLE_CODE(bref.unpack(meas_result_scell_v1310_present, 1)); + meas_result_scell_v1310.set_present(meas_result_scell_v1310_present); + bool meas_result_best_neigh_cell_v1310_present; HANDLE_CODE(bref.unpack(meas_result_best_neigh_cell_v1310_present, 1)); - if (meas_result_scell_v1310_present) { - meas_result_scell_v1310 = make_copy_ptr(meas_result_scell_v1310_s_()); + meas_result_best_neigh_cell_v1310.set_present(meas_result_best_neigh_cell_v1310_present); + if (meas_result_scell_v1310.is_present()) { HANDLE_CODE( unpack_unalign_integer(meas_result_scell_v1310->rs_sinr_result_r13, bref, (uint8_t)0, (uint8_t)127)); } - if (meas_result_best_neigh_cell_v1310_present) { - meas_result_best_neigh_cell_v1310 = make_copy_ptr(meas_result_best_neigh_cell_v1310_s_()); + if (meas_result_best_neigh_cell_v1310.is_present()) { HANDLE_CODE(unpack_unalign_integer( meas_result_best_neigh_cell_v1310->rs_sinr_result_r13, bref, (uint8_t)0, (uint8_t)127)); } @@ -88438,18 +87440,13 @@ void meas_result_serv_freq_r10_s::to_json(json_writer& j) const if (meas_result_best_neigh_cell_v1250_present) { j.write_int("measResultBestNeighCell-v1250", meas_result_best_neigh_cell_v1250); } - rrc_asn1_warn_assert( - meas_result_scell_v1310_present != (meas_result_scell_v1310.get() != NULL), __FILE__, __LINE__); - if (meas_result_scell_v1310_present) { + if (meas_result_scell_v1310.is_present()) { j.write_fieldname("measResultSCell-v1310"); j.start_obj(); j.write_int("rs-sinr-Result-r13", meas_result_scell_v1310->rs_sinr_result_r13); j.end_obj(); } - rrc_asn1_warn_assert(meas_result_best_neigh_cell_v1310_present != (meas_result_best_neigh_cell_v1310.get() != NULL), - __FILE__, - __LINE__); - if (meas_result_best_neigh_cell_v1310_present) { + if (meas_result_best_neigh_cell_v1310.is_present()) { j.write_fieldname("measResultBestNeighCell-v1310"); j.start_obj(); j.write_int("rs-sinr-Result-r13", meas_result_best_neigh_cell_v1310->rs_sinr_result_r13); @@ -88489,18 +87486,15 @@ SRSASN_CODE meas_result_serv_freq_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(meas_result_best_neigh_cell_v1360_present != (meas_result_best_neigh_cell_v1360.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= meas_result_best_neigh_cell_v1360_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= meas_result_best_neigh_cell_v1360.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_best_neigh_cell_v1360_present, 1)); - if (meas_result_best_neigh_cell_v1360_present) { + HANDLE_CODE(bref.pack(meas_result_best_neigh_cell_v1360.is_present(), 1)); + if (meas_result_best_neigh_cell_v1360.is_present()) { HANDLE_CODE(pack_unalign_integer( bref, meas_result_best_neigh_cell_v1360->rsrp_result_ncell_v1360, (int8_t)-17, (int8_t)-1)); } @@ -88537,15 +87531,16 @@ SRSASN_CODE meas_result_serv_freq_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_best_neigh_cell_v1360_present; HANDLE_CODE(bref.unpack(meas_result_best_neigh_cell_v1360_present, 1)); - if (meas_result_best_neigh_cell_v1360_present) { - meas_result_best_neigh_cell_v1360 = make_copy_ptr(meas_result_best_neigh_cell_v1360_s_()); + meas_result_best_neigh_cell_v1360.set_present(meas_result_best_neigh_cell_v1360_present); + if (meas_result_best_neigh_cell_v1360.is_present()) { HANDLE_CODE(unpack_unalign_integer( meas_result_best_neigh_cell_v1360->rsrp_result_ncell_v1360, bref, (int8_t)-17, (int8_t)-1)); } @@ -88579,10 +87574,7 @@ void meas_result_serv_freq_r13_s::to_json(json_writer& j) const j.end_obj(); } if (ext) { - rrc_asn1_warn_assert(meas_result_best_neigh_cell_v1360_present != (meas_result_best_neigh_cell_v1360.get() != NULL), - __FILE__, - __LINE__); - if (meas_result_best_neigh_cell_v1360_present) { + if (meas_result_best_neigh_cell_v1360.is_present()) { j.write_fieldname("measResultBestNeighCell-v1360"); j.start_obj(); j.write_int("rsrpResultNCell-v1360", meas_result_best_neigh_cell_v1360->rsrp_result_ncell_v1360); @@ -89012,16 +88004,15 @@ SRSASN_CODE sl_disc_sys_info_report_r13_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(freq_info_v1370_present != (freq_info_v1370.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= freq_info_v1370_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= freq_info_v1370.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(freq_info_v1370_present, 1)); - if (freq_info_v1370_present) { + HANDLE_CODE(bref.pack(freq_info_v1370.is_present(), 1)); + if (freq_info_v1370.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, freq_info_v1370->add_spec_emission_v1370, (uint16_t)33, (uint16_t)288)); } } @@ -89103,15 +88094,16 @@ SRSASN_CODE sl_disc_sys_info_report_r13_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool freq_info_v1370_present; HANDLE_CODE(bref.unpack(freq_info_v1370_present, 1)); - if (freq_info_v1370_present) { - freq_info_v1370 = make_copy_ptr(freq_info_v1370_s_()); + freq_info_v1370.set_present(freq_info_v1370_present); + if (freq_info_v1370.is_present()) { HANDLE_CODE( unpack_unalign_integer(freq_info_v1370->add_spec_emission_v1370, bref, (uint16_t)33, (uint16_t)288)); } @@ -89202,8 +88194,7 @@ void sl_disc_sys_info_report_r13_s::to_json(json_writer& j) const j.write_int("referenceSignalPower-r13", ref_sig_pwr_r13); } if (ext) { - rrc_asn1_warn_assert(freq_info_v1370_present != (freq_info_v1370.get() != NULL), __FILE__, __LINE__); - if (freq_info_v1370_present) { + if (freq_info_v1370.is_present()) { j.write_fieldname("freqInfo-v1370"); j.start_obj(); j.write_int("additionalSpectrumEmission-v1370", freq_info_v1370->add_spec_emission_v1370); @@ -89405,7 +88396,7 @@ SRSASN_CODE ue_radio_paging_info_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); + ext_groups_packer_guard group_flags; group_flags[0] |= ue_category_dl_v1310_present; group_flags[0] |= ce_mode_a_r13_present; group_flags[0] |= ce_mode_b_r13_present; @@ -89416,14 +88407,14 @@ SRSASN_CODE ue_radio_paging_info_r12_s::pack(bit_ref& bref) const group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(ue_category_dl_v1310_present, 1)); HANDLE_CODE(bref.pack(ce_mode_a_r13_present, 1)); HANDLE_CODE(bref.pack(ce_mode_b_r13_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(wake_up_signal_r15_present, 1)); HANDLE_CODE(bref.pack(wake_up_signal_tdd_r15_present, 1)); @@ -89449,18 +88440,18 @@ SRSASN_CODE ue_radio_paging_info_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(ue_category_dl_v1310_present, 1)); HANDLE_CODE(bref.unpack(ce_mode_a_r13_present, 1)); HANDLE_CODE(bref.unpack(ce_mode_b_r13_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(wake_up_signal_r15_present, 1)); HANDLE_CODE(bref.unpack(wake_up_signal_tdd_r15_present, 1)); @@ -90171,14 +89162,13 @@ SRSASN_CODE rstd_inter_freq_info_r10_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, meas_prs_offset_r10, (uint8_t)0, (uint8_t)39)); if (ext) { - ext_groups_header group_flags(2); + ext_groups_packer_guard group_flags; group_flags[0] |= carrier_freq_v1090_present; - rrc_asn1_warn_assert(meas_prs_offset_r15_present != (meas_prs_offset_r15.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= meas_prs_offset_r15_present; + group_flags[1] |= meas_prs_offset_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(carrier_freq_v1090_present, 1)); if (carrier_freq_v1090_present) { @@ -90186,10 +89176,10 @@ SRSASN_CODE rstd_inter_freq_info_r10_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_prs_offset_r15_present, 1)); - if (meas_prs_offset_r15_present) { + HANDLE_CODE(bref.pack(meas_prs_offset_r15.is_present(), 1)); + if (meas_prs_offset_r15.is_present()) { HANDLE_CODE(meas_prs_offset_r15->pack(bref)); } } @@ -90203,11 +89193,11 @@ SRSASN_CODE rstd_inter_freq_info_r10_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(meas_prs_offset_r10, bref, (uint8_t)0, (uint8_t)39)); if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(carrier_freq_v1090_present, 1)); if (carrier_freq_v1090_present) { @@ -90215,11 +89205,12 @@ SRSASN_CODE rstd_inter_freq_info_r10_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_prs_offset_r15_present; HANDLE_CODE(bref.unpack(meas_prs_offset_r15_present, 1)); - if (meas_prs_offset_r15_present) { - meas_prs_offset_r15 = make_copy_ptr(meas_prs_offset_r15_c_()); + meas_prs_offset_r15.set_present(meas_prs_offset_r15_present); + if (meas_prs_offset_r15.is_present()) { HANDLE_CODE(meas_prs_offset_r15->unpack(bref)); } } @@ -90235,8 +89226,7 @@ void rstd_inter_freq_info_r10_s::to_json(json_writer& j) const if (carrier_freq_v1090_present) { j.write_int("carrierFreq-v1090", carrier_freq_v1090); } - rrc_asn1_warn_assert(meas_prs_offset_r15_present != (meas_prs_offset_r15.get() != NULL), __FILE__, __LINE__); - if (meas_prs_offset_r15_present) { + if (meas_prs_offset_r15.is_present()) { j.write_fieldname("measPRS-Offset-r15"); meas_prs_offset_r15->to_json(j); } @@ -91097,25 +90087,21 @@ SRSASN_CODE fail_report_scg_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); + ext_groups_packer_guard group_flags; group_flags[0] |= fail_type_v1290_present; - rrc_asn1_warn_assert(meas_result_serv_freq_list_ext_r13_present != - (meas_result_serv_freq_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[1] |= meas_result_serv_freq_list_ext_r13_present; + group_flags[1] |= meas_result_serv_freq_list_ext_r13.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(fail_type_v1290_present, 1)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_serv_freq_list_ext_r13_present, 1)); - if (meas_result_serv_freq_list_ext_r13_present) { + HANDLE_CODE(bref.pack(meas_result_serv_freq_list_ext_r13.is_present(), 1)); + if (meas_result_serv_freq_list_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_serv_freq_list_ext_r13, 1, 32)); } } @@ -91137,20 +90123,21 @@ SRSASN_CODE fail_report_scg_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(fail_type_v1290_present, 1)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_serv_freq_list_ext_r13_present; HANDLE_CODE(bref.unpack(meas_result_serv_freq_list_ext_r13_present, 1)); - if (meas_result_serv_freq_list_ext_r13_present) { - meas_result_serv_freq_list_ext_r13 = make_copy_ptr(meas_result_serv_freq_list_ext_r13_l()); + meas_result_serv_freq_list_ext_r13.set_present(meas_result_serv_freq_list_ext_r13_present); + if (meas_result_serv_freq_list_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_serv_freq_list_ext_r13, bref, 1, 32)); } } @@ -91179,11 +90166,7 @@ void fail_report_scg_r12_s::to_json(json_writer& j) const if (fail_type_v1290_present) { j.write_str("failureType-v1290", "maxUL-TimingDiff-v1290"); } - rrc_asn1_warn_assert(meas_result_serv_freq_list_ext_r13_present != - (meas_result_serv_freq_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (meas_result_serv_freq_list_ext_r13_present) { + if (meas_result_serv_freq_list_ext_r13.is_present()) { j.start_array("measResultServFreqListExt-r13"); for (uint32_t i1 = 0; i1 < meas_result_serv_freq_list_ext_r13->size(); ++i1) { ((*meas_result_serv_freq_list_ext_r13)[i1]).to_json(j); @@ -91324,131 +90307,96 @@ SRSASN_CODE meas_results_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(8); - rrc_asn1_warn_assert( - meas_result_for_ecid_r9_present != (meas_result_for_ecid_r9.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= meas_result_for_ecid_r9_present; - rrc_asn1_warn_assert(location_info_r10_present != (location_info_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= location_info_r10_present; - rrc_asn1_warn_assert( - meas_result_serv_freq_list_r10_present != (meas_result_serv_freq_list_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= meas_result_serv_freq_list_r10_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= meas_result_for_ecid_r9.is_present(); + group_flags[1] |= location_info_r10.is_present(); + group_flags[1] |= meas_result_serv_freq_list_r10.is_present(); group_flags[2] |= meas_id_v1250_present; group_flags[2] |= meas_result_pcell_v1250_present; - rrc_asn1_warn_assert( - meas_result_csi_rs_list_r12_present != (meas_result_csi_rs_list_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= meas_result_csi_rs_list_r12_present; - rrc_asn1_warn_assert( - meas_result_for_rssi_r13_present != (meas_result_for_rssi_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_result_for_rssi_r13_present; - rrc_asn1_warn_assert(meas_result_serv_freq_list_ext_r13_present != - (meas_result_serv_freq_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - group_flags[3] |= meas_result_serv_freq_list_ext_r13_present; - rrc_asn1_warn_assert(meas_result_sstd_r13_present != (meas_result_sstd_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_result_sstd_r13_present; - rrc_asn1_warn_assert( - meas_result_pcell_v1310_present != (meas_result_pcell_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_result_pcell_v1310_present; - rrc_asn1_warn_assert( - ul_pdcp_delay_result_list_r13_present != (ul_pdcp_delay_result_list_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= ul_pdcp_delay_result_list_r13_present; - rrc_asn1_warn_assert( - meas_result_list_wlan_r13_present != (meas_result_list_wlan_r13.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_result_list_wlan_r13_present; + group_flags[2] |= meas_result_csi_rs_list_r12.is_present(); + group_flags[3] |= meas_result_for_rssi_r13.is_present(); + group_flags[3] |= meas_result_serv_freq_list_ext_r13.is_present(); + group_flags[3] |= meas_result_sstd_r13.is_present(); + group_flags[3] |= meas_result_pcell_v1310.is_present(); + group_flags[3] |= ul_pdcp_delay_result_list_r13.is_present(); + group_flags[3] |= meas_result_list_wlan_r13.is_present(); group_flags[4] |= meas_result_pcell_v1360_present; - rrc_asn1_warn_assert( - meas_result_list_cbr_r14_present != (meas_result_list_cbr_r14.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= meas_result_list_cbr_r14_present; - rrc_asn1_warn_assert( - meas_result_list_wlan_r14_present != (meas_result_list_wlan_r14.get() != NULL), __FILE__, __LINE__); - group_flags[5] |= meas_result_list_wlan_r14_present; - rrc_asn1_warn_assert(meas_result_serv_freq_list_nr_r15_present != (meas_result_serv_freq_list_nr_r15.get() != NULL), - __FILE__, - __LINE__); - group_flags[6] |= meas_result_serv_freq_list_nr_r15_present; - rrc_asn1_warn_assert( - meas_result_cell_list_sftd_r15_present != (meas_result_cell_list_sftd_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= meas_result_cell_list_sftd_r15_present; - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= log_meas_result_list_bt_r15_present; - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= log_meas_result_list_wlan_r15_present; - rrc_asn1_warn_assert( - meas_result_sensing_r15_present != (meas_result_sensing_r15.get() != NULL), __FILE__, __LINE__); - group_flags[7] |= meas_result_sensing_r15_present; + group_flags[5] |= meas_result_list_cbr_r14.is_present(); + group_flags[5] |= meas_result_list_wlan_r14.is_present(); + group_flags[6] |= meas_result_serv_freq_list_nr_r15.is_present(); + group_flags[6] |= meas_result_cell_list_sftd_r15.is_present(); + group_flags[7] |= log_meas_result_list_bt_r15.is_present(); + group_flags[7] |= log_meas_result_list_wlan_r15.is_present(); + group_flags[7] |= meas_result_sensing_r15.is_present(); group_flags[7] |= height_ue_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_for_ecid_r9_present, 1)); - if (meas_result_for_ecid_r9_present) { + HANDLE_CODE(bref.pack(meas_result_for_ecid_r9.is_present(), 1)); + if (meas_result_for_ecid_r9.is_present()) { HANDLE_CODE(meas_result_for_ecid_r9->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(location_info_r10_present, 1)); - HANDLE_CODE(bref.pack(meas_result_serv_freq_list_r10_present, 1)); - if (location_info_r10_present) { + HANDLE_CODE(bref.pack(location_info_r10.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_serv_freq_list_r10.is_present(), 1)); + if (location_info_r10.is_present()) { HANDLE_CODE(location_info_r10->pack(bref)); } - if (meas_result_serv_freq_list_r10_present) { + if (meas_result_serv_freq_list_r10.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_serv_freq_list_r10, 1, 5)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_id_v1250_present, 1)); HANDLE_CODE(bref.pack(meas_result_pcell_v1250_present, 1)); - HANDLE_CODE(bref.pack(meas_result_csi_rs_list_r12_present, 1)); + HANDLE_CODE(bref.pack(meas_result_csi_rs_list_r12.is_present(), 1)); if (meas_id_v1250_present) { HANDLE_CODE(pack_unalign_integer(bref, meas_id_v1250, (uint8_t)33, (uint8_t)64)); } if (meas_result_pcell_v1250_present) { HANDLE_CODE(pack_unalign_integer(bref, meas_result_pcell_v1250, (int8_t)-30, (int8_t)46)); } - if (meas_result_csi_rs_list_r12_present) { + if (meas_result_csi_rs_list_r12.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_csi_rs_list_r12, 1, 8)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); - - HANDLE_CODE(bref.pack(meas_result_for_rssi_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_result_serv_freq_list_ext_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_result_sstd_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_result_pcell_v1310_present, 1)); - HANDLE_CODE(bref.pack(ul_pdcp_delay_result_list_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_result_list_wlan_r13_present, 1)); - if (meas_result_for_rssi_r13_present) { + varlength_field_pack_guard varlen_scope(bref); + + HANDLE_CODE(bref.pack(meas_result_for_rssi_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_serv_freq_list_ext_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_sstd_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_pcell_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(ul_pdcp_delay_result_list_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_list_wlan_r13.is_present(), 1)); + if (meas_result_for_rssi_r13.is_present()) { HANDLE_CODE(meas_result_for_rssi_r13->pack(bref)); } - if (meas_result_serv_freq_list_ext_r13_present) { + if (meas_result_serv_freq_list_ext_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_serv_freq_list_ext_r13, 1, 32)); } - if (meas_result_sstd_r13_present) { + if (meas_result_sstd_r13.is_present()) { HANDLE_CODE(meas_result_sstd_r13->pack(bref)); } - if (meas_result_pcell_v1310_present) { + if (meas_result_pcell_v1310.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, meas_result_pcell_v1310->rs_sinr_result_r13, (uint8_t)0, (uint8_t)127)); } - if (ul_pdcp_delay_result_list_r13_present) { + if (ul_pdcp_delay_result_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *ul_pdcp_delay_result_list_r13, 1, 6)); } - if (meas_result_list_wlan_r13_present) { + if (meas_result_list_wlan_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_wlan_r13, 1, 8)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_result_pcell_v1360_present, 1)); if (meas_result_pcell_v1360_present) { @@ -91456,43 +90404,43 @@ SRSASN_CODE meas_results_s::pack(bit_ref& bref) const } } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_list_cbr_r14_present, 1)); - HANDLE_CODE(bref.pack(meas_result_list_wlan_r14_present, 1)); - if (meas_result_list_cbr_r14_present) { + HANDLE_CODE(bref.pack(meas_result_list_cbr_r14.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_list_wlan_r14.is_present(), 1)); + if (meas_result_list_cbr_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_cbr_r14, 1, 72)); } - if (meas_result_list_wlan_r14_present) { + if (meas_result_list_wlan_r14.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_wlan_r14, 1, 32)); } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(meas_result_serv_freq_list_nr_r15_present, 1)); - HANDLE_CODE(bref.pack(meas_result_cell_list_sftd_r15_present, 1)); - if (meas_result_serv_freq_list_nr_r15_present) { + HANDLE_CODE(bref.pack(meas_result_serv_freq_list_nr_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_cell_list_sftd_r15.is_present(), 1)); + if (meas_result_serv_freq_list_nr_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_serv_freq_list_nr_r15, 1, 32)); } - if (meas_result_cell_list_sftd_r15_present) { + if (meas_result_cell_list_sftd_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_cell_list_sftd_r15, 1, 3)); } } if (group_flags[7]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15_present, 1)); - HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15_present, 1)); - HANDLE_CODE(bref.pack(meas_result_sensing_r15_present, 1)); + HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_sensing_r15.is_present(), 1)); HANDLE_CODE(bref.pack(height_ue_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_bt_r15, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_wlan_r15, 1, 32)); } - if (meas_result_sensing_r15_present) { + if (meas_result_sensing_r15.is_present()) { HANDLE_CODE(meas_result_sensing_r15->pack(bref)); } if (height_ue_r15_present) { @@ -91515,86 +90463,96 @@ SRSASN_CODE meas_results_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(8); + ext_groups_unpacker_guard group_flags(8); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_for_ecid_r9_present; HANDLE_CODE(bref.unpack(meas_result_for_ecid_r9_present, 1)); - if (meas_result_for_ecid_r9_present) { - meas_result_for_ecid_r9 = make_copy_ptr(meas_result_for_ecid_r9_s()); + meas_result_for_ecid_r9.set_present(meas_result_for_ecid_r9_present); + if (meas_result_for_ecid_r9.is_present()) { HANDLE_CODE(meas_result_for_ecid_r9->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool location_info_r10_present; HANDLE_CODE(bref.unpack(location_info_r10_present, 1)); + location_info_r10.set_present(location_info_r10_present); + bool meas_result_serv_freq_list_r10_present; HANDLE_CODE(bref.unpack(meas_result_serv_freq_list_r10_present, 1)); - if (location_info_r10_present) { - location_info_r10 = make_copy_ptr(location_info_r10_s()); + meas_result_serv_freq_list_r10.set_present(meas_result_serv_freq_list_r10_present); + if (location_info_r10.is_present()) { HANDLE_CODE(location_info_r10->unpack(bref)); } - if (meas_result_serv_freq_list_r10_present) { - meas_result_serv_freq_list_r10 = make_copy_ptr(meas_result_serv_freq_list_r10_l()); + if (meas_result_serv_freq_list_r10.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_serv_freq_list_r10, bref, 1, 5)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_id_v1250_present, 1)); HANDLE_CODE(bref.unpack(meas_result_pcell_v1250_present, 1)); + bool meas_result_csi_rs_list_r12_present; HANDLE_CODE(bref.unpack(meas_result_csi_rs_list_r12_present, 1)); + meas_result_csi_rs_list_r12.set_present(meas_result_csi_rs_list_r12_present); if (meas_id_v1250_present) { HANDLE_CODE(unpack_unalign_integer(meas_id_v1250, bref, (uint8_t)33, (uint8_t)64)); } if (meas_result_pcell_v1250_present) { HANDLE_CODE(unpack_unalign_integer(meas_result_pcell_v1250, bref, (int8_t)-30, (int8_t)46)); } - if (meas_result_csi_rs_list_r12_present) { - meas_result_csi_rs_list_r12 = make_copy_ptr(meas_result_csi_rs_list_r12_l()); + if (meas_result_csi_rs_list_r12.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_csi_rs_list_r12, bref, 1, 8)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_for_rssi_r13_present; HANDLE_CODE(bref.unpack(meas_result_for_rssi_r13_present, 1)); + meas_result_for_rssi_r13.set_present(meas_result_for_rssi_r13_present); + bool meas_result_serv_freq_list_ext_r13_present; HANDLE_CODE(bref.unpack(meas_result_serv_freq_list_ext_r13_present, 1)); + meas_result_serv_freq_list_ext_r13.set_present(meas_result_serv_freq_list_ext_r13_present); + bool meas_result_sstd_r13_present; HANDLE_CODE(bref.unpack(meas_result_sstd_r13_present, 1)); + meas_result_sstd_r13.set_present(meas_result_sstd_r13_present); + bool meas_result_pcell_v1310_present; HANDLE_CODE(bref.unpack(meas_result_pcell_v1310_present, 1)); + meas_result_pcell_v1310.set_present(meas_result_pcell_v1310_present); + bool ul_pdcp_delay_result_list_r13_present; HANDLE_CODE(bref.unpack(ul_pdcp_delay_result_list_r13_present, 1)); + ul_pdcp_delay_result_list_r13.set_present(ul_pdcp_delay_result_list_r13_present); + bool meas_result_list_wlan_r13_present; HANDLE_CODE(bref.unpack(meas_result_list_wlan_r13_present, 1)); - if (meas_result_for_rssi_r13_present) { - meas_result_for_rssi_r13 = make_copy_ptr(meas_result_for_rssi_r13_s()); + meas_result_list_wlan_r13.set_present(meas_result_list_wlan_r13_present); + if (meas_result_for_rssi_r13.is_present()) { HANDLE_CODE(meas_result_for_rssi_r13->unpack(bref)); } - if (meas_result_serv_freq_list_ext_r13_present) { - meas_result_serv_freq_list_ext_r13 = make_copy_ptr(meas_result_serv_freq_list_ext_r13_l()); + if (meas_result_serv_freq_list_ext_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_serv_freq_list_ext_r13, bref, 1, 32)); } - if (meas_result_sstd_r13_present) { - meas_result_sstd_r13 = make_copy_ptr(meas_result_sstd_r13_s()); + if (meas_result_sstd_r13.is_present()) { HANDLE_CODE(meas_result_sstd_r13->unpack(bref)); } - if (meas_result_pcell_v1310_present) { - meas_result_pcell_v1310 = make_copy_ptr(meas_result_pcell_v1310_s_()); + if (meas_result_pcell_v1310.is_present()) { HANDLE_CODE( unpack_unalign_integer(meas_result_pcell_v1310->rs_sinr_result_r13, bref, (uint8_t)0, (uint8_t)127)); } - if (ul_pdcp_delay_result_list_r13_present) { - ul_pdcp_delay_result_list_r13 = make_copy_ptr(ul_pdcp_delay_result_list_r13_l()); + if (ul_pdcp_delay_result_list_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*ul_pdcp_delay_result_list_r13, bref, 1, 6)); } - if (meas_result_list_wlan_r13_present) { - meas_result_list_wlan_r13 = make_copy_ptr(meas_result_list_wlan_r13_l()); + if (meas_result_list_wlan_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_wlan_r13, bref, 1, 8)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_result_pcell_v1360_present, 1)); if (meas_result_pcell_v1360_present) { @@ -91602,50 +90560,57 @@ SRSASN_CODE meas_results_s::unpack(bit_ref& bref) } } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_list_cbr_r14_present; HANDLE_CODE(bref.unpack(meas_result_list_cbr_r14_present, 1)); + meas_result_list_cbr_r14.set_present(meas_result_list_cbr_r14_present); + bool meas_result_list_wlan_r14_present; HANDLE_CODE(bref.unpack(meas_result_list_wlan_r14_present, 1)); - if (meas_result_list_cbr_r14_present) { - meas_result_list_cbr_r14 = make_copy_ptr(meas_result_list_cbr_r14_l()); + meas_result_list_wlan_r14.set_present(meas_result_list_wlan_r14_present); + if (meas_result_list_cbr_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_cbr_r14, bref, 1, 72)); } - if (meas_result_list_wlan_r14_present) { - meas_result_list_wlan_r14 = make_copy_ptr(meas_result_list_wlan_r14_l()); + if (meas_result_list_wlan_r14.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_wlan_r14, bref, 1, 32)); } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool meas_result_serv_freq_list_nr_r15_present; HANDLE_CODE(bref.unpack(meas_result_serv_freq_list_nr_r15_present, 1)); + meas_result_serv_freq_list_nr_r15.set_present(meas_result_serv_freq_list_nr_r15_present); + bool meas_result_cell_list_sftd_r15_present; HANDLE_CODE(bref.unpack(meas_result_cell_list_sftd_r15_present, 1)); - if (meas_result_serv_freq_list_nr_r15_present) { - meas_result_serv_freq_list_nr_r15 = make_copy_ptr(meas_result_serv_freq_list_nr_r15_l()); + meas_result_cell_list_sftd_r15.set_present(meas_result_cell_list_sftd_r15_present); + if (meas_result_serv_freq_list_nr_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_serv_freq_list_nr_r15, bref, 1, 32)); } - if (meas_result_cell_list_sftd_r15_present) { - meas_result_cell_list_sftd_r15 = make_copy_ptr(meas_result_cell_list_sftd_r15_l()); + if (meas_result_cell_list_sftd_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_cell_list_sftd_r15, bref, 1, 3)); } } if (group_flags[7]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool log_meas_result_list_bt_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_bt_r15_present, 1)); + log_meas_result_list_bt_r15.set_present(log_meas_result_list_bt_r15_present); + bool log_meas_result_list_wlan_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_wlan_r15_present, 1)); + log_meas_result_list_wlan_r15.set_present(log_meas_result_list_wlan_r15_present); + bool meas_result_sensing_r15_present; HANDLE_CODE(bref.unpack(meas_result_sensing_r15_present, 1)); + meas_result_sensing_r15.set_present(meas_result_sensing_r15_present); HANDLE_CODE(bref.unpack(height_ue_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { - log_meas_result_list_bt_r15 = make_copy_ptr(log_meas_result_list_bt_r15_l()); + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_bt_r15, bref, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { - log_meas_result_list_wlan_r15 = make_copy_ptr(log_meas_result_list_wlan_r15_l()); + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_wlan_r15, bref, 1, 32)); } - if (meas_result_sensing_r15_present) { - meas_result_sensing_r15 = make_copy_ptr(meas_result_sensing_r15_s()); + if (meas_result_sensing_r15.is_present()) { HANDLE_CODE(meas_result_sensing_r15->unpack(bref)); } if (height_ue_r15_present) { @@ -91669,20 +90634,15 @@ void meas_results_s::to_json(json_writer& j) const meas_result_neigh_cells.to_json(j); } if (ext) { - rrc_asn1_warn_assert( - meas_result_for_ecid_r9_present != (meas_result_for_ecid_r9.get() != NULL), __FILE__, __LINE__); - if (meas_result_for_ecid_r9_present) { + if (meas_result_for_ecid_r9.is_present()) { j.write_fieldname("measResultForECID-r9"); meas_result_for_ecid_r9->to_json(j); } - rrc_asn1_warn_assert(location_info_r10_present != (location_info_r10.get() != NULL), __FILE__, __LINE__); - if (location_info_r10_present) { + if (location_info_r10.is_present()) { j.write_fieldname("locationInfo-r10"); location_info_r10->to_json(j); } - rrc_asn1_warn_assert( - meas_result_serv_freq_list_r10_present != (meas_result_serv_freq_list_r10.get() != NULL), __FILE__, __LINE__); - if (meas_result_serv_freq_list_r10_present) { + if (meas_result_serv_freq_list_r10.is_present()) { j.start_array("measResultServFreqList-r10"); for (uint32_t i1 = 0; i1 < meas_result_serv_freq_list_r10->size(); ++i1) { ((*meas_result_serv_freq_list_r10)[i1]).to_json(j); @@ -91695,57 +90655,42 @@ void meas_results_s::to_json(json_writer& j) const if (meas_result_pcell_v1250_present) { j.write_int("measResultPCell-v1250", meas_result_pcell_v1250); } - rrc_asn1_warn_assert( - meas_result_csi_rs_list_r12_present != (meas_result_csi_rs_list_r12.get() != NULL), __FILE__, __LINE__); - if (meas_result_csi_rs_list_r12_present) { + if (meas_result_csi_rs_list_r12.is_present()) { j.start_array("measResultCSI-RS-List-r12"); for (uint32_t i1 = 0; i1 < meas_result_csi_rs_list_r12->size(); ++i1) { ((*meas_result_csi_rs_list_r12)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_result_for_rssi_r13_present != (meas_result_for_rssi_r13.get() != NULL), __FILE__, __LINE__); - if (meas_result_for_rssi_r13_present) { + if (meas_result_for_rssi_r13.is_present()) { j.write_fieldname("measResultForRSSI-r13"); meas_result_for_rssi_r13->to_json(j); } - rrc_asn1_warn_assert(meas_result_serv_freq_list_ext_r13_present != - (meas_result_serv_freq_list_ext_r13.get() != NULL), - __FILE__, - __LINE__); - if (meas_result_serv_freq_list_ext_r13_present) { + if (meas_result_serv_freq_list_ext_r13.is_present()) { j.start_array("measResultServFreqListExt-r13"); for (uint32_t i1 = 0; i1 < meas_result_serv_freq_list_ext_r13->size(); ++i1) { ((*meas_result_serv_freq_list_ext_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(meas_result_sstd_r13_present != (meas_result_sstd_r13.get() != NULL), __FILE__, __LINE__); - if (meas_result_sstd_r13_present) { + if (meas_result_sstd_r13.is_present()) { j.write_fieldname("measResultSSTD-r13"); meas_result_sstd_r13->to_json(j); } - rrc_asn1_warn_assert( - meas_result_pcell_v1310_present != (meas_result_pcell_v1310.get() != NULL), __FILE__, __LINE__); - if (meas_result_pcell_v1310_present) { + if (meas_result_pcell_v1310.is_present()) { j.write_fieldname("measResultPCell-v1310"); j.start_obj(); j.write_int("rs-sinr-Result-r13", meas_result_pcell_v1310->rs_sinr_result_r13); j.end_obj(); } - rrc_asn1_warn_assert( - ul_pdcp_delay_result_list_r13_present != (ul_pdcp_delay_result_list_r13.get() != NULL), __FILE__, __LINE__); - if (ul_pdcp_delay_result_list_r13_present) { + if (ul_pdcp_delay_result_list_r13.is_present()) { j.start_array("ul-PDCP-DelayResultList-r13"); for (uint32_t i1 = 0; i1 < ul_pdcp_delay_result_list_r13->size(); ++i1) { ((*ul_pdcp_delay_result_list_r13)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_result_list_wlan_r13_present != (meas_result_list_wlan_r13.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_wlan_r13_present) { + if (meas_result_list_wlan_r13.is_present()) { j.start_array("measResultListWLAN-r13"); for (uint32_t i1 = 0; i1 < meas_result_list_wlan_r13->size(); ++i1) { ((*meas_result_list_wlan_r13)[i1]).to_json(j); @@ -91755,64 +90700,49 @@ void meas_results_s::to_json(json_writer& j) const if (meas_result_pcell_v1360_present) { j.write_int("measResultPCell-v1360", meas_result_pcell_v1360); } - rrc_asn1_warn_assert( - meas_result_list_cbr_r14_present != (meas_result_list_cbr_r14.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_cbr_r14_present) { + if (meas_result_list_cbr_r14.is_present()) { j.start_array("measResultListCBR-r14"); for (uint32_t i1 = 0; i1 < meas_result_list_cbr_r14->size(); ++i1) { ((*meas_result_list_cbr_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_result_list_wlan_r14_present != (meas_result_list_wlan_r14.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_wlan_r14_present) { + if (meas_result_list_wlan_r14.is_present()) { j.start_array("measResultListWLAN-r14"); for (uint32_t i1 = 0; i1 < meas_result_list_wlan_r14->size(); ++i1) { ((*meas_result_list_wlan_r14)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(meas_result_serv_freq_list_nr_r15_present != (meas_result_serv_freq_list_nr_r15.get() != NULL), - __FILE__, - __LINE__); - if (meas_result_serv_freq_list_nr_r15_present) { + if (meas_result_serv_freq_list_nr_r15.is_present()) { j.start_array("measResultServFreqListNR-r15"); for (uint32_t i1 = 0; i1 < meas_result_serv_freq_list_nr_r15->size(); ++i1) { ((*meas_result_serv_freq_list_nr_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_result_cell_list_sftd_r15_present != (meas_result_cell_list_sftd_r15.get() != NULL), __FILE__, __LINE__); - if (meas_result_cell_list_sftd_r15_present) { + if (meas_result_cell_list_sftd_r15.is_present()) { j.start_array("measResultCellListSFTD-r15"); for (uint32_t i1 = 0; i1 < meas_result_cell_list_sftd_r15->size(); ++i1) { ((*meas_result_cell_list_sftd_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_bt_r15_present) { + if (log_meas_result_list_bt_r15.is_present()) { j.start_array("logMeasResultListBT-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_bt_r15->size(); ++i1) { ((*log_meas_result_list_bt_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { j.start_array("logMeasResultListWLAN-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_wlan_r15->size(); ++i1) { ((*log_meas_result_list_wlan_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - meas_result_sensing_r15_present != (meas_result_sensing_r15.get() != NULL), __FILE__, __LINE__); - if (meas_result_sensing_r15_present) { + if (meas_result_sensing_r15.is_present()) { j.write_fieldname("measResultSensing-r15"); meas_result_sensing_r15->to_json(j); } @@ -92129,60 +91059,43 @@ SRSASN_CODE rlf_report_r9_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(7); - rrc_asn1_warn_assert(location_info_r10_present != (location_info_r10.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= location_info_r10_present; - rrc_asn1_warn_assert(failed_pcell_id_r10_present != (failed_pcell_id_r10.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= failed_pcell_id_r10_present; - rrc_asn1_warn_assert(reest_cell_id_r10_present != (reest_cell_id_r10.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= reest_cell_id_r10_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= location_info_r10.is_present(); + group_flags[0] |= failed_pcell_id_r10.is_present(); + group_flags[0] |= reest_cell_id_r10.is_present(); group_flags[0] |= time_conn_fail_r10_present; group_flags[0] |= conn_fail_type_r10_present; - rrc_asn1_warn_assert(prev_pcell_id_r10_present != (prev_pcell_id_r10.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= prev_pcell_id_r10_present; - rrc_asn1_warn_assert(failed_pcell_id_v1090_present != (failed_pcell_id_v1090.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= failed_pcell_id_v1090_present; - rrc_asn1_warn_assert(basic_fields_r11_present != (basic_fields_r11.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= basic_fields_r11_present; - rrc_asn1_warn_assert(prev_utra_cell_id_r11_present != (prev_utra_cell_id_r11.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= prev_utra_cell_id_r11_present; - rrc_asn1_warn_assert(sel_utra_cell_id_r11_present != (sel_utra_cell_id_r11.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= sel_utra_cell_id_r11_present; - rrc_asn1_warn_assert(failed_pcell_id_v1250_present != (failed_pcell_id_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= failed_pcell_id_v1250_present; + group_flags[0] |= prev_pcell_id_r10.is_present(); + group_flags[1] |= failed_pcell_id_v1090.is_present(); + group_flags[2] |= basic_fields_r11.is_present(); + group_flags[2] |= prev_utra_cell_id_r11.is_present(); + group_flags[2] |= sel_utra_cell_id_r11.is_present(); + group_flags[3] |= failed_pcell_id_v1250.is_present(); group_flags[3] |= meas_result_last_serv_cell_v1250_present; - rrc_asn1_warn_assert( - last_serv_cell_rsrq_type_r12_present != (last_serv_cell_rsrq_type_r12.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= last_serv_cell_rsrq_type_r12_present; - rrc_asn1_warn_assert( - meas_result_list_eutra_v1250_present != (meas_result_list_eutra_v1250.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= meas_result_list_eutra_v1250_present; + group_flags[3] |= last_serv_cell_rsrq_type_r12.is_present(); + group_flags[3] |= meas_result_list_eutra_v1250.is_present(); group_flags[4] |= drb_established_with_qci_minus1_r13_present; group_flags[5] |= meas_result_last_serv_cell_v1360_present; - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= log_meas_result_list_bt_r15_present; - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - group_flags[6] |= log_meas_result_list_wlan_r15_present; + group_flags[6] |= log_meas_result_list_bt_r15.is_present(); + group_flags[6] |= log_meas_result_list_wlan_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(location_info_r10_present, 1)); - HANDLE_CODE(bref.pack(failed_pcell_id_r10_present, 1)); - HANDLE_CODE(bref.pack(reest_cell_id_r10_present, 1)); + HANDLE_CODE(bref.pack(location_info_r10.is_present(), 1)); + HANDLE_CODE(bref.pack(failed_pcell_id_r10.is_present(), 1)); + HANDLE_CODE(bref.pack(reest_cell_id_r10.is_present(), 1)); HANDLE_CODE(bref.pack(time_conn_fail_r10_present, 1)); HANDLE_CODE(bref.pack(conn_fail_type_r10_present, 1)); - HANDLE_CODE(bref.pack(prev_pcell_id_r10_present, 1)); - if (location_info_r10_present) { + HANDLE_CODE(bref.pack(prev_pcell_id_r10.is_present(), 1)); + if (location_info_r10.is_present()) { HANDLE_CODE(location_info_r10->pack(bref)); } - if (failed_pcell_id_r10_present) { + if (failed_pcell_id_r10.is_present()) { HANDLE_CODE(failed_pcell_id_r10->pack(bref)); } - if (reest_cell_id_r10_present) { + if (reest_cell_id_r10.is_present()) { HANDLE_CODE(reest_cell_id_r10->pack(bref)); } if (time_conn_fail_r10_present) { @@ -92191,31 +91104,31 @@ SRSASN_CODE rlf_report_r9_s::pack(bit_ref& bref) const if (conn_fail_type_r10_present) { HANDLE_CODE(pack_enum(bref, conn_fail_type_r10)); } - if (prev_pcell_id_r10_present) { + if (prev_pcell_id_r10.is_present()) { HANDLE_CODE(prev_pcell_id_r10->pack(bref)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(failed_pcell_id_v1090_present, 1)); - if (failed_pcell_id_v1090_present) { + HANDLE_CODE(bref.pack(failed_pcell_id_v1090.is_present(), 1)); + if (failed_pcell_id_v1090.is_present()) { HANDLE_CODE( pack_unalign_integer(bref, failed_pcell_id_v1090->carrier_freq_v1090, (uint32_t)65536, (uint32_t)262143)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(basic_fields_r11_present, 1)); - HANDLE_CODE(bref.pack(prev_utra_cell_id_r11_present, 1)); - HANDLE_CODE(bref.pack(sel_utra_cell_id_r11_present, 1)); - if (basic_fields_r11_present) { + HANDLE_CODE(bref.pack(basic_fields_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(prev_utra_cell_id_r11.is_present(), 1)); + HANDLE_CODE(bref.pack(sel_utra_cell_id_r11.is_present(), 1)); + if (basic_fields_r11.is_present()) { HANDLE_CODE(basic_fields_r11->c_rnti_r11.pack(bref)); HANDLE_CODE(pack_enum(bref, basic_fields_r11->rlf_cause_r11)); HANDLE_CODE(pack_unalign_integer(bref, basic_fields_r11->time_since_fail_r11, (uint32_t)0, (uint32_t)172800)); } - if (prev_utra_cell_id_r11_present) { + if (prev_utra_cell_id_r11.is_present()) { HANDLE_CODE(bref.pack(prev_utra_cell_id_r11->cell_global_id_r11_present, 1)); HANDLE_CODE(pack_unalign_integer(bref, prev_utra_cell_id_r11->carrier_freq_r11, (uint16_t)0, (uint16_t)16383)); HANDLE_CODE(prev_utra_cell_id_r11->pci_r11.pack(bref)); @@ -92223,38 +91136,38 @@ SRSASN_CODE rlf_report_r9_s::pack(bit_ref& bref) const HANDLE_CODE(prev_utra_cell_id_r11->cell_global_id_r11.pack(bref)); } } - if (sel_utra_cell_id_r11_present) { + if (sel_utra_cell_id_r11.is_present()) { HANDLE_CODE(pack_unalign_integer(bref, sel_utra_cell_id_r11->carrier_freq_r11, (uint16_t)0, (uint16_t)16383)); HANDLE_CODE(sel_utra_cell_id_r11->pci_r11.pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(failed_pcell_id_v1250_present, 1)); + HANDLE_CODE(bref.pack(failed_pcell_id_v1250.is_present(), 1)); HANDLE_CODE(bref.pack(meas_result_last_serv_cell_v1250_present, 1)); - HANDLE_CODE(bref.pack(last_serv_cell_rsrq_type_r12_present, 1)); - HANDLE_CODE(bref.pack(meas_result_list_eutra_v1250_present, 1)); - if (failed_pcell_id_v1250_present) { + HANDLE_CODE(bref.pack(last_serv_cell_rsrq_type_r12.is_present(), 1)); + HANDLE_CODE(bref.pack(meas_result_list_eutra_v1250.is_present(), 1)); + if (failed_pcell_id_v1250.is_present()) { HANDLE_CODE(failed_pcell_id_v1250->tac_failed_pcell_r12.pack(bref)); } if (meas_result_last_serv_cell_v1250_present) { HANDLE_CODE(pack_unalign_integer(bref, meas_result_last_serv_cell_v1250, (int8_t)-30, (int8_t)46)); } - if (last_serv_cell_rsrq_type_r12_present) { + if (last_serv_cell_rsrq_type_r12.is_present()) { HANDLE_CODE(last_serv_cell_rsrq_type_r12->pack(bref)); } - if (meas_result_list_eutra_v1250_present) { + if (meas_result_list_eutra_v1250.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *meas_result_list_eutra_v1250, 1, 8)); } } if (group_flags[4]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(drb_established_with_qci_minus1_r13_present, 1)); } if (group_flags[5]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(meas_result_last_serv_cell_v1360_present, 1)); if (meas_result_last_serv_cell_v1360_present) { @@ -92262,14 +91175,14 @@ SRSASN_CODE rlf_report_r9_s::pack(bit_ref& bref) const } } if (group_flags[6]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15_present, 1)); - HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { + HANDLE_CODE(bref.pack(log_meas_result_list_bt_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(log_meas_result_list_wlan_r15.is_present(), 1)); + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_bt_r15, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *log_meas_result_list_wlan_r15, 1, 32)); } } @@ -92306,28 +91219,33 @@ SRSASN_CODE rlf_report_r9_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(7); + ext_groups_unpacker_guard group_flags(7); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool location_info_r10_present; HANDLE_CODE(bref.unpack(location_info_r10_present, 1)); + location_info_r10.set_present(location_info_r10_present); + bool failed_pcell_id_r10_present; HANDLE_CODE(bref.unpack(failed_pcell_id_r10_present, 1)); + failed_pcell_id_r10.set_present(failed_pcell_id_r10_present); + bool reest_cell_id_r10_present; HANDLE_CODE(bref.unpack(reest_cell_id_r10_present, 1)); + reest_cell_id_r10.set_present(reest_cell_id_r10_present); HANDLE_CODE(bref.unpack(time_conn_fail_r10_present, 1)); HANDLE_CODE(bref.unpack(conn_fail_type_r10_present, 1)); + bool prev_pcell_id_r10_present; HANDLE_CODE(bref.unpack(prev_pcell_id_r10_present, 1)); - if (location_info_r10_present) { - location_info_r10 = make_copy_ptr(location_info_r10_s()); + prev_pcell_id_r10.set_present(prev_pcell_id_r10_present); + if (location_info_r10.is_present()) { HANDLE_CODE(location_info_r10->unpack(bref)); } - if (failed_pcell_id_r10_present) { - failed_pcell_id_r10 = make_copy_ptr(failed_pcell_id_r10_c_()); + if (failed_pcell_id_r10.is_present()) { HANDLE_CODE(failed_pcell_id_r10->unpack(bref)); } - if (reest_cell_id_r10_present) { - reest_cell_id_r10 = make_copy_ptr(cell_global_id_eutra_s()); + if (reest_cell_id_r10.is_present()) { HANDLE_CODE(reest_cell_id_r10->unpack(bref)); } if (time_conn_fail_r10_present) { @@ -92336,35 +91254,39 @@ SRSASN_CODE rlf_report_r9_s::unpack(bit_ref& bref) if (conn_fail_type_r10_present) { HANDLE_CODE(unpack_enum(conn_fail_type_r10, bref)); } - if (prev_pcell_id_r10_present) { - prev_pcell_id_r10 = make_copy_ptr(cell_global_id_eutra_s()); + if (prev_pcell_id_r10.is_present()) { HANDLE_CODE(prev_pcell_id_r10->unpack(bref)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool failed_pcell_id_v1090_present; HANDLE_CODE(bref.unpack(failed_pcell_id_v1090_present, 1)); - if (failed_pcell_id_v1090_present) { - failed_pcell_id_v1090 = make_copy_ptr(failed_pcell_id_v1090_s_()); + failed_pcell_id_v1090.set_present(failed_pcell_id_v1090_present); + if (failed_pcell_id_v1090.is_present()) { HANDLE_CODE( unpack_unalign_integer(failed_pcell_id_v1090->carrier_freq_v1090, bref, (uint32_t)65536, (uint32_t)262143)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool basic_fields_r11_present; HANDLE_CODE(bref.unpack(basic_fields_r11_present, 1)); + basic_fields_r11.set_present(basic_fields_r11_present); + bool prev_utra_cell_id_r11_present; HANDLE_CODE(bref.unpack(prev_utra_cell_id_r11_present, 1)); + prev_utra_cell_id_r11.set_present(prev_utra_cell_id_r11_present); + bool sel_utra_cell_id_r11_present; HANDLE_CODE(bref.unpack(sel_utra_cell_id_r11_present, 1)); - if (basic_fields_r11_present) { - basic_fields_r11 = make_copy_ptr(basic_fields_r11_s_()); + sel_utra_cell_id_r11.set_present(sel_utra_cell_id_r11_present); + if (basic_fields_r11.is_present()) { HANDLE_CODE(basic_fields_r11->c_rnti_r11.unpack(bref)); HANDLE_CODE(unpack_enum(basic_fields_r11->rlf_cause_r11, bref)); HANDLE_CODE(unpack_unalign_integer(basic_fields_r11->time_since_fail_r11, bref, (uint32_t)0, (uint32_t)172800)); } - if (prev_utra_cell_id_r11_present) { - prev_utra_cell_id_r11 = make_copy_ptr(prev_utra_cell_id_r11_s_()); + if (prev_utra_cell_id_r11.is_present()) { HANDLE_CODE(bref.unpack(prev_utra_cell_id_r11->cell_global_id_r11_present, 1)); HANDLE_CODE( unpack_unalign_integer(prev_utra_cell_id_r11->carrier_freq_r11, bref, (uint16_t)0, (uint16_t)16383)); @@ -92373,42 +91295,44 @@ SRSASN_CODE rlf_report_r9_s::unpack(bit_ref& bref) HANDLE_CODE(prev_utra_cell_id_r11->cell_global_id_r11.unpack(bref)); } } - if (sel_utra_cell_id_r11_present) { - sel_utra_cell_id_r11 = make_copy_ptr(sel_utra_cell_id_r11_s_()); + if (sel_utra_cell_id_r11.is_present()) { HANDLE_CODE(unpack_unalign_integer(sel_utra_cell_id_r11->carrier_freq_r11, bref, (uint16_t)0, (uint16_t)16383)); HANDLE_CODE(sel_utra_cell_id_r11->pci_r11.unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool failed_pcell_id_v1250_present; HANDLE_CODE(bref.unpack(failed_pcell_id_v1250_present, 1)); + failed_pcell_id_v1250.set_present(failed_pcell_id_v1250_present); HANDLE_CODE(bref.unpack(meas_result_last_serv_cell_v1250_present, 1)); + bool last_serv_cell_rsrq_type_r12_present; HANDLE_CODE(bref.unpack(last_serv_cell_rsrq_type_r12_present, 1)); + last_serv_cell_rsrq_type_r12.set_present(last_serv_cell_rsrq_type_r12_present); + bool meas_result_list_eutra_v1250_present; HANDLE_CODE(bref.unpack(meas_result_list_eutra_v1250_present, 1)); - if (failed_pcell_id_v1250_present) { - failed_pcell_id_v1250 = make_copy_ptr(failed_pcell_id_v1250_s_()); + meas_result_list_eutra_v1250.set_present(meas_result_list_eutra_v1250_present); + if (failed_pcell_id_v1250.is_present()) { HANDLE_CODE(failed_pcell_id_v1250->tac_failed_pcell_r12.unpack(bref)); } if (meas_result_last_serv_cell_v1250_present) { HANDLE_CODE(unpack_unalign_integer(meas_result_last_serv_cell_v1250, bref, (int8_t)-30, (int8_t)46)); } - if (last_serv_cell_rsrq_type_r12_present) { - last_serv_cell_rsrq_type_r12 = make_copy_ptr(rsrq_type_r12_s()); + if (last_serv_cell_rsrq_type_r12.is_present()) { HANDLE_CODE(last_serv_cell_rsrq_type_r12->unpack(bref)); } - if (meas_result_list_eutra_v1250_present) { - meas_result_list_eutra_v1250 = make_copy_ptr(meas_result_list2_eutra_v1250_l()); + if (meas_result_list_eutra_v1250.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*meas_result_list_eutra_v1250, bref, 1, 8)); } } if (group_flags[4]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(drb_established_with_qci_minus1_r13_present, 1)); } if (group_flags[5]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(meas_result_last_serv_cell_v1360_present, 1)); if (meas_result_last_serv_cell_v1360_present) { @@ -92416,16 +91340,18 @@ SRSASN_CODE rlf_report_r9_s::unpack(bit_ref& bref) } } if (group_flags[6]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool log_meas_result_list_bt_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_bt_r15_present, 1)); + log_meas_result_list_bt_r15.set_present(log_meas_result_list_bt_r15_present); + bool log_meas_result_list_wlan_r15_present; HANDLE_CODE(bref.unpack(log_meas_result_list_wlan_r15_present, 1)); - if (log_meas_result_list_bt_r15_present) { - log_meas_result_list_bt_r15 = make_copy_ptr(log_meas_result_list_bt_r15_l()); + log_meas_result_list_wlan_r15.set_present(log_meas_result_list_wlan_r15_present); + if (log_meas_result_list_bt_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_bt_r15, bref, 1, 32)); } - if (log_meas_result_list_wlan_r15_present) { - log_meas_result_list_wlan_r15 = make_copy_ptr(log_meas_result_list_wlan_r15_l()); + if (log_meas_result_list_wlan_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*log_meas_result_list_wlan_r15, bref, 1, 32)); } } @@ -92476,18 +91402,15 @@ void rlf_report_r9_s::to_json(json_writer& j) const j.end_obj(); } if (ext) { - rrc_asn1_warn_assert(location_info_r10_present != (location_info_r10.get() != NULL), __FILE__, __LINE__); - if (location_info_r10_present) { + if (location_info_r10.is_present()) { j.write_fieldname("locationInfo-r10"); location_info_r10->to_json(j); } - rrc_asn1_warn_assert(failed_pcell_id_r10_present != (failed_pcell_id_r10.get() != NULL), __FILE__, __LINE__); - if (failed_pcell_id_r10_present) { + if (failed_pcell_id_r10.is_present()) { j.write_fieldname("failedPCellId-r10"); failed_pcell_id_r10->to_json(j); } - rrc_asn1_warn_assert(reest_cell_id_r10_present != (reest_cell_id_r10.get() != NULL), __FILE__, __LINE__); - if (reest_cell_id_r10_present) { + if (reest_cell_id_r10.is_present()) { j.write_fieldname("reestablishmentCellId-r10"); reest_cell_id_r10->to_json(j); } @@ -92497,20 +91420,17 @@ void rlf_report_r9_s::to_json(json_writer& j) const if (conn_fail_type_r10_present) { j.write_str("connectionFailureType-r10", conn_fail_type_r10.to_string()); } - rrc_asn1_warn_assert(prev_pcell_id_r10_present != (prev_pcell_id_r10.get() != NULL), __FILE__, __LINE__); - if (prev_pcell_id_r10_present) { + if (prev_pcell_id_r10.is_present()) { j.write_fieldname("previousPCellId-r10"); prev_pcell_id_r10->to_json(j); } - rrc_asn1_warn_assert(failed_pcell_id_v1090_present != (failed_pcell_id_v1090.get() != NULL), __FILE__, __LINE__); - if (failed_pcell_id_v1090_present) { + if (failed_pcell_id_v1090.is_present()) { j.write_fieldname("failedPCellId-v1090"); j.start_obj(); j.write_int("carrierFreq-v1090", failed_pcell_id_v1090->carrier_freq_v1090); j.end_obj(); } - rrc_asn1_warn_assert(basic_fields_r11_present != (basic_fields_r11.get() != NULL), __FILE__, __LINE__); - if (basic_fields_r11_present) { + if (basic_fields_r11.is_present()) { j.write_fieldname("basicFields-r11"); j.start_obj(); j.write_str("c-RNTI-r11", basic_fields_r11->c_rnti_r11.to_string()); @@ -92518,8 +91438,7 @@ void rlf_report_r9_s::to_json(json_writer& j) const j.write_int("timeSinceFailure-r11", basic_fields_r11->time_since_fail_r11); j.end_obj(); } - rrc_asn1_warn_assert(prev_utra_cell_id_r11_present != (prev_utra_cell_id_r11.get() != NULL), __FILE__, __LINE__); - if (prev_utra_cell_id_r11_present) { + if (prev_utra_cell_id_r11.is_present()) { j.write_fieldname("previousUTRA-CellId-r11"); j.start_obj(); j.write_int("carrierFreq-r11", prev_utra_cell_id_r11->carrier_freq_r11); @@ -92531,8 +91450,7 @@ void rlf_report_r9_s::to_json(json_writer& j) const } j.end_obj(); } - rrc_asn1_warn_assert(sel_utra_cell_id_r11_present != (sel_utra_cell_id_r11.get() != NULL), __FILE__, __LINE__); - if (sel_utra_cell_id_r11_present) { + if (sel_utra_cell_id_r11.is_present()) { j.write_fieldname("selectedUTRA-CellId-r11"); j.start_obj(); j.write_int("carrierFreq-r11", sel_utra_cell_id_r11->carrier_freq_r11); @@ -92540,8 +91458,7 @@ void rlf_report_r9_s::to_json(json_writer& j) const sel_utra_cell_id_r11->pci_r11.to_json(j); j.end_obj(); } - rrc_asn1_warn_assert(failed_pcell_id_v1250_present != (failed_pcell_id_v1250.get() != NULL), __FILE__, __LINE__); - if (failed_pcell_id_v1250_present) { + if (failed_pcell_id_v1250.is_present()) { j.write_fieldname("failedPCellId-v1250"); j.start_obj(); j.write_str("tac-FailedPCell-r12", failed_pcell_id_v1250->tac_failed_pcell_r12.to_string()); @@ -92550,15 +91467,11 @@ void rlf_report_r9_s::to_json(json_writer& j) const if (meas_result_last_serv_cell_v1250_present) { j.write_int("measResultLastServCell-v1250", meas_result_last_serv_cell_v1250); } - rrc_asn1_warn_assert( - last_serv_cell_rsrq_type_r12_present != (last_serv_cell_rsrq_type_r12.get() != NULL), __FILE__, __LINE__); - if (last_serv_cell_rsrq_type_r12_present) { + if (last_serv_cell_rsrq_type_r12.is_present()) { j.write_fieldname("lastServCellRSRQ-Type-r12"); last_serv_cell_rsrq_type_r12->to_json(j); } - rrc_asn1_warn_assert( - meas_result_list_eutra_v1250_present != (meas_result_list_eutra_v1250.get() != NULL), __FILE__, __LINE__); - if (meas_result_list_eutra_v1250_present) { + if (meas_result_list_eutra_v1250.is_present()) { j.start_array("measResultListEUTRA-v1250"); for (uint32_t i1 = 0; i1 < meas_result_list_eutra_v1250->size(); ++i1) { ((*meas_result_list_eutra_v1250)[i1]).to_json(j); @@ -92571,18 +91484,14 @@ void rlf_report_r9_s::to_json(json_writer& j) const if (meas_result_last_serv_cell_v1360_present) { j.write_int("measResultLastServCell-v1360", meas_result_last_serv_cell_v1360); } - rrc_asn1_warn_assert( - log_meas_result_list_bt_r15_present != (log_meas_result_list_bt_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_bt_r15_present) { + if (log_meas_result_list_bt_r15.is_present()) { j.start_array("logMeasResultListBT-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_bt_r15->size(); ++i1) { ((*log_meas_result_list_bt_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - log_meas_result_list_wlan_r15_present != (log_meas_result_list_wlan_r15.get() != NULL), __FILE__, __LINE__); - if (log_meas_result_list_wlan_r15_present) { + if (log_meas_result_list_wlan_r15.is_present()) { j.start_array("logMeasResultListWLAN-r15"); for (uint32_t i1 = 0; i1 < log_meas_result_list_wlan_r15->size(); ++i1) { ((*log_meas_result_list_wlan_r15)[i1]).to_json(j); @@ -113191,19 +112100,15 @@ SRSASN_CODE ue_eutra_cap_add_xdd_mode_v1060_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(otdoa_positioning_capabilities_r10_present != - (otdoa_positioning_capabilities_r10.get() != NULL), - __FILE__, - __LINE__); - group_flags[0] |= otdoa_positioning_capabilities_r10_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= otdoa_positioning_capabilities_r10.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(otdoa_positioning_capabilities_r10_present, 1)); - if (otdoa_positioning_capabilities_r10_present) { + HANDLE_CODE(bref.pack(otdoa_positioning_capabilities_r10.is_present(), 1)); + if (otdoa_positioning_capabilities_r10.is_present()) { HANDLE_CODE(otdoa_positioning_capabilities_r10->pack(bref)); } } @@ -113232,15 +112137,16 @@ SRSASN_CODE ue_eutra_cap_add_xdd_mode_v1060_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool otdoa_positioning_capabilities_r10_present; HANDLE_CODE(bref.unpack(otdoa_positioning_capabilities_r10_present, 1)); - if (otdoa_positioning_capabilities_r10_present) { - otdoa_positioning_capabilities_r10 = make_copy_ptr(otdoa_positioning_capabilities_r10_s()); + otdoa_positioning_capabilities_r10.set_present(otdoa_positioning_capabilities_r10_present); + if (otdoa_positioning_capabilities_r10.is_present()) { HANDLE_CODE(otdoa_positioning_capabilities_r10->unpack(bref)); } } @@ -113266,11 +112172,7 @@ void ue_eutra_cap_add_xdd_mode_v1060_s::to_json(json_writer& j) const inter_rat_params_utra_tdd_v1060.to_json(j); } if (ext) { - rrc_asn1_warn_assert(otdoa_positioning_capabilities_r10_present != - (otdoa_positioning_capabilities_r10.get() != NULL), - __FILE__, - __LINE__); - if (otdoa_positioning_capabilities_r10_present) { + if (otdoa_positioning_capabilities_r10.is_present()) { j.write_fieldname("otdoa-PositioningCapabilities-r10"); otdoa_positioning_capabilities_r10->to_json(j); } @@ -114413,20 +113315,16 @@ SRSASN_CODE as_cfg_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, source_dl_carrier_freq, (uint16_t)0, (uint16_t)65535)); if (ext) { - ext_groups_header group_flags(4); + ext_groups_packer_guard group_flags; group_flags[0] |= source_sib_type1_ext_present; - group_flags[0] |= source_other_cfg_r9.get() != NULL; - rrc_asn1_warn_assert( - source_scell_cfg_list_r10_present != (source_scell_cfg_list_r10.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= source_scell_cfg_list_r10_present; - rrc_asn1_warn_assert(source_cfg_scg_r12_present != (source_cfg_scg_r12.get() != NULL), __FILE__, __LINE__); - group_flags[2] |= source_cfg_scg_r12_present; - rrc_asn1_warn_assert(as_cfg_nr_r15_present != (as_cfg_nr_r15.get() != NULL), __FILE__, __LINE__); - group_flags[3] |= as_cfg_nr_r15_present; + group_flags[0] |= source_other_cfg_r9.is_present(); + group_flags[1] |= source_scell_cfg_list_r10.is_present(); + group_flags[2] |= source_cfg_scg_r12.is_present(); + group_flags[3] |= as_cfg_nr_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(source_sib_type1_ext_present, 1)); if (source_sib_type1_ext_present) { @@ -114435,26 +113333,26 @@ SRSASN_CODE as_cfg_s::pack(bit_ref& bref) const HANDLE_CODE(source_other_cfg_r9->pack(bref)); } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(source_scell_cfg_list_r10_present, 1)); - if (source_scell_cfg_list_r10_present) { + HANDLE_CODE(bref.pack(source_scell_cfg_list_r10.is_present(), 1)); + if (source_scell_cfg_list_r10.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *source_scell_cfg_list_r10, 1, 4)); } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(source_cfg_scg_r12_present, 1)); - if (source_cfg_scg_r12_present) { + HANDLE_CODE(bref.pack(source_cfg_scg_r12.is_present(), 1)); + if (source_cfg_scg_r12.is_present()) { HANDLE_CODE(source_cfg_scg_r12->pack(bref)); } } if (group_flags[3]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(as_cfg_nr_r15_present, 1)); - if (as_cfg_nr_r15_present) { + HANDLE_CODE(bref.pack(as_cfg_nr_r15.is_present(), 1)); + if (as_cfg_nr_r15.is_present()) { HANDLE_CODE(as_cfg_nr_r15->pack(bref)); } } @@ -114475,43 +113373,45 @@ SRSASN_CODE as_cfg_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(source_dl_carrier_freq, bref, (uint16_t)0, (uint16_t)65535)); if (ext) { - ext_groups_header group_flags(4); + ext_groups_unpacker_guard group_flags(4); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(source_sib_type1_ext_present, 1)); if (source_sib_type1_ext_present) { HANDLE_CODE(source_sib_type1_ext.unpack(bref)); } - source_other_cfg_r9 = make_copy_ptr(other_cfg_r9_s()); HANDLE_CODE(source_other_cfg_r9->unpack(bref)); } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool source_scell_cfg_list_r10_present; HANDLE_CODE(bref.unpack(source_scell_cfg_list_r10_present, 1)); - if (source_scell_cfg_list_r10_present) { - source_scell_cfg_list_r10 = make_copy_ptr(scell_to_add_mod_list_r10_l()); + source_scell_cfg_list_r10.set_present(source_scell_cfg_list_r10_present); + if (source_scell_cfg_list_r10.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*source_scell_cfg_list_r10, bref, 1, 4)); } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool source_cfg_scg_r12_present; HANDLE_CODE(bref.unpack(source_cfg_scg_r12_present, 1)); - if (source_cfg_scg_r12_present) { - source_cfg_scg_r12 = make_copy_ptr(scg_cfg_r12_s()); + source_cfg_scg_r12.set_present(source_cfg_scg_r12_present); + if (source_cfg_scg_r12.is_present()) { HANDLE_CODE(source_cfg_scg_r12->unpack(bref)); } } if (group_flags[3]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool as_cfg_nr_r15_present; HANDLE_CODE(bref.unpack(as_cfg_nr_r15_present, 1)); - if (as_cfg_nr_r15_present) { - as_cfg_nr_r15 = make_copy_ptr(as_cfg_nr_r15_s()); + as_cfg_nr_r15.set_present(as_cfg_nr_r15_present); + if (as_cfg_nr_r15.is_present()) { HANDLE_CODE(as_cfg_nr_r15->unpack(bref)); } } @@ -114543,22 +113443,18 @@ void as_cfg_s::to_json(json_writer& j) const } j.write_fieldname("sourceOtherConfig-r9"); source_other_cfg_r9->to_json(j); - rrc_asn1_warn_assert( - source_scell_cfg_list_r10_present != (source_scell_cfg_list_r10.get() != NULL), __FILE__, __LINE__); - if (source_scell_cfg_list_r10_present) { + if (source_scell_cfg_list_r10.is_present()) { j.start_array("sourceSCellConfigList-r10"); for (uint32_t i1 = 0; i1 < source_scell_cfg_list_r10->size(); ++i1) { ((*source_scell_cfg_list_r10)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert(source_cfg_scg_r12_present != (source_cfg_scg_r12.get() != NULL), __FILE__, __LINE__); - if (source_cfg_scg_r12_present) { + if (source_cfg_scg_r12.is_present()) { j.write_fieldname("sourceConfigSCG-r12"); source_cfg_scg_r12->to_json(j); } - rrc_asn1_warn_assert(as_cfg_nr_r15_present != (as_cfg_nr_r15.get() != NULL), __FILE__, __LINE__); - if (as_cfg_nr_r15_present) { + if (as_cfg_nr_r15.is_present()) { j.write_fieldname("as-ConfigNR-r15"); as_cfg_nr_r15->to_json(j); } @@ -114894,13 +113790,13 @@ SRSASN_CODE as_context_v1130_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); + ext_groups_packer_guard group_flags; group_flags[0] |= sidelink_ue_info_r12_present; group_flags[1] |= source_context_en_dc_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sidelink_ue_info_r12_present, 1)); if (sidelink_ue_info_r12_present) { @@ -114908,7 +113804,7 @@ SRSASN_CODE as_context_v1130_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(source_context_en_dc_r15_present, 1)); if (source_context_en_dc_r15_present) { @@ -114936,11 +113832,11 @@ SRSASN_CODE as_context_v1130_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sidelink_ue_info_r12_present, 1)); if (sidelink_ue_info_r12_present) { @@ -114948,7 +113844,7 @@ SRSASN_CODE as_context_v1130_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(source_context_en_dc_r15_present, 1)); if (source_context_en_dc_r15_present) { @@ -115028,14 +113924,14 @@ SRSASN_CODE candidate_cell_info_r10_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(3); + ext_groups_packer_guard group_flags; group_flags[0] |= dl_carrier_freq_v1090_present; group_flags[1] |= rsrq_result_v1250_present; group_flags[2] |= rs_sinr_result_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(dl_carrier_freq_v1090_present, 1)); if (dl_carrier_freq_v1090_present) { @@ -115043,7 +113939,7 @@ SRSASN_CODE candidate_cell_info_r10_s::pack(bit_ref& bref) const } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(rsrq_result_v1250_present, 1)); if (rsrq_result_v1250_present) { @@ -115051,7 +113947,7 @@ SRSASN_CODE candidate_cell_info_r10_s::pack(bit_ref& bref) const } } if (group_flags[2]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(rs_sinr_result_r13_present, 1)); if (rs_sinr_result_r13_present) { @@ -115077,11 +113973,11 @@ SRSASN_CODE candidate_cell_info_r10_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(3); + ext_groups_unpacker_guard group_flags(3); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(dl_carrier_freq_v1090_present, 1)); if (dl_carrier_freq_v1090_present) { @@ -115089,7 +113985,7 @@ SRSASN_CODE candidate_cell_info_r10_s::unpack(bit_ref& bref) } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(rsrq_result_v1250_present, 1)); if (rsrq_result_v1250_present) { @@ -115097,7 +113993,7 @@ SRSASN_CODE candidate_cell_info_r10_s::unpack(bit_ref& bref) } } if (group_flags[2]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(rs_sinr_result_r13_present, 1)); if (rs_sinr_result_r13_present) { @@ -115150,22 +114046,20 @@ SRSASN_CODE cell_to_add_mod_r12_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= s_cell_idx_r13_present; - rrc_asn1_warn_assert( - meas_result_cell_to_add_v1310_present != (meas_result_cell_to_add_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= meas_result_cell_to_add_v1310_present; + group_flags[0] |= meas_result_cell_to_add_v1310.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(s_cell_idx_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_result_cell_to_add_v1310_present, 1)); + HANDLE_CODE(bref.pack(meas_result_cell_to_add_v1310.is_present(), 1)); if (s_cell_idx_r13_present) { HANDLE_CODE(pack_unalign_integer(bref, s_cell_idx_r13, (uint8_t)1, (uint8_t)31)); } - if (meas_result_cell_to_add_v1310_present) { + if (meas_result_cell_to_add_v1310.is_present()) { HANDLE_CODE( pack_unalign_integer(bref, meas_result_cell_to_add_v1310->rs_sinr_result_r13, (uint8_t)0, (uint8_t)127)); } @@ -115190,19 +114084,20 @@ SRSASN_CODE cell_to_add_mod_r12_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(s_cell_idx_r13_present, 1)); + bool meas_result_cell_to_add_v1310_present; HANDLE_CODE(bref.unpack(meas_result_cell_to_add_v1310_present, 1)); + meas_result_cell_to_add_v1310.set_present(meas_result_cell_to_add_v1310_present); if (s_cell_idx_r13_present) { HANDLE_CODE(unpack_unalign_integer(s_cell_idx_r13, bref, (uint8_t)1, (uint8_t)31)); } - if (meas_result_cell_to_add_v1310_present) { - meas_result_cell_to_add_v1310 = make_copy_ptr(meas_result_cell_to_add_v1310_s_()); + if (meas_result_cell_to_add_v1310.is_present()) { HANDLE_CODE( unpack_unalign_integer(meas_result_cell_to_add_v1310->rs_sinr_result_r13, bref, (uint8_t)0, (uint8_t)127)); } @@ -115232,9 +114127,7 @@ void cell_to_add_mod_r12_s::to_json(json_writer& j) const if (s_cell_idx_r13_present) { j.write_int("sCellIndex-r13", s_cell_idx_r13); } - rrc_asn1_warn_assert( - meas_result_cell_to_add_v1310_present != (meas_result_cell_to_add_v1310.get() != NULL), __FILE__, __LINE__); - if (meas_result_cell_to_add_v1310_present) { + if (meas_result_cell_to_add_v1310.is_present()) { j.write_fieldname("measResultCellToAdd-v1310"); j.start_obj(); j.write_int("rs-sinr-Result-r13", meas_result_cell_to_add_v1310->rs_sinr_result_r13); @@ -116270,28 +115163,24 @@ SRSASN_CODE rrm_cfg_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(2); - rrc_asn1_warn_assert( - candidate_cell_info_list_r10_present != (candidate_cell_info_list_r10.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= candidate_cell_info_list_r10_present; - rrc_asn1_warn_assert( - candidate_cell_info_list_nr_r15_present != (candidate_cell_info_list_nr_r15.get() != NULL), __FILE__, __LINE__); - group_flags[1] |= candidate_cell_info_list_nr_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= candidate_cell_info_list_r10.is_present(); + group_flags[1] |= candidate_cell_info_list_nr_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(candidate_cell_info_list_r10_present, 1)); - if (candidate_cell_info_list_r10_present) { + HANDLE_CODE(bref.pack(candidate_cell_info_list_r10.is_present(), 1)); + if (candidate_cell_info_list_r10.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *candidate_cell_info_list_r10, 1, 8)); } } if (group_flags[1]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(candidate_cell_info_list_nr_r15_present, 1)); - if (candidate_cell_info_list_nr_r15_present) { + HANDLE_CODE(bref.pack(candidate_cell_info_list_nr_r15.is_present(), 1)); + if (candidate_cell_info_list_nr_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *candidate_cell_info_list_nr_r15, 1, 32)); } } @@ -116308,24 +115197,26 @@ SRSASN_CODE rrm_cfg_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(2); + ext_groups_unpacker_guard group_flags(2); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool candidate_cell_info_list_r10_present; HANDLE_CODE(bref.unpack(candidate_cell_info_list_r10_present, 1)); - if (candidate_cell_info_list_r10_present) { - candidate_cell_info_list_r10 = make_copy_ptr(candidate_cell_info_list_r10_l()); + candidate_cell_info_list_r10.set_present(candidate_cell_info_list_r10_present); + if (candidate_cell_info_list_r10.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*candidate_cell_info_list_r10, bref, 1, 8)); } } if (group_flags[1]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool candidate_cell_info_list_nr_r15_present; HANDLE_CODE(bref.unpack(candidate_cell_info_list_nr_r15_present, 1)); - if (candidate_cell_info_list_nr_r15_present) { - candidate_cell_info_list_nr_r15 = make_copy_ptr(meas_result_serv_freq_list_nr_r15_l()); + candidate_cell_info_list_nr_r15.set_present(candidate_cell_info_list_nr_r15_present); + if (candidate_cell_info_list_nr_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*candidate_cell_info_list_nr_r15, bref, 1, 32)); } } @@ -116339,18 +115230,14 @@ void rrm_cfg_s::to_json(json_writer& j) const j.write_str("ue-InactiveTime", ue_inactive_time.to_string()); } if (ext) { - rrc_asn1_warn_assert( - candidate_cell_info_list_r10_present != (candidate_cell_info_list_r10.get() != NULL), __FILE__, __LINE__); - if (candidate_cell_info_list_r10_present) { + if (candidate_cell_info_list_r10.is_present()) { j.start_array("candidateCellInfoList-r10"); for (uint32_t i1 = 0; i1 < candidate_cell_info_list_r10->size(); ++i1) { ((*candidate_cell_info_list_r10)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - candidate_cell_info_list_nr_r15_present != (candidate_cell_info_list_nr_r15.get() != NULL), __FILE__, __LINE__); - if (candidate_cell_info_list_nr_r15_present) { + if (candidate_cell_info_list_nr_r15.is_present()) { j.start_array("candidateCellInfoListNR-r15"); for (uint32_t i1 = 0; i1 < candidate_cell_info_list_nr_r15->size(); ++i1) { ((*candidate_cell_info_list_nr_r15)[i1]).to_json(j); @@ -116816,22 +115703,20 @@ SRSASN_CODE meas_result_serv_cell_scg_r12_s::pack(bit_ref& bref) const HANDLE_CODE(pack_unalign_integer(bref, meas_result_scell_r12.rsrq_result_scell_r12, (uint8_t)0, (uint8_t)34)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= serv_cell_id_r13_present; - rrc_asn1_warn_assert( - meas_result_scell_v1310_present != (meas_result_scell_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= meas_result_scell_v1310_present; + group_flags[0] |= meas_result_scell_v1310.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(serv_cell_id_r13_present, 1)); - HANDLE_CODE(bref.pack(meas_result_scell_v1310_present, 1)); + HANDLE_CODE(bref.pack(meas_result_scell_v1310.is_present(), 1)); if (serv_cell_id_r13_present) { HANDLE_CODE(pack_unalign_integer(bref, serv_cell_id_r13, (uint8_t)0, (uint8_t)31)); } - if (meas_result_scell_v1310_present) { + if (meas_result_scell_v1310.is_present()) { HANDLE_CODE( pack_unalign_integer(bref, meas_result_scell_v1310->rs_sinr_result_scell_r13, (uint8_t)0, (uint8_t)127)); } @@ -116847,19 +115732,20 @@ SRSASN_CODE meas_result_serv_cell_scg_r12_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_unalign_integer(meas_result_scell_r12.rsrq_result_scell_r12, bref, (uint8_t)0, (uint8_t)34)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(serv_cell_id_r13_present, 1)); + bool meas_result_scell_v1310_present; HANDLE_CODE(bref.unpack(meas_result_scell_v1310_present, 1)); + meas_result_scell_v1310.set_present(meas_result_scell_v1310_present); if (serv_cell_id_r13_present) { HANDLE_CODE(unpack_unalign_integer(serv_cell_id_r13, bref, (uint8_t)0, (uint8_t)31)); } - if (meas_result_scell_v1310_present) { - meas_result_scell_v1310 = make_copy_ptr(meas_result_scell_v1310_s_()); + if (meas_result_scell_v1310.is_present()) { HANDLE_CODE( unpack_unalign_integer(meas_result_scell_v1310->rs_sinr_result_scell_r13, bref, (uint8_t)0, (uint8_t)127)); } @@ -116880,9 +115766,7 @@ void meas_result_serv_cell_scg_r12_s::to_json(json_writer& j) const if (serv_cell_id_r13_present) { j.write_int("servCellId-r13", serv_cell_id_r13); } - rrc_asn1_warn_assert( - meas_result_scell_v1310_present != (meas_result_scell_v1310.get() != NULL), __FILE__, __LINE__); - if (meas_result_scell_v1310_present) { + if (meas_result_scell_v1310.is_present()) { j.write_fieldname("measResultSCell-v1310"); j.start_obj(); j.write_int("rs-sinr-ResultSCell-r13", meas_result_scell_v1310->rs_sinr_result_scell_r13); @@ -117788,16 +116672,15 @@ SRSASN_CODE sl_precfg_comm_pool_r12_s::pack(bit_ref& bref) const HANDLE_CODE(trpt_subset_r12.pack(bref)); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(prio_list_r13_present != (prio_list_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= prio_list_r13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= prio_list_r13.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(prio_list_r13_present, 1)); - if (prio_list_r13_present) { + HANDLE_CODE(bref.pack(prio_list_r13.is_present(), 1)); + if (prio_list_r13.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *prio_list_r13, 1, 8, UnalignedIntegerPacker(1, 8))); } } @@ -117818,15 +116701,16 @@ SRSASN_CODE sl_precfg_comm_pool_r12_s::unpack(bit_ref& bref) HANDLE_CODE(trpt_subset_r12.unpack(bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool prio_list_r13_present; HANDLE_CODE(bref.unpack(prio_list_r13_present, 1)); - if (prio_list_r13_present) { - prio_list_r13 = make_copy_ptr(sl_prio_list_r13_l()); + prio_list_r13.set_present(prio_list_r13_present); + if (prio_list_r13.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*prio_list_r13, bref, 1, 8, UnalignedIntegerPacker(1, 8))); } } @@ -117849,8 +116733,7 @@ void sl_precfg_comm_pool_r12_s::to_json(json_writer& j) const j.write_int("dataTxParameters-r12", data_tx_params_r12); j.write_str("trpt-Subset-r12", trpt_subset_r12.to_string()); if (ext) { - rrc_asn1_warn_assert(prio_list_r13_present != (prio_list_r13.get() != NULL), __FILE__, __LINE__); - if (prio_list_r13_present) { + if (prio_list_r13.is_present()) { j.start_array("priorityList-r13"); for (uint32_t i1 = 0; i1 < prio_list_r13->size(); ++i1) { j.write_int(((*prio_list_r13)[i1])); @@ -117934,12 +116817,12 @@ SRSASN_CODE sl_precfg_general_r12_s::pack(bit_ref& bref) const HANDLE_CODE(reserved_r12.pack(bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= add_spec_emission_v1440_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(add_spec_emission_v1440_present, 1)); if (add_spec_emission_v1440_present) { @@ -117967,11 +116850,11 @@ SRSASN_CODE sl_precfg_general_r12_s::unpack(bit_ref& bref) HANDLE_CODE(reserved_r12.unpack(bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(add_spec_emission_v1440_present, 1)); if (add_spec_emission_v1440_present) { @@ -118044,12 +116927,12 @@ SRSASN_CODE sl_precfg_sync_r12_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, sync_ref_diff_hyst_r12)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= sync_tx_periodic_r13_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(sync_tx_periodic_r13_present, 1)); } @@ -118069,11 +116952,11 @@ SRSASN_CODE sl_precfg_sync_r12_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(sync_ref_diff_hyst_r12, bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(sync_tx_periodic_r13_present, 1)); } @@ -118144,24 +117027,20 @@ SRSASN_CODE sl_v2x_precfg_comm_pool_r14_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - sl_min_t2_value_list_r15_present != (sl_min_t2_value_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= sl_min_t2_value_list_r15_present; - rrc_asn1_warn_assert( - cbr_pssch_tx_cfg_list_v1530_present != (cbr_pssch_tx_cfg_list_v1530.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= cbr_pssch_tx_cfg_list_v1530_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= sl_min_t2_value_list_r15.is_present(); + group_flags[0] |= cbr_pssch_tx_cfg_list_v1530.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(sl_min_t2_value_list_r15_present, 1)); - HANDLE_CODE(bref.pack(cbr_pssch_tx_cfg_list_v1530_present, 1)); - if (sl_min_t2_value_list_r15_present) { + HANDLE_CODE(bref.pack(sl_min_t2_value_list_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(cbr_pssch_tx_cfg_list_v1530.is_present(), 1)); + if (sl_min_t2_value_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *sl_min_t2_value_list_r15, 1, 8)); } - if (cbr_pssch_tx_cfg_list_v1530_present) { + if (cbr_pssch_tx_cfg_list_v1530.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *cbr_pssch_tx_cfg_list_v1530, 1, 8)); } } @@ -118212,20 +117091,22 @@ SRSASN_CODE sl_v2x_precfg_comm_pool_r14_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool sl_min_t2_value_list_r15_present; HANDLE_CODE(bref.unpack(sl_min_t2_value_list_r15_present, 1)); + sl_min_t2_value_list_r15.set_present(sl_min_t2_value_list_r15_present); + bool cbr_pssch_tx_cfg_list_v1530_present; HANDLE_CODE(bref.unpack(cbr_pssch_tx_cfg_list_v1530_present, 1)); - if (sl_min_t2_value_list_r15_present) { - sl_min_t2_value_list_r15 = make_copy_ptr(sl_min_t2_value_list_r15_l()); + cbr_pssch_tx_cfg_list_v1530.set_present(cbr_pssch_tx_cfg_list_v1530_present); + if (sl_min_t2_value_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*sl_min_t2_value_list_r15, bref, 1, 8)); } - if (cbr_pssch_tx_cfg_list_v1530_present) { - cbr_pssch_tx_cfg_list_v1530 = make_copy_ptr(sl_cbr_pppp_tx_precfg_list_v1530_l()); + if (cbr_pssch_tx_cfg_list_v1530.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*cbr_pssch_tx_cfg_list_v1530, bref, 1, 8)); } } @@ -118278,18 +117159,14 @@ void sl_v2x_precfg_comm_pool_r14_s::to_json(json_writer& j) const j.end_array(); } if (ext) { - rrc_asn1_warn_assert( - sl_min_t2_value_list_r15_present != (sl_min_t2_value_list_r15.get() != NULL), __FILE__, __LINE__); - if (sl_min_t2_value_list_r15_present) { + if (sl_min_t2_value_list_r15.is_present()) { j.start_array("sl-MinT2ValueList-r15"); for (uint32_t i1 = 0; i1 < sl_min_t2_value_list_r15->size(); ++i1) { ((*sl_min_t2_value_list_r15)[i1]).to_json(j); } j.end_array(); } - rrc_asn1_warn_assert( - cbr_pssch_tx_cfg_list_v1530_present != (cbr_pssch_tx_cfg_list_v1530.get() != NULL), __FILE__, __LINE__); - if (cbr_pssch_tx_cfg_list_v1530_present) { + if (cbr_pssch_tx_cfg_list_v1530.is_present()) { j.start_array("cbr-pssch-TxConfigList-v1530"); for (uint32_t i1 = 0; i1 < cbr_pssch_tx_cfg_list_v1530->size(); ++i1) { ((*cbr_pssch_tx_cfg_list_v1530)[i1]).to_json(j); @@ -118348,12 +117225,12 @@ SRSASN_CODE sl_precfg_v2x_sync_r14_s::pack(bit_ref& bref) const HANDLE_CODE(pack_enum(bref, sync_ref_diff_hyst_r14)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_packer_guard group_flags; group_flags[0] |= slss_tx_disabled_r15_present; group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); HANDLE_CODE(bref.pack(slss_tx_disabled_r15_present, 1)); } @@ -118371,11 +117248,11 @@ SRSASN_CODE sl_precfg_v2x_sync_r14_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_enum(sync_ref_diff_hyst_r14, bref)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); HANDLE_CODE(bref.unpack(slss_tx_disabled_r15_present, 1)); } @@ -118409,36 +117286,33 @@ SRSASN_CODE sl_precfg_r12_s::pack(bit_ref& bref) const HANDLE_CODE(pack_dyn_seq_of(bref, precfg_comm_r12, 1, 4)); if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert(precfg_comm_v1310_present != (precfg_comm_v1310.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= precfg_comm_v1310_present; - rrc_asn1_warn_assert(precfg_disc_r13_present != (precfg_disc_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= precfg_disc_r13_present; - rrc_asn1_warn_assert(precfg_relay_r13_present != (precfg_relay_r13.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= precfg_relay_r13_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= precfg_comm_v1310.is_present(); + group_flags[0] |= precfg_disc_r13.is_present(); + group_flags[0] |= precfg_relay_r13.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(precfg_comm_v1310_present, 1)); - HANDLE_CODE(bref.pack(precfg_disc_r13_present, 1)); - HANDLE_CODE(bref.pack(precfg_relay_r13_present, 1)); - if (precfg_comm_v1310_present) { + HANDLE_CODE(bref.pack(precfg_comm_v1310.is_present(), 1)); + HANDLE_CODE(bref.pack(precfg_disc_r13.is_present(), 1)); + HANDLE_CODE(bref.pack(precfg_relay_r13.is_present(), 1)); + if (precfg_comm_v1310.is_present()) { HANDLE_CODE(bref.pack(precfg_comm_v1310->comm_tx_pool_list_r13_present, 1)); HANDLE_CODE(pack_dyn_seq_of(bref, precfg_comm_v1310->comm_rx_pool_list_r13, 1, 12)); if (precfg_comm_v1310->comm_tx_pool_list_r13_present) { HANDLE_CODE(pack_dyn_seq_of(bref, precfg_comm_v1310->comm_tx_pool_list_r13, 1, 7)); } } - if (precfg_disc_r13_present) { + if (precfg_disc_r13.is_present()) { HANDLE_CODE(bref.pack(precfg_disc_r13->disc_tx_pool_list_r13_present, 1)); HANDLE_CODE(pack_dyn_seq_of(bref, precfg_disc_r13->disc_rx_pool_list_r13, 1, 16)); if (precfg_disc_r13->disc_tx_pool_list_r13_present) { HANDLE_CODE(pack_dyn_seq_of(bref, precfg_disc_r13->disc_tx_pool_list_r13, 1, 4)); } } - if (precfg_relay_r13_present) { + if (precfg_relay_r13.is_present()) { HANDLE_CODE(precfg_relay_r13->pack(bref)); } } @@ -118453,33 +117327,36 @@ SRSASN_CODE sl_precfg_r12_s::unpack(bit_ref& bref) HANDLE_CODE(unpack_dyn_seq_of(precfg_comm_r12, bref, 1, 4)); if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool precfg_comm_v1310_present; HANDLE_CODE(bref.unpack(precfg_comm_v1310_present, 1)); + precfg_comm_v1310.set_present(precfg_comm_v1310_present); + bool precfg_disc_r13_present; HANDLE_CODE(bref.unpack(precfg_disc_r13_present, 1)); + precfg_disc_r13.set_present(precfg_disc_r13_present); + bool precfg_relay_r13_present; HANDLE_CODE(bref.unpack(precfg_relay_r13_present, 1)); - if (precfg_comm_v1310_present) { - precfg_comm_v1310 = make_copy_ptr(precfg_comm_v1310_s_()); + precfg_relay_r13.set_present(precfg_relay_r13_present); + if (precfg_comm_v1310.is_present()) { HANDLE_CODE(bref.unpack(precfg_comm_v1310->comm_tx_pool_list_r13_present, 1)); HANDLE_CODE(unpack_dyn_seq_of(precfg_comm_v1310->comm_rx_pool_list_r13, bref, 1, 12)); if (precfg_comm_v1310->comm_tx_pool_list_r13_present) { HANDLE_CODE(unpack_dyn_seq_of(precfg_comm_v1310->comm_tx_pool_list_r13, bref, 1, 7)); } } - if (precfg_disc_r13_present) { - precfg_disc_r13 = make_copy_ptr(precfg_disc_r13_s_()); + if (precfg_disc_r13.is_present()) { HANDLE_CODE(bref.unpack(precfg_disc_r13->disc_tx_pool_list_r13_present, 1)); HANDLE_CODE(unpack_dyn_seq_of(precfg_disc_r13->disc_rx_pool_list_r13, bref, 1, 16)); if (precfg_disc_r13->disc_tx_pool_list_r13_present) { HANDLE_CODE(unpack_dyn_seq_of(precfg_disc_r13->disc_tx_pool_list_r13, bref, 1, 4)); } } - if (precfg_relay_r13_present) { - precfg_relay_r13 = make_copy_ptr(sl_precfg_relay_r13_s()); + if (precfg_relay_r13.is_present()) { HANDLE_CODE(precfg_relay_r13->unpack(bref)); } } @@ -118499,8 +117376,7 @@ void sl_precfg_r12_s::to_json(json_writer& j) const } j.end_array(); if (ext) { - rrc_asn1_warn_assert(precfg_comm_v1310_present != (precfg_comm_v1310.get() != NULL), __FILE__, __LINE__); - if (precfg_comm_v1310_present) { + if (precfg_comm_v1310.is_present()) { j.write_fieldname("preconfigComm-v1310"); j.start_obj(); j.start_array("commRxPoolList-r13"); @@ -118517,8 +117393,7 @@ void sl_precfg_r12_s::to_json(json_writer& j) const } j.end_obj(); } - rrc_asn1_warn_assert(precfg_disc_r13_present != (precfg_disc_r13.get() != NULL), __FILE__, __LINE__); - if (precfg_disc_r13_present) { + if (precfg_disc_r13.is_present()) { j.write_fieldname("preconfigDisc-r13"); j.start_obj(); j.start_array("discRxPoolList-r13"); @@ -118535,8 +117410,7 @@ void sl_precfg_r12_s::to_json(json_writer& j) const } j.end_obj(); } - rrc_asn1_warn_assert(precfg_relay_r13_present != (precfg_relay_r13.get() != NULL), __FILE__, __LINE__); - if (precfg_relay_r13_present) { + if (precfg_relay_r13.is_present()) { j.write_fieldname("preconfigRelay-r13"); precfg_relay_r13->to_json(j); } @@ -118576,17 +117450,15 @@ SRSASN_CODE sl_v2x_precfg_freq_info_r14_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - v2x_freq_sel_cfg_list_r15_present != (v2x_freq_sel_cfg_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= v2x_freq_sel_cfg_list_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= v2x_freq_sel_cfg_list_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(v2x_freq_sel_cfg_list_r15_present, 1)); - if (v2x_freq_sel_cfg_list_r15_present) { + HANDLE_CODE(bref.pack(v2x_freq_sel_cfg_list_r15.is_present(), 1)); + if (v2x_freq_sel_cfg_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *v2x_freq_sel_cfg_list_r15, 1, 8)); } } @@ -118624,15 +117496,16 @@ SRSASN_CODE sl_v2x_precfg_freq_info_r14_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool v2x_freq_sel_cfg_list_r15_present; HANDLE_CODE(bref.unpack(v2x_freq_sel_cfg_list_r15_present, 1)); - if (v2x_freq_sel_cfg_list_r15_present) { - v2x_freq_sel_cfg_list_r15 = make_copy_ptr(sl_v2x_freq_sel_cfg_list_r15_l()); + v2x_freq_sel_cfg_list_r15.set_present(v2x_freq_sel_cfg_list_r15_present); + if (v2x_freq_sel_cfg_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*v2x_freq_sel_cfg_list_r15, bref, 1, 8)); } } @@ -118679,9 +117552,7 @@ void sl_v2x_precfg_freq_info_r14_s::to_json(json_writer& j) const j.write_int("offsetDFN-r14", offset_dfn_r14); } if (ext) { - rrc_asn1_warn_assert( - v2x_freq_sel_cfg_list_r15_present != (v2x_freq_sel_cfg_list_r15.get() != NULL), __FILE__, __LINE__); - if (v2x_freq_sel_cfg_list_r15_present) { + if (v2x_freq_sel_cfg_list_r15.is_present()) { j.start_array("v2x-FreqSelectionConfigList-r15"); for (uint32_t i1 = 0; i1 < v2x_freq_sel_cfg_list_r15->size(); ++i1) { ((*v2x_freq_sel_cfg_list_r15)[i1]).to_json(j); @@ -118708,32 +117579,27 @@ SRSASN_CODE sl_v2x_precfg_r14_s::pack(bit_ref& bref) const } if (ext) { - ext_groups_header group_flags(1); - rrc_asn1_warn_assert( - v2x_packet_dupl_cfg_r15_present != (v2x_packet_dupl_cfg_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= v2x_packet_dupl_cfg_r15_present; - rrc_asn1_warn_assert(sync_freq_list_r15_present != (sync_freq_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= sync_freq_list_r15_present; + ext_groups_packer_guard group_flags; + group_flags[0] |= v2x_packet_dupl_cfg_r15.is_present(); + group_flags[0] |= sync_freq_list_r15.is_present(); group_flags[0] |= slss_tx_multi_freq_r15_present; - rrc_asn1_warn_assert( - v2x_tx_profile_list_r15_present != (v2x_tx_profile_list_r15.get() != NULL), __FILE__, __LINE__); - group_flags[0] |= v2x_tx_profile_list_r15_present; + group_flags[0] |= v2x_tx_profile_list_r15.is_present(); group_flags.pack(bref); if (group_flags[0]) { - varlength_field_pack_guard packer(bref); + varlength_field_pack_guard varlen_scope(bref); - HANDLE_CODE(bref.pack(v2x_packet_dupl_cfg_r15_present, 1)); - HANDLE_CODE(bref.pack(sync_freq_list_r15_present, 1)); + HANDLE_CODE(bref.pack(v2x_packet_dupl_cfg_r15.is_present(), 1)); + HANDLE_CODE(bref.pack(sync_freq_list_r15.is_present(), 1)); HANDLE_CODE(bref.pack(slss_tx_multi_freq_r15_present, 1)); - HANDLE_CODE(bref.pack(v2x_tx_profile_list_r15_present, 1)); - if (v2x_packet_dupl_cfg_r15_present) { + HANDLE_CODE(bref.pack(v2x_tx_profile_list_r15.is_present(), 1)); + if (v2x_packet_dupl_cfg_r15.is_present()) { HANDLE_CODE(v2x_packet_dupl_cfg_r15->pack(bref)); } - if (sync_freq_list_r15_present) { + if (sync_freq_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *sync_freq_list_r15, 1, 8, UnalignedIntegerPacker(0, 262143))); } - if (v2x_tx_profile_list_r15_present) { + if (v2x_tx_profile_list_r15.is_present()) { HANDLE_CODE(pack_dyn_seq_of(bref, *v2x_tx_profile_list_r15, 1, 256, EnumPacker())); } } @@ -118756,26 +117622,29 @@ SRSASN_CODE sl_v2x_precfg_r14_s::unpack(bit_ref& bref) } if (ext) { - ext_groups_header group_flags(1); + ext_groups_unpacker_guard group_flags(1); group_flags.unpack(bref); if (group_flags[0]) { - varlength_field_unpack_guard unpacker(bref); + varlength_field_unpack_guard varlen_scope(bref); + bool v2x_packet_dupl_cfg_r15_present; HANDLE_CODE(bref.unpack(v2x_packet_dupl_cfg_r15_present, 1)); + v2x_packet_dupl_cfg_r15.set_present(v2x_packet_dupl_cfg_r15_present); + bool sync_freq_list_r15_present; HANDLE_CODE(bref.unpack(sync_freq_list_r15_present, 1)); + sync_freq_list_r15.set_present(sync_freq_list_r15_present); HANDLE_CODE(bref.unpack(slss_tx_multi_freq_r15_present, 1)); + bool v2x_tx_profile_list_r15_present; HANDLE_CODE(bref.unpack(v2x_tx_profile_list_r15_present, 1)); - if (v2x_packet_dupl_cfg_r15_present) { - v2x_packet_dupl_cfg_r15 = make_copy_ptr(sl_v2x_packet_dupl_cfg_r15_s()); + v2x_tx_profile_list_r15.set_present(v2x_tx_profile_list_r15_present); + if (v2x_packet_dupl_cfg_r15.is_present()) { HANDLE_CODE(v2x_packet_dupl_cfg_r15->unpack(bref)); } - if (sync_freq_list_r15_present) { - sync_freq_list_r15 = make_copy_ptr(sl_v2x_sync_freq_list_r15_l()); + if (sync_freq_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*sync_freq_list_r15, bref, 1, 8, UnalignedIntegerPacker(0, 262143))); } - if (v2x_tx_profile_list_r15_present) { - v2x_tx_profile_list_r15 = make_copy_ptr(sl_v2x_tx_profile_list_r15_l()); + if (v2x_tx_profile_list_r15.is_present()) { HANDLE_CODE(unpack_dyn_seq_of(*v2x_tx_profile_list_r15, bref, 1, 256, EnumPacker())); } } @@ -118802,14 +117671,11 @@ void sl_v2x_precfg_r14_s::to_json(json_writer& j) const cbr_precfg_list_r14.to_json(j); } if (ext) { - rrc_asn1_warn_assert( - v2x_packet_dupl_cfg_r15_present != (v2x_packet_dupl_cfg_r15.get() != NULL), __FILE__, __LINE__); - if (v2x_packet_dupl_cfg_r15_present) { + if (v2x_packet_dupl_cfg_r15.is_present()) { j.write_fieldname("v2x-PacketDuplicationConfig-r15"); v2x_packet_dupl_cfg_r15->to_json(j); } - rrc_asn1_warn_assert(sync_freq_list_r15_present != (sync_freq_list_r15.get() != NULL), __FILE__, __LINE__); - if (sync_freq_list_r15_present) { + if (sync_freq_list_r15.is_present()) { j.start_array("syncFreqList-r15"); for (uint32_t i1 = 0; i1 < sync_freq_list_r15->size(); ++i1) { j.write_int(((*sync_freq_list_r15)[i1])); @@ -118819,9 +117685,7 @@ void sl_v2x_precfg_r14_s::to_json(json_writer& j) const if (slss_tx_multi_freq_r15_present) { j.write_str("slss-TxMultiFreq-r15", "true"); } - rrc_asn1_warn_assert( - v2x_tx_profile_list_r15_present != (v2x_tx_profile_list_r15.get() != NULL), __FILE__, __LINE__); - if (v2x_tx_profile_list_r15_present) { + if (v2x_tx_profile_list_r15.is_present()) { j.start_array("v2x-TxProfileList-r15"); for (uint32_t i1 = 0; i1 < v2x_tx_profile_list_r15->size(); ++i1) { j.write_str(((*v2x_tx_profile_list_r15)[i1]).to_string()); diff --git a/lib/src/asn1/rrc_asn1_enum.cc b/lib/src/asn1/rrc_asn1_enum.cc index 6f8cf9d29..72915459b 100644 --- a/lib/src/asn1/rrc_asn1_enum.cc +++ b/lib/src/asn1/rrc_asn1_enum.cc @@ -26,8 +26,8 @@ using namespace asn1; using namespace asn1::rrc; /******************************************************************************* -/* Helper Functions -/******************************************************************************/ + * Helper Functions + ******************************************************************************/ static void invalid_enum_number(int value, const char* name) { @@ -36,8 +36,8 @@ static void invalid_enum_number(int value, const char* name) } /******************************************************************************* -/* Struct Methods -/******************************************************************************/ + * Struct Methods + ******************************************************************************/ std::string phich_cfg_s::phich_dur_opts::to_string() const { diff --git a/lib/src/asn1/rrc_asn1_utils.cc b/lib/src/asn1/rrc_asn1_utils.cc index 55666717d..919a31243 100644 --- a/lib/src/asn1/rrc_asn1_utils.cc +++ b/lib/src/asn1/rrc_asn1_utils.cc @@ -74,6 +74,32 @@ void to_asn1(asn1::rrc::s_tmsi_s* asn1_type, const s_tmsi_t& cfg) asn1_type->m_tmsi.from_number(cfg.m_tmsi); } +/*************************** + * CQI Report Aperiodic + **************************/ + +srslte_cqi_report_mode_t make_aperiodic_mode(const asn1::rrc::cqi_report_mode_aperiodic_e asn_mode) +{ + switch (asn_mode) { + case asn1::rrc::cqi_report_mode_aperiodic_e::rm12: + return SRSLTE_CQI_MODE_12; + case asn1::rrc::cqi_report_mode_aperiodic_e::rm20: + return SRSLTE_CQI_MODE_20; + case asn1::rrc::cqi_report_mode_aperiodic_e::rm22: + return SRSLTE_CQI_MODE_22; + case asn1::rrc::cqi_report_mode_aperiodic_e::rm30: + return SRSLTE_CQI_MODE_30; + case asn1::rrc::cqi_report_mode_aperiodic_e::rm31: + return SRSLTE_CQI_MODE_31; + case asn1::rrc::cqi_report_mode_aperiodic_e::rm10_v1310: + case asn1::rrc::cqi_report_mode_aperiodic_e::rm11_v1310: + case asn1::rrc::cqi_report_mode_aperiodic_e::rm32_v1250: + fprintf(stderr, "Aperiodic mode %s not handled\n", asn_mode.to_string().c_str()); + default: + return SRSLTE_CQI_MODE_NA; + } +} + /*************************** * Establishment Cause **************************/ @@ -155,4 +181,601 @@ void to_asn1(asn1::rrc::rlc_cfg_c* asn1_type, const srslte::rlc_config_t& cfg) } +/*************************** + * MAC Config + **************************/ + +void set_mac_cfg_t_sched_request_cfg(mac_cfg_t* cfg, const asn1::rrc::sched_request_cfg_c& asn1_type) +{ + cfg->sr_cfg.enabled = asn1_type.type() == asn1::rrc::setup_e::setup; + if (cfg->sr_cfg.enabled) { + cfg->sr_cfg.dsr_transmax = asn1_type.setup().dsr_trans_max.to_number(); + } +} + +// MAC-MainConfig section is always present +void set_mac_cfg_t_main_cfg(mac_cfg_t* cfg, const asn1::rrc::mac_main_cfg_s& asn1_type) +{ + // Update values only if each section is present + if (asn1_type.phr_cfg_present) { + cfg->phr_cfg.enabled = asn1_type.phr_cfg.type() == asn1::rrc::setup_e::setup; + if (cfg->phr_cfg.enabled) { + cfg->phr_cfg.prohibit_timer = asn1_type.phr_cfg.setup().prohibit_phr_timer.to_number(); + cfg->phr_cfg.periodic_timer = asn1_type.phr_cfg.setup().periodic_phr_timer.to_number(); + cfg->phr_cfg.db_pathloss_change = asn1_type.phr_cfg.setup().dl_pathloss_change.to_number(); + } + } + if (asn1_type.mac_main_cfg_v1020.is_present()) { + cfg->phr_cfg.extended = asn1_type.mac_main_cfg_v1020.get()->extended_phr_r10_present; + } + if (asn1_type.ul_sch_cfg_present) { + cfg->bsr_cfg.periodic_timer = asn1_type.ul_sch_cfg.periodic_bsr_timer.to_number(); + cfg->bsr_cfg.retx_timer = asn1_type.ul_sch_cfg.retx_bsr_timer.to_number(); + if (asn1_type.ul_sch_cfg.max_harq_tx_present) { + cfg->harq_cfg.max_harq_tx = asn1_type.ul_sch_cfg.max_harq_tx.to_number(); + } + } + // TimeAlignmentDedicated overwrites Common?? + cfg->time_alignment_timer = asn1_type.time_align_timer_ded.to_number(); +} + +// RACH-Common section is always present +void set_mac_cfg_t_rach_cfg_common(mac_cfg_t* cfg, const asn1::rrc::rach_cfg_common_s& asn1_type) +{ + + // Preamble info + cfg->rach_cfg.nof_preambles = asn1_type.preamb_info.nof_ra_preambs.to_number(); + if (asn1_type.preamb_info.preambs_group_a_cfg_present) { + cfg->rach_cfg.nof_groupA_preambles = + asn1_type.preamb_info.preambs_group_a_cfg.size_of_ra_preambs_group_a.to_number(); + cfg->rach_cfg.messageSizeGroupA = asn1_type.preamb_info.preambs_group_a_cfg.msg_size_group_a.to_number(); + cfg->rach_cfg.messagePowerOffsetGroupB = + asn1_type.preamb_info.preambs_group_a_cfg.msg_pwr_offset_group_b.to_number(); + } else { + cfg->rach_cfg.nof_groupA_preambles = 0; + } + + // Power ramping + cfg->rach_cfg.powerRampingStep = asn1_type.pwr_ramp_params.pwr_ramp_step.to_number(); + cfg->rach_cfg.iniReceivedTargetPower = asn1_type.pwr_ramp_params.preamb_init_rx_target_pwr.to_number(); + + // Supervision info + cfg->rach_cfg.preambleTransMax = asn1_type.ra_supervision_info.preamb_trans_max.to_number(); + cfg->rach_cfg.responseWindowSize = asn1_type.ra_supervision_info.ra_resp_win_size.to_number(); + cfg->rach_cfg.contentionResolutionTimer = asn1_type.ra_supervision_info.mac_contention_resolution_timer.to_number(); + + // HARQ Msg3 + cfg->harq_cfg.max_harq_msg3_tx = asn1_type.max_harq_msg3_tx; +} + +void set_mac_cfg_t_time_alignment(mac_cfg_t* cfg, const asn1::rrc::time_align_timer_opts asn1_type) +{ + cfg->time_alignment_timer = asn1_type.to_number(); +} + +void set_phy_cfg_t_dedicated_cfg(phy_cfg_t* cfg, const asn1::rrc::phys_cfg_ded_s& asn1_type) +{ + if (asn1_type.pucch_cfg_ded_present) { + + if (asn1_type.pucch_cfg_ded.tdd_ack_nack_feedback_mode_present) { + cfg->ul_cfg.pucch.tdd_ack_multiplex = asn1_type.pucch_cfg_ded.tdd_ack_nack_feedback_mode == + asn1::rrc::pucch_cfg_ded_s::tdd_ack_nack_feedback_mode_e_::mux; + } else { + cfg->ul_cfg.pucch.tdd_ack_multiplex = false; + } + } + + if (asn1_type.pucch_cfg_ded_v1020.is_present()) { + auto* pucch_cfg_ded = asn1_type.pucch_cfg_ded_v1020.get(); + + if (pucch_cfg_ded->pucch_format_r10_present) { + + typedef asn1::rrc::pucch_cfg_ded_v1020_s::pucch_format_r10_c_ pucch_format_r10_t; + auto* pucch_format_r10 = &pucch_cfg_ded->pucch_format_r10; + + if (pucch_format_r10->type() == pucch_format_r10_t::types::format3_r10) { + // Select feedback mode + cfg->ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3; + + auto* format3_r13 = &pucch_format_r10->format3_r10(); + for (uint32_t n = 0; n < SRSLTE_MIN(format3_r13->n3_pucch_an_list_r13.size(), SRSLTE_PUCCH_SIZE_AN_CS); n++) { + cfg->ul_cfg.pucch.n3_pucch_an_list[n] = format3_r13->n3_pucch_an_list_r13[n]; + } + if (format3_r13->two_ant_port_activ_pucch_format3_r13_present) { + if (format3_r13->two_ant_port_activ_pucch_format3_r13.type() == asn1::rrc::setup_e::setup) { + // TODO: UL MIMO Configure PUCCH two antenna port + } else { + // TODO: UL MIMO Disable two antenna port + } + } + } else if (pucch_format_r10->type() == asn1::rrc::pucch_cfg_ded_v1020_s::pucch_format_r10_c_::types::ch_sel_r10) { + + typedef pucch_format_r10_t::ch_sel_r10_s_ ch_sel_r10_t; + auto* ch_sel_r10 = &pucch_format_r10->ch_sel_r10(); + + if (ch_sel_r10->n1_pucch_an_cs_r10_present) { + typedef ch_sel_r10_t::n1_pucch_an_cs_r10_c_ n1_pucch_an_cs_r10_t; + auto* n1_pucch_an_cs_r10 = &ch_sel_r10->n1_pucch_an_cs_r10; + + if (n1_pucch_an_cs_r10->type() == asn1::rrc::setup_e::setup) { + // Select feedback mode + cfg->ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS; + + typedef n1_pucch_an_cs_r10_t::setup_s_::n1_pucch_an_cs_list_r10_l_ n1_pucch_an_cs_list_r10_t; + n1_pucch_an_cs_list_r10_t n1_pucch_an_cs_list = + ch_sel_r10->n1_pucch_an_cs_r10.setup().n1_pucch_an_cs_list_r10; + for (uint32_t i = 0; i < SRSLTE_MIN(n1_pucch_an_cs_list.size(), SRSLTE_PUCCH_NOF_AN_CS); i++) { + asn1::rrc::n1_pucch_an_cs_r10_l n1_pucch_an_cs = n1_pucch_an_cs_list[i]; + for (uint32_t j = 0; j < SRSLTE_PUCCH_SIZE_AN_CS; j++) { + cfg->ul_cfg.pucch.n1_pucch_an_cs[j][i] = n1_pucch_an_cs[j]; + } + } + } else { + cfg->ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL; + } + } + } else { + // Do nothing + } + } + } + + if (asn1_type.pusch_cfg_ded_present) { + cfg->ul_cfg.pusch.uci_offset.I_offset_ack = asn1_type.pusch_cfg_ded.beta_offset_ack_idx; + cfg->ul_cfg.pusch.uci_offset.I_offset_cqi = asn1_type.pusch_cfg_ded.beta_offset_cqi_idx; + cfg->ul_cfg.pusch.uci_offset.I_offset_ri = asn1_type.pusch_cfg_ded.beta_offset_ri_idx; + } + + if (asn1_type.ul_pwr_ctrl_ded_present) { + cfg->ul_cfg.power_ctrl.p0_ue_pusch = asn1_type.ul_pwr_ctrl_ded.p0_ue_pusch; + cfg->ul_cfg.power_ctrl.delta_mcs_based = + asn1_type.ul_pwr_ctrl_ded.delta_mcs_enabled == asn1::rrc::ul_pwr_ctrl_ded_s::delta_mcs_enabled_e_::en0; + cfg->ul_cfg.power_ctrl.acc_enabled = asn1_type.ul_pwr_ctrl_ded.accumulation_enabled; + cfg->ul_cfg.power_ctrl.p0_ue_pucch = asn1_type.ul_pwr_ctrl_ded.p0_ue_pucch; + cfg->ul_cfg.power_ctrl.p_srs_offset = asn1_type.ul_pwr_ctrl_ded.p_srs_offset; + } + + if (asn1_type.ul_pwr_ctrl_ded.filt_coef_present) { + // TODO + } + + if (asn1_type.tpc_pdcch_cfg_pucch_present) { + // TODO + } + + if (asn1_type.tpc_pdcch_cfg_pusch_present) { + // TODO + } + + if (asn1_type.cqi_report_cfg_present) { + + if (asn1_type.cqi_report_cfg.cqi_report_periodic_present) { + + cfg->dl_cfg.cqi_report.periodic_configured = + asn1_type.cqi_report_cfg.cqi_report_periodic.type() == asn1::rrc::setup_e::setup; + if (cfg->dl_cfg.cqi_report.periodic_configured) { + cfg->ul_cfg.pucch.n_pucch_2 = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx; + cfg->ul_cfg.pucch.simul_cqi_ack = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().simul_ack_nack_and_cqi; + + cfg->dl_cfg.cqi_report.pmi_idx = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx; + cfg->dl_cfg.cqi_report.format_is_subband = + asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.type().value == + asn1::rrc::cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::subband_cqi; + if (cfg->dl_cfg.cqi_report.format_is_subband) { + cfg->dl_cfg.cqi_report.subband_size = + asn1_type.cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.subband_cqi().k; + } + if (asn1_type.cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present) { + cfg->dl_cfg.cqi_report.ri_idx = asn1_type.cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx; + cfg->dl_cfg.cqi_report.ri_idx_present = true; + } else { + cfg->dl_cfg.cqi_report.ri_idx_present = false; + } + } else { + cfg->ul_cfg.pucch.n_pucch_2 = 0; + cfg->ul_cfg.pucch.simul_cqi_ack = false; + } + } + + if (asn1_type.cqi_report_cfg.cqi_report_mode_aperiodic_present) { + + cfg->dl_cfg.cqi_report.aperiodic_configured = true; + cfg->dl_cfg.cqi_report.aperiodic_mode = make_aperiodic_mode(asn1_type.cqi_report_cfg.cqi_report_mode_aperiodic); + } + } + + if (asn1_type.cqi_report_cfg_pcell_v1250.is_present()) { + auto cqi_report_cfg_pcell_v1250 = asn1_type.cqi_report_cfg_pcell_v1250.get(); + if (cqi_report_cfg_pcell_v1250->alt_cqi_table_r12_present) { + cfg->dl_cfg.pdsch.use_tbs_index_alt = true; + } + } else { + cfg->dl_cfg.pdsch.use_tbs_index_alt = false; + } + + if (asn1_type.srs_ul_cfg_ded_present) { + cfg->ul_cfg.srs.dedicated_enabled = asn1_type.srs_ul_cfg_ded.type() == asn1::rrc::setup_e::setup; + if (cfg->ul_cfg.srs.dedicated_enabled) { + cfg->ul_cfg.srs.configured = cfg->ul_cfg.srs.dedicated_enabled and cfg->ul_cfg.srs.common_enabled; + cfg->ul_cfg.srs.I_srs = asn1_type.srs_ul_cfg_ded.setup().srs_cfg_idx; + cfg->ul_cfg.srs.B = asn1_type.srs_ul_cfg_ded.setup().srs_bw; + cfg->ul_cfg.srs.b_hop = asn1_type.srs_ul_cfg_ded.setup().srs_hop_bw; + cfg->ul_cfg.srs.n_rrc = asn1_type.srs_ul_cfg_ded.setup().freq_domain_position; + cfg->ul_cfg.srs.k_tc = asn1_type.srs_ul_cfg_ded.setup().tx_comb; + cfg->ul_cfg.srs.n_srs = asn1_type.srs_ul_cfg_ded.setup().cyclic_shift; + } + } + + if (asn1_type.ant_info_r10.is_present() && + asn1_type.ant_info_r10->type() == asn1::rrc::phys_cfg_ded_s::ant_info_r10_c_::types::explicit_value_r10) { + // Parse Release 10 + asn1::rrc::ant_info_ded_r10_s::tx_mode_r10_e_::options tx_mode = + asn1_type.ant_info_r10->explicit_value_r10().tx_mode_r10.value; + if ((srslte_tm_t)tx_mode < SRSLTE_TMINV) { + cfg->dl_cfg.tm = (srslte_tm_t)tx_mode; + } else { + fprintf(stderr, + "Transmission mode (R10) %s is not supported\n", + asn1_type.ant_info_r10->explicit_value_r10().tx_mode_r10.to_string().c_str()); + } + } else if (asn1_type.ant_info_present && + asn1_type.ant_info.type() == asn1::rrc::phys_cfg_ded_s::ant_info_c_::types::explicit_value) { + // Parse Release 8 + asn1::rrc::ant_info_ded_s::tx_mode_e_::options tx_mode = asn1_type.ant_info.explicit_value().tx_mode.value; + if ((srslte_tm_t)tx_mode < SRSLTE_TMINV) { + cfg->dl_cfg.tm = (srslte_tm_t)tx_mode; + } else { + fprintf(stderr, + "Transmission mode (R8) %s is not supported\n", + asn1_type.ant_info.explicit_value().tx_mode.to_string().c_str()); + } + } + if (asn1_type.sched_request_cfg_present) { + if (asn1_type.sched_request_cfg_present and asn1_type.sched_request_cfg.type() == asn1::rrc::setup_e::setup) { + cfg->ul_cfg.pucch.I_sr = asn1_type.sched_request_cfg.setup().sr_cfg_idx; + cfg->ul_cfg.pucch.n_pucch_sr = asn1_type.sched_request_cfg.setup().sr_pucch_res_idx; + cfg->ul_cfg.pucch.sr_configured = true; + } else { + cfg->ul_cfg.pucch.I_sr = 0; + cfg->ul_cfg.pucch.n_pucch_sr = 0; + cfg->ul_cfg.pucch.sr_configured = false; + } + } + + if (asn1_type.pdsch_cfg_ded_present) { + // Configure PDSCH + if (asn1_type.pdsch_cfg_ded_present && cfg->dl_cfg.pdsch.p_b < 4) { + cfg->dl_cfg.pdsch.p_a = asn1_type.pdsch_cfg_ded.p_a.to_number(); + cfg->dl_cfg.pdsch.power_scale = true; + } else { + cfg->dl_cfg.pdsch.power_scale = false; + } + } +} + +void set_phy_cfg_t_common_prach(phy_cfg_t* cfg, const asn1::rrc::prach_cfg_info_s* asn1_type, uint32_t root_seq_idx) +{ + if (asn1_type) { + cfg->prach_cfg.config_idx = asn1_type->prach_cfg_idx; + cfg->prach_cfg.zero_corr_zone = asn1_type->zero_correlation_zone_cfg; + cfg->prach_cfg.freq_offset = asn1_type->prach_freq_offset; + cfg->prach_cfg.hs_flag = asn1_type->high_speed_flag; + } + cfg->prach_cfg.root_seq_idx = root_seq_idx; +} + +void set_phy_cfg_t_common_pdsch(phy_cfg_t* cfg, const asn1::rrc::pdsch_cfg_common_s& asn1_type) +{ + cfg->dl_cfg.pdsch.rs_power = (float)asn1_type.ref_sig_pwr; + cfg->dl_cfg.pdsch.p_b = asn1_type.p_b; +} + +void set_phy_cfg_t_enable_64qam(phy_cfg_t* cfg, const bool enabled) +{ + cfg->ul_cfg.pusch.enable_64qam = enabled; +} + +void set_phy_cfg_t_common_pusch(phy_cfg_t* cfg, const asn1::rrc::pusch_cfg_common_s& asn1_type) +{ + /* PUSCH DMRS signal configuration */ + bzero(&cfg->ul_cfg.dmrs, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); + cfg->ul_cfg.dmrs.group_hopping_en = asn1_type.ul_ref_sigs_pusch.group_hop_enabled; + cfg->ul_cfg.dmrs.sequence_hopping_en = asn1_type.ul_ref_sigs_pusch.seq_hop_enabled; + cfg->ul_cfg.dmrs.cyclic_shift = asn1_type.ul_ref_sigs_pusch.cyclic_shift; + cfg->ul_cfg.dmrs.delta_ss = asn1_type.ul_ref_sigs_pusch.group_assign_pusch; + + /* PUSCH Hopping configuration */ + bzero(&cfg->ul_cfg.hopping, sizeof(srslte_pusch_hopping_cfg_t)); + cfg->ul_cfg.hopping.n_sb = asn1_type.pusch_cfg_basic.n_sb; + cfg->ul_cfg.hopping.hopping_offset = asn1_type.pusch_cfg_basic.pusch_hop_offset; + cfg->ul_cfg.hopping.hop_mode = + asn1_type.pusch_cfg_basic.hop_mode.value == + asn1::rrc::pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame + ? cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF + : cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; +} + +void set_phy_cfg_t_common_pucch(phy_cfg_t* cfg, const asn1::rrc::pucch_cfg_common_s& asn1_type) +{ + /* PUCCH configuration */ + cfg->ul_cfg.pucch.delta_pucch_shift = asn1_type.delta_pucch_shift.to_number(); + cfg->ul_cfg.pucch.N_cs = asn1_type.n_cs_an; + cfg->ul_cfg.pucch.n_rb_2 = asn1_type.n_rb_cqi; + cfg->ul_cfg.pucch.N_pucch_1 = asn1_type.n1_pucch_an; +} + +void set_phy_cfg_t_common_srs(phy_cfg_t* cfg, const asn1::rrc::srs_ul_cfg_common_c& asn1_type) +{ + cfg->ul_cfg.srs.common_enabled = asn1_type.type() == asn1::rrc::setup_e::setup; + if (cfg->ul_cfg.srs.common_enabled) { + cfg->ul_cfg.srs.simul_ack = asn1_type.setup().ack_nack_srs_simul_tx; + cfg->ul_cfg.srs.bw_cfg = asn1_type.setup().srs_bw_cfg.to_number(); + cfg->ul_cfg.srs.subframe_config = asn1_type.setup().srs_sf_cfg.to_number(); + } +} + +void set_phy_cfg_t_common_pwr_ctrl(phy_cfg_t* cfg, const asn1::rrc::ul_pwr_ctrl_common_s& asn1_type) +{ + cfg->ul_cfg.power_ctrl.p0_nominal_pusch = asn1_type.p0_nominal_pusch; + cfg->ul_cfg.power_ctrl.alpha = asn1_type.alpha.to_number(); + cfg->ul_cfg.power_ctrl.p0_nominal_pucch = asn1_type.p0_nominal_pucch; + cfg->ul_cfg.power_ctrl.delta_f_pucch[0] = asn1_type.delta_flist_pucch.delta_f_pucch_format1.to_number(); + cfg->ul_cfg.power_ctrl.delta_f_pucch[1] = asn1_type.delta_flist_pucch.delta_f_pucch_format1b.to_number(); + cfg->ul_cfg.power_ctrl.delta_f_pucch[2] = asn1_type.delta_flist_pucch.delta_f_pucch_format2.to_number(); + cfg->ul_cfg.power_ctrl.delta_f_pucch[3] = asn1_type.delta_flist_pucch.delta_f_pucch_format2a.to_number(); + cfg->ul_cfg.power_ctrl.delta_f_pucch[4] = asn1_type.delta_flist_pucch.delta_f_pucch_format2b.to_number(); + + cfg->ul_cfg.power_ctrl.delta_preamble_msg3 = asn1_type.delta_preamb_msg3; +} + +void set_phy_cfg_t_scell_config(phy_cfg_t* cfg, const asn1::rrc::scell_to_add_mod_r10_s& asn1_type) +{ + + if (asn1_type.rr_cfg_common_scell_r10_present) { + + // Enable always CSI request extra bit + cfg->dl_cfg.dci.multiple_csi_request_enabled = true; + + auto* rr_cfg_common_scell_r10 = &asn1_type.rr_cfg_common_scell_r10; + + if (rr_cfg_common_scell_r10->ul_cfg_r10_present) { + auto* ul_cfg_r10 = &rr_cfg_common_scell_r10->ul_cfg_r10; + + // Parse Power control + auto* ul_pwr_ctrl_common_scell_r10 = &ul_cfg_r10->ul_pwr_ctrl_common_scell_r10; + bzero(&cfg->ul_cfg.power_ctrl, sizeof(srslte_ue_ul_powerctrl_t)); + cfg->ul_cfg.power_ctrl.p0_nominal_pusch = ul_pwr_ctrl_common_scell_r10->p0_nominal_pusch_r10; + cfg->ul_cfg.power_ctrl.alpha = ul_pwr_ctrl_common_scell_r10->alpha_r10.to_number(); + + // Parse SRS + cfg->ul_cfg.srs.common_enabled = ul_cfg_r10->srs_ul_cfg_common_r10.type() == asn1::rrc::setup_e::setup; + if (cfg->ul_cfg.srs.common_enabled) { + auto* srs_ul_cfg_common = &ul_cfg_r10->srs_ul_cfg_common_r10.setup(); + cfg->ul_cfg.srs.simul_ack = srs_ul_cfg_common->ack_nack_srs_simul_tx; + cfg->ul_cfg.srs.bw_cfg = srs_ul_cfg_common->srs_bw_cfg.to_number(); + cfg->ul_cfg.srs.subframe_config = srs_ul_cfg_common->srs_sf_cfg.to_number(); + } + + // Parse PUSCH + auto* pusch_cfg_common = &ul_cfg_r10->pusch_cfg_common_r10; + bzero(&cfg->ul_cfg.hopping, sizeof(srslte_pusch_hopping_cfg_t)); + cfg->ul_cfg.hopping.n_sb = pusch_cfg_common->pusch_cfg_basic.n_sb; + cfg->ul_cfg.hopping.hop_mode = + pusch_cfg_common->pusch_cfg_basic.hop_mode.value == + asn1::rrc::pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame + ? cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF + : cfg->ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; + cfg->ul_cfg.hopping.hopping_offset = pusch_cfg_common->pusch_cfg_basic.pusch_hop_offset; + cfg->ul_cfg.pusch.enable_64qam = pusch_cfg_common->pusch_cfg_basic.enable64_qam; + } + } + + if (asn1_type.rr_cfg_ded_scell_r10_present) { + auto* rr_cfg_ded_scell_r10 = &asn1_type.rr_cfg_ded_scell_r10; + if (rr_cfg_ded_scell_r10->phys_cfg_ded_scell_r10_present) { + auto* phys_cfg_ded_scell_r10 = &rr_cfg_ded_scell_r10->phys_cfg_ded_scell_r10; + + // Parse nonUL Configuration + if (phys_cfg_ded_scell_r10->non_ul_cfg_r10_present) { + + auto* non_ul_cfg = &phys_cfg_ded_scell_r10->non_ul_cfg_r10; + + // Parse Transmission mode + if (non_ul_cfg->ant_info_r10_present) { + if (non_ul_cfg->ant_info_r10.tx_mode_r10.to_number() < (uint8_t)SRSLTE_TMINV) { + cfg->dl_cfg.tm = (srslte_tm_t)non_ul_cfg->ant_info_r10.tx_mode_r10.to_number(); + } else { + fprintf(stderr, + "Transmission mode (R10) %s is not supported\n", + non_ul_cfg->ant_info_r10.tx_mode_r10.to_string().c_str()); + } + } + + // Parse Cross carrier scheduling + if (non_ul_cfg->cross_carrier_sched_cfg_r10_present) { + typedef asn1::rrc::cross_carrier_sched_cfg_r10_s::sched_cell_info_r10_c_ sched_info_t; + + typedef sched_info_t::types cross_carrier_type_e; + auto* sched_info = &non_ul_cfg->cross_carrier_sched_cfg_r10.sched_cell_info_r10; + + cross_carrier_type_e cross_carrier_type = sched_info->type(); + if (cross_carrier_type == cross_carrier_type_e::own_r10) { + cfg->dl_cfg.dci.cif_present = sched_info->own_r10().cif_presence_r10; + } else { + cfg->dl_cfg.dci.cif_present = false; // This CC does not have Carrier Indicator Field + // ue_cfg->dl_cfg.blablabla = sched_info->other_r10().pdsch_start_r10; + // ue_cfg->dl_cfg.blablabla = sched_info->other_r10().sched_cell_id_r10; + } + } + + // Parse pdsch config dedicated + if (non_ul_cfg->pdsch_cfg_ded_r10_present) { + cfg->dl_cfg.pdsch.p_b = asn1_type.rr_cfg_common_scell_r10.non_ul_cfg_r10.pdsch_cfg_common_r10.p_b; + cfg->dl_cfg.pdsch.p_a = non_ul_cfg->pdsch_cfg_ded_r10.p_a.to_number(); + cfg->dl_cfg.pdsch.power_scale = true; + } + } + + // Parse UL Configuration + if (phys_cfg_ded_scell_r10->ul_cfg_r10_present) { + auto* ul_cfg_r10 = &phys_cfg_ded_scell_r10->ul_cfg_r10; + + // Parse CQI param + if (ul_cfg_r10->cqi_report_cfg_scell_r10_present) { + auto* cqi_report_cfg = &ul_cfg_r10->cqi_report_cfg_scell_r10; + + // Aperiodic report + if (cqi_report_cfg->cqi_report_mode_aperiodic_r10_present) { + cfg->dl_cfg.cqi_report.aperiodic_configured = true; + cfg->dl_cfg.cqi_report.aperiodic_mode = make_aperiodic_mode(cqi_report_cfg->cqi_report_mode_aperiodic_r10); + } + + // Periodic report + if (cqi_report_cfg->cqi_report_periodic_scell_r10_present) { + if (cqi_report_cfg->cqi_report_periodic_scell_r10.type() == asn1::rrc::setup_e::setup) { + typedef asn1::rrc::cqi_report_periodic_r10_c::setup_s_ cqi_cfg_t; + cqi_cfg_t cqi_cfg = cqi_report_cfg->cqi_report_periodic_scell_r10.setup(); + cfg->dl_cfg.cqi_report.periodic_configured = true; + cfg->dl_cfg.cqi_report.pmi_idx = cqi_cfg.cqi_pmi_cfg_idx; + cfg->dl_cfg.cqi_report.format_is_subband = + cqi_cfg.cqi_format_ind_periodic_r10.type().value == + cqi_cfg_t::cqi_format_ind_periodic_r10_c_::types::subband_cqi_r10; + if (cfg->dl_cfg.cqi_report.format_is_subband) { + cfg->dl_cfg.cqi_report.subband_size = cqi_cfg.cqi_format_ind_periodic_r10.subband_cqi_r10().k; + } + if (cqi_cfg.ri_cfg_idx_present) { + cfg->dl_cfg.cqi_report.ri_idx = cqi_cfg.ri_cfg_idx; + cfg->dl_cfg.cqi_report.ri_idx_present = true; + } else { + cfg->dl_cfg.cqi_report.ri_idx_present = false; + } + } else { + // Release, disable periodic reporting + cfg->dl_cfg.cqi_report.periodic_configured = false; + } + } + } + + // Sounding reference signals Dedicated + if (ul_cfg_r10->srs_ul_cfg_ded_r10_present) { + cfg->ul_cfg.srs.dedicated_enabled = ul_cfg_r10->srs_ul_cfg_ded_r10.type() == asn1::rrc::setup_e::setup; + if (cfg->ul_cfg.srs.dedicated_enabled) { + auto* srs_ul_cfg_ded_r10 = &ul_cfg_r10->srs_ul_cfg_ded_r10.setup(); + cfg->ul_cfg.srs.configured = cfg->ul_cfg.srs.dedicated_enabled and cfg->ul_cfg.srs.common_enabled; + cfg->ul_cfg.srs.I_srs = srs_ul_cfg_ded_r10->srs_cfg_idx; + cfg->ul_cfg.srs.B = srs_ul_cfg_ded_r10->srs_bw; + cfg->ul_cfg.srs.b_hop = srs_ul_cfg_ded_r10->srs_hop_bw; + cfg->ul_cfg.srs.n_rrc = srs_ul_cfg_ded_r10->freq_domain_position; + cfg->ul_cfg.srs.k_tc = srs_ul_cfg_ded_r10->tx_comb; + cfg->ul_cfg.srs.n_srs = srs_ul_cfg_ded_r10->cyclic_shift; + } + } + } + + if (phys_cfg_ded_scell_r10->cqi_report_cfg_scell_v1250.is_present()) { + // Enable/disable PDSCH 256QAM + auto cqi_report_cfg_scell = phys_cfg_ded_scell_r10->cqi_report_cfg_scell_v1250.get(); + cfg->dl_cfg.pdsch.use_tbs_index_alt = cqi_report_cfg_scell->alt_cqi_table_r12_present; + } else { + // Assume there is no PDSCH 256QAM + cfg->dl_cfg.pdsch.use_tbs_index_alt = false; + } + } + } +} + +// MBMS + +mbms_notif_cfg_t make_mbms_notif_cfg(const asn1::rrc::mbms_notif_cfg_r9_s& asn1_type) +{ + mbms_notif_cfg_t ret{}; + ret.notif_repeat_coeff = (mbms_notif_cfg_t::coeff_t)asn1_type.notif_repeat_coeff_r9.value; + ret.notif_offset = asn1_type.notif_offset_r9; + ret.notif_sf_idx = asn1_type.notif_sf_idx_r9; + return ret; +} + +mbsfn_area_info_t make_mbsfn_area_info(const asn1::rrc::mbsfn_area_info_r9_s& asn1_type) +{ + mbsfn_area_info_t ret{}; + ret.mbsfn_area_id = asn1_type.mbsfn_area_id_r9; + ret.non_mbsfn_region_len = (mbsfn_area_info_t::region_len_t)asn1_type.non_mbsfn_region_len.value; + ret.notif_ind = asn1_type.notif_ind_r9; + ret.mcch_cfg.mcch_repeat_period = + (mbsfn_area_info_t::mcch_cfg_t::repeat_period_t)asn1_type.mcch_cfg_r9.mcch_repeat_period_r9.value; + ret.mcch_cfg.mcch_offset = asn1_type.mcch_cfg_r9.mcch_offset_r9; + ret.mcch_cfg.mcch_mod_period = + (mbsfn_area_info_t::mcch_cfg_t::mod_period_t)asn1_type.mcch_cfg_r9.mcch_mod_period_r9.value; + ret.mcch_cfg.sf_alloc_info = asn1_type.mcch_cfg_r9.sf_alloc_info_r9.to_number(); + ret.mcch_cfg.sig_mcs = (mbsfn_area_info_t::mcch_cfg_t::sig_mcs_t)asn1_type.mcch_cfg_r9.sig_mcs_r9.value; + return ret; +} + +mbsfn_sf_cfg_t make_mbsfn_sf_cfg(const asn1::rrc::mbsfn_sf_cfg_s& sf_cfg) +{ + mbsfn_sf_cfg_t cfg{}; + cfg.radioframe_alloc_period = (mbsfn_sf_cfg_t::alloc_period_t)sf_cfg.radioframe_alloc_period.value; + cfg.radioframe_alloc_offset = sf_cfg.radioframe_alloc_offset; + cfg.nof_alloc_subfrs = (mbsfn_sf_cfg_t::sf_alloc_type_t)sf_cfg.sf_alloc.type().value; + if (sf_cfg.sf_alloc.type().value == asn1::rrc::mbsfn_sf_cfg_s::sf_alloc_c_::types_opts::one_frame) { + cfg.sf_alloc = sf_cfg.sf_alloc.one_frame().to_number(); + } else { + cfg.sf_alloc = sf_cfg.sf_alloc.four_frames().to_number(); + } + return cfg; +} + +pmch_info_t make_pmch_info(const asn1::rrc::pmch_info_r9_s& asn1_type) +{ + pmch_info_t ret{}; + ret.sf_alloc_end = asn1_type.pmch_cfg_r9.sf_alloc_end_r9; + ret.data_mcs = asn1_type.pmch_cfg_r9.data_mcs_r9; + ret.mch_sched_period = (pmch_info_t::mch_sched_period_t)asn1_type.pmch_cfg_r9.mch_sched_period_r9.value; + + ret.nof_mbms_session_info = asn1_type.mbms_session_info_list_r9.size(); + for (uint32_t i = 0; i < ret.nof_mbms_session_info; ++i) { + auto& asn1item = asn1_type.mbms_session_info_list_r9[i]; + auto& item = ret.mbms_session_info_list[i]; + item.session_id_present = asn1item.session_id_r9_present; + item.lc_ch_id = asn1item.lc_ch_id_r9; + item.session_id = asn1item.session_id_r9[0]; + item.tmgi.plmn_id_type = (tmgi_t::plmn_id_type_t)asn1item.tmgi_r9.plmn_id_r9.type().value; + if (item.tmgi.plmn_id_type == tmgi_t::plmn_id_type_t::plmn_idx) { + item.tmgi.plmn_id.plmn_idx = asn1item.tmgi_r9.plmn_id_r9.plmn_idx_r9(); + } else { + item.tmgi.plmn_id.explicit_value = make_plmn_id_t(asn1item.tmgi_r9.plmn_id_r9.explicit_value_r9()); + } + memcpy(item.tmgi.serviced_id, &asn1item.tmgi_r9.service_id_r9[0], 3); + } + return ret; +} + +mcch_msg_t make_mcch_msg(const asn1::rrc::mcch_msg_s& asn1_type) +{ + mcch_msg_t msg{}; + auto& r9 = asn1_type.msg.c1().mbsfn_area_cfg_r9(); + msg.nof_common_sf_alloc = r9.common_sf_alloc_r9.size(); + for (uint32_t i = 0; i < msg.nof_common_sf_alloc; ++i) { + msg.common_sf_alloc[i] = make_mbsfn_sf_cfg(r9.common_sf_alloc_r9[i]); + } + msg.common_sf_alloc_period = (mcch_msg_t::common_sf_alloc_period_t)r9.common_sf_alloc_period_r9.value; + msg.nof_pmch_info = r9.pmch_info_list_r9.size(); + for (uint32_t i = 0; i < msg.nof_pmch_info; ++i) { + msg.pmch_info_list[i] = make_pmch_info(r9.pmch_info_list_r9[i]); + } + return msg; +} +static_assert(ASN1_RRC_MAX_SESSION_PER_PMCH == pmch_info_t::max_session_per_pmch, "ASN1 to srsLTE interface mismatch"); + +sib13_t make_sib13(const asn1::rrc::sib_type13_r9_s& asn1_type) +{ + sib13_t sib13{}; + sib13.nof_mbsfn_area_info = asn1_type.mbsfn_area_info_list_r9.size(); + for (uint32_t i = 0; i < asn1_type.mbsfn_area_info_list_r9.size(); ++i) { + sib13.mbsfn_area_info_list[i] = make_mbsfn_area_info(asn1_type.mbsfn_area_info_list_r9[i]); + } + sib13.notif_cfg = make_mbms_notif_cfg(asn1_type.notif_cfg_r9); + return sib13; +} + } // namespace srslte diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 0fd0eef51..bf612999d 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -21,6 +21,9 @@ file(GLOB CXX_SOURCES "*.cc") file(GLOB C_SOURCES "*.c") +# Avoid warnings caused by libmbedtls about deprecated functions +set_source_files_properties(security.cc PROPERTIES COMPILE_FLAGS -Wno-deprecated-declarations) + add_library(srslte_common STATIC ${C_SOURCES} ${CXX_SOURCES}) add_custom_target(gen_build_info COMMAND cmake -P ${CMAKE_BINARY_DIR}/SRSLTEbuildinfo.cmake) add_dependencies(srslte_common gen_build_info) diff --git a/lib/src/common/buffer_pool.cc b/lib/src/common/buffer_pool.cc index 30312bdb7..a0ce2b828 100644 --- a/lib/src/common/buffer_pool.cc +++ b/lib/src/common/buffer_pool.cc @@ -49,5 +49,5 @@ void byte_buffer_pool::cleanup(void) } pthread_mutex_unlock(&instance_mutex); } - -} // namespace srsue + +} // namespace srslte diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index 0038bbf03..3bc4ebe49 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -37,6 +37,7 @@ #include "srslte/common/liblte_security.h" #include "math.h" #include "srslte/common/liblte_ssl.h" +#include "srslte/common/zuc.h" /******************************************************************************* DEFINES @@ -807,6 +808,88 @@ LIBLTE_ERROR_ENUM liblte_security_128_eia2( return (err); } +u32 GET_WORD(u32* DATA, u32 i) +{ + u32 WORD, ti; + ti = i % 32; + if (ti == 0) + WORD = DATA[i / 32]; + else + WORD = (DATA[i / 32] << ti) | (DATA[i / 32 + 1] >> (32 - ti)); + return WORD; +} + +u8 GET_BIT(uint8_t* DATA, u32 i) +{ + return (DATA[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; +} + +LIBLTE_ERROR_ENUM liblte_security_128_eia3( + uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* msg, uint32 msg_len, uint8* mac) + +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8_t iv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + uint32* ks; + uint32 msg_len_block_8, msg_len_block_32, m; + + if (key != NULL && msg != NULL && mac != NULL) { + msg_len_block_8 = (msg_len + 7) / 8; + msg_len_block_32 = (msg_len + 31) / 32; + + // Construct iv + iv[0] = (count >> 24) & 0xFF; + iv[1] = (count >> 16) & 0xFF; + iv[2] = (count >> 8) & 0xFF; + iv[3] = count & 0xFF; + + iv[4] = (bearer << 3) & 0xF8; + iv[5] = iv[6] = iv[7] = 0; + + iv[8] = ((count >> 24) & 0xFF) ^ ((direction & 1) << 7); + iv[9] = (count >> 16) & 0xFF; + iv[10] = (count >> 8) & 0xFF; + iv[11] = count & 0xFF; + + iv[12] = iv[4]; + iv[13] = iv[5]; + iv[14] = iv[6] ^ ((direction & 1) << 7); + iv[15] = iv[7]; + + zuc_state_t zuc_state; + // Initialize keystream + zuc_initialize(&zuc_state, key, iv); + + // Generate keystream + int N = msg_len + 64; + int L = (N + 31) / 32; + + ks = (uint32*)calloc(L, sizeof(uint32)); + + zuc_generate_keystream(&zuc_state, L, ks); + + uint32_t T = 0; + for (uint32_t i = 0; i < msg_len; i++) { + if (GET_BIT(msg, i)) { + T ^= GET_WORD(ks, i); + } + } + + T ^= GET_WORD(ks, msg_len); + + uint32_t mac_tmp = T ^ ks[L - 1]; + mac[0] = (mac_tmp >> 24) & 0xFF; + mac[1] = (mac_tmp >> 16) & 0xFF; + mac[2] = (mac_tmp >> 8) & 0xFF; + mac[3] = mac_tmp & 0xFF; + + free(ks); + } + + return (err); +} + /********************************************************************* Name: liblte_security_encryption_eea1 @@ -951,6 +1034,89 @@ LIBLTE_ERROR_ENUM liblte_security_decryption_eea2( return liblte_security_encryption_eea2(key, count, bearer, direction, ct, ct_len, out); } +/********************************************************************* + Name: liblte_security_encryption_eea1 + + Description: 128-bit encryption algorithm EEA1. + + Document Reference: 33.401 v13.1.0 Annex B.1.2 + 35.215 v13.0.0 References + Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D1 v2.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_encryption_eea3( + uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* msg, uint32 msg_len, uint8* out) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8_t iv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + uint32* ks; + int32 i; + uint32 msg_len_block_8, msg_len_block_32, m; + + if (key != NULL && msg != NULL && out != NULL) { + msg_len_block_8 = (msg_len + 7) / 8; + msg_len_block_32 = (msg_len + 31) / 32; + + // Construct iv + iv[0] = (count >> 24) & 0xFF; + iv[1] = (count >> 16) & 0xFF; + iv[2] = (count >> 8) & 0xFF; + iv[3] = (count)&0xFF; + iv[4] = ((bearer & 0x1F) << 3) | ((direction & 0x01) << 2); + iv[5] = 0; + iv[6] = 0; + iv[7] = 0; + iv[8] = iv[0]; + iv[9] = iv[1]; + iv[10] = iv[2]; + iv[11] = iv[3]; + iv[12] = iv[4]; + iv[13] = iv[5]; + iv[14] = iv[6]; + iv[15] = iv[7]; + + zuc_state_t zuc_state; + // Initialize keystream + zuc_initialize(&zuc_state, key, iv); + + // Generate keystream + + ks = (uint32*)calloc(msg_len_block_32, sizeof(uint32)); + zuc_generate_keystream(&zuc_state, msg_len_block_32, ks); + + // Generate output except last block + for (i = 0; i < (int32_t)msg_len_block_32 - 1; i++) { + out[4 * i + 0] = msg[4 * i + 0] ^ ((ks[i] >> 24) & 0xFF); + out[4 * i + 1] = msg[4 * i + 1] ^ ((ks[i] >> 16) & 0xFF); + out[4 * i + 2] = msg[4 * i + 2] ^ ((ks[i] >> 8) & 0xFF); + out[4 * i + 3] = msg[4 * i + 3] ^ ((ks[i] & 0xFF)); + } + + // Process last bytes + for (i = (msg_len_block_32 - 1) * 4; i < (int32_t)msg_len_block_8; i++) { + out[i] = msg[i] ^ ((ks[i / 4] >> ((3 - (i % 4)) * 8)) & 0xFF); + } + + // Zero tailing bits + zero_tailing_bits(out, msg_len); + + // Clean up + free(ks); + // zuc_deinitialize(state_ptr); + + err = LIBLTE_SUCCESS; + } + + return (err); +} + +LIBLTE_ERROR_ENUM liblte_security_decryption_eea3( + uint8* key, uint32 count, uint8 bearer, uint8 direction, uint8* msg, uint32 msg_len, uint8* out) +{ + return liblte_security_encryption_eea3(key, count, bearer, direction, msg, msg_len, out); +} + /********************************************************************* Name: liblte_security_milenage_f1 diff --git a/lib/src/common/log_filter.cc b/lib/src/common/log_filter.cc index 0808a265e..058a1b4fe 100644 --- a/lib/src/common/log_filter.cc +++ b/lib/src/common/log_filter.cc @@ -65,216 +65,173 @@ void log_filter::init(std::string layer, logger *logger_, bool tti) do_tti = tti; } -void log_filter::all_log(srslte::LOG_LEVEL_ENUM level, - uint32_t tti, - const char *msg) +void log_filter::all_log( + srslte::LOG_LEVEL_ENUM level, uint32_t tti, const char* msg, const uint8_t* hex, int size, bool long_msg) { - if(logger_h) { - std::stringstream ss; + char buffer_tti[16] = {}; + char buffer_time[64] = {}; - ss << now_time() << " "; - if (show_layer_en) { - ss << "[" <allocate_unique_log_str(); } - if (add_string_en) { - ss << add_string_val << " "; - } - ss << msg; - str_ptr s_ptr(new std::string(ss.str())); - logger_h->log(s_ptr); - } -} + if (log_str) { + now_time(buffer_time, sizeof(buffer_time)); + if (do_tti) { + get_tti_str(tti, buffer_tti, sizeof(buffer_tti)); + } -void log_filter::all_log(srslte::LOG_LEVEL_ENUM level, - uint32_t tti, - const char *msg, - const uint8_t *hex, - int size) -{ - if(logger_h) { - std::stringstream ss; + snprintf(log_str->str(), + log_str->get_buffer_size(), + "%s [%s] %s %s%s%s%s%s", + buffer_time, + get_service_name().c_str(), + log_level_text_short[level], + do_tti ? buffer_tti : "", + add_string_en ? add_string_val.c_str() : "", + msg, + msg[strlen(msg) - 1] != '\n' ? "\n" : "", + (hex_limit > 0 && hex && size > 0) ? hex_string(hex, size).c_str() : ""); - ss << now_time() << " "; - if (show_layer_en) { - ss << "[" <log(std::move(log_str)); } else { - ss << log_level_text[level] << " "; + logger_h->log_char("Error in Log: Not enough buffers in pool\n"); } - - if(do_tti) { - ss << "[" << std::setfill('0') << std::setw(5) << tti << "] "; - } - - if (add_string_en) { - ss << add_string_val << " "; - } - ss << msg; - - if (msg[strlen(msg)-1] != '\n') { - ss << std::endl; - } - - if (hex_limit > 0 && hex && size > 0) { - ss << hex_string(hex, size); - } - str_ptr s_ptr(new std::string(ss.str())); - logger_h->log(s_ptr); } } void log_filter::console(const char * message, ...) { - char *args_msg = NULL; + char args_msg[char_buff_size]; va_list args; va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) + if (vsnprintf(args_msg, char_buff_size, message, args) > 0) printf("%s",args_msg); // Print directly to stdout fflush(stdout); va_end(args); - free(args_msg); } +#define all_log_expand(log_level) \ + do { \ + if (level >= log_level) { \ + char args_msg[char_buff_size]; \ + va_list args; \ + va_start(args, message); \ + if (vsnprintf(args_msg, char_buff_size, message, args) > 0) \ + all_log(log_level, tti, args_msg); \ + va_end(args); \ + } \ + } while (0) + +#define all_log_hex_expand(log_level) \ + do { \ + if (level >= log_level) { \ + char args_msg[char_buff_size]; \ + va_list args; \ + va_start(args, message); \ + if (vsnprintf(args_msg, char_buff_size, message, args) > 0) \ + all_log(log_level, tti, args_msg, hex, size); \ + va_end(args); \ + } \ + } while (0) + void log_filter::error(const char * message, ...) { - if (level >= LOG_LEVEL_ERROR) { - char *args_msg = NULL; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_ERROR, tti, args_msg); - va_end(args); - free(args_msg); - } + all_log_expand(LOG_LEVEL_ERROR); } + void log_filter::warning(const char * message, ...) { - if (level >= LOG_LEVEL_WARNING) { - char *args_msg = NULL; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_WARNING, tti, args_msg); - va_end(args); - free(args_msg); - } + all_log_expand(LOG_LEVEL_WARNING); } + void log_filter::info(const char * message, ...) { - if (level >= LOG_LEVEL_INFO) { - char *args_msg = NULL; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_INFO, tti, args_msg); - va_end(args); - free(args_msg); - } + all_log_expand(LOG_LEVEL_INFO); } + void log_filter::debug(const char * message, ...) { + all_log_expand(LOG_LEVEL_DEBUG); +} + +void log_filter::debug_long(const char* message, ...) +{ if (level >= LOG_LEVEL_DEBUG) { - char *args_msg = NULL; + char* args_msg = NULL; va_list args; va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_DEBUG, tti, args_msg); + if (vasprintf(&args_msg, message, args) > 0) + all_log(LOG_LEVEL_DEBUG, tti, args_msg, nullptr, strlen(args_msg), true); va_end(args); free(args_msg); } } void log_filter::error_hex(const uint8_t *hex, int size, const char * message, ...) { - if (level >= LOG_LEVEL_ERROR) { - char *args_msg = NULL; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_ERROR, tti, args_msg, hex, size); - va_end(args); - free(args_msg); - } + all_log_hex_expand(LOG_LEVEL_ERROR); } + void log_filter::warning_hex(const uint8_t *hex, int size, const char * message, ...) { - if (level >= LOG_LEVEL_WARNING) { - char *args_msg = NULL; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_WARNING, tti, args_msg, hex, size); - va_end(args); - free(args_msg); - } + all_log_hex_expand(LOG_LEVEL_WARNING); } + void log_filter::info_hex(const uint8_t *hex, int size, const char * message, ...) { - if (level >= LOG_LEVEL_INFO) { - char *args_msg = NULL; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_INFO, tti, args_msg, hex, size); - va_end(args); - free(args_msg); - } + all_log_hex_expand(LOG_LEVEL_INFO); } + void log_filter::debug_hex(const uint8_t *hex, int size, const char * message, ...) { - if (level >= LOG_LEVEL_DEBUG) { - char *args_msg = NULL; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message, args) > 0) - all_log(LOG_LEVEL_DEBUG, tti, args_msg, hex, size); - va_end(args); - free(args_msg); - } + all_log_hex_expand(LOG_LEVEL_DEBUG); } void log_filter::set_time_src(time_itf *source, time_format_t format) { this->time_src = source; this->time_format = format; } +void log_filter::get_tti_str(const uint32_t tti_, char* buffer, const uint32_t buffer_len) +{ + snprintf(buffer, buffer_len, "[%5d] ", tti_); +} -std::string log_filter::now_time() +void log_filter::now_time(char* buffer, const uint32_t buffer_len) { struct timeval rawtime; struct tm * timeinfo; - char buffer[64]; char us[16]; srslte_timestamp_t now; uint64_t usec_epoch; + if (buffer_len < 16) { + fprintf(stderr, "Error buffer provided for time too small\n"); + return; + } + if (!time_src) { gettimeofday(&rawtime, NULL); timeinfo = localtime(&rawtime.tv_sec); if (time_format == TIME) { - strftime(buffer, 64, "%H:%M:%S", timeinfo); - strcat(buffer, "."); + strftime(buffer, buffer_len, "%H:%M:%S.", timeinfo); snprintf(us, 16, "%06ld", rawtime.tv_usec); - strcat(buffer, us); + uint32_t dest_len = strlen(buffer); + strncat(buffer, us, buffer_len - dest_len - 1); } else { usec_epoch = rawtime.tv_sec * 1000000 + rawtime.tv_usec; - snprintf(buffer, 64, "%ld", usec_epoch); + snprintf(buffer, buffer_len, "%ld", usec_epoch); } } else { now = time_src->get_time(); if (time_format == TIME) { - snprintf(buffer, 64, "%ld:%06u", now.full_secs, (uint32_t) (now.frac_secs * 1e6)); + snprintf(buffer, buffer_len, "%ld:%06u", now.full_secs, (uint32_t)(now.frac_secs * 1e6)); } else { usec_epoch = now.full_secs * 1000000 + (uint32_t) (now.frac_secs * 1e6); - snprintf(buffer, 64, "%ld", usec_epoch); + snprintf(buffer, buffer_len, "%ld", usec_epoch); } } - - return std::string(buffer); } std::string log_filter::hex_string(const uint8_t *hex, int size) @@ -297,4 +254,4 @@ std::string log_filter::hex_string(const uint8_t *hex, int size) return ss.str(); } -} // namespace srsue +} // namespace srslte diff --git a/lib/src/common/logger_file.cc b/lib/src/common/logger_file.cc index b0f082062..b38958d51 100644 --- a/lib/src/common/logger_file.cc +++ b/lib/src/common/logger_file.cc @@ -33,44 +33,58 @@ logger_file::logger_file() : logfile(NULL), is_running(false), cur_length(0), ma pthread_cond_init(¬_empty, NULL); } -logger_file::~logger_file() { - if(is_running) { - log(new std::string("Closing log\n")); - pthread_mutex_lock(&mutex); - is_running = false; - pthread_cond_signal(¬_empty); // wakeup thread and let it terminate - pthread_mutex_unlock(&mutex); - wait_thread_finish(); - flush(); - if (logfile) { - fclose(logfile); - } - } +logger_file::~logger_file() +{ + stop(); pthread_mutex_destroy(&mutex); pthread_cond_destroy(¬_empty); } void logger_file::init(std::string file, int max_length_) { - pthread_mutex_init(&mutex, NULL); - pthread_cond_init(¬_empty, NULL); + if (is_running) { + fprintf(stderr, "Error: logger thread is already running.\n"); + return; + } + pthread_mutex_lock(&mutex); max_length = (int64_t)max_length_*1024; name_idx = 0; filename = file; logfile = fopen(filename.c_str(), "w"); - if(logfile == NULL) { + if (logfile == NULL) { printf("Error: could not create log file, no messages will be logged!\n"); } is_running = true; start(-2); + pthread_mutex_unlock(&mutex); } -void logger_file::log(const char *msg) { - log(new std::string(msg)); +void logger_file::stop() +{ + if (is_running) { + logger::log_char("Closing log\n"); + pthread_mutex_lock(&mutex); + is_running = false; + pthread_cond_signal(¬_empty); // wakeup thread and let it terminate + pthread_mutex_unlock(&mutex); + wait_thread_finish(); + pthread_mutex_lock(&mutex); + flush(); + if (logfile) { + fclose(logfile); + logfile = NULL; + } + pthread_mutex_unlock(&mutex); + } else { + pthread_mutex_lock(&mutex); + flush(); // flush even if thread isn't running anymore + pthread_mutex_unlock(&mutex); + } } -void logger_file::log(str_ptr msg) { +void logger_file::log(unique_log_str_t msg) +{ pthread_mutex_lock(&mutex); - buffer.push_back(msg); + buffer.push_back(std::move(msg)); pthread_cond_signal(¬_empty); pthread_mutex_unlock(&mutex); } @@ -85,13 +99,14 @@ void logger_file::run_thread() { return; // Thread done. Messages in buffer will be handled in flush. } } - str_ptr s = buffer.front(); + unique_log_str_t s = std::move(buffer.front()); + int n = 0; - if(logfile) - n = fprintf(logfile, "%s", s->c_str()); - delete s; + if (logfile) { + n = fprintf(logfile, "%s", s->str()); + } buffer.pop_front(); - pthread_mutex_unlock(&mutex); + if (n > 0) { cur_length += (int64_t) n; if (cur_length >= max_length && max_length > 0) { @@ -107,18 +122,20 @@ void logger_file::run_thread() { cur_length = 0; } } + pthread_mutex_unlock(&mutex); } } -void logger_file::flush() { - std::deque::iterator it; - for(it=buffer.begin();it!=buffer.end();it++) - { - str_ptr s = *it; - if(logfile) - fprintf(logfile, "%s", s->c_str()); - delete s; +void logger_file::flush() +{ + std::deque::iterator it; + for (it = buffer.begin(); it != buffer.end(); it++) { + unique_log_str_t s = std::move(*it); + if (logfile) { + fprintf(logfile, "%s", s->str()); + } } + buffer.clear(); } -} // namespace srsue +} // namespace srslte diff --git a/lib/src/common/mac_nr_pcap.cc b/lib/src/common/mac_nr_pcap.cc new file mode 100644 index 000000000..1fbed7f89 --- /dev/null +++ b/lib/src/common/mac_nr_pcap.cc @@ -0,0 +1,117 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/common/mac_nr_pcap.h" +#include "srslte/srslte.h" +#include + +namespace srslte { + +mac_nr_pcap::mac_nr_pcap() {} + +mac_nr_pcap::~mac_nr_pcap() +{ + if (pcap_file) { + close(); + } +} + +void mac_nr_pcap::enable(const bool& enable_) +{ + enable_write = enable_; +} +void mac_nr_pcap::open(const std::string& filename_, const uint16_t& ue_id_) +{ + fprintf(stdout, "Opening MAC-NR PCAP with DLT=%d\n", UDP_DLT); + filename = filename_; + pcap_file = LTE_PCAP_Open(UDP_DLT, filename.c_str()); + ue_id = ue_id_; + enable_write = true; +} +void mac_nr_pcap::close() +{ + enable_write = false; + fprintf(stdout, "Saving MAC-NR PCAP to %s\n", filename.c_str()); + LTE_PCAP_Close(pcap_file); + pcap_file = nullptr; +} + +void mac_nr_pcap::set_ue_id(const uint16_t& ue_id_) +{ + ue_id = ue_id_; +} + +void mac_nr_pcap::pack_and_write(uint8_t* pdu, + uint32_t pdu_len_bytes, + uint32_t tti, + uint16_t crnti, + uint8_t harqid, + uint8_t direction, + uint8_t rnti_type) +{ + if (enable_write) { + mac_nr_context_info_t context = {}; + context.radioType = FDD_RADIO; + context.direction = direction; + context.rntiType = rnti_type; + context.rnti = crnti; + context.ueid = ue_id; + context.harqid = harqid; + context.system_frame_number = tti / 10; + context.sub_frame_number = tti % 10; + + if (pdu) { + NR_PCAP_MAC_WritePDU(pcap_file, &context, pdu, pdu_len_bytes); + } + } +} + +void mac_nr_pcap::write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti) +{ + pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, C_RNTI); +} + +void mac_nr_pcap::write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti) +{ + pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_UPLINK, C_RNTI); +} + +void mac_nr_pcap::write_dl_ra_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti) +{ + pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, RA_RNTI); +} + +void mac_nr_pcap::write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti) +{ + pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, NO_RNTI); +} + +void mac_nr_pcap::write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti) +{ + pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, P_RNTI); +} + +void mac_nr_pcap::write_dl_si_rnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti) +{ + pack_and_write(pdu, pdu_len_bytes, tti, rnti, harqid, DIRECTION_DOWNLINK, SI_RNTI); +} + +} // namespace srslte diff --git a/lib/src/common/mac_nr_pdu.cc b/lib/src/common/mac_nr_pdu.cc new file mode 100644 index 000000000..8800710db --- /dev/null +++ b/lib/src/common/mac_nr_pdu.cc @@ -0,0 +1,275 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/common/mac_nr_pdu.h" + +namespace srslte { + +mac_nr_sch_subpdu::mac_nr_sch_subpdu(mac_nr_sch_pdu* parent_) : parent(parent_) {} + +mac_nr_sch_subpdu::nr_lcid_sch_t mac_nr_sch_subpdu::get_type() +{ + if (lcid >= 32) { + return (nr_lcid_sch_t)lcid; + } + + return CCCH; +} + +bool mac_nr_sch_subpdu::is_sdu() +{ + return get_type() == CCCH; +} + +bool mac_nr_sch_subpdu::is_var_len_ce() +{ + return false; +} + +// return length of PDU +uint32_t mac_nr_sch_subpdu::read_subheader(const uint8_t* ptr) +{ + // Skip R, read F bit and LCID + F_bit = (bool)(*ptr & 0x40) ? true : false; + lcid = (uint8_t)*ptr & 0x3f; + ptr++; + header_length = 1; + + if (is_sdu() || is_var_len_ce()) { + // Read first length byte + sdu_length = (uint32_t)*ptr; + ptr++; + header_length++; + + if (F_bit) { + // add second length byte + sdu_length = sdu_length << 8 | ((uint32_t)*ptr & 0xff); + ptr++; + header_length++; + } + } else { + sdu_length = sizeof_ce(lcid, parent->is_ulsch()); + } + sdu = (uint8_t*)ptr; + return header_length; +} + +void mac_nr_sch_subpdu::set_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_) +{ + lcid = lcid_; + sdu = const_cast(payload_); + sdu_length = len_; + header_length = 2; + + if (sdu_length >= 256) { + F_bit = true; + header_length += 1; + } +} + +void mac_nr_sch_subpdu::set_padding(const uint32_t len_) +{ + lcid = PADDING; + // 1 Byte R/LCID MAC subheader + sdu_length = len_ - 1; + header_length = 1; +} + +// Section 6.1.2 +uint32_t mac_nr_sch_subpdu::write_subpdu(const uint8_t* start_) +{ + uint8_t* ptr = const_cast(start_); + *ptr = (uint8_t)((F_bit ? 1 : 0) << 6) | ((uint8_t)lcid & 0x3f); + ptr += 1; + + if (header_length == 3) { + // 3 Byte R/F/LCID/L MAC subheader with 16-bit L field + *ptr = ((sdu_length & 0xff00) >> 8); + ptr += 1; + *ptr = static_cast(sdu_length); + ptr += 1; + + } else if (header_length == 2) { + // 2 Byte R/F/LCID/L MAC subheader with 8-bit L field + *ptr = static_cast(sdu_length); + ptr += 1; + } else if (header_length == 1) { + // do nothing + } else { + fprintf(stderr, "Error while packing PDU. Unsupported header length (%d)\n", header_length); + } + + // copy SDU payload + if (sdu) { + memcpy(ptr, sdu, sdu_length); + } else { + // clear memory + memset(ptr, 0, sdu_length); + } + + ptr += sdu_length; + + // return total length of subpdu + return ptr - start_; +} + +uint32_t mac_nr_sch_subpdu::get_total_length() +{ + return (header_length + sdu_length); +} + +uint32_t mac_nr_sch_subpdu::get_sdu_length() +{ + return sdu_length; +} + +uint32_t mac_nr_sch_subpdu::get_lcid() +{ + return lcid; +} + +uint8_t* mac_nr_sch_subpdu::get_sdu() +{ + return sdu; +} + +uint32_t mac_nr_sch_subpdu::sizeof_ce(uint32_t lcid, bool is_ul) +{ + if (is_ul) { + switch (lcid) { + case CRNTI: + return 2; + case SHORT_TRUNC_BSR: + return 1; + case SHORT_BSR: + return 1; + case PADDING: + return 0; + } + } else { + switch (lcid) { + case CON_RES_ID: + return 6; + case TA_CMD: + return 1; + case DRX_CMD: + return 0; + case PADDING: + return 0; + } + } + return 0; +} + +void mac_nr_sch_pdu::pack() +{ + // SDUs are written in place, only add padding if needed + if (remaining_len) { + mac_nr_sch_subpdu padding_subpdu(this); + padding_subpdu.set_padding(remaining_len); + padding_subpdu.write_subpdu(buffer->msg + buffer->N_bytes); + + // update length + buffer->N_bytes += padding_subpdu.get_total_length(); + remaining_len -= padding_subpdu.get_total_length(); + subpdus.push_back(padding_subpdu); + } +} + +void mac_nr_sch_pdu::unpack(const uint8_t* payload, const uint32_t& len) +{ + uint32_t offset = 0; + while (offset < len) { + mac_nr_sch_subpdu sch_pdu(this); + sch_pdu.read_subheader(payload + offset); + offset += sch_pdu.get_total_length(); + subpdus.push_back(sch_pdu); + } + if (offset != len) { + fprintf(stderr, "Error parsing NR MAC PDU (len=%d, offset=%d)\n", len, offset); + } +} + +uint32_t mac_nr_sch_pdu::get_num_subpdus() +{ + return subpdus.size(); +} + +const mac_nr_sch_subpdu& mac_nr_sch_pdu::get_subpdu(const uint32_t& index) +{ + return subpdus.at(index); +} + +bool mac_nr_sch_pdu::is_ulsch() +{ + return ulsch; +} + +void mac_nr_sch_pdu::init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool ulsch_) +{ + buffer = buffer_; + pdu_len = pdu_len_; + remaining_len = pdu_len_; + ulsch = ulsch_; +} + +uint32_t mac_nr_sch_pdu::size_header_sdu(const uint32_t nbytes) +{ + if (nbytes < 256) { + return 2; + } else { + return 3; + } +} + +uint32_t mac_nr_sch_pdu::get_remaing_len() +{ + return remaining_len; +} + +uint32_t mac_nr_sch_pdu::add_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_) +{ + int header_size = size_header_sdu(len_); + + if (header_size + len_ > remaining_len) { + printf("Header and SDU exceed space in PDU (%d > %d).\n", header_size + len_, remaining_len); + return SRSLTE_ERROR; + } + + mac_nr_sch_subpdu sch_pdu(this); + sch_pdu.set_sdu(lcid_, payload_, len_); + uint32_t length = sch_pdu.write_subpdu(buffer->msg + buffer->N_bytes); + + if (length != sch_pdu.get_total_length()) { + fprintf(stderr, "Error writing subPDU (Length error: %d != %d)\n", length, sch_pdu.get_total_length()); + return SRSLTE_ERROR; + } + + // update length and advance payload pointer + buffer->N_bytes += length; + remaining_len -= length; + + subpdus.push_back(sch_pdu); + + return SRSLTE_SUCCESS; +} + +} // namespace srslte diff --git a/lib/src/common/pdu.cc b/lib/src/common/pdu.cc index 18c04d294..9fbef8bc9 100644 --- a/lib/src/common/pdu.cc +++ b/lib/src/common/pdu.cc @@ -177,7 +177,7 @@ uint8_t* sch_pdu::write_packet(srslte::log* log_h) // Print warning if we have padding only if (nof_subheaders <= 0 && nof_subheaders < (int)max_subheaders) { - log_h->warning("Writing MAC PDU with padding only (%d B)\n", pdu_len); + log_h->debug("Writing MAC PDU with padding only (%d B)\n", pdu_len); } /* Sanity check and print if error */ @@ -556,9 +556,9 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format) uint32_t ce_size = format == LONG_BSR ? 3 : 1; if (((sch_pdu*)parent)->has_space_ce(ce_size)) { if (format == LONG_BSR) { - w_payload_ce[0] = (buff_size_table(buff_size[0]) & 0x3f) << 2 | (buff_size_table(buff_size[1]) & 0xc0) >> 6; - w_payload_ce[1] = (buff_size_table(buff_size[1]) & 0xf) << 4 | (buff_size_table(buff_size[2]) & 0xf0) >> 4; - w_payload_ce[2] = (buff_size_table(buff_size[2]) & 0x3) << 6 | (buff_size_table(buff_size[3]) & 0x3f); + w_payload_ce[0] = ((buff_size_table(buff_size[0]) & 0x3f) << 2) | ((buff_size_table(buff_size[1]) & 0x30) >> 4); + w_payload_ce[1] = ((buff_size_table(buff_size[1]) & 0xf) << 4) | ((buff_size_table(buff_size[2]) & 0x3c) >> 2); + w_payload_ce[2] = ((buff_size_table(buff_size[2]) & 0x3) << 6) | ((buff_size_table(buff_size[3]) & 0x3f)); } else { w_payload_ce[0] = (nonzero_lcg & 0x3) << 6 | (buff_size_table(buff_size[nonzero_lcg]) & 0x3f); } diff --git a/lib/src/common/rlc_pcap.cc b/lib/src/common/rlc_pcap.cc index 7410ec7f4..0b71f38cd 100644 --- a/lib/src/common/rlc_pcap.cc +++ b/lib/src/common/rlc_pcap.cc @@ -32,8 +32,8 @@ void rlc_pcap::enable(bool en) } void rlc_pcap::open(const char* filename, uint32_t ue_id) { - fprintf(stdout, "Opening RLC PCAP with DLT=%d\n", RLC_LTE_DLT); - pcap_file = LTE_PCAP_Open(RLC_LTE_DLT, filename); + fprintf(stdout, "Opening RLC PCAP with DLT=%d\n", UDP_DLT); + pcap_file = LTE_PCAP_Open(UDP_DLT, filename); this->ue_id = ue_id; enable_write = true; } diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index ba2c5d8d3..56de0697f 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -150,24 +150,19 @@ uint8_t security_128_eia1( uint8_t *key, return SRSLTE_SUCCESS; } -uint8_t security_128_eia2( uint8_t *key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t *msg, - uint32_t msg_len, - uint8_t *mac) +uint8_t security_128_eia2( + uint8_t* key, uint32_t count, uint32_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac) +{ + return liblte_security_128_eia2(key, count, bearer, direction, msg, msg_len, mac); +} + +uint8_t security_128_eia3( + uint8_t* key, uint32_t count, uint32_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac) { - return liblte_security_128_eia2(key, - count, - bearer, - direction, - msg, - msg_len, - mac); + return liblte_security_128_eia3(key, count, bearer, direction, msg, msg_len * 8, mac); } -uint8_t security_md5(const uint8_t *input, size_t len, uint8_t *output) +uint8_t security_md5(const uint8_t* input, size_t len, uint8_t* output) { memset(output, 0x00, 16); #ifdef HAVE_MBEDTLS @@ -179,7 +174,6 @@ uint8_t security_md5(const uint8_t *input, size_t len, uint8_t *output) return SRSLTE_SUCCESS; } - /****************************************************************************** * Encryption / Decryption *****************************************************************************/ @@ -202,34 +196,26 @@ uint8_t security_128_eea1(uint8_t *key, } +uint8_t security_128_eea2( + uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out) +{ -uint8_t security_128_eea2(uint8_t *key, - uint32_t count, - uint8_t bearer, - uint8_t direction, - uint8_t *msg, - uint32_t msg_len, - uint8_t *msg_out){ + return liblte_security_encryption_eea2(key, count, bearer, direction, msg, msg_len * 8, msg_out); +} - return liblte_security_encryption_eea2(key, - count, - bearer, - direction, - msg, - msg_len * 8, - msg_out); +uint8_t security_128_eea3( + uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out) +{ + + return liblte_security_encryption_eea3(key, count, bearer, direction, msg, msg_len * 8, msg_out); } /****************************************************************************** * Authentication *****************************************************************************/ -uint8_t compute_opc( uint8_t *k, - uint8_t *op, - uint8_t *opc) +uint8_t compute_opc(uint8_t* k, uint8_t* op, uint8_t* opc) { - return liblte_compute_opc(k, - op, - opc); + return liblte_compute_opc(k, op, opc); } uint8_t security_milenage_f1( uint8_t *k, @@ -290,5 +276,4 @@ uint8_t security_milenage_f5_star( uint8_t *k, ak); } - -} // namespace srsue +} // namespace srslte diff --git a/lib/src/common/thread_pool.cc b/lib/src/common/thread_pool.cc index 1eddae834..3d41b7f3d 100644 --- a/lib/src/common/thread_pool.cc +++ b/lib/src/common/thread_pool.cc @@ -19,9 +19,10 @@ * */ +#include "srslte/common/thread_pool.h" #include +#include #include -#include "srslte/common/thread_pool.h" #define DEBUG 0 #define debug_thread(fmt, ...) do { if(DEBUG) printf(fmt, __VA_ARGS__); } while(0) @@ -280,6 +281,128 @@ uint32_t thread_pool::get_nof_workers() return nof_workers; } +/************************************************************************** + * task_thread_pool - uses a queue to enqueue callables, that start + * once a worker is available + *************************************************************************/ + +task_thread_pool::task_thread_pool(uint32_t nof_workers) : running(false) +{ + workers.reserve(nof_workers); + for (uint32_t i = 0; i < nof_workers; ++i) { + workers.emplace_back(this, i); + } +} + +task_thread_pool::~task_thread_pool() +{ + stop(); +} + +void task_thread_pool::start(int32_t prio, uint32_t mask) +{ + std::lock_guard lock(queue_mutex); + running = true; + for (worker_t& w : workers) { + w.setup(prio, mask); + } +} + +void task_thread_pool::stop() +{ + std::unique_lock lock(queue_mutex); + if (running) { + running = false; + bool workers_running = false; + for (worker_t& w : workers) { + if (w.is_running()) { + workers_running = true; + break; + } + } + lock.unlock(); + if (workers_running) { + cv_empty.notify_all(); + } + for (worker_t& w : workers) { + w.stop(); + } + } +} + +void task_thread_pool::push_task(const task_t& task) +{ + { + std::lock_guard lock(queue_mutex); + pending_tasks.push(task); + } + cv_empty.notify_one(); +} + +void task_thread_pool::push_task(task_t&& task) +{ + { + std::lock_guard lock(queue_mutex); + pending_tasks.push(std::move(task)); + } + cv_empty.notify_one(); +} + +uint32_t task_thread_pool::nof_pending_tasks() +{ + std::lock_guard lock(queue_mutex); + return pending_tasks.size(); +} + +task_thread_pool::worker_t::worker_t(srslte::task_thread_pool* parent_, uint32_t my_id) : + parent(parent_), + thread(std::string("TASKWORKER") + std::to_string(my_id)), + id_(my_id) +{ +} + +void task_thread_pool::worker_t::stop() +{ + wait_thread_finish(); +} + +void task_thread_pool::worker_t::setup(int32_t prio, uint32_t mask) +{ + running = true; + if (mask == 255) { + start(prio); + } else { + start_cpu_mask(prio, mask); + } +} + +bool task_thread_pool::worker_t::wait_task(task_t* task) +{ + std::unique_lock lock(parent->queue_mutex); + while (parent->running and parent->pending_tasks.empty()) { + parent->cv_empty.wait(lock); + } + if (not parent->running) { + return false; + } + if (task) { + *task = std::move(parent->pending_tasks.front()); + } + parent->pending_tasks.pop(); + return true; } +void task_thread_pool::worker_t::run_thread() +{ + // main loop + task_t task; + while (wait_task(&task)) { + task(id()); + } + + // on exit, notify pool class + std::unique_lock lock(parent->queue_mutex); + running = false; +} +} // namespace srslte diff --git a/lib/src/common/zuc.cc b/lib/src/common/zuc.cc new file mode 100644 index 000000000..0823379c0 --- /dev/null +++ b/lib/src/common/zuc.cc @@ -0,0 +1,233 @@ +/*--------------------------------------------------------- + + zuc.cc + Adapted from ETSI/SAGE specifications: + "Specification of the 3GPP Confidentiality + and Integrity Algorithms 128-EEA3 & 128-EIA3. + Document 2: ZUC Specification" + +---------------------------------------------------------*/ + +#include "srslte/common/zuc.h" + +#define MAKEU32(a, b, c, d) (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d))) +#define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF) +#define MAKEU31(a, b, c) (((u32)(a) << 23) | ((u32)(b) << 8) | (u32)(c)) +#define ROT(a, k) (((a) << k) | ((a) >> (32 - k))) + +/* the s-boxes */ +u8 S0[256] = { + 0x3e, 0x72, 0x5b, 0x47, 0xca, 0xe0, 0x00, 0x33, 0x04, 0xd1, 0x54, 0x98, 0x09, 0xb9, 0x6d, 0xcb, 0x7b, 0x1b, 0xf9, + 0x32, 0xaf, 0x9d, 0x6a, 0xa5, 0xb8, 0x2d, 0xfc, 0x1d, 0x08, 0x53, 0x03, 0x90, 0x4d, 0x4e, 0x84, 0x99, 0xe4, 0xce, + 0xd9, 0x91, 0xdd, 0xb6, 0x85, 0x48, 0x8b, 0x29, 0x6e, 0xac, 0xcd, 0xc1, 0xf8, 0x1e, 0x73, 0x43, 0x69, 0xc6, 0xb5, + 0xbd, 0xfd, 0x39, 0x63, 0x20, 0xd4, 0x38, 0x76, 0x7d, 0xb2, 0xa7, 0xcf, 0xed, 0x57, 0xc5, 0xf3, 0x2c, 0xbb, 0x14, + 0x21, 0x06, 0x55, 0x9b, 0xe3, 0xef, 0x5e, 0x31, 0x4f, 0x7f, 0x5a, 0xa4, 0x0d, 0x82, 0x51, 0x49, 0x5f, 0xba, 0x58, + 0x1c, 0x4a, 0x16, 0xd5, 0x17, 0xa8, 0x92, 0x24, 0x1f, 0x8c, 0xff, 0xd8, 0xae, 0x2e, 0x01, 0xd3, 0xad, 0x3b, 0x4b, + 0xda, 0x46, 0xeb, 0xc9, 0xde, 0x9a, 0x8f, 0x87, 0xd7, 0x3a, 0x80, 0x6f, 0x2f, 0xc8, 0xb1, 0xb4, 0x37, 0xf7, 0x0a, + 0x22, 0x13, 0x28, 0x7c, 0xcc, 0x3c, 0x89, 0xc7, 0xc3, 0x96, 0x56, 0x07, 0xbf, 0x7e, 0xf0, 0x0b, 0x2b, 0x97, 0x52, + 0x35, 0x41, 0x79, 0x61, 0xa6, 0x4c, 0x10, 0xfe, 0xbc, 0x26, 0x95, 0x88, 0x8a, 0xb0, 0xa3, 0xfb, 0xc0, 0x18, 0x94, + 0xf2, 0xe1, 0xe5, 0xe9, 0x5d, 0xd0, 0xdc, 0x11, 0x66, 0x64, 0x5c, 0xec, 0x59, 0x42, 0x75, 0x12, 0xf5, 0x74, 0x9c, + 0xaa, 0x23, 0x0e, 0x86, 0xab, 0xbe, 0x2a, 0x02, 0xe7, 0x67, 0xe6, 0x44, 0xa2, 0x6c, 0xc2, 0x93, 0x9f, 0xf1, 0xf6, + 0xfa, 0x36, 0xd2, 0x50, 0x68, 0x9e, 0x62, 0x71, 0x15, 0x3d, 0xd6, 0x40, 0xc4, 0xe2, 0x0f, 0x8e, 0x83, 0x77, 0x6b, + 0x25, 0x05, 0x3f, 0x0c, 0x30, 0xea, 0x70, 0xb7, 0xa1, 0xe8, 0xa9, 0x65, 0x8d, 0x27, 0x1a, 0xdb, 0x81, 0xb3, 0xa0, + 0xf4, 0x45, 0x7a, 0x19, 0xdf, 0xee, 0x78, 0x34, 0x60}; + +u8 S1[256] = { + 0x55, 0xc2, 0x63, 0x71, 0x3b, 0xc8, 0x47, 0x86, 0x9f, 0x3c, 0xda, 0x5b, 0x29, 0xaa, 0xfd, 0x77, 0x8c, 0xc5, 0x94, + 0x0c, 0xa6, 0x1a, 0x13, 0x00, 0xe3, 0xa8, 0x16, 0x72, 0x40, 0xf9, 0xf8, 0x42, 0x44, 0x26, 0x68, 0x96, 0x81, 0xd9, + 0x45, 0x3e, 0x10, 0x76, 0xc6, 0xa7, 0x8b, 0x39, 0x43, 0xe1, 0x3a, 0xb5, 0x56, 0x2a, 0xc0, 0x6d, 0xb3, 0x05, 0x22, + 0x66, 0xbf, 0xdc, 0x0b, 0xfa, 0x62, 0x48, 0xdd, 0x20, 0x11, 0x06, 0x36, 0xc9, 0xc1, 0xcf, 0xf6, 0x27, 0x52, 0xbb, + 0x69, 0xf5, 0xd4, 0x87, 0x7f, 0x84, 0x4c, 0xd2, 0x9c, 0x57, 0xa4, 0xbc, 0x4f, 0x9a, 0xdf, 0xfe, 0xd6, 0x8d, 0x7a, + 0xeb, 0x2b, 0x53, 0xd8, 0x5c, 0xa1, 0x14, 0x17, 0xfb, 0x23, 0xd5, 0x7d, 0x30, 0x67, 0x73, 0x08, 0x09, 0xee, 0xb7, + 0x70, 0x3f, 0x61, 0xb2, 0x19, 0x8e, 0x4e, 0xe5, 0x4b, 0x93, 0x8f, 0x5d, 0xdb, 0xa9, 0xad, 0xf1, 0xae, 0x2e, 0xcb, + 0x0d, 0xfc, 0xf4, 0x2d, 0x46, 0x6e, 0x1d, 0x97, 0xe8, 0xd1, 0xe9, 0x4d, 0x37, 0xa5, 0x75, 0x5e, 0x83, 0x9e, 0xab, + 0x82, 0x9d, 0xb9, 0x1c, 0xe0, 0xcd, 0x49, 0x89, 0x01, 0xb6, 0xbd, 0x58, 0x24, 0xa2, 0x5f, 0x38, 0x78, 0x99, 0x15, + 0x90, 0x50, 0xb8, 0x95, 0xe4, 0xd0, 0x91, 0xc7, 0xce, 0xed, 0x0f, 0xb4, 0x6f, 0xa0, 0xcc, 0xf0, 0x02, 0x4a, 0x79, + 0xc3, 0xde, 0xa3, 0xef, 0xea, 0x51, 0xe6, 0x6b, 0x18, 0xec, 0x1b, 0x2c, 0x80, 0xf7, 0x74, 0xe7, 0xff, 0x21, 0x5a, + 0x6a, 0x54, 0x1e, 0x41, 0x31, 0x92, 0x35, 0xc4, 0x33, 0x07, 0x0a, 0xba, 0x7e, 0x0e, 0x34, 0x88, 0xb1, 0x98, 0x7c, + 0xf3, 0x3d, 0x60, 0x6c, 0x7b, 0xca, 0xd3, 0x1f, 0x32, 0x65, 0x04, 0x28, 0x64, 0xbe, 0x85, 0x9b, 0x2f, 0x59, 0x8a, + 0xd7, 0xb0, 0x25, 0xac, 0xaf, 0x12, 0x03, 0xe2, 0xf2}; + +/* the constants D */ +u32 EK_d[16] = {0x44D7, + 0x26BC, + 0x626B, + 0x135E, + 0x5789, + 0x35E2, + 0x7135, + 0x09AF, + 0x4D78, + 0x2F13, + 0x6BC4, + 0x1AF1, + 0x5E26, + 0x3C4D, + 0x789A, + 0x47AC}; + +/* ——————————————————————- */ +/* c = a + b mod (2^31 – 1) */ +u32 AddM(u32 a, u32 b) +{ + u32 c = a + b; + return (c & 0x7FFFFFFF) + (c >> 31); +} + +/* LFSR with initialization mode */ +void LFSRWithInitialisationMode(zuc_state_t* state, u32 u) +{ + u32 f, v; + f = state->LFSR_S0; + v = MulByPow2(state->LFSR_S0, 8); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S4, 20); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S10, 21); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S13, 17); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S15, 15); + f = AddM(f, v); + f = AddM(f, u); + + /* update the state */ + state->LFSR_S0 = state->LFSR_S1; + state->LFSR_S1 = state->LFSR_S2; + state->LFSR_S2 = state->LFSR_S3; + state->LFSR_S3 = state->LFSR_S4; + state->LFSR_S4 = state->LFSR_S5; + state->LFSR_S5 = state->LFSR_S6; + state->LFSR_S6 = state->LFSR_S7; + state->LFSR_S7 = state->LFSR_S8; + state->LFSR_S8 = state->LFSR_S9; + state->LFSR_S9 = state->LFSR_S10; + state->LFSR_S10 = state->LFSR_S11; + state->LFSR_S11 = state->LFSR_S12; + state->LFSR_S12 = state->LFSR_S13; + state->LFSR_S13 = state->LFSR_S14; + state->LFSR_S14 = state->LFSR_S15; + state->LFSR_S15 = f; +} + +/* LFSR with work mode */ +void LFSRWithWorkMode(zuc_state_t* state) +{ + u32 f, v; + f = state->LFSR_S0; + v = MulByPow2(state->LFSR_S0, 8); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S4, 20); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S10, 21); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S13, 17); + f = AddM(f, v); + v = MulByPow2(state->LFSR_S15, 15); + f = AddM(f, v); + + /* update the state */ + state->LFSR_S0 = state->LFSR_S1; + state->LFSR_S1 = state->LFSR_S2; + state->LFSR_S2 = state->LFSR_S3; + state->LFSR_S3 = state->LFSR_S4; + state->LFSR_S4 = state->LFSR_S5; + state->LFSR_S5 = state->LFSR_S6; + state->LFSR_S6 = state->LFSR_S7; + state->LFSR_S7 = state->LFSR_S8; + state->LFSR_S8 = state->LFSR_S9; + state->LFSR_S9 = state->LFSR_S10; + state->LFSR_S10 = state->LFSR_S11; + state->LFSR_S11 = state->LFSR_S12; + state->LFSR_S12 = state->LFSR_S13; + state->LFSR_S13 = state->LFSR_S14; + state->LFSR_S14 = state->LFSR_S15; + state->LFSR_S15 = f; +} + +/* BitReorganization */ +void BitReorganization(zuc_state_t* state) +{ + state->BRC_X0 = ((state->LFSR_S15 & 0x7FFF8000) << 1) | (state->LFSR_S14 & 0xFFFF); + state->BRC_X1 = ((state->LFSR_S11 & 0xFFFF) << 16) | (state->LFSR_S9 >> 15); + state->BRC_X2 = ((state->LFSR_S7 & 0xFFFF) << 16) | (state->LFSR_S5 >> 15); + state->BRC_X3 = ((state->LFSR_S2 & 0xFFFF) << 16) | (state->LFSR_S0 >> 15); +} + +/* L1 */ +u32 L1(u32 X) +{ + return (X ^ ROT(X, 2) ^ ROT(X, 10) ^ ROT(X, 18) ^ ROT(X, 24)); +} + +/* L2 */ +u32 L2(u32 X) +{ + return (X ^ ROT(X, 8) ^ ROT(X, 14) ^ ROT(X, 22) ^ ROT(X, 30)); +} + +/* F */ +u32 F(zuc_state_t* state) +{ + u32 W, W1, W2, u, v; + W = (state->BRC_X0 ^ state->F_R1) + state->F_R2; + W1 = state->F_R1 + state->BRC_X1; + W2 = state->F_R2 ^ state->BRC_X2; + u = L1((W1 << 16) | (W2 >> 16)); + v = L2((W2 << 16) | (W1 >> 16)); + + state->F_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF], S0[(u >> 8) & 0xFF], S1[u & 0xFF]); + state->F_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF], S0[(v >> 8) & 0xFF], S1[v & 0xFF]); + return W; +} + +/* initialize */ + +void zuc_initialize(zuc_state_t* state, u8* k, u8* iv) +{ + u32 w, nCount; + + /* expand key */ + state->LFSR_S0 = MAKEU31(k[0], EK_d[0], iv[0]); + state->LFSR_S1 = MAKEU31(k[1], EK_d[1], iv[1]); + state->LFSR_S2 = MAKEU31(k[2], EK_d[2], iv[2]); + state->LFSR_S3 = MAKEU31(k[3], EK_d[3], iv[3]); + state->LFSR_S4 = MAKEU31(k[4], EK_d[4], iv[4]); + state->LFSR_S5 = MAKEU31(k[5], EK_d[5], iv[5]); + state->LFSR_S6 = MAKEU31(k[6], EK_d[6], iv[6]); + state->LFSR_S7 = MAKEU31(k[7], EK_d[7], iv[7]); + state->LFSR_S8 = MAKEU31(k[8], EK_d[8], iv[8]); + state->LFSR_S9 = MAKEU31(k[9], EK_d[9], iv[9]); + state->LFSR_S10 = MAKEU31(k[10], EK_d[10], iv[10]); + state->LFSR_S11 = MAKEU31(k[11], EK_d[11], iv[11]); + state->LFSR_S12 = MAKEU31(k[12], EK_d[12], iv[12]); + state->LFSR_S13 = MAKEU31(k[13], EK_d[13], iv[13]); + state->LFSR_S14 = MAKEU31(k[14], EK_d[14], iv[14]); + state->LFSR_S15 = MAKEU31(k[15], EK_d[15], iv[15]); + + /* set F_R1 and F_R2 to zero */ + state->F_R1 = 0; + state->F_R2 = 0; + nCount = 32; + while (nCount > 0) { + BitReorganization(state); + w = F(state); + LFSRWithInitialisationMode(state, w >> 1); + nCount--; + } +} + +void zuc_generate_keystream(zuc_state_t* state, int key_stream_len, u32* p_keystream) +{ + int i; + { + BitReorganization(state); + F(state); /* discard the output of F */ + LFSRWithWorkMode(state); + } + for (i = 0; i < key_stream_len; i++) { + BitReorganization(state); + p_keystream[i] = F(state) ^ state->BRC_X3; + LFSRWithWorkMode(state); + } +} diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 1356e8270..5435709bf 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -864,7 +864,7 @@ static void fill_res(srslte_chest_dl_t* q, srslte_chest_dl_res_t* res) } else { res->snr_ant_port_db[a][port_id] = 0.0; } - res->rsrp_ant_port_dbm[a][port_id] = db(q->rsrp[a][port_id]); + res->rsrp_ant_port_dbm[a][port_id] = dbm(q->rsrp[a][port_id]); res->rsrq_ant_port_db[a][port_id] = db(q->cell.nof_prb * q->rsrp[a][port_id] / q->rssi[a][port_id]); } } diff --git a/lib/src/phy/channel/channel.cc b/lib/src/phy/channel/channel.cc index 4de69e736..d43b1be34 100644 --- a/lib/src/phy/channel/channel.cc +++ b/lib/src/phy/channel/channel.cc @@ -55,13 +55,24 @@ channel::channel(const channel::args_t& channel_args, uint32_t _nof_ports) // Create delay if (channel_args.delay_enable && ret == SRSLTE_SUCCESS) { delay[i] = (srslte_channel_delay_t*)calloc(sizeof(srslte_channel_delay_t), 1); - ret = srslte_channel_delay_init( - delay[i], channel_args.delay_min_us, channel_args.delay_max_us, channel_args.delay_period_s, srate_max); + ret = srslte_channel_delay_init(delay[i], + channel_args.delay_min_us, + channel_args.delay_max_us, + channel_args.delay_period_s, + channel_args.delay_init_time_s, + srate_max); } else { delay[i] = nullptr; } } + // Create high speed train + if (channel_args.hst_enable && ret == SRSLTE_SUCCESS) { + hst = (srslte_channel_hst_t*)calloc(sizeof(srslte_channel_hst_t), 1); + srslte_channel_hst_init(hst, channel_args.hst_fd_hz, channel_args.hst_period_s, channel_args.hst_init_time_s); + } + + // Create Radio Link Failure simulator if (channel_args.rlf_enable && ret == SRSLTE_SUCCESS) { rlf = (srslte_channel_rlf_t*)calloc(sizeof(srslte_channel_rlf_t), 1); srslte_channel_rlf_init(rlf, channel_args.rlf_t_on_ms, channel_args.rlf_t_off_ms); @@ -82,6 +93,11 @@ channel::~channel() free(buffer_out); } + if (hst) { + srslte_channel_hst_free(hst); + free(hst); + } + if (rlf) { srslte_channel_rlf_free(rlf); free(rlf); @@ -100,6 +116,11 @@ channel::~channel() } } +void channel::set_logger(log_filter* _log_h) +{ + log_h = _log_h; +} + void channel::run(cf_t* in[SRSLTE_MAX_PORTS], cf_t* out[SRSLTE_MAX_PORTS], uint32_t len, const srslte_timestamp_t& t) { // check input pointers @@ -121,6 +142,11 @@ void channel::run(cf_t* in[SRSLTE_MAX_PORTS], cf_t* out[SRSLTE_MAX_PORTS], uint3 memcpy(buffer_in, buffer_out, sizeof(cf_t) * len); } + if (hst) { + srslte_channel_hst_execute(hst, buffer_in, buffer_out, len, &t); + memcpy(buffer_in, buffer_out, sizeof(cf_t) * len); + } + if (rlf) { srslte_channel_rlf_execute(rlf, buffer_in, buffer_out, len, &t); memcpy(buffer_in, buffer_out, sizeof(cf_t) * len); @@ -130,6 +156,24 @@ void channel::run(cf_t* in[SRSLTE_MAX_PORTS], cf_t* out[SRSLTE_MAX_PORTS], uint3 memcpy(out[i], buffer_in, sizeof(cf_t) * len); } } + + if (log_h) { + // Logging + std::stringstream str; + + str << "t=" << t.full_secs + t.frac_secs << "s; "; + + if (delay[0]) { + str << "delay=" << delay[0]->delay_us << "us; "; + } + + if (hst) { + str << "hst=" << hst->fs_hz << "Hz; "; + } + + log_h->debug("%s\n", str.str().c_str()); + } + } else { for (uint32_t i = 0; i < nof_ports; i++) { // Check buffers are not null @@ -156,5 +200,9 @@ void channel::set_srate(uint32_t srate) } current_srate = srate; } + + if (hst) { + srslte_channel_hst_update_srate(hst, srate); + } } } diff --git a/lib/src/phy/channel/delay.c b/lib/src/phy/channel/delay.c index 200add5a9..c7c902db7 100644 --- a/lib/src/phy/channel/delay.c +++ b/lib/src/phy/channel/delay.c @@ -23,18 +23,27 @@ #include #include -static inline double caulculate_delay_us(srslte_channel_delay_t* q, const srslte_timestamp_t* ts) +static inline double calculate_delay_us(srslte_channel_delay_t* q, const srslte_timestamp_t* ts) { - uint32_t mod_secs = (uint32_t)(ts->full_secs % q->period_s); - double arg = 2.0 * M_PI * ((double)mod_secs + ts->frac_secs) / (double)q->period_s; + // Convert period from seconds to samples + uint64_t period_nsamples = (uint64_t)roundf(q->period_s * q->srate_hz); + + // Convert timestamp to samples + uint64_t ts_nsamples = srslte_timestamp_uint64(ts, q->srate_hz) + (uint64_t)q->init_time_s * q->srate_hz; + + // Calculate time modulus in period + uint64_t mod_t_nsamples = ts_nsamples - period_nsamples * (ts_nsamples / period_nsamples); + double t = (double)mod_t_nsamples / (double)q->srate_hz; + + double arg = 2.0 * M_PI * t / (double)q->period_s; double delay_us = q->delay_min_us + (q->delay_max_us - q->delay_min_us) * (1.0 + sin(arg)) / 2.0; return delay_us; } -static inline uint32_t caulculate_delay_nsamples(srslte_channel_delay_t* q, double delay_us) +static inline uint32_t calculate_delay_nsamples(srslte_channel_delay_t* q) { - return (uint32_t)round(delay_us * (double)q->srate_hz / 1e6); + return (uint32_t)round(q->delay_us * (double)q->srate_hz / 1e6); } static inline uint32_t ringbuffer_available_nsamples(srslte_channel_delay_t* q) @@ -42,8 +51,12 @@ static inline uint32_t ringbuffer_available_nsamples(srslte_channel_delay_t* q) return srslte_ringbuffer_status(&q->rb) / sizeof(cf_t); } -int srslte_channel_delay_init( - srslte_channel_delay_t* q, float delay_min_us, float delay_max_us, uint32_t period_s, uint32_t srate_max_hz) +int srslte_channel_delay_init(srslte_channel_delay_t* q, + float delay_min_us, + float delay_max_us, + float period_s, + float init_time_s, + uint32_t srate_max_hz) { // Calculate buffer size uint32_t buff_size = (uint32_t)ceilf(delay_max_us * (float)srate_max_hz / 1e6f); @@ -63,6 +76,7 @@ int srslte_channel_delay_init( q->srate_max_hz = srate_max_hz; q->srate_hz = srate_max_hz; q->period_s = period_s; + q->init_time_s = init_time_s; return ret; } @@ -85,18 +99,18 @@ void srslte_channel_delay_free(srslte_channel_delay_t* q) void srslte_channel_delay_execute( srslte_channel_delay_t* q, const cf_t* in, cf_t* out, uint32_t len, const srslte_timestamp_t* ts) { - double delay_us = caulculate_delay_us(q, ts); - uint32_t delay_nsamples = caulculate_delay_nsamples(q, delay_us); + q->delay_us = calculate_delay_us(q, ts); + q->delay_nsamples = calculate_delay_nsamples(q); uint32_t available_nsamples = ringbuffer_available_nsamples(q); - uint32_t read_nsamples = SRSLTE_MIN(delay_nsamples, len); + uint32_t read_nsamples = SRSLTE_MIN(q->delay_nsamples, len); uint32_t copy_nsamples = (len > read_nsamples) ? (len - read_nsamples) : 0; - if (available_nsamples < delay_nsamples) { - uint32_t nzeros = delay_nsamples - available_nsamples; + if (available_nsamples < q->delay_nsamples) { + uint32_t nzeros = q->delay_nsamples - available_nsamples; bzero(q->zero_buffer, sizeof(cf_t) * nzeros); srslte_ringbuffer_write(&q->rb, q->zero_buffer, sizeof(cf_t) * nzeros); - } else if (available_nsamples > delay_nsamples) { - srslte_ringbuffer_read(&q->rb, q->zero_buffer, sizeof(cf_t) * (available_nsamples - delay_nsamples)); + } else if (available_nsamples > q->delay_nsamples) { + srslte_ringbuffer_read(&q->rb, q->zero_buffer, sizeof(cf_t) * (available_nsamples - q->delay_nsamples)); } // Read buffered samples diff --git a/lib/src/phy/channel/hst.c b/lib/src/phy/channel/hst.c new file mode 100644 index 000000000..c383b916b --- /dev/null +++ b/lib/src/phy/channel/hst.c @@ -0,0 +1,87 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/phy/channel/hst.h" + +int srslte_channel_hst_init(srslte_channel_hst_t* q, float fd_hz, float period_d, float init_time_s) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q) { + q->fd_hz = fd_hz; // Hz + q->ds_m = 300.0f; // m + q->dmin_m = 2.0f; // m + q->period_s = period_d; // s + q->init_time_s = init_time_s; // s + q->fs_hz = NAN; + ret = SRSLTE_SUCCESS; + } + + return ret; +} + +void srslte_channel_hst_update_srate(srslte_channel_hst_t* q, uint32_t srate) +{ + if (q) { + q->srate_hz = srate; + } +} + +void srslte_channel_hst_execute( + srslte_channel_hst_t* q, cf_t* in, cf_t* out, uint32_t len, const srslte_timestamp_t* ts) +{ + if (q && q->srate_hz) { + // Convert period from seconds to samples + uint64_t period_nsamples = (uint64_t)roundf(q->period_s * q->srate_hz); + + // Convert timestamp to samples + uint64_t ts_nsamples = srslte_timestamp_uint64(ts, q->srate_hz) + (uint64_t)q->init_time_s * q->srate_hz; + + // Calculate time modulus in period + uint64_t mod_t_nsamples = ts_nsamples - period_nsamples * (ts_nsamples / period_nsamples); + float t = (float)mod_t_nsamples / (float)q->srate_hz; + + float costheta = 0; + + if (0 <= t && t <= q->period_s / 2.0f) { + float num = q->period_s / 4.0f - t; + float den = sqrtf(powf(q->dmin_m * q->period_s / (q->ds_m * 2), 2.0f) + powf(num, 2.0f)); + costheta = num / den; + } else if (q->period_s / 2.0f < t && t < q->period_s) { + float num = -1.5f / 2.0f * q->period_s + t; + float den = sqrtf(powf(q->dmin_m * q->period_s / (q->ds_m * 2), 2.0f) + powf(num, 2.0f)); + costheta = num / den; + } + + // Calculate doppler shift + q->fs_hz = q->fd_hz * costheta; + + // Apply doppler shift, assume the doppler does not vary in a sub-frame + srslte_vec_apply_cfo(in, -q->fs_hz / q->srate_hz, out, len); + } +} + +void srslte_channel_hst_free(srslte_channel_hst_t* q) +{ + if (q) { + bzero(q, sizeof(srslte_channel_hst_t)); + } +} diff --git a/lib/src/phy/channel/test/CMakeLists.txt b/lib/src/phy/channel/test/CMakeLists.txt index 77f68594f..3578864eb 100644 --- a/lib/src/phy/channel/test/CMakeLists.txt +++ b/lib/src/phy/channel/test/CMakeLists.txt @@ -33,3 +33,7 @@ add_executable(delay_channel_test delay_channel_test.c) target_link_libraries(delay_channel_test srslte_phy srslte_common srslte_phy ${SEC_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) add_test(delay_channel_test delay_channel_test -m 10 -M 100 -t 1000 -T 1 -s 1.92e6) +add_executable(hst_channel_test hst_channel_test.c) +target_link_libraries(hst_channel_test srslte_phy srslte_common srslte_phy ${SEC_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +add_test(hst_channel_test hst_channel_test -f 750 -t 7.2 -i 0 -T 1 -s 1.92e6) + diff --git a/lib/src/phy/channel/test/delay_channel_test.c b/lib/src/phy/channel/test/delay_channel_test.c index aad5514dc..14e2192ec 100644 --- a/lib/src/phy/channel/test/delay_channel_test.c +++ b/lib/src/phy/channel/test/delay_channel_test.c @@ -29,7 +29,8 @@ static srslte_channel_delay_t delay = {}; static uint32_t delay_min_us = 10; static uint32_t delay_max_us = 3333; -static uint32_t delay_period_s = 1; +static float delay_period_s = 1; +static float delay_init_time_s = 0; static uint32_t srate_hz = 1920000; static uint32_t sim_time_periods = 1; @@ -40,7 +41,7 @@ static void usage(char* prog) printf("Usage: %s [mMtsT]\n", prog); printf("\t-m Minimum delay in microseconds [Default %d]\n", delay_min_us); printf("\t-M Maximum delay in microseconds [Default %d]\n", delay_max_us); - printf("\t-t Delay period in seconds: [Default %d]\n", delay_period_s); + printf("\t-t Delay period in seconds: [Default %.1f]\n", delay_period_s); printf("\t-s Sampling rate in Hz: [Default %d]\n", srate_hz); printf("\t-T Simulation Time in periods: [Default %d]\n", sim_time_periods); } @@ -98,7 +99,7 @@ int main(int argc, char** argv) // Initialise delay channel if (ret == SRSLTE_SUCCESS) { - ret = srslte_channel_delay_init(&delay, delay_min_us, delay_max_us, delay_period_s, srate_hz); + ret = srslte_channel_delay_init(&delay, delay_min_us, delay_max_us, delay_period_s, delay_init_time_s, srate_hz); } // Run actual test @@ -131,7 +132,7 @@ int main(int argc, char** argv) double elapsed_us = t[0].tv_sec * 1e6 + t[0].tv_usec; // Print result and exit - printf("Test delay_min_us=%d; delay_max_us=%d; delay_period_s=%d; srate_hz=%d; periods=%d; %s ... %.1f MSps\n", + printf("Test delay_min_us=%d; delay_max_us=%d; delay_period_s=%.1f; srate_hz=%d; periods=%d; %s ... %.1f MSps\n", delay_min_us, delay_max_us, delay_period_s, diff --git a/lib/src/phy/channel/test/hst_channel_test.c b/lib/src/phy/channel/test/hst_channel_test.c new file mode 100644 index 000000000..6cee302ff --- /dev/null +++ b/lib/src/phy/channel/test/hst_channel_test.c @@ -0,0 +1,151 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/phy/utils/vector.h" +#include +#include +#include + +static srslte_channel_hst_t hst = {}; + +static float fd_hz = 750; +static float period_s = 7.2; +static float init_time_s = 0; +static uint32_t srate_hz = 1920000; +static uint32_t sim_time_periods = 1; + +#define INPUT_TYPE 0 /* 0: Dirac Delta; Otherwise: Random*/ + +static void usage(char* prog) +{ + printf("Usage: %s [mMtsT]\n", prog); + printf("\t-f Doppler frequency [Default %.1f]\n", fd_hz); + printf("\t-t Period in seconds: [Default %.1f]\n", period_s); + printf("\t-i Initial time in seconds: [Default %.1f]\n", init_time_s); + printf("\t-s Sampling rate in Hz: [Default %d]\n", srate_hz); + printf("\t-T Simulation Time in periods: [Default %d]\n", sim_time_periods); +} + +static void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "ftisT")) != -1) { + switch (opt) { + case 'f': + fd_hz = strtof(argv[optind], NULL); + break; + case 't': + period_s = strtof(argv[optind], NULL); + break; + case 'i': + init_time_s = strtof(argv[optind], NULL); + break; + case 's': + srate_hz = (uint32_t)strtof(argv[optind], NULL); + break; + case 'T': + sim_time_periods = (uint32_t)strtol(argv[optind], NULL, 10); + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +int main(int argc, char** argv) +{ + int ret = SRSLTE_SUCCESS; + cf_t* input_buffer = NULL; + cf_t* output_buffer = NULL; + srslte_timestamp_t ts = {}; // Initialised to zero + struct timeval t[3] = {}; + + // Parse arguments + parse_args(argc, argv); + + // Initialise buffers + uint32_t size = srate_hz / 1000; // 1 ms samples + input_buffer = srslte_vec_malloc(sizeof(cf_t) * size); + output_buffer = srslte_vec_malloc(sizeof(cf_t) * size); + if (!input_buffer || !output_buffer) { + fprintf(stderr, "Error: Allocating memory\n"); + ret = SRSLTE_ERROR; + } + + // Generate random samples + if (ret == SRSLTE_SUCCESS) { + srslte_vec_gen_sine(1.0f, 0.0f, input_buffer, size); + } + + // Initialise delay channel + if (ret == SRSLTE_SUCCESS) { + ret = srslte_channel_hst_init(&hst, fd_hz, period_s, init_time_s); + srslte_channel_hst_update_srate(&hst, srate_hz); + } + + // Run actual test + gettimeofday(&t[1], NULL); + for (int i = 0; i < sim_time_periods && ret == SRSLTE_SUCCESS; i++) { + for (int j = 0; j < 1000 * period_s; j++) { + // Run delay channel + srslte_channel_hst_execute(&hst, input_buffer, output_buffer, size, &ts); + + // Increment timestamp 1ms + srslte_timestamp_add(&ts, 0, 0.001); + + float ideal_freq = hst.fs_hz; + float meas_freq = srslte_vec_estimate_frequency(output_buffer, size) * srate_hz; + // printf("[%03d.%03d] fs = [%6.1f | %6.1f] Hz\n", i, j, ideal_freq, meas_freq); + if (fabsf(ideal_freq - meas_freq) > 0.5f) { + printf("Error [%03d.%03d] fs = [%6.1f | %6.1f] Hz\n", i, j, ideal_freq, meas_freq); + return SRSLTE_ERROR; + } + } + } + gettimeofday(&t[2], NULL); + get_time_interval(t); + + // Free + srslte_channel_hst_free(&hst); + + if (input_buffer) { + free(input_buffer); + } + + if (output_buffer) { + free(output_buffer); + } + + uint64_t nof_samples = sim_time_periods * (uint64_t)(1000 * period_s) * size; + double elapsed_us = t[0].tv_sec * 1e6 + t[0].tv_usec; + + // Print result and exit + printf("Test fd=%.1fHz; period=%.1fs; init_time=%.1fs; srate_hz=%d; periods=%d; %s ... %.1f MSps\n", + fd_hz, + period_s, + init_time_s, + srate_hz, + sim_time_periods, + (ret == SRSLTE_SUCCESS) ? "Passed" : "Failed", + (double)nof_samples / elapsed_us); + exit(ret); +} diff --git a/lib/src/phy/common/phy_common.c b/lib/src/phy/common/phy_common.c index 52699d06e..062a001db 100644 --- a/lib/src/phy/common/phy_common.c +++ b/lib/src/phy/common/phy_common.c @@ -46,7 +46,7 @@ bool srslte_cellid_isvalid(uint32_t cell_id) { } bool srslte_nofprb_isvalid(uint32_t nof_prb) { - if (nof_prb >= 6 && nof_prb <= SRSLTE_MAX_PRB) { + if (nof_prb >= 6 && nof_prb <= 100) { return true; } else { return false; @@ -739,3 +739,42 @@ uint32_t srslte_print_check(char* s, size_t max_len, uint32_t cur_len, const cha } return cur_len; } + +bool srslte_nbiot_prb_isvalid(srslte_nbiot_cell_t* cell) +{ + if (cell->nbiot_prb <= cell->base.nof_prb) { + return true; + } + return false; +} + +bool srslte_nbiot_cell_isvalid(srslte_nbiot_cell_t* cell) +{ + return (srslte_cell_isvalid(&cell->base) && srslte_nbiot_portid_isvalid(cell->nof_ports) && + srslte_nbiot_prb_isvalid(cell) && srslte_cellid_isvalid(cell->n_id_ncell)); +} + +bool srslte_nbiot_portid_isvalid(uint32_t port_id) +{ + if (port_id <= SRSLTE_NBIOT_MAX_PORTS) { + return true; + } else { + return false; + } +} + +char* srslte_nbiot_mode_string(srslte_nbiot_mode_t mode) +{ + switch (mode) { + case SRSLTE_NBIOT_MODE_INBAND_SAME_PCI: + return "Inband (Same PCI)"; + case SRSLTE_NBIOT_MODE_INBAND_DIFFERENT_PCI: + return "Inband (Different PCI)"; + case SRSLTE_NBIOT_MODE_GUARDBAND: + return "Guardband"; + case SRSLTE_NBIOT_MODE_STANDALONE: + return "Standalone"; + default: + return "N/A"; + } +} \ No newline at end of file diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index 33c176481..5c27e8faa 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -580,14 +580,13 @@ void srslte_ofdm_set_normalize(srslte_ofdm_t *q, bool normalize_enable) { void srslte_ofdm_tx_sf(srslte_ofdm_t *q) { uint32_t n; - if(!q->mbsfn_subframe){ + if (!q->mbsfn_subframe) { for (n=0;n<2;n++) { srslte_ofdm_tx_slot(q, n); } - } - else{ - srslte_ofdm_tx_slot_mbsfn(q, &q->in_buffer[0*q->nof_re*q->nof_symbols], &q->out_buffer[0*q->slot_sz]); - srslte_ofdm_tx_slot(q, 1); + } else { + srslte_ofdm_tx_slot_mbsfn(q, &q->in_buffer[0 * q->nof_re * q->nof_symbols], &q->out_buffer[0 * q->slot_sz]); + srslte_ofdm_tx_slot(q, 1); } if (q->freq_shift) { srslte_vec_prod_ccc(q->out_buffer, q->shift_buffer, q->out_buffer, 2*q->slot_sz); diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index 40900d1c2..0cc695663 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -217,7 +217,7 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t* q, // If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // try again to decode ACK only - if (cfg->uci_cfg.is_scheduling_request_tti && cfg->uci_cfg.ack.nof_acks && !res->detected) { + if (cfg->uci_cfg.is_scheduling_request_tti && srslte_uci_cfg_total_ack(&cfg->uci_cfg) && !res->detected) { cfg->uci_cfg.is_scheduling_request_tti = false; if (get_pucch(q, ul_sf, cfg, res)) { return -1; diff --git a/lib/src/phy/fec/softbuffer.c b/lib/src/phy/fec/softbuffer.c index 9d0ba07e4..9523eb7a2 100644 --- a/lib/src/phy/fec/softbuffer.c +++ b/lib/src/phy/fec/softbuffer.c @@ -138,11 +138,15 @@ void srslte_softbuffer_rx_reset_cb(srslte_softbuffer_rx_t *q, uint32_t nof_cb) { if (q->buffer_f[i]) { bzero(q->buffer_f[i], SOFTBUFFER_SIZE*sizeof(int16_t)); } + if (q->data[i]) { + bzero(q->data[i], sizeof(uint8_t) * 6144 / 8); + } } } if (q->cb_crc) { bzero(q->cb_crc, sizeof(bool) * q->max_cb); } + q->tb_crc = false; } diff --git a/lib/src/phy/io/filesource.c b/lib/src/phy/io/filesource.c index 8cf6dad86..3f4f4ee8d 100644 --- a/lib/src/phy/io/filesource.c +++ b/lib/src/phy/io/filesource.c @@ -52,7 +52,7 @@ void srslte_filesource_seek(srslte_filesource_t *q, int pos) { int read_complex_f(FILE *f, _Complex float *y) { char in_str[64]; - _Complex float x; + _Complex float x = 0; if (NULL == fgets(in_str, 64, f)) { return -1; } else { diff --git a/lib/src/phy/io/netsource.c b/lib/src/phy/io/netsource.c index 1cb779eed..139860129 100644 --- a/lib/src/phy/io/netsource.c +++ b/lib/src/phy/io/netsource.c @@ -111,6 +111,22 @@ int srslte_netsource_read(srslte_netsource_t *q, void *buffer, int nbytes) { } } +int srslte_netsource_write(srslte_netsource_t* q, void* buffer, int nbytes) +{ + // Loop until all bytes are sent + char* ptr = (char*)buffer; + while (nbytes > 0) { + ssize_t i = send(q->connfd, ptr, nbytes, 0); + if (i < 1) { + perror("Error calling send()\n"); + return SRSLTE_ERROR; + } + ptr += i; + nbytes -= i; + } + return SRSLTE_SUCCESS; +} + int srslte_netsource_set_nonblocking(srslte_netsource_t *q) { if (fcntl(q->sockfd, F_SETFL, O_NONBLOCK)) { perror("fcntl"); diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 03fb20d65..acfa4abaa 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -501,7 +501,23 @@ static int dci_format0_unpack( } // CQI request - dci->cqi_request = *y++ ? true : false; + if (cfg->multiple_csi_request_enabled) { + dci->multiple_csi_request_present = true; + dci->multiple_csi_request = srslte_bit_pack(&y, 2); + } else { + dci->cqi_request = *y++ ? true : false; + } + + // SRS request + if (cfg->srs_request_enabled) { + dci->srs_request_present = true; + dci->srs_request = *y++ ? true : false; + } + + if (cfg->ra_format_enabled) { + dci->ra_type_present = true; + dci->ra_type = *y++ ? true : false; + } return SRSLTE_SUCCESS; } @@ -1373,7 +1389,7 @@ char* srslte_dci_format_string_short(srslte_dci_format_t format) { } } -char* ra_type_string(srslte_ra_type_t alloc_type) +static char* ra_type_string(srslte_ra_type_t alloc_type) { switch (alloc_type) { case SRSLTE_RA_ALLOC_TYPE0: @@ -1387,6 +1403,21 @@ char* ra_type_string(srslte_ra_type_t alloc_type) } } +static char* freq_hop_fl_string(int freq_hop) +{ + switch (freq_hop) { + case 0: + return "1/4"; + case 1: + return "-1/4"; + case 2: + return "1/2"; + case 3: + return "type2"; + } + return "n/a"; +} + void srslte_dci_dl_fprint(FILE* f, srslte_dci_dl_t* dci, uint32_t nof_prb) { fprintf(f, " - Resource Allocation Type:\t\t%s\n", ra_type_string(dci->alloc_type)); @@ -1490,9 +1521,6 @@ uint32_t srslte_dci_dl_info(srslte_dci_dl_t* dci_dl, char* info_str, uint32_t le n = srslte_print_check(info_str, len, n, ", mcs={", 0); n = print_multi(info_str, n, len, dci_dl, 0); n = srslte_print_check(info_str, len, n, "}", 0); - n = srslte_print_check(info_str, len, n, ", rv={", 0); - n = print_multi(info_str, n, len, dci_dl, 1); - n = srslte_print_check(info_str, len, n, "}", 0); n = srslte_print_check(info_str, len, n, ", ndi={", 0); n = print_multi(info_str, n, len, dci_dl, 2); n = srslte_print_check(info_str, len, n, "}", 0); @@ -1519,25 +1547,39 @@ uint32_t srslte_dci_ul_info(srslte_dci_ul_t* dci_ul, char* info_str, uint32_t le { uint32_t n = 0; - n = srslte_print_check(info_str, len, 0, "f=0, cce=%2d, L=%d", dci_ul->location.ncce, dci_ul->location.L); + n = srslte_print_check(info_str, len, n, "f=0, "); - n = srslte_print_check(info_str, len, n, ", riv=%d", dci_ul->type2_alloc.riv); + if (dci_ul->cif_present) { + n = srslte_print_check(info_str, len, n, "cif=%d, ", dci_ul->cif); + } - n = srslte_print_check( - info_str, len, n, ", mcs=%d, rv=%d, ndi=%d", dci_ul->tb.mcs_idx, dci_ul->tb.rv, dci_ul->tb.ndi); + n = srslte_print_check(info_str, + len, + n, + "cce=%2d, L=%d, riv=%d, mcs=%d, rv=%d, ndi=%d, f_h=%s, cqi=%s, tpc_pusch=%d, dmrs_cs=%d", + dci_ul->location.ncce, + dci_ul->location.L, + dci_ul->type2_alloc.riv, + dci_ul->tb.mcs_idx, + dci_ul->tb.rv, + dci_ul->tb.ndi, + freq_hop_fl_string(dci_ul->freq_hop_fl), + dci_ul->cqi_request ? "yes" : "no", + dci_ul->tpc_pusch, + dci_ul->n_dmrs); - if (dci_ul->is_tdd) { - n = srslte_print_check(info_str, len, n, ", ul_idx=%d", dci_ul->ul_idx); + if (dci_ul->multiple_csi_request_present) { + n = srslte_print_check(info_str, len, n, ", csi=%d", dci_ul->multiple_csi_request); } - - if (dci_ul->is_tdd) { - n = srslte_print_check(info_str, len, n, ", dai=%d", dci_ul->dai); + if (dci_ul->srs_request_present) { + n = srslte_print_check(info_str, len, n, ", srs_request=%s", dci_ul->srs_request ? "yes" : "no"); + } + if (dci_ul->ra_type_present) { + n = srslte_print_check(info_str, len, n, ", ra_type=%s", dci_ul->ra_type ? "yes" : "no"); } - n = srslte_print_check(info_str, len, n, ", tpc_pusch=%d, dmrs_cs=%d", dci_ul->tpc_pusch, dci_ul->n_dmrs); - - if (dci_ul->cqi_request) { - n = srslte_print_check(info_str, len, n, ", cqi_request"); + if (dci_ul->is_tdd) { + n = srslte_print_check(info_str, len, n, ", ul_idx=%d, dai=%d", dci_ul->ul_idx, dci_ul->dai); } return n; diff --git a/lib/src/phy/phch/pdcch.c b/lib/src/phy/phch/pdcch.c index 10d429948..9f7fb1792 100644 --- a/lib/src/phy/phch/pdcch.c +++ b/lib/src/phy/phch/pdcch.c @@ -296,7 +296,9 @@ uint32_t srslte_pdcch_common_locations_ncce(uint32_t nof_cce, srslte_dci_locatio for (l = 3; l > 1; l--) { L = (1 << l); for (i = 0; i < SRSLTE_MIN(nof_cce, 16) / (L); i++) { - uint32_t ncce = (L) * (i % (nof_cce / (L))); + // Simplified expression, derived from: + // L * ((Yk + m) % (N_cce / L)) + i + uint32_t ncce = L * i; if (k < max_candidates && ncce + L <= nof_cce) { c[k].L = l; c[k].ncce = ncce; diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index 44c19c06c..501121a1f 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -571,7 +571,7 @@ static int encode_bits(srslte_pucch_cfg_t* cfg, uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) { if (format < SRSLTE_PUCCH_FORMAT_2) { - memcpy(pucch_bits, uci_data->ack.ack_value, cfg->uci_cfg.ack.nof_acks * sizeof(uint8_t)); + memcpy(pucch_bits, uci_data->ack.ack_value, srslte_uci_cfg_total_ack(&cfg->uci_cfg) * sizeof(uint8_t)); } else if (format >= SRSLTE_PUCCH_FORMAT_2 && format < SRSLTE_PUCCH_FORMAT_3) { /* Put RI (goes alone) */ if (cfg->uci_cfg.cqi.ri_len) { @@ -594,7 +594,7 @@ static int encode_bits(srslte_pucch_cfg_t* cfg, } else if (format == SRSLTE_PUCCH_FORMAT_3) { uint8_t temp[SRSLTE_UCI_MAX_ACK_BITS + 1]; uint32_t k = 0; - for (; k < cfg->uci_cfg.ack.nof_acks; k++) { + for (; k < srslte_uci_cfg_total_ack(&cfg->uci_cfg); k++) { temp[k] = (uint8_t)((uci_data->ack.ack_value[k] == 1) ? 1 : 0); } if (cfg->uci_cfg.is_scheduling_request_tti) { @@ -719,7 +719,7 @@ static void decode_bits(srslte_uci_cfg_t* uci_cfg, } // Save ACK bits - for (uint32_t a = 0; a < uci_cfg->ack.nof_acks; a++) { + for (uint32_t a = 0; a < srslte_uci_cfg_total_ack(uci_cfg); a++) { if (uci_cfg->cqi.data_enable || uci_cfg->cqi.ri_len) { uci_data->ack.ack_value[a] = pucch_dmrs_bits[a]; } else { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index c8f89f1ed..f85a81afd 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -938,7 +938,7 @@ static int uci_decode_ri_ack( uint32_t cqi_len = srslte_cqi_size(&cfg->uci_cfg.cqi); // Deinterleave and decode HARQ bits - if (cfg->uci_cfg.ack.nof_acks > 0) { + if (srslte_uci_cfg_total_ack(&cfg->uci_cfg) > 0) { float beta = beta_harq_offset[cfg->uci_offset.I_offset_ack]; if (cfg->grant.tb.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_offset.I_offset_cqi]; @@ -951,7 +951,7 @@ static int uci_decode_ri_ack( cqi_len, q->ack_ri_bits, uci_data->ack.ack_value, - cfg->uci_cfg.ack.nof_acks, + srslte_uci_cfg_total_ack(&cfg->uci_cfg), false); if (ret < 0) { return ret; @@ -1120,7 +1120,7 @@ int srslte_ulsch_encode(srslte_sch_t* q, beta, nb_q / Qm, true, - cfg->uci_cfg.ack.N_bundle, + cfg->uci_cfg.ack[0].N_bundle, q->ack_ri_bits); if (ret < 0) { return ret; @@ -1169,24 +1169,24 @@ int srslte_ulsch_encode(srslte_sch_t* q, ulsch_interleave(g_bits, Qm, nb_q / Qm, cfg->grant.nof_symb, q_bits, q->ack_ri_bits, Q_prime_ri * Qm, q->temp_g_bits); // Encode (and interleave) ACK - if (cfg->uci_cfg.ack.nof_acks > 0) { + if (srslte_uci_cfg_total_ack(&cfg->uci_cfg) > 0) { float beta = beta_harq_offset[cfg->uci_offset.I_offset_ack]; if (cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_offset.I_offset_cqi]; } ret = srslte_uci_encode_ack_ri(cfg, uci_data->ack.ack_value, - cfg->uci_cfg.ack.nof_acks, + srslte_uci_cfg_total_ack(&cfg->uci_cfg), (uint32_t)uci_cqi_len, beta, nb_q / Qm, false, - cfg->uci_cfg.ack.N_bundle, + cfg->uci_cfg.ack[0].N_bundle, &q->ack_ri_bits[Q_prime_ri * Qm]); if (ret < 0) { return ret; } - Q_prime_ack = (uint32_t) ret; + Q_prime_ack = (uint32_t) ret; } uint32_t nof_ri_ack_bits = (Q_prime_ack + Q_prime_ri) * Qm; diff --git a/lib/src/phy/phch/test/prach_test_usrp.c b/lib/src/phy/phch/test/prach_test_usrp.c index 55107a650..fb18def7b 100644 --- a/lib/src/phy/phch/test/prach_test_usrp.c +++ b/lib/src/phy/phch/test/prach_test_usrp.c @@ -173,16 +173,6 @@ int main(int argc, char **argv) { srslte_rf_set_rx_freq(&rf, 0, uhd_freq); srslte_rf_set_tx_freq(&rf, 0, uhd_freq); - if (srate > 1e6 && (srate / 1000) > 0) { - if (30720%(srate/1000) == 0) { - srslte_rf_set_master_clock_rate(&rf, 30.72e6); - } else { - srslte_rf_set_master_clock_rate(&rf, 23.04e6); - } - } else { - printf("Invalid sampling rate %d Hz\n", srate); - exit(-1); - } printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000); float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate); if (srate_rf != srate) { diff --git a/lib/src/phy/phch/test/pucch_test.c b/lib/src/phy/phch/test/pucch_test.c index f4de4b861..b03c241d9 100644 --- a/lib/src/phy/phch/test/pucch_test.c +++ b/lib/src/phy/phch/test/pucch_test.c @@ -204,13 +204,13 @@ int main(int argc, char **argv) { case SRSLTE_PUCCH_FORMAT_1A: case SRSLTE_PUCCH_FORMAT_2A: uci_data.value.ack.ack_value[0] = 1; - uci_data.cfg.ack.nof_acks = 1; + uci_data.cfg.ack[0].nof_acks = 1; break; case SRSLTE_PUCCH_FORMAT_1B: case SRSLTE_PUCCH_FORMAT_2B: uci_data.value.ack.ack_value[0] = 1; uci_data.value.ack.ack_value[1] = 1; - uci_data.cfg.ack.nof_acks = 2; + uci_data.cfg.ack[0].nof_acks = 2; break; default: break; diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index 2226c1e53..43f4ae04d 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -121,7 +121,7 @@ void parse_extensive_param(char *param, char *arg) { uci_data_tx.cfg.cqi.ri_len = 1; } } else if (!strcmp(param, "uci_ack")) { - uci_data_tx.cfg.ack.nof_acks = SRSLTE_MIN(uci_data_tx.cfg.ack.nof_acks + 1, SRSLTE_UCI_MAX_ACK_BITS); + uci_data_tx.cfg.ack[0].nof_acks = SRSLTE_MIN(uci_data_tx.cfg.ack[0].nof_acks + 1, SRSLTE_UCI_MAX_ACK_BITS); } else if (!strcmp(param, "enable_64qam")) { enable_64_qam ^= true; } else { @@ -295,7 +295,7 @@ int main(int argc, char** argv) data[i] = (uint8_t)srslte_random_uniform_int_dist(random_h, 0, 255); } - for (uint32_t a = 0; a < uci_data_tx.cfg.ack.nof_acks; a++) { + for (uint32_t a = 0; a < uci_data_tx.cfg.ack[0].nof_acks; a++) { uci_data_tx.value.ack.ack_value[a] = (uint8_t)srslte_random_uniform_int_dist(random_h, 0, 1); } @@ -338,17 +338,17 @@ int main(int argc, char** argv) INFO("Rx Data is Ok\n"); } - if (uci_data_tx.cfg.ack.nof_acks) { - if (memcmp(uci_data_tx.value.ack.ack_value, pusch_res.uci.ack.ack_value, uci_data_tx.cfg.ack.nof_acks) != 0) { + if (uci_data_tx.cfg.ack[0].nof_acks) { + if (memcmp(uci_data_tx.value.ack.ack_value, pusch_res.uci.ack.ack_value, uci_data_tx.cfg.ack[0].nof_acks) != 0) { printf("UCI ACK bit error:\n"); printf("\tTx: "); - srslte_vec_fprint_byte(stdout, uci_data_tx.value.ack.ack_value, uci_data_tx.cfg.ack.nof_acks); + srslte_vec_fprint_byte(stdout, uci_data_tx.value.ack.ack_value, uci_data_tx.cfg.ack[0].nof_acks); printf("\tRx: "); - srslte_vec_fprint_byte(stdout, pusch_res.uci.ack.ack_value, cfg.uci_cfg.ack.nof_acks); + srslte_vec_fprint_byte(stdout, pusch_res.uci.ack.ack_value, cfg.uci_cfg.ack[0].nof_acks); ret = SRSLTE_ERROR; } else { INFO("Rx ACK (%d bits) is Ok, %d%d\n", - uci_data_tx.cfg.ack.nof_acks, + uci_data_tx.cfg.ack[0].nof_acks, uci_data_tx.value.ack.ack_value[0], uci_data_tx.value.ack.ack_value[1]); } diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 8579672eb..8b5ede7d1 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -787,6 +787,23 @@ int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t* cfg, return (int) Qprime; } +uint32_t srslte_uci_cfg_total_ack(srslte_uci_cfg_t* uci_cfg) +{ + uint32_t nof_ack = 0; + for (uint32_t i = 0; i < SRSLTE_MAX_CARRIERS; i++) { + nof_ack += uci_cfg->ack[i].nof_acks; + } + return nof_ack; +} + +void srslte_uci_data_reset(srslte_uci_data_t* uci_data) +{ + bzero(uci_data, sizeof(srslte_uci_data_t)); + + /* Set all ACKs to DTX */ + memset(uci_data->value.ack.ack_value, 2, SRSLTE_UCI_MAX_ACK_BITS); +} + int srslte_uci_data_info(srslte_uci_cfg_t* uci_cfg, srslte_uci_value_t* uci_data, char* str, uint32_t str_len) { int n = 0; @@ -795,13 +812,13 @@ int srslte_uci_data_info(srslte_uci_cfg_t* uci_cfg, srslte_uci_value_t* uci_data n = srslte_print_check(str, str_len, n, ", sr=%s", uci_data->scheduling_request ? "yes" : "no"); } - if (uci_cfg->ack.nof_acks) { + if (srslte_uci_cfg_total_ack(uci_cfg)) { n = srslte_print_check(str, str_len, n, ", ack="); - for (uint32_t i = 0; i < uci_cfg->ack.nof_acks; i++) { + for (uint32_t i = 0; i < srslte_uci_cfg_total_ack(uci_cfg); i++) { n = srslte_print_check(str, str_len, n, "%d", uci_data->ack.ack_value[i]); } - if (uci_cfg->ack.N_bundle) { - n = srslte_print_check(str, str_len, n, ", n_bundle=%d", uci_cfg->ack.N_bundle); + if (uci_cfg->ack[0].N_bundle) { + n = srslte_print_check(str, str_len, n, ", n_bundle=%d", uci_cfg->ack[0].N_bundle); } } diff --git a/lib/src/phy/rf/CMakeLists.txt b/lib/src/phy/rf/CMakeLists.txt index 9ae3494b7..c20a9bd6f 100644 --- a/lib/src/phy/rf/CMakeLists.txt +++ b/lib/src/phy/rf/CMakeLists.txt @@ -44,7 +44,7 @@ if(RF_FOUND) if (ZEROMQ_FOUND) add_definitions(-DENABLE_ZEROMQ) - list(APPEND SOURCES_RF rf_zmq_imp.c) + list(APPEND SOURCES_RF rf_zmq_imp.c rf_zmq_imp_tx.c rf_zmq_imp_rx.c) endif (ZEROMQ_FOUND) add_library(srslte_rf SHARED ${SOURCES_RF}) diff --git a/lib/src/phy/rf/rf_blade_imp.c b/lib/src/phy/rf/rf_blade_imp.c index 9ae0872b3..ddb66fcdf 100644 --- a/lib/src/phy/rf/rf_blade_imp.c +++ b/lib/src/phy/rf/rf_blade_imp.c @@ -26,7 +26,7 @@ #include "srslte/srslte.h" #include "rf_blade_imp.h" - +#define UNUSED __attribute__((unused)) #define CONVERT_BUFFER_SIZE (240*1024) typedef struct { @@ -40,21 +40,16 @@ typedef struct { srslte_rf_info_t info; } rf_blade_handler_t; -srslte_rf_error_handler_t blade_error_handler = NULL; - -void rf_blade_suppress_stdout(void *h) { - bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_SILENT); -} +static srslte_rf_error_handler_t blade_error_handler = NULL; -void rf_blade_register_error_handler(void *notused, srslte_rf_error_handler_t new_handler) +void rf_blade_suppress_stdout(UNUSED void* h) { - new_handler = blade_error_handler; + bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_SILENT); } -bool rf_blade_rx_wait_lo_locked(void *h) +void rf_blade_register_error_handler(UNUSED void* ptr, srslte_rf_error_handler_t new_handler) { - usleep(1000); - return true; + blade_error_handler = new_handler; } const unsigned int num_buffers = 256; @@ -63,8 +58,7 @@ const unsigned int buffer_size_tx = 1024; const unsigned int num_transfers = 32; const unsigned int timeout_ms = 4000; - -char* rf_blade_devname(void* h) +char* rf_blade_devname(UNUSED void* h) { return DEVNAME; } @@ -85,7 +79,7 @@ int rf_blade_start_tx_stream(void *h) ERROR("Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); return status; } - status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, true); + status = bladerf_enable_module(handler->dev, BLADERF_TX_X1, true); if (status != 0) { ERROR("Failed to enable TX module: %s\n", bladerf_strerror(status)); return status; @@ -94,7 +88,7 @@ int rf_blade_start_tx_stream(void *h) return 0; } -int rf_blade_start_rx_stream(void *h, bool now) +int rf_blade_start_rx_stream(void* h, UNUSED bool now) { int status; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; @@ -125,12 +119,12 @@ int rf_blade_start_rx_stream(void *h, bool now) ERROR("Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); return status; } - status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, true); + status = bladerf_enable_module(handler->dev, BLADERF_RX_X1, true); if (status != 0) { ERROR("Failed to enable RX module: %s\n", bladerf_strerror(status)); return status; } - status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, true); + status = bladerf_enable_module(handler->dev, BLADERF_TX_X1, true); if (status != 0) { ERROR("Failed to enable TX module: %s\n", bladerf_strerror(status)); return status; @@ -142,12 +136,12 @@ int rf_blade_start_rx_stream(void *h, bool now) int rf_blade_stop_rx_stream(void *h) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - int status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, false); + int status = bladerf_enable_module(handler->dev, BLADERF_RX_X1, false); if (status != 0) { ERROR("Failed to enable RX module: %s\n", bladerf_strerror(status)); return status; } - status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, false); + status = bladerf_enable_module(handler->dev, BLADERF_TX_X1, false); if (status != 0) { ERROR("Failed to enable TX module: %s\n", bladerf_strerror(status)); return status; @@ -157,21 +151,19 @@ int rf_blade_stop_rx_stream(void *h) return 0; } -void rf_blade_flush_buffer(void *h) -{ -} +void rf_blade_flush_buffer(UNUSED void* h) {} -bool rf_blade_has_rssi(void *h) +bool rf_blade_has_rssi(UNUSED void* h) { return false; } -float rf_blade_get_rssi(void *h) +float rf_blade_get_rssi(UNUSED void* h) { return 0; } -int rf_blade_open_multi(char *args, void **h, uint32_t nof_channels) +int rf_blade_open_multi(char* args, void** h, UNUSED uint32_t nof_channels) { return rf_blade_open(args, h); } @@ -196,7 +188,7 @@ int rf_blade_open(char *args, void **h) return status; } - status = bladerf_set_gain_mode(handler->dev, BLADERF_MODULE_RX, BLADERF_GAIN_MGC); + status = bladerf_set_gain_mode(handler->dev, BLADERF_RX_X1, BLADERF_GAIN_MGC); if (status) { ERROR("Unable to open device: %s\n", bladerf_strerror(status)); return status; @@ -205,24 +197,24 @@ int rf_blade_open(char *args, void **h) //bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_VERBOSE); /* Get Gain ranges and set Rx to maximum */ - status = bladerf_get_gain_range(handler->dev, BLADERF_MODULE_RX, &range_rx); - if ((status != 0) | (range_rx == NULL)) { + status = bladerf_get_gain_range(handler->dev, BLADERF_RX_X1, &range_rx); + if ((status != 0) || (range_rx == NULL)) { ERROR("Failed to get RX gain range: %s\n", bladerf_strerror(status)); return status; } - bladerf_get_gain_range(handler->dev, BLADERF_MODULE_RX, &range_tx); - if ((status != 0) | (range_tx == NULL)) { + status = bladerf_get_gain_range(handler->dev, BLADERF_TX_X1, &range_tx); + if ((status != 0) || (range_tx == NULL)) { ERROR("Failed to get TX gain range: %s\n", bladerf_strerror(status)); return status; } - status = bladerf_set_gain(handler->dev, BLADERF_MODULE_RX, (bladerf_gain) range_rx->max); + status = bladerf_set_gain(handler->dev, BLADERF_RX_X1, (bladerf_gain)range_rx->max); if (status != 0) { ERROR("Failed to set RX LNA gain: %s\n", bladerf_strerror(status)); return status; } - handler->rx_stream_enabled = false; + handler->rx_stream_enabled = false; handler->tx_stream_enabled = false; /* Set default sampling rates */ @@ -246,32 +238,23 @@ int rf_blade_close(void *h) return 0; } -void rf_blade_set_master_clock_rate(void *h, double rate) -{ -} - -bool rf_blade_is_master_clock_dynamic(void *h) -{ - return true; -} - double rf_blade_set_rx_srate(void *h, double freq) { uint32_t bw; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - int status = bladerf_set_sample_rate(handler->dev, BLADERF_MODULE_RX, (uint32_t) freq, &handler->rx_rate); + int status = bladerf_set_sample_rate(handler->dev, BLADERF_RX_X1, (uint32_t)freq, &handler->rx_rate); if (status != 0) { ERROR("Failed to set samplerate = %u: %s\n", (uint32_t)freq, bladerf_strerror(status)); return -1; } - if (handler->rx_rate < 2000000) { - status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate, &bw); + if (handler->rx_rate < 2000000) { + status = bladerf_set_bandwidth(handler->dev, BLADERF_RX_X1, handler->rx_rate, &bw); if (status != 0) { ERROR("Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status)); return -1; } } else { - status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, (bladerf_bandwidth) (handler->rx_rate * 0.8), &bw); + status = bladerf_set_bandwidth(handler->dev, BLADERF_RX_X1, (bladerf_bandwidth)(handler->rx_rate * 0.8), &bw); if (status != 0) { ERROR("Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status)); return -1; @@ -285,12 +268,12 @@ double rf_blade_set_tx_srate(void *h, double freq) { uint32_t bw; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - int status = bladerf_set_sample_rate(handler->dev, BLADERF_MODULE_TX, (uint32_t) freq, &handler->tx_rate); + int status = bladerf_set_sample_rate(handler->dev, BLADERF_TX_X1, (uint32_t)freq, &handler->tx_rate); if (status != 0) { ERROR("Failed to set samplerate = %u: %s\n", (uint32_t)freq, bladerf_strerror(status)); return -1; - } - status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_TX, handler->tx_rate, &bw); + } + status = bladerf_set_bandwidth(handler->dev, BLADERF_TX_X1, handler->tx_rate, &bw); if (status != 0) { ERROR("Failed to set bandwidth = %u: %s\n", handler->tx_rate, bladerf_strerror(status)); return -1; @@ -302,7 +285,7 @@ double rf_blade_set_rx_gain(void *h, double gain) { int status; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - status = bladerf_set_gain(handler->dev, BLADERF_MODULE_RX, (bladerf_gain) gain); + status = bladerf_set_gain(handler->dev, BLADERF_RX_X1, (bladerf_gain)gain); if (status != 0) { ERROR("Failed to set RX gain: %s\n", bladerf_strerror(status)); return -1; @@ -314,7 +297,7 @@ double rf_blade_set_tx_gain(void *h, double gain) { int status; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - status = bladerf_set_gain(handler->dev, BLADERF_MODULE_TX, (bladerf_gain) gain); + status = bladerf_set_gain(handler->dev, BLADERF_TX_X1, (bladerf_gain)gain); if (status != 0) { ERROR("Failed to set TX gain: %s\n", bladerf_strerror(status)); return -1; @@ -327,7 +310,7 @@ double rf_blade_get_rx_gain(void *h) int status; bladerf_gain gain = 0; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - status = bladerf_get_gain(handler->dev, BLADERF_MODULE_RX, &gain); + status = bladerf_get_gain(handler->dev, BLADERF_RX_X1, &gain); if (status != 0) { ERROR("Failed to get RX gain: %s\n", bladerf_strerror(status)); return -1; @@ -340,7 +323,7 @@ double rf_blade_get_tx_gain(void *h) int status; bladerf_gain gain = 0; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; - status = bladerf_get_gain(handler->dev, BLADERF_MODULE_TX, &gain); + status = bladerf_get_gain(handler->dev, BLADERF_TX_X1, &gain); if (status != 0) { ERROR("Failed to get TX gain: %s\n", bladerf_strerror(status)); return -1; @@ -361,34 +344,34 @@ srslte_rf_info_t *rf_blade_get_info(void *h) return info; } -double rf_blade_set_rx_freq(void* h, uint32_t ch, double freq) +double rf_blade_set_rx_freq(void* h, UNUSED uint32_t ch, double freq) { rf_blade_handler_t* handler = (rf_blade_handler_t*)h; bladerf_frequency f_int = (uint32_t) round(freq); - int status = bladerf_set_frequency(handler->dev, BLADERF_MODULE_RX, f_int); + int status = bladerf_set_frequency(handler->dev, BLADERF_RX_X1, f_int); if (status != 0) { ERROR("Failed to set samplerate = %u: %s\n", (uint32_t)freq, bladerf_strerror(status)); return -1; } f_int=0; - bladerf_get_frequency(handler->dev, BLADERF_MODULE_RX, &f_int); + bladerf_get_frequency(handler->dev, BLADERF_RX_X1, &f_int); printf("set RX frequency to %lu\n", f_int); return freq; } -double rf_blade_set_tx_freq(void* h, uint32_t ch, double freq) +double rf_blade_set_tx_freq(void* h, UNUSED uint32_t ch, double freq) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; bladerf_frequency f_int = (uint32_t)round(freq); - int status = bladerf_set_frequency(handler->dev, BLADERF_MODULE_TX, f_int); + int status = bladerf_set_frequency(handler->dev, BLADERF_TX_X1, f_int); if (status != 0) { ERROR("Failed to set samplerate = %u: %s\n", (uint32_t)freq, bladerf_strerror(status)); return -1; } f_int=0; - bladerf_get_frequency(handler->dev, BLADERF_MODULE_TX, &f_int); + bladerf_get_frequency(handler->dev, BLADERF_TX_X1, &f_int); printf("set TX frequency to %lu\n", f_int); return freq; } @@ -404,13 +387,6 @@ static void timestamp_to_secs(uint32_t rate, uint64_t timestamp, time_t *secs, d } } -static void secs_to_timestamps(uint32_t rate, time_t secs, double frac_secs, uint64_t *timestamp) { - double totalsecs = (double) secs + frac_secs; - if (timestamp) { - *timestamp = rate * totalsecs; - } -} - void rf_blade_get_time(void *h, time_t *secs, double *frac_secs) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; @@ -433,12 +409,8 @@ int rf_blade_recv_with_time_multi(void *h, return rf_blade_recv_with_time(h, *data, nsamples, blocking, secs, frac_secs); } -int rf_blade_recv_with_time(void *h, - void *data, - uint32_t nsamples, - bool blocking, - time_t *secs, - double *frac_secs) +int rf_blade_recv_with_time( + void* h, void* data, uint32_t nsamples, UNUSED bool blocking, time_t* secs, double* frac_secs) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; struct bladerf_metadata meta; @@ -453,7 +425,7 @@ int rf_blade_recv_with_time(void *h, } status = bladerf_sync_rx(handler->dev, handler->rx_buffer, nsamples, &meta, 2000); if (status) { - ERROR("RX failed: %s\n\n", bladerf_strerror(status)); + ERROR("RX failed: %s; nsamples=%d;\n", bladerf_strerror(status), nsamples); return -1; } else if (meta.status & BLADERF_META_STATUS_OVERRUN) { if (blade_error_handler) { @@ -487,15 +459,15 @@ int rf_blade_send_timed_multi(void *h, is_end_of_burst); } -int rf_blade_send_timed(void *h, - void *data, - int nsamples, - time_t secs, - double frac_secs, - bool has_time_spec, - bool blocking, - bool is_start_of_burst, - bool is_end_of_burst) +int rf_blade_send_timed(void* h, + void* data, + int nsamples, + time_t secs, + double frac_secs, + bool has_time_spec, + UNUSED bool blocking, + bool is_start_of_burst, + bool is_end_of_burst) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; struct bladerf_metadata meta; @@ -515,7 +487,9 @@ int rf_blade_send_timed(void *h, memset(&meta, 0, sizeof(meta)); if (is_start_of_burst) { if (has_time_spec) { - secs_to_timestamps(handler->tx_rate, secs, frac_secs, &meta.timestamp); + // Convert time to ticks + srslte_timestamp_t ts = {.full_secs = secs, .frac_secs = frac_secs}; + meta.timestamp = srslte_timestamp_uint64(&ts, handler->tx_rate); } else { meta.flags |= BLADERF_META_FLAG_TX_NOW; } diff --git a/lib/src/phy/rf/rf_blade_imp.h b/lib/src/phy/rf/rf_blade_imp.h index e3bd48e05..61964ee56 100644 --- a/lib/src/phy/rf/rf_blade_imp.h +++ b/lib/src/phy/rf/rf_blade_imp.h @@ -45,17 +45,9 @@ SRSLTE_API void rf_blade_flush_buffer(void *h); SRSLTE_API bool rf_blade_has_rssi(void *h); -SRSLTE_API float rf_blade_get_rssi(void *h); +SRSLTE_API float rf_blade_get_rssi(void *h); -SRSLTE_API bool rf_blade_rx_wait_lo_locked(void *h); - -SRSLTE_API void rf_blade_set_master_clock_rate(void *h, - double rate); - -SRSLTE_API bool rf_blade_is_master_clock_dynamic(void *h); - -SRSLTE_API double rf_blade_set_rx_srate(void *h, - double freq); +SRSLTE_API double rf_blade_set_rx_srate(void* h, double freq); SRSLTE_API double rf_blade_set_rx_gain(void *h, double gain); diff --git a/lib/src/phy/rf/rf_dev.h b/lib/src/phy/rf/rf_dev.h index 94a81d663..9d3d2de0d 100644 --- a/lib/src/phy/rf/rf_dev.h +++ b/lib/src/phy/rf/rf_dev.h @@ -23,7 +23,6 @@ typedef struct { const char *name; char* (*srslte_rf_devname) (void *h); - bool (*srslte_rf_rx_wait_lo_locked) (void *h); int (*srslte_rf_start_rx_stream)(void *h, bool now); int (*srslte_rf_stop_rx_stream)(void *h); void (*srslte_rf_flush_buffer)(void *h); @@ -34,8 +33,6 @@ typedef struct { int (*srslte_rf_open)(char *args, void **h); int (*srslte_rf_open_multi)(char *args, void **h, uint32_t nof_channels); int (*srslte_rf_close)(void *h); - void (*srslte_rf_set_master_clock_rate)(void *h, double rate); - bool (*srslte_rf_is_master_clock_dynamic)(void *h); double (*srslte_rf_set_rx_srate)(void *h, double freq); double (*srslte_rf_set_rx_gain)(void *h, double gain); double (*srslte_rf_set_tx_gain)(void *h, double gain); @@ -66,7 +63,6 @@ typedef struct { static rf_dev_t dev_uhd = {"UHD", rf_uhd_devname, - rf_uhd_rx_wait_lo_locked, rf_uhd_start_rx_stream, rf_uhd_stop_rx_stream, rf_uhd_flush_buffer, @@ -77,8 +73,6 @@ static rf_dev_t dev_uhd = {"UHD", rf_uhd_open, .srslte_rf_open_multi = rf_uhd_open_multi, rf_uhd_close, - rf_uhd_set_master_clock_rate, - rf_uhd_is_master_clock_dynamic, rf_uhd_set_rx_srate, rf_uhd_set_rx_gain, rf_uhd_set_tx_gain, @@ -103,7 +97,6 @@ static rf_dev_t dev_uhd = {"UHD", static rf_dev_t dev_blade = {"bladeRF", rf_blade_devname, - rf_blade_rx_wait_lo_locked, rf_blade_start_rx_stream, rf_blade_stop_rx_stream, rf_blade_flush_buffer, @@ -114,8 +107,6 @@ static rf_dev_t dev_blade = {"bladeRF", rf_blade_open, .srslte_rf_open_multi = rf_blade_open_multi, rf_blade_close, - rf_blade_set_master_clock_rate, - rf_blade_is_master_clock_dynamic, rf_blade_set_rx_srate, rf_blade_set_rx_gain, rf_blade_set_tx_gain, @@ -139,7 +130,6 @@ static rf_dev_t dev_blade = {"bladeRF", static rf_dev_t dev_soapy = {"soapy", rf_soapy_devname, - rf_soapy_rx_wait_lo_locked, rf_soapy_start_rx_stream, rf_soapy_stop_rx_stream, rf_soapy_flush_buffer, @@ -150,8 +140,6 @@ static rf_dev_t dev_soapy = {"soapy", rf_soapy_open, rf_soapy_open_multi, rf_soapy_close, - rf_soapy_set_master_clock_rate, - rf_soapy_is_master_clock_dynamic, rf_soapy_set_rx_srate, rf_soapy_set_rx_gain, rf_soapy_set_tx_gain, @@ -177,7 +165,6 @@ static rf_dev_t dev_soapy = {"soapy", static rf_dev_t dev_zmq = {"zmq", rf_zmq_devname, - rf_zmq_rx_wait_lo_locked, rf_zmq_start_rx_stream, rf_zmq_stop_rx_stream, rf_zmq_flush_buffer, @@ -188,8 +175,6 @@ static rf_dev_t dev_zmq = {"zmq", rf_zmq_open, .srslte_rf_open_multi = rf_zmq_open_multi, rf_zmq_close, - rf_zmq_set_master_clock_rate, - rf_zmq_is_master_clock_dynamic, rf_zmq_set_rx_srate, rf_zmq_set_rx_gain, rf_zmq_set_tx_gain, diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index d60d9d2b6..eb1d214be 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -131,11 +131,6 @@ const char* srslte_rf_name(srslte_rf_t *rf) { return ((rf_dev_t*) rf->dev)->srslte_rf_devname(rf->handler); } -bool srslte_rf_rx_wait_lo_locked(srslte_rf_t *rf) -{ - return ((rf_dev_t*) rf->dev)->srslte_rf_rx_wait_lo_locked(rf->handler); -} - int srslte_rf_start_rx_stream(srslte_rf_t *rf, bool now) { return ((rf_dev_t*) rf->dev)->srslte_rf_start_rx_stream(rf->handler, now); @@ -192,16 +187,6 @@ int srslte_rf_close(srslte_rf_t *rf) return ((rf_dev_t*) rf->dev)->srslte_rf_close(rf->handler); } -void srslte_rf_set_master_clock_rate(srslte_rf_t *rf, double rate) -{ - ((rf_dev_t*) rf->dev)->srslte_rf_set_master_clock_rate(rf->handler, rate); -} - -bool srslte_rf_is_master_clock_dynamic(srslte_rf_t *rf) -{ - return ((rf_dev_t*) rf->dev)->srslte_rf_is_master_clock_dynamic(rf->handler); -} - double srslte_rf_set_rx_srate(srslte_rf_t *rf, double freq) { return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_srate(rf->handler, freq); diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index d172b4da1..fbe51ec61 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -53,6 +53,7 @@ typedef struct { bool rx_stream_active; srslte_rf_info_t info; double tx_rate; + double master_clock_rate; size_t rx_mtu, tx_mtu; size_t num_rx_channels; size_t num_tx_channels; @@ -192,10 +193,8 @@ char* rf_soapy_devname(void* h) return handler->devname; } - -bool rf_soapy_rx_wait_lo_locked(void *h) +static bool rf_soapy_rx_wait_lo_locked(rf_soapy_handler_t* handler) { - rf_soapy_handler_t *handler = (rf_soapy_handler_t*)h; char *ret = SoapySDRDevice_readChannelSensor(handler->device, SOAPY_SDR_RX, 0, "lo_locked"); if (ret != NULL) { return (strcmp(ret, "true") == 0 ? true : false); @@ -219,8 +218,11 @@ int rf_soapy_start_rx_stream(void *h, bool now) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; if(handler->rx_stream_active == false){ - if(SoapySDRDevice_activateStream(handler->device, handler->rxStream, SOAPY_SDR_HAS_TIME | SOAPY_SDR_END_BURST, 0, 0) != 0) + if (SoapySDRDevice_activateStream(handler->device, handler->rxStream, 0, 0, 0) != 0) { + printf("Error starting Rx streaming.\n"); return SRSLTE_ERROR; + } + handler->rx_stream_active = true; } return SRSLTE_SUCCESS; @@ -377,8 +379,8 @@ int rf_soapy_open_multi(char* args, void** h, uint32_t num_requested_channels) for (uint32_t i = 0; i < handler->num_rx_channels; ++i) { list = SoapySDRDevice_listChannelSensors(handler->device, SOAPY_SDR_RX, i, &list_length); printf("Available sensors for Rx channel %d: \n", i); - for (int i = 0; i < list_length; i++) { - printf(" - %s\n", list[i]); + for (int j = 0; j < list_length; j++) { + printf(" - %s\n", list[j]); } } @@ -483,6 +485,7 @@ int rf_soapy_open_multi(char* args, void** h, uint32_t num_requested_channels) } has_agc = SoapySDRDevice_hasGainMode(handler->device, SOAPY_SDR_TX, 0); + list = SoapySDRDevice_listGains(handler->device, SOAPY_SDR_TX, 0, &list_length); printf("State of gain elements for Tx channel 0 (AGC %s):\n", has_agc ? "supported":"not supported"); for(int i = 0; i < list_length; i++) { printf(" - %s: %.2f dB\n", list[i], SoapySDRDevice_getGainElement(handler->device, SOAPY_SDR_TX, 0, list[i])); @@ -550,24 +553,6 @@ int rf_soapy_close(void *h) return SRSLTE_SUCCESS; } -void rf_soapy_set_master_clock_rate(void *h, double rate) -{ - rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; - if (SoapySDRDevice_setMasterClockRate(handler->device, rate) != 0) { - printf("rf_soapy_set_master_clock_rate Rx fail: %s\n", SoapySDRDevice_lastError()); - } - - printf("Set master clock rate to %.2f MHz\n", SoapySDRDevice_getMasterClockRate(handler->device)/1e6); -} - - -bool rf_soapy_is_master_clock_dynamic(void *h) -{ - printf("TODO: implement rf_soapy_is_master_clock_dynamic()\n"); - return false; -} - - double rf_soapy_set_rx_srate(void *h, double rate) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; @@ -774,12 +759,10 @@ int rf_soapy_recv_with_time_multi(void *h, if (ret == SOAPY_SDR_OVERFLOW || (ret > 0 && (flags & SOAPY_SDR_END_ABRUPT) != 0)) { log_overflow(handler); continue; - } else - if (ret == SOAPY_SDR_TIMEOUT) { + } else if (ret == SOAPY_SDR_TIMEOUT) { log_late(handler, true); continue; - } else - if (ret < 0) { + } else if (ret < 0) { // unspecific error printf("SoapySDRDevice_readStream returned %d: %s\n", ret, SoapySDR_errToStr(ret)); handler->num_other_errors++; @@ -787,8 +770,8 @@ int rf_soapy_recv_with_time_multi(void *h, // update rx time only for first segment if (secs != NULL && frac_secs != NULL && n == 0) { - *secs = timeNs / 1e9; - *frac_secs = (timeNs % 1000000000)/1e9; + *secs = floor(timeNs / 1e9); + *frac_secs = (timeNs % 1000000000) / 1e9; //printf("rx_time: secs=%lld, frac_secs=%lf timeNs=%llu\n", *secs, *frac_secs, timeNs); } @@ -913,9 +896,7 @@ int rf_soapy_send_timed_multi(void* h, timeNs += adv; } n += ret; - } - else - if (ret < 0) { + } else if (ret < 0) { // An error has occured switch (ret) { case SOAPY_SDR_TIMEOUT: diff --git a/lib/src/phy/rf/rf_soapy_imp.h b/lib/src/phy/rf/rf_soapy_imp.h index 865883634..155dd3aec 100644 --- a/lib/src/phy/rf/rf_soapy_imp.h +++ b/lib/src/phy/rf/rf_soapy_imp.h @@ -46,17 +46,11 @@ SRSLTE_API void rf_soapy_flush_buffer(void *h); SRSLTE_API bool rf_soapy_has_rssi(void *h); -SRSLTE_API float rf_soapy_get_rssi(void *h); +SRSLTE_API float rf_soapy_get_rssi(void* h); -SRSLTE_API bool rf_soapy_rx_wait_lo_locked(void *h); +SRSLTE_API void rf_soapy_set_master_clock_rate(void* h, double rate); -SRSLTE_API void rf_soapy_set_master_clock_rate(void *h, - double rate); - -SRSLTE_API bool rf_soapy_is_master_clock_dynamic(void *h); - -SRSLTE_API double rf_soapy_set_rx_srate(void *h, - double freq); +SRSLTE_API double rf_soapy_set_rx_srate(void* h, double freq); SRSLTE_API double rf_soapy_set_rx_gain(void *h, double gain); diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index e75dd2850..c3473e28d 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -19,17 +19,18 @@ * */ -#include -#include +#include #include +#include +#include #include -#include -#include "srslte/srslte.h" -#include "rf_uhd_imp.h" #include "rf_helper.h" +#include "srslte/srslte.h" #include "uhd_c_api.h" +#include "rf_uhd_imp.h" + #define HAVE_ASYNC_THREAD 1 #if UHD_VERSION < 3130000 @@ -37,41 +38,42 @@ #endif /* UHD_VERSION < 3140000 */ typedef struct { - char *devname; - uhd_usrp_handle usrp; + char* devname; + uhd_usrp_handle usrp; uhd_rx_streamer_handle rx_stream; uhd_tx_streamer_handle tx_stream; - - uhd_rx_metadata_handle rx_md, rx_md_first; - uhd_tx_metadata_handle tx_md; - + + uhd_rx_metadata_handle rx_md, rx_md_first; + uhd_tx_metadata_handle tx_md; + srslte_rf_info_t info; - size_t rx_nof_samples; - size_t tx_nof_samples; - double tx_rate; - bool dynamic_rate; - bool has_rssi; - uint32_t nof_rx_channels; - int nof_tx_channels; + size_t rx_nof_samples; + size_t tx_nof_samples; + double tx_rate; + bool dynamic_rate; + bool has_rssi; + uint32_t nof_rx_channels; + int nof_tx_channels; - srslte_rf_error_handler_t uhd_error_handler; + srslte_rf_error_handler_t uhd_error_handler; float current_master_clock; - bool async_thread_running; + bool async_thread_running; pthread_t async_thread; pthread_mutex_t tx_mutex; } rf_uhd_handler_t; -void suppress_handler(const char *x) +void suppress_handler(const char* x) { // do nothing } -cf_t zero_mem[64*1024]; +cf_t zero_mem[64 * 1024]; -static void log_overflow(rf_uhd_handler_t *h) { +static void log_overflow(rf_uhd_handler_t* h) +{ if (h->uhd_error_handler) { srslte_rf_error_t error; bzero(&error, sizeof(srslte_rf_error_t)); @@ -80,18 +82,20 @@ static void log_overflow(rf_uhd_handler_t *h) { } } -static void log_late(rf_uhd_handler_t *h, bool is_rx) { +static void log_late(rf_uhd_handler_t* h, bool is_rx) +{ if (h->uhd_error_handler) { srslte_rf_error_t error; bzero(&error, sizeof(srslte_rf_error_t)); - error.opt = is_rx?1:0; + error.opt = is_rx ? 1 : 0; error.type = SRSLTE_RF_ERROR_LATE; h->uhd_error_handler(error); } } #if HAVE_ASYNC_THREAD -static void log_underflow(rf_uhd_handler_t *h) { +static void log_underflow(rf_uhd_handler_t* h) +{ if (h->uhd_error_handler) { srslte_rf_error_t error; bzero(&error, sizeof(srslte_rf_error_t)); @@ -101,7 +105,8 @@ static void log_underflow(rf_uhd_handler_t *h) { } #endif -static void log_rx_error(rf_uhd_handler_t *h) { +static void log_rx_error(rf_uhd_handler_t* h) +{ if (h->uhd_error_handler) { char error_string[512]; uhd_usrp_last_error(h->usrp, error_string, 512); @@ -115,18 +120,19 @@ static void log_rx_error(rf_uhd_handler_t *h) { } #if HAVE_ASYNC_THREAD -static void* async_thread(void *h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - uhd_async_metadata_handle md; - uhd_async_metadata_make(&md); - while(handler->async_thread_running) { - bool valid; +static void* async_thread(void* h) +{ + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + uhd_async_metadata_handle md; + uhd_async_metadata_make(&md); + while (handler->async_thread_running) { + bool valid; uhd_error err = uhd_tx_streamer_recv_async_msg(handler->tx_stream, &md, 0.5, &valid); if (err == UHD_ERROR_NONE) { if (valid) { - uhd_async_metadata_event_code_t event_code; + uhd_async_metadata_event_code_t event_code; uhd_async_metadata_event_code(md, &event_code); - if (event_code == UHD_ASYNC_METADATA_EVENT_CODE_UNDERFLOW || + if (event_code == UHD_ASYNC_METADATA_EVENT_CODE_UNDERFLOW || event_code == UHD_ASYNC_METADATA_EVENT_CODE_UNDERFLOW_IN_PACKET) { log_underflow(handler); } else if (event_code == UHD_ASYNC_METADATA_EVENT_CODE_TIME_ERROR) { @@ -135,108 +141,124 @@ static void* async_thread(void *h) { } } else { ERROR("Error while receiving aync metadata: 0x%x\n", err); - return NULL; + return NULL; } } uhd_async_metadata_free(&md); - return NULL; + return NULL; } #endif -void rf_uhd_suppress_stdout(void *h) { +void rf_uhd_suppress_stdout(void* h) +{ rf_uhd_register_msg_handler_c(suppress_handler); } -void rf_uhd_register_error_handler(void *h, srslte_rf_error_handler_t new_handler) +void rf_uhd_register_error_handler(void* h, srslte_rf_error_handler_t new_handler) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; handler->uhd_error_handler = new_handler; } -static bool find_string(uhd_string_vector_handle h, char *str) +static bool find_string(uhd_string_vector_handle h, char* str) { - char buff[128]; + char buff[128]; size_t n; uhd_string_vector_size(h, &n); - for (int i=0;iusrp, sensor_name, 0, value_h); - } else { - uhd_usrp_get_mboard_sensor(handler->usrp, sensor_name, 0, value_h); - } - uhd_sensor_value_to_bool(*value_h, &val_out); + uhd_error error; + *is_locked = false; + + uhd_sensor_value_handle value_h; + uhd_string_vector_handle sensors; + + uhd_string_vector_make(&sensors); + uhd_sensor_value_make_from_bool(&value_h, "", true, "True", "False"); + if (is_mboard) { + // motherboard sensor + error = uhd_usrp_get_mboard_sensor_names(handler->usrp, 0, &sensors); } else { - usleep(500); - val_out = true; + // daughterboard sensor + error = uhd_usrp_get_rx_sensor_names(handler->usrp, 0, &sensors); } - - return val_out; + + if (error == UHD_ERROR_NONE && find_string(sensors, sensor_name)) { + do { + if (is_mboard) { + error = uhd_usrp_get_mboard_sensor(handler->usrp, sensor_name, 0, &value_h); + } else { + error = uhd_usrp_get_rx_sensor(handler->usrp, sensor_name, 0, &value_h); + } + if (error != UHD_ERROR_NONE) { + break; + } + uhd_sensor_value_to_bool(value_h, is_locked); + usleep(1000); // 1ms + timeout -= 1; // 1ms + } while (*is_locked == false && timeout > 0); + } + if (error != UHD_ERROR_NONE) { + fprintf(stderr, + "%s has no sensor \"%s\", or reading failed. UHD error: %i\n", + is_mboard ? "Motherboard" : "Daugherboard", + sensor_name, + error); + // board doesn't have this sensor, sleep for timeout + *is_locked = true; + usleep(timeout * 1000); + } + + uhd_string_vector_free(&sensors); + uhd_sensor_value_free(&value_h); + + return error; } char* rf_uhd_devname(void* h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - return handler->devname; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + return handler->devname; } -bool rf_uhd_rx_wait_lo_locked(void *h) +bool rf_uhd_rx_wait_lo_locked(void* h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - - uhd_string_vector_handle mb_sensors; - uhd_string_vector_handle rx_sensors; - char *sensor_name; - uhd_sensor_value_handle value_h; - uhd_string_vector_make(&mb_sensors); - uhd_string_vector_make(&rx_sensors); - uhd_sensor_value_make_from_bool(&value_h, "", true, "True", "False"); - uhd_usrp_get_mboard_sensor_names(handler->usrp, 0, &mb_sensors); - uhd_usrp_get_rx_sensor_names(handler->usrp, 0, &rx_sensors); + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; - /*if (find_string(rx_sensors, "lo_locked")) { - sensor_name = "lo_locked"; - } else */if (find_string(mb_sensors, "ref_locked")) { - sensor_name = "ref_locked"; - } else { - sensor_name = NULL; - } - - double report = 0.0; - while (!isLocked(handler, sensor_name, false, &value_h) && report < 30.0) { - report += 0.1; - usleep(1000); - } + // wait for clock source to lock + char* sensor_name = "lo_locked"; + bool is_locked = false; - bool val = isLocked(handler, sensor_name, false, &value_h); - - uhd_string_vector_free(&mb_sensors); - uhd_string_vector_free(&rx_sensors); - uhd_sensor_value_free(&value_h); + // blocks until sensor is blocked + uhd_error error = wait_sensor_locked(handler, sensor_name, false, 300, &is_locked); - return val; + if (!is_locked || error != UHD_ERROR_NONE) { + fprintf(stderr, + "Could not lock reference clock source. Sensor: %s=%s, UHD error: %i\n", + sensor_name, + is_locked ? "true" : "false", + error); + } + + return is_locked; } -int rf_uhd_start_rx_stream(void *h, bool now) +int rf_uhd_start_rx_stream(void* h, bool now) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; - uhd_stream_cmd_t stream_cmd = { - .stream_mode = UHD_STREAM_MODE_START_CONTINUOUS, - .stream_now = now - }; + uhd_stream_cmd_t stream_cmd = {.stream_mode = UHD_STREAM_MODE_START_CONTINUOUS, .stream_now = now}; if (!now) { uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs); stream_cmd.time_spec_frac_secs += 0.2; @@ -249,45 +271,45 @@ int rf_uhd_start_rx_stream(void *h, bool now) return 0; } -int rf_uhd_stop_rx_stream(void *h) +int rf_uhd_stop_rx_stream(void* h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - uhd_stream_cmd_t stream_cmd = { - .stream_mode = UHD_STREAM_MODE_STOP_CONTINUOUS, - .stream_now = true - }; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + uhd_stream_cmd_t stream_cmd = {.stream_mode = UHD_STREAM_MODE_STOP_CONTINUOUS, .stream_now = true}; uhd_rx_streamer_issue_stream_cmd(handler->rx_stream, &stream_cmd); return 0; } -void rf_uhd_flush_buffer(void *h) +void rf_uhd_flush_buffer(void* h) { - int n; - cf_t tmp1[1024]; - cf_t tmp2[1024]; - void *data[2] = {tmp1, tmp2}; + int n; + cf_t tmp1[1024]; + cf_t tmp2[1024]; + void* data[2] = {tmp1, tmp2}; do { n = rf_uhd_recv_with_time_multi(h, data, 1024, 0, NULL, NULL); - } while (n > 0); + } while (n > 0); } -bool rf_uhd_has_rssi(void *h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; +bool rf_uhd_has_rssi(void* h) +{ + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; return handler->has_rssi; } -bool get_has_rssi(void *h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - uhd_string_vector_handle rx_sensors; +bool get_has_rssi(void* h) +{ + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + uhd_string_vector_handle rx_sensors; uhd_string_vector_make(&rx_sensors); uhd_usrp_get_rx_sensor_names(handler->usrp, 0, &rx_sensors); - bool ret = find_string(rx_sensors, "rssi"); + bool ret = find_string(rx_sensors, "rssi"); uhd_string_vector_free(&rx_sensors); - return ret; + return ret; } -float rf_uhd_get_rssi(void *h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; +float rf_uhd_get_rssi(void* h) +{ + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; if (handler->has_rssi) { double val_out; @@ -303,23 +325,23 @@ float rf_uhd_get_rssi(void *h) { } } -int rf_uhd_open(char *args, void **h) +int rf_uhd_open(char* args, void** h) { return rf_uhd_open_multi(args, h, 1); } -int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) +int rf_uhd_open_multi(char* args, void** h, uint32_t nof_channels) { if (h) { - *h = NULL; - - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) malloc(sizeof(rf_uhd_handler_t)); + *h = NULL; + + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)malloc(sizeof(rf_uhd_handler_t)); if (!handler) { perror("malloc"); - return -1; + return -1; } bzero(handler, sizeof(rf_uhd_handler_t)); - *h = handler; + *h = handler; // Disable fast-path (U/L/O) messages setenv("UHD_LOG_FASTPATH_DISABLE", "1", 0); @@ -331,26 +353,26 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) uhd_string_vector_handle devices_str; uhd_string_vector_make(&devices_str); uhd_usrp_find("", &devices_str); - - char args2[512]; - + + char args2[512]; + handler->dynamic_rate = true; - + // Allow NULL parameter if (args == NULL) { args = ""; - } + } handler->devname = NULL; pthread_mutex_init(&handler->tx_mutex, NULL); // Initialize handler handler->uhd_error_handler = NULL; - - bzero(zero_mem, sizeof(cf_t)*64*1024); + + bzero(zero_mem, sizeof(cf_t) * 64 * 1024); // Check external clock argument - enum {DEFAULT, EXTERNAL, GPSDO} clock_src; + enum { DEFAULT, EXTERNAL, GPSDO } clock_src; if (strstr(args, "clock=external")) { REMOVE_SUBSTRING_WITHCOMAS(args, "clock=external"); clock_src = EXTERNAL; @@ -371,7 +393,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) #endif // Set over the wire format - char *otw_format = "sc16"; + char* otw_format = "sc16"; if (strstr(args, "otw_format=sc12")) { REMOVE_SUBSTRING_WITHCOMAS(args, "otw_format=sc12"); otw_format = "sc12"; @@ -384,17 +406,17 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) } // Set transmitter subdevice spec string - const char tx_subdev_arg[] = "tx_subdev_spec="; - char tx_subdev_str[64] = {0}; - char *tx_subdev_ptr = strstr(args, tx_subdev_arg); + const char tx_subdev_arg[] = "tx_subdev_spec="; + char tx_subdev_str[64] = {0}; + char* tx_subdev_ptr = strstr(args, tx_subdev_arg); if (tx_subdev_ptr) { copy_subdev_string(tx_subdev_str, tx_subdev_ptr + strlen(tx_subdev_arg)); } // Set receiver subdevice spec string - const char rx_subdev_arg[] = "rx_subdev_spec="; - char rx_subdev_str[64] = {0}; - char *rx_subdev_ptr = strstr(args, rx_subdev_arg); + const char rx_subdev_arg[] = "rx_subdev_spec="; + char rx_subdev_str[64] = {0}; + char* rx_subdev_ptr = strstr(args, rx_subdev_arg); if (rx_subdev_ptr) { copy_subdev_string(rx_subdev_str, rx_subdev_ptr + strlen(rx_subdev_arg)); } @@ -410,66 +432,66 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) } /* If device type or name not given in args, choose a B200 */ - if (args[0]=='\0') { + if (args[0] == '\0') { if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) { // If B200 is available, use it args = "type=b200,master_clock_rate=23.04e6"; handler->current_master_clock = 23040000; - handler->devname = DEVNAME_B200; + handler->devname = DEVNAME_B200; } else if (find_string(devices_str, "type=x300")) { // Else if X300 is available, set master clock rate now (can't be changed later) - args = "type=x300,master_clock_rate=184.32e6"; + args = "type=x300,master_clock_rate=184.32e6"; handler->current_master_clock = 184320000; - handler->dynamic_rate = false; - handler->devname = DEVNAME_X300; + handler->dynamic_rate = false; + handler->devname = DEVNAME_X300; } else if (find_string(devices_str, "type=e3x0")) { // Else if E3X0 is available, set master clock rate now (can't be changed later) - args = "type=e3x0,master_clock_rate=30.72e6"; + args = "type=e3x0,master_clock_rate=30.72e6"; handler->dynamic_rate = false; - handler->devname = DEVNAME_E3X0; + handler->devname = DEVNAME_E3X0; } else if (find_string(devices_str, "type=n3xx")) { - args = "type=n3xx,master_clock_rate=122.88e6"; + args = "type=n3xx,master_clock_rate=122.88e6"; handler->current_master_clock = 122880000; - handler->dynamic_rate = false; - handler->devname = DEVNAME_N300; + handler->dynamic_rate = false; + handler->devname = DEVNAME_N300; srslte_use_standard_symbol_size(true); } } else { // If args is set and x300 type is specified, make sure master_clock_rate is defined if (strstr(args, "type=x300") && !strstr(args, "master_clock_rate")) { - sprintf(args2, "%s,master_clock_rate=184.32e6",args); - args = args2; + sprintf(args2, "%s,master_clock_rate=184.32e6", args); + args = args2; handler->current_master_clock = 184320000; - handler->dynamic_rate = false; - handler->devname = DEVNAME_X300; + handler->dynamic_rate = false; + handler->devname = DEVNAME_X300; } else if (strstr(args, "type=n3xx")) { sprintf(args2, "%s,master_clock_rate=122.88e6", args); - args = args2; + args = args2; handler->current_master_clock = 122880000; - handler->dynamic_rate = false; - handler->devname = DEVNAME_N300; + handler->dynamic_rate = false; + handler->devname = DEVNAME_N300; srslte_use_standard_symbol_size(true); - } else if (strstr(args, "type=e3x0")) { + } else if (strstr(args, "type=e3x0")) { snprintf(args2, sizeof(args2), "%s,master_clock_rate=30.72e6", args); - args = args2; + args = args2; handler->devname = DEVNAME_E3X0; } else { snprintf(args2, sizeof(args2), "%s,master_clock_rate=23.04e6", args); - args = args2; + args = args2; handler->current_master_clock = 23040000; - handler->devname = DEVNAME_B200; + handler->devname = DEVNAME_B200; } } - + uhd_string_vector_free(&devices_str); - + /* Create UHD handler */ printf("Opening USRP with args: %s\n", args); uhd_error error = uhd_usrp_make(&handler->usrp, args); if (error) { fprintf(stderr, "Error opening UHD: code %d\n", error); free(handler); - return -1; + return -1; } /* Set transmitter subdev spec if specified */ @@ -500,61 +522,79 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) if (strstr(dev_str, "B2") || strstr(dev_str, "B2")) { handler->devname = DEVNAME_B200; } else if (strstr(dev_str, "X3") || strstr(dev_str, "X3")) { - handler->devname = DEVNAME_X300; + handler->devname = DEVNAME_X300; } else if (strstr(dev_str, "n3xx")) { handler->devname = DEVNAME_N300; } } if (!handler->devname) { - handler->devname = "uhd_unknown"; + handler->devname = "uhd_unknown"; } - - // Set external clock reference + + bool is_locked = false; + char* sensor_name = ""; + + // Set external clock reference if (clock_src == EXTERNAL) { uhd_usrp_set_clock_source(handler->usrp, "external", 0); uhd_usrp_set_time_source(handler->usrp, "external", 0); + sensor_name = "ref_locked"; } else if (clock_src == GPSDO) { uhd_usrp_set_clock_source(handler->usrp, "gpsdo", 0); uhd_usrp_set_time_source(handler->usrp, "gpsdo", 0); + sensor_name = "gps_locked"; + } + // wait until external reference / GPS is locked + if (clock_src != DEFAULT) { + // blocks until clock source is locked + error = wait_sensor_locked(handler, sensor_name, true, 300, &is_locked); + + if (!is_locked || error != UHD_ERROR_NONE) { + fprintf(stderr, + "Could not lock reference clock source. Sensor: %s=%s, UHD error: %i\n", + sensor_name, + is_locked ? "true" : "false", + error); + } } handler->has_rssi = get_has_rssi(handler); - size_t channel[4] = {0, 1, 2, 3}; + size_t channel[4] = {0, 1, 2, 3}; uhd_stream_args_t stream_args = { - .cpu_format = "fc32", - .otw_format = otw_format, - .args = "", - .channel_list = channel, - .n_channels = nof_channels, + .cpu_format = "fc32", + .otw_format = otw_format, + .args = "", + .channel_list = channel, + .n_channels = nof_channels, }; - + handler->nof_rx_channels = nof_channels; handler->nof_tx_channels = nof_channels; /* Set default rate to avoid decimation warnings */ - for (int i=0;iusrp, 1.92e6, i); uhd_usrp_set_tx_rate(handler->usrp, 1.92e6, i); } if (nof_channels > 1) - uhd_usrp_set_time_unknown_pps(handler->usrp, 0, 0.0); + uhd_usrp_set_time_unknown_pps(handler->usrp, 0, 0.0); /* Initialize rx and tx stremers */ uhd_rx_streamer_make(&handler->rx_stream); error = uhd_usrp_get_rx_stream(handler->usrp, &stream_args, handler->rx_stream); if (error) { ERROR("Error opening RX stream: %d\n", error); - return -1; + return -1; } uhd_tx_streamer_make(&handler->tx_stream); error = uhd_usrp_get_tx_stream(handler->usrp, &stream_args, handler->tx_stream); if (error) { ERROR("Error opening TX stream: %d\n", error); - return -1; + return -1; } - + uhd_rx_streamer_max_num_samps(handler->rx_stream, &handler->rx_nof_samples); uhd_tx_streamer_max_num_samps(handler->tx_stream, &handler->tx_nof_samples); @@ -578,7 +618,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) uhd_tx_metadata_make(&handler->tx_md, false, 0, 0, false, false); // Set starting gain to half maximum in case of using AGC - rf_uhd_set_rx_gain(handler, handler->info.max_rx_gain*0.7); + rf_uhd_set_rx_gain(handler, handler->info.max_rx_gain * 0.7); #if HAVE_ASYNC_THREAD if (start_async_thread) { @@ -596,17 +636,16 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) return 0; } else { - return SRSLTE_ERROR_INVALID_INPUTS; + return SRSLTE_ERROR_INVALID_INPUTS; } } - -int rf_uhd_close(void *h) +int rf_uhd_close(void* h) { rf_uhd_stop_rx_stream(h); - - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - + + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + uhd_tx_metadata_free(&handler->tx_md); uhd_rx_metadata_free(&handler->rx_md_first); uhd_rx_metadata_free(&handler->rx_md); @@ -623,36 +662,39 @@ int rf_uhd_close(void *h) uhd_usrp_free(&handler->usrp); free(handler); - + /** Something else to close the USRP?? */ return SRSLTE_SUCCESS; } -void rf_uhd_set_master_clock_rate(void *h, double rate) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - if (fmod(handler->current_master_clock, rate)) { - if (handler->dynamic_rate) { - uhd_usrp_set_master_clock_rate(handler->usrp, rate, 0); - } +void rf_uhd_set_master_clock_rate(void* h, double rate) +{ + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + if (handler->dynamic_rate && handler->current_master_clock != rate) { + uhd_usrp_set_master_clock_rate(handler->usrp, rate, 0); handler->current_master_clock = rate; } } -bool rf_uhd_is_master_clock_dynamic(void *h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - return handler->dynamic_rate; -} - -double rf_uhd_set_rx_srate(void *h, double freq) +double rf_uhd_set_rx_srate(void* h, double freq) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + + // Set master clock rate + if (fmod(handler->current_master_clock, freq)) { + rf_uhd_set_master_clock_rate(handler, 4 * freq); + } + if (handler->nof_rx_channels > 1) { #ifdef UHD_SUPPORTS_COMMAND_TIME time_t full; double frac; uhd_usrp_get_time_now(handler->usrp, 0, &full, &frac); frac += 0.100; - if (frac >= 1.0) { full++; frac -= 1.0; }; + if (frac >= 1.0) { + full++; + frac -= 1.0; + }; uhd_usrp_set_command_time(handler->usrp, full, frac, 0); #endif /* UHD_SUPPORTS_COMMAND_TIME */ for (int i = 0; i < handler->nof_rx_channels; i++) { @@ -667,16 +709,25 @@ double rf_uhd_set_rx_srate(void *h, double freq) return freq; } -double rf_uhd_set_tx_srate(void *h, double freq) +double rf_uhd_set_tx_srate(void* h, double freq) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + + // Set master clock rate + if (fmod(handler->current_master_clock, freq)) { + rf_uhd_set_master_clock_rate(handler, 4 * freq); + } + if (handler->nof_tx_channels > 1) { #ifdef UHD_SUPPORTS_COMMAND_TIME time_t full; double frac; uhd_usrp_get_time_now(handler->usrp, 0, &full, &frac); frac += 0.100; - if (frac >= 1.0) { full++; frac -= 1.0; }; + if (frac >= 1.0) { + full++; + frac -= 1.0; + }; uhd_usrp_set_command_time(handler->usrp, full, frac, 0); #endif /* UHD_SUPPORTS_COMMAND_TIME */ for (int i = 0; i < handler->nof_tx_channels; i++) { @@ -689,49 +740,49 @@ double rf_uhd_set_tx_srate(void *h, double freq) uhd_usrp_set_tx_rate(handler->usrp, freq, 0); } handler->tx_rate = freq; - return freq; + return freq; } -double rf_uhd_set_rx_gain(void *h, double gain) +double rf_uhd_set_rx_gain(void* h, double gain) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - for (int i=0;inof_rx_channels;i++) { + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + for (int i = 0; i < handler->nof_rx_channels; i++) { uhd_usrp_set_rx_gain(handler->usrp, gain, i, ""); } return gain; } -double rf_uhd_set_tx_gain(void *h, double gain) +double rf_uhd_set_tx_gain(void* h, double gain) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - for (int i=0;inof_tx_channels;i++) { + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + for (int i = 0; i < handler->nof_tx_channels; i++) { uhd_usrp_set_tx_gain(handler->usrp, gain, i, ""); } return gain; } -double rf_uhd_get_rx_gain(void *h) +double rf_uhd_get_rx_gain(void* h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - double gain; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + double gain; uhd_usrp_get_rx_gain(handler->usrp, 0, "", &gain); return gain; } -double rf_uhd_get_tx_gain(void *h) +double rf_uhd_get_tx_gain(void* h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - double gain; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + double gain; uhd_usrp_get_tx_gain(handler->usrp, 0, "", &gain); return gain; } -srslte_rf_info_t *rf_uhd_get_info(void *h) +srslte_rf_info_t* rf_uhd_get_info(void* h) { - srslte_rf_info_t *info = NULL; + srslte_rf_info_t* info = NULL; if (h) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - info = &handler->info; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + info = &handler->info; } return info; } @@ -739,12 +790,12 @@ srslte_rf_info_t *rf_uhd_get_info(void *h) double rf_uhd_set_rx_freq(void* h, uint32_t ch, double freq) { uhd_tune_request_t tune_request = { - .target_freq = freq, - .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, + .target_freq = freq, + .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, .dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, }; uhd_tune_result_t tune_result; - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; if (ch < handler->nof_rx_channels) { uhd_usrp_set_rx_freq(handler->usrp, &tune_request, ch, &tune_result); } else { @@ -752,18 +803,19 @@ double rf_uhd_set_rx_freq(void* h, uint32_t ch, double freq) uhd_usrp_set_rx_freq(handler->usrp, &tune_request, i, &tune_result); } } + rf_uhd_rx_wait_lo_locked(handler); return freq; } double rf_uhd_set_tx_freq(void* h, uint32_t ch, double freq) { uhd_tune_request_t tune_request = { - .target_freq = freq, - .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, + .target_freq = freq, + .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, .dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, }; uhd_tune_result_t tune_result; - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; if (ch < handler->nof_tx_channels) { uhd_usrp_set_tx_freq(handler->usrp, &tune_request, ch, &tune_result); } else { @@ -774,9 +826,9 @@ double rf_uhd_set_tx_freq(void* h, uint32_t ch, double freq) return freq; } - -void rf_uhd_get_time(void *h, time_t *secs, double *frac_secs) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; +void rf_uhd_get_time(void* h, time_t* secs, double* frac_secs) +{ + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; uhd_usrp_get_time_now(handler->usrp, 0, secs, frac_secs); } @@ -788,33 +840,24 @@ void rf_uhd_sync_pps(void* h) } } -int rf_uhd_recv_with_time(void *h, - void *data, - uint32_t nsamples, - bool blocking, - time_t *secs, - double *frac_secs) +int rf_uhd_recv_with_time(void* h, void* data, uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs) { return rf_uhd_recv_with_time_multi(h, &data, nsamples, blocking, secs, frac_secs); } -int rf_uhd_recv_with_time_multi(void *h, - void *data[SRSLTE_MAX_PORTS], - uint32_t nsamples, - bool blocking, - time_t *secs, - double *frac_secs) +int rf_uhd_recv_with_time_multi( + void* h, void* data[SRSLTE_MAX_PORTS], uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs) { - rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - uhd_rx_metadata_handle *md = &handler->rx_md_first; - size_t rxd_samples = 0; - size_t rxd_samples_total = 0; - int trials = 0; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; + uhd_rx_metadata_handle* md = &handler->rx_md_first; + size_t rxd_samples = 0; + size_t rxd_samples_total = 0; + int trials = 0; if (blocking) { while (rxd_samples_total < nsamples && trials < 100) { - void *buffs_ptr[4]; - for (int i=0;inof_rx_channels;i++) { - cf_t *data_c = (cf_t*) data[i]; + void* buffs_ptr[4]; + for (int i = 0; i < handler->nof_rx_channels; i++) { + cf_t* data_c = (cf_t*)data[i]; buffs_ptr[i] = &data_c[rxd_samples_total]; } @@ -822,12 +865,12 @@ int rf_uhd_recv_with_time_multi(void *h, size_t num_rx_samples = (num_samps_left > handler->rx_nof_samples) ? handler->rx_nof_samples : num_samps_left; rxd_samples = 0; - uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, buffs_ptr, - num_rx_samples, md, 1.0, false, &rxd_samples); + uhd_error error = + uhd_rx_streamer_recv(handler->rx_stream, buffs_ptr, num_rx_samples, md, 1.0, false, &rxd_samples); if (error) { ERROR("Error receiving from UHD: %d\n", error); log_rx_error(handler); - return -1; + return -1; } uhd_rx_metadata_error_code_t error_code = 0; @@ -850,7 +893,7 @@ int rf_uhd_recv_with_time_multi(void *h, } } } else { - uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, data, nsamples, md, 0.0, false, &rxd_samples); + uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, data, nsamples, md, 0.0, false, &rxd_samples); rxd_samples_total = rxd_samples; if (error) { ERROR("Error receiving from UHD: %d\n", error); @@ -863,33 +906,34 @@ int rf_uhd_recv_with_time_multi(void *h, } return rxd_samples_total; } - -int rf_uhd_send_timed(void *h, - void *data, - int nsamples, - time_t secs, - double frac_secs, - bool has_time_spec, - bool blocking, - bool is_start_of_burst, - bool is_end_of_burst) + +int rf_uhd_send_timed(void* h, + void* data, + int nsamples, + time_t secs, + double frac_secs, + bool has_time_spec, + bool blocking, + bool is_start_of_burst, + bool is_end_of_burst) { - void *_data[SRSLTE_MAX_PORTS]= {data, zero_mem, zero_mem, zero_mem}; + void* _data[SRSLTE_MAX_PORTS] = {data, zero_mem, zero_mem, zero_mem}; - return rf_uhd_send_timed_multi(h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst); + return rf_uhd_send_timed_multi( + h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst); } -int rf_uhd_send_timed_multi(void *h, - void *data[4], - int nsamples, +int rf_uhd_send_timed_multi(void* h, + void* data[4], + int nsamples, time_t secs, double frac_secs, - bool has_time_spec, - bool blocking, - bool is_start_of_burst, - bool is_end_of_burst) + bool has_time_spec, + bool blocking, + bool is_start_of_burst, + bool is_end_of_burst) { - rf_uhd_handler_t* handler = (rf_uhd_handler_t*) h; + rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; pthread_mutex_lock(&handler->tx_mutex); int ret = -1; @@ -901,13 +945,13 @@ int rf_uhd_send_timed_multi(void *h, } size_t txd_samples; - int trials = 0; + int trials = 0; if (blocking) { if (has_time_spec) { uhd_tx_metadata_set_time_spec(&handler->tx_md, secs, frac_secs); } - int n = 0; - cf_t *data_c[4]; + int n = 0; + cf_t* data_c[4]; for (int i = 0; i < 4; i++) { data_c[i] = data[i] ? data[i] : zero_mem; } @@ -920,28 +964,28 @@ int rf_uhd_send_timed_multi(void *h, } else { uhd_tx_metadata_set_start(&handler->tx_md, false); } - + // middle packets are never end of burst, last one as defined if (nsamples - n > tx_samples) { uhd_tx_metadata_set_end(&handler->tx_md, false); } else { - tx_samples = nsamples - n; + tx_samples = nsamples - n; uhd_tx_metadata_set_end(&handler->tx_md, is_end_of_burst); } - const void *buffs_ptr[4]; + const void* buffs_ptr[4]; for (int i = 0; i < 4; i++) { - void *buff = (void*) &data_c[i][n]; + void* buff = (void*)&data_c[i][n]; buffs_ptr[i] = buff; } - uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, - tx_samples, &handler->tx_md, 1.0, &txd_samples); + uhd_error error = + uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, tx_samples, &handler->tx_md, 1.0, &txd_samples); if (error) { ERROR("Error sending to UHD: %d\n", error); goto unlock; } - // Increase time spec - uhd_tx_metadata_add_time_spec(&handler->tx_md, txd_samples/handler->tx_rate); + // Increase time spec + uhd_tx_metadata_add_time_spec(&handler->tx_md, txd_samples / handler->tx_rate); n += txd_samples; trials++; } while (n < nsamples && trials < 100); @@ -950,9 +994,9 @@ int rf_uhd_send_timed_multi(void *h, } else { - const void *buffs_ptr[4]; + const void* buffs_ptr[4]; for (int i = 0; i < 4; i++) { - buffs_ptr[i] = data[i]; + buffs_ptr[i] = data[i]; } uhd_tx_metadata_set_has_time_spec(&handler->tx_md, is_start_of_burst); uhd_tx_metadata_set_start(&handler->tx_md, is_start_of_burst); @@ -964,10 +1008,8 @@ int rf_uhd_send_timed_multi(void *h, } ret = txd_samples; - } unlock: pthread_mutex_unlock(&handler->tx_mutex); return ret; } - diff --git a/lib/src/phy/rf/rf_uhd_imp.h b/lib/src/phy/rf/rf_uhd_imp.h index 083679527..34aac195d 100644 --- a/lib/src/phy/rf/rf_uhd_imp.h +++ b/lib/src/phy/rf/rf_uhd_imp.h @@ -54,17 +54,9 @@ SRSLTE_API void rf_uhd_flush_buffer(void *h); SRSLTE_API bool rf_uhd_has_rssi(void *h); -SRSLTE_API float rf_uhd_get_rssi(void *h); +SRSLTE_API float rf_uhd_get_rssi(void* h); -SRSLTE_API bool rf_uhd_rx_wait_lo_locked(void *h); - -SRSLTE_API void rf_uhd_set_master_clock_rate(void *h, - double rate); - -SRSLTE_API bool rf_uhd_is_master_clock_dynamic(void *h); - -SRSLTE_API double rf_uhd_set_rx_srate(void *h, - double freq); +SRSLTE_API double rf_uhd_set_rx_srate(void* h, double freq); SRSLTE_API double rf_uhd_set_rx_gain(void *h, double gain); diff --git a/lib/src/phy/rf/rf_utils.c b/lib/src/phy/rf/rf_utils.c index cef343556..550e59697 100644 --- a/lib/src/phy/rf/rf_utils.c +++ b/lib/src/phy/rf/rf_utils.c @@ -53,7 +53,6 @@ int rf_rssi_scan(srslte_rf_t *rf, float *freqs, float *rssi, int nof_bands, doub f = (double) freqs[i]; srslte_rf_set_rx_freq(rf, 0, f); - srslte_rf_rx_wait_lo_locked(rf); usleep(10000); srslte_rf_start_rx_stream(rf, false); diff --git a/lib/src/phy/rf/rf_zmq_imp.c b/lib/src/phy/rf/rf_zmq_imp.c index 216daba81..c9d4dcd91 100644 --- a/lib/src/phy/rf/rf_zmq_imp.c +++ b/lib/src/phy/rf/rf_zmq_imp.c @@ -21,17 +21,14 @@ #include "rf_zmq_imp.h" #include "rf_helper.h" +#include "rf_zmq_imp_trx.h" #include -#include #include #include -#include -#include #include #include #include -#include -#include +#include #include typedef struct { @@ -39,11 +36,10 @@ typedef struct { char* devname; srslte_rf_info_t info; uint32_t nof_channels; - bool running; // RF State - double srate; // radio rate configured by upper layers - double base_srate; + uint32_t srate; // radio rate configured by upper layers + uint32_t base_srate; uint32_t decim_factor; // decimation factor between base_srate used on transport on radio's rate double rx_gain; double tx_freq; @@ -52,8 +48,8 @@ typedef struct { // Server void* context; - void* transmitter; - void* receiver; + rf_zmq_tx_t transmitter; + rf_zmq_rx_t receiver; char rx_port[PARAM_LEN]; char tx_port[PARAM_LEN]; @@ -61,31 +57,14 @@ typedef struct { // Various sample buffers cf_t* buffer_decimation; - cf_t* buffer_rx; cf_t* buffer_tx; - // Rx and Tx timestamps + // Rx timestamp uint64_t next_rx_ts; - uint64_t next_tx_ts; - - // Ringbuffer - srslte_ringbuffer_t rx_ringbuffer; pthread_t thread; - pthread_mutex_t mutex; - pthread_mutex_t mutex_tx; } rf_zmq_handler_t; -/* Definitions */ -#define VERBOSE 0 - -#define NSAMPLES2NBYTES(X) (((uint32_t)(X)) * sizeof(cf_t)) -#define NBYTES2NSAMPLES(X) ((X) / sizeof(cf_t)) -#define BUFFER_SIZE (NSAMPLES2NBYTES(3072000)) // 10 subframes at 20 MHz -#define ZMQ_TIMEOUT_MS 1000 -#define ZMQ_MAXTRIALS 3 -#define ZMQ_TRX_MARGIN_MS 1 - void update_rates(rf_zmq_handler_t* handler, double srate); /* @@ -97,14 +76,14 @@ const char zmq_devname[4] = "zmq"; * Static methods */ -static inline void rf_zmq_info(rf_zmq_handler_t* handler, const char* format, ...) +void rf_zmq_info(char* id, const char* format, ...) { #if VERBOSE struct timeval t; gettimeofday(&t, NULL); va_list args; va_start(args, format); - printf("[%s@%02ld.%06ld] ", handler ? handler->id : "zmq", t.tv_sec % 10, t.tv_usec); + printf("[%s@%02ld.%06ld] ", id ? id : "zmq", t.tv_sec % 10, t.tv_usec); vprintf(format, args); va_end(args); #else /* VERBOSE */ @@ -112,7 +91,7 @@ static inline void rf_zmq_info(rf_zmq_handler_t* handler, const char* format, .. #endif /* VERBOSE */ } -static void rf_zmq_error(rf_zmq_handler_t* handler, const char* format, ...) +void rf_zmq_error(char* id, const char* format, ...) { struct timeval t; gettimeofday(&t, NULL); @@ -129,14 +108,12 @@ static inline int update_ts(void* h, uint64_t* ts, int nsamples, const char* dir if (h && nsamples > 0) { rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h; - pthread_mutex_lock(&handler->mutex); (*ts) += nsamples; - pthread_mutex_unlock(&handler->mutex); srslte_timestamp_t _ts = {}; srslte_timestamp_init_uint64(&_ts, *ts, handler->base_srate); - rf_zmq_info(handler, " -> next %s time after %d samples: %d + %.3f\n", dir, nsamples, _ts.full_secs, - _ts.frac_secs); + rf_zmq_info( + handler->id, " -> next %s time after %d samples: %d + %.3f\n", dir, nsamples, _ts.full_secs, _ts.frac_secs); ret = SRSLTE_SUCCESS; } @@ -144,7 +121,7 @@ static inline int update_ts(void* h, uint64_t* ts, int nsamples, const char* dir return ret; } -static inline int rf_zmq_handle_error(rf_zmq_handler_t* handler, const char* text) +int rf_zmq_handle_error(char* id, const char* text) { int ret = SRSLTE_SUCCESS; @@ -154,127 +131,18 @@ static inline int rf_zmq_handle_error(rf_zmq_handler_t* handler, const char* tex // handled errors case EFSM: case EAGAIN: - rf_zmq_info(handler, "Warning %s: %s\n", text, zmq_strerror(err)); + rf_zmq_info(id, "Warning %s: %s\n", text, zmq_strerror(err)); break; - // critical non-handled errors + + // critical non-handled errors default: ret = SRSLTE_ERROR; - rf_zmq_error(handler, "Error %s: %s\n", text, zmq_strerror(err)); + rf_zmq_error(id, "Error %s: %s\n", text, zmq_strerror(err)); } return ret; } -static int rf_zmq_tx(rf_zmq_handler_t* handler, uint8_t* buffer, uint32_t nbytes) -{ - int n, ntrials; - pthread_mutex_lock(&handler->mutex_tx); - - // Receive Transmit request - uint8_t dummy; - - for (ntrials = 0, n = -1; ntrials < ZMQ_MAXTRIALS && n < 0 && handler->running; ntrials++) { - n = zmq_recv(handler->transmitter, &dummy, sizeof(dummy), 0); - if (n < 0) { - if (rf_zmq_handle_error(handler, "tx request receive")) { - n = SRSLTE_ERROR; - goto clean_exit; - } - } else { - rf_zmq_info(handler, " - tx request received\n"); - rf_zmq_info(handler, " - sending %d samples (%d B)\n", NBYTES2NSAMPLES(nbytes), nbytes); - } - } - - // Send zeros - for (ntrials = 0, n = -1; ntrials < ZMQ_MAXTRIALS && n < 0 && handler->running; ntrials++) { - n = zmq_send(handler->transmitter, buffer, nbytes, 0); - if (n < 0) { - if (rf_zmq_handle_error(handler, "tx baseband send")) { - n = SRSLTE_ERROR; - goto clean_exit; - } - } else if (n != nbytes) { - rf_zmq_error(handler, "[zmq] Error: transmitter expected %d bytes and sent %d. %s.\n", nbytes, n, - strerror(zmq_errno())); - n = SRSLTE_ERROR; - goto clean_exit; - } - } - // update both tx timestamp and ringbuffer - update_ts(handler, &handler->next_tx_ts, NBYTES2NSAMPLES(nbytes), "tx"); - -clean_exit: - pthread_mutex_unlock(&handler->mutex_tx); - - return (n > 0) ? nbytes : SRSLTE_ERROR; -} - -static int rf_zmq_tx_zeros(rf_zmq_handler_t* handler, int32_t nsamples) -{ - rf_zmq_info(handler, "Tx %d zero samples\n", nsamples); - - if (NSAMPLES2NBYTES(nsamples) > ZMQ_MAX_RX_BYTES) { - // can't transmit zeros, buffer too small - fprintf(stderr, "[zmq] Error: zero buffer too small (%ld) to transmit %ld samples\n", ZMQ_MAX_RX_BYTES, - NSAMPLES2NBYTES(nsamples)); - return SRSLTE_ERROR; - } - - bzero(handler->buffer_tx, NSAMPLES2NBYTES(nsamples)); - - return rf_zmq_tx(handler, (uint8_t*)handler->buffer_tx, NSAMPLES2NBYTES(nsamples)); -} - -static void* rf_zmq_async_rx_thread(void* h) -{ - rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h; - - while (handler->receiver && handler->running) { - int n = SRSLTE_ERROR; - uint8_t dummy = 0xFF; - int ntrials = 0; - - rf_zmq_info(handler, "-- ASYNC RX wait...\n"); - - // Send request - for (ntrials = 0; n < 0 && ntrials < ZMQ_MAXTRIALS && handler->running; ntrials++) { - rf_zmq_info(handler, " - tx'ing rx request\n"); - n = zmq_send(handler->receiver, &dummy, sizeof(dummy), 0); - if (n < 0) { - if (rf_zmq_handle_error(handler, "synchronous rx request send")) { - return NULL; - } - } - } - - // Receive baseband - for (n = (n < 0) ? 0 : -1; n < 0 && handler->running;) { - n = zmq_recv(handler->receiver, handler->buffer_rx, BUFFER_SIZE, 0); - if (n == -1) { - if (rf_zmq_handle_error(handler, "asynchronous rx baseband receive")) { - return NULL; - } - } else if (n > BUFFER_SIZE) { - fprintf(stderr, "[zmq] Error: receiver expected <= %ld bytes and received %d at channel %d.\n", BUFFER_SIZE, n, - 0); - return NULL; - } - } - - // Write received data in buffer - if (n > 0) { - if (srslte_ringbuffer_write(&handler->rx_ringbuffer, handler->buffer_rx, n) != n) { - rf_zmq_error(handler, "[zmq] error writing asynchronous ring buffer...\n"); - } - rf_zmq_info(handler, " - received %d baseband samples (%d B). %d samples available.\n", NBYTES2NSAMPLES(n), n, - srslte_ringbuffer_status(&handler->rx_ringbuffer)); - } - } - - return NULL; -} - /* * Public methods */ @@ -294,12 +162,6 @@ char* rf_zmq_devname(void* h) return (char*)zmq_devname; } -bool rf_zmq_rx_wait_lo_locked(void* h) -{ - // TODO: Return true if it is client and connected - return true; -} - int rf_zmq_start_rx_stream(void* h, bool now) { return SRSLTE_SUCCESS; @@ -348,7 +210,7 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels) } bzero(handler, sizeof(rf_zmq_handler_t)); *h = handler; - handler->base_srate = 23.04e6; // Sample rate for 100 PRB cell + handler->base_srate = ZMQ_BASERATE_DEFAULT_HZ; // Sample rate for 100 PRB cell handler->rx_gain = 0.0; handler->info.max_rx_gain = +INFINITY; handler->info.min_rx_gain = -INFINITY; @@ -356,9 +218,6 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels) handler->info.min_tx_gain = -INFINITY; strcpy(handler->id, "zmq\0"); - pthread_mutex_init(&handler->mutex, NULL); - pthread_mutex_init(&handler->mutex_tx, NULL); - // parse args if (args) { // base_srate @@ -369,7 +228,7 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels) if (config_ptr) { copy_subdev_string(config_str, config_ptr + strlen(config_arg)); printf("Using base rate=%s\n", config_str); - handler->base_srate = strtod(config_str, NULL); + handler->base_srate = (uint32_t)strtod(config_str, NULL); remove_substring(args, config_arg); remove_substring(args, config_str); } @@ -430,118 +289,44 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels) goto clean_exit; } + // initialize transmitter if (strlen(handler->tx_port) != 0) { - // Initialise transmitter - handler->transmitter = zmq_socket(handler->context, ZMQ_REP); - if (!handler->transmitter) { - fprintf(stderr, "[zmq] Error: creating transmitter socket\n"); + if (rf_zmq_tx_open(&handler->transmitter, handler->id, handler->context, handler->tx_port) != SRSLTE_SUCCESS) { + fprintf(stderr, "[zmq] Error: opening transmitter\n"); goto clean_exit; } - - rf_zmq_info(handler, "Binding transmitter: %s\n", handler->tx_port); - - ret = zmq_bind(handler->transmitter, handler->tx_port); - if (ret) { - fprintf(stderr, "Error: connecting transmitter socket: %s\n", zmq_strerror(zmq_errno())); - goto clean_exit; - } - -#if ZMQ_TIMEOUT_MS - // set recv timeout for transmitter - int timeout = ZMQ_TIMEOUT_MS; - if (zmq_setsockopt(handler->transmitter, ZMQ_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { - fprintf(stderr, "Error: setting receive timeout on tx socket\n"); - goto clean_exit; - } - if (zmq_setsockopt(handler->transmitter, ZMQ_SNDTIMEO, &timeout, sizeof(timeout)) == -1) { - fprintf(stderr, "Error: setting receive timeout on tx socket\n"); - goto clean_exit; - } - - // set linger timeout for transmitter - timeout = 0; - if (zmq_setsockopt(handler->transmitter, ZMQ_LINGER, &timeout, sizeof(timeout)) == -1) { - fprintf(stderr, "Error: setting linger timeout on tx socket\n"); - } -#endif - } else { fprintf(stdout, "[zmq] %s Tx port not specified. Disabling transmitter.\n", handler->id); } // initialize receiver if (strlen(handler->rx_port) != 0) { - handler->receiver = zmq_socket(handler->context, ZMQ_REQ); - if (!handler->receiver) { - fprintf(stderr, "[zmq] Error: creating receiver socket\n"); - goto clean_exit; - } - - rf_zmq_info(handler, "Connecting receiver: %s\n", handler->rx_port); - - ret = zmq_connect(handler->receiver, handler->rx_port); - if (ret) { - fprintf(stderr, "Error: binding receiver socket: %s\n", zmq_strerror(zmq_errno())); - goto clean_exit; - } - -#if ZMQ_TIMEOUT_MS - // set recv timeout for receiver - int timeout = ZMQ_TIMEOUT_MS; - if (zmq_setsockopt(handler->receiver, ZMQ_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { - fprintf(stderr, "Error: setting receive timeout on tx socket\n"); - goto clean_exit; - } - if (zmq_setsockopt(handler->receiver, ZMQ_SNDTIMEO, &timeout, sizeof(timeout)) == -1) { - fprintf(stderr, "Error: setting receive timeout on tx socket\n"); - goto clean_exit; - } - - timeout = 0; - // set linger timeout for receiver - if (zmq_setsockopt(handler->receiver, ZMQ_LINGER, &timeout, sizeof(timeout)) == -1) { - fprintf(stderr, "Error: setting linger timeout on rx socket\n"); - } -#endif - - // init rx ringbuffer - if (srslte_ringbuffer_init(&handler->rx_ringbuffer, BUFFER_SIZE)) { - fprintf(stderr, "Error, initiating rx ringbuffer\n"); + if (rf_zmq_rx_open(&handler->receiver, handler->id, handler->context, handler->rx_port) != SRSLTE_SUCCESS) { + fprintf(stderr, "[zmq] Error: opening receiver\n"); goto clean_exit; } } else { fprintf(stdout, "[zmq] %s Rx port not specified. Disabling receiver.\n", handler->id); } - if (handler->transmitter == NULL && handler->receiver == NULL) { + if (!handler->transmitter.running && !handler->receiver.running) { fprintf(stderr, "[zmq] Error: Neither Tx port nor Rx port specified.\n"); goto clean_exit; } // Create decimation and overflow buffer - handler->buffer_decimation = srslte_vec_malloc(ZMQ_MAX_RX_BYTES); + handler->buffer_decimation = srslte_vec_malloc(ZMQ_MAX_BUFFER_SIZE); if (!handler->buffer_decimation) { fprintf(stderr, "Error: allocating decimation buffer\n"); goto clean_exit; } - handler->buffer_tx = srslte_vec_malloc(ZMQ_MAX_RX_BYTES); + handler->buffer_tx = srslte_vec_malloc(ZMQ_MAX_BUFFER_SIZE); if (!handler->buffer_tx) { fprintf(stderr, "Error: allocating tx buffer\n"); goto clean_exit; } - handler->buffer_rx = srslte_vec_malloc(ZMQ_MAX_RX_BYTES); - if (!handler->buffer_rx) { - fprintf(stderr, "Error: allocating rx buffer\n"); - goto clean_exit; - } - - handler->running = true; - if (handler->receiver) { - pthread_create(&handler->thread, NULL, rf_zmq_async_rx_thread, handler); - } - ret = SRSLTE_SUCCESS; clean_exit: @@ -558,23 +343,15 @@ int rf_zmq_close(void* h) rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h; - rf_zmq_info(handler, "Closing %s ...\n", handler->id); + rf_zmq_info(handler->id, "Closing ...\n"); - handler->running = false; if (handler->thread) { pthread_join(handler->thread, NULL); pthread_detach(handler->thread); } - if (handler->transmitter) { - zmq_close(handler->transmitter); - handler->transmitter = NULL; - } - if (handler->receiver) { - zmq_close(handler->receiver); - handler->receiver = NULL; - srslte_ringbuffer_free(&handler->rx_ringbuffer); - } + rf_zmq_tx_close(&handler->transmitter); + rf_zmq_rx_close(&handler->receiver); if (handler->context) { zmq_ctx_destroy(handler->context); @@ -588,35 +365,18 @@ int rf_zmq_close(void* h) free(handler->buffer_tx); } - if (handler->buffer_rx) { - free(handler->buffer_rx); - } - - pthread_mutex_destroy(&handler->mutex); - pthread_mutex_destroy(&handler->mutex_tx); - // Free all free(handler); return SRSLTE_SUCCESS; } -void rf_zmq_set_master_clock_rate(void* h, double rate) -{ - // Do nothing -} - -bool rf_zmq_is_master_clock_dynamic(void* h) -{ - return false; -} - void update_rates(rf_zmq_handler_t* handler, double srate) { if (handler) { // Decimation must be full integer if (((uint64_t)handler->base_srate % (uint64_t)srate) == 0) { - handler->srate = srate; + handler->srate = (uint32_t)srate; handler->decim_factor = handler->base_srate / handler->srate; } else { fprintf(stderr, "Error: couldn't update sample rate. %.2f is not divisible by %.2f\n", srate / 1e6, @@ -740,9 +500,8 @@ int rf_zmq_recv_with_time_multi( uint32_t nbytes = NSAMPLES2NBYTES(nsamples * handler->decim_factor); uint32_t nsamples_baserate = nsamples * handler->decim_factor; - uint32_t nbytes_baserate = NSAMPLES2NBYTES(nsamples_baserate); - rf_zmq_info(handler, "Rx %d samples (%d B)\n", nsamples, nbytes); + rf_zmq_info(handler->id, "Rx %d samples (%d B)\n", nsamples, nbytes); // set timestamp for this reception if (secs != NULL && frac_secs != NULL) { @@ -753,48 +512,56 @@ int rf_zmq_recv_with_time_multi( } // return if receiver is turned off - if (handler->receiver == NULL) { + if (!handler->receiver.running) { update_ts(handler, &handler->next_rx_ts, nsamples_baserate, "rx"); return nsamples; } // Check available buffer size - if (nbytes > ZMQ_MAX_RX_BYTES) { - fprintf(stderr, "[zmq] Error: Trying to receive %d B but buffer is only %ld B at channel %d.\n", nbytes, - ZMQ_MAX_RX_BYTES, 0); + if (nbytes > ZMQ_MAX_BUFFER_SIZE) { + fprintf(stderr, + "[zmq] Error: Trying to receive %d B but buffer is only %ld B at channel %d.\n", + nbytes, + ZMQ_MAX_BUFFER_SIZE, + 0); goto clean_exit; } // receive samples srslte_timestamp_t ts_tx = {}, ts_rx = {}; - srslte_timestamp_init_uint64(&ts_tx, handler->next_tx_ts, handler->base_srate); + srslte_timestamp_init_uint64(&ts_tx, handler->transmitter.nsamples, handler->base_srate); srslte_timestamp_init_uint64(&ts_rx, handler->next_rx_ts, handler->base_srate); - rf_zmq_info(handler, " - next rx time: %d + %.3f\n", ts_rx.full_secs, ts_rx.frac_secs); - rf_zmq_info(handler, " - next tx time: %d + %.3f\n", ts_tx.full_secs, ts_tx.frac_secs); + rf_zmq_info(handler->id, " - next rx time: %d + %.3f\n", ts_rx.full_secs, ts_rx.frac_secs); + rf_zmq_info(handler->id, " - next tx time: %d + %.3f\n", ts_tx.full_secs, ts_tx.frac_secs); + + // Leave time for the Tx to transmit + usleep((1000000 * nsamples) / handler->base_srate); // check for tx gap if we're also transmitting on this radio - if (handler->transmitter) { - uint32_t margin_nsamples = - (uint32_t)(handler->tx_used ? (0) : (nsamples_baserate + ZMQ_TRX_MARGIN_MS * handler->base_srate / 1000.0)); - int num_tx_gap_samples_base_rate = (int)(handler->next_rx_ts - handler->next_tx_ts + margin_nsamples); - if (num_tx_gap_samples_base_rate > 0) { - rf_zmq_info(handler, " - tx_gap of %d samples\n", num_tx_gap_samples_base_rate); - - // Transmit zero samples - rf_zmq_tx_zeros(handler, num_tx_gap_samples_base_rate); - } else { - rf_zmq_info(handler, " - no tx gap detected\n"); - } + if (handler->transmitter.running) { + rf_zmq_tx_align(&handler->transmitter, handler->next_rx_ts + nsamples_baserate); } // copy from rx buffer as many samples as requested into provided buffer cf_t* ptr = (handler->decim_factor != 1) ? handler->buffer_decimation : data[0]; - if (srslte_ringbuffer_read(&handler->rx_ringbuffer, ptr, nbytes_baserate) != nbytes) { - fprintf(stderr, "Error: reading from rx ringbuffer.\n"); - goto clean_exit; + int32_t count = 0; + while (count < nsamples_baserate && handler->receiver.running) { + int32_t n = rf_zmq_rx_baseband(&handler->receiver, &ptr[count], nsamples_baserate); + if (n > 0) { + // No error + count += n; + } else if (n == SRSLTE_ERROR_TIMEOUT) { + // Timeout, do nothing, keep going + } else if (n > 0) { + // Other error, exit + fprintf(stderr, "Error: receiving data.\n"); + goto clean_exit; + } } - rf_zmq_info(handler, " - read %d samples. %d samples available\n", NBYTES2NSAMPLES(nbytes), - NBYTES2NSAMPLES(srslte_ringbuffer_status(&handler->rx_ringbuffer))); + rf_zmq_info(handler->id, + " - read %d samples. %d samples available\n", + NBYTES2NSAMPLES(nbytes), + NBYTES2NSAMPLES(srslte_ringbuffer_status(&handler->receiver.ringbuffer))); // decimate if needed if (handler->decim_factor != 1) { @@ -809,10 +576,17 @@ int rf_zmq_recv_with_time_multi( } dst[i] = avg; } - rf_zmq_info(handler, " - re-adjust bytes due to %dx decimation %d --> %d samples)\n", handler->decim_factor, - nsamples_baserate, nsamples); + rf_zmq_info(handler->id, + " - re-adjust bytes due to %dx decimation %d --> %d samples)\n", + handler->decim_factor, + nsamples_baserate, + nsamples); } + // Set gain + float scale = powf(10.0f, handler->rx_gain / 20); + srslte_vec_sc_prod_cfc(data[0], scale, data[0], nsamples); + // update rx time update_ts(handler, &handler->next_rx_ts, nsamples_baserate, "rx"); } @@ -859,49 +633,47 @@ int rf_zmq_send_timed_multi(void* h, uint32_t nsamples_baseband = nsamples * handler->decim_factor; uint32_t nbytes_baseband = NSAMPLES2NBYTES(nsamples_baseband); - if (nbytes_baseband > ZMQ_MAX_RX_BYTES) { - fprintf(stderr, "Error: trying to transmit too many samples (%d > %ld).\n", nbytes, ZMQ_MAX_RX_BYTES); + if (nbytes_baseband > ZMQ_MAX_BUFFER_SIZE) { + fprintf(stderr, "Error: trying to transmit too many samples (%d > %ld).\n", nbytes, ZMQ_MAX_BUFFER_SIZE); goto clean_exit; } - rf_zmq_info(handler, "Tx %d samples (%d B)\n", nsamples, nbytes); + rf_zmq_info(handler->id, "Tx %d samples (%d B)\n", nsamples, nbytes); // return if transmitter is switched off - if (handler->tx_port == 0) { + if (strlen(handler->tx_port) == 0) { return SRSLTE_SUCCESS; } // check if this is a tx in the future if (has_time_spec) { - rf_zmq_info(handler, " - tx time: %d + %.3f\n", secs, frac_secs); + rf_zmq_info(handler->id, " - tx time: %d + %.3f\n", secs, frac_secs); srslte_timestamp_t ts = {}; srslte_timestamp_init(&ts, secs, frac_secs); uint64_t tx_ts = srslte_timestamp_uint64(&ts, handler->base_srate); - int32_t num_tx_gap_samples = (int32_t)((int64_t)tx_ts - (int64_t)handler->next_tx_ts); + int num_tx_gap_samples = rf_zmq_tx_align(&handler->transmitter, tx_ts); if (num_tx_gap_samples < 0) { - fprintf(stderr, "[zmq] Error: tx time is %.3f ms in the past (%ld < %ld)\n", - -1000.0 * num_tx_gap_samples / handler->base_srate, tx_ts, handler->next_tx_ts); + fprintf(stderr, + "[zmq] Error: tx time is %.3f ms in the past (%ld < %ld)\n", + -1000.0 * num_tx_gap_samples / handler->base_srate, + tx_ts, + handler->transmitter.nsamples); goto clean_exit; - } else if (num_tx_gap_samples > 0) { - rf_zmq_info(handler, " - tx gap of %d baseband samples\n", num_tx_gap_samples); - - // send zero samples - int n = rf_zmq_tx_zeros(handler, num_tx_gap_samples); - if (n == -1) { - goto clean_exit; - } - } else { - rf_zmq_info(handler, " - no tx gap detected\n"); } } + // Select buffer pointer depending on interpolation cf_t* buf = (handler->decim_factor != 1) ? handler->buffer_tx : data[0]; + // Interpolate if required if (handler->decim_factor != 1) { - rf_zmq_info(handler, " - re-adjust bytes due to %dx interpolation %d --> %d samples)\n", handler->decim_factor, - nsamples, nsamples_baseband); + rf_zmq_info(handler->id, + " - re-adjust bytes due to %dx interpolation %d --> %d samples)\n", + handler->decim_factor, + nsamples, + nsamples_baseband); int n = 0; cf_t* src = data[0]; @@ -919,8 +691,8 @@ int rf_zmq_send_timed_multi(void* h, } } - // send baseband samples - int n = rf_zmq_tx(handler, (uint8_t*)buf, nbytes_baseband); + // Send base-band samples + int n = rf_zmq_tx_baseband(&handler->transmitter, buf, nsamples_baseband); if (n == SRSLTE_ERROR) { goto clean_exit; } diff --git a/lib/src/phy/rf/rf_zmq_imp.h b/lib/src/phy/rf/rf_zmq_imp.h index 06f49c28f..cab2f68e6 100644 --- a/lib/src/phy/rf/rf_zmq_imp.h +++ b/lib/src/phy/rf/rf_zmq_imp.h @@ -28,8 +28,6 @@ #define DEVNAME_ZMQ "ZeroMQ" #define PARAM_LEN (128) #define PARAM_LEN_SHORT (PARAM_LEN / 2) -#define ZMQ_MAX_RX_BYTES \ - (5 * SRSLTE_SF_LEN_MAX * sizeof(cf_t)) // Five subframes at max LTE rate using default FFT-length SRSLTE_API int rf_zmq_open(char* args, void** handler); @@ -51,12 +49,6 @@ SRSLTE_API bool rf_zmq_has_rssi(void* h); SRSLTE_API float rf_zmq_get_rssi(void* h); -SRSLTE_API bool rf_zmq_rx_wait_lo_locked(void* h); - -SRSLTE_API void rf_zmq_set_master_clock_rate(void* h, double rate); - -SRSLTE_API bool rf_zmq_is_master_clock_dynamic(void* h); - SRSLTE_API double rf_zmq_set_rx_srate(void* h, double freq); SRSLTE_API double rf_zmq_set_rx_gain(void* h, double gain); diff --git a/lib/src/phy/rf/rf_zmq_imp_rx.c b/lib/src/phy/rf/rf_zmq_imp_rx.c new file mode 100644 index 000000000..97d99b658 --- /dev/null +++ b/lib/src/phy/rf/rf_zmq_imp_rx.c @@ -0,0 +1,197 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2019 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE 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. + * + * srsLTE 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 "rf_zmq_imp_trx.h" +#include +#include +#include +#include + +static void* rf_zmq_async_rx_thread(void* h) +{ + rf_zmq_rx_t* q = (rf_zmq_rx_t*)h; + + while (q->sock && q->running) { + int nbytes = 0; + int n = SRSLTE_ERROR; + uint8_t dummy = 0xFF; + + rf_zmq_info(q->id, "-- ASYNC RX wait...\n"); + + // Send request + while (n < 0 && q->running) { + rf_zmq_info(q->id, " - tx'ing rx request\n"); + n = zmq_send(q->sock, &dummy, sizeof(dummy), 0); + if (n < 0) { + if (rf_zmq_handle_error(q->id, "synchronous rx request send")) { + return NULL; + } + } + } + + // Receive baseband + for (n = (n < 0) ? 0 : -1; n < 0 && q->running;) { + n = zmq_recv(q->sock, q->temp_buffer, ZMQ_MAX_BUFFER_SIZE, 0); + if (n == -1) { + if (rf_zmq_handle_error(q->id, "asynchronous rx baseband receive")) { + return NULL; + } + + } else if (n > ZMQ_MAX_BUFFER_SIZE) { + fprintf(stderr, + "[zmq] Error: receiver expected <= %ld bytes and received %d at channel %d.\n", + ZMQ_MAX_BUFFER_SIZE, + n, + 0); + return NULL; + } else { + nbytes = n; + } + } + + // Write received data in buffer + if (nbytes > 0) { + n = -1; + + // Try to write in ring buffer + while (n < 0 && q->running) { + n = srslte_ringbuffer_write_timed(&q->ringbuffer, q->temp_buffer, nbytes, ZMQ_TIMEOUT_MS); + } + + // Check write + if (nbytes == n) { + rf_zmq_info(q->id, + " - received %d baseband samples (%d B). %d samples available.\n", + NBYTES2NSAMPLES(n), + n, + NBYTES2NSAMPLES(srslte_ringbuffer_status(&q->ringbuffer))); + } + } + } + + return NULL; +} + +int rf_zmq_rx_open(rf_zmq_rx_t* q, char* id, void* zmq_ctx, char* sock_args) +{ + int ret = SRSLTE_ERROR; + + if (q) { + // Copy id + strncpy(q->id, id, 16); + + // Zero object + bzero(q, sizeof(rf_zmq_tx_t)); + + // Create socket + q->sock = zmq_socket(zmq_ctx, ZMQ_REQ); + if (!q->sock) { + fprintf(stderr, "[zmq] Error: creating transmitter socket\n"); + goto clean_exit; + } + + rf_zmq_info(q->id, "Connecting receiver: %s\n", sock_args); + + ret = zmq_connect(q->sock, sock_args); + if (ret) { + fprintf(stderr, "Error: connecting receiver socket: %s\n", zmq_strerror(zmq_errno())); + goto clean_exit; + } + +#if ZMQ_TIMEOUT_MS + int timeout = ZMQ_TIMEOUT_MS; + if (zmq_setsockopt(q->sock, ZMQ_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { + fprintf(stderr, "Error: setting receive timeout on rx socket\n"); + goto clean_exit; + } + + if (zmq_setsockopt(q->sock, ZMQ_SNDTIMEO, &timeout, sizeof(timeout)) == -1) { + fprintf(stderr, "Error: setting receive timeout on rx socket\n"); + goto clean_exit; + } + + timeout = 0; + if (zmq_setsockopt(q->sock, ZMQ_LINGER, &timeout, sizeof(timeout)) == -1) { + fprintf(stderr, "Error: setting linger timeout on rx socket\n"); + goto clean_exit; + } +#endif + + if (srslte_ringbuffer_init(&q->ringbuffer, ZMQ_MAX_BUFFER_SIZE)) { + fprintf(stderr, "Error: initiating ringbuffer\n"); + goto clean_exit; + } + + q->temp_buffer = srslte_vec_malloc(ZMQ_MAX_BUFFER_SIZE); + if (!q->temp_buffer) { + fprintf(stderr, "Error: allocating rx buffer\n"); + goto clean_exit; + } + + if (pthread_mutex_init(&q->mutex, NULL)) { + fprintf(stderr, "Error: creating mutex\n"); + goto clean_exit; + } + + if (pthread_create(&q->thread, NULL, rf_zmq_async_rx_thread, q)) { + fprintf(stderr, "Error: creating thread\n"); + goto clean_exit; + } + + q->running = true; + ret = SRSLTE_SUCCESS; + } + +clean_exit: + return ret; +} + +int rf_zmq_rx_baseband(rf_zmq_rx_t* q, cf_t* buffer, uint32_t nsamples) +{ + return srslte_ringbuffer_read_timed(&q->ringbuffer, buffer, NSAMPLES2NBYTES(nsamples), ZMQ_TIMEOUT_MS); +} + +void rf_zmq_rx_close(rf_zmq_rx_t* q) +{ + rf_zmq_info(q->id, "Closing ...\n"); + q->running = false; + + if (q->thread) { + pthread_join(q->thread, NULL); + pthread_detach(q->thread); + } + + srslte_ringbuffer_free(&q->ringbuffer); + + if (q->temp_buffer) { + free(q->temp_buffer); + } + + if (q->sock) { + zmq_close(q->sock); + q->sock = NULL; + } +} diff --git a/lib/src/phy/rf/rf_zmq_imp_trx.h b/lib/src/phy/rf/rf_zmq_imp_trx.h new file mode 100644 index 000000000..2f6f8727f --- /dev/null +++ b/lib/src/phy/rf/rf_zmq_imp_trx.h @@ -0,0 +1,91 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2019 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_RF_ZMQ_IMP_TRX_H +#define SRSLTE_RF_ZMQ_IMP_TRX_H + +#include +#include +#include + +/* Definitions */ +#define VERBOSE (0) +#define NSAMPLES2NBYTES(X) (((uint32_t)(X)) * sizeof(cf_t)) +#define NBYTES2NSAMPLES(X) ((X) / sizeof(cf_t)) +#define ZMQ_MAX_BUFFER_SIZE (NSAMPLES2NBYTES(3072000)) // 10 subframes at 20 MHz +#define ZMQ_TIMEOUT_MS (1000) +#define ZMQ_BASERATE_DEFAULT_HZ (23040000) + +typedef struct { + char id[16]; + void* sock; + uint64_t nsamples; + bool running; + pthread_mutex_t mutex; + cf_t* zeros; +} rf_zmq_tx_t; + +typedef struct { + char id[16]; + void* sock; + uint64_t nsamples; + bool running; + pthread_t thread; + pthread_mutex_t mutex; + srslte_ringbuffer_t ringbuffer; + cf_t* temp_buffer; +} rf_zmq_rx_t; + +/* + * Common functions + */ +SRSLTE_API void rf_zmq_info(char* id, const char* format, ...); + +SRSLTE_API void rf_zmq_error(char* id, const char* format, ...); + +SRSLTE_API int rf_zmq_handle_error(char* id, const char* text); + +/* + * Transmitter functions + */ +SRSLTE_API int rf_zmq_tx_open(rf_zmq_tx_t* q, const char* id, void* zmq_ctx, char* sock_args); + +SRSLTE_API int rf_zmq_tx_align(rf_zmq_tx_t* q, uint64_t ts); + +SRSLTE_API int rf_zmq_tx_baseband(rf_zmq_tx_t* q, cf_t* buffer, uint32_t nsamples); + +SRSLTE_API void rf_zmq_tx_close(rf_zmq_tx_t* q); + +/* + * Receiver functions + */ +SRSLTE_API int rf_zmq_rx_open(rf_zmq_rx_t* q, char* id, void* zmq_ctx, char* sock_args); + +SRSLTE_API int rf_zmq_rx_baseband(rf_zmq_rx_t* q, cf_t* buffer, uint32_t nsamples); + +SRSLTE_API void rf_zmq_rx_close(rf_zmq_rx_t* q); + +#endif // SRSLTE_RF_ZMQ_IMP_TRX_H diff --git a/lib/src/phy/rf/rf_zmq_imp_tx.c b/lib/src/phy/rf/rf_zmq_imp_tx.c new file mode 100644 index 000000000..ad38d2e7e --- /dev/null +++ b/lib/src/phy/rf/rf_zmq_imp_tx.c @@ -0,0 +1,190 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2019 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE 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. + * + * srsLTE 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 "rf_zmq_imp_trx.h" +#include +#include +#include +#include +#include + +int rf_zmq_tx_open(rf_zmq_tx_t* q, const char* id, void* zmq_ctx, char* sock_args) +{ + int ret = SRSLTE_ERROR; + + if (q) { + // Copy id + strncpy(q->id, id, 16); + + // Zero object + bzero(q, sizeof(rf_zmq_tx_t)); + + // Create socket + q->sock = zmq_socket(zmq_ctx, ZMQ_REP); + if (!q->sock) { + fprintf(stderr, "[zmq] Error: creating transmitter socket\n"); + goto clean_exit; + } + + rf_zmq_info(q->id, "Binding transmitter: %s\n", sock_args); + + ret = zmq_bind(q->sock, sock_args); + if (ret) { + fprintf(stderr, "Error: connecting transmitter socket: %s\n", zmq_strerror(zmq_errno())); + goto clean_exit; + } + +#if ZMQ_TIMEOUT_MS + int timeout = ZMQ_TIMEOUT_MS; + if (zmq_setsockopt(q->sock, ZMQ_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { + fprintf(stderr, "Error: setting receive timeout on tx socket\n"); + goto clean_exit; + } + + if (zmq_setsockopt(q->sock, ZMQ_SNDTIMEO, &timeout, sizeof(timeout)) == -1) { + fprintf(stderr, "Error: setting receive timeout on tx socket\n"); + goto clean_exit; + } + + timeout = 0; + if (zmq_setsockopt(q->sock, ZMQ_LINGER, &timeout, sizeof(timeout)) == -1) { + fprintf(stderr, "Error: setting linger timeout on tx socket\n"); + goto clean_exit; + } +#endif + + if (pthread_mutex_init(&q->mutex, NULL)) { + fprintf(stderr, "Error: creating mutex\n"); + goto clean_exit; + } + + q->zeros = srslte_vec_malloc(ZMQ_MAX_BUFFER_SIZE); + if (!q->zeros) { + fprintf(stderr, "Error: allocating zeros\n"); + goto clean_exit; + } + bzero(q->zeros, ZMQ_MAX_BUFFER_SIZE); + + q->running = true; + + ret = SRSLTE_SUCCESS; + } + +clean_exit: + return ret; +} + +static int _rf_zmq_tx_baseband(rf_zmq_tx_t* q, cf_t* buffer, uint32_t nsamples) +{ + int n = SRSLTE_ERROR; + + while (n < 0 && q->running) { + // Receive Transmit request + uint8_t dummy; + n = zmq_recv(q->sock, &dummy, sizeof(dummy), 0); + if (n < 0) { + if (rf_zmq_handle_error(q->id, "tx request receive")) { + n = SRSLTE_ERROR; + goto clean_exit; + } + } else { + // Tx request received successful + rf_zmq_info(q->id, " - tx request received\n"); + rf_zmq_info(q->id, " - sending %d samples (%d B)\n", nsamples, NSAMPLES2NBYTES(nsamples)); + } + + // Send base-band if request was received + if (n > 0) { + n = zmq_send(q->sock, buffer, NSAMPLES2NBYTES(nsamples), 0); + if (n < 0) { + if (rf_zmq_handle_error(q->id, "tx baseband send")) { + n = SRSLTE_ERROR; + goto clean_exit; + } + } else if (n != NSAMPLES2NBYTES(nsamples)) { + rf_zmq_error(q->id, + "[zmq] Error: transmitter expected %d bytes and sent %d. %s.\n", + NSAMPLES2NBYTES(nsamples), + n, + strerror(zmq_errno())); + n = SRSLTE_ERROR; + goto clean_exit; + } + } + + // If failed to receive request or send base-band, keep trying + } + + // Increment sample counter + q->nsamples += nsamples; + n = nsamples; + +clean_exit: + return n; +} + +int rf_zmq_tx_align(rf_zmq_tx_t* q, uint64_t ts) +{ + pthread_mutex_lock(&q->mutex); + + int64_t nsamples = (int64_t)ts - (int64_t)q->nsamples; + + if (nsamples > 0) { + rf_zmq_info(q->id, " - Detected Tx gap of %d samples.\n", nsamples); + _rf_zmq_tx_baseband(q, q->zeros, (uint32_t)nsamples); + } + + pthread_mutex_unlock(&q->mutex); + + return (int)nsamples; +} + +int rf_zmq_tx_baseband(rf_zmq_tx_t* q, cf_t* buffer, uint32_t nsamples) +{ + int n; + + pthread_mutex_lock(&q->mutex); + + n = _rf_zmq_tx_baseband(q, buffer, nsamples); + + pthread_mutex_unlock(&q->mutex); + + return n; +} + +void rf_zmq_tx_close(rf_zmq_tx_t* q) +{ + q->running = false; + + if (q->zeros) { + free(q->zeros); + } + + if (q->sock) { + zmq_close(q->sock); + q->sock = NULL; + } +} diff --git a/lib/src/phy/sync/find_sss.c b/lib/src/phy/sync/find_sss.c index 7eec97b24..c7468b269 100644 --- a/lib/src/phy/sync/find_sss.c +++ b/lib/src/phy/sync/find_sss.c @@ -65,18 +65,30 @@ static void corr_all_sz_partial(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSL static void extract_pair_sss(srslte_sss_t *q, const cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) { cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; + // Run FFT srslte_dft_run_c(&q->dftp_input, input, input_fft); - + + // Equalize if available channel estimate if (ce) { srslte_vec_div_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce, &input_fft[q->fft_size/2-SRSLTE_SSS_N], 2*SRSLTE_SSS_N); } - + + // Extract FFT Data for (int i = 0; i < SRSLTE_SSS_N; i++) { y[0][i] = input_fft[q->fft_size/2-SRSLTE_SSS_N + 2 * i]; y[1][i] = input_fft[q->fft_size/2-SRSLTE_SSS_N + 2 * i + 1]; } + // Normalize + for (int i = 0; i < 2; i++) { + float avg_pow = srslte_vec_avg_power_cf(y[i], SRSLTE_SSS_N); + float rms = (avg_pow != 0.0f) ? sqrtf(avg_pow) : 1.0f; + + srslte_vec_sc_prod_cfc(y[i], 1.0 / rms, y[i], SRSLTE_SSS_N); + } + + // Unmask signal with sequence generated from NID2 srslte_vec_prod_cfc(y[0], q->fc_tables[q->N_id_2].c[0], y[0], SRSLTE_SSS_N); srslte_vec_prod_cfc(y[1], q->fc_tables[q->N_id_2].c[1], y[1], SRSLTE_SSS_N); diff --git a/lib/src/phy/sync/npss.c b/lib/src/phy/sync/npss.c new file mode 100644 index 000000000..3bd60b2c2 --- /dev/null +++ b/lib/src/phy/sync/npss.c @@ -0,0 +1,436 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include + +#include "srslte/phy/common/phy_common.h" +#include "srslte/phy/dft/dft.h" +#include "srslte/phy/io/filesink.h" +#include "srslte/phy/sync/npss.h" +#include "srslte/phy/utils/convolution.h" +#include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" + +#define PRINT_ERR(err) fprintf(stderr, "%s(): %s", __PRETTY_FUNCTION__, err) + +#define DUMP_SIGNALS 0 +#define DO_FREQ_SHIFT 1 + +const float factor_lut[SRSLTE_NPSS_LEN] = {1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1}; + +/* Initializes the NPSS synchronization object. + * + * It correlates a signal of frame_size samples with the NPSS sequence in the time domain + * The NPSS sequence is transformed using 11 * fft_size samples plus cyclic prefix. + */ +int srslte_npss_synch_init(srslte_npss_synch_t* q, uint32_t frame_size, uint32_t fft_size) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL) { + ret = SRSLTE_ERROR; + + memset(q, 0, sizeof(srslte_npss_synch_t)); + + q->fft_size = q->max_fft_size = fft_size; + q->frame_size = q->max_frame_size = frame_size; + q->ema_alpha = 0.2; + + uint32_t buffer_size = SRSLTE_NPSS_CORR_FILTER_LEN + frame_size + 1; + + q->tmp_input = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + if (!q->tmp_input) { + PRINT_ERR("Error allocating memory\n"); + goto clean_and_exit; + } + memset(q->tmp_input, 0, buffer_size * sizeof(cf_t)); + + q->conv_output = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + if (!q->conv_output) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + memset(q->conv_output, 0, sizeof(cf_t) * buffer_size); + q->conv_output_avg = srslte_vec_malloc(buffer_size * sizeof(float)); + if (!q->conv_output_avg) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + memset(q->conv_output_avg, 0, sizeof(float) * buffer_size); +#ifdef SRSLTE_NPSS_ACCUMULATE_ABS + q->conv_output_abs = srslte_vec_malloc(buffer_size * sizeof(float)); + if (!q->conv_output_abs) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + memset(q->conv_output_abs, 0, sizeof(float) * buffer_size); +#endif + + q->npss_signal_time = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + if (!q->npss_signal_time) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + memset(q->npss_signal_time, 0, sizeof(cf_t) * buffer_size); + + // The NPSS is translated into the time domain + if (srslte_npss_corr_init(q->npss_signal_time, fft_size, q->frame_size)) { + fprintf(stderr, "Error initiating NPSS detector for fft_size=%d\n", fft_size); + goto clean_and_exit; + } + +#ifdef CONVOLUTION_FFT + if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, SRSLTE_NPSS_CORR_FILTER_LEN)) { + fprintf(stderr, "Error initiating convolution FFT\n"); + goto clean_and_exit; + } + // run convolution once to compute filter + srslte_corr_fft_cc_run(&q->conv_fft, q->tmp_input, q->npss_signal_time, q->conv_output); +#endif + + srslte_npss_synch_reset(q); + + ret = SRSLTE_SUCCESS; + } + +clean_and_exit: + if (ret == SRSLTE_ERROR) { + srslte_npss_synch_free(q); + } + return ret; +} + +int srslte_npss_synch_resize(srslte_npss_synch_t* q, uint32_t frame_size, uint32_t fft_size) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + if (q != NULL) { + ret = SRSLTE_ERROR; + + if (fft_size > q->max_fft_size || frame_size > q->max_frame_size) { + PRINT_ERR("fft_size and frame_size must be lower than initialized\n"); + return SRSLTE_ERROR; + } + + q->ema_alpha = 0.2; + q->fft_size = fft_size; + q->frame_size = frame_size; + + uint32_t buffer_size = SRSLTE_NPSS_CORR_FILTER_LEN + frame_size + 1; + memset(q->tmp_input, 0, buffer_size * sizeof(cf_t)); + memset(q->conv_output, 0, sizeof(cf_t) * buffer_size); + memset(q->conv_output_avg, 0, sizeof(float) * buffer_size); + +#ifdef SRSLTE_NPSS_ACCUMULATE_ABS + memset(q->conv_output_abs, 0, sizeof(float) * buffer_size); +#endif + + // Re-generate NPSS sequences for this FFT size + if (srslte_npss_corr_init(q->npss_signal_time, fft_size, q->frame_size)) { + fprintf(stderr, "Error initiating NPSS detector for fft_size=%d\n", fft_size); + return SRSLTE_ERROR; + } + +#ifdef CONVOLUTION_FFT + if (srslte_conv_fft_cc_replan(&q->conv_fft, frame_size, SRSLTE_NPSS_CORR_FILTER_LEN)) { + fprintf(stderr, "Error initiating convolution FFT\n"); + return SRSLTE_ERROR; + } +#endif + + srslte_npss_synch_reset(q); + + ret = SRSLTE_SUCCESS; + } + return ret; +} + +int srslte_npss_corr_init(cf_t* npss_signal_time, const uint32_t fft_size, const uint32_t frame_size) +{ + srslte_dft_plan_t plan; + _Complex float npss_signal_pad[fft_size]; + _Complex float npss_signal[SRSLTE_NPSS_TOT_LEN] = {}; + + // generate correlation sequence + srslte_npss_generate(npss_signal); +#if DUMP_SIGNALS + // srslte_vec_save_file("npss_corr_seq_freq.bin", npss_signal, SRSLTE_NPSS_TOT_LEN*sizeof(cf_t)); +#endif + + // zero buffers + memset(npss_signal_time, 0, (fft_size + frame_size) * sizeof(cf_t)); + memset(npss_signal_pad, 0, fft_size * sizeof(cf_t)); + + // construct dft plan and convert signal into the time domain + if (srslte_dft_plan(&plan, fft_size, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { + return SRSLTE_ERROR; + } + srslte_dft_plan_set_mirror(&plan, true); + srslte_dft_plan_set_dc(&plan, false); + srslte_dft_plan_set_norm(&plan, true); + + // one symbol at a time + cf_t* output = npss_signal_time; + int output_len = 0; + for (int i = 0; i < SRSLTE_NPSS_NUM_OFDM_SYMS; i++) { + // zero buffer, copy NPSS symbol to appr. pos and transform to time-domain + memset(npss_signal_pad, 0, fft_size * sizeof(cf_t)); + + // 5th NPSS symbol has CP length of 10 symbols + int cp_len = (i != 4) ? SRSLTE_CP_LEN_NORM(1, SRSLTE_NBIOT_FFT_SIZE) : SRSLTE_CP_LEN_NORM(0, SRSLTE_NBIOT_FFT_SIZE); + int k = (fft_size - SRSLTE_NRE) / 2; // place NPSS in the centre + + memcpy(&npss_signal_pad[k], &npss_signal[i * SRSLTE_NPSS_LEN], SRSLTE_NPSS_LEN * sizeof(cf_t)); + srslte_dft_run_c(&plan, npss_signal_pad, &output[cp_len]); + + // add CP + memcpy(output, &output[fft_size], cp_len * sizeof(cf_t)); + + // prepare next iteration + output += fft_size + cp_len; + output_len += fft_size + cp_len; + } + + assert(output_len == SRSLTE_NPSS_CORR_FILTER_LEN); + +#if DO_FREQ_SHIFT + // shift entire signal in frequency domain by half a subcarrier + cf_t shift_buffer[SRSLTE_SF_LEN(fft_size)]; + cf_t* ptr = shift_buffer; + for (uint32_t n = 0; n < 2; n++) { + for (uint32_t i = 0; i < 7; i++) { + uint32_t cplen = SRSLTE_CP_LEN_NORM(i, fft_size); + for (uint32_t t = 0; t < fft_size + cplen; t++) { + ptr[t] = cexpf(I * 2 * M_PI * ((float)t - (float)cplen) * -SRSLTE_NBIOT_FREQ_SHIFT_FACTOR / fft_size); + } + ptr += fft_size + cplen; + } + } + srslte_vec_prod_ccc( + npss_signal_time, &shift_buffer[SRSLTE_NPSS_CORR_OFFSET], npss_signal_time, SRSLTE_NPSS_CORR_FILTER_LEN); + srslte_vec_sc_prod_cfc(npss_signal_time, 1.0 / 3, npss_signal_time, output_len); +#endif + + srslte_dft_plan_free(&plan); + + return SRSLTE_SUCCESS; +} + +/** Performs time-domain NPSS correlation. + * Returns the index of the NPSS correlation peak in a subframe. + * The frame starts at corr_peak_pos-SRSLTE_NPSS_CORR_OFFSET+frame_size/2. + * The value of the correlation is stored in corr_peak_value. + * + * Input buffer must be subframe_size long. + */ +int srslte_npss_sync_find(srslte_npss_synch_t* q, cf_t* input, float* corr_peak_value) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && input != NULL) { + uint32_t corr_peak_pos; + uint32_t conv_output_len; + + // Correlate input with NPSS sequence + if (q->frame_size >= q->fft_size) { +#ifdef CONVOLUTION_FFT + memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t)); + conv_output_len = srslte_corr_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->npss_signal_time, q->conv_output); +#else + conv_output_len = + srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size); +#endif + } else { + for (int i = 0; i < q->frame_size; i++) { + q->conv_output[i] = srslte_vec_dot_prod_ccc(q->npss_signal_time, &input[i], q->fft_size); + } + conv_output_len = q->frame_size; + } + +#ifdef SRSLTE_NPSS_ABS_SQUARE + srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len - 1); +#else + srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len - 1); +#endif + + if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) { + srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len - 1); + srslte_vec_sc_prod_fff(q->conv_output_avg, 1 - q->ema_alpha, q->conv_output_avg, conv_output_len - 1); + + srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len - 1); + } else { + memcpy(q->conv_output_avg, q->conv_output_abs, sizeof(float) * (conv_output_len - 1)); + } + + // Find maximum of the absolute value of the correlation + corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len - 1); + +#if DUMP_SIGNALS + printf("Dumping debug signals.\n"); + srslte_vec_save_file("npss_find_input.bin", input, q->frame_size * sizeof(cf_t)); + srslte_vec_save_file("npss_corr_seq_time.bin", q->npss_signal_time, SRSLTE_NPSS_CORR_FILTER_LEN * sizeof(cf_t)); + srslte_vec_save_file("npss_find_conv_output_abs.bin", q->conv_output_abs, conv_output_len * sizeof(float)); + srslte_vec_save_file("npss_find_conv_output_avg.bin", q->conv_output_avg, conv_output_len * sizeof(float)); +#endif + + // save absolute value + q->peak_value = q->conv_output_avg[corr_peak_pos]; + +#ifdef SRSLTE_NPSS_RETURN_PSR + // Find second side lobe + + // Find end of peak lobe to the right + int pl_ub = corr_peak_pos + 1; + while (q->conv_output_avg[pl_ub + 1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) { + pl_ub++; + } + // Find end of peak lobe to the left + int pl_lb; + if (corr_peak_pos > 2) { + pl_lb = corr_peak_pos - 1; + while (q->conv_output_avg[pl_lb - 1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { + pl_lb--; + } + } else { + pl_lb = 0; + } + + int sl_distance_right = conv_output_len - 1 - pl_ub; + if (sl_distance_right < 0) { + sl_distance_right = 0; + } + int sl_distance_left = pl_lb; + + int sl_right = pl_ub + srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right); + int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); + float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); + if (corr_peak_value) { + *corr_peak_value = q->conv_output_avg[corr_peak_pos] / side_lobe_value; + + if (*corr_peak_value < 10) { + DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", + corr_peak_pos, + pl_ub, + pl_lb, + sl_right, + sl_left, + q->conv_output_avg[corr_peak_pos], + side_lobe_value, + *corr_peak_value); + } + } +#else + if (corr_peak_value) { + *corr_peak_value = q->conv_output_avg[corr_peak_pos]; + } +#endif + + ret = (int)corr_peak_pos; + } + return ret; +} + +void srslte_npss_synch_set_ema_alpha(srslte_npss_synch_t* q, float alpha) +{ + q->ema_alpha = alpha; +} + +void srslte_npss_synch_free(srslte_npss_synch_t* q) +{ + if (q) { + if (q->npss_signal_time) { + free(q->npss_signal_time); + } +#ifdef CONVOLUTION_FFT + srslte_conv_fft_cc_free(&q->conv_fft); +#endif + if (q->tmp_input) { + free(q->tmp_input); + } + if (q->conv_output) { + free(q->conv_output); + } + if (q->conv_output_abs) { + free(q->conv_output_abs); + } + if (q->conv_output_avg) { + free(q->conv_output_avg); + } + } +} + +void srslte_npss_synch_reset(srslte_npss_synch_t* q) +{ + if (q->conv_output_avg) { + uint32_t buffer_size = SRSLTE_NPSS_CORR_FILTER_LEN + q->max_frame_size + 1; + memset(q->conv_output_avg, 0, sizeof(float) * buffer_size); + } +} + +/** + * This function calculates the Zadoff-Chu sequence. + * 36.211 13.2.0 section 10.2.7.1.1 + * + * It produces SRSLTE_NPSS_LEN * SRSLTE_NPSS_NUM_SC = 11 * 11 = 121 samples. + * @param signal Output array. + */ +int srslte_npss_generate(cf_t* signal) +{ + float arg; + const float root_value = 5.0; + + int sign = -1; + int l = 0; + int n = 0; + + // iterate over symbol indices + for (l = 0; l < SRSLTE_CP_NORM_SF_NSYMB - 3; l++) { + // iterate over subcarriers, leave out last one + for (n = 0; n < SRSLTE_NRE - 1; n++) { + arg = (float)sign * M_PI * root_value * ((float)n * ((float)n + 1.0)) / 11.0; + __real__ signal[l * SRSLTE_NPSS_LEN + n] = cosf(arg); + __imag__ signal[l * SRSLTE_NPSS_LEN + n] = sinf(arg); + + signal[l * SRSLTE_NPSS_LEN + n] *= factor_lut[l]; + } + } + + return 0; +} + +/** 36.211 10.3 section 6.11.1.2 + */ +void srslte_npss_put_subframe( + srslte_npss_synch_t* q, cf_t* npss_signal, cf_t* sf, const uint32_t nof_prb, const uint32_t nbiot_prb_offset) +{ + // skip first 3 OFDM symbols over all PRBs completely + uint32_t k = 3 * nof_prb * SRSLTE_NRE + nbiot_prb_offset * SRSLTE_NRE; + + // put NPSS in each of the 11 symbols of the subframe + for (int l = 0; l < SRSLTE_CP_NORM_SF_NSYMB - 3; l++) { + memcpy(&sf[k + SRSLTE_NPSS_LEN * l], &npss_signal[SRSLTE_NPSS_LEN * l], SRSLTE_NPSS_LEN * sizeof(cf_t)); + k += (nof_prb - 1) * SRSLTE_NRE + 1; // last SC of the PRB is also null + } +} diff --git a/lib/src/phy/sync/nsss.c b/lib/src/phy/sync/nsss.c new file mode 100644 index 000000000..22589b7c2 --- /dev/null +++ b/lib/src/phy/sync/nsss.c @@ -0,0 +1,398 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include + +#include "srslte/phy/common/phy_common.h" +#include "srslte/phy/sync/nsss.h" +#include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" + +#define PRINT_ERR(err) fprintf(stderr, "%s: %s", __PRETTY_FUNCTION__, err) + +#define DUMP_SIGNALS 0 +#define DO_FREQ_SHIFT 1 +#define SRSLTE_NSSS_RETURN_PSR 0 + +int srslte_nsss_synch_init(srslte_nsss_synch_t* q, uint32_t input_size, uint32_t fft_size) +{ + if (q != NULL && fft_size <= 2048) { + int ret = SRSLTE_ERROR; + bzero(q, sizeof(srslte_nsss_synch_t)); + + q->fft_size = q->max_fft_size = fft_size; + + q->input_size = input_size; + q->corr_peak_threshold = 2.0; + + uint32_t buffer_size = SRSLTE_NSSS_CORR_FILTER_LEN + q->input_size + 1; + DEBUG("NSSS buffer size is %d samples.\n", buffer_size); + q->tmp_input = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + if (!q->tmp_input) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + bzero(q->tmp_input, buffer_size * sizeof(cf_t)); + + q->conv_output = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + if (!q->conv_output) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + bzero(q->conv_output, sizeof(cf_t) * buffer_size); + + q->conv_output_abs = srslte_vec_malloc(buffer_size * sizeof(float)); + if (!q->conv_output_abs) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + bzero(q->conv_output_abs, sizeof(float) * buffer_size); + + for (int i = 0; i < SRSLTE_NUM_PCI; i++) { + q->nsss_signal_time[i] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + if (!q->nsss_signal_time[i]) { + fprintf(stderr, "Error allocating memory\n"); + goto clean_and_exit; + } + bzero(q->nsss_signal_time[i], sizeof(cf_t) * buffer_size); + } + + // generate NSSS sequences + if (srslte_nsss_corr_init(q)) { + fprintf(stderr, "Error initiating NSSS detector for fft_size=%d\n", fft_size); + goto clean_and_exit; + } + + if (srslte_conv_fft_cc_init(&q->conv_fft, q->input_size, SRSLTE_NSSS_CORR_FILTER_LEN)) { + fprintf(stderr, "Error initiating convolution FFT\n"); + goto clean_and_exit; + } + + ret = SRSLTE_SUCCESS; + + clean_and_exit: + if (ret == SRSLTE_ERROR) { + srslte_nsss_synch_free(q); + } + return ret; + } + return SRSLTE_ERROR_INVALID_INPUTS; +} + +void srslte_nsss_synch_free(srslte_nsss_synch_t* q) +{ + if (q) { + for (int i = 0; i < SRSLTE_NUM_PCI; i++) { + if (q->nsss_signal_time[i]) { + free(q->nsss_signal_time[i]); + } + } + srslte_conv_fft_cc_free(&q->conv_fft); + if (q->tmp_input) { + free(q->tmp_input); + } + if (q->conv_output) { + free(q->conv_output); + } + if (q->conv_output_abs) { + free(q->conv_output_abs); + } + } +} + +int srslte_nsss_synch_resize(srslte_nsss_synch_t* q, uint32_t fft_size) +{ + if (q != NULL && fft_size <= 2048) { + if (fft_size > q->max_fft_size) { + PRINT_ERR("fft_size must be lower than initialized\n"); + return SRSLTE_ERROR; + } + + q->fft_size = fft_size; + + if (srslte_nsss_corr_init(q) != SRSLTE_SUCCESS) { + PRINT_ERR("Couldn't initialize NSSS sequence\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; + } + return SRSLTE_ERROR_INVALID_INPUTS; +} + +int srslte_nsss_corr_init(srslte_nsss_synch_t* q) +{ + srslte_dft_plan_t plan; + float complex nsss_signal_pad[q->fft_size]; + + // construct dft plan + if (srslte_dft_plan(&plan, q->fft_size, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { + return SRSLTE_ERROR; + } + srslte_dft_plan_set_mirror(&plan, true); + srslte_dft_plan_set_dc(&plan, false); + srslte_dft_plan_set_norm(&plan, true); + +#if DO_FREQ_SHIFT + // shift entire signal in frequency domain by half a subcarrier + cf_t shift_buffer[SRSLTE_SF_LEN(q->fft_size)]; + cf_t* ptr = shift_buffer; + for (uint32_t n = 0; n < 2; n++) { + for (uint32_t i = 0; i < 7; i++) { + uint32_t cplen = SRSLTE_CP_LEN_NORM(i, q->fft_size); + for (uint32_t t = 0; t < q->fft_size + cplen; t++) { + ptr[t] = cexpf(I * 2 * M_PI * ((float)t - (float)cplen) * -SRSLTE_NBIOT_FREQ_SHIFT_FACTOR / q->fft_size); + } + ptr += q->fft_size + cplen; + } + } +#endif + + // generate correlation sequences + DEBUG("Generating NSSS sequences\n"); + for (int i = 0; i < SRSLTE_NUM_PCI; i++) { + float complex nsss_signal[SRSLTE_NSSS_TOT_LEN]; + bzero(nsss_signal, SRSLTE_NSSS_TOT_LEN * sizeof(cf_t)); + srslte_nsss_generate(nsss_signal, i); + + // one symbol at a time + cf_t* output = q->nsss_signal_time[i]; + int output_len = 0; + for (int i = 0; i < SRSLTE_NSSS_NSYMB; i++) { + // zero buffer, copy NSSS symbol to appr. pos and transform to time-domain + bzero(nsss_signal_pad, q->fft_size * sizeof(cf_t)); + + // 5th NSSS symbol has CP length of 10 symbols + int cp_len = + (i != 4) ? SRSLTE_CP_LEN_NORM(1, SRSLTE_NBIOT_FFT_SIZE) : SRSLTE_CP_LEN_NORM(0, SRSLTE_NBIOT_FFT_SIZE); + int k = (q->fft_size - SRSLTE_NRE) / 2; // place seq in the centre + k = 57; + + // use generated sequence for theta_f = 0 + int theta_f = 0; + memcpy(&nsss_signal_pad[k], + &nsss_signal[(theta_f * SRSLTE_NSSS_LEN) + i * SRSLTE_NSSS_NSC], + SRSLTE_NSSS_NSC * sizeof(cf_t)); + srslte_dft_run_c(&plan, nsss_signal_pad, &output[cp_len]); + + // add CP + memcpy(output, &output[q->fft_size], cp_len * sizeof(cf_t)); + + // prepare next iteration + output += q->fft_size + cp_len; + output_len += q->fft_size + cp_len; + } + assert(output_len == SRSLTE_NSSS_CORR_FILTER_LEN); + +#if DO_FREQ_SHIFT + srslte_vec_prod_ccc(q->nsss_signal_time[i], + &shift_buffer[SRSLTE_NSSS_CORR_OFFSET], + q->nsss_signal_time[i], + SRSLTE_NSSS_CORR_FILTER_LEN); + // srslte_vec_sc_prod_cfc(npss_signal_time, 1.0/3, npss_signal_time, output_len); +#endif + +#if DUMP_SIGNALS +#define MAX_FNAME_LEN 40 + char fname[MAX_FNAME_LEN]; + snprintf(fname, MAX_FNAME_LEN, "nsss_corr_seq_time_id%d.bin", i); + srslte_vec_save_file(fname, q->nsss_signal_time[i], SRSLTE_NSSS_CORR_FILTER_LEN * sizeof(cf_t)); + + snprintf(fname, MAX_FNAME_LEN, "nsss_corr_seq_freq_id%d.bin", i); + srslte_vec_save_file(fname, nsss_signal, SRSLTE_NSSS_TOT_LEN * sizeof(cf_t)); +#endif + } + + srslte_dft_plan_free(&plan); + return SRSLTE_SUCCESS; +} + +int srslte_nsss_sync_find( + srslte_nsss_synch_t* q, cf_t* input, float* corr_peak_value, uint32_t* cell_id, uint32_t* sfn_partial) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && input != NULL && corr_peak_value != NULL && cell_id != NULL && sfn_partial != NULL) { + float peak_value; + ret = SRSLTE_ERROR; + + // save input + memcpy(q->tmp_input, input, q->input_size * sizeof(cf_t)); + + if (*cell_id == SRSLTE_CELL_ID_UNKNOWN) { + DEBUG("N_id_ncell is not set. Perform exhaustive search on input.\n"); + + // brute-force: correlate with all possible sequences until cell is found + for (int i = 0; i < SRSLTE_NUM_PCI; i++) { + srslte_nsss_sync_find_pci(q, q->tmp_input, i); + } + + // find maximum of all correlation maxima + uint32_t max_id = srslte_vec_max_fi(q->peak_values, SRSLTE_NUM_PCI); + if (q->peak_values[max_id] > q->corr_peak_threshold) { + // cell found, set return values + *cell_id = max_id; + ret = SRSLTE_SUCCESS; + } + peak_value = q->peak_values[max_id]; + + } else { + DEBUG("Current N_id_ncell is %d.\n", *cell_id); + + // run correlation only for given id + srslte_nsss_sync_find_pci(q, q->tmp_input, *cell_id); + + if (q->peak_values[*cell_id] > q->corr_peak_threshold) { + ret = SRSLTE_SUCCESS; + } + peak_value = q->peak_values[*cell_id]; + } + + // set remaining return values + if (sfn_partial) { + *sfn_partial = 0; // we only search for the first of the four possible shifts + } + if (corr_peak_value) { + *corr_peak_value = peak_value; + } + } + return ret; +} + +// Correlates input signal with the NSSS sequence for a given n_id_ncell +void srslte_nsss_sync_find_pci(srslte_nsss_synch_t* q, cf_t* input, uint32_t cell_id) +{ + // correlate input with NSSS sequences + uint32_t conv_output_len = srslte_corr_fft_cc_run(&q->conv_fft, input, q->nsss_signal_time[cell_id], q->conv_output); + srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len - 1); + + // Find maximum of the absolute value of the correlation + uint32_t corr_peak_pos = srslte_vec_max_fi(q->conv_output_abs, conv_output_len - 1); + +#if DUMP_SIGNALS + printf("Dumping debug signals for cell-id %d.\n", i); + srslte_vec_save_file("nsss_find_input.bin", input, q->input_size * sizeof(cf_t)); + srslte_vec_save_file("nsss_corr_seq_time.bin", q->nsss_signal_time[i], SRSLTE_NSSS_CORR_FILTER_LEN * sizeof(cf_t)); + srslte_vec_save_file("nsss_find_conv_output_abs.bin", q->conv_output_abs, conv_output_len * sizeof(float)); +#endif + +#if SRSLTE_NSSS_RETURN_PSR + // Find second side lobe + + // Find end of peak lobe to the right + int pl_ub = corr_peak_pos + 1; + while (q->conv_output_abs[pl_ub + 1] <= q->conv_output_abs[pl_ub] && pl_ub < conv_output_len) { + pl_ub++; + } + // Find end of peak lobe to the left + int pl_lb; + if (corr_peak_pos > 2) { + pl_lb = corr_peak_pos - 1; + while (q->conv_output_abs[pl_lb - 1] <= q->conv_output_abs[pl_lb] && pl_lb > 1) { + pl_lb--; + } + } else { + pl_lb = 0; + } + + int sl_distance_right = conv_output_len - 1 - pl_ub; + if (sl_distance_right < 0) { + sl_distance_right = 0; + } + int sl_distance_left = pl_lb; + + int sl_right = pl_ub + srslte_vec_max_fi(&q->conv_output_abs[pl_ub], sl_distance_right); + int sl_left = srslte_vec_max_fi(q->conv_output_abs, sl_distance_left); + float side_lobe_value = SRSLTE_MAX(q->conv_output_abs[sl_right], q->conv_output_abs[sl_left]); + q->peak_values[cell_id] = q->conv_output_abs[corr_peak_pos] / side_lobe_value; + DEBUG("NSSS n_id_ncell=%d at peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", + cell_id, + corr_peak_pos, + pl_ub, + pl_lb, + sl_right, + sl_left, + q->conv_output_abs[corr_peak_pos], + side_lobe_value, + q->peak_values[cell_id]); +#else + // save max. absolute value + q->peak_values[cell_id] = q->conv_output_abs[corr_peak_pos]; + DEBUG("NSSS n_id_ncell=%d with peak=%f found at: %d\n", cell_id, q->peak_values[cell_id], corr_peak_pos); +#endif +} + +// generate the NSSS signal for each of 4 different cyclic shifts +// return 4 * 132 = 528 complex samples +void srslte_nsss_generate(cf_t* signal, uint32_t cell_id) +{ + if (srslte_cellid_isvalid(cell_id)) { + int u = cell_id % 126 + 3; + int q = floor(cell_id / 126.0); + int sign = -1; + + // iterate over all possible cyclic shifts + for (int theta_f = 0; theta_f < SRSLTE_NSSS_NUM_SEQ; theta_f++) { + for (int n = 0; n < SRSLTE_NSSS_LEN; n++) { + int n_prime = n % 131; + int m = n % 128; + + float arg = (float)sign * 2.0 * M_PI * ((float)theta_f) * ((float)n); + float complex tmp1; + __real__ tmp1 = cosf(arg); + __imag__ tmp1 = sinf(arg); + + arg = ((float)sign * M_PI * ((float)u) * (float)n_prime * ((float)n_prime + 1.0)) / 131.0; + float complex tmp2; + __real__ tmp2 = cosf(arg); + __imag__ tmp2 = sinf(arg); + + signal[theta_f * SRSLTE_NSSS_LEN + n] = b_q_m[q][m] * tmp1 * tmp2; + } + } + } else { + DEBUG("Invalid n_id_ncell %d\n", cell_id); + } +} + +void srslte_nsss_put_subframe(srslte_nsss_synch_t* q, + cf_t* nsss, + cf_t* subframe, + const int nf, + const uint32_t nof_prb, + const uint32_t nbiot_prb_offset) +{ + int theta_f = (int)floor(33 / 132.0 * (nf / 2.0)) % SRSLTE_NSSS_NUM_SEQ; + + // skip first 3 OFDM symbols over all PRBs completely + int k = 3 * nof_prb * SRSLTE_NRE + nbiot_prb_offset * SRSLTE_NRE; + + DEBUG("%d.9: Putting NSSS with theta_f=%d\n", nf, theta_f); + for (int l = 0; l < SRSLTE_CP_NORM_SF_NSYMB - 3; l++) { + memcpy(&subframe[k + SRSLTE_NSSS_NSC * l], + &nsss[(theta_f * SRSLTE_NSSS_LEN) + (l * SRSLTE_NSSS_NSC)], + SRSLTE_NSSS_NSC * sizeof(cf_t)); + k += (nof_prb - 1) * SRSLTE_NRE; + } +} diff --git a/lib/src/phy/sync/refsignal_dl_sync.c b/lib/src/phy/sync/refsignal_dl_sync.c new file mode 100644 index 000000000..f88565a1d --- /dev/null +++ b/lib/src/phy/sync/refsignal_dl_sync.c @@ -0,0 +1,355 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include + +int srslte_refsignal_dl_sync_init(srslte_refsignal_dl_sync_t* q) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q) { + // Initialise internals + bzero(q, sizeof(srslte_refsignal_dl_sync_t)); + + // Initialise Reference signals + ret = srslte_refsignal_cs_init(&q->refsignal, SRSLTE_MAX_PRB); + + // Allocate time buffers + for (int i = 0; i < SRSLTE_NOF_SF_X_FRAME; i++) { + q->sequences[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX); + if (!q->sequences[i]) { + perror("Allocating sequence\n"); + } + } + + // Allocate Temporal OFDM buffer + q->ifft_buffer_in = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX); + if (!q->ifft_buffer_in) { + perror("Allocating ifft_buffer_in\n"); + } + + q->ifft_buffer_out = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX); + if (!q->ifft_buffer_out) { + perror("Allocating ifft_buffer_out\n"); + } + + // Allocate correlation + q->correlation = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX * 2); + if (!q->correlation) { + perror("Allocating correlation\n"); + } + + // Initiate OFDM modulator + if (!ret) { + ret = srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, q->ifft_buffer_in, q->ifft_buffer_out, SRSLTE_MAX_PRB); + } + + // Set PRB + if (!ret) { + ret = srslte_ofdm_tx_set_prb(&q->ifft, SRSLTE_CP_NORM, SRSLTE_MAX_PRB); + } + + // Initiate FFT Convolution + if (!ret) { + ret = srslte_conv_fft_cc_init(&q->conv_fft_cc, q->ifft.sf_sz, q->ifft.sf_sz); + } + } + + return ret; +} + +int srslte_refsignal_dl_sync_set_cell(srslte_refsignal_dl_sync_t* q, srslte_cell_t cell) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q) { + cf_t pss_signal[SRSLTE_PSS_LEN]; + float sss_signal0[SRSLTE_SSS_LEN]; + float sss_signal5[SRSLTE_SSS_LEN]; + + // Generate Synchronization signals + srslte_pss_generate(pss_signal, cell.id % 3); + srslte_sss_generate(sss_signal0, sss_signal5, cell.id); + + // Set cell for Ref signals + ret = srslte_refsignal_cs_set_cell(&q->refsignal, cell); + + // Resize OFDM + if (!ret && q->ifft.nof_re != cell.nof_prb * SRSLTE_NRE) { + ret = srslte_ofdm_tx_set_prb(&q->ifft, cell.cp, cell.nof_prb); + } + + // Replan convolution + if (q->conv_fft_cc.filter_len != q->ifft.sf_sz) { + srslte_conv_fft_cc_replan(&q->conv_fft_cc, q->ifft.sf_sz, q->ifft.sf_sz); + } + + // Generate frame with references + if (!ret) { + for (int i = 0; i < SRSLTE_NOF_SF_X_FRAME && ret == SRSLTE_SUCCESS; i++) { + uint32_t nof_re = 0; + + // Default Subframe configuration + srslte_dl_sf_cfg_t dl_sf_cfg = {}; + dl_sf_cfg.tti = i; + + // Reset OFDM buffer + bzero(q->ifft_buffer_in, sizeof(cf_t) * q->ifft.sf_sz); + + // Put Synchronization signals + if (i == 0 || i == 5) { + srslte_pss_put_slot(pss_signal, q->ifft_buffer_in, cell.nof_prb, cell.cp); + srslte_sss_put_slot(i ? sss_signal5 : sss_signal0, q->ifft_buffer_in, cell.nof_prb, cell.cp); + } + + // Increase correlation for 2 port eNb + cell.nof_ports = 2; + + // Put Reference signals + for (int p = 0; p < cell.nof_ports; p++) { + ret = srslte_refsignal_cs_put_sf(&q->refsignal, &dl_sf_cfg, p, q->ifft_buffer_in); + + // Increment number of resource elements + if (p == 0) { + nof_re += srslte_refsignal_cs_nof_re(&q->refsignal, &dl_sf_cfg, p); + } + } + + // Run OFDM modulator + srslte_ofdm_tx_sf(&q->ifft); + + // Undo scaling and normalize overall power to 1 + float scale = 1.0f / nof_re; + + // Copy time domain signal, normalized by number of RE + srslte_vec_sc_prod_cfc(q->ifft_buffer_out, scale, q->sequences[i], q->ifft.sf_sz); + } + } + } + + return ret; +} + +void srslte_refsignal_dl_sync_free(srslte_refsignal_dl_sync_t* q) +{ + if (q) { + srslte_refsignal_free(&q->refsignal); + + srslte_ofdm_tx_free(&q->ifft); + + if (q->ifft_buffer_in) { + free(q->ifft_buffer_in); + } + + if (q->ifft_buffer_out) { + free(q->ifft_buffer_out); + } + + if (q->correlation) { + free(q->correlation); + } + + for (int i = 0; i < SRSLTE_NOF_SF_X_FRAME; i++) { + if (q->sequences[i]) { + free(q->sequences[i]); + } + } + + srslte_conv_fft_cc_free(&q->conv_fft_cc); + } +} + +int srslte_refsignal_dl_sync_find_peak(srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t nsamples) +{ + int ret = SRSLTE_ERROR; + float thr = 5.5f; + float peak_value = 0.0f; + int peak_idx = 0; + float rms_avg = 0; + uint32_t sf_len = q->ifft.sf_sz; + + // Load correlation sequence and convert to frequency domain + cf_t* ptr_filt = q->conv_fft_cc.filter_fft; + memcpy(ptr_filt, q->sequences[0], sizeof(cf_t) * sf_len); + bzero(&ptr_filt[sf_len], sizeof(cf_t) * sf_len); + srslte_dft_run_c(&q->conv_fft_cc.filter_plan, ptr_filt, ptr_filt); + + // Limit correlate for a frame or less + nsamples = SRSLTE_MIN(nsamples - sf_len, SRSLTE_NOF_SF_X_FRAME * sf_len); + + // Correlation + for (int n = 0; n < nsamples; n += sf_len) { + // Set input data, two subframes + cf_t* ptr_in = &buffer[n]; + + // Correlate + srslte_corr_fft_cc_run_opt(&q->conv_fft_cc, ptr_in, ptr_filt, q->correlation); + + // Find maximum, calculate RMS and peak + uint32_t imax = srslte_vec_max_abs_ci(q->correlation, sf_len); + float peak = cabsf(q->correlation[imax]); + float rms = sqrtf(srslte_vec_avg_power_cf(q->correlation, sf_len)); + rms_avg += rms; + + // Found bigger peak + if (peak > peak_value) { + peak_value = peak; + peak_idx = imax + n; + } + } + + // Condition of peak detection + rms_avg /= floorf((float)nsamples / sf_len); + if (peak_value > rms_avg * thr) { + ret = peak_idx; + } + + INFO("pci=%03d; sf_len=%d; imax=%d; peak=%.3f; rms=%.3f; peak/rms=%.3f\n", + q->refsignal.cell.id, + sf_len, + peak_idx, + peak_value, + rms_avg, + peak_value / rms_avg); + + // Return the peak position if found, -1 otherwise + return ret; +} + +void srslte_refsignal_dl_sync_run(srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t nsamples) +{ + if (q) { + uint32_t sf_len = q->ifft.sf_sz; + uint32_t sf_count = 0; + float rsrp_lin = 0.0f; + float rssi_lin = 0.0f; + float cfo_acc = 0.0f; + + // Stage 1: find peak + int peak_idx = srslte_refsignal_dl_sync_find_peak(q, buffer, nsamples); + + // Stage 2: Proccess subframes + if (peak_idx >= 0) { + // Calculate initial subframe index and sample + uint32_t sf_idx_init = (2 * SRSLTE_NOF_SF_X_FRAME - peak_idx / sf_len) % SRSLTE_NOF_SF_X_FRAME; + uint32_t n_init = peak_idx % sf_len; + + for (int sf_idx = sf_idx_init, n = n_init; n < (nsamples - sf_len + 1); + sf_idx = (sf_idx + 1) % SRSLTE_NOF_SF_X_FRAME, n += sf_len) { + cf_t* buf = &buffer[n]; + + // Measure subframe rsrp, rssi and accumulate + float rsrp = 0.0f, rssi = 0.0f, cfo = 0.0f; + srslte_refsignal_dl_sync_measure_sf(q, buf, sf_idx, &rsrp, &rssi, &cfo); + rsrp_lin += rsrp; + rssi_lin += rssi; + cfo_acc += cfo; + sf_count++; + } + + // Average measurements + if (sf_count) { + rsrp_lin /= sf_count; + rssi_lin /= sf_count; + cfo_acc /= sf_count; + } + + // Calculate in dBm + q->rsrp_dBfs = 10.0f * log10f(rsrp_lin) + 30.0f; + + // Calculate RSSI in dBm + q->rssi_dBfs = 10.0f * log10f(rssi_lin) + 30.0f; + + // Calculate RSRQ + q->rsrq_dB = 10.0f * log10f(q->refsignal.cell.nof_prb) + q->rsrp_dBfs - q->rssi_dBfs; + + q->found = true; + q->cfo_Hz = cfo_acc; + q->peak_index = peak_idx; + } else { + q->found = false; + q->rsrp_dBfs = NAN; + q->rssi_dBfs = NAN; + q->rsrq_dB = NAN; + q->cfo_Hz = NAN; + q->peak_index = UINT32_MAX; + } + } +} + +void srslte_refsignal_dl_sync_measure_sf( + srslte_refsignal_dl_sync_t* q, cf_t* buffer, uint32_t sf_idx, float* rsrp, float* rssi, float* cfo) +{ + float rsrp_lin = 0.0f; + float rssi_lin = 0.0f; + cf_t corr[4] = {}; + srslte_dl_sf_cfg_t dl_sf_cfg = {}; + dl_sf_cfg.tti = sf_idx; + + if (q) { + cf_t* sf_sequence = q->sequences[sf_idx % SRSLTE_NOF_SF_X_FRAME]; + + uint32_t symbol_sz = q->ifft.symbol_sz; + uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(&q->refsignal, &dl_sf_cfg, 0); + uint32_t cp_len0 = SRSLTE_CP_LEN_NORM(0, symbol_sz); + uint32_t cp_len1 = SRSLTE_CP_LEN_NORM(1, symbol_sz); + + for (uint32_t l = 0; l < nsymbols; l++) { + // Calculate FFT window offset for reference signals symbols + uint32_t symbidx = srslte_refsignal_cs_nsymbol(l, q->refsignal.cell.cp, 0); + uint32_t offset = cp_len0 + (symbol_sz + cp_len1) * symbidx; + + if (l >= nsymbols / 2) { + offset += cp_len0 - cp_len1; + } + + // Complex correlation + corr[l] = srslte_vec_dot_prod_conj_ccc(&buffer[offset], &sf_sequence[offset], symbol_sz); + + // Calculate RSRP + rsrp_lin += __real__(corr[l] * conjf(corr[l])); + + // Calculate RSSI + rssi_lin += srslte_vec_dot_prod_conj_ccc(&buffer[offset], &buffer[offset], symbol_sz); + } + + // Return measurements + if (rsrp) { + *rsrp = rsrp_lin * nsymbols; + } + + if (rssi) { + *rssi = (float)q->refsignal.cell.nof_prb * rssi_lin / (float)nsymbols * 7.41f; + } + + if (cfo) { + *cfo = 0; + *cfo += cargf(corr[2] * conjf(corr[0])) / (2.0f * M_PI * 7.5f) * 15000.0f; + *cfo += cargf(corr[3] * conjf(corr[1])) / (2.0f * M_PI * 7.5f) * 15000.0f; + *cfo /= 2; + } + } +} diff --git a/lib/src/phy/sync/sss.c b/lib/src/phy/sync/sss.c index 188cb04d3..209bbb84f 100644 --- a/lib/src/phy/sync/sss.c +++ b/lib/src/phy/sync/sss.c @@ -133,16 +133,22 @@ uint32_t srslte_sss_subframe(uint32_t m0, uint32_t m1) { } /** Returns the N_id_1 value based on the m0 and m1 values */ -int srslte_sss_N_id_1(srslte_sss_t *q, uint32_t m0, uint32_t m1) { - int N_id_1 = -1; - if (m1 > m0) { - if (m0 < 30 && m1 - 1 < 30) { - N_id_1 = q->N_id_1_table[m0][m1 - 1]; - } - } else { - if (m1 < 30 && m0 - 1 < 30) { - N_id_1 = q->N_id_1_table[m1][m0 - 1]; +int srslte_sss_N_id_1(srslte_sss_t* q, uint32_t m0, uint32_t m1, float corr) +{ + int N_id_1 = SRSLTE_ERROR; + + // Check threshold, consider not found (error) if the correlation is not above the threshold + if (corr > q->corr_peak_threshold) { + if (m1 > m0) { + if (m0 < 30 && m1 - 1 < 30) { + N_id_1 = q->N_id_1_table[m0][m1 - 1]; + } + } else { + if (m1 < 30 && m0 - 1 < 30) { + N_id_1 = q->N_id_1_table[m1][m0 - 1]; + } } - } + } + return N_id_1; } diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index 8bf29c586..42fd2296c 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -271,6 +271,11 @@ bool srslte_sync_sss_detected(srslte_sync_t* q) return q->sss_detected; } +float srslte_sync_sss_correlation_peak(srslte_sync_t* q) +{ + return q->sss_corr; +} + bool srslte_sync_sss_available(srslte_sync_t* q) { return q->sss_available; @@ -544,11 +549,12 @@ static bool sync_sss_symbol(srslte_sync_t* q, const cf_t* input, uint32_t* sf_id *corr = q->m0_value + q->m1_value; *sf_idx = srslte_sss_subframe(q->m0, q->m1); - ret = srslte_sss_N_id_1(&q->sss, q->m0, q->m1); + ret = srslte_sss_N_id_1(&q->sss, q->m0, q->m1, *corr); if (ret >= 0) { *N_id_1 = (uint32_t)ret; - INFO("SSS detected N_id_1=%d, sf_idx=%d, %s CP\n", + INFO("SSS detected N_id_1=%d (corr=%7.1f), sf_idx=%d, %s CP\n", *N_id_1, + *corr, *sf_idx, SRSLTE_CP_ISNORM(q->cp) ? "Normal" : "Extended"); return true; @@ -741,6 +747,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin } q->sss_available = true; + q->sss_detected = false; for (uint32_t f = 0; f < nof_frame_type_trials; f++) { if (frame_type_trials[f] == SRSLTE_FDD) { sss_idx = (int)find_offset + peak_pos - 2 * SRSLTE_SYMBOL_SZ(q->fft_size, q->cp) + @@ -766,7 +773,9 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin } sss_ptr = q->sss_filt; } - q->sss_detected = sync_sss_symbol(q, sss_ptr, &sf_idx[f], &N_id_1[f], &sss_corr[f]); + + // Consider SSS detected if at least one trial found the SSS + q->sss_detected |= sync_sss_symbol(q, sss_ptr, &sf_idx[f], &N_id_1[f], &sss_corr[f]); } else { q->sss_available = false; } @@ -777,10 +786,12 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin q->frame_type = SRSLTE_FDD; q->sf_idx = sf_idx[0]; q->N_id_1 = N_id_1[0]; + q->sss_corr = sss_corr[0]; } else { q->frame_type = SRSLTE_TDD; q->sf_idx = sf_idx[1] + 1; q->N_id_1 = N_id_1[1]; + q->sss_corr = sss_corr[1]; } DEBUG("SYNC: Detected SSS %s, corr=%.2f/%.2f\n", q->frame_type == SRSLTE_FDD ? "FDD" : "TDD", @@ -793,6 +804,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin q->sf_idx = sf_idx[0] + 1; } q->N_id_1 = N_id_1[0]; + q->sss_corr = sss_corr[0]; } } diff --git a/lib/src/phy/sync/sync_nbiot.c b/lib/src/phy/sync/sync_nbiot.c new file mode 100644 index 000000000..a4d28028a --- /dev/null +++ b/lib/src/phy/sync/sync_nbiot.c @@ -0,0 +1,355 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include + +#include "srslte/phy/common/phy_common.h" +#include "srslte/phy/sync/cfo.h" +#include "srslte/phy/sync/sync_nbiot.h" +#include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" + +#define CFO_EMA_ALPHA 0.1 +#define CP_EMA_ALPHA 0.1 +#define DEFAULT_CFO_TOL 50.0 // Hz + +/* We use the default LTE synch object internally for all the generic + * functions like CFO correction, etc. + * + */ +int srslte_sync_nbiot_init(srslte_sync_nbiot_t* q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL) { + ret = SRSLTE_ERROR; + + q->n_id_ncell = SRSLTE_CELL_ID_UNKNOWN; + q->mean_cfo = 0; + q->cfo_ema_alpha = CFO_EMA_ALPHA; + q->fft_size = fft_size; + q->frame_size = frame_size; + q->max_frame_size = frame_size; + q->max_offset = max_offset; + q->threshold = 5.0; + q->enable_cfo_estimation = true; + + if (srslte_cfo_init(&q->cfocorr, q->frame_size)) { + fprintf(stderr, "Error initiating CFO\n"); + goto clean_exit; + } + + // Set default CFO tolerance + srslte_sync_nbiot_set_cfo_tol(q, DEFAULT_CFO_TOL); + + // initialize shift buffer for CFO estimation + q->shift_buffer = srslte_vec_malloc(SRSLTE_SF_LEN(q->fft_size) * sizeof(cf_t)); + if (!q->shift_buffer) { + perror("malloc"); + goto clean_exit; + } + srslte_cexptab_gen_sf(q->shift_buffer, -SRSLTE_NBIOT_FREQ_SHIFT_FACTOR, q->fft_size); + + // allocate memory for early CFO estimation + q->cfo_output = srslte_vec_malloc(10 * SRSLTE_SF_LEN(q->fft_size) * sizeof(cf_t)); + if (!q->cfo_output) { + perror("malloc"); + goto clean_exit; + } + + // configure CP + q->cp = SRSLTE_CP_NORM; + q->cp_len = SRSLTE_CP_LEN_NORM(1, q->fft_size); + if (q->frame_size < q->fft_size) { + q->nof_symbols = 1; + } else { + q->nof_symbols = q->frame_size / (q->fft_size + q->cp_len) - 1; + } + + if (srslte_npss_synch_init(&q->npss, frame_size, fft_size)) { + fprintf(stderr, "Error initializing NPSS object\n"); + return SRSLTE_ERROR; + } + + if (srslte_nsss_synch_init(&q->nsss, SRSLTE_NSSS_NUM_SF_DETECT * SRSLTE_SF_LEN_PRB_NBIOT, fft_size)) { + fprintf(stderr, "Error initializing NSSS object\n"); + exit(-1); + } + + if (srslte_cp_synch_init(&q->cp_synch, fft_size)) { + fprintf(stderr, "Error initiating CFO\n"); + goto clean_exit; + } + + ret = SRSLTE_SUCCESS; + } + +clean_exit: + if (ret == SRSLTE_ERROR) { + srslte_sync_nbiot_free(q); + } + return ret; +} + +void srslte_sync_nbiot_free(srslte_sync_nbiot_t* q) +{ + if (q) { + srslte_npss_synch_free(&q->npss); + srslte_nsss_synch_free(&q->nsss); + srslte_cfo_free(&q->cfocorr); + srslte_cp_synch_free(&q->cp_synch); + if (q->shift_buffer) { + free(q->shift_buffer); + } + if (q->cfo_output) { + free(q->cfo_output); + } + } +} + +int srslte_sync_nbiot_resize(srslte_sync_nbiot_t* q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && frame_size <= 307200) { + ret = SRSLTE_ERROR; + + if (frame_size > q->max_frame_size) { + fprintf(stderr, "Error in srslte_sync_nbiot_resize(): frame_size must be lower than initialized\n"); + return ret; + } + q->mean_cfo = 0; + q->cfo_i = 0; + q->find_cfo_i = false; + q->find_cfo_i_initiated = false; + q->cfo_ema_alpha = CFO_EMA_ALPHA; + q->fft_size = fft_size; + q->frame_size = frame_size; + q->max_offset = max_offset; + + if (srslte_npss_synch_resize(&q->npss, max_offset, fft_size)) { + fprintf(stderr, "Error resizing PSS object\n"); + return ret; + } + if (srslte_nsss_synch_resize(&q->nsss, fft_size)) { + fprintf(stderr, "Error resizing SSS object\n"); + return ret; + } + + if (srslte_cp_synch_resize(&q->cp_synch, fft_size)) { + fprintf(stderr, "Error resizing CFO\n"); + return ret; + } + + if (srslte_cfo_resize(&q->cfocorr, q->frame_size)) { + fprintf(stderr, "Error resizing CFO\n"); + return ret; + } + + // Update CFO tolerance + srslte_sync_nbiot_set_cfo_tol(q, q->current_cfo_tol); + + DEBUG("NBIOT SYNC init with frame_size=%d, max_offset=%d and fft_size=%d\n", frame_size, max_offset, fft_size); + + ret = SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid parameters frame_size: %d, fft_size: %d\n", frame_size, fft_size); + } + + return ret; +} + +/** Finds the NPSS sequence around the position find_offset in the buffer input. + * Returns 1 if the correlation peak exceeds the threshold set by srslte_sync_set_threshold() + * or 0 otherwise. Returns a negative number on error. + * + * The maximum of the correlation peak is always stored in *peak_position + */ +srslte_sync_find_ret_t +srslte_sync_nbiot_find(srslte_sync_nbiot_t* q, cf_t* input, uint32_t find_offset, uint32_t* peak_position) +{ + srslte_sync_find_ret_t ret = SRSLTE_SYNC_NOFOUND; + + int peak_pos = 0; + if (peak_position) { + *peak_position = 0; + } + + // Retrieve CFO from a set of candidates + if (q->enable_cfo_cand_test) { + q->mean_cfo = q->cfo_cand[q->cfo_cand_idx] / 15000; + q->cfo_cand_idx = (q->cfo_cand_idx + 1) % q->cfo_num_cand; + } + + // correct CFO using current estimate, store result in seperate buffer for NPSS detection + srslte_cfo_correct(&q->cfocorr, input, q->cfo_output, -q->mean_cfo / q->fft_size); + + peak_pos = srslte_npss_sync_find(&q->npss, &q->cfo_output[find_offset], &q->peak_value); + if (peak_pos < 0) { + fprintf(stderr, "Error calling finding NPSS sequence, peak pos: %d\n", peak_pos); + return SRSLTE_ERROR; + } + + if (peak_position) { + *peak_position = (uint32_t)peak_pos; + } + + /* If peak is over threshold return success */ + if (q->peak_value >= q->threshold) { + ret = SRSLTE_SYNC_FOUND; + } + + // estimate CFO after NPSS has been detected + if (q->enable_cfo_estimation) { + // check if there are enough samples left + if (peak_pos + SRSLTE_NPSS_CFO_OFFSET + SRSLTE_NPSS_CFO_NUM_SAMPS + SRSLTE_NBIOT_FFT_SIZE < q->frame_size) { + // shift input signal + srslte_vec_prod_ccc(&q->shift_buffer[SRSLTE_SF_LEN(q->fft_size) / 2], + &input[peak_pos + SRSLTE_NPSS_CFO_OFFSET], + &input[peak_pos + SRSLTE_NPSS_CFO_OFFSET], + SRSLTE_NPSS_CFO_NUM_SAMPS); + + // use second slot of the NPSS for CFO estimation + float cfo = cfo_estimate_nbiot(q, &input[peak_pos + SRSLTE_NPSS_CFO_OFFSET]); + + // compute exponential moving average CFO + q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha); + DEBUG("CFO=%.4f, mean=%.4f (%.2f Hz), ema=%.2f\n", cfo, q->mean_cfo, q->mean_cfo * 15000, q->cfo_ema_alpha); + } else { + DEBUG("Not enough samples for CFO estimation. Skipping.\n"); + } + } + + DEBUG("sync_nbiot ret=%d find_offset=%d frame_len=%d, pos=%d peak=%.2f threshold=%.2f, CFO=%.3f kHz\n", + ret, + find_offset, + q->frame_size, + peak_pos, + q->peak_value, + q->threshold, + 15 * (q->mean_cfo)); + + return ret; +} + +// Use two OFDM symbols to estimate CFO +float cfo_estimate_nbiot(srslte_sync_nbiot_t* q, cf_t* input) +{ + uint32_t cp_offset = 0; + cp_offset = + srslte_cp_synch(&q->cp_synch, input, q->max_offset, SRSLTE_NPSS_CFO_NUM_SYMS, SRSLTE_CP_LEN_NORM(1, q->fft_size)); + cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset); + float cfo = -carg(cp_corr_max) / M_PI / 2; + return cfo; +} + +void srslte_sync_nbiot_set_threshold(srslte_sync_nbiot_t* q, float threshold) +{ + q->threshold = threshold; +} + +void srslte_sync_nbiot_set_cfo_enable(srslte_sync_nbiot_t* q, bool enable) +{ + q->enable_cfo_estimation = enable; +} + +void srslte_sync_nbiot_set_cfo_cand_test_enable(srslte_sync_nbiot_t* q, bool enable) +{ + q->enable_cfo_cand_test = enable; +} + +int srslte_sync_nbiot_set_cfo_cand(srslte_sync_nbiot_t* q, const float* cand, const int num) +{ + if (num > MAX_NUM_CFO_CANDITATES) { + printf("Too many candidates, maximum is %d.\n", MAX_NUM_CFO_CANDITATES); + return SRSLTE_ERROR; + } + for (int i = 0; i < num; i++) { + q->cfo_cand[i] = cand[i]; + } + q->cfo_num_cand = num; + return SRSLTE_SUCCESS; +} + +void srslte_sync_nbiot_set_cfo_tol(srslte_sync_nbiot_t* q, float tol) +{ + srslte_cfo_set_tol(&q->cfocorr, tol / (15000.0 * q->fft_size)); +} + +void srslte_sync_nbiot_set_cfo_ema_alpha(srslte_sync_nbiot_t* q, float alpha) +{ + q->cfo_ema_alpha = alpha; +} + +void srslte_sync_nbiot_set_npss_ema_alpha(srslte_sync_nbiot_t* q, float alpha) +{ + srslte_npss_synch_set_ema_alpha(&q->npss, alpha); +} + +/** Determines the N_id_ncell using the samples in the buffer input. + * The function expects two subframes of samples provided as input which + * both contain subframe 9 of two consecutive frames. Either the first + * or the seconds contain the NSSS sequence. + * + * Returns 1 if the correlation peak exceeds the threshold or 0 otherwise. + * Returns a negative number on error. + * + */ +int srslte_sync_nbiot_find_cell_id(srslte_sync_nbiot_t* q, cf_t* input) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + float peak_value; + uint32_t sfn_partial; + + if (q != NULL && input != NULL && q->frame_size == SRSLTE_SF_LEN_PRB_NBIOT) { + ret = srslte_nsss_sync_find(&q->nsss, input, &peak_value, &q->n_id_ncell, &sfn_partial); + printf("NSSS with peak=%f, cell-id: %d, partial SFN: %x\n", peak_value, q->n_id_ncell, sfn_partial); + } + return ret; +} + +int srslte_sync_nbiot_get_cell_id(srslte_sync_nbiot_t* q) +{ + return q->n_id_ncell; +} + +float srslte_sync_nbiot_get_cfo(srslte_sync_nbiot_t* q) +{ + return q->mean_cfo + q->cfo_i; +} + +void srslte_sync_nbiot_set_cfo(srslte_sync_nbiot_t* q, float cfo) +{ + q->mean_cfo = cfo; +} + +float srslte_sync_nbiot_get_peak_value(srslte_sync_nbiot_t* q) +{ + return q->peak_value; +} + +void srslte_sync_nbiot_reset(srslte_sync_nbiot_t* q) +{ + srslte_npss_synch_reset(&q->npss); +} diff --git a/lib/src/phy/sync/test/CMakeLists.txt b/lib/src/phy/sync/test/CMakeLists.txt index 77df8cfd4..25035c18e 100644 --- a/lib/src/phy/sync/test/CMakeLists.txt +++ b/lib/src/phy/sync/test/CMakeLists.txt @@ -25,18 +25,29 @@ add_executable(pss_file pss_file.c) target_link_libraries(pss_file srslte_phy) -if(UHD_FOUND) +add_executable(npss_file npss_file.c) +target_link_libraries(npss_file srslte_phy) + +if(RF_FOUND) add_executable(pss_usrp pss_usrp.c) - target_link_libraries(pss_usrp srslte_phy srslte_rf) -endif(UHD_FOUND) + target_link_libraries(pss_usrp srslte_rf srslte_phy) + + add_executable(npss_usrp npss_usrp.c) + target_link_libraries(npss_usrp srslte_rf srslte_phy) + + add_executable(nsss_usrp nsss_usrp.c) + target_link_libraries(nsss_usrp srslte_rf srslte_phy) +endif(RF_FOUND) if(SRSGUI_FOUND) include_directories(${SRSGUI_INCLUDE_DIRS}) target_link_libraries(pss_file ${SRSGUI_LIBRARIES}) - if(UHD_FOUND) + if(RF_FOUND) target_link_libraries(pss_usrp ${SRSGUI_LIBRARIES}) - endif(UHD_FOUND) - add_definitions(-DENABLE_GUI) + target_link_libraries(npss_usrp ${SRSGUI_LIBRARIES}) + endif(RF_FOUND) +else(SRSGUI_FOUND) + add_definitions(-DDISABLE_GRAPHICS) endif(SRSGUI_FOUND) ######################################################################## @@ -46,6 +57,15 @@ endif(SRSGUI_FOUND) add_executable(sync_test sync_test.c) target_link_libraries(sync_test srslte_phy) +add_executable(sync_nbiot_test sync_nbiot_test.c) +target_link_libraries(sync_nbiot_test srslte_phy) + +add_executable(npss_test npss_test.c) +target_link_libraries(npss_test srslte_phy) + +add_executable(nsss_test nsss_test.c) +target_link_libraries(nsss_test srslte_phy) + add_test(sync_test_100 sync_test -o 100 -c 501) add_test(sync_test_400 sync_test -o 400 -c 2) add_test(sync_test_100_e sync_test -o 100 -e -c 150) @@ -56,6 +76,10 @@ add_test(sync_test_400 sync_test -o 400 -p 50 -c 500) add_test(sync_test_100_e sync_test -o 100 -e -p 50 -c 133) add_test(sync_test_400_e sync_test -o 400 -e -p 50 -c 123) +add_test(npss_test_nonoise npss_test) +add_test(nsss_test_nonoise_2 nsss_test -c 2) +add_test(nsss_test_nonoise_501 nsss_test -c 501) + ######################################################################## # CFO TEST ######################################################################## @@ -65,7 +89,3 @@ target_link_libraries(cfo_test srslte_phy) add_test(cfo_test_1 cfo_test -f 0.12345 -n 1000) add_test(cfo_test_2 cfo_test -f 0.99849 -n 1000) - - - - diff --git a/lib/src/phy/sync/test/npss_file.c b/lib/src/phy/sync/test/npss_file.c new file mode 100644 index 000000000..b53fcf156 --- /dev/null +++ b/lib/src/phy/sync/test/npss_file.c @@ -0,0 +1,307 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/phy/io/filesink.h" +#include "srslte/phy/io/filesource.h" +#include "srslte/phy/sync/npss.h" +#include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define OUTPUT_FILENAME "npss_file.m" +void write_to_file(); + +srslte_nbiot_cell_t cell = { + .base = {.nof_prb = 1, .cp = SRSLTE_CP_NORM, .id = 0}, + .base.nof_ports = 1, + .base.nof_prb = 1, + .nbiot_prb = 0, +}; + +bool disable_plots = false; +char* input_file_name; +int cell_id = -1; +int nof_frames = 1; +uint32_t fft_size = 128; +float threshold = 0.4; +int N_id_2_sync = -1; +srslte_cp_t cp = SRSLTE_CP_NORM; +int file_offset = 0; +bool save_frame_to_file = false; + +#define FLEN (fft_size * 15 * 10) // for one entire frame + +void usage(char* prog) +{ + printf("Usage: %s [nlestodv] -i cell_id -f input_file_name\n", prog); + printf("\t-n nof_frames [Default %d]\n", nof_frames); + printf("\t-l N_id_2 to sync [Default use cell_id]\n"); + printf("\t-s Safe to aligned frame to file [Default %d]\n", save_frame_to_file); + printf("\t-t threshold [Default %.2f]\n", threshold); + printf("\t-o file read offset [Default %d]\n", file_offset); + printf("\t-v srslte_verbose\n"); +} + +void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "nlstvof")) != -1) { + switch (opt) { + case 'f': + input_file_name = argv[optind]; + break; + case 't': + threshold = atof(argv[optind]); + break; + case 'o': + file_offset = atoi(argv[optind]); + break; + case 'l': + N_id_2_sync = atoi(argv[optind]); + break; + case 's': + save_frame_to_file = true; + break; + case 'n': + nof_frames = atoi(argv[optind]); + break; + case 'v': + srslte_verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } +} +float m0_value, m1_value; + +int main(int argc, char** argv) +{ + srslte_filesource_t fsrc; + cf_t* buffer; + int frame_cnt, n; + srslte_npss_synch_t npss; + int peak_idx, last_peak; + float peak_value; + float mean_peak; + uint32_t nof_det, nof_nodet, nof_nopeak, nof_nopeakdet; + + parse_args(argc, argv); + + buffer = malloc(sizeof(cf_t) * FLEN * 2); + if (!buffer) { + perror("malloc"); + exit(-1); + } + + if (srslte_npss_synch_init(&npss, FLEN, fft_size)) { + fprintf(stderr, "Error initializing NPSS object\n"); + exit(-1); + } + + printf("Opening file...\n"); + if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { + fprintf(stderr, "Error opening file %s\n", input_file_name); + exit(-1); + } + + printf("Frame length %d samples\n", FLEN); + printf("NPSS detection threshold: %.2f\n", threshold); + + nof_det = nof_nodet = nof_nopeak = nof_nopeakdet = 0; + frame_cnt = 0; + last_peak = 0; + mean_peak = 0; + int peak_offset = 0; + + n = srslte_filesource_read(&fsrc, buffer, file_offset); + + bool save_and_exit = false; + while (frame_cnt < nof_frames || nof_frames == -1) { + n = srslte_filesource_read(&fsrc, buffer, FLEN - peak_offset); + if (n < 0) { + fprintf(stderr, "Error reading samples\n"); + exit(-1); + } + if (n < FLEN / 10) { + fprintf(stdout, "End of file (n=%d, flen=%d, peak=%d)\n", n, FLEN, peak_offset); + break; + } + + if (save_frame_to_file && save_and_exit) { + char* filename = "frame_hyp.bin"; + printf("Saving entire frame to %s\n", filename); + srslte_vec_save_file(filename, buffer, FLEN * sizeof(cf_t)); + exit(-1); + } + + peak_idx = srslte_npss_sync_find(&npss, buffer, &peak_value); + if (peak_idx < 0) { + fprintf(stderr, "Error finding NPSS peak\n"); + exit(-1); + } + + mean_peak = SRSLTE_VEC_CMA(peak_value, mean_peak, frame_cnt); + + if (peak_value >= threshold) { + nof_det++; + + // try to align frame + if (save_frame_to_file && !save_and_exit) { + cf_t dummy[FLEN]; // full frame + printf("Peak_idx at %d\n", peak_idx); + int num_drop = peak_idx - SRSLTE_NPSS_CORR_OFFSET + FLEN / 2; + printf("Dropping %d samples!\n", num_drop); + + if (num_drop > FLEN) { + printf("wrapping num drop to %d\n", num_drop); + num_drop = num_drop % FLEN; + } + + srslte_filesource_read(&fsrc, dummy, num_drop); + save_and_exit = true; + } + + } else { + nof_nodet++; + } + + if (frame_cnt > 100) { + if (abs(last_peak - peak_idx) > 4) { + if (peak_value >= threshold) { + nof_nopeakdet++; + } + nof_nopeak++; + } + } + + frame_cnt++; + + printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " + "FA: %4.2f\n", + frame_cnt, + (peak_value > threshold) ? peak_idx : 0, + peak_value, + mean_peak, + (float)nof_det / frame_cnt, + (float)nof_nopeakdet / frame_cnt); + + if (SRSLTE_VERBOSE_ISINFO()) { + printf("\n"); + } + + usleep(10000); + + last_peak = peak_idx; + } + + printf("NPSS detected #%d\n", nof_det); + + srslte_vec_save_file( + "npss_find_conv_output_abs.bin", npss.conv_output_abs, (FLEN + SRSLTE_NPSS_CORR_FILTER_LEN) * sizeof(float)); + srslte_vec_save_file("npss_corr_seq_time.bin", npss.npss_signal_time, SRSLTE_NPSS_CORR_FILTER_LEN * sizeof(cf_t)); + + write_to_file(); + + srslte_npss_synch_free(&npss); + free(buffer); + srslte_filesource_free(&fsrc); + + printf("Ok\n"); + exit(0); +} + +float tmp[1000000]; +void write_to_file() +{ + srslte_filesink_t debug_fsink; + char fname[] = OUTPUT_FILENAME; + if (srslte_filesink_init(&debug_fsink, fname, SRSLTE_TEXT)) { + fprintf(stderr, "Error opening file %s\n", fname); + exit(-1); + } + + fprintf(debug_fsink.f, "%% %s : auto-generated file\n", OUTPUT_FILENAME); + fprintf(debug_fsink.f, "clear all;\n"); + fprintf(debug_fsink.f, "close all;\n"); + fprintf(debug_fsink.f, "pkg load signal;\n\n"); + + // the correlation sequence + fprintf(debug_fsink.f, "len = %u;\n", SRSLTE_NPSS_CORR_FILTER_LEN); + fprintf(debug_fsink.f, "sig1=read_complex('npss_corr_seq_time.bin', len);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t=1:len;\n"); + fprintf(debug_fsink.f, "plot(t,real(sig1),t,imag(sig1));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title(\"Correlation sequence time-domain\");\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the FFT of the first symbol after the frequency correction + fprintf(debug_fsink.f, "npss_sym0=sig1(10:137);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(real(fftshift(fft(npss_sym0.*exp(-2*pi*1i*(0:127)'*.5/128), 128))));\n"); + fprintf(debug_fsink.f, "title(\"FFT of first symbol after frequency correction\");\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the input signal + fprintf(debug_fsink.f, "len = %u;\n", FLEN); + fprintf(debug_fsink.f, "sig=read_complex('%s', len);\n", input_file_name); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t= 1:length(sig);\n"); + fprintf(debug_fsink.f, "plot(t,real(sig),t,imag(sig));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title(\"Subframe time-domain\");\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the correlation output + fprintf(debug_fsink.f, "num_samples = %u;\n", SRSLTE_NPSS_CORR_FILTER_LEN + FLEN - 1); + fprintf(debug_fsink.f, "conv = read_real('npss_find_conv_output_abs.bin', num_samples);\n"); + fprintf(debug_fsink.f, "t=1:length(conv);\n"); + fprintf(debug_fsink.f, "\n\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(t,conv);\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title(\"Convolution output absolute\");\n"); + fprintf(debug_fsink.f, "ylabel('Correlation magnitude');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // cross-correlation in octave + fprintf(debug_fsink.f, "[corr, lag] = xcorr(sig,sig1);\n"); + fprintf(debug_fsink.f, "\n\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(abs(corr));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title(\"Correlation in Octave\");\n"); + fprintf(debug_fsink.f, "ylabel('Correlation magnitude');\n"); + fprintf(debug_fsink.f, "\n\n"); + + srslte_filesink_free(&debug_fsink); + printf("data written to %s\n", OUTPUT_FILENAME); +} diff --git a/lib/src/phy/sync/test/npss_test.c b/lib/src/phy/sync/test/npss_test.c new file mode 100644 index 000000000..06dfab29b --- /dev/null +++ b/lib/src/phy/sync/test/npss_test.c @@ -0,0 +1,220 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "srslte/phy/sync/npss.h" +#include "srslte/srslte.h" + +#define OUTPUT_FILENAME "npss_test.m" +void write_to_file(); + +#define DUMP_SIGNALS 0 + +int input_len = SRSLTE_SF_LEN(SRSLTE_NBIOT_FFT_SIZE); + +void usage(char* prog) +{ + printf("Usage: %s [cpoev]\n", prog); + printf("\t-v srslte_verbose\n"); +} + +void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "lv")) != -1) { + switch (opt) { + case 'l': + input_len = atoi(argv[optind]); + break; + case 'v': + srslte_verbose = SRSLTE_VERBOSE_DEBUG; + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +int main(int argc, char** argv) +{ + cf_t* fft_buffer; + cf_t* input_buffer; + + srslte_npss_synch_t syncobj; + srslte_ofdm_t ifft; + struct timeval t[3]; + int fft_size; + int peak_pos; + float peak_value; + int ret = SRSLTE_ERROR; + + parse_args(argc, argv); + + if (input_len < SRSLTE_SF_LEN(SRSLTE_NBIOT_FFT_SIZE)) { + fprintf(stderr, "Input len too small (%d), must be at least one subframe\n", input_len); + exit(-1); + } + + fft_size = srslte_symbol_sz(SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL); + if (fft_size < 0) { + fprintf(stderr, "Invalid nof_prb=%d\n", SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL); + exit(-1); + } + + printf("Input buffer length is %d samples\n", input_len); + uint32_t buffer_len = input_len + SRSLTE_NPSS_CORR_FILTER_LEN + 1; + fft_buffer = malloc(sizeof(cf_t) * buffer_len); + if (!fft_buffer) { + perror("malloc"); + exit(-1); + } + bzero(fft_buffer, sizeof(cf_t) * buffer_len); + + input_buffer = malloc(sizeof(cf_t) * input_len); + if (!input_buffer) { + perror("malloc"); + exit(-1); + } + bzero(input_buffer, sizeof(cf_t) * input_len); + + if (srslte_ofdm_tx_init(&ifft, SRSLTE_CP_NORM, input_buffer, fft_buffer, SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL)) { + fprintf(stderr, "Error creating iFFT object\n"); + exit(-1); + } + srslte_ofdm_set_freq_shift(&ifft, -SRSLTE_NBIOT_FREQ_SHIFT_FACTOR); + + if (srslte_npss_synch_init(&syncobj, input_len, fft_size)) { + fprintf(stderr, "Error initializing NPSS object\n"); + return SRSLTE_ERROR; + } + + // generate NPSS/NSSS signals + _Complex float npss_signal[SRSLTE_NPSS_TOT_LEN]; + srslte_npss_generate(npss_signal); + srslte_npss_put_subframe( + &syncobj, npss_signal, input_buffer, SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL, SRSLTE_NBIOT_DEFAULT_PRB_OFFSET); + + // Transform to OFDM symbols + srslte_ofdm_tx_sf(&ifft); + + // look for NPSS signal + gettimeofday(&t[1], NULL); + peak_pos = srslte_npss_sync_find(&syncobj, fft_buffer, &peak_value); + gettimeofday(&t[2], NULL); + get_time_interval(t); + printf("NPPS with peak=%f found at: %d (in %.0f usec)\n", + peak_value, + peak_pos, + (int)t[0].tv_sec * 1e6 + (int)t[0].tv_usec); + + // write results to file +#if DUMP_SIGNALS + srslte_vec_save_file("npss_find_conv_output_abs.bin", syncobj.conv_output_abs, buffer_len * sizeof(float)); + srslte_vec_save_file("npss_sf_time.bin", fft_buffer, input_len * sizeof(cf_t)); + srslte_vec_save_file("npss_corr_seq_time.bin", syncobj.npss_signal_time, SRSLTE_NPSS_CORR_FILTER_LEN * sizeof(cf_t)); + write_to_file(); +#endif + + // cleanup + srslte_npss_synch_free(&syncobj); + free(fft_buffer); + free(input_buffer); + srslte_ofdm_tx_free(&ifft); + + if (peak_pos == SRSLTE_NPSS_CORR_OFFSET) { + printf("Ok\n"); + ret = SRSLTE_SUCCESS; + } else { + printf("Failed\n"); + } + + return ret; +} + +void write_to_file() +{ + srslte_filesink_t debug_fsink; + char fname[] = OUTPUT_FILENAME; + if (srslte_filesink_init(&debug_fsink, fname, SRSLTE_TEXT)) { + fprintf(stderr, "Error opening file %s\n", fname); + exit(-1); + } + + fprintf(debug_fsink.f, "%% %s : auto-generated file\n", OUTPUT_FILENAME); + fprintf(debug_fsink.f, "clear all;\n"); + fprintf(debug_fsink.f, "close all;\n"); + fprintf(debug_fsink.f, "pkg load signal;\n\n"); + + // the correlation sequence + fprintf(debug_fsink.f, "len = %u;\n", SRSLTE_NPSS_CORR_FILTER_LEN); + fprintf(debug_fsink.f, "sig1=read_complex('npss_corr_seq_time.bin', len);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t=1:len;\n"); + fprintf(debug_fsink.f, "plot(t,real(sig1),t,imag(sig1));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Correlation sequence time-domain');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the generated subframe + fprintf(debug_fsink.f, "len = %u;\n", input_len); + fprintf(debug_fsink.f, "sig=read_complex('npss_sf_time.bin', len);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t= 1:len;\n"); + fprintf(debug_fsink.f, "plot(t,real(sig),t,imag(sig));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Subframe time-domain');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the correlation output + fprintf(debug_fsink.f, "num_samples = %u;\n", SRSLTE_NPSS_CORR_FILTER_LEN + input_len - 1); + fprintf(debug_fsink.f, "sig = read_real('npss_find_conv_output_abs.bin', num_samples);\n"); + fprintf(debug_fsink.f, "t=1:num_samples;\n"); + fprintf(debug_fsink.f, "\n\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(t,sig);\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Convolution output absolute');\n"); + fprintf(debug_fsink.f, "ylabel('Correlation magnitude');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // cross-correlation in octave + fprintf(debug_fsink.f, "[corr, lag] = xcorr(sig1,sig1);\n"); + fprintf(debug_fsink.f, "\n\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(abs(corr));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Correlation in Octave');\n"); + fprintf(debug_fsink.f, "ylabel('Correlation magnitude');\n"); + fprintf(debug_fsink.f, "\n\n"); + + srslte_filesink_free(&debug_fsink); + printf("data written to %s\n", OUTPUT_FILENAME); +} diff --git a/lib/src/phy/sync/test/npss_usrp.c b/lib/src/phy/sync/test/npss_usrp.c new file mode 100644 index 000000000..f7e93cd8a --- /dev/null +++ b/lib/src/phy/sync/test/npss_usrp.c @@ -0,0 +1,313 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "srslte/phy/rf/rf.h" +#include "srslte/phy/sync/npss.h" +#include "srslte/srslte.h" + +#ifndef DISABLE_GRAPHICS +void init_plots(); +void do_plots_npss(float* corr, float energy, uint32_t size); +#endif + +bool disable_plots = false; +char* rf_args = ""; +float rf_gain = 40.0, rf_freq = -1.0; +int nof_frames = -1; +uint32_t fft_size = 128; +float threshold = 0.4; +bool save_frame_to_file = false; +float cfo_fixed = 0.0; +bool has_cfo_corr = true; + +srslte_nbiot_cell_t cell = { + .base = {.nof_prb = 1, .cp = SRSLTE_CP_NORM, .nof_ports = 1, .id = 0}, + .nbiot_prb = 0, + .n_id_ncell = 0, +}; + +void usage(char* prog) +{ + printf("Usage: %s [adgtvnp] -f rx_frequency_hz -i cell_id\n", prog); + printf("\t-a RF args [Default %s]\n", rf_args); + printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain); + printf("\t-C Disable CFO correction [Default %s]\n", has_cfo_corr ? "Enabled" : "Disabled"); + printf("\t-c Manual CFO offset [Default %.0f Hz]\n", cfo_fixed); + printf("\t-n nof_frames [Default %d]\n", nof_frames); + printf("\t-s Save frame to file [Default %d]\n", save_frame_to_file); + printf("\t-t threshold [Default %.2f]\n", threshold); +#ifndef DISABLE_GRAPHICS + printf("\t-d disable plots [Default enabled]\n"); +#else + printf("\t plots are disabled. Graphics library not available\n"); +#endif + printf("\t-v srslte_verbose\n"); +} + +void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "aCcdgtvsfi")) != -1) { + switch (opt) { + case 'a': + rf_args = argv[optind]; + break; + case 'C': + has_cfo_corr = false; + break; + case 'c': + cfo_fixed = atof(argv[optind]); + break; + case 'g': + rf_gain = atof(argv[optind]); + break; + case 'f': + rf_freq = atof(argv[optind]); + break; + case 't': + threshold = atof(argv[optind]); + break; + case 'i': + cell.base.id = atoi(argv[optind]); + break; + case 's': + save_frame_to_file = true; + disable_plots = true; + break; + case 'n': + nof_frames = atoi(argv[optind]); + break; + case 'd': + disable_plots = true; + break; + case 'v': + srslte_verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (rf_freq < 0) { + usage(argv[0]); + exit(-1); + } +} + +float m0_value, m1_value; + +bool go_exit = false; +void sig_int_handler(int signo) +{ + printf("SIGINT received. Exiting...\n"); + if (signo == SIGINT) { + go_exit = true; + } +} + +int main(int argc, char** argv) +{ + cf_t* buffer; + int frame_cnt, n; + srslte_rf_t rf; + srslte_cfo_t cfocorr; + srslte_npss_synch_t npss; + int32_t flen; + int peak_idx; + float peak_value; + float mean_peak; + uint32_t nof_det, nof_nodet, nof_nopeak, nof_nopeakdet; + + parse_args(argc, argv); + +#ifndef DISABLE_GRAPHICS + if (!disable_plots) + init_plots(); +#endif + + signal(SIGINT, sig_int_handler); + + float srate = 15000.0 * fft_size; + flen = srate * 10 / 1000; + + printf("Frame length %d samples\n", flen); + printf("NPSS detection threshold: %.2f\n", threshold); + + if (cfo_fixed) { + printf("Manually compensating %.0f Hz CFO offset\n", cfo_fixed); + } + + if (srslte_cfo_init(&cfocorr, flen)) { + fprintf(stderr, "Error initiating CFO\n"); + exit(-1); + } + srslte_cfo_set_tol(&cfocorr, 50.0 / (15000.0 * fft_size)); + + printf("Opening RF device...\n"); + if (srslte_rf_open(&rf, rf_args)) { + fprintf(stderr, "Error opening rf\n"); + exit(-1); + } + + printf("Set RX rate: %.2f MHz\n", srslte_rf_set_rx_srate(&rf, srate) / 1000000); + printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain)); + printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, 0, rf_freq) / 1000000); + + buffer = malloc(sizeof(cf_t) * flen * 2); + if (!buffer) { + perror("malloc"); + exit(-1); + } + bzero(buffer, sizeof(cf_t) * flen * 2); + + if (srslte_npss_synch_init(&npss, flen, fft_size)) { + fprintf(stderr, "Error initializing NPSS object\n"); + exit(-1); + } + + srslte_rf_start_rx_stream(&rf, false); + + nof_det = nof_nodet = nof_nopeak = nof_nopeakdet = 0; + frame_cnt = 0; + mean_peak = 0; + peak_idx = 0; + int peak_offset = 0; + + bool save_and_exit = false; + while ((frame_cnt < nof_frames || nof_frames == -1) && !go_exit) { + n = srslte_rf_recv(&rf, buffer, flen - peak_offset, 1); + if (n < 0) { + fprintf(stderr, "Error receiving samples\n"); + exit(-1); + } + + frame_cnt++; + + if (save_frame_to_file && save_and_exit) { + char* filename = "frame_hyp.bin"; + printf("Saving entire frame to %s\n", filename); + srslte_vec_save_file(filename, buffer, flen * sizeof(cf_t)); + go_exit = true; + } + + // perform CFO correction + if (has_cfo_corr) { + srslte_cfo_correct(&cfocorr, buffer, buffer, -cfo_fixed / (15000 * fft_size)); + } + + peak_idx = srslte_npss_sync_find(&npss, buffer, &peak_value); + if (peak_idx < 0) { + fprintf(stderr, "Error finding NPSS peak\n"); + exit(-1); + } + + mean_peak = SRSLTE_VEC_CMA(peak_value, mean_peak, frame_cnt); + + if (peak_value >= threshold) { + nof_det++; + + // try to align frame + if (save_frame_to_file && !save_and_exit) { + cf_t dummy[flen]; // full frame + printf("Peak_idx at %d\n", peak_idx); + int num_drop = peak_idx - SRSLTE_NPSS_CORR_OFFSET + flen / 2; + printf("Dropping %d samples!\n", num_drop); + + if (num_drop > flen) { + printf("wrapping num drop to %d\n", num_drop); + num_drop = num_drop % flen; + } + + srslte_rf_recv(&rf, dummy, num_drop, 1); + save_and_exit = true; + } + } else { + nof_nodet++; + } + printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, " + "FA: %4.2f\r", + frame_cnt, + (peak_value > threshold) ? (peak_idx - SRSLTE_NPSS_CORR_OFFSET - flen / 10 / 2) : 0, + peak_value, + mean_peak, + (float)nof_det / frame_cnt, + (float)nof_nopeakdet / frame_cnt); + + if (SRSLTE_VERBOSE_ISINFO()) { + printf("\n"); + } + +#ifndef DISABLE_GRAPHICS + if (!disable_plots) { + int len = SRSLTE_NPSS_CORR_FILTER_LEN + npss.frame_size - 1; + do_plots_npss(npss.conv_output_avg, npss.conv_output_avg[peak_idx], len); + } +#endif + } + + printf("NPSS detected #%d\n", nof_det); + + srslte_npss_synch_free(&npss); + srslte_cfo_free(&cfocorr); + free(buffer); + srslte_rf_close(&rf); + + printf("Ok\n"); + exit(0); +} + +/********************************************************************** + * Plotting Functions + ***********************************************************************/ +#ifndef DISABLE_GRAPHICS + +#include "srsgui/srsgui.h" +plot_real_t pssout; +plot_real_t psss1; + +float tmp[1000000]; + +void init_plots() +{ + sdrgui_init(); + plot_real_init(&pssout); + plot_real_setTitle(&pssout, "NPSS xCorr"); + plot_real_setLabels(&pssout, "Index", "Absolute value"); + plot_real_setYAxisScale(&pssout, 0, 1); +} + +void do_plots_npss(float* corr, float peak, uint32_t size) +{ + srslte_vec_sc_prod_fff(corr, 1. / peak, tmp, size); + plot_real_setNewData(&pssout, tmp, size); +} + +#endif diff --git a/lib/src/phy/sync/test/nsss_test.c b/lib/src/phy/sync/test/nsss_test.c new file mode 100644 index 000000000..6e9a6d219 --- /dev/null +++ b/lib/src/phy/sync/test/nsss_test.c @@ -0,0 +1,284 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "srslte/phy/sync/nsss.h" +#include "srslte/srslte.h" + +#define OUTPUT_FILENAME "nsss_test.m" +void write_to_file(); + +int sfn = 0; +uint32_t n_id_ncell = SRSLTE_CELL_ID_UNKNOWN; +char* input_file_name; + +int max_num_sf = 20; + +#define NOF_PRB 1 + +#define DUMP_SIGNALS 0 +#define MAX_CORR_LEN 10000 +#define SFLEN (1 * SRSLTE_SF_LEN(SRSLTE_NBIOT_FFT_SIZE)) + +void usage(char* prog) +{ + printf("Usage: %s [fcpoev]\n", prog); + printf("\t-f file to read from\n"); + printf("\t-c cell ID\n"); + printf("\t-n SFN\n"); + printf("\t-r Maximum number of subframes to read from file [default: %d]\n", max_num_sf); + printf("\t-v srslte_verbose\n"); +} + +void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "fcprnov")) != -1) { + switch (opt) { + case 'f': + input_file_name = argv[optind]; + break; + case 'c': + n_id_ncell = atoi(argv[optind]); + break; + case 'n': + sfn = atoi(argv[optind]); + break; + case 'r': + max_num_sf = atoi(argv[optind]); + break; + case 'v': + srslte_verbose = SRSLTE_VERBOSE_DEBUG; + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +int main(int argc, char** argv) +{ + cf_t* fft_buffer = NULL; + cf_t* buffer = NULL; + srslte_nsss_synch_t syncobj = {}; + srslte_ofdm_t ifft = {}; + int fft_size = 0; + float peak_value = 0.0; + int num_sf = 1; + int ret = SRSLTE_ERROR; + + parse_args(argc, argv); + + buffer = malloc(sizeof(cf_t) * SFLEN * max_num_sf); + if (!buffer) { + perror("malloc"); + return ret; + } + memset(buffer, 0, sizeof(cf_t) * SFLEN * max_num_sf); + + fft_size = srslte_symbol_sz(NOF_PRB); + if (fft_size < 0) { + fprintf(stderr, "Invalid nof_prb=%d\n", NOF_PRB); + goto exit; + } + + printf("SFLEN is %d samples\n", SFLEN); + fft_buffer = malloc(sizeof(cf_t) * SFLEN * max_num_sf); + if (!fft_buffer) { + perror("malloc"); + goto exit; + } + memset(fft_buffer, 0, sizeof(cf_t) * SFLEN * max_num_sf); + + if (srslte_ofdm_tx_init(&ifft, SRSLTE_CP_NORM, buffer, fft_buffer, NOF_PRB)) { + fprintf(stderr, "Error creating iFFT object\n"); + goto exit; + } + + if (input_file_name != NULL) { + srslte_filesource_t fsrc; + printf("Opening file %s\n", input_file_name); + if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { + fprintf(stderr, "Error opening file %s\n", input_file_name); + goto exit; + } + num_sf = 0; + + // offset file + int file_offset = 0; + srslte_filesource_read(&fsrc, buffer, file_offset); + + // now read + while (num_sf < max_num_sf) { + int n = srslte_filesource_read(&fsrc, &fft_buffer[num_sf * SFLEN], SFLEN); + if (n < 0) { + fprintf(stderr, "Error reading samples\n"); + goto exit; + } + if (n < SFLEN) { + fprintf(stdout, "End of file (n=%d, sflen=%d)\n", n, SFLEN); + break; + } + num_sf++; + } + srslte_filesource_free(&fsrc); + printf("Read %d sumbframes from file.\n", num_sf); + } + + // initialize NSSS object with actual input length + printf("Initializing NSSS synch with %dx%d samples.\n", num_sf, SFLEN); + if (srslte_nsss_synch_init(&syncobj, num_sf * SFLEN, fft_size)) { + fprintf(stderr, "Error initializing NSSS object\n"); + goto exit; + } + + // write single NSSS sequence if not reading from input file + if (!input_file_name) { + // generate NPSS/NSSS signals + printf("Generating NSSS sequence for n_id_ncell=%d\n", n_id_ncell); + cf_t nsss_signals[SRSLTE_NSSS_TOT_LEN] = {}; + srslte_nsss_generate(nsss_signals, n_id_ncell == SRSLTE_CELL_ID_UNKNOWN ? 0 : n_id_ncell); + +#if DUMP_SIGNALS + srslte_vec_save_file("nsss_signal_freq.bin", nsss_signals, SRSLTE_NSSS_LEN * sizeof(cf_t)); +#endif + + srslte_nsss_put_subframe( + &syncobj, nsss_signals, buffer, sfn, SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL, SRSLTE_NBIOT_DEFAULT_PRB_OFFSET); + + // Transform to OFDM symbols + srslte_ofdm_tx_sf(&ifft); + } + + // look for NSSS signal + uint32_t n_id_ncell_detected = SRSLTE_CELL_ID_UNKNOWN; + uint32_t sfn_partial = 0; + srslte_nsss_sync_find(&syncobj, fft_buffer, &peak_value, &n_id_ncell_detected, &sfn_partial); + printf("NSSS with peak=%f, n_id_ncell: %d, partial SFN: %x\n", peak_value, n_id_ncell_detected, sfn_partial); + + if (n_id_ncell_detected == (n_id_ncell == SRSLTE_CELL_ID_UNKNOWN ? 0 : n_id_ncell)) { + printf("Ok\n"); + ret = SRSLTE_SUCCESS; + } else { + printf("Failed\n"); + } + +#if DUMP_SIGNALS +// dump signals +#define MAX_FNAME_LEN 40 + char fname[MAX_FNAME_LEN] = {}; + snprintf(fname, MAX_FNAME_LEN, "nsss_find_input.bin"); + printf("Saving entire sub-frame to %s\n", fname); + srslte_vec_save_file(fname, fft_buffer, num_sf * SFLEN * sizeof(cf_t)); + srslte_vec_save_file("nsss_corr_seq_time.bin", + syncobj.nsss_signal_time[n_id_ncell == SRSLTE_CELL_ID_UNKNOWN ? 0 : n_id_ncell], + SRSLTE_NSSS_CORR_FILTER_LEN * sizeof(cf_t)); + if (n_id_ncell_detected != SRSLTE_CELL_ID_UNKNOWN) { + // run correlation again with found cell to populate conv_output_abs + srslte_nsss_sync_find(&syncobj, fft_buffer, &peak_value, &n_id_ncell_detected, &sfn_partial); + } + srslte_vec_save_file("nsss_find_conv_output_abs.bin", + syncobj.conv_output_abs, + (SRSLTE_NSSS_CORR_FILTER_LEN + num_sf * SFLEN) * sizeof(float)); + + // write Octave script + write_to_file(); +#endif + + // cleanup +exit: + srslte_nsss_synch_free(&syncobj); + srslte_ofdm_tx_free(&ifft); + if (buffer) { + free(buffer); + } + if (fft_buffer) { + free(fft_buffer); + } + + return ret; +} + +void write_to_file() +{ + srslte_filesink_t debug_fsink; + char fname[] = OUTPUT_FILENAME; + if (srslte_filesink_init(&debug_fsink, fname, SRSLTE_TEXT)) { + fprintf(stderr, "Error opening file %s\n", fname); + exit(-1); + } + + fprintf(debug_fsink.f, "%% %s : auto-generated file\n", OUTPUT_FILENAME); + fprintf(debug_fsink.f, "clear all;\n"); + fprintf(debug_fsink.f, "close all;\n"); + fprintf(debug_fsink.f, "set(0,'DefaultFigureWindowStyle','docked');\n\n"); + fprintf(debug_fsink.f, "max_len = 1920 * 100;\n"); + + // the correlation sequence + fprintf(debug_fsink.f, "corr_seq=read_complex('nsss_corr_seq_time.bin', max_len);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t=1:length(corr_seq);\n"); + fprintf(debug_fsink.f, "plot(t,real(corr_seq),t,imag(corr_seq));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Correlation sequence time-domain');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the generated subframe + fprintf(debug_fsink.f, "input=read_complex('nsss_find_input.bin', max_len);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t=1:length(input);\n"); + fprintf(debug_fsink.f, "plot(t,real(input),t,imag(input));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Subframe time-domain');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the correlation output + fprintf(debug_fsink.f, "corr_srslte = read_real('nsss_find_conv_output_abs.bin', max_len);\n"); + fprintf(debug_fsink.f, "t=1:length(corr_srslte);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(t,corr_srslte);\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Convolution output absolute');\n"); + fprintf(debug_fsink.f, "ylabel('Auto-correlation magnitude');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // correlation in octave + fprintf(debug_fsink.f, "[corr_oct, lag] = xcorr(input,corr_seq);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(abs(corr_oct));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Correlation in Octave');\n"); + fprintf(debug_fsink.f, "ylabel('Correlation magnitude');\n"); + fprintf(debug_fsink.f, "\n\n"); + + srslte_filesink_free(&debug_fsink); + printf("data written to %s\n", OUTPUT_FILENAME); +} diff --git a/lib/src/phy/sync/test/nsss_usrp.c b/lib/src/phy/sync/test/nsss_usrp.c new file mode 100644 index 000000000..74358a3dc --- /dev/null +++ b/lib/src/phy/sync/test/nsss_usrp.c @@ -0,0 +1,189 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "srslte/phy/io/filesink.h" +#include "srslte/phy/io/filesource.h" +#include "srslte/phy/rf/rf.h" +#include "srslte/phy/sync/cfo.h" +#include "srslte/phy/sync/nsss.h" +#include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" + +char* rf_args = ""; +float rf_gain = 40.0, rf_freq = -1.0; +int nof_frames = -1; +uint32_t fft_size = 128; +float threshold = 0.4; +bool has_cfo_corr = true; +float cfo_fixed = 0.0; + +srslte_nbiot_cell_t cell = { + .base = {.nof_prb = 1, .cp = SRSLTE_CP_NORM, .nof_ports = 1, .id = 0}, + .nbiot_prb = 0, + .n_id_ncell = 0, +}; + +void usage(char* prog) +{ + printf("Usage: %s [adgtvnp] -f rx_frequency_hz -i cell_id\n", prog); + printf("\t-a RF args [Default %s]\n", rf_args); + printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain); + printf("\t-C Disable CFO correction [Default %s]\n", has_cfo_corr ? "Enabled" : "Disabled"); + printf("\t-c Manual CFO offset [Default %.0f Hz]\n", cfo_fixed); + printf("\t-n nof_frames [Default %d]\n", nof_frames); + printf("\t-t threshold [Default %.2f]\n", threshold); + printf("\t-v srslte_verbose\n"); +} + +void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "agCctvfi")) != -1) { + switch (opt) { + case 'a': + rf_args = argv[optind]; + break; + case 'C': + has_cfo_corr = false; + break; + case 'c': + cfo_fixed = atof(argv[optind]); + break; + case 'g': + rf_gain = atof(argv[optind]); + break; + case 'f': + rf_freq = atof(argv[optind]); + break; + case 't': + threshold = atof(argv[optind]); + break; + case 'i': + cell.n_id_ncell = atoi(argv[optind]); + break; + case 'n': + nof_frames = atoi(argv[optind]); + break; + case 'v': + srslte_verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (rf_freq < 0) { + usage(argv[0]); + exit(-1); + } +} + +bool go_exit = false; +void sig_int_handler(int signo) +{ + printf("SIGINT received. Exiting...\n"); + if (signo == SIGINT) { + go_exit = true; + } +} + +int main(int argc, char** argv) +{ + cf_t* buffer; + int n; + srslte_rf_t rf; + srslte_nsss_synch_t nsss; + float nsss_peak_value; + parse_args(argc, argv); + + signal(SIGINT, sig_int_handler); + + float srate = 15000.0 * fft_size; + int input_len = srate * 10 / 1000 * 2; // capture two full frames to make sure we have one NSSS + + printf("Input length %d samples\n", input_len); + + printf("Opening RF device...\n"); + if (srslte_rf_open(&rf, rf_args)) { + fprintf(stderr, "Error opening rf\n"); + exit(-1); + } + + printf("Set RX rate: %.2f MHz\n", srslte_rf_set_rx_srate(&rf, srate) / 1000000); + printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain)); + printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, 0, rf_freq) / 1000000); + + buffer = malloc(sizeof(cf_t) * input_len * 2); + if (!buffer) { + perror("malloc"); + exit(-1); + } + + if (srslte_nsss_synch_init(&nsss, input_len, fft_size)) { + fprintf(stderr, "Error initializing NSSS object\n"); + exit(-1); + } + + srslte_rf_start_rx_stream(&rf, false); + + printf("Receiving two full frames ..\n"); + n = srslte_rf_recv(&rf, buffer, input_len, 1); + if (n != input_len) { + fprintf(stderr, "Error receiving samples\n"); + exit(-1); + } + srslte_rf_close(&rf); + + // perform CFO correction + if (has_cfo_corr) { + srslte_cfo_t cfocorr; + if (srslte_cfo_init(&cfocorr, input_len)) { + fprintf(stderr, "Error initiating CFO\n"); + exit(-1); + } + srslte_cfo_set_tol(&cfocorr, 50.0 / (15000.0 * fft_size)); + srslte_cfo_correct(&cfocorr, buffer, buffer, -cfo_fixed / (15000 * fft_size)); + srslte_cfo_free(&cfocorr); + } + + // try to find NSSS + printf("Detecting cell id ..\n"); + uint32_t cell_id = SRSLTE_CELL_ID_UNKNOWN; + uint32_t sfn_partial; + srslte_nsss_sync_find(&nsss, buffer, &nsss_peak_value, &cell_id, &sfn_partial); + printf("Cell id: %d, peak_value=%f\n", cell_id, nsss_peak_value); + + srslte_nsss_synch_free(&nsss); + free(buffer); + + printf("Ok\n"); + exit(0); +} diff --git a/lib/src/phy/sync/test/pss_file.c b/lib/src/phy/sync/test/pss_file.c index a596d88d8..fff433bc1 100644 --- a/lib/src/phy/sync/test/pss_file.c +++ b/lib/src/phy/sync/test/pss_file.c @@ -233,21 +233,21 @@ int main(int argc, char **argv) { int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN)); if (sss_idx >= 0 && sss_idx < flen-fft_size) { srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { - sss_error2++; + if (srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value) != N_id_1) { + sss_error2++; } INFO("sf_idx = %d\n", srslte_sss_subframe(m0, m1)); - INFO("Partial N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + INFO("Partial N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value)); srslte_sss_m0m1_diff(&sss, &buffer[sss_idx], &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { - sss_error3++; + if (srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value) != N_id_1) { + sss_error3++; } - INFO("Diff N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + INFO("Diff N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value)); srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { - sss_error1++; + if (srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value) != N_id_1) { + sss_error1++; } - INFO("Full N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + INFO("Full N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value)); } // Estimate CP diff --git a/lib/src/phy/sync/test/pss_usrp.c b/lib/src/phy/sync/test/pss_usrp.c index f86ea9a58..5fb4883a4 100644 --- a/lib/src/phy/sync/test/pss_usrp.c +++ b/lib/src/phy/sync/test/pss_usrp.c @@ -157,16 +157,9 @@ int main(int argc, char **argv) { exit(-1); } - if (srate < 10e6) { - srslte_rf_set_master_clock_rate(&rf, 4*srate); - } else { - srslte_rf_set_master_clock_rate(&rf, srate); - } - printf("Set RX rate: %.2f MHz\n", srslte_rf_set_rx_srate(&rf, srate) / 1000000); printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain)); printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, 0, rf_freq) / 1000000); - srslte_rf_rx_wait_lo_locked(&rf); buffer = malloc(sizeof(cf_t) * flen * 2); if (!buffer) { @@ -272,23 +265,23 @@ int main(int argc, char **argv) { // Filter SSS srslte_pss_filter(&pss, &buffer[sss_idx], &buffer[sss_idx]); - INFO("Full N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + INFO("Full N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value)); srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 1, ce, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { - sss_error2++; + if (srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value) != N_id_1) { + sss_error2++; } - INFO("Partial N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + INFO("Partial N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value)); srslte_sss_m0m1_diff_coh(&sss, &buffer[sss_idx], ce, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { - sss_error3++; + if (srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value) != N_id_1) { + sss_error3++; } - INFO("Diff N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + INFO("Diff N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value)); } srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { - sss_error1++; + if (srslte_sss_N_id_1(&sss, m0, m1, m1_value + m0_value) != N_id_1) { + sss_error1++; } - + // Estimate CP if (peak_idx > 2*(fft_size + SRSLTE_CP_LEN_EXT(fft_size))) { srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx); diff --git a/lib/src/phy/sync/test/sync_nbiot_test.c b/lib/src/phy/sync/test/sync_nbiot_test.c new file mode 100644 index 000000000..46127625e --- /dev/null +++ b/lib/src/phy/sync/test/sync_nbiot_test.c @@ -0,0 +1,275 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "srslte/phy/sync/sync_nbiot.h" +#include "srslte/srslte.h" + +int offset = 0; +float cfo = 0.0; +float snr = -1.0; + +#define OUTPUT_FILENAME "sync_nbiot_test.m" +void write_to_file(); +char* input_file_name; + +#define DUMP_SIGNALS 1 +#define MAX_CORR_LEN 10000 +#define SFLEN (10 * SRSLTE_SF_LEN(128)) + +void usage(char* prog) +{ + printf("Usage: %s [cgofv] -f input_file_name\n", prog); + printf("\t-c add CFO [Default %f]\n", cfo); + printf("\t-g add AWGN with target SNR [Default off]\n"); + printf("\t-o offset [Default %d]\n", offset); + printf("\t-v srslte_verbose\n"); +} + +void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "cgofv")) != -1) { + switch (opt) { + case 'f': + input_file_name = argv[optind]; + break; + case 'c': + cfo = atof(argv[optind]); + break; + case 'g': + snr = atof(argv[optind]); + break; + case 'o': + offset = atoi(argv[optind]); + break; + case 'v': + srslte_verbose = SRSLTE_VERBOSE_DEBUG; + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +int main(int argc, char** argv) +{ + int ret = SRSLTE_ERROR; + int sf_idx = 0; + cf_t* fft_buffer = NULL; + _Complex float buffer[SFLEN]; // FLEN + fft_size + + srslte_filesource_t fsrc = {}; + uint32_t find_idx = 0; + srslte_sync_nbiot_t syncobj = {}; + srslte_ofdm_t ifft = {}; + srslte_cfo_t cfocorr = {}; + int fft_size = 0; + + input_file_name = NULL; + + parse_args(argc, argv); + + if (input_file_name != NULL) { + printf("Opening file...\n"); + if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { + fprintf(stderr, "Error opening file %s\n", input_file_name); + goto exit; + } + } + + fft_size = srslte_symbol_sz(SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL); + if (fft_size < 0) { + fprintf(stderr, "Invalid nof_prb=%d\n", SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL); + exit(-1); + } + + printf("SFLEN is %d samples\n", SFLEN); + fft_buffer = malloc(sizeof(cf_t) * SFLEN * 2); + if (!fft_buffer) { + perror("malloc"); + goto exit; + } + + memset(buffer, 0, sizeof(cf_t) * SFLEN); + + if (srslte_cfo_init(&cfocorr, SFLEN)) { + fprintf(stderr, "Error initiating CFO\n"); + goto exit; + } + // Set a CFO tolerance of approx 100 Hz + srslte_cfo_set_tol(&cfocorr, 100.0 / (15000.0 * fft_size)); + + // init synch object for a maximum SFLEN samples + if (srslte_sync_nbiot_init(&syncobj, SFLEN, SFLEN, fft_size)) { + fprintf(stderr, "Error initiating NPSS/NSSS\n"); + goto exit; + } + srslte_sync_nbiot_set_cfo_enable(&syncobj, true); + + if (input_file_name == NULL) { + // generating test sequence + if (srslte_ofdm_tx_init( + &ifft, SRSLTE_CP_NORM, buffer, &fft_buffer[offset], SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL)) { + fprintf(stderr, "Error creating iFFT object\n"); + goto exit; + } + srslte_ofdm_set_normalize(&ifft, true); + srslte_ofdm_set_freq_shift(&ifft, -SRSLTE_NBIOT_FREQ_SHIFT_FACTOR); + + // generate NPSS/NSSS signals + cf_t npss_signal[SRSLTE_NPSS_TOT_LEN]; + srslte_npss_generate(npss_signal); + srslte_npss_put_subframe( + &syncobj.npss, npss_signal, buffer, SRSLTE_NBIOT_DEFAULT_NUM_PRB_BASECELL, SRSLTE_NBIOT_DEFAULT_PRB_OFFSET); + + // Transform to OFDM symbols + memset(fft_buffer, 0, sizeof(cf_t) * SFLEN * 2); + srslte_ofdm_tx_sf(&ifft); + + srslte_ofdm_tx_free(&ifft); + } else { + // read samples from file + printf("Reading %d samples from file.\n", SFLEN); + int n = srslte_filesource_read(&fsrc, fft_buffer, SFLEN); + if (n < 0) { + fprintf(stderr, "Error reading samples\n"); + goto exit; + } + } + +#ifdef DUMP_SIGNALS + srslte_vec_save_file( + "npss_corr_seq_time.bin", syncobj.npss.npss_signal_time, SRSLTE_NPSS_CORR_FILTER_LEN * sizeof(cf_t)); + srslte_vec_save_file("npss_sf_time.bin", fft_buffer, SFLEN * sizeof(cf_t)); +#endif + + if (cfo > 0.0) { + float delta_freq = cfo / 15000 / SRSLTE_NBIOT_FFT_SIZE; + printf("Adding CFO with target: %.4f\n", delta_freq); + printf("WARNING: not working at the moment!\n"); + srslte_cfo_correct(&cfocorr, fft_buffer, fft_buffer, delta_freq); + } + + // add some noise to the signal + if (snr != -1.0) { + snr -= 10.0; + printf("Adding AWGN with target SNR: %.2fdB\n", snr); + float nstd = powf(10.0f, -snr / 20.0f); + srslte_ch_awgn_c(fft_buffer, fft_buffer, nstd, SFLEN); + } + + // look for NPSS signal + if (srslte_sync_nbiot_find(&syncobj, fft_buffer, 0, &find_idx) < 0) { + fprintf(stderr, "Error running srslte_sync_nbiot_find()\n"); + exit(-1); + } + + printf("NPPS with peak=%f found at: %d, offset: %d, SF starts at %d\n", syncobj.peak_value, find_idx, offset, sf_idx); + + // write results to file + write_to_file(); + +#ifdef DUMP_SIGNALS + srslte_vec_save_file("npss_find_conv_output_abs.bin", + syncobj.npss.conv_output_abs, + (SFLEN + SRSLTE_NPSS_CORR_FILTER_LEN - 1) * sizeof(float)); +#endif + + printf("Ok\n"); + + ret = SRSLTE_SUCCESS; + + // cleanup +exit: + if (input_file_name != NULL) { + srslte_filesource_free(&fsrc); + } + srslte_sync_nbiot_free(&syncobj); + srslte_cfo_free(&cfocorr); + + if (fft_buffer) { + free(fft_buffer); + } + + return ret; +} + +void write_to_file() +{ + srslte_filesink_t debug_fsink; + char fname[] = OUTPUT_FILENAME; + if (srslte_filesink_init(&debug_fsink, fname, SRSLTE_TEXT)) { + fprintf(stderr, "Error opening file %s\n", fname); + exit(-1); + } + + fprintf(debug_fsink.f, "%% %s : auto-generated file\n", OUTPUT_FILENAME); + fprintf(debug_fsink.f, "clear all;\n"); + fprintf(debug_fsink.f, "close all;\n"); + fprintf(debug_fsink.f, "set(0,'DefaultFigureWindowStyle','docked');\n\n"); + + // the correlation sequence + fprintf(debug_fsink.f, "len = %u;\n", SRSLTE_NPSS_CORR_FILTER_LEN); + fprintf(debug_fsink.f, "sig1=read_complex('npss_corr_seq_time.bin', len);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t=1:len;\n"); + fprintf(debug_fsink.f, "plot(t,real(sig1),t,imag(sig1));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Correlation sequence time-domain');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the generated subframe + fprintf(debug_fsink.f, "len = %u;\n", SFLEN); + fprintf(debug_fsink.f, "sig=read_complex('npss_sf_time.bin', len);\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "t= 1:len;\n"); + fprintf(debug_fsink.f, "plot(t,real(sig),t,imag(sig));\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Subframe time-domain');\n"); + fprintf(debug_fsink.f, "\n\n"); + + // the correlation output + fprintf(debug_fsink.f, "num_samples = %u;\n", SRSLTE_NPSS_CORR_FILTER_LEN + SFLEN - 1); + fprintf(debug_fsink.f, "sig = read_real('npss_find_conv_output_abs.bin', num_samples);\n"); + fprintf(debug_fsink.f, "t=1:num_samples;\n"); + fprintf(debug_fsink.f, "\n\n"); + fprintf(debug_fsink.f, "figure;\n"); + fprintf(debug_fsink.f, "plot(t,sig);\n"); + fprintf(debug_fsink.f, "xlabel('sample index');\n"); + fprintf(debug_fsink.f, "title('Convolution output absolute');\n"); + fprintf(debug_fsink.f, "ylabel('Auto-correlation magnitude');\n"); + fprintf(debug_fsink.f, "\n\n"); + + srslte_filesink_free(&debug_fsink); + printf("data written to %s\n", OUTPUT_FILENAME); +} diff --git a/lib/src/phy/ue/CMakeLists.txt b/lib/src/phy/ue/CMakeLists.txt index 496750c1f..7727ce8b9 100644 --- a/lib/src/phy/ue/CMakeLists.txt +++ b/lib/src/phy/ue/CMakeLists.txt @@ -20,3 +20,5 @@ file(GLOB SOURCES "*.c") add_library(srslte_ue OBJECT ${SOURCES}) + +add_subdirectory(test) \ No newline at end of file diff --git a/lib/src/phy/ue/test/CMakeLists.txt b/lib/src/phy/ue/test/CMakeLists.txt new file mode 100644 index 000000000..481f16b72 --- /dev/null +++ b/lib/src/phy/ue/test/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright 2013-2019 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE 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. +# +# srsLTE 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/. +# + +######################################################################## +# PROGRAM TO DEBUG PSS FROM USRP +######################################################################## + +add_executable(gen_ack_test gen_ack_test.c) +target_link_libraries(gen_ack_test srslte_phy) +add_test(gen_ack_test gen_ack_test) + +add_executable(pucch_resource_test pucch_resource_test.c) +target_link_libraries(pucch_resource_test srslte_phy) +add_test(pucch_resource_test pucch_resource_test) diff --git a/lib/src/phy/ue/test/gen_ack_test.c b/lib/src/phy/ue/test/gen_ack_test.c new file mode 100644 index 000000000..6a7b4d813 --- /dev/null +++ b/lib/src/phy/ue/test/gen_ack_test.c @@ -0,0 +1,161 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include + +#include "srslte/srslte.h" + +#define TESTASSERT(cond) \ + do { \ + if (!(cond)) { \ + printf("[%s][Line %d]. Fail at %s\n", __FUNCTION__, __LINE__, #cond); \ + return -1; \ + } \ + } while (false) + +int fdd_tests(uint32_t max_cc) +{ + srslte_ue_dl_t ue_dl = {}; + srslte_dl_sf_cfg_t sf_cfg_dl = {}; // This is used for TDD only + + uint32_t test_cnt = 0; + + // Force FDD + ue_dl.cell.frame_type = SRSLTE_FDD; + + for (uint32_t nof_cc = 1; nof_cc <= max_cc; nof_cc++) { + for (uint32_t nof_tb = 1; nof_tb <= SRSLTE_MAX_CODEWORDS; nof_tb++) { + for (uint32_t nof_active_cc = 1; nof_active_cc <= nof_cc; nof_active_cc++) { + for (uint32_t nof_active_tb = 1; nof_active_tb <= nof_tb; nof_active_tb++) { + srslte_pdsch_ack_t ack_info = {}; + ack_info.nof_cc = nof_cc; + ack_info.transmission_mode = nof_tb == 1 ? SRSLTE_TM1 : SRSLTE_TM4; + + // Check different modes? + ack_info.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS; + + for (uint32_t cc_idx = 0; cc_idx < nof_cc; cc_idx++) { + ack_info.cc[cc_idx].M = 1; // always 1 in FDD + ack_info.cc[cc_idx].m[0].present = cc_idx < nof_active_cc; + ack_info.cc[cc_idx].m[0].resource.n_cce = cc_idx + 1; + if (ack_info.cc[cc_idx].m[0].present) { + for (uint32_t j = 0; j < nof_tb; j++) { + ack_info.cc[cc_idx].m[0].value[j] = j < nof_active_tb ? 1 : 2; + } + } else { + memset(ack_info.cc[cc_idx].m[0].value, 2, SRSLTE_MAX_CODEWORDS); + } + } + + for (uint32_t sr_enabled = 0; sr_enabled < 2; sr_enabled++) { // 0: true, 1: false, otherwise: break + for (uint8_t cqi_enabled = 0; cqi_enabled < 2; cqi_enabled++) { + for (uint8_t simul_cqi_ack = 0; simul_cqi_ack < cqi_enabled + 1; simul_cqi_ack++) { + for (uint8_t pusch_enabled = 0; pusch_enabled < 2; pusch_enabled++) { + srslte_uci_data_t uci_data = {}; + + ack_info.is_pusch_available = (pusch_enabled > 0); + ack_info.simul_cqi_ack = (simul_cqi_ack > 0); + + // Generate ACK/NACK bits + srslte_uci_data_reset(&uci_data); + uci_data.value.scheduling_request = (sr_enabled > 0); + uci_data.cfg.cqi.data_enable = (cqi_enabled > 0); + + printf("FDD Test %d: TM=%d, CC=%d, nof_active_tb=%d, nof_active_cc=%d, sr_request=%s, cqi_data=%s, " + "simul_cqi_ack=%s, is_pusch=%s\n", + test_cnt++, + ack_info.transmission_mode + 1, + nof_cc, + nof_active_tb, + nof_active_cc, + sr_enabled ? "yes" : "no", + cqi_enabled ? "yes" : "no", + simul_cqi_ack ? "yes" : "no", + pusch_enabled ? "yes" : "no"); + + srslte_ue_dl_gen_ack(&ue_dl, &sf_cfg_dl, &ack_info, &uci_data); + + // Check output + if (nof_cc == 1) { + TESTASSERT(uci_data.cfg.ack[0].nof_acks == nof_active_tb); + } else if (uci_data.value.scheduling_request) { + TESTASSERT(uci_data.cfg.ack[0].nof_acks == 1); + } else if (cqi_enabled && !pusch_enabled) { + // No PUSCH, CSI and HARQ ACK collision + if (nof_active_cc == 1 && simul_cqi_ack) { + // CSI shall not be dropped + TESTASSERT(uci_data.cfg.cqi.data_enable); + + // Serving cell only HARQ ACK is multiplexed + TESTASSERT(uci_data.cfg.ack[0].nof_acks == nof_active_tb); + + // Other serving cells HARQ shall not be multiplexed + for (int i = 1; i < nof_cc; i++) { + TESTASSERT(uci_data.cfg.ack[i].nof_acks == 0); + } + } else { + // CSI shall be dropped + TESTASSERT(!uci_data.cfg.cqi.data_enable); + + // Acknowledgments as usual + for (int i = 0; i < nof_cc; i++) { + TESTASSERT(uci_data.cfg.ack[i].nof_acks == nof_tb); + } + } + } else { + for (int i = 0; i < nof_cc; i++) { + TESTASSERT(uci_data.cfg.ack[i].nof_acks == nof_tb); + } + } + uint32_t k = 0; + for (uint32_t i = 0; i < nof_cc; i++) { + TESTASSERT(uci_data.cfg.ack[i].ncce[0] == i + 1); + for (uint32_t j = 0; j < uci_data.cfg.ack[i].nof_acks; j++) { + TESTASSERT(uci_data.value.ack.ack_value[k++]); + } + } + TESTASSERT(k == srslte_uci_cfg_total_ack(&uci_data.cfg)); + TESTASSERT(uci_data.value.ack.ack_value[k] == 2); + } + } + } + } + } + } + } + } + return 0; +} + +int main(int argc, char** argv) +{ + + // Test only until Format1B - CS + TESTASSERT(fdd_tests(2) == 0); + + printf("Ok\n"); + exit(0); +} diff --git a/lib/src/phy/ue/test/pucch_resource_test.c b/lib/src/phy/ue/test/pucch_resource_test.c new file mode 100644 index 000000000..324cc2d5d --- /dev/null +++ b/lib/src/phy/ue/test/pucch_resource_test.c @@ -0,0 +1,165 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include + +#include "srslte/srslte.h" + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + printf("[%s][Line %d]. Fail at %s\n", __FUNCTION__, __LINE__, #cond); \ + return -1; \ + } \ + } + +int fdd_tests() +{ + srslte_cell_t cell; + srslte_pucch_cfg_t pucch_cfg; + srslte_uci_cfg_t uci_cfg; + srslte_uci_value_t uci_value; + + ZERO_OBJECT(cell); + cell.cp = SRSLTE_CP_NORM; + cell.frame_type = SRSLTE_FDD; + cell.nof_prb = 50; + + ZERO_OBJECT(pucch_cfg); + pucch_cfg.n_pucch_sr = 3; + pucch_cfg.N_pucch_1 = 7; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 2; j++) { + pucch_cfg.n1_pucch_an_cs[i][j] = j * 11 + i * 13; + } + } + ZERO_OBJECT(uci_value); + + // Format 1 + ZERO_OBJECT(uci_cfg); + uci_value.scheduling_request = true; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1); + TESTASSERT(pucch_cfg.n_pucch == pucch_cfg.n_pucch_sr); + + // Format 1A with and without SR + for (int i = 0; i < 2; i++) { + uci_value.scheduling_request = i == 0; + ZERO_OBJECT(uci_cfg); + uci_cfg.ack[0].nof_acks = 1; + uci_cfg.ack[0].ncce[0] = 13; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1A); + if (i == 0) { + TESTASSERT(pucch_cfg.n_pucch == pucch_cfg.n_pucch_sr); + } else { + TESTASSERT(pucch_cfg.n_pucch == uci_cfg.ack[0].ncce[0] + pucch_cfg.N_pucch_1); + } + } + + // Format 1B with and without SR, MIMO + pucch_cfg.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL; + for (int i = 0; i < 2; i++) { + uci_value.scheduling_request = i == 0; + uci_value.ack.ack_value[0] = 1; // To force a different resource than n_pucch_0 in case of CS incorrectly selected + uci_value.ack.ack_value[1] = 1; + ZERO_OBJECT(uci_cfg); + uci_cfg.ack[0].nof_acks = 2; + uci_cfg.ack[0].ncce[0] = 13; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1B); + if (i == 0) { + TESTASSERT(pucch_cfg.n_pucch == pucch_cfg.n_pucch_sr); + } else { + TESTASSERT(pucch_cfg.n_pucch == uci_cfg.ack[0].ncce[0] + pucch_cfg.N_pucch_1); + } + } + + // Format 1B-CS, no SR, 2 CA SISO + uci_value.scheduling_request = 0; + ZERO_OBJECT(uci_cfg); + pucch_cfg.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS; + uci_cfg.ack[0].nof_acks = 1; + uci_cfg.ack[1].nof_acks = 1; + uci_cfg.ack[0].ncce[0] = 13; + uci_cfg.ack[1].ncce[0] = 4; + + // Both on Pcell + + // ACK/ACK, n_pucch = n_pucch_1 + uci_value.ack.ack_value[0] = 1; + uci_value.ack.ack_value[1] = 1; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1B); + TESTASSERT(pucch_cfg.n_pucch == uci_cfg.ack[1].ncce[0] + pucch_cfg.N_pucch_1); + + // ACK/DTX, n_pucch = n_pucch_0 + uci_value.ack.ack_value[0] = 1; + uci_value.ack.ack_value[1] = 2; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1B); + TESTASSERT(pucch_cfg.n_pucch == uci_cfg.ack[0].ncce[0] + pucch_cfg.N_pucch_1); + + // Each on its serving cell, n_pucch_1 is explicit + uci_cfg.ack[1].grant_cc_idx = 1; + uci_cfg.ack[1].tpc_for_pucch = 3; + uci_value.ack.ack_value[0] = 1; + uci_value.ack.ack_value[1] = 1; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1B); + TESTASSERT(pucch_cfg.n_pucch == pucch_cfg.n1_pucch_an_cs[uci_cfg.ack[1].tpc_for_pucch][0]); + + // PCell scheduled on Scell + uci_cfg.ack[0].grant_cc_idx = 1; + uci_cfg.ack[0].tpc_for_pucch = 2; + uci_value.ack.ack_value[0] = 1; + uci_value.ack.ack_value[1] = 2; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1B); + TESTASSERT(pucch_cfg.n_pucch == pucch_cfg.n1_pucch_an_cs[uci_cfg.ack[0].tpc_for_pucch][0]); + + // MIMO has the same logic of resource selection, no need to test for now + + // Format 1B-CS with SR + ZERO_OBJECT(uci_cfg); + uci_value.scheduling_request = true; + uci_cfg.ack[0].nof_acks = 1; + uci_cfg.ack[1].nof_acks = 1; + srslte_ue_ul_pucch_resource_selection(&cell, &pucch_cfg, &uci_cfg, &uci_value); + TESTASSERT(pucch_cfg.format == SRSLTE_PUCCH_FORMAT_1B); + + return 0; +} + +int main(int argc, char** argv) +{ + + // Test only until Format1B - CS + TESTASSERT(fdd_tests() == 0); + + printf("Ok\n"); + exit(0); +} diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 10cc77485..8af9b6dc5 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -479,7 +479,7 @@ static int dci_blind_search(srslte_ue_dl_t* q, int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, - srslte_ue_dl_cfg_t* cfg, + srslte_ue_dl_cfg_t* dl_cfg, uint16_t rnti, srslte_dci_ul_t dci_ul[SRSLTE_MAX_DCI_MSG]) { @@ -497,7 +497,7 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t* q, uint32_t sf_idx = sf->tti % 10; uint32_t cfi = sf->cfi; - set_mi_value(q, sf, cfg); + set_mi_value(q, sf, dl_cfg); // Configure and run DCI blind search dci_blind_search_t search_space; @@ -512,12 +512,12 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t* q, current_ss->format = SRSLTE_DCI_FORMAT0; INFO("Searching UL C-RNTI in %d ue locations\n", search_space.nof_locations); - nof_msg = dci_blind_search(q, sf, rnti, current_ss, &cfg->dci_cfg, dci_msg); + nof_msg = dci_blind_search(q, sf, rnti, current_ss, &dl_cfg->cfg.dci, dci_msg); } // Unpack DCI messages for (uint32_t i = 0; i < nof_msg; i++) { - if (srslte_dci_msg_unpack_pusch(&q->cell, sf, &cfg->dci_cfg, &dci_msg[i], &dci_ul[i])) { + if (srslte_dci_msg_unpack_pusch(&q->cell, sf, &dl_cfg->cfg.dci, &dci_msg[i], &dci_ul[i])) { ERROR("Unpacking UL DCI\n"); return SRSLTE_ERROR; } @@ -533,13 +533,13 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t* q, // Blind search for SI/P/RA-RNTI static int find_dl_dci_type_siprarnti(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, - srslte_ue_dl_cfg_t* cfg, + srslte_ue_dl_cfg_t* dl_cfg, uint16_t rnti, srslte_dci_msg_t dci_msg[SRSLTE_MAX_DCI_MSG]) { int ret = 0; - srslte_dci_cfg_t* dci_cfg = &cfg->dci_cfg; + srslte_dci_cfg_t* dci_cfg = &dl_cfg->cfg.dci; // Configure and run DCI blind search dci_blind_search_t search_space; @@ -575,7 +575,7 @@ static int find_dl_dci_type_crnti(srslte_ue_dl_t* q, uint32_t sf_idx = sf->tti % 10; uint32_t cfi = sf->cfi; - srslte_dci_cfg_t* dci_cfg = &cfg->dci_cfg; + srslte_dci_cfg_t* dci_cfg = &cfg->cfg.dci; // Search UE-specific search space if (q->pregen_rnti == rnti) { @@ -619,25 +619,25 @@ static int find_dl_dci_type_crnti(srslte_ue_dl_t* q, int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, - srslte_ue_dl_cfg_t* cfg, + srslte_ue_dl_cfg_t* dl_cfg, uint16_t rnti, srslte_dci_dl_t dci_dl[SRSLTE_MAX_DCI_MSG]) { - set_mi_value(q, sf, cfg); + set_mi_value(q, sf, dl_cfg); srslte_dci_msg_t dci_msg[SRSLTE_MAX_DCI_MSG]; int nof_msg = 0; if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || SRSLTE_RNTI_ISRAR(rnti)) { - nof_msg = find_dl_dci_type_siprarnti(q, sf, cfg, rnti, dci_msg); + nof_msg = find_dl_dci_type_siprarnti(q, sf, dl_cfg, rnti, dci_msg); } else { - nof_msg = find_dl_dci_type_crnti(q, sf, cfg, rnti, dci_msg); + nof_msg = find_dl_dci_type_crnti(q, sf, dl_cfg, rnti, dci_msg); } // Unpack DCI messages for (uint32_t i = 0; i < nof_msg; i++) { - if (srslte_dci_msg_unpack_pdsch(&q->cell, sf, &cfg->dci_cfg, &dci_msg[i], &dci_dl[i])) { + if (srslte_dci_msg_unpack_pdsch(&q->cell, sf, &dl_cfg->cfg.dci, &dci_msg[i], &dci_dl[i])) { ERROR("Unpacking DL DCI\n"); return SRSLTE_ERROR; } @@ -651,7 +651,7 @@ int srslte_ue_dl_dci_to_pdsch_grant(srslte_ue_dl_t* q, srslte_dci_dl_t* dci, srslte_pdsch_grant_t* grant) { - return srslte_ra_dl_dci_to_grant(&q->cell, sf, cfg->cfg.tm, cfg->pdsch_use_tbs_index_alt, dci, grant); + return srslte_ra_dl_dci_to_grant(&q->cell, sf, cfg->cfg.tm, cfg->cfg.pdsch.use_tbs_index_alt, dci, grant); } int srslte_ue_dl_decode_pdsch(srslte_ue_dl_t* q, @@ -927,157 +927,176 @@ void srslte_ue_dl_gen_cqi_aperiodic(srslte_ue_dl_t* q, } } -// Table 7.3-1 -static const uint32_t multiple_acknack[10][2] = { - {0, 0}, {1, 1}, {1, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 1}}; - -/* UE downlink procedure for reporting ACK/NACK, Section 7.3 36.213 +/* UE downlink procedure for reporting HARQ-ACK bits in FDD, Section 7.3 36.213 */ -void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, - srslte_dl_sf_cfg_t* sf, - srslte_pdsch_ack_t* ack_info, - srslte_uci_data_t* uci_data) +static void gen_ack_fdd(srslte_pdsch_ack_t* ack_info, srslte_uci_data_t* uci_data) { - uint32_t V_dai_dl = 0; - - bool is_tdd_mode16 = sf->tdd_config.sf_config >= 1 && sf->tdd_config.sf_config <= 6; - uint32_t nof_tb = 1; if (ack_info->transmission_mode > SRSLTE_TM2) { nof_tb = SRSLTE_MAX_CODEWORDS; } - // Implementation 3GPP 36.213 V10.13.0. Section 7.3. 2nd Clause. - if (q->cell.frame_type == SRSLTE_FDD) { - if (ack_info->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS && - uci_data->value.scheduling_request && !ack_info->is_pusch_available) { - for (uint32_t cc_idx = 0; cc_idx < ack_info->nof_cc; cc_idx++) { - uint32_t dtx_count = 0; - bool bundle_spatial = true; - + // Second clause: When 2 CC are configured with PUCCH CS mode and SR is also requested, bundle spatial codewords + if (ack_info->nof_cc == 2 && uci_data->value.scheduling_request == true && + ack_info->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS) { + for (uint32_t cc_idx = 0; cc_idx < ack_info->nof_cc; cc_idx++) { + if (ack_info->cc[cc_idx].m[0].present) { + uci_data->value.ack.ack_value[cc_idx] = 1; for (uint32_t tb = 0; tb < nof_tb; tb++) { - if (ack_info->cc[cc_idx].m[0].present && ack_info->cc[cc_idx].m[0].value[tb] != 2) { - if (ack_info->cc[cc_idx].m[0].value[tb] != 1) { - bundle_spatial = false; - } - if (cc_idx != 0) { - uci_data->cfg.ack.has_scell_ack = true; - } - } else { - dtx_count++; + if (ack_info->cc[cc_idx].m[0].value[tb] != 2) { + uci_data->value.ack.ack_value[cc_idx] &= ack_info->cc[cc_idx].m[0].value[tb]; } } - uci_data->value.ack.ack_value[cc_idx] = (uint8_t)((bundle_spatial && dtx_count != nof_tb) ? 1 : 0); + } else { + uci_data->value.ack.ack_value[cc_idx] = 2; } + } + for (uint32_t i = 0; i < 2; i++) { + uci_data->cfg.ack[i].nof_acks = 1; + } + } else { + // By default, in FDD we just pass through all HARQ-ACK bits + uint32_t tb_count = 0; + uint32_t tb_count_cc0 = 0; + uint32_t n = 0; + for (uint32_t cc_idx = 0; cc_idx < ack_info->nof_cc; cc_idx++) { + for (uint32_t tb = 0; tb < nof_tb; tb++, n++) { + uci_data->value.ack.ack_value[n] = ack_info->cc[cc_idx].m[0].value[tb]; + if (ack_info->cc[cc_idx].m[0].present && ack_info->cc[cc_idx].m[0].value[tb] != 2) { + tb_count++; + } - uci_data->cfg.ack.nof_acks = ack_info->nof_cc; - uci_data->cfg.ack.tdd_ack_M = 1; - return; - - } else if ((ack_info->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS && - ack_info->is_pusch_available) || - ack_info->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3) { - uint32_t tb_count = 0; - uint32_t n = 0; - for (uint32_t cc_idx = 0; cc_idx < ack_info->nof_cc; cc_idx++) { - for (uint32_t tb = 0; tb < nof_tb; tb++, n++) { - uci_data->value.ack.ack_value[n] = ack_info->cc[cc_idx].m[0].value[tb]; - if (ack_info->cc[cc_idx].m[0].present && ack_info->cc[cc_idx].m[0].value[tb] != 2) { - tb_count++; - } + // Save primary cell number of TB + if (cc_idx == 0) { + tb_count_cc0 = tb_count; } } - uci_data->cfg.ack.nof_acks = (tb_count != 0) ? n : 0; - return; } - } + if (ack_info->nof_cc == 1) { + // If only 1 configured cell, report 1 or 2 bits depending on number of detected TB + uci_data->cfg.ack[0].nof_acks = tb_count; + } else if (uci_data->cfg.cqi.data_enable && !ack_info->is_pusch_available) { + // 3GPP 36.213 R.15 Section 10.1.1: + // For FDD or for FDD-TDD and primary cell frame structure type 1 and for a UE that is configured with more than + // one serving cell, in case of collision between a periodic CSI report and an HARQ-ACK in a same subframe without + // PUSCH, + if (tb_count_cc0 == tb_count && ack_info->simul_cqi_ack) { + // - if the parameter simultaneousAckNackAndCQI provided by higher layers is set TRUE and if the HARQ-ACK + // corresponds to a PDSCH transmission or PDCCH/EPDCCH indicating downlink SPS release only on the + // primary cell, then the periodic CSI report is multiplexed with HARQ-ACK on PUCCH using PUCCH format 2/2a/2b + uci_data->cfg.ack[0].nof_acks = tb_count_cc0; +#if 0 + } else if (ack_info->simul_cqi_ack_pucch3 && + tb_count + srslte_cqi_size(&uci_data->cfg.cqi) + uci_data->value.scheduling_request ? 1 : 0 <= 22) { + // - else if the UE is configured with PUCCH format 3 and if the parameter simultaneousAckNackAndCQI-Format3- + // r11 provided by higher layers is set TRUE, and if PUCCH resource is determined according to subclause + // 10.1.2.2.2, and + // - if the total number of bits in the subframe corresponding to HARQ-ACKs, SR (if any), and the CSI is not + // larger than 22 or + // - if the total number of bits in the subframe corresponding to spatially bundled HARQ-ACKs, SR (if any), and + // the CSI is not larger than 22 then the periodic CSI report is multiplexed with HARQ-ACK on PUCCH using + // the determined PUCCH format 3 resource according to [4] + for (int i = 0; i < ack_info->nof_cc; i++) { + uci_data->cfg.ack[i].nof_acks = (tb_count != 0) ? nof_tb : 0; + } +#endif + } else { + // - otherwise, CSI is dropped + uci_data->cfg.cqi.data_enable = false; - // Calculate U_dai and count number of ACK for this subframe by spatial bundling across codewords - uint32_t nof_pos_acks = 0; - uint32_t nof_total_acks = 0; - uint32_t U_dai = 0; - for (uint32_t cc_idx = 0; cc_idx < ack_info->nof_cc; cc_idx++) { - for (uint32_t i = 0; i < ack_info->cc[cc_idx].M; i++) { - bool bundle_spatial = false; - bool first_bundle = true; - for (uint32_t j = 0; j < nof_tb; j++) { - if (ack_info->cc[cc_idx].m[i].present) { - if (first_bundle) { - bundle_spatial = ack_info->cc[cc_idx].m[i].value[j] == 1; - U_dai++; - first_bundle = false; - } else { - bundle_spatial &= ack_info->cc[cc_idx].m[i].value[j] == 1; - } - if (bundle_spatial) { - nof_pos_acks++; - } - if (ack_info->cc[cc_idx].m[i].value[j] != 2) { - nof_total_acks++; - } + // + for (int i = 0; i < 2; i++) { + uci_data->cfg.ack[i].nof_acks = (tb_count != 0) ? nof_tb : 0; } } + } else { + // For 2 or more configured cells, report nof_tb per carrier except if there are no HARQ-ACK bits to report, in + // which case we set to 0 + for (int i = 0; i < 2; i++) { + uci_data->cfg.ack[i].nof_acks = (tb_count != 0) ? nof_tb : 0; + } } } - for (uint32_t cc_idx = 0; cc_idx < ack_info->nof_cc; cc_idx++) { + // n_cce values are just copied + for (uint32_t i = 0; i < ack_info->nof_cc; i++) { + uci_data->cfg.ack[i].ncce[0] = ack_info->cc[i].m[0].resource.n_cce; + uci_data->cfg.ack[i].grant_cc_idx = ack_info->cc[i].m[0].resource.grant_cc_idx; + uci_data->cfg.ack[i].tpc_for_pucch = ack_info->cc[i].m[0].resource.tpc_for_pucch; + } +} + +// Table 7.3-1 +static const uint32_t multiple_acknack[10][2] = { + {0, 0}, {1, 1}, {1, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 1}}; + +/* UE downlink procedure for reporting HARQ-ACK bits in TDD, Section 7.3 36.213 + */ +static void gen_ack_tdd(bool is_tdd_mode16, srslte_pdsch_ack_t* ack_info, srslte_uci_data_t* uci_data) +{ + uint32_t V_dai_dl = 0; + + uint32_t nof_tb = 1; + if (ack_info->transmission_mode > SRSLTE_TM2) { + nof_tb = SRSLTE_MAX_CODEWORDS; + } + + if (ack_info->nof_cc > 1) { + fprintf(stderr, "Error generating HARQ-ACK bits. Only 1 CC is supported in TDD\n"); + } - // Arrange bits for FDD or TDD Bundling or Multiplexing - srslte_pdsch_ack_cc_t* ack_value = &ack_info->cc[cc_idx]; + // Arrange bits for FDD or TDD Bundling or Multiplexing. + srslte_pdsch_ack_cc_t* ack_value = &ack_info->cc[0]; + srslte_uci_cfg_ack_t* ack_cfg = &uci_data->cfg.ack[0]; - uint32_t min_k = 10; + uint32_t min_k = 10; - if (ack_info->cc[cc_idx].M > 0) { + if (ack_value->M > 0) { - uci_data->cfg.ack.tdd_ack_M = ack_value->M; + ack_cfg->tdd_ack_M = ack_value->M; - // ACK/NACK bundling or multiplexing and M=1 - if (ack_info->tdd_ack_bundle || ack_value->M == 1) { - for (uint32_t tb = 0; tb < nof_tb; tb++) { - bool first_in_bundle = true; - for (uint32_t k = 0; k < ack_value->M; k++) { - if (ack_value->m[k].present && ack_value->m[k].value[tb] != 2) { - uci_data->cfg.ack.has_scell_ack |= (cc_idx != 0); // If a grant is detected in an scell - - // Bundle on time domain - if (first_in_bundle) { - uci_data->value.ack.ack_value[nof_tb * cc_idx + tb] = ack_value->m[k].value[tb]; - first_in_bundle = false; - } else { - uci_data->value.ack.ack_value[nof_tb * cc_idx + tb] = (uint8_t)( - ((uci_data->value.ack.ack_value[nof_tb * cc_idx + tb] == 1) & (ack_value->m[k].value[tb])) ? 1 : 0); - } - // V_dai_dl is for the one with lowest k value - if (ack_value->m[k].k < min_k || q->cell.frame_type == SRSLTE_FDD) { - min_k = ack_value->m[k].k; - V_dai_dl = ack_value->m[k].resource.v_dai_dl + 1; // Table 7.3-X - if (cc_idx == 0) { - uci_data->cfg.ack.ncce[0] = ack_info->cc[cc_idx].m[k].resource.n_cce; - uci_data->cfg.ack.tdd_ack_m = k; - } - } + // ACK/NACK bundling or multiplexing and M=1 + if (!ack_info->tdd_ack_multiplex || ack_value->M == 1) { + for (uint32_t tb = 0; tb < nof_tb; tb++) { + bool first_in_bundle = true; + for (uint32_t k = 0; k < ack_value->M; k++) { + if (ack_value->m[k].present && ack_value->m[k].value[tb] != 2) { + // Bundle on time domain + if (first_in_bundle) { + uci_data->value.ack.ack_value[tb] = ack_value->m[k].value[tb]; + first_in_bundle = false; + } else { + uci_data->value.ack.ack_value[tb] = + (uint8_t)(((uci_data->value.ack.ack_value[tb] == 1) & (ack_value->m[k].value[tb])) ? 1 : 0); + } + // V_dai_dl is for the one with lowest k value + if (ack_value->m[k].k < min_k) { + min_k = ack_value->m[k].k; + V_dai_dl = ack_value->m[k].resource.v_dai_dl + 1; // Table 7.3-X + ack_cfg->ncce[0] = ack_value->m[k].resource.n_cce; + ack_cfg->tdd_ack_m = k; } } } - // ACK/NACK multiplexing and M > 1 - } else { - for (uint32_t k = 0; k < ack_value->M; k++) { - // Bundle spatial domain - bool spatial_ack = true; - for (uint32_t i = 0; i < nof_tb; i++) { - if (ack_value->m[k].value[i] != 2) { - spatial_ack &= (ack_value->m[k].value[i] == 1); - } + } + // ACK/NACK multiplexing and M > 1 + } else { + for (uint32_t k = 0; k < ack_value->M; k++) { + // Bundle spatial domain + bool spatial_ack = true; + for (uint32_t i = 0; i < nof_tb; i++) { + if (ack_value->m[k].value[i] != 2) { + spatial_ack &= (ack_value->m[k].value[i] == 1); } - // In multiplexing for pusch, sort them accordingly - if (ack_value->m[k].present) { - uint32_t p = k; - if (q->cell.frame_type == SRSLTE_TDD && ack_info->is_pusch_available && ack_info->is_grant_available) { - p = ack_value->m[k].resource.v_dai_dl; - } - uci_data->value.ack.ack_value[ack_value->M * cc_idx + p] = (uint8_t)(spatial_ack ? 1 : 0); - uci_data->cfg.ack.ncce[ack_value->M * cc_idx + p] = ack_info->cc[cc_idx].m[k].resource.n_cce; + } + // In multiplexing for pusch, sort them accordingly + if (ack_value->m[k].present) { + uint32_t p = k; + if (ack_info->is_pusch_available && ack_info->is_grant_available) { + p = ack_value->m[k].resource.v_dai_dl; } + uci_data->value.ack.ack_value[p] = (uint8_t)(spatial_ack ? 1 : 0); + ack_cfg->ncce[p] = ack_value->m[k].resource.n_cce; } } } @@ -1085,17 +1104,43 @@ void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, bool missing_ack = false; + // Calculate U_dai and count number of ACK for this subframe by spatial bundling across codewords + uint32_t nof_pos_acks = 0; + uint32_t U_dai = 0; + uint32_t nof_total_acks = 0; + for (uint32_t i = 0; i < ack_value->M; i++) { + bool bundle_spatial = false; + bool first_bundle = true; + for (uint32_t j = 0; j < nof_tb; j++) { + if (ack_value->m[i].present) { + if (first_bundle) { + bundle_spatial = ack_value->m[i].value[j] == 1; + U_dai++; + first_bundle = false; + } else { + bundle_spatial &= ack_value->m[i].value[j] == 1; + } + if (bundle_spatial) { + nof_pos_acks++; + } + if (ack_value->m[i].value[j] != 2) { + nof_total_acks++; + } + } + } + } + // For TDD PUSCH - if (q->cell.frame_type == SRSLTE_TDD && is_tdd_mode16) { + if (is_tdd_mode16) { ack_info->V_dai_ul++; // Table 7.3-x - uci_data->cfg.ack.tdd_is_bundling = ack_info->tdd_ack_bundle; + ack_cfg->tdd_is_multiplex = ack_info->tdd_ack_multiplex; // Bundling or multiplexing and M=1 - if (ack_info->tdd_ack_bundle || ack_info->cc[0].M == 1) { + if (!ack_info->tdd_ack_multiplex || ack_info->cc[0].M == 1) { // 1 or 2 ACK/NACK bits - uci_data->cfg.ack.nof_acks = nof_tb; + ack_cfg->nof_acks = nof_tb; // Determine if there is any missing ACK/NACK in the set and N_bundle value @@ -1103,7 +1148,7 @@ void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, if (!ack_info->is_pusch_available) { if ((V_dai_dl != (U_dai - 1) % 4 + 1 && U_dai > 0) || U_dai == 0) { // In ul procedure 10.2, skip ACK/NACK in bundling PUCCH - uci_data->cfg.ack.nof_acks = 0; + ack_cfg->nof_acks = 0; if (U_dai > 0) { missing_ack = true; } @@ -1112,30 +1157,30 @@ void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, } else if (ack_info->is_grant_available) { if (ack_info->V_dai_ul != (U_dai - 1) % 4 + 1) { bzero(uci_data->value.ack.ack_value, nof_tb); - uci_data->cfg.ack.N_bundle = ack_info->V_dai_ul + 2; + ack_cfg->N_bundle = ack_info->V_dai_ul + 2; } else { - uci_data->cfg.ack.N_bundle = ack_info->V_dai_ul; + ack_cfg->N_bundle = ack_info->V_dai_ul; } // do not transmit case if (ack_info->V_dai_ul == 4 && U_dai == 0) { - uci_data->cfg.ack.nof_acks = 0; + ack_cfg->nof_acks = 0; } // Transmitting on PUSCH not based on grant } else { if (V_dai_dl != (U_dai - 1) % 4 + 1 && U_dai > 0) { bzero(uci_data->value.ack.ack_value, nof_tb); } - uci_data->cfg.ack.N_bundle = U_dai; + ack_cfg->N_bundle = U_dai; // do not transmit case if (U_dai == 0) { - uci_data->cfg.ack.nof_acks = 0; + ack_cfg->nof_acks = 0; } } // In PUSCH and MIMO, nack 2nd codeword if not received, in PUCCH do not transmit - if (nof_tb == 2 && uci_data->value.ack.ack_value[1] == 2 && uci_data->cfg.ack.nof_acks == 2) { + if (nof_tb == 2 && uci_data->value.ack.ack_value[1] == 2 && ack_cfg->nof_acks == 2) { if (!ack_info->is_pusch_available) { - uci_data->cfg.ack.nof_acks = 1; + ack_cfg->nof_acks = 1; } else { uci_data->value.ack.ack_value[1] = 0; } @@ -1147,15 +1192,15 @@ void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, if (ack_info->is_grant_available) { // Do not transmit if... if (!(ack_info->V_dai_ul == 4 && U_dai == 0)) { - uci_data->cfg.ack.nof_acks = ack_info->V_dai_ul; + ack_cfg->nof_acks = ack_info->V_dai_ul; } } else { - uci_data->cfg.ack.nof_acks = ack_info->cc[0].M; + ack_cfg->nof_acks = ack_info->cc[0].M; } // Set DTX bits to NACKs uint32_t count_acks = 0; - for (uint32_t i = 0; i < uci_data->cfg.ack.nof_acks; i++) { + for (uint32_t i = 0; i < ack_cfg->nof_acks; i++) { if (uci_data->value.ack.ack_value[i] == 2) { uci_data->value.ack.ack_value[i] = 0; } else { @@ -1163,26 +1208,19 @@ void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, } } if (!count_acks) { - uci_data->cfg.ack.nof_acks = 0; + ack_cfg->nof_acks = 0; } } else { - uci_data->cfg.ack.nof_acks = ack_info->cc[0].M; + ack_cfg->nof_acks = ack_info->cc[0].M; } } } else { - if (q->cell.frame_type == SRSLTE_TDD) { // And subframe config 0 - uci_data->cfg.ack.N_bundle = 1; - } - uci_data->cfg.ack.nof_acks = nof_total_acks; - } - - // If no pending ACK/NACK - if (uci_data->cfg.ack.nof_acks == 0) { - return; + ack_cfg->N_bundle = 1; + ack_cfg->nof_acks = nof_total_acks; } // Multiple ACK/NACK responses with SR and CQI - if (q->cell.frame_type == SRSLTE_TDD && uci_data->cfg.ack.nof_acks && !ack_info->is_pusch_available && + if (ack_cfg->nof_acks && !ack_info->is_pusch_available && (uci_data->value.scheduling_request || ((uci_data->cfg.cqi.data_enable || uci_data->cfg.cqi.ri_len) && ack_info->simul_cqi_ack))) { if (missing_ack) { @@ -1193,7 +1231,23 @@ void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, uci_data->value.ack.ack_value[0] = multiple_acknack[nof_pos_acks][0]; uci_data->value.ack.ack_value[1] = multiple_acknack[nof_pos_acks][1]; } - uci_data->cfg.ack.nof_acks = 2; + ack_cfg->nof_acks = 2; + } +} + +/* UE downlink procedure for reporting ACK/NACK, Section 7.3 36.213 + */ +void srslte_ue_dl_gen_ack(srslte_ue_dl_t* q, + srslte_dl_sf_cfg_t* sf, + srslte_pdsch_ack_t* ack_info, + srslte_uci_data_t* uci_data) +{ + + if (q->cell.frame_type == SRSLTE_FDD) { + gen_ack_fdd(ack_info, uci_data); + } else { + bool is_tdd_mode16 = sf->tdd_config.sf_config >= 1 && sf->tdd_config.sf_config <= 6; + gen_ack_tdd(is_tdd_mode16, ack_info, uci_data); } } diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index c91bc22b4..5fa17f6e6 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -35,7 +35,7 @@ #define MAX_TIME_OFFSET 128 -#define TRACK_MAX_LOST 20 +#define TRACK_MAX_LOST 10 #define TRACK_FRAME_SIZE 32 #define FIND_NOF_AVG_FRAMES 4 @@ -398,7 +398,7 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) srslte_sync_set_threshold(&q->sfind, 3.0); srslte_sync_set_em_alpha(&q->strack, 0.0); - srslte_sync_set_threshold(&q->strack, 1.2); + srslte_sync_set_threshold(&q->strack, 1.5); } // When cell is unknown, do CP CFO correction @@ -635,7 +635,8 @@ static int track_peak_ok(srslte_ue_sync_t* q, uint32_t track_idx) q->peak_idx = q->sf_len/2 + q->last_sample_offset; q->frame_ok_cnt++; - + q->frame_no_cnt = 0; + return 1; } diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 0d0ad995d..db5de765d 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -385,7 +385,7 @@ float srslte_ue_ul_pucch_power(srslte_ue_ul_t* q, srslte_ue_ul_cfg_t* cfg, srslt float h; int n_cqi = srslte_cqi_size(&uci_cfg->cqi); - int n_harq = uci_cfg->ack.nof_acks; + int n_harq = srslte_uci_cfg_total_ack(uci_cfg); if (format <= SRSLTE_PUCCH_FORMAT_1B) { h = 0; @@ -487,15 +487,16 @@ get_format(srslte_pucch_cfg_t* cfg, srslte_uci_cfg_t* uci_cfg, srslte_uci_value_ if (!uci_cfg->cqi.data_enable && uci_cfg->cqi.ri_len == 0) { // PUCCH Format 3 condition specified in: // 3GPP 36.213 10.1.2.2.2 PUCCH format 3 HARQ-ACK procedure - if (cfg->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3 && uci_cfg->ack.has_scell_ack) { + if (cfg->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3 && + srslte_uci_cfg_total_ack(uci_cfg) > 1) { format = SRSLTE_PUCCH_FORMAT_3; } // 1-bit ACK + optional SR - else if (uci_cfg->ack.nof_acks == 1) { + else if (srslte_uci_cfg_total_ack(uci_cfg) == 1) { format = SRSLTE_PUCCH_FORMAT_1A; } // 2-bit ACK + optional SR - else if (uci_cfg->ack.nof_acks >= 2) { + else if (srslte_uci_cfg_total_ack(uci_cfg) >= 2 && srslte_uci_cfg_total_ack(uci_cfg) <= 4) { format = SRSLTE_PUCCH_FORMAT_1B; // with channel selection if > 2 } // If UCI value is provided, use SR signal only, otherwise SR request opportunity @@ -503,52 +504,79 @@ get_format(srslte_pucch_cfg_t* cfg, srslte_uci_cfg_t* uci_cfg, srslte_uci_value_ if (uci_value->scheduling_request) { format = SRSLTE_PUCCH_FORMAT_1; } + } else if (uci_cfg->is_scheduling_request_tti) { + format = SRSLTE_PUCCH_FORMAT_1; } else { - if (uci_cfg->is_scheduling_request_tti) { - format = SRSLTE_PUCCH_FORMAT_1; - } + fprintf(stderr, + "Error selecting PUCCH format: Unsupported number of ACK bits %d\n", + srslte_uci_cfg_total_ack(uci_cfg)); } } // CQI data else { // CQI and no ack - if (uci_cfg->ack.nof_acks == 0) { + if (srslte_uci_cfg_total_ack(uci_cfg) == 0) { format = SRSLTE_PUCCH_FORMAT_2; } // CQI + 1-bit ACK - else if (uci_cfg->ack.nof_acks == 1 && SRSLTE_CP_ISNORM(cp)) { + else if (srslte_uci_cfg_total_ack(uci_cfg) == 1 && SRSLTE_CP_ISNORM(cp)) { format = SRSLTE_PUCCH_FORMAT_2A; } // CQI + 2-bit ACK - else if (uci_cfg->ack.nof_acks == 2) { + else if (srslte_uci_cfg_total_ack(uci_cfg) == 2) { format = SRSLTE_PUCCH_FORMAT_2B; } // CQI + 2-bit ACK + cyclic prefix - else if (uci_cfg->ack.nof_acks == 1 && SRSLTE_CP_ISEXT(cp)) { + else if (srslte_uci_cfg_total_ack(uci_cfg) == 1 && SRSLTE_CP_ISEXT(cp)) { format = SRSLTE_PUCCH_FORMAT_2B; } } return format; } -// n_pucch and b0b1 selection for CA, tables 10.1.2.2.1-3 to -5 -static uint32_t -get_npucch_cs(srslte_pucch_cfg_t* cfg, uint32_t n_cce, srslte_uci_cfg_t* uci_cfg, srslte_uci_value_t* uci_value) +// Selection of n_pucch for PUCCH Format 1a and 1b with channel selection for 1 and 2 CC +static uint32_t get_npucch_cs(srslte_pucch_cfg_t* cfg, srslte_uci_cfg_t* uci_cfg, srslte_uci_value_t* uci_value) { - uint32_t n_pucch = 0; - uint8_t* b = uci_value->ack.ack_value; + uint32_t n_pucch = 0; + uint8_t* b = uci_value->ack.ack_value; + uint32_t n_pucch_i[4] = {}; + + // Determine the 4 PUCCH resources n_pucch_j associated with HARQ-ACK(j) + uint32_t k = 0; + for (int i = 0; i < 2; i++) { + // If grant has been scheduled in PCell + if (uci_cfg->ack[i].grant_cc_idx == 0) { + for (uint32_t j = 0; j < uci_cfg->ack[i].nof_acks; j++) { + if (k < 4) { + n_pucch_i[k++] = uci_cfg->ack[i].ncce[0] + cfg->N_pucch_1 + j; + } else { + fprintf(stderr, "get_npucch_cs(): Too many ack bits\n"); + } + } + } else { + for (uint32_t j = 0; j < uci_cfg->ack[i].nof_acks; j++) { + if (k < 4) { + n_pucch_i[k++] = cfg->n1_pucch_an_cs[uci_cfg->ack[i].tpc_for_pucch % 4][j]; + } else { + fprintf(stderr, "get_npucch_cs(): Too many ack bits\n"); + } + } + } + } - switch (uci_cfg->ack.nof_acks) { + // Do resource selection and bit mapping according to tables 10.1.2.2.1-3, 10.1.2.2.1-4 and 10.1.2.2.1-5 + switch (srslte_uci_cfg_total_ack(uci_cfg)) { case 1: - n_pucch = n_cce + cfg->N_pucch_1; + // 1-bit is Format1A always + n_pucch = n_pucch_i[0]; break; case 2: if (b[1] != 1) { /* n_pucch1_0 */ - n_pucch = n_cce + cfg->N_pucch_1; + n_pucch = n_pucch_i[0]; } else { /* n_pucch1_1 */ - n_pucch = cfg->n1_pucch_an_cs[cfg->tpc_for_pucch % 4][0]; + n_pucch = n_pucch_i[1]; } if (b[0] == 1) { b[0] = 1; @@ -561,13 +589,13 @@ get_npucch_cs(srslte_pucch_cfg_t* cfg, uint32_t n_cce, srslte_uci_cfg_t* uci_cfg case 3: if (b[0] != 1 && b[1] != 1) { /* n_pucch1_2 */ - n_pucch = cfg->n1_pucch_an_cs[cfg->tpc_for_pucch % 4][0]; + n_pucch = n_pucch_i[2]; } else if (b[2] == 1) { /* n_pucch1_1 */ - n_pucch = cfg->n1_pucch_an_cs[cfg->tpc_for_pucch % 4][0]; + n_pucch = n_pucch_i[1]; } else { /* n_pucch1_0 */ - n_pucch = n_cce + cfg->N_pucch_1; + n_pucch = n_pucch_i[0]; } if (b[0] != 1 && b[1] != 1 && b[2] != 1) { b[0] = 0; @@ -586,16 +614,16 @@ get_npucch_cs(srslte_pucch_cfg_t* cfg, uint32_t n_cce, srslte_uci_cfg_t* uci_cfg case 4: if (b[2] != 1 && b[3] != 1) { /* n_pucch1_0 */ - n_pucch = n_cce + cfg->N_pucch_1; + n_pucch = n_pucch_i[0]; } else if (b[1] == 1 && b[2] == 1) { /* n_pucch1_1 */ - n_pucch = n_cce + cfg->N_pucch_1 + 1; + n_pucch = n_pucch_i[1]; } else if (b[0] == 1) { /* n_pucch1_2 */ - n_pucch = cfg->n1_pucch_an_cs[cfg->tpc_for_pucch % 4][0]; + n_pucch = n_pucch_i[2]; } else { /* n_pucch1_3 */ - n_pucch = cfg->n1_pucch_an_cs[cfg->tpc_for_pucch % 4][1]; + n_pucch = n_pucch_i[3]; } if (b[2] != 1 && b[3] != 1) { /* n_pucch1_0 */ @@ -651,7 +679,7 @@ static void set_b01(uint8_t* b, uint8_t x) static uint32_t get_npucch_tdd(uint32_t n_pucch[4], srslte_uci_cfg_t* uci_cfg, srslte_uci_value_t* uci_value) { uint8_t* b = uci_value->ack.ack_value; - switch (uci_cfg->ack.nof_acks) { + switch (uci_cfg->ack[0].nof_acks) { case 1: return n_pucch[0]; case 2: @@ -673,7 +701,7 @@ static uint32_t get_npucch_tdd(uint32_t n_pucch[4], srslte_uci_cfg_t* uci_cfg, s } break; case 3: - uci_cfg->ack.nof_acks = 2; + uci_cfg->ack[0].nof_acks = 2; if (is_ack(b[0]) && is_ack(b[1]) && is_ack(b[2])) { set_b01(b, 3); return n_pucch[2]; @@ -707,7 +735,7 @@ static uint32_t get_npucch_tdd(uint32_t n_pucch[4], srslte_uci_cfg_t* uci_cfg, s } break; case 4: - uci_cfg->ack.nof_acks = 2; + uci_cfg->ack[0].nof_acks = 2; if (is_ack(b[0]) && is_ack(b[1]) && is_ack(b[2]) && is_ack(b[3])) { set_b01(b, 3); return n_pucch[1]; @@ -800,49 +828,55 @@ get_npucch(srslte_pucch_cfg_t* cfg, srslte_uci_cfg_t* uci_cfg, srslte_uci_value_ { uint32_t n_pucch_res = 0; + if (uci_cfg->is_scheduling_request_tti) { + return cfg->n_pucch_sr; + } + if (uci_value) { - if (cfg->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS && cfg->format < SRSLTE_PUCCH_FORMAT_2 && - !uci_value->scheduling_request && uci_cfg->ack.nof_acks > 0) { - n_pucch_res = get_npucch_cs(cfg, uci_cfg->ack.ncce[0], uci_cfg, uci_value); - return n_pucch_res; - } else if (cfg->ack_nack_feedback_mode == SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3 && - cfg->format == SRSLTE_PUCCH_FORMAT_3) { - n_pucch_res = cfg->n3_pucch_an_list[cfg->tpc_for_pucch % SRSLTE_PUCCH_SIZE_AN_CS]; - return n_pucch_res; - } else if (uci_value->scheduling_request) { - // If SR signal or SR opportunity, use n_pucch_sr for format 1, 1a, 1b - n_pucch_res = cfg->n_pucch_sr; - return n_pucch_res; + if (uci_value->scheduling_request) { + return cfg->n_pucch_sr; } - } else if (uci_cfg->is_scheduling_request_tti) { - n_pucch_res = cfg->n_pucch_sr; - return n_pucch_res; + } + + if (!uci_value || !cell || !uci_cfg) { + fprintf(stderr, "get_npucch(): Invalid parameters\n"); + return 0; } if (cfg->format < SRSLTE_PUCCH_FORMAT_2) { if (cfg->sps_enabled) { - n_pucch_res = cfg->n_pucch_1[cfg->tpc_for_pucch % 4]; + n_pucch_res = cfg->n_pucch_1[uci_cfg->ack[0].tpc_for_pucch % 4]; } else { if (cell->frame_type == SRSLTE_FDD) { - n_pucch_res = uci_cfg->ack.ncce[0] + cfg->N_pucch_1; + switch (cfg->ack_nack_feedback_mode) { + case SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3: + n_pucch_res = cfg->n3_pucch_an_list[uci_cfg->ack[0].tpc_for_pucch % SRSLTE_PUCCH_SIZE_AN_CS]; + break; + case SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS: + n_pucch_res = get_npucch_cs(cfg, uci_cfg, uci_value); + break; + default: + n_pucch_res = uci_cfg->ack[0].ncce[0] + cfg->N_pucch_1; + break; + } } else { - if (uci_cfg->ack.tdd_is_bundling || uci_cfg->ack.tdd_ack_M == 1) { - n_pucch_res = n_pucch_i_tdd( - uci_cfg->ack.ncce[0], cfg->N_pucch_1, cell->nof_prb, uci_cfg->ack.tdd_ack_M, uci_cfg->ack.tdd_ack_m); + // only 1 CC supported in TDD + if (!uci_cfg->ack[0].tdd_is_multiplex || uci_cfg->ack[0].tdd_ack_M == 1) { + n_pucch_res = n_pucch_i_tdd(uci_cfg->ack[0].ncce[0], + cfg->N_pucch_1, + cell->nof_prb, + uci_cfg->ack[0].tdd_ack_M, + uci_cfg->ack[0].tdd_ack_m); } else { - if (uci_cfg->ack.tdd_ack_M <= 4) { + if (uci_cfg->ack[0].tdd_ack_M <= 4) { uint32_t n_pucch[4] = {}; - for (uint32_t i = 0; i < uci_cfg->ack.tdd_ack_M; i++) { + for (uint32_t i = 0; i < uci_cfg->ack[0].tdd_ack_M; i++) { n_pucch[i] = - n_pucch_i_tdd(uci_cfg->ack.ncce[i], cfg->N_pucch_1, cell->nof_prb, uci_cfg->ack.tdd_ack_M, i); - } - if (uci_value) { - n_pucch_res = get_npucch_tdd(n_pucch, uci_cfg, uci_value); - } else { - ERROR("Error Not Implemented: TDD requires uci_value\n"); + n_pucch_i_tdd(uci_cfg->ack[0].ncce[i], cfg->N_pucch_1, cell->nof_prb, uci_cfg->ack[0].tdd_ack_M, i); } + n_pucch_res = get_npucch_tdd(n_pucch, uci_cfg, uci_value); } else { - ERROR("Invalid M=%d in PUCCH TDD multiplexing\n", uci_cfg->ack.tdd_ack_M); + ERROR("Invalid M=%d in PUCCH TDD multiplexing\n", uci_cfg->ack[0].tdd_ack_M); } } } @@ -861,7 +895,7 @@ void srslte_ue_ul_pucch_resource_selection(srslte_cell_t* cell, srslte_uci_value_t* uci_value) { // Drop CQI if there is collision with ACK - if ((!cfg->simul_cqi_ack || uci_cfg->ack.has_scell_ack) && uci_cfg->ack.nof_acks > 0 && uci_cfg->cqi.data_enable) { + if (!cfg->simul_cqi_ack && srslte_uci_cfg_total_ack(uci_cfg) > 0 && uci_cfg->cqi.data_enable) { uci_cfg->cqi.data_enable = false; } @@ -870,16 +904,17 @@ void srslte_ue_ul_pucch_resource_selection(srslte_cell_t* cell, if (uci_value) { if (cfg->format == SRSLTE_PUCCH_FORMAT_3) { + fprintf(stderr, "Warning: PUCCH3 under development\n"); uint8_t* b = uci_value->ack.ack_value; uint8_t temp[SRSLTE_UCI_MAX_ACK_BITS + 1]; - uint32_t k = uci_cfg->ack.nof_acks; - for (; k < uci_cfg->ack.nof_acks; k++) { + uint32_t k = uci_cfg->ack[0].nof_acks; + for (; k < uci_cfg->ack[0].nof_acks; k++) { temp[k] = (uint8_t)((b[k] == 1) ? 1 : 0); } - memcpy(temp, uci_value->ack.ack_value, uci_cfg->ack.nof_acks); + memcpy(temp, uci_value->ack.ack_value, uci_cfg->ack[0].nof_acks); if (uci_cfg->is_scheduling_request_tti) { - temp[uci_cfg->ack.nof_acks] = (uint8_t)(uci_value->scheduling_request ? 1 : 0); + temp[uci_cfg->ack[0].nof_acks] = (uint8_t)(uci_value->scheduling_request ? 1 : 0); k++; } srslte_uci_encode_ack_sr_pucch3(temp, k, b); @@ -993,7 +1028,7 @@ bool srslte_ue_ul_gen_sr(srslte_ue_ul_cfg_t* cfg, srslte_ul_sf_cfg_t* sf, srslte return false; } -#define uci_pending(cfg) (cfg.ack.nof_acks > 0 || cfg.cqi.data_enable || cfg.cqi.ri_len > 0) +#define uci_pending(cfg) (srslte_uci_cfg_total_ack(&cfg) > 0 || cfg.cqi.data_enable || cfg.cqi.ri_len > 0) int srslte_ue_ul_encode(srslte_ue_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_ue_ul_cfg_t* cfg, srslte_pusch_data_t* data) { @@ -1002,7 +1037,7 @@ int srslte_ue_ul_encode(srslte_ue_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_ue_ul_ /* Convert DTX to NACK in channel-selection mode (Release 10 only)*/ if (cfg->ul_cfg.pucch.ack_nack_feedback_mode != SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL) { uint32_t dtx_count = 0; - for (uint32_t a = 0; a < cfg->ul_cfg.pusch.uci_cfg.ack.nof_acks; a++) { + for (uint32_t a = 0; a < srslte_uci_cfg_total_ack(&cfg->ul_cfg.pusch.uci_cfg); a++) { if (data->uci.ack.ack_value[a] == 2) { data->uci.ack.ack_value[a] = 0; dtx_count++; @@ -1010,8 +1045,10 @@ int srslte_ue_ul_encode(srslte_ue_ul_t* q, srslte_ul_sf_cfg_t* sf, srslte_ue_ul_ } /* If all bits are DTX, do not transmit HARQ */ - if (dtx_count == cfg->ul_cfg.pusch.uci_cfg.ack.nof_acks) { - cfg->ul_cfg.pusch.uci_cfg.ack.nof_acks = 0; + if (dtx_count == srslte_uci_cfg_total_ack(&cfg->ul_cfg.pusch.uci_cfg)) { + for (int i = 0; i < 2; i++) { // Format 1b-CS only supports 2 CC + cfg->ul_cfg.pusch.uci_cfg.ack[i].nof_acks = 0; + } } } diff --git a/lib/src/phy/utils/ringbuffer.c b/lib/src/phy/utils/ringbuffer.c index 38f6d6f41..22fe6d23c 100644 --- a/lib/src/phy/utils/ringbuffer.c +++ b/lib/src/phy/utils/ringbuffer.c @@ -34,11 +34,12 @@ int srslte_ringbuffer_init(srslte_ringbuffer_t *q, int capacity) } q->active = true; q->capacity = capacity; - pthread_mutex_init(&q->mutex, NULL); - pthread_cond_init(&q->cvar, NULL); + pthread_mutex_init(&q->mutex, NULL); + pthread_cond_init(&q->write_cvar, NULL); + pthread_cond_init(&q->read_cvar, NULL); srslte_ringbuffer_reset(q); - return 0; + return 0; } void srslte_ringbuffer_free(srslte_ringbuffer_t *q) @@ -47,10 +48,11 @@ void srslte_ringbuffer_free(srslte_ringbuffer_t *q) srslte_ringbuffer_stop(q); if (q->buffer) { free(q->buffer); - q->buffer = NULL; + q->buffer = NULL; } - pthread_mutex_destroy(&q->mutex); - pthread_cond_destroy(&q->cvar); + pthread_mutex_destroy(&q->mutex); + pthread_cond_destroy(&q->write_cvar); + pthread_cond_destroy(&q->read_cvar); } } @@ -90,20 +92,64 @@ int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *p, int nof_bytes) ERROR("Buffer overrun: lost %d bytes\n", nof_bytes - w_bytes); } if (w_bytes > q->capacity - q->wpm) { - int x = q->capacity - q->wpm; - memcpy(&q->buffer[q->wpm], ptr, x); - memcpy(q->buffer, &ptr[x], w_bytes - x); + int x = q->capacity - q->wpm; + memcpy(&q->buffer[q->wpm], ptr, x); + memcpy(q->buffer, &ptr[x], w_bytes - x); } else { - memcpy(&q->buffer[q->wpm], ptr, w_bytes); + memcpy(&q->buffer[q->wpm], ptr, w_bytes); } - q->wpm += w_bytes; + q->wpm += w_bytes; if (q->wpm >= q->capacity) { - q->wpm -= q->capacity; + q->wpm -= q->capacity; } - q->count += w_bytes; - pthread_cond_broadcast(&q->cvar); + q->count += w_bytes; + pthread_cond_broadcast(&q->write_cvar); pthread_mutex_unlock(&q->mutex); - return w_bytes; + return w_bytes; +} + +int srslte_ringbuffer_write_timed(srslte_ringbuffer_t* q, void* p, int nof_bytes, uint32_t timeout_ms) +{ + int ret = SRSLTE_SUCCESS; + uint8_t* ptr = (uint8_t*)p; + int w_bytes = nof_bytes; + struct timespec towait; + struct timeval now; + + // Get current time and update timeout + gettimeofday(&now, NULL); + towait.tv_sec = now.tv_sec + timeout_ms / 1000U; + towait.tv_nsec = (now.tv_usec + 1000UL * (timeout_ms % 1000U)) * 1000UL; + pthread_mutex_lock(&q->mutex); + + // Wait to have enough space in the buffer + while (q->count + w_bytes > q->capacity && q->active && ret == SRSLTE_SUCCESS) { + ret = pthread_cond_timedwait(&q->read_cvar, &q->mutex, &towait); + } + + if (ret == ETIMEDOUT) { + ret = SRSLTE_ERROR_TIMEOUT; + } else if (!q->active) { + ret = SRSLTE_SUCCESS; + } else if (ret == SRSLTE_SUCCESS) { + if (w_bytes > q->capacity - q->wpm) { + int x = q->capacity - q->wpm; + memcpy(&q->buffer[q->wpm], ptr, x); + memcpy(q->buffer, &ptr[x], w_bytes - x); + } else { + memcpy(&q->buffer[q->wpm], ptr, w_bytes); + } + q->wpm += w_bytes; + if (q->wpm >= q->capacity) { + q->wpm -= q->capacity; + } + q->count += w_bytes; + } else { + ret = SRSLTE_ERROR; + } + pthread_cond_broadcast(&q->write_cvar); + pthread_mutex_unlock(&q->mutex); + return w_bytes; } int srslte_ringbuffer_read(srslte_ringbuffer_t *q, void *p, int nof_bytes) @@ -111,26 +157,27 @@ int srslte_ringbuffer_read(srslte_ringbuffer_t *q, void *p, int nof_bytes) uint8_t *ptr = (uint8_t*) p; pthread_mutex_lock(&q->mutex); while(q->count < nof_bytes && q->active) { - pthread_cond_wait(&q->cvar, &q->mutex); + pthread_cond_wait(&q->write_cvar, &q->mutex); } if (!q->active) { pthread_mutex_unlock(&q->mutex); return 0; } if (nof_bytes + q->rpm > q->capacity) { - int x = q->capacity - q->rpm; + int x = q->capacity - q->rpm; memcpy(ptr, &q->buffer[q->rpm], x); memcpy(&ptr[x], q->buffer, nof_bytes - x); - } else { + } else { memcpy(ptr, &q->buffer[q->rpm], nof_bytes); } - q->rpm += nof_bytes; + q->rpm += nof_bytes; if (q->rpm >= q->capacity) { - q->rpm -= q->capacity; + q->rpm -= q->capacity; } - q->count -= nof_bytes; + q->count -= nof_bytes; + pthread_cond_broadcast(&q->read_cvar); pthread_mutex_unlock(&q->mutex); - return nof_bytes; + return nof_bytes; } int srslte_ringbuffer_read_timed(srslte_ringbuffer_t* q, void* p, int nof_bytes, uint32_t timeout_ms) @@ -150,7 +197,7 @@ int srslte_ringbuffer_read_timed(srslte_ringbuffer_t* q, void* p, int nof_bytes, // Wait for having enough samples while (q->count < nof_bytes && q->active && ret == SRSLTE_SUCCESS) { - ret = pthread_cond_timedwait(&q->cvar, &q->mutex, &towait); + ret = pthread_cond_timedwait(&q->write_cvar, &q->mutex, &towait); } if (ret == ETIMEDOUT) { @@ -176,6 +223,7 @@ int srslte_ringbuffer_read_timed(srslte_ringbuffer_t* q, void* p, int nof_bytes, } // Unlock mutex + pthread_cond_broadcast(&q->read_cvar); pthread_mutex_unlock(&q->mutex); return ret; @@ -184,7 +232,8 @@ int srslte_ringbuffer_read_timed(srslte_ringbuffer_t* q, void* p, int nof_bytes, void srslte_ringbuffer_stop(srslte_ringbuffer_t *q) { pthread_mutex_lock(&q->mutex); q->active = false; - pthread_cond_broadcast(&q->cvar); + pthread_cond_broadcast(&q->write_cvar); + pthread_cond_broadcast(&q->read_cvar); pthread_mutex_unlock(&q->mutex); } @@ -195,7 +244,7 @@ int srslte_ringbuffer_read_convert_conj(srslte_ringbuffer_t* q, cf_t* dst_ptr, f pthread_mutex_lock(&q->mutex); while (q->count < nof_bytes && q->active) { - pthread_cond_wait(&q->cvar, &q->mutex); + pthread_cond_wait(&q->write_cvar, &q->mutex); } if (!q->active) { pthread_mutex_unlock(&q->mutex); @@ -218,6 +267,7 @@ int srslte_ringbuffer_read_convert_conj(srslte_ringbuffer_t* q, cf_t* dst_ptr, f q->rpm -= q->capacity; } q->count -= nof_bytes; + pthread_cond_broadcast(&q->read_cvar); pthread_mutex_unlock(&q->mutex); return nof_samples; } @@ -230,7 +280,7 @@ int srslte_ringbuffer_read_block(srslte_ringbuffer_t* q, void** p, int nof_bytes /* Wait until enough data is in the buffer */ while (q->count < nof_bytes && q->active) { - pthread_cond_wait(&q->cvar, &q->mutex); + pthread_cond_wait(&q->write_cvar, &q->mutex); } if (!q->active) { @@ -245,6 +295,7 @@ int srslte_ringbuffer_read_block(srslte_ringbuffer_t* q, void** p, int nof_bytes q->rpm -= q->capacity; } } + pthread_cond_broadcast(&q->read_cvar); pthread_mutex_unlock(&q->mutex); return ret; } diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 8d02950c8..af932cda0 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -255,6 +255,11 @@ void radio::tx_end() } } +bool radio::get_is_start_of_burst() +{ + return is_start_of_burst; +} + void radio::set_freq_offset(double freq) { freq_offset = freq; } @@ -274,19 +279,8 @@ double radio::set_rx_gain_th(float gain) return srslte_rf_set_rx_gain_th(&rf_device, gain); } -void radio::set_master_clock_rate(double rate) -{ - if (rate != master_clock_rate) { - srslte_rf_stop_rx_stream(&rf_device); - srslte_rf_set_master_clock_rate(&rf_device, rate); - srslte_rf_start_rx_stream(&rf_device, false); - master_clock_rate = rate; - } -} - void radio::set_rx_srate(double srate) { - set_master_clock_rate(srate); srslte_rf_set_rx_srate(&rf_device, srate); } @@ -327,7 +321,6 @@ float radio::get_rx_gain() void radio::set_tx_srate(double srate) { - set_master_clock_rate(srate); cur_tx_srate = srslte_rf_set_tx_srate(&rf_device, srate); burst_preamble_samples = (uint32_t) (cur_tx_srate * burst_preamble_sec); if (burst_preamble_samples > burst_preamble_max_samples) { diff --git a/lib/src/radio/radio_multi.cc b/lib/src/radio/radio_multi.cc index 75676bb81..5b39d7f36 100644 --- a/lib/src/radio/radio_multi.cc +++ b/lib/src/radio/radio_multi.cc @@ -89,7 +89,7 @@ int radio_multi::init(const rf_args_t& args_, phy_interface_radio* phy_) radio->set_burst_preamble(strtof(args.burst_preamble.c_str(), nullptr)); } if (args.continuous_tx != "auto") { - radio->set_continuous_tx(!(args.continuous_tx == "yes")); + radio->set_continuous_tx(args.continuous_tx == "yes"); } // Set PHY options diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 75ec0e9d3..2b82e8cc7 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -120,11 +120,11 @@ void pdcp::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu) pthread_rwlock_unlock(&rwlock); } -void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg) +void pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg) { pthread_rwlock_wrlock(&rwlock); if (not valid_lcid(lcid)) { - if (not pdcp_array.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { + if (not pdcp_array.insert(pdcp_map_pair_t(lcid, new pdcp_entity_lte())).second) { pdcp_log->error("Error inserting PDCP entity in to array\n."); goto unlock_and_exit; } @@ -141,11 +141,11 @@ unlock_and_exit: pthread_rwlock_unlock(&rwlock); } -void pdcp::add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cfg) +void pdcp::add_bearer_mrb(uint32_t lcid, pdcp_config_t cfg) { pthread_rwlock_wrlock(&rwlock); if (not valid_mch_lcid(lcid)) { - if (not pdcp_array_mrb.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { + if (not pdcp_array_mrb.insert(pdcp_map_pair_t(lcid, new pdcp_entity_lte())).second) { pdcp_log->error("Error inserting PDCP entity in to array\n."); goto unlock_and_exit; } @@ -183,8 +183,8 @@ void pdcp::change_lcid(uint32_t old_lcid, uint32_t new_lcid) // make sure old LCID exists and new LCID is still free if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) { // insert old PDCP entity into new LCID - pdcp_map_t::iterator it = pdcp_array.find(old_lcid); - pdcp_entity_interface *pdcp_entity = it->second; + pdcp_map_t::iterator it = pdcp_array.find(old_lcid); + pdcp_entity_lte* pdcp_entity = it->second; if (not pdcp_array.insert(pdcp_map_pair_t(new_lcid, pdcp_entity)).second) { pdcp_log->error("Error inserting PDCP entity into array\n."); goto exit; @@ -193,7 +193,11 @@ void pdcp::change_lcid(uint32_t old_lcid, uint32_t new_lcid) pdcp_array.erase(it); pdcp_log->warning("Changed LCID of PDCP bearer from %d to %d\n", old_lcid, new_lcid); } else { - pdcp_log->error("Can't change PDCP of bearer %s from %d to %d. Bearer doesn't exist or new LCID already occupied.\n", rrc->get_rb_name(old_lcid).c_str(), old_lcid, new_lcid); + pdcp_log->error( + "Can't change PDCP of bearer %s from %d to %d. Bearer doesn't exist or new LCID already occupied.\n", + rrc->get_rb_name(old_lcid).c_str(), + old_lcid, + new_lcid); } exit: pthread_rwlock_unlock(&rwlock); @@ -208,7 +212,7 @@ void pdcp::config_security(uint32_t lcid, { pthread_rwlock_rdlock(&rwlock); if (valid_lcid(lcid)) { - pdcp_array.at(lcid)->config_security(k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); + pdcp_array.at(lcid)->config_security(k_rrc_enc, k_rrc_int, k_up_enc, nullptr, cipher_algo, integ_algo); } pthread_rwlock_unlock(&rwlock); } @@ -218,7 +222,7 @@ void pdcp::config_security_all(uint8_t* k_rrc_enc, uint8_t* k_rrc_int, uint8_t* { pthread_rwlock_rdlock(&rwlock); for (pdcp_map_t::iterator it = pdcp_array.begin(); it != pdcp_array.end(); ++it) { - it->second->config_security(k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); + it->second->config_security(k_rrc_enc, k_rrc_int, k_up_enc, nullptr, cipher_algo, integ_algo); } pthread_rwlock_unlock(&rwlock); } @@ -241,29 +245,6 @@ void pdcp::enable_encryption(uint32_t lcid) pthread_rwlock_unlock(&rwlock); } -uint32_t pdcp::get_dl_count(uint32_t lcid) -{ - int ret = 0; - pthread_rwlock_rdlock(&rwlock); - if (valid_lcid(lcid)) { - ret = pdcp_array.at(lcid)->get_dl_count(); - } - pthread_rwlock_unlock(&rwlock); - return ret; -} - -uint32_t pdcp::get_ul_count(uint32_t lcid) -{ - int ret = 0; - pthread_rwlock_rdlock(&rwlock); - if (valid_lcid(lcid)) { - ret = pdcp_array.at(lcid)->get_ul_count(); - } - pthread_rwlock_unlock(&rwlock); - return ret; -} - - /******************************************************************************* RLC interface *******************************************************************************/ @@ -333,4 +314,4 @@ bool pdcp::valid_mch_lcid(uint32_t lcid) return true; } -} // namespace srsue +} // namespace srslte diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc deleted file mode 100644 index d8acf43b9..000000000 --- a/lib/src/upper/pdcp_entity.cc +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright 2013-2019 Software Radio Systems Limited - * - * This file is part of srsLTE. - * - * srsLTE 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. - * - * srsLTE 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 "srslte/upper/pdcp_entity.h" -#include "srslte/common/security.h" - -namespace srslte { - -pdcp_entity::pdcp_entity() -{ - pthread_mutex_init(&mutex, nullptr); -} - -pdcp_entity::~pdcp_entity() -{ - pthread_mutex_destroy(&mutex); -} - -void pdcp_entity::init(srsue::rlc_interface_pdcp* rlc_, - srsue::rrc_interface_pdcp* rrc_, - srsue::gw_interface_pdcp* gw_, - srslte::log* log_, - uint32_t lcid_, - srslte_pdcp_config_t cfg_) -{ - rlc = rlc_; - rrc = rrc_; - gw = gw_; - log = log_; - lcid = lcid_; - cfg = cfg_; - active = true; - tx_count = 0; - rx_count = 0; - do_integrity = false; - do_encryption = false; - - cfg = cfg_; - - // set length of SN field in bytes - sn_len_bytes = (cfg.sn_len == 5) ? 1 : 2; - - if (cfg.is_control) { - reordering_window = 0; - } else if (cfg.is_data) { - reordering_window = 2048; - } - - rx_hfn = 0; - next_pdcp_rx_sn = 0; - maximum_pdcp_sn = (1 << cfg.sn_len) - 1; - last_submitted_pdcp_rx_sn = maximum_pdcp_sn; - log->info("Init %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id); - log->info("SN len bits: %d, SN len bytes: %d, reordering window: %d, Maximum SN %d\n", - cfg.sn_len, - sn_len_bytes, - reordering_window, - maximum_pdcp_sn); -} - -// Reestablishment procedure: 36.323 5.2 -void pdcp_entity::reestablish() -{ - log->info("Re-establish %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id); - // For SRBs - if (cfg.is_control) { - tx_count = 0; - rx_count = 0; - rx_hfn = 0; - next_pdcp_rx_sn = 0; - } else { - // Only reset counter in RLC-UM - if (rlc->rb_is_um(lcid)) { - tx_count = 0; - rx_count = 0; - rx_hfn = 0; - next_pdcp_rx_sn = 0; - } else { - tx_count = 0; - rx_count = 0; - rx_hfn = 0; - next_pdcp_rx_sn = 0; - last_submitted_pdcp_rx_sn = maximum_pdcp_sn; - } - } -} - -// Used to stop/pause the entity (called on RRC conn release) -void pdcp_entity::reset() -{ - active = false; - if (log) { - log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str()); - } -} - -bool pdcp_entity::is_active() -{ - return active; -} - -// GW/RRC interface -void pdcp_entity::write_sdu(unique_byte_buffer_t sdu, bool blocking) -{ - log->info_hex(sdu->msg, sdu->N_bytes, - "TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s", - rrc->get_rb_name(lcid).c_str(), tx_count, - (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); - - pthread_mutex_lock(&mutex); - - if (cfg.is_control) { - pdcp_pack_control_pdu(tx_count, sdu.get()); - if(do_integrity) { - integrity_generate(sdu->msg, - sdu->N_bytes-4, - &sdu->msg[sdu->N_bytes-4]); - } - } - - if (cfg.is_data) { - if(12 == cfg.sn_len) { - pdcp_pack_data_pdu_long_sn(tx_count, sdu.get()); - } else { - pdcp_pack_data_pdu_short_sn(tx_count, sdu.get()); - } - } - - if(do_encryption) { - cipher_encrypt(&sdu->msg[sn_len_bytes], - sdu->N_bytes-sn_len_bytes, - &sdu->msg[sn_len_bytes]); - log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", rrc->get_rb_name(lcid).c_str()); - } - tx_count++; - - pthread_mutex_unlock(&mutex); - - rlc->write_sdu(lcid, std::move(sdu), blocking); -} - -void pdcp_entity::config_security(uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, - uint8_t *k_up_enc_, - CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, - INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) -{ - for(int i=0; i<32; i++) - { - k_rrc_enc[i] = k_rrc_enc_[i]; - k_rrc_int[i] = k_rrc_int_[i]; - k_up_enc[i] = k_up_enc_[i]; - } - cipher_algo = cipher_algo_; - integ_algo = integ_algo_; -} - -void pdcp_entity::enable_integrity() -{ - do_integrity = true; -} - -void pdcp_entity::enable_encryption() -{ - do_encryption = true; -} - -// RLC interface -void pdcp_entity::write_pdu(unique_byte_buffer_t pdu) -{ - log->info_hex(pdu->msg, - pdu->N_bytes, - "RX %s PDU (%d B), do_integrity = %s, do_encryption = %s", - rrc->get_rb_name(lcid).c_str(), - pdu->N_bytes, - (do_integrity) ? "true" : "false", - (do_encryption) ? "true" : "false"); - - // Sanity check - if (pdu->N_bytes < sn_len_bytes) { - log->debug("Ignoring PDCP PDU: size=%d, sn_len_bytes=%d\n", pdu->N_bytes, sn_len_bytes); - return; - } - - - pthread_mutex_lock(&mutex); - - if (cfg.is_data) { - - // Check PDCP control messages - if ((pdu->msg[0] & 0x80) == 0) { - log->debug("Unhandled PDCP Control PDU\n"); - goto exit; // TODO handle PDCP control PDUs - } - - // Handle DRB messages - if (rlc->rb_is_um(lcid)) { - handle_um_drb_pdu(pdu); - } else { - handle_am_drb_pdu(pdu); - } - gw->write_pdu(lcid, std::move(pdu)); - } else { - // Handle SRB messages - if (cfg.is_control) { - uint32_t sn = *pdu->msg & 0x1F; - if (do_encryption) { - cipher_decrypt(&pdu->msg[sn_len_bytes], sn, pdu->N_bytes - sn_len_bytes, &(pdu->msg[sn_len_bytes])); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); - } - - if (do_integrity) { - if (not integrity_verify(pdu->msg, sn, pdu->N_bytes - 4, &(pdu->msg[pdu->N_bytes - 4]))) { - log->error_hex(pdu->msg, pdu->N_bytes, "%s Dropping PDU", rrc->get_rb_name(lcid).c_str()); - goto exit; - } - } - - pdcp_unpack_control_pdu(pdu.get(), &sn); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn); - } - // pass to RRC - rrc->write_pdu(lcid, std::move(pdu)); - } -exit: - rx_count++; - pthread_mutex_unlock(&mutex); -} - -/**************************************************************************** - * Rx data/control handler functions - * Ref: 3GPP TS 36.323 v10.1.0 Section 5.1.2 - ***************************************************************************/ -// DRBs mapped on RLC UM (5.1.2.1.3) -void pdcp_entity::handle_um_drb_pdu(const srslte::unique_byte_buffer_t &pdu) -{ - uint32_t sn; - if (12 == cfg.sn_len) { - pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn); - } else { - pdcp_unpack_data_pdu_short_sn(pdu.get(), &sn); - } - - if (sn < next_pdcp_rx_sn) { - rx_hfn++; - } - - uint32_t count = (rx_hfn << cfg.sn_len) | sn; - if (do_encryption) { - cipher_decrypt(pdu->msg, count, pdu->N_bytes, pdu->msg); - log->debug_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); - } - - next_pdcp_rx_sn = sn + 1; - if (next_pdcp_rx_sn > maximum_pdcp_sn) { - next_pdcp_rx_sn = 0; - rx_hfn++; - } - - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn); - return; -} - -// DRBs mapped on RLC AM, without re-ordering (5.1.2.1.2) -void pdcp_entity::handle_am_drb_pdu(const srslte::unique_byte_buffer_t &pdu) -{ - uint32_t sn, count; - pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn); - - int32_t last_submit_diff_sn = last_submitted_pdcp_rx_sn - sn; - int32_t sn_diff_last_submit = sn - last_submitted_pdcp_rx_sn; - int32_t sn_diff_next_pdcp_rx_sn = sn - next_pdcp_rx_sn; - - log->debug("RX HFN: %d, SN: %d, Last_Submitted_PDCP_RX_SN: %d, Next_PDCP_RX_SN %d\n", - rx_hfn, - sn, - last_submitted_pdcp_rx_sn, - next_pdcp_rx_sn); - - bool discard = false; - if ((0 <= sn_diff_last_submit && sn_diff_last_submit > (int32_t)reordering_window) || - (0 <= last_submit_diff_sn && last_submit_diff_sn < (int32_t)reordering_window)) { - log->debug("|SN - last_submitted_sn| is larger than re-ordering window.\n"); - if (sn > next_pdcp_rx_sn) { - count = (rx_hfn - 1) << cfg.sn_len | sn; - } else { - count = rx_hfn << cfg.sn_len | sn; - } - discard = true; - } else if ((int32_t)(next_pdcp_rx_sn - sn) > (int32_t)reordering_window) { - log->debug("(Next_PDCP_RX_SN - SN) is larger than re-ordering window.\n"); - rx_hfn++; - count = (rx_hfn << cfg.sn_len) | sn; - next_pdcp_rx_sn = sn + 1; - } else if (sn_diff_next_pdcp_rx_sn >= (int32_t)reordering_window) { - log->debug("(SN - Next_PDCP_RX_SN) is larger or equal than re-ordering window.\n"); - count = ((rx_hfn - 1) << cfg.sn_len) | sn; - } else if (sn >= next_pdcp_rx_sn) { - log->debug("SN is larger or equal than Next_PDCP_RX_SN.\n"); - count = (rx_hfn << cfg.sn_len) | sn; - next_pdcp_rx_sn = sn + 1; - if (next_pdcp_rx_sn > maximum_pdcp_sn) { - next_pdcp_rx_sn = 0; - rx_hfn++; - } - } else if (sn < next_pdcp_rx_sn) { - log->debug("SN is smaller than Next_PDCP_RX_SN.\n"); - count = (rx_hfn << cfg.sn_len) | sn; - } - - // FIXME Check if PDU is not due to re-establishment of lower layers? - cipher_decrypt(pdu->msg, count, pdu->N_bytes, pdu->msg); - log->debug_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); - - if (!discard) { - last_submitted_pdcp_rx_sn = sn; - } - return; -} - -/**************************************************************************** - * Security functions - ***************************************************************************/ -void pdcp_entity::integrity_generate( uint8_t *msg, - uint32_t msg_len, - uint8_t *mac) -{ - switch(integ_algo) - { - case INTEGRITY_ALGORITHM_ID_EIA0: - break; - case INTEGRITY_ALGORITHM_ID_128_EIA1: - security_128_eia1(&k_rrc_int[16], - tx_count, - cfg.bearer_id - 1, - cfg.direction, - msg, - msg_len, - mac); - break; - case INTEGRITY_ALGORITHM_ID_128_EIA2: - security_128_eia2(&k_rrc_int[16], - tx_count, - cfg.bearer_id - 1, - cfg.direction, - msg, - msg_len, - mac); - break; - default: - break; - } - - log->debug("Integrity gen input:\n"); - log->debug_hex(&k_rrc_int[16], 16, " K_rrc_int"); - log->debug(" Local count: %d\n", tx_count); - log->debug(" Bearer ID: %d\n", cfg.bearer_id); - log->debug(" Direction: %s\n", (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink"); - log->debug_hex(msg, msg_len, " Message"); - log->debug_hex(mac, 4, "MAC (generated)"); -} - -bool pdcp_entity::integrity_verify(uint8_t *msg, - uint32_t count, - uint32_t msg_len, - uint8_t *mac) -{ - uint8_t mac_exp[4] = {0x00}; - uint8_t i = 0; - bool isValid = true; - - switch(integ_algo) - { - case INTEGRITY_ALGORITHM_ID_EIA0: - break; - case INTEGRITY_ALGORITHM_ID_128_EIA1: - security_128_eia1(&k_rrc_int[16], - count, - cfg.bearer_id - 1, - (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), - msg, - msg_len, - mac_exp); - break; - case INTEGRITY_ALGORITHM_ID_128_EIA2: - security_128_eia2(&k_rrc_int[16], - count, - cfg.bearer_id - 1, - (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), - msg, - msg_len, - mac_exp); - break; - default: - break; - } - - log->debug("Integrity check input:\n"); - log->debug_hex(&k_rrc_int[16], 16, " K_rrc_int"); - log->debug(" Local count: %d\n", count); - log->debug(" Bearer ID: %d\n", cfg.bearer_id); - log->debug(" Direction: %s\n", (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? "Uplink" : "Downlink"); - log->debug_hex(msg, msg_len, " Message"); - - switch(integ_algo) - { - case INTEGRITY_ALGORITHM_ID_EIA0: - break; - case INTEGRITY_ALGORITHM_ID_128_EIA1: // Intentional fall-through - case INTEGRITY_ALGORITHM_ID_128_EIA2: - for(i=0; i<4; i++){ - if(mac[i] != mac_exp[i]){ - log->error_hex(mac_exp, 4, "MAC mismatch (expected)"); - log->error_hex(mac, 4, "MAC mismatch (found)"); - isValid = false; - break; - } - } - if (isValid){ - log->info_hex(mac_exp, 4, "MAC match"); - } - break; - default: - break; - } - - return isValid; -} - -void pdcp_entity::cipher_encrypt(uint8_t *msg, - uint32_t msg_len, - uint8_t *ct) -{ - byte_buffer_t ct_tmp; - uint8_t *k_enc; - - // If control plane use RRC encrytion key. If data use user plane key - if (cfg.is_control) { - k_enc = k_rrc_enc; - } else { - k_enc = k_up_enc; - } - - log->debug("Cipher encrypt input:\n"); - log->debug_hex(&k_enc[16], 16, " K_enc"); - log->debug(" Local count: %d\n", tx_count); - log->debug(" TX HFN: %d COUNT %d\n", (tx_count >> cfg.sn_len), (tx_count << (32-cfg.sn_len)) >> (32-cfg.sn_len)); - log->debug(" Bearer ID: %d\n", cfg.bearer_id); - log->debug(" Direction: %s\n", (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink"); - - switch(cipher_algo) - { - case CIPHERING_ALGORITHM_ID_EEA0: - break; - case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&(k_enc[16]), - tx_count, - cfg.bearer_id - 1, - cfg.direction, - msg, - msg_len, - ct_tmp.msg); - memcpy(ct, ct_tmp.msg, msg_len); - break; - case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&(k_enc[16]), - tx_count, - cfg.bearer_id - 1, - cfg.direction, - msg, - msg_len, - ct_tmp.msg); - memcpy(ct, ct_tmp.msg, msg_len); - break; - default: - break; - } -} - -void pdcp_entity::cipher_decrypt(uint8_t *ct, - uint32_t count, - uint32_t ct_len, - uint8_t *msg) -{ - byte_buffer_t msg_tmp; - uint8_t *k_enc; - // If control plane use RRC encrytion key. If data use user plane key - if (cfg.is_control) { - k_enc = k_rrc_enc; - } else { - k_enc = k_up_enc; - } - - switch(cipher_algo) - { - case CIPHERING_ALGORITHM_ID_EEA0: - break; - case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&(k_enc[16]), - count, - cfg.bearer_id - 1, - (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), - ct, - ct_len, - msg_tmp.msg); - memcpy(msg, msg_tmp.msg, ct_len); - break; - case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&(k_enc[16]), - count, - cfg.bearer_id - 1, - (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), - ct, - ct_len, - msg_tmp.msg); - memcpy(msg, msg_tmp.msg, ct_len); - break; - default: - break; - } -} - - -uint32_t pdcp_entity::get_dl_count() -{ - return rx_count; -} - - -uint32_t pdcp_entity::get_ul_count() -{ - return tx_count; -} - -/**************************************************************************** - * Pack/Unpack helper functions - * Ref: 3GPP TS 36.323 v10.1.0 - ***************************************************************************/ - -void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu) -{ - // Make room and add header - sdu->msg--; - sdu->N_bytes++; - *sdu->msg = sn & 0x1F; - - // Add MAC - sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 24) & 0xFF; - sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 16) & 0xFF; - sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 8) & 0xFF; - sdu->msg[sdu->N_bytes++] = PDCP_CONTROL_MAC_I & 0xFF; - -} - -void pdcp_unpack_control_pdu(byte_buffer_t *pdu, uint32_t *sn) -{ - // Strip header - *sn = *pdu->msg & 0x1F; - pdu->msg++; - pdu->N_bytes--; - - // Strip MAC - pdu->N_bytes -= 4; - - // TODO: integrity check MAC -} - -void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t *sdu) -{ - // Make room and add header - sdu->msg--; - sdu->N_bytes++; - sdu->msg[0] = (PDCP_D_C_DATA_PDU << 7) | (sn & 0x7F); -} - -void pdcp_unpack_data_pdu_short_sn(byte_buffer_t *sdu, uint32_t *sn) -{ - // Strip header - *sn = sdu->msg[0] & 0x7F; - sdu->msg++; - sdu->N_bytes--; -} - -void pdcp_pack_data_pdu_long_sn(uint32_t sn, byte_buffer_t *sdu) -{ - // Make room and add header - sdu->msg -= 2; - sdu->N_bytes += 2; - sdu->msg[0] = (PDCP_D_C_DATA_PDU << 7) | ((sn >> 8) & 0x0F); - sdu->msg[1] = sn & 0xFF; -} - -void pdcp_unpack_data_pdu_long_sn(byte_buffer_t *sdu, uint32_t *sn) -{ - // Strip header - *sn = (sdu->msg[0] & 0x0F) << 8; - *sn |= sdu->msg[1]; - sdu->msg += 2; - sdu->N_bytes -= 2; -} - -} diff --git a/lib/src/upper/pdcp_entity_base.cc b/lib/src/upper/pdcp_entity_base.cc new file mode 100644 index 000000000..7e9c2993b --- /dev/null +++ b/lib/src/upper/pdcp_entity_base.cc @@ -0,0 +1,226 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/upper/pdcp_entity_base.h" +#include "srslte/common/security.h" + +namespace srslte { + +pdcp_entity_base::pdcp_entity_base() {} + +pdcp_entity_base::~pdcp_entity_base() {} + +void pdcp_entity_base::config_security(uint8_t* k_rrc_enc_, + uint8_t* k_rrc_int_, + uint8_t* k_up_enc_, + uint8_t* k_up_int_, + CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, + INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) +{ + for (int i = 0; i < 32; i++) { + k_rrc_enc[i] = k_rrc_enc_[i]; + k_rrc_int[i] = k_rrc_int_[i]; + k_up_enc[i] = k_up_enc_[i]; + if (k_up_int_ != nullptr) { + k_up_int[i] = k_up_int_[i]; + } + } + cipher_algo = cipher_algo_; + integ_algo = integ_algo_; + + log->info("Configuring security with %s and %s\n", + integrity_algorithm_id_text[integ_algo], + ciphering_algorithm_id_text[cipher_algo]); + + log->debug_hex(k_rrc_enc, 32, "K_rrc_enc"); + log->debug_hex(k_up_enc, 32, "K_up_enc"); + log->debug_hex(k_rrc_int, 32, "K_rrc_int"); + log->debug_hex(k_up_int, 32, "K_up_int"); +} + +/**************************************************************************** + * Security functions + ***************************************************************************/ +void pdcp_entity_base::integrity_generate(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* mac) +{ + uint8_t* k_int; + + // If control plane use RRC integrity key. If data use user plane key + if (is_srb()) { + k_int = k_rrc_int; + } else { + k_int = k_up_int; + } + + switch (integ_algo) { + case INTEGRITY_ALGORITHM_ID_EIA0: + break; + case INTEGRITY_ALGORITHM_ID_128_EIA1: + security_128_eia1(&k_int[16], count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, mac); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA2: + security_128_eia2(&k_int[16], count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, mac); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(&k_int[16], count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, mac); + break; + default: + break; + } + + log->debug("Integrity gen input: COUNT %d, Bearer ID %d, Direction %s\n", + count, + cfg.bearer_id, + (cfg.tx_direction == SECURITY_DIRECTION_DOWNLINK ? "Downlink" : "Uplink")); + log->debug_hex(msg, msg_len, "Integrity gen input msg:"); + log->debug_hex(mac, 4, "MAC (generated)"); +} + +bool pdcp_entity_base::integrity_verify(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* mac) +{ + uint8_t mac_exp[4] = {}; + bool is_valid = true; + uint8_t* k_int; + + // If control plane use RRC integrity key. If data use user plane key + if (is_srb()) { + k_int = k_rrc_int; + } else { + k_int = k_up_int; + } + + switch (integ_algo) { + case INTEGRITY_ALGORITHM_ID_EIA0: + break; + case INTEGRITY_ALGORITHM_ID_128_EIA1: + security_128_eia1(&k_int[16], count, cfg.bearer_id - 1, cfg.rx_direction, msg, msg_len, mac_exp); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA2: + security_128_eia2(&k_int[16], count, cfg.bearer_id - 1, cfg.rx_direction, msg, msg_len, mac_exp); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(&k_int[16], count, cfg.bearer_id - 1, cfg.rx_direction, msg, msg_len, mac_exp); + break; + default: + break; + } + + log->debug("Integrity check input: COUNT %d, Bearer ID %d, Direction %s\n", + count, + cfg.bearer_id, + cfg.rx_direction == SECURITY_DIRECTION_DOWNLINK ? "Downlink" : "Uplink"); + log->debug_hex(msg, msg_len, "Integrity check input msg:"); + + if (integ_algo != INTEGRITY_ALGORITHM_ID_EIA0) { + for (uint8_t i = 0; i < 4; i++) { + if (mac[i] != mac_exp[i]) { + log->error_hex(mac_exp, 4, "MAC mismatch (expected)"); + log->error_hex(mac, 4, "MAC mismatch (found)"); + is_valid = false; + break; + } + } + if (is_valid) { + log->info_hex(mac_exp, 4, "MAC match"); + } + } + + return is_valid; +} + +void pdcp_entity_base::cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* ct) +{ + uint8_t* k_enc; + uint8_t ct_tmp[PDCP_MAX_SDU_SIZE]; + + // If control plane use RRC encrytion key. If data use user plane key + if (is_srb()) { + k_enc = k_rrc_enc; + } else { + k_enc = k_up_enc; + } + + log->debug("Cipher encrypt input: COUNT: %d, Bearer ID: %d, Direction %s\n", + count, + cfg.bearer_id, + cfg.tx_direction == SECURITY_DIRECTION_DOWNLINK ? "Downlink" : "Uplink"); + log->debug_hex(msg, msg_len, "Cipher encrypt input msg"); + + switch (cipher_algo) { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&(k_enc[16]), count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, ct_tmp); + memcpy(ct, ct_tmp, msg_len); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&(k_enc[16]), count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, ct_tmp); + memcpy(ct, ct_tmp, msg_len); + break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&(k_enc[16]), count, cfg.bearer_id - 1, cfg.tx_direction, msg, msg_len, ct_tmp); + memcpy(ct, ct_tmp, msg_len); + break; + default: + break; + } + log->debug_hex(ct, msg_len, "Cipher encrypt output msg"); +} + +void pdcp_entity_base::cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t count, uint8_t* msg) +{ + uint8_t* k_enc; + uint8_t msg_tmp[PDCP_MAX_SDU_SIZE]; + + // If control plane use RRC encrytion key. If data use user plane key + if (is_srb()) { + k_enc = k_rrc_enc; + } else { + k_enc = k_up_enc; + } + + log->debug("Cipher decrypt input: COUNT: %d, Bearer ID: %d, Direction %s\n", + count, + cfg.bearer_id, + (cfg.rx_direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink"); + log->debug_hex(ct, ct_len, "Cipher decrypt input msg"); + + switch (cipher_algo) { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&k_enc[16], count, cfg.bearer_id - 1, cfg.rx_direction, ct, ct_len, msg_tmp); + memcpy(msg, msg_tmp, ct_len); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&k_enc[16], count, cfg.bearer_id - 1, cfg.rx_direction, ct, ct_len, msg_tmp); + memcpy(msg, msg_tmp, ct_len); + break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_enc[16], count, cfg.bearer_id - 1, cfg.rx_direction, ct, ct_len, msg_tmp); + memcpy(msg, msg_tmp, ct_len); + break; + default: + break; + } + log->debug_hex(msg, ct_len, "Cipher decrypt output msg"); +} +} // namespace srslte diff --git a/lib/src/upper/pdcp_entity_lte.cc b/lib/src/upper/pdcp_entity_lte.cc new file mode 100644 index 000000000..cfdb35aba --- /dev/null +++ b/lib/src/upper/pdcp_entity_lte.cc @@ -0,0 +1,364 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/upper/pdcp_entity_lte.h" +#include "srslte/common/security.h" + +namespace srslte { + +pdcp_entity_lte::pdcp_entity_lte() {} + +pdcp_entity_lte::~pdcp_entity_lte() {} + +void pdcp_entity_lte::init(srsue::rlc_interface_pdcp* rlc_, + srsue::rrc_interface_pdcp* rrc_, + srsue::gw_interface_pdcp* gw_, + srslte::log* log_, + uint32_t lcid_, + pdcp_config_t cfg_) +{ + rlc = rlc_; + rrc = rrc_; + gw = gw_; + log = log_; + lcid = lcid_; + cfg = cfg_; + active = true; + tx_count = 0; + rx_count = 0; + do_integrity = false; + do_encryption = false; + + if (is_srb()) { + reordering_window = 0; + } else if (is_drb()) { + reordering_window = 2048; + } + + rx_hfn = 0; + next_pdcp_rx_sn = 0; + maximum_pdcp_sn = (1 << cfg.sn_len) - 1; + last_submitted_pdcp_rx_sn = maximum_pdcp_sn; + log->info("Init %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id); + log->info("SN len bits: %d, SN len bytes: %d, reordering window: %d, Maximum SN %d\n", + cfg.sn_len, + cfg.hdr_len_bytes, + reordering_window, + maximum_pdcp_sn); +} + +// Reestablishment procedure: 36.323 5.2 +void pdcp_entity_lte::reestablish() +{ + log->info("Re-establish %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id); + // For SRBs + if (is_srb()) { + tx_count = 0; + rx_count = 0; + rx_hfn = 0; + next_pdcp_rx_sn = 0; + } else { + // Only reset counter in RLC-UM + if (rlc->rb_is_um(lcid)) { + tx_count = 0; + rx_count = 0; + rx_hfn = 0; + next_pdcp_rx_sn = 0; + } else { + tx_count = 0; + rx_count = 0; + rx_hfn = 0; + next_pdcp_rx_sn = 0; + last_submitted_pdcp_rx_sn = maximum_pdcp_sn; + } + } +} + +// Used to stop/pause the entity (called on RRC conn release) +void pdcp_entity_lte::reset() +{ + active = false; + if (log) { + log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str()); + } +} + +// GW/RRC interface +void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking) +{ + log->info_hex(sdu->msg, + sdu->N_bytes, + "TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s", + rrc->get_rb_name(lcid).c_str(), + tx_count, + (do_integrity) ? "true" : "false", + (do_encryption) ? "true" : "false"); + + { + std::unique_lock lock(mutex); + + if (is_srb()) { + pdcp_pack_control_pdu(tx_count, sdu.get()); + if (do_integrity) { + integrity_generate(sdu->msg, sdu->N_bytes - 4, tx_count, &sdu->msg[sdu->N_bytes - 4]); + } + } + + if (is_drb()) { + if (12 == cfg.sn_len) { + pdcp_pack_data_pdu_long_sn(tx_count, sdu.get()); + } else { + pdcp_pack_data_pdu_short_sn(tx_count, sdu.get()); + } + } + + if (do_encryption) { + cipher_encrypt( + &sdu->msg[cfg.hdr_len_bytes], sdu->N_bytes - cfg.hdr_len_bytes, tx_count, &sdu->msg[cfg.hdr_len_bytes]); + log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", rrc->get_rb_name(lcid).c_str()); + } + tx_count++; + } + + rlc->write_sdu(lcid, std::move(sdu), blocking); +} + +// RLC interface +void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu) +{ + log->info_hex(pdu->msg, + pdu->N_bytes, + "RX %s PDU (%d B), do_integrity = %s, do_encryption = %s", + rrc->get_rb_name(lcid).c_str(), + pdu->N_bytes, + (do_integrity) ? "true" : "false", + (do_encryption) ? "true" : "false"); + + // Sanity check + if (pdu->N_bytes <= cfg.hdr_len_bytes) { + return; + } + + std::unique_lock lock(mutex); + if (is_drb()) { + // Handle DRB messages + if (rlc->rb_is_um(lcid)) { + handle_um_drb_pdu(pdu); + } else { + handle_am_drb_pdu(pdu); + } + gw->write_pdu(lcid, std::move(pdu)); + } else { + // Handle SRB messages + if (is_srb()) { + uint32_t sn = *pdu->msg & 0x1F; + if (do_encryption) { + cipher_decrypt( + &pdu->msg[cfg.hdr_len_bytes], pdu->N_bytes - cfg.hdr_len_bytes, sn, &(pdu->msg[cfg.hdr_len_bytes])); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); + } + + if (do_integrity) { + if (not integrity_verify(pdu->msg, pdu->N_bytes - 4, sn, &(pdu->msg[pdu->N_bytes - 4]))) { + log->error_hex(pdu->msg, pdu->N_bytes, "%s Dropping PDU", rrc->get_rb_name(lcid).c_str()); + goto exit; + } + } + + pdcp_unpack_control_pdu(pdu.get(), &sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn); + } + // pass to RRC + rrc->write_pdu(lcid, std::move(pdu)); + } +exit: + rx_count++; +} + +/**************************************************************************** + * Rx data/control handler functions + * Ref: 3GPP TS 36.323 v10.1.0 Section 5.1.2 + ***************************************************************************/ +// DRBs mapped on RLC UM (5.1.2.1.3) +void pdcp_entity_lte::handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu) +{ + uint32_t sn; + if (12 == cfg.sn_len) { + pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn); + } else { + pdcp_unpack_data_pdu_short_sn(pdu.get(), &sn); + } + + if (sn < next_pdcp_rx_sn) { + rx_hfn++; + } + + uint32_t count = (rx_hfn << cfg.sn_len) | sn; + if (do_encryption) { + cipher_decrypt(pdu->msg, pdu->N_bytes, count, pdu->msg); + log->debug_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); + } + + next_pdcp_rx_sn = sn + 1; + if (next_pdcp_rx_sn > maximum_pdcp_sn) { + next_pdcp_rx_sn = 0; + rx_hfn++; + } + + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn); + return; +} + +// DRBs mapped on RLC AM, without re-ordering (5.1.2.1.2) +void pdcp_entity_lte::handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu) +{ + uint32_t sn, count; + pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn); + + int32_t last_submit_diff_sn = last_submitted_pdcp_rx_sn - sn; + int32_t sn_diff_last_submit = sn - last_submitted_pdcp_rx_sn; + int32_t sn_diff_next_pdcp_rx_sn = sn - next_pdcp_rx_sn; + + log->debug("RX HFN: %d, SN: %d, Last_Submitted_PDCP_RX_SN: %d, Next_PDCP_RX_SN %d\n", + rx_hfn, + sn, + last_submitted_pdcp_rx_sn, + next_pdcp_rx_sn); + + bool discard = false; + if ((0 <= sn_diff_last_submit && sn_diff_last_submit > (int32_t)reordering_window) || + (0 <= last_submit_diff_sn && last_submit_diff_sn < (int32_t)reordering_window)) { + log->debug("|SN - last_submitted_sn| is larger than re-ordering window.\n"); + if (sn > next_pdcp_rx_sn) { + count = (rx_hfn - 1) << cfg.sn_len | sn; + } else { + count = rx_hfn << cfg.sn_len | sn; + } + discard = true; + } else if ((int32_t)(next_pdcp_rx_sn - sn) > (int32_t)reordering_window) { + log->debug("(Next_PDCP_RX_SN - SN) is larger than re-ordering window.\n"); + rx_hfn++; + count = (rx_hfn << cfg.sn_len) | sn; + next_pdcp_rx_sn = sn + 1; + } else if (sn_diff_next_pdcp_rx_sn >= (int32_t)reordering_window) { + log->debug("(SN - Next_PDCP_RX_SN) is larger or equal than re-ordering window.\n"); + count = ((rx_hfn - 1) << cfg.sn_len) | sn; + } else if (sn >= next_pdcp_rx_sn) { + log->debug("SN is larger or equal than Next_PDCP_RX_SN.\n"); + count = (rx_hfn << cfg.sn_len) | sn; + next_pdcp_rx_sn = sn + 1; + if (next_pdcp_rx_sn > maximum_pdcp_sn) { + next_pdcp_rx_sn = 0; + rx_hfn++; + } + } else if (sn < next_pdcp_rx_sn) { + log->debug("SN is smaller than Next_PDCP_RX_SN.\n"); + count = (rx_hfn << cfg.sn_len) | sn; + } + + // FIXME Check if PDU is not due to re-establishment of lower layers? + cipher_decrypt(pdu->msg, pdu->N_bytes, count, pdu->msg); + log->debug_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); + + if (!discard) { + last_submitted_pdcp_rx_sn = sn; + } + return; +} + +/**************************************************************************** + * Security functions + ***************************************************************************/ +uint32_t pdcp_entity_lte::get_dl_count() +{ + return rx_count; +} + +uint32_t pdcp_entity_lte::get_ul_count() +{ + return tx_count; +} + +/**************************************************************************** + * Pack/Unpack helper functions + * Ref: 3GPP TS 36.323 v10.1.0 + ***************************************************************************/ +void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t* sdu) +{ + // Make room and add header + sdu->msg--; + sdu->N_bytes++; + *sdu->msg = sn & 0x1F; + + // Add MAC + sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 24) & 0xFF; + sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 16) & 0xFF; + sdu->msg[sdu->N_bytes++] = (PDCP_CONTROL_MAC_I >> 8) & 0xFF; + sdu->msg[sdu->N_bytes++] = PDCP_CONTROL_MAC_I & 0xFF; +} + +void pdcp_unpack_control_pdu(byte_buffer_t* pdu, uint32_t* sn) +{ + // Strip header + *sn = *pdu->msg & 0x1F; + pdu->msg++; + pdu->N_bytes--; + + // Strip MAC + pdu->N_bytes -= 4; + + // TODO: integrity check MAC +} + +void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t* sdu) +{ + // Make room and add header + sdu->msg--; + sdu->N_bytes++; + sdu->msg[0] = (PDCP_D_C_DATA_PDU << 7) | (sn & 0x7F); +} + +void pdcp_unpack_data_pdu_short_sn(byte_buffer_t* sdu, uint32_t* sn) +{ + // Strip header + *sn = sdu->msg[0] & 0x7F; + sdu->msg++; + sdu->N_bytes--; +} + +void pdcp_pack_data_pdu_long_sn(uint32_t sn, byte_buffer_t* sdu) +{ + // Make room and add header + sdu->msg -= 2; + sdu->N_bytes += 2; + sdu->msg[0] = (PDCP_D_C_DATA_PDU << 7) | ((sn >> 8) & 0x0F); + sdu->msg[1] = sn & 0xFF; +} + +void pdcp_unpack_data_pdu_long_sn(byte_buffer_t* sdu, uint32_t* sn) +{ + // Strip header + *sn = (sdu->msg[0] & 0x0F) << 8; + *sn |= sdu->msg[1]; + sdu->msg += 2; + sdu->N_bytes -= 2; +} +} // namespace srslte diff --git a/lib/src/upper/pdcp_entity_nr.cc b/lib/src/upper/pdcp_entity_nr.cc new file mode 100644 index 000000000..d14a8dd94 --- /dev/null +++ b/lib/src/upper/pdcp_entity_nr.cc @@ -0,0 +1,261 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/upper/pdcp_entity_nr.h" +#include "srslte/common/int_helpers.h" +#include "srslte/common/security.h" + +namespace srslte { + +pdcp_entity_nr::pdcp_entity_nr() {} + +pdcp_entity_nr::~pdcp_entity_nr() {} + +void pdcp_entity_nr::init(srsue::rlc_interface_pdcp* rlc_, + srsue::rrc_interface_pdcp* rrc_, + srsue::gw_interface_pdcp* gw_, + srslte::log* log_, + uint32_t lcid_, + pdcp_config_t cfg_) +{ + rlc = rlc_; + rrc = rrc_; + gw = gw_; + log = log_; + lcid = lcid_; + cfg = cfg_; + active = true; + do_integrity = false; + do_encryption = false; + + window_size = 1 << (cfg.sn_len - 1); +} + +// Reestablishment procedure: 38.323 5.2 +void pdcp_entity_nr::reestablish() +{ + log->info("Re-establish %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id); + // TODO +} + +// Used to stop/pause the entity (called on RRC conn release) +void pdcp_entity_nr::reset() +{ + active = false; + if (log) { + log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str()); + } +} + +// SDAP/RRC interface +void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu, bool blocking) +{ + log->info_hex(sdu->msg, + sdu->N_bytes, + "TX %s SDU, do_integrity = %s, do_encryption = %s", + rrc->get_rb_name(lcid).c_str(), + (do_integrity) ? "true" : "false", + (do_encryption) ? "true" : "false"); + + // Start discard timer TODO + // Perform header compression TODO + + // Integrity protection + uint8_t mac[4]; + integrity_generate(sdu->msg, sdu->N_bytes, tx_next, mac); + + // Ciphering + cipher_encrypt(sdu->msg, sdu->N_bytes, tx_next, sdu->msg); + + // Write PDCP header info + write_data_header(sdu, tx_next); + + // Append MAC-I + append_mac(sdu, mac); + + // Increment TX_NEXT + tx_next++; + + // Check if PDCP is associated with more than on RLC entity TODO + // Write to lower layers + rlc->write_sdu(lcid, std::move(sdu), blocking); +} + +// RLC interface +void pdcp_entity_nr::write_pdu(unique_byte_buffer_t pdu) +{ + log->info_hex(pdu->msg, + pdu->N_bytes, + "RX %s PDU (%d B), do_integrity = %s, do_encryption = %s", + rrc->get_rb_name(lcid).c_str(), + pdu->N_bytes, + (do_integrity) ? "true" : "false", + (do_encryption) ? "true" : "false"); + + // Sanity check + if (pdu->N_bytes <= cfg.hdr_len_bytes) { + return; + } + + // Extract RCVD_SN from header + uint32_t rcvd_sn = read_data_header(pdu); + + // Extract MAC + uint8_t mac[4]; + extract_mac(pdu, mac); + + // Calculate RCVD_COUNT + uint32_t rcvd_hfn, rcvd_count; + if ((int64_t)rcvd_sn < (int64_t)SN(rx_deliv) - (int64_t)window_size) { + rcvd_hfn = HFN(rx_deliv) + 1; + } else if (rcvd_sn >= SN(rx_deliv) + window_size) { + rcvd_hfn = HFN(rx_deliv) - 1; + } else { + rcvd_hfn = HFN(rx_deliv); + } + rcvd_count = COUNT(rcvd_hfn, rcvd_sn); + + // Decripting + cipher_decrypt(pdu->msg, pdu->N_bytes, rcvd_count, pdu->msg); + + // Integrity check + bool is_valid = integrity_verify(pdu->msg, pdu->N_bytes, rcvd_count, mac); + if (!is_valid) { + return; // Invalid packet, drop. + } + + // Check valid rcvd_count + if (rcvd_count < rx_deliv) { + return; // Invalid count, drop. + } + + // TODO check if PDU has been received + // TODO Store PDU in reception buffer + + // Update RX_NEXT + if (rcvd_count >= rx_next) { + rx_next = rcvd_count + 1; + } + + // TODO if out-of-order configured, submit to upper layer + + if (rcvd_count == rx_deliv) { + // Deliver to upper layers (TODO queueing needs to be implemented) + if (is_srb()) { + rrc->write_pdu(lcid, std::move(pdu)); + } else { + gw->write_pdu(lcid, std::move(pdu)); + } + + // Update RX_DELIV + rx_deliv = rcvd_count + 1; // TODO needs to be corrected when queueing is implemented + printf("New RX_deliv %d, rcvd_count %d\n", rx_deliv, rcvd_count); + } + + // Not clear how to update RX_DELIV without reception buffer (TODO) + + // TODO handle reordering timers +} + +uint32_t pdcp_entity_nr::read_data_header(const unique_byte_buffer_t& pdu) +{ + // Check PDU is long enough to extract header + if (pdu->N_bytes <= cfg.hdr_len_bytes) { + log->error("PDU too small to extract header\n"); + return 0; + } + + // Extract RCVD_SN + uint16_t rcvd_sn_16 = 0; + uint32_t rcvd_sn_32 = 0; + switch (cfg.sn_len) { + case PDCP_SN_LEN_12: + srslte::uint8_to_uint16(pdu->msg, &rcvd_sn_16); + rcvd_sn_32 = SN(rcvd_sn_16); + break; + case PDCP_SN_LEN_18: + srslte::uint8_to_uint24(pdu->msg, &rcvd_sn_32); + rcvd_sn_32 = SN(rcvd_sn_32); + break; + break; + default: + log->error("Cannot extract RCVD_SN, invalid SN length configured: %d\n", cfg.sn_len); + } + + // Discard header + pdu->msg += cfg.hdr_len_bytes; + pdu->N_bytes -= cfg.hdr_len_bytes; + return rcvd_sn_32; +} + +void pdcp_entity_nr::write_data_header(const srslte::unique_byte_buffer_t& sdu, uint32_t count) +{ + // Add room for header + if (cfg.hdr_len_bytes > sdu->get_headroom()) { + log->error("Not enough space to add header\n"); + return; + } + sdu->msg -= cfg.hdr_len_bytes; + sdu->N_bytes += cfg.hdr_len_bytes; + + // Add SN + switch (cfg.sn_len) { + case PDCP_SN_LEN_12: + srslte::uint16_to_uint8(SN(count), sdu->msg); + if (is_drb()) { + sdu->msg[0] |= 0x80; // On Data PDUs for DRBs we must set the D flag. + } + break; + case PDCP_SN_LEN_18: + srslte::uint24_to_uint8(SN(count), sdu->msg); + sdu->msg[0] |= 0x80; // Data PDU and SN LEN 18 implies DRB, D flag must be present + break; + default: + log->error("Invalid SN length configuration: %d bits\n", cfg.sn_len); + } +} + +void pdcp_entity_nr::extract_mac(const unique_byte_buffer_t& pdu, uint8_t* mac) +{ + // Check enough space for MAC + if (pdu->N_bytes < 4) { + log->error("PDU too small to extract MAC-I\n"); + return; + } + + // Extract MAC + memcpy(mac, &pdu->msg[pdu->N_bytes - 4], 4); + pdu->N_bytes -= 4; +} + +void pdcp_entity_nr::append_mac(const unique_byte_buffer_t& sdu, uint8_t* mac) +{ + // Check enough space for MAC + if (sdu->N_bytes + 4 > sdu->get_tailroom()) { + log->error("Not enough space to add MAC-I\n"); + return; + } + + // Append MAC + memcpy(&sdu->msg[sdu->N_bytes], mac, 4); + sdu->N_bytes += 4; +} +} // namespace srslte diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index f68273661..802b738dd 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -53,12 +53,12 @@ rlc::~rlc() void rlc::init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, - mac_interface_timers* mac_timers_, + srslte::timers* timers_, uint32_t lcid_) { - pdcp = pdcp_; - rrc = rrc_; - mac_timers = mac_timers_; + pdcp = pdcp_; + rrc = rrc_; + timers = timers_; default_lcid = lcid_; gettimeofday(&metrics_time[1], NULL); @@ -384,13 +384,13 @@ void rlc::add_bearer(uint32_t lcid, rlc_config_t cnfg) if (not valid_lcid(lcid)) { switch (cnfg.rlc_mode) { case rlc_mode_t::tm: - rlc_entity = new rlc_tm(rlc_log, lcid, pdcp, rrc, mac_timers); + rlc_entity = new rlc_tm(rlc_log, lcid, pdcp, rrc, timers); break; case rlc_mode_t::am: - rlc_entity = new rlc_am(rlc_log, lcid, pdcp, rrc, mac_timers); + rlc_entity = new rlc_am(rlc_log, lcid, pdcp, rrc, timers); break; case rlc_mode_t::um: - rlc_entity = new rlc_um(rlc_log, lcid, pdcp, rrc, mac_timers); + rlc_entity = new rlc_um(rlc_log, lcid, pdcp, rrc, timers); break; default: rlc_log->error("Cannot add RLC entity - invalid mode\n"); @@ -428,10 +428,10 @@ unlock_and_exit: void rlc::add_bearer_mrb(uint32_t lcid) { pthread_rwlock_wrlock(&rwlock); - rlc_common *rlc_entity = NULL; + rlc_common* rlc_entity = NULL; if (not valid_lcid_mrb(lcid)) { - rlc_entity = new rlc_um(rlc_log, lcid, pdcp, rrc, mac_timers); + rlc_entity = new rlc_um(rlc_log, lcid, pdcp, rrc, timers); // configure and add to array if (not rlc_entity->configure(rlc_config_t::mch_config())) { rlc_log->error("Error configuring RLC entity\n."); @@ -523,7 +523,7 @@ exit: void rlc::suspend_bearer(uint32_t lcid) { - pthread_rwlock_wrlock(&rwlock); + pthread_rwlock_rdlock(&rwlock); if (valid_lcid(lcid)) { if (rlc_array.at(lcid)->suspend()) { @@ -540,7 +540,7 @@ void rlc::suspend_bearer(uint32_t lcid) void rlc::resume_bearer(uint32_t lcid) { - pthread_rwlock_wrlock(&rwlock); + pthread_rwlock_rdlock(&rwlock); rlc_log->info("Resuming radio bearer %s\n", rrc->get_rb_name(lcid).c_str()); if (valid_lcid(lcid)) { diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index cf188cb92..d00dbd473 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -32,25 +32,21 @@ namespace srslte { -rlc_am::rlc_am(srslte::log* log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srslte::mac_interface_timers* mac_timers_) : +rlc_am::rlc_am(srslte::log* log_, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srslte::timers* timers_) : log(log_), rrc(rrc_), pdcp(pdcp_), - mac_timers(mac_timers_), + timers(timers_), lcid(lcid_), tx(this), rx(this) { } -rlc_am::~rlc_am() -{ -} - // Applies new configuration. Must be just reestablished or initiated bool rlc_am::configure(rlc_config_t cfg_) { @@ -170,11 +166,11 @@ rlc_am::rlc_am_tx::rlc_am_tx(rlc_am* parent_) : log(parent_->log), pool(byte_buffer_pool::get_instance()) { - poll_retx_timer_id = parent->mac_timers->timer_get_unique_id(); - poll_retx_timer = parent->mac_timers->timer_get(poll_retx_timer_id); + poll_retx_timer_id = parent->timers->get_unique_id(); + poll_retx_timer = parent->timers->get(poll_retx_timer_id); - status_prohibit_timer_id = parent->mac_timers->timer_get_unique_id(); - status_prohibit_timer = parent->mac_timers->timer_get(status_prohibit_timer_id); + status_prohibit_timer_id = parent->timers->get_unique_id(); + status_prohibit_timer = parent->timers->get(status_prohibit_timer_id); pthread_mutex_init(&mutex, NULL); } @@ -182,10 +178,10 @@ rlc_am::rlc_am_tx::rlc_am_tx(rlc_am* parent_) : rlc_am::rlc_am_tx::~rlc_am_tx() { poll_retx_timer->stop(); - parent->mac_timers->timer_release_id(poll_retx_timer_id); + parent->timers->release_id(poll_retx_timer_id); status_prohibit_timer->stop(); - parent->mac_timers->timer_release_id(status_prohibit_timer_id); + parent->timers->release_id(status_prohibit_timer_id); pthread_mutex_destroy(&mutex); } @@ -225,11 +221,11 @@ void rlc_am::rlc_am_tx::stop() tx_enabled = false; - if (parent->mac_timers != NULL && poll_retx_timer != NULL) { + if (parent->timers != NULL && poll_retx_timer != NULL) { poll_retx_timer->stop(); } - if (parent->mac_timers != NULL && status_prohibit_timer != NULL) { + if (parent->timers != NULL && status_prohibit_timer != NULL) { status_prohibit_timer->stop(); } @@ -1124,8 +1120,8 @@ rlc_am::rlc_am_rx::rlc_am_rx(rlc_am* parent_) : pool(byte_buffer_pool::get_instance()), log(parent_->log) { - reordering_timer_id = parent->mac_timers->timer_get_unique_id(); - reordering_timer = parent->mac_timers->timer_get(reordering_timer_id); + reordering_timer_id = parent->timers->get_unique_id(); + reordering_timer = parent->timers->get(reordering_timer_id); pthread_mutex_init(&mutex, NULL); } @@ -1133,7 +1129,7 @@ rlc_am::rlc_am_rx::rlc_am_rx(rlc_am* parent_) : rlc_am::rlc_am_rx::~rlc_am_rx() { reordering_timer->stop(); - parent->mac_timers->timer_release_id(reordering_timer_id); + parent->timers->release_id(reordering_timer_id); pthread_mutex_destroy(&mutex); } @@ -1166,7 +1162,7 @@ void rlc_am::rlc_am_rx::stop() { pthread_mutex_lock(&mutex); - if (parent->mac_timers != NULL && reordering_timer != NULL) { + if (parent->timers != NULL && reordering_timer != NULL) { reordering_timer->stop(); } @@ -1633,6 +1629,14 @@ int rlc_am::rlc_am_rx::get_status_pdu(rlc_status_pdu_t* status, const uint32_t m if (status->N_nack >= 1) { log->debug("Removing last NACK SN=%d\n", status->nacks[status->N_nack].nack_sn); status->N_nack--; + // make sure we don't have the current ACK_SN in the NACK list + if (rlc_am_is_valid_status_pdu(*status) == false) { + // No space to send any NACKs + log->debug("Resetting N_nack to zero\n"); + status->N_nack = 0; + } + } else { + log->error("Failed to generate small enough status PDU\n"); } break; } @@ -1786,13 +1790,11 @@ bool rlc_am::rlc_am_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rl return true; } -bool rlc_am::rlc_am_rx::inside_rx_window(uint16_t sn) +bool rlc_am::rlc_am_rx::inside_rx_window(const int16_t sn) { - if(RX_MOD_BASE(sn) >= RX_MOD_BASE(vr_r) && - RX_MOD_BASE(sn) < RX_MOD_BASE(vr_mr)) - { + if (RX_MOD_BASE(sn) >= RX_MOD_BASE(static_cast(vr_r)) && RX_MOD_BASE(sn) < RX_MOD_BASE(vr_mr)) { return true; - }else{ + } else { return false; } } @@ -2030,6 +2032,16 @@ int rlc_am_write_status_pdu(rlc_status_pdu_t *status, uint8_t *payload) return tmp.N_bits/8; } +bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status) +{ + for (uint16_t i = 0; i < status.N_nack; ++i) { + if (status.nacks[i].nack_sn == status.ack_sn) { + return false; + } + } + return true; +} + uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t *header) { uint32_t len = 2; // Fixed part is 2 bytes diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index bcc6757fc..33099fc1d 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -23,12 +23,12 @@ namespace srslte { -rlc_tm::rlc_tm(srslte::log* log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srslte::mac_interface_timers* mac_timers_, - uint32_t queue_len_) : +rlc_tm::rlc_tm(srslte::log* log_, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srslte::timers* timers_, + uint32_t queue_len_) : ul_queue(queue_len_), log(log_), pdcp(pdcp_), @@ -193,4 +193,4 @@ void rlc_tm::write_pdu(uint8_t *payload, uint32_t nof_bytes) } } -} // namespace srsue +} // namespace srslte diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index aa059d24a..1700ca8ff 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -22,7 +22,7 @@ #include "srslte/upper/rlc_um.h" #include -#define RX_MOD_BASE(x) (((x)-vr_uh-cfg.rx_window_size)%cfg.rx_mod) +#define RX_MOD_BASE(x) (((x)-vr_uh - cfg.um.rx_window_size) % cfg.um.rx_mod) using namespace asn1::rrc; @@ -32,13 +32,12 @@ rlc_um::rlc_um(srslte::log* log_, uint32_t lcid_, srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, - mac_interface_timers* mac_timers_) : + srslte::timers* timers_) : lcid(lcid_), pool(byte_buffer_pool::get_instance()), rrc(rrc_), log(log_), - tx(log_), - rx(log_, lcid_, pdcp_, rrc_, mac_timers_) + rx(log_, lcid_, pdcp_, rrc_, timers_) { } @@ -60,31 +59,51 @@ bool rlc_um::configure(rlc_config_t cnfg_) return false; } - if (not tx.configure(cfg, rb_name)) { - return false; - } + if (cfg.type == rlc_type_t::lte) { + tx.reset(new rlc_um_tx(log)); + if (not tx->configure(cfg, rb_name)) { + return false; + } - log->info("%s configured in %s: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", - rb_name.c_str(), - srslte::to_string(cnfg_.rlc_mode).c_str(), - cfg.um.t_reordering, - srslte::to_number(cfg.um.rx_sn_field_length), - srslte::to_number(cfg.um.tx_sn_field_length)); + log->info("%s configured in %s: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", + rb_name.c_str(), + srslte::to_string(cnfg_.rlc_mode).c_str(), + cfg.um.t_reordering, + srslte::to_number(cfg.um.rx_sn_field_length), + srslte::to_number(cfg.um.tx_sn_field_length)); + } else { + tx.reset(new rlc_um_tx_nr(log)); + if (not tx->configure(cfg, rb_name)) { + return false; + } + + log->info("%s configured in %s: sn_field_length=%u bits\n", + rb_name.c_str(), + srslte::to_string(cnfg_.rlc_mode).c_str(), + srslte::to_number(cfg.um_nr.sn_field_length)); + } return true; } bool rlc_um::rlc_um_rx::configure(rlc_config_t cnfg_, std::string rb_name_) { - cfg = cnfg_.um; + cfg = cnfg_; - if (cfg.rx_mod == 0) { - log->error("Error configuring %s RLC UM: rx_mod==0\n", get_rb_name()); - return false; - } + if (cfg.type == rlc_type_t::lte) { + if (cfg.um.rx_mod == 0) { + log->error("Error configuring %s RLC UM: rx_mod==0\n", get_rb_name()); + return false; + } - // set reordering timer - if (reordering_timer != NULL) { - reordering_timer->set(this, cfg.t_reordering); + // set reordering timer + if (reordering_timer != NULL) { + reordering_timer->set(this, cfg.um.t_reordering); + } + } else { + if (cfg.um_nr.mod == 0) { + log->error("Error configuring %s RLC UM: rx_mod==0\n", get_rb_name()); + return false; + } } rb_name = rb_name_; @@ -94,13 +113,12 @@ bool rlc_um::rlc_um_rx::configure(rlc_config_t cnfg_, std::string rb_name_) return true; } - -void rlc_um::empty_queue() { +void rlc_um::empty_queue() +{ // Drop all messages in TX SDU queue - tx.empty_queue(); + tx->empty_queue(); } - bool rlc_um::is_mrb() { return cfg.um.is_mrb; @@ -109,14 +127,16 @@ bool rlc_um::is_mrb() void rlc_um::reestablish() { - tx.reestablish(); // calls stop and enables tx again + tx->reestablish(); // calls stop and enables tx again rx.reestablish(); // nothing else needed } void rlc_um::stop() { - tx.stop(); + if (tx) { + tx->stop(); + } rx.stop(); } @@ -137,9 +157,9 @@ uint32_t rlc_um::get_bearer() void rlc_um::write_sdu(unique_byte_buffer_t sdu, bool blocking) { if (blocking) { - tx.write_sdu(std::move(sdu)); + tx->write_sdu(std::move(sdu)); } else { - tx.try_write_sdu(std::move(sdu)); + tx->try_write_sdu(std::move(sdu)); } } @@ -149,17 +169,17 @@ void rlc_um::write_sdu(unique_byte_buffer_t sdu, bool blocking) bool rlc_um::has_data() { - return tx.has_data(); + return tx->has_data(); } uint32_t rlc_um::get_buffer_state() { - return tx.get_buffer_state(); + return tx->get_buffer_state(); } int rlc_um::read_pdu(uint8_t *payload, uint32_t nof_bytes) { - return tx.build_data_pdu(payload, nof_bytes); + return tx->build_data_pdu(payload, nof_bytes); } void rlc_um::write_pdu(uint8_t *payload, uint32_t nof_bytes) @@ -169,7 +189,7 @@ void rlc_um::write_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t rlc_um::get_num_tx_bytes() { - return tx.get_num_tx_bytes(); + return tx->get_num_tx_bytes(); } uint32_t rlc_um::get_num_rx_bytes() @@ -179,7 +199,7 @@ uint32_t rlc_um::get_num_rx_bytes() void rlc_um::reset_metrics() { - tx.reset_metrics(); + tx->reset_metrics(); rx.reset_metrics(); } @@ -199,57 +219,29 @@ std::string rlc_um::get_rb_name(srsue::rrc_interface_rlc *rrc, uint32_t lcid, bo } } - /**************************************************************************** - * Tx subclass implementation + * Tx subclass implementation (base) ***************************************************************************/ -rlc_um::rlc_um_tx::rlc_um_tx(srslte::log* log_) : pool(byte_buffer_pool::get_instance()), log(log_) -{ - pthread_mutex_init(&mutex, NULL); -} - +rlc_um::rlc_um_tx_base::rlc_um_tx_base(srslte::log* log_) : pool(byte_buffer_pool::get_instance()), log(log_) {} -rlc_um::rlc_um_tx::~rlc_um_tx() -{ - pthread_mutex_destroy(&mutex); -} +rlc_um::rlc_um_tx_base::~rlc_um_tx_base() {} -bool rlc_um::rlc_um_tx::configure(rlc_config_t cnfg_, std::string rb_name_) -{ - cfg = cnfg_.um; - - if (cfg.tx_mod == 0) { - log->error("Error configuring %s RLC UM: tx_mod==0\n", get_rb_name()); - return false; - } - - tx_sdu_queue.resize(cnfg_.tx_queue_length); - - rb_name = rb_name_; - tx_enabled = true; - - return true; -} - - -void rlc_um::rlc_um_tx::stop() +void rlc_um::rlc_um_tx_base::stop() { tx_enabled = false; empty_queue(); } - -void rlc_um::rlc_um_tx::reestablish() +void rlc_um::rlc_um_tx_base::reestablish() { stop(); tx_enabled = true; } - -void rlc_um::rlc_um_tx::empty_queue() +void rlc_um::rlc_um_tx_base::empty_queue() { - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); // deallocate all SDUs in transmit queue while(tx_sdu_queue.size() > 0) { @@ -258,37 +250,32 @@ void rlc_um::rlc_um_tx::empty_queue() // deallocate SDU that is currently processed tx_sdu.reset(); - - pthread_mutex_unlock(&mutex); } - -uint32_t rlc_um::rlc_um_tx::get_num_tx_bytes() +uint32_t rlc_um::rlc_um_tx_base::get_num_tx_bytes() { return num_tx_bytes; } - -void rlc_um::rlc_um_tx::reset_metrics() +void rlc_um::rlc_um_tx_base::reset_metrics() { - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); num_tx_bytes = 0; - pthread_mutex_unlock(&mutex); } - -bool rlc_um::rlc_um_tx::has_data() +bool rlc_um::rlc_um_tx_base::has_data() { return (tx_sdu != NULL || !tx_sdu_queue.is_empty()); } - -uint32_t rlc_um::rlc_um_tx::get_buffer_state() +uint32_t rlc_um::rlc_um_tx_base::get_buffer_state() { + std::lock_guard lock(mutex); + // Bytes needed for tx SDUs uint32_t n_sdus = tx_sdu_queue.size(); uint32_t n_bytes = tx_sdu_queue.size_bytes(); - if(tx_sdu) { + if (tx_sdu) { n_sdus++; n_bytes += tx_sdu->N_bytes; } @@ -300,12 +287,12 @@ uint32_t rlc_um::rlc_um_tx::get_buffer_state() // Room needed for fixed header? if(n_bytes > 0) - n_bytes += (cfg.is_mrb)?2:3; + n_bytes += (cfg.um.is_mrb) ? 2 : 3; return n_bytes; } -void rlc_um::rlc_um_tx::write_sdu(unique_byte_buffer_t sdu) +void rlc_um::rlc_um_tx_base::write_sdu(unique_byte_buffer_t sdu) { if (!tx_enabled) { return; @@ -319,7 +306,7 @@ void rlc_um::rlc_um_tx::write_sdu(unique_byte_buffer_t sdu) } } -void rlc_um::rlc_um_tx::try_write_sdu(unique_byte_buffer_t sdu) +void rlc_um::rlc_um_tx_base::try_write_sdu(unique_byte_buffer_t sdu) { if (!tx_enabled) { sdu.reset(); @@ -346,35 +333,67 @@ void rlc_um::rlc_um_tx::try_write_sdu(unique_byte_buffer_t sdu) } } - -int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) +int rlc_um::rlc_um_tx_base::build_data_pdu(uint8_t* payload, uint32_t nof_bytes) { - pthread_mutex_lock(&mutex); - log->debug("MAC opportunity - %d bytes\n", nof_bytes); + unique_byte_buffer_t pdu; + { + std::lock_guard lock(mutex); + log->debug("MAC opportunity - %d bytes\n", nof_bytes); - if (not tx_enabled) { - pthread_mutex_unlock(&mutex); - return 0; - } + if (not tx_enabled) { + return 0; + } - if(!tx_sdu && tx_sdu_queue.size() == 0) { - log->info("No data available to be sent\n"); - pthread_mutex_unlock(&mutex); - return 0; + if (!tx_sdu && tx_sdu_queue.size() == 0) { + log->info("No data available to be sent\n"); + return 0; + } + + pdu = allocate_unique_buffer(*pool); + if (!pdu || pdu->N_bytes != 0) { + log->error("Failed to allocate PDU buffer\n"); + return 0; + } } + return build_data_pdu(std::move(pdu), payload, nof_bytes); +} - unique_byte_buffer_t pdu = allocate_unique_buffer(*pool); - if(!pdu || pdu->N_bytes != 0) { - log->error("Failed to allocate PDU buffer\n"); - pthread_mutex_unlock(&mutex); - return 0; +const char* rlc_um::rlc_um_tx_base::get_rb_name() +{ + return rb_name.c_str(); +} + +/**************************************************************************** + * Tx Subclass implementation for LTE + ***************************************************************************/ + +rlc_um::rlc_um_tx::rlc_um_tx(srslte::log* log_) : rlc_um_tx_base(log_) {} + +bool rlc_um::rlc_um_tx::configure(rlc_config_t cnfg_, std::string rb_name_) +{ + cfg = cnfg_; + + if (cfg.um.tx_mod == 0) { + log->error("Error configuring %s RLC UM: tx_mod==0\n", get_rb_name()); + return false; } + tx_sdu_queue.resize(cnfg_.tx_queue_length); + + rb_name = rb_name_; + tx_enabled = true; + + return true; +} + +int rlc_um::rlc_um_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t* payload, uint32_t nof_bytes) +{ + std::lock_guard lock(mutex); rlc_umd_pdu_header_t header; header.fi = RLC_FI_FIELD_START_AND_END_ALIGNED; header.sn = vt_us; header.N_li = 0; - header.sn_size = cfg.tx_sn_field_length; + header.sn_size = cfg.um.tx_sn_field_length; uint32_t to_move = 0; uint32_t last_li = 0; @@ -387,7 +406,6 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) { log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", get_rb_name(), nof_bytes, head_len); - pthread_mutex_unlock(&mutex); return 0; } @@ -446,7 +464,7 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Set SN header.sn = vt_us; - vt_us = (vt_us + 1)%cfg.tx_mod; + vt_us = (vt_us + 1) % cfg.um.tx_mod; // Add header and TX rlc_um_write_data_pdu_header(&header, pdu.get()); @@ -459,54 +477,152 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) num_tx_bytes += ret; - pthread_mutex_unlock(&mutex); return ret; } +void rlc_um::rlc_um_tx::debug_state() +{ + log->debug("%s vt_us = %d\n", get_rb_name(), vt_us); +} + +/**************************************************************************** + * Tx Subclass implementation for NR + ***************************************************************************/ -const char* rlc_um::rlc_um_tx::get_rb_name() +rlc_um::rlc_um_tx_nr::rlc_um_tx_nr(srslte::log* log_) : rlc_um_tx_base(log_) {} + +bool rlc_um::rlc_um_tx_nr::configure(rlc_config_t cnfg_, std::string rb_name_) { - return rb_name.c_str(); + cfg = cnfg_; + + if (cfg.um_nr.mod == 0) { + log->error("Error configuring %s RLC UM: tx_mod==0\n", get_rb_name()); + return false; + } + + tx_sdu_queue.resize(cnfg_.tx_queue_length); + + rb_name = rb_name_; + tx_enabled = true; + + return true; } +int rlc_um::rlc_um_tx_nr::build_data_pdu(unique_byte_buffer_t pdu, uint8_t* payload, uint32_t nof_bytes) +{ + std::lock_guard lock(mutex); + rlc_um_nr_pdu_header_t header = {}; + header.si = rlc_nr_si_field_t::full_sdu; + header.sn = TX_Next; + header.sn_size = cfg.um_nr.sn_field_length; -void rlc_um::rlc_um_tx::debug_state() + uint32_t to_move = 0; + uint8_t* pdu_ptr = pdu->msg; + + int head_len = rlc_um_nr_packed_length(header); + int pdu_space = SRSLTE_MIN(nof_bytes, pdu->get_tailroom()); + + if (pdu_space <= head_len + 1) { + log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", + get_rb_name(), + nof_bytes, + head_len); + return 0; + } + + // Check for SDU segment + if (tx_sdu) { + uint32_t space = pdu_space - head_len; + to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; + log->debug( + "%s adding remainder of SDU segment - %d bytes of %d remaining\n", get_rb_name(), to_move, tx_sdu->N_bytes); + memcpy(pdu_ptr, tx_sdu->msg, to_move); + pdu_ptr += to_move; + pdu->N_bytes += to_move; + tx_sdu->N_bytes -= to_move; + tx_sdu->msg += to_move; + if (tx_sdu->N_bytes == 0) { + log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", get_rb_name(), tx_sdu->get_latency_us()); + tx_sdu.reset(); + header.si = rlc_nr_si_field_t::last_segment; + } else { + header.si = rlc_nr_si_field_t::neither_first_nor_last_segment; + } + pdu_space -= SRSLTE_MIN(to_move, pdu->get_tailroom()); + } else { + // Pull SDU from queue + log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len); + + head_len = rlc_um_nr_packed_length(header); + tx_sdu = tx_sdu_queue.read(); + uint32_t space = pdu_space - head_len; + to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; + log->debug("%s adding new SDU - %d bytes of %d remaining\n", get_rb_name(), to_move, tx_sdu->N_bytes); + memcpy(pdu_ptr, tx_sdu->msg, to_move); + pdu_ptr += to_move; + pdu->N_bytes += to_move; + tx_sdu->N_bytes -= to_move; + tx_sdu->msg += to_move; + if (tx_sdu->N_bytes == 0) { + log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", get_rb_name(), tx_sdu->get_latency_us()); + tx_sdu.reset(); + header.si = rlc_nr_si_field_t::full_sdu; + } else { + header.si = rlc_nr_si_field_t::first_segment; + } + pdu_space -= to_move; + } + + // Update SN if needed + if (header.si == rlc_nr_si_field_t::last_segment) { + TX_Next = (TX_Next + 1) % cfg.um_nr.mod; + } + + // Add header and TX + rlc_um_nr_write_data_pdu_header(header, pdu.get()); + memcpy(payload, pdu->msg, pdu->N_bytes); + uint32_t ret = pdu->N_bytes; + + log->info_hex(payload, ret, "%s Tx PDU SN=%d (%d B)\n", get_rb_name(), header.sn, pdu->N_bytes); + + debug_state(); + + num_tx_bytes += ret; + + return ret; +} + +void rlc_um::rlc_um_tx_nr::debug_state() { - log->debug("%s vt_us = %d\n", get_rb_name(), vt_us); + log->debug("%s TX_Next = %d\n", get_rb_name(), TX_Next); } /**************************************************************************** * Rx subclass implementation ***************************************************************************/ -rlc_um::rlc_um_rx::rlc_um_rx(srslte::log* log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc* pdcp_, - srsue::rrc_interface_rlc* rrc_, - srslte::mac_interface_timers* mac_timers_) : +rlc_um::rlc_um_rx::rlc_um_rx(srslte::log* log_, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srslte::timers* timers_) : pool(byte_buffer_pool::get_instance()), log(log_), pdcp(pdcp_), rrc(rrc_), - mac_timers(mac_timers_), + timers(timers_), lcid(lcid_) { - reordering_timer_id = mac_timers->timer_get_unique_id(); - reordering_timer = mac_timers->timer_get(reordering_timer_id); - - pthread_mutex_init(&mutex, NULL); + reordering_timer_id = timers->get_unique_id(); + reordering_timer = timers->get(reordering_timer_id); } - rlc_um::rlc_um_rx::~rlc_um_rx() { reordering_timer->stop(); - mac_timers->timer_release_id(reordering_timer_id); - - pthread_mutex_destroy(&mutex); + timers->release_id(reordering_timer_id); } - void rlc_um::rlc_um_rx::reestablish() { // try to reassemble any SDUs if possible @@ -517,22 +633,17 @@ void rlc_um::rlc_um_rx::reestablish() } } - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); reset(); rx_enabled = true; - pthread_mutex_unlock(&mutex); } void rlc_um::rlc_um_rx::stop() { - pthread_mutex_lock(&mutex); - + std::lock_guard lock(mutex); reset(); - reordering_timer->stop(); - - pthread_mutex_unlock(&mutex); } void rlc_um::rlc_um_rx::reset() @@ -552,7 +663,7 @@ void rlc_um::rlc_um_rx::reset() void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) { - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); rlc_umd_pdu_t pdu; int header_len = 0; @@ -560,34 +671,33 @@ void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) rlc_umd_pdu_header_t header; if (!rx_enabled) { - goto unlock_and_exit; + return; } num_rx_bytes += nof_bytes; - rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.rx_sn_field_length, &header); + rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.um.rx_sn_field_length, &header); log->info_hex(payload, nof_bytes, "RX %s Rx data PDU SN: %d (%d B)", get_rb_name(), header.sn, nof_bytes); - if(RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh-cfg.rx_window_size) && - RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ur)) - { + if (RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh - cfg.um.rx_window_size) && + RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ur)) { log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", get_rb_name(), header.sn, vr_ur, vr_uh); - goto unlock_and_exit; + return; } it = rx_window.find(header.sn); if(rx_window.end() != it) { log->info("%s Discarding duplicate SN: %d\n", get_rb_name(), header.sn); - goto unlock_and_exit; + return; } // Write to rx window pdu.buf = allocate_unique_buffer(*pool); if (!pdu.buf) { log->error("Discarting packet: no space in buffer pool\n"); - goto unlock_and_exit; + return; } memcpy(pdu.buf->msg, payload, nof_bytes); pdu.buf->N_bytes = nof_bytes; @@ -600,7 +710,7 @@ void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Update vr_uh if(!inside_reordering_window(header.sn)) { - vr_uh = (header.sn + 1)%cfg.rx_mod; + vr_uh = (header.sn + 1) % cfg.um.rx_mod; } // Reassemble and deliver SDUs, while updating vr_ur @@ -625,9 +735,6 @@ void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) } debug_state(); - -unlock_and_exit: - pthread_mutex_unlock(&mutex); } @@ -671,13 +778,14 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() rx_sdu->N_bytes += len; rx_window[vr_ur].buf->msg += len; rx_window[vr_ur].buf->N_bytes -= len; - if((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) || (vr_ur != ((vr_ur_in_rx_sdu+1)%cfg.rx_mod))) { + if ((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) || + (vr_ur != ((vr_ur_in_rx_sdu + 1) % cfg.um.rx_mod))) { log->warning("Dropping remainder of lost PDU (lower edge middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n", vr_ur, vr_ur_in_rx_sdu); rx_sdu->clear(); } else { log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)", get_rb_name(), vr_ur, i); rx_sdu->set_timestamp(); - if(cfg.is_mrb){ + if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { pdcp->write_pdu(lcid, std::move(rx_sdu)); @@ -707,7 +815,7 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() } else { log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", get_rb_name(), vr_ur); rx_sdu->set_timestamp(); - if(cfg.is_mrb){ + if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { pdcp->write_pdu(lcid, std::move(rx_sdu)); @@ -726,7 +834,7 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() rx_window.erase(vr_ur); } - vr_ur = (vr_ur + 1)%cfg.rx_mod; + vr_ur = (vr_ur + 1) % cfg.um.rx_mod; } // Now update vr_ur until we reach an SN we haven't yet received @@ -774,8 +882,17 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() log->info("Updating vr_ur_in_rx_sdu. old=%d, new=%d\n", vr_ur_in_rx_sdu, vr_ur); vr_ur_in_rx_sdu = vr_ur; } else { - log->info_hex(rx_window[vr_ur].buf->msg, len, "Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d\n", - len, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes, vr_ur_in_rx_sdu, vr_ur, cfg.rx_mod, (vr_ur_in_rx_sdu+1)%cfg.rx_mod); + log->info_hex(rx_window[vr_ur].buf->msg, + len, + "Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, " + "vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d\n", + len, + rx_sdu->N_bytes, + rx_window[vr_ur].buf->N_bytes, + vr_ur_in_rx_sdu, + vr_ur, + cfg.um.rx_mod, + (vr_ur_in_rx_sdu + 1) % cfg.um.rx_mod); } memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len); @@ -787,7 +904,7 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() if (pdu_belongs_to_rx_sdu()) { log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", get_rb_name(), vr_ur, i); rx_sdu->set_timestamp(); - if(cfg.is_mrb){ + if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { pdcp->write_pdu(lcid, std::move(rx_sdu)); @@ -833,7 +950,7 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus() } else { log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", get_rb_name(), vr_ur); rx_sdu->set_timestamp(); - if(cfg.is_mrb){ + if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { pdcp->write_pdu(lcid, std::move(rx_sdu)); @@ -851,7 +968,7 @@ clean_up_rx_window: // Clean up rx_window rx_window.erase(vr_ur); - vr_ur = (vr_ur + 1)%cfg.rx_mod; + vr_ur = (vr_ur + 1) % cfg.um.rx_mod; } } @@ -860,7 +977,7 @@ clean_up_rx_window: bool rlc_um::rlc_um_rx::pdu_belongs_to_rx_sdu() { // return true if the currently received SDU - if (((vr_ur_in_rx_sdu + 1)%cfg.rx_mod == vr_ur) || (vr_ur == vr_ur_in_rx_sdu)) { + if (((vr_ur_in_rx_sdu + 1) % cfg.um.rx_mod == vr_ur) || (vr_ur == vr_ur_in_rx_sdu)) { return true; } return false; @@ -871,10 +988,10 @@ bool rlc_um::rlc_um_rx::pdu_belongs_to_rx_sdu() // 36.322 Section 5.1.2.2.1 bool rlc_um::rlc_um_rx::inside_reordering_window(uint16_t sn) { - if (cfg.rx_window_size == 0 || rx_window.empty()) { + if (cfg.um.rx_window_size == 0 || rx_window.empty()) { return true; } - if (RX_MOD_BASE(vr_uh-cfg.rx_window_size) <= RX_MOD_BASE(sn) && RX_MOD_BASE(sn) < RX_MOD_BASE(vr_uh)) { + if (RX_MOD_BASE(vr_uh - cfg.um.rx_window_size) <= RX_MOD_BASE(sn) && RX_MOD_BASE(sn) < RX_MOD_BASE(vr_uh)) { return true; } else { return false; @@ -890,9 +1007,8 @@ uint32_t rlc_um::rlc_um_rx::get_num_rx_bytes() void rlc_um::rlc_um_rx::reset_metrics() { - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); num_rx_bytes = 0; - pthread_mutex_unlock(&mutex); } @@ -902,7 +1018,7 @@ void rlc_um::rlc_um_rx::reset_metrics() void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id) { - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); if (reordering_timer != NULL && reordering_timer_id == timeout_id) { // 36.322 v10 Section 5.1.2.2.4 log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", @@ -916,7 +1032,7 @@ void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id) } while(RX_MOD_BASE(vr_ur) < RX_MOD_BASE(vr_ux)) { - vr_ur = (vr_ur + 1)%cfg.rx_mod; + vr_ur = (vr_ur + 1) % cfg.um.rx_mod; log->debug("Entering Reassemble from timeout id=%d\n", timeout_id); reassemble_rx_sdus(); log->debug("Finished reassemble from timeout id=%d\n", timeout_id); @@ -930,7 +1046,6 @@ void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id) debug_state(); } - pthread_mutex_unlock(&mutex); } /**************************************************************************** @@ -1077,4 +1192,128 @@ bool rlc_um_end_aligned(uint8_t fi) return (fi == RLC_FI_FIELD_START_AND_END_ALIGNED || fi == RLC_FI_FIELD_NOT_START_ALIGNED); } -} // namespace srsue +/**************************************************************************** + * Header pack/unpack helper functions + * Ref: 3GPP TS 38.322 v15.3.0 Section 6.2.2.3 + ***************************************************************************/ + +uint32_t rlc_um_nr_read_data_pdu_header(const byte_buffer_t* pdu, + const rlc_um_nr_sn_size_t sn_size, + rlc_um_nr_pdu_header_t* header) +{ + return rlc_um_nr_read_data_pdu_header(pdu->msg, pdu->N_bytes, sn_size, header); +} + +uint32_t rlc_um_nr_read_data_pdu_header(const uint8_t* payload, + const uint32_t nof_bytes, + const rlc_um_nr_sn_size_t sn_size, + rlc_um_nr_pdu_header_t* header) +{ + uint8_t* ptr = const_cast(payload); + + header->sn_size = sn_size; + + // Fixed part + if (sn_size == rlc_um_nr_sn_size_t::size6bits) { + header->si = (rlc_nr_si_field_t)((*ptr >> 6) & 0x03); // 2 bits SI + header->sn = *ptr & 0x3F; // 6 bits SN + // sanity check + if (header->si == rlc_nr_si_field_t::full_sdu and not header->sn == 0) { + fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); + return 0; + } + ptr++; + } else if (sn_size == rlc_um_nr_sn_size_t::size12bits) { + header->si = (rlc_nr_si_field_t)((*ptr >> 6) & 0x03); // 2 bits SI + header->sn = (*ptr & 0x0F) << 4; // 4 bits SN + + // sanity check + if (header->si == rlc_nr_si_field_t::first_segment) { + // make sure two reserved bits are not set + if (((*ptr >> 4) & 0x03) != 0) { + fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); + return 0; + } + } + + // continue unpacking remaining SN + ptr++; + header->sn |= (*ptr & 0xFF); // 8 bits SN + ptr++; + } else { + fprintf(stderr, "Unsupported SN length\n"); + return 0; + } + + // Read optional part + if (header->si == rlc_nr_si_field_t::last_segment || + header->si == rlc_nr_si_field_t::neither_first_nor_last_segment) { + // read SO + header->so = (*ptr & 0xFF) << 8; + ptr++; + header->so |= (*ptr & 0xFF); + ptr++; + } + + // return consumed bytes + return (ptr - payload); +} + +uint32_t rlc_um_nr_packed_length(const rlc_um_nr_pdu_header_t& header) +{ + uint32_t len = 0; + if (header.si == rlc_nr_si_field_t::full_sdu || header.si == rlc_nr_si_field_t::first_segment) { + len = 1; + if (header.sn_size == rlc_um_nr_sn_size_t::size12bits) { + len++; + } + } else { + if (header.sn_size == rlc_um_nr_sn_size_t::size6bits) { + len = 3; + } else { + len = 4; + } + } + return len; +} + +uint32_t rlc_um_nr_write_data_pdu_header(const rlc_um_nr_pdu_header_t& header, byte_buffer_t* pdu) +{ + // Make room for the header + uint32_t len = rlc_um_nr_packed_length(header); + pdu->msg -= len; + uint8_t* ptr = pdu->msg; + + // write SI field + *ptr = (header.si & 0x03) << 6; // 2 bits SI + + if (header.si == rlc_nr_si_field_t::full_sdu) { + // that's all .. + ptr++; + } else { + if (header.sn_size == rlc_um_nr_sn_size_t::size6bits) { + // write SN + *ptr |= (header.sn & 0x3f); // 6 bit SN + ptr++; + } else { + // 12bit SN + *ptr |= (header.sn & 0xf); // 4 bit SN + ptr++; + *ptr = (header.sn & 0xFF); // remaining 8 bit SN + ptr++; + } + if (header.so) { + // write SO + *ptr = (header.so) >> 8; // first part of SO + ptr++; + *ptr = (header.so & 0xFF); // second part of SO + ptr++; + } + } + + pdu->N_bytes += ptr - pdu->msg; + + return len; +} + +} // namespace srslte diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt index e114eaef2..4fd15f39f 100644 --- a/lib/test/asn1/CMakeLists.txt +++ b/lib/test/asn1/CMakeLists.txt @@ -49,3 +49,7 @@ add_test(srslte_asn1_m2ap_test srslte_asn1_m2ap_test) add_executable(srslte_asn1_nas_test srslte_asn1_nas_test.cc) target_link_libraries(srslte_asn1_nas_test srslte_common srslte_phy srslte_asn1) add_test(srslte_asn1_nas_test srslte_asn1_nas_test) + +add_executable(rrc_asn1_test rrc_asn1_test.cc) +target_link_libraries(rrc_asn1_test rrc_asn1) +add_test(rrc_asn1_test rrc_asn1_test) \ No newline at end of file diff --git a/lib/test/asn1/rrc_asn1_test.cc b/lib/test/asn1/rrc_asn1_test.cc new file mode 100644 index 000000000..033ec4229 --- /dev/null +++ b/lib/test/asn1/rrc_asn1_test.cc @@ -0,0 +1,615 @@ +/* + Copyright 2013-2017 Software Radio Systems Limited + + This file is part of srsLTE + + srsLTE 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. + + srsLTE 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 "srslte/asn1/rrc_asn1.h" +#include +#include + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ + return -1; \ + } \ + } + +using namespace asn1; +using namespace asn1::rrc; + +struct ConsoleLogger { + ConsoleLogger(const std::string& layer_) : layer(layer_) {} + + void log(srsasn_logger_level_t log_level, const char* str) + { + switch (log_level) { + case LOG_LEVEL_DEBUG: + printf("[%s][D] %s", layer.c_str(), str); + break; + case LOG_LEVEL_INFO: + printf("[%s][I] %s", layer.c_str(), str); + break; + case LOG_LEVEL_WARN: + printf("[%s][W] %s", layer.c_str(), str); + break; + case LOG_LEVEL_ERROR: + printf("[%s][E] %s", layer.c_str(), str); + break; + default: + break; + } + } + +private: + std::string layer; +}; +void print_console(srsasn_logger_level_t log_level, void* ctx, const char* str) +{ + ConsoleLogger* logger = (ConsoleLogger*)ctx; + logger->log(log_level, str); +} + +struct TestLogger { + TestLogger(const std::string& layer_) : layer(layer_), last_level(LOG_LEVEL_INFO) {} + void log(srsasn_logger_level_t log_level, const char* str) + { + last_level = log_level; + last_str = str; + } + std::string layer; + srsasn_logger_level_t last_level; + std::string last_str; +}; +void test_print(srsasn_logger_level_t log_level, void* ctx, const char* str) +{ + TestLogger* logger = (TestLogger*)ctx; + logger->log(log_level, str); +} + +ConsoleLogger asn_logger("ASN"); +ConsoleLogger rrc_logger("RRC"); +TestLogger test_logger("TEST"); + +// TESTS + +int test_generic() +{ + pusch_enhance_cfg_r14_c choice_type1; + + // make suce a choice is always started in null mode + TESTASSERT(choice_type1.type() == pusch_enhance_cfg_r14_c::types::nulltype); + + // test logger handler + rrc_log_register_handler(&test_logger, test_print); + std::string test_str = "This is a console test to see if the RRC logger is working fine\n"; + rrc_log_print(LOG_LEVEL_INFO, test_str.c_str()); + TESTASSERT(test_logger.last_str == test_str); + TESTASSERT(test_logger.last_level == LOG_LEVEL_INFO); + // go back to original logger + rrc_log_register_handler(&rrc_logger, print_console); + + // Test deep copy of choice types + sib_type14_r11_s::eab_param_r11_c_ choice2; + choice2.set_eab_per_plmn_list_r11(); + choice2.eab_per_plmn_list_r11().resize(5); + for (uint32_t i = 0; i < 5; ++i) { + choice2.eab_per_plmn_list_r11()[i].eab_cfg_r11_present = true; + } + { + sib_type14_r11_s::eab_param_r11_c_ choice2_cpy(choice2); + TESTASSERT(choice2_cpy.type() == sib_type14_r11_s::eab_param_r11_c_::types::eab_per_plmn_list_r11); + TESTASSERT(choice2_cpy.eab_per_plmn_list_r11()[3].eab_cfg_r11_present); + TESTASSERT(choice2_cpy.eab_per_plmn_list_r11().data() != choice2.eab_per_plmn_list_r11().data()); + + choice2_cpy = choice2; + TESTASSERT(choice2_cpy.type() == sib_type14_r11_s::eab_param_r11_c_::types::eab_per_plmn_list_r11); + TESTASSERT(choice2_cpy.eab_per_plmn_list_r11()[3].eab_cfg_r11_present); + TESTASSERT(choice2_cpy.eab_per_plmn_list_r11().data() != choice2.eab_per_plmn_list_r11().data()); + } + + asn1::rrc::setup_e e; + e.value = setup_opts::setup; + TESTASSERT(e.value == setup_e::setup); + + // + // srb_to_add_mod_s::rlc_cfg_c_ choice_type2; + // choice_type2.set(srb_to_add_mod_s::rlc_cfg_c_::types::explicit_value); + // printf("%s\n", choice_type2.explicit_value().type().to_string().c_str()); + + return 0; +} + +int test_json_printer() +{ + as_cfg_s cfg; + // cfg.source_other_cfg_r9 = asn1::make_copy_ptr(other_cfg_r9_s()); + // To avoid errors with unitialized enums + cfg.source_mib.phich_cfg.phich_res.value = phich_cfg_s::phich_res_e_::half; + cfg.source_mib.phich_cfg.phich_dur.value = phich_cfg_s::phich_dur_e_::normal; + + json_writer jw; + // cfg.to_json(jw); + // printf("%s\n", jw.to_string().c_str()); + return 0; +} + +int test_mib_msg() +{ + uint8_t rrc_msg[] = {0x94, 0x64, 0xC0}; + uint32_t rrc_msg_len = sizeof(rrc_msg); + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg)); + + bcch_bch_msg_s bcch_bch_msg; + bcch_bch_msg.unpack(bref); + + bcch_bch_msg_type_s& bcch_msg = bcch_bch_msg.msg; + TESTASSERT(bcch_msg.dl_bw == mib_s::dl_bw_e_::n75); + TESTASSERT(bcch_msg.phich_cfg.phich_dur == phich_cfg_s::phich_dur_e_::extended); + TESTASSERT(bcch_msg.phich_cfg.phich_res == phich_cfg_s::phich_res_e_::half); + TESTASSERT(bcch_msg.sys_frame_num == "00011001"); + TESTASSERT(bcch_msg.sched_info_sib1_br_r13 == 6); + TESTASSERT(not bcch_msg.sys_info_unchanged_br_r15); + TESTASSERT(bcch_msg.spare == "0000"); + + TESTASSERT((uint32_t)bref.distance(bref0) / 8 == rrc_msg_len); + + uint8_t rrc_msg2[rrc_msg_len]; + bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2)); + bcch_bch_msg.pack(bref2); + TESTASSERT(bref.distance(bref0) == bref2.distance(bit_ref(&rrc_msg2[0], sizeof(rrc_msg2)))); + TESTASSERT(memcmp(rrc_msg2, rrc_msg, rrc_msg_len) == 0); + + // // test print + // json_writer j; + // bcch_bch_msg.to_json(j); + // std::cout << j.to_string() << std::endl; + + return 0; +} + +int test_bcch_dl_sch_msg() +{ + // 000149001250400800094000A03F01000A7FC9800104286C000C + uint8_t rrc_msg[] = {0x00, 0x01, 0x49, 0x00, 0x12, 0x50, 0x40, 0x08, 0x00, 0x09, 0x40, 0x00, 0xA0, + 0x3F, 0x01, 0x00, 0x0A, 0x7F, 0xC9, 0x80, 0x01, 0x04, 0x28, 0x6C, 0x00, 0x0C}; + uint32_t rrc_msg_len = sizeof(rrc_msg); + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg)); + + bcch_dl_sch_msg_s bcch_msg; + bcch_msg.unpack(bref); + + TESTASSERT(bcch_msg.msg.type() == bcch_dl_sch_msg_type_c::types::c1); + TESTASSERT(bcch_msg.msg.c1().type() == bcch_dl_sch_msg_type_c::c1_c_::types::sys_info); + sys_info_s::crit_exts_c_* sinfo = &bcch_msg.msg.c1().sys_info().crit_exts; + TESTASSERT(sinfo->type() == sys_info_s::crit_exts_c_::types::sys_info_r8); + sys_info_r8_ies_s& sys_r8 = sinfo->sys_info_r8(); + TESTASSERT(not sys_r8.non_crit_ext_present); + TESTASSERT(sys_r8.sib_type_and_info.size() == 1); + TESTASSERT(sys_r8.sib_type_and_info[0].type() == sib_info_item_c::types::sib2); + sib_type2_s* sib2 = &(sys_r8.sib_type_and_info[0].sib2()); + TESTASSERT(sib2->ac_barr_info_present); + TESTASSERT(not sib2->mbsfn_sf_cfg_list_present); + TESTASSERT(sib2->ac_barr_info.ac_barr_for_mo_sig_present); + TESTASSERT(not sib2->ac_barr_info.ac_barr_for_mo_data_present); + TESTASSERT(not sib2->ac_barr_info.ac_barr_for_emergency); + TESTASSERT(sib2->ac_barr_info.ac_barr_for_mo_sig.ac_barr_factor == ac_barr_cfg_s::ac_barr_factor_e_::p60); + TESTASSERT(sib2->ac_barr_info.ac_barr_for_mo_sig.ac_barr_time == ac_barr_cfg_s::ac_barr_time_e_::s4); + TESTASSERT(sib2->ac_barr_info.ac_barr_for_mo_sig.ac_barr_for_special_ac == "00000"); + rr_cfg_common_sib_s* res_sib = &sib2->rr_cfg_common; + TESTASSERT(not res_sib->rach_cfg_common.preamb_info.preambs_group_a_cfg_present); + TESTASSERT(res_sib->rach_cfg_common.preamb_info.nof_ra_preambs == + rach_cfg_common_s::preamb_info_s_::nof_ra_preambs_e_::n40); + TESTASSERT(res_sib->rach_cfg_common.pwr_ramp_params.pwr_ramp_step == pwr_ramp_params_s::pwr_ramp_step_e_::db0); + TESTASSERT(res_sib->rach_cfg_common.pwr_ramp_params.preamb_init_rx_target_pwr == + pwr_ramp_params_s::preamb_init_rx_target_pwr_e_::dbm_minus100); + TESTASSERT(res_sib->rach_cfg_common.ra_supervision_info.preamb_trans_max == preamb_trans_max_e::n3); + TESTASSERT(res_sib->rach_cfg_common.ra_supervision_info.ra_resp_win_size == + rach_cfg_common_s::ra_supervision_info_s_::ra_resp_win_size_e_::sf6); + TESTASSERT(res_sib->rach_cfg_common.ra_supervision_info.mac_contention_resolution_timer == + rach_cfg_common_s::ra_supervision_info_s_::mac_contention_resolution_timer_e_::sf8); + TESTASSERT(res_sib->rach_cfg_common.max_harq_msg3_tx == 1); + + TESTASSERT(res_sib->bcch_cfg.mod_period_coeff == bcch_cfg_s::mod_period_coeff_e_::n2); + TESTASSERT(res_sib->pcch_cfg.default_paging_cycle == pcch_cfg_s::default_paging_cycle_e_::rf128); + TESTASSERT(res_sib->pcch_cfg.nb == pcch_cfg_s::nb_e_::four_t); + TESTASSERT(res_sib->prach_cfg.root_seq_idx == 0); + TESTASSERT(res_sib->prach_cfg.prach_cfg_info.prach_cfg_idx == 18); + TESTASSERT(res_sib->prach_cfg.prach_cfg_info.high_speed_flag); + TESTASSERT(res_sib->prach_cfg.prach_cfg_info.zero_correlation_zone_cfg == 0); + TESTASSERT(res_sib->prach_cfg.prach_cfg_info.prach_freq_offset == 0); + TESTASSERT(res_sib->pdsch_cfg_common.ref_sig_pwr == -50); + TESTASSERT(res_sib->pdsch_cfg_common.p_b == 0); + //... + TESTASSERT(res_sib->pucch_cfg_common.n1_pucch_an == 511); + TESTASSERT(res_sib->srs_ul_cfg_common.type() == srs_ul_cfg_common_c::types::release); + TESTASSERT(res_sib->ul_pwr_ctrl_common.p0_nominal_pusch == -50); + //... + TESTASSERT(sib2->freq_info.add_spec_emission == 1); + TESTASSERT(sib2->time_align_timer_common == time_align_timer_e::sf1920); + + TESTASSERT(ceil(bref.distance(bref0) / 8.0) == rrc_msg_len); + + uint8_t rrc_msg2[rrc_msg_len]; + bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2)); + bcch_msg.pack(bref2); + TESTASSERT(bref.distance(bref0) == bref2.distance(bit_ref(&rrc_msg2[0], sizeof(rrc_msg2)))); + TESTASSERT(memcmp(rrc_msg2, rrc_msg, rrc_msg_len) == 0); + + // // test print + // json_writer j; + // bcch_msg.to_json(j); + // std::cout << j.to_string() << std::endl; + + return 0; +} + +int test_bcch_dl_sch_msg2() +{ + // 406404e100070019b018c06010A940 + uint8_t rrc_msg[] = {0x40, 0x64, 0x04, 0xe1, 0x00, 0x07, 0x00, 0x19, 0xb0, 0x18, 0xc0, 0x60, 0x10, 0xA9, 0x40}; + uint32_t rrc_msg_len = sizeof(rrc_msg); + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg)); + + bcch_dl_sch_msg_s bcch_msg; + bcch_msg.unpack(bref); + + TESTASSERT(bcch_msg.msg.type() == bcch_dl_sch_msg_type_c::types::c1); + TESTASSERT(bcch_msg.msg.c1().type() == bcch_dl_sch_msg_type_c::c1_c_::types::sib_type1); + sib_type1_s& sib1 = bcch_msg.msg.c1().sib_type1(); + TESTASSERT(not sib1.p_max_present); + TESTASSERT(sib1.sched_info_list.size() == 1); + TESTASSERT(sib1.sched_info_list[0].si_periodicity.value == sched_info_s::si_periodicity_e_::rf16); + TESTASSERT(sib1.sched_info_list[0].sib_map_info.size() == 1); + TESTASSERT(sib1.sched_info_list[0].sib_map_info[0] == sib_type_e::sib_type13_v920); + + TESTASSERT(ceil(bref.distance(bref0) / 8.0) == rrc_msg_len); + + uint8_t rrc_msg2[rrc_msg_len]; + bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2)); + bcch_msg.pack(bref2); + TESTASSERT(bref.distance(bref0) == bref2.distance(bit_ref(&rrc_msg2[0], sizeof(rrc_msg2)))); + TESTASSERT(memcmp(rrc_msg2, rrc_msg, rrc_msg_len) == 0); + + return 0; +} + +int test_bcch_dl_sch_msg3() +{ + // 00830992B7EC9300A3424B000C000500205D6AAAF04200C01DDC801C4880030010A713228500 + uint8_t rrc_msg[] = {0x00, 0x83, 0x09, 0x92, 0xB7, 0xEC, 0x93, 0x00, 0xA3, 0x42, 0x4B, 0x00, 0x0C, + 0x00, 0x05, 0x00, 0x20, 0x5D, 0x6A, 0xAA, 0xF0, 0x42, 0x00, 0xC0, 0x1D, 0xDC, + 0x80, 0x1C, 0x48, 0x80, 0x03, 0x00, 0x10, 0xA7, 0x13, 0x22, 0x85, 0x00}; + uint32_t rrc_msg_len = sizeof(rrc_msg); + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + + bcch_dl_sch_msg_s bcch_msg; + bcch_msg.unpack(bref); + + TESTASSERT(bcch_msg.msg.type() == bcch_dl_sch_msg_type_c::types::c1); + + TESTASSERT(ceil(bref.distance(rrc_msg) / 8.0) == rrc_msg_len); + + uint8_t rrc_msg2[rrc_msg_len]; + bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2)); + bcch_msg.pack(bref2); + + bref = bit_ref(&rrc_msg2[0], sizeof(rrc_msg2)); + bcch_msg.unpack(bref); + TESTASSERT(bref.distance(rrc_msg2) == bref2.distance(rrc_msg2)); + + bref = bit_ref(&rrc_msg[0], sizeof(rrc_msg)); + bcch_msg.pack(bref); + + TESTASSERT(bref.distance(rrc_msg) == bref2.distance(rrc_msg2)); + TESTASSERT(memcmp(rrc_msg2, rrc_msg, bref.distance_bytes(rrc_msg)) == 0); + + return 0; +} + +int test_dl_dcch_msg() +{ + // 20021008000C406000 + uint8_t rrc_msg[] = {0x20, 0x02, 0x10, 0x08, 0x00, 0x0C, 0x40, 0x60, 0x00}; + uint32_t rrc_msg_len = sizeof(rrc_msg); + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg)); + + dl_dcch_msg_s dl_dcch_msg; + dl_dcch_msg.unpack(bref); + + TESTASSERT(ceil(bref.distance(bref0) / 8.0) == rrc_msg_len); + + TESTASSERT(dl_dcch_msg.msg.type() == dl_dcch_msg_type_c::types::c1); + TESTASSERT(dl_dcch_msg.msg.c1().type() == dl_dcch_msg_type_c::c1_c_::types::rrc_conn_recfg); + rrc_conn_recfg_s* rrc_recfg = &dl_dcch_msg.msg.c1().rrc_conn_recfg(); + TESTASSERT(rrc_recfg->rrc_transaction_id == 0); + TESTASSERT(rrc_recfg->crit_exts.type() == rrc_conn_recfg_s::crit_exts_c_::types::c1); + TESTASSERT(rrc_recfg->crit_exts.c1().type() == rrc_conn_recfg_s::crit_exts_c_::c1_c_::types::rrc_conn_recfg_r8); + rrc_conn_recfg_r8_ies_s* rrc_recfg_r8 = &rrc_recfg->crit_exts.c1().rrc_conn_recfg_r8(); + TESTASSERT(not rrc_recfg_r8->meas_cfg_present); + TESTASSERT(not rrc_recfg_r8->mob_ctrl_info_present); + TESTASSERT(not rrc_recfg_r8->ded_info_nas_list_present); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded_present); + TESTASSERT(not rrc_recfg_r8->security_cfg_ho_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext_present); + + //... + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.drb_to_add_mod_list_present); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.drb_to_add_mod_list.size() == 1); + drb_to_add_mod_s* drb = &rrc_recfg_r8->rr_cfg_ded.drb_to_add_mod_list[0]; + TESTASSERT(drb->drb_id == 1); + //... + TESTASSERT(drb->rlc_cfg_v1510.is_present()); + + uint8_t rrc_msg2[rrc_msg_len]; + bit_ref bref2(&rrc_msg2[0], sizeof(rrc_msg2)), bref2_0(&rrc_msg2[0], sizeof(rrc_msg2)); + dl_dcch_msg.pack(bref2); // FIXME: Should I generate a pack/unpack method for RLC-Config-v1510??? + TESTASSERT(bref.distance(bref0) == bref2.distance(bref2_0)); + TESTASSERT(memcmp(rrc_msg2, rrc_msg, rrc_msg_len) == 0); + + // // test print + // json_writer j; + // dl_dcch_msg.to_json(j); + // std::cout << j.to_string() << std::endl; + + return 0; +} + +int ue_rrc_conn_recfg_r15_v10_test() +{ + // 201695a8000005143a0002900878b0000046625a03593800000000083a100a48aa1a2780280002a782800002a783000002a78400000001c2900e080848e0434b73a32b93732ba0336b73198181b0336b1b19a1a980233b8393982808c8005332f037f7f7d7d7f7f2f83027a12027a122805fb2a7830400000f38900f78b962ca4f5380dfb9c0327002ea03a03b1793400f40010800d9809016cda8141a0020c8287000b001efb00024a082120205024a04e3f0d00000 + uint8_t rrc_msg[] = { + 0x20, 0x16, 0x95, 0xa8, 0x00, 0x00, 0x05, 0x14, 0x3a, 0x00, 0x02, 0x90, 0x08, 0x78, 0xb0, 0x00, 0x00, 0x46, 0x62, + 0x5a, 0x03, 0x59, 0x38, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0x10, 0x0a, 0x48, 0xaa, 0x1a, 0x27, 0x80, 0x28, 0x00, + 0x02, 0xa7, 0x82, 0x80, 0x00, 0x02, 0xa7, 0x83, 0x00, 0x00, 0x02, 0xa7, 0x84, 0x00, 0x00, 0x00, 0x01, 0xc2, 0x90, + 0x0e, 0x08, 0x08, 0x48, 0xe0, 0x43, 0x4b, 0x73, 0xa3, 0x2b, 0x93, 0x73, 0x2b, 0xa0, 0x33, 0x6b, 0x73, 0x19, 0x81, + 0x81, 0xb0, 0x33, 0x6b, 0x1b, 0x19, 0xa1, 0xa9, 0x80, 0x23, 0x3b, 0x83, 0x93, 0x98, 0x28, 0x08, 0xc8, 0x00, 0x53, + 0x32, 0xf0, 0x37, 0xf7, 0xf7, 0xd7, 0xd7, 0xf7, 0xf2, 0xf8, 0x30, 0x27, 0xa1, 0x20, 0x27, 0xa1, 0x22, 0x80, 0x5f, + 0xb2, 0xa7, 0x83, 0x04, 0x00, 0x00, 0x0f, 0x38, 0x90, 0x0f, 0x78, 0xb9, 0x62, 0xca, 0x4f, 0x53, 0x80, 0xdf, 0xb9, + 0xc0, 0x32, 0x70, 0x02, 0xea, 0x03, 0xa0, 0x3b, 0x17, 0x93, 0x40, 0x0f, 0x40, 0x01, 0x08, 0x00, 0xd9, 0x80, 0x90, + 0x16, 0xcd, 0xa8, 0x14, 0x1a, 0x00, 0x20, 0xc8, 0x28, 0x70, 0x00, 0xb0, 0x01, 0xef, 0xb0, 0x00, 0x24, 0xa0, 0x82, + 0x12, 0x02, 0x05, 0x02, 0x4a, 0x04, 0xe3, 0xf0, 0xd0, 0x00, 0x00}; + uint32_t rrc_msg_len = sizeof(rrc_msg); + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + bit_ref bref0(&rrc_msg[0], sizeof(rrc_msg)); + + dl_dcch_msg_s dl_dcch_msg; + dl_dcch_msg.unpack(bref); + + TESTASSERT(ceil(bref.distance(bref0) / 8.0) == rrc_msg_len); + + TESTASSERT(dl_dcch_msg.msg.type() == dl_dcch_msg_type_c::types::c1); + TESTASSERT(dl_dcch_msg.msg.c1().type() == dl_dcch_msg_type_c::c1_c_::types::rrc_conn_recfg); + rrc_conn_recfg_s* rrc_recfg = &dl_dcch_msg.msg.c1().rrc_conn_recfg(); + TESTASSERT(rrc_recfg->rrc_transaction_id == 0); + TESTASSERT(rrc_recfg->crit_exts.type() == rrc_conn_recfg_s::crit_exts_c_::types::c1); + TESTASSERT(rrc_recfg->crit_exts.c1().type() == rrc_conn_recfg_s::crit_exts_c_::c1_c_::types::rrc_conn_recfg_r8); + rrc_conn_recfg_r8_ies_s* rrc_recfg_r8 = &rrc_recfg->crit_exts.c1().rrc_conn_recfg_r8(); + TESTASSERT(rrc_recfg_r8->meas_cfg_present); + TESTASSERT(not rrc_recfg_r8->mob_ctrl_info_present); + TESTASSERT(rrc_recfg_r8->ded_info_nas_list_present); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded_present); + TESTASSERT(not rrc_recfg_r8->security_cfg_ho_present); + TESTASSERT(rrc_recfg_r8->non_crit_ext_present); + + // MeasConfig + TESTASSERT(not rrc_recfg_r8->meas_cfg.meas_obj_to_rem_list_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.meas_obj_to_add_mod_list_present); + TESTASSERT(not rrc_recfg_r8->meas_cfg.report_cfg_to_rem_list_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.report_cfg_to_add_mod_list_present); + TESTASSERT(not rrc_recfg_r8->meas_cfg.meas_id_to_rem_list_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.meas_id_to_add_mod_list_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.quant_cfg_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.s_measure_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.speed_state_pars_present); + + TESTASSERT(rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_eutra_present); + TESTASSERT(not rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_utra_present); + TESTASSERT(not rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_geran_present); + TESTASSERT(not rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_cdma2000_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_eutra.filt_coef_rsrp_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_eutra.filt_coef_rsrp == filt_coef_e::fc6); + TESTASSERT(rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_eutra.filt_coef_rsrq_present); + TESTASSERT(rrc_recfg_r8->meas_cfg.quant_cfg.quant_cfg_eutra.filt_coef_rsrq == filt_coef_e::fc4); + TESTASSERT(rrc_recfg_r8->meas_cfg.s_measure == 90); + TESTASSERT(rrc_recfg_r8->meas_cfg.speed_state_pars.type() == meas_cfg_s::speed_state_pars_c_::types::release); + + TESTASSERT(rrc_recfg_r8->ded_info_nas_list.size() == 1); + TESTASSERT(rrc_recfg_r8->ded_info_nas_list[0].size() == 107); + + // RR Config + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.srb_to_add_mod_list_present); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.drb_to_add_mod_list_present); + + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.srb_to_add_mod_list.size() == 1); + srb_to_add_mod_s* srb = &rrc_recfg_r8->rr_cfg_ded.srb_to_add_mod_list[0]; + TESTASSERT(srb->rlc_cfg_present); + TESTASSERT(srb->lc_ch_cfg_present); + TESTASSERT(srb->srb_id == 2); + TESTASSERT(srb->rlc_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types::explicit_value); + rlc_cfg_c& explicit_value = srb->rlc_cfg.explicit_value(); + TESTASSERT(explicit_value.type() == rlc_cfg_c::types::am); + rlc_cfg_c::am_s_& am = explicit_value.am(); + TESTASSERT(am.ul_am_rlc.t_poll_retx == t_poll_retx_e::ms35); + TESTASSERT(am.ul_am_rlc.poll_pdu == poll_pdu_e::p_infinity); + TESTASSERT(am.ul_am_rlc.poll_byte == poll_byte_e::kbinfinity); + TESTASSERT(am.ul_am_rlc.max_retx_thres == ul_am_rlc_s::max_retx_thres_e_::t32); + TESTASSERT(am.dl_am_rlc.t_reordering == t_reordering_e::ms35); + TESTASSERT(am.dl_am_rlc.t_status_prohibit == t_status_prohibit_e::ms0); + TESTASSERT(srb->lc_ch_cfg.type() == srb_to_add_mod_s::lc_ch_cfg_c_::types::explicit_value); + TESTASSERT(srb->lc_ch_cfg.explicit_value().ul_specific_params_present); + lc_ch_cfg_s::ul_specific_params_s_& ulparams = srb->lc_ch_cfg.explicit_value().ul_specific_params; + TESTASSERT(ulparams.lc_ch_group_present); + TESTASSERT(ulparams.prio == 3); + TESTASSERT(ulparams.prioritised_bit_rate == lc_ch_cfg_s::ul_specific_params_s_::prioritised_bit_rate_e_::infinity); + TESTASSERT(ulparams.bucket_size_dur == lc_ch_cfg_s::ul_specific_params_s_::bucket_size_dur_e_::ms50); + TESTASSERT(ulparams.lc_ch_group == 0); + + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.drb_to_add_mod_list.size() == 1); + drb_to_add_mod_s* drb = &rrc_recfg_r8->rr_cfg_ded.drb_to_add_mod_list[0]; + TESTASSERT(drb->eps_bearer_id_present); + TESTASSERT(not drb->pdcp_cfg_present); + TESTASSERT(drb->rlc_cfg_present); + TESTASSERT(drb->lc_ch_id_present); + TESTASSERT(drb->lc_ch_cfg_present); + TESTASSERT(drb->eps_bearer_id == 5); + TESTASSERT(drb->drb_id == 1); + TESTASSERT(drb->rlc_cfg.type() == rlc_cfg_c::types::um_bi_dir); + TESTASSERT(drb->rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len == sn_field_len_e::size10); + TESTASSERT(drb->rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len == sn_field_len_e::size10); + TESTASSERT(drb->rlc_cfg.um_bi_dir().dl_um_rlc.t_reordering == t_reordering_e::ms40); + TESTASSERT(drb->lc_ch_id == 3); + TESTASSERT(drb->lc_ch_cfg.ul_specific_params_present); + TESTASSERT(drb->lc_ch_cfg.ul_specific_params.lc_ch_group_present); + TESTASSERT(drb->lc_ch_cfg.ul_specific_params.prio == 12); + TESTASSERT(drb->lc_ch_cfg.ul_specific_params.prioritised_bit_rate == + lc_ch_cfg_s::ul_specific_params_s_::prioritised_bit_rate_e_::kbps8); + TESTASSERT(drb->lc_ch_cfg.ul_specific_params.bucket_size_dur == + lc_ch_cfg_s::ul_specific_params_s_::bucket_size_dur_e_::ms300); + TESTASSERT(drb->lc_ch_cfg.ul_specific_params.lc_ch_group == 3); + // ... + TESTASSERT(not rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.pdsch_cfg_ded_present); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.pucch_cfg_ded_present); + TESTASSERT(not rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.pucch_cfg_ded.tdd_ack_nack_feedback_mode_present); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.pucch_cfg_ded.ack_nack_repeat.type() == + pucch_cfg_ded_s::ack_nack_repeat_c_::types::release); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.ant_info_r10.is_present()); + TESTASSERT(not rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.ant_info_ul_r10.is_present()); + TESTASSERT(not rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.cif_presence_r10_present); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.cqi_report_cfg_r10.is_present()); + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.csi_rs_cfg_r10.is_present()); + // ... + TESTASSERT(rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.ant_info_r10->type() == + phys_cfg_ded_s::ant_info_r10_c_::types::explicit_value_r10); + ant_info_ded_r10_s& ant_r10 = rrc_recfg_r8->rr_cfg_ded.phys_cfg_ded.ant_info_r10->explicit_value_r10(); + TESTASSERT(ant_r10.codebook_subset_restrict_r10_present); + TESTASSERT(ant_r10.tx_mode_r10 == ant_info_ded_r10_s::tx_mode_r10_e_::tm3); + TESTASSERT(ant_r10.codebook_subset_restrict_r10.length() == 2); + TESTASSERT(ant_r10.codebook_subset_restrict_r10 == "11"); + TESTASSERT(ant_r10.ue_tx_ant_sel.type() == ant_info_ded_r10_s::ue_tx_ant_sel_c_::types::release); + // ... + TESTASSERT(not rrc_recfg_r8->non_crit_ext.late_non_crit_ext_present); + TESTASSERT(rrc_recfg_r8->non_crit_ext.non_crit_ext_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.other_cfg_r9_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.full_cfg_r9_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.s_cell_to_release_list_r10_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.s_cell_to_add_mod_list_r10_present); + TESTASSERT(rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.sib_type1_ded_r11_present); + TESTASSERT(rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present); + TESTASSERT( + not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.wlan_offload_info_r12_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.scg_cfg_r12_present); + TESTASSERT( + not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.sl_sync_tx_ctrl_r12_present); + TESTASSERT( + not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.sl_disc_cfg_r12_present); + TESTASSERT( + not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.sl_comm_cfg_r12_present); + TESTASSERT(rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .s_cell_to_release_list_ext_r13_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .s_cell_to_add_mod_list_ext_r13_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .lwa_cfg_r13_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .lwip_cfg_r13_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .rclwi_cfg_r13_present); + TESTASSERT( + rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.sl_v2x_cfg_ded_r14_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.s_cell_to_add_mod_list_ext_v1430_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.per_cc_gap_ind_request_r14_present); + TESTASSERT(not rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.sib_type2_ded_r14_present); + TESTASSERT(rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext_present); + rrc_conn_recfg_v1510_ies_s* v1510 = &rrc_recfg_r8->non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.non_crit_ext.non_crit_ext; + TESTASSERT(not v1510->nr_cfg_r15_present); + TESTASSERT(not v1510->sk_counter_r15_present); + TESTASSERT(v1510->nr_radio_bearer_cfg1_r15_present); + TESTASSERT(not v1510->nr_radio_bearer_cfg2_r15_present); + TESTASSERT(not v1510->tdm_pattern_cfg_r15_present); + TESTASSERT(not v1510->non_crit_ext_present); + TESTASSERT(v1510->nr_radio_bearer_cfg1_r15.size() == 8); // FIXME: Get a better way for oct_string comparison + TESTASSERT(v1510->nr_radio_bearer_cfg1_r15[0] == 20); + TESTASSERT(v1510->nr_radio_bearer_cfg1_r15[7] == 0); + + return 0; +} + +int failed_dl_ccch_unpack() +{ + uint8_t rrc_msg[] = {0xa5, 0xa8, 0xd8, 0x10, 0x0e, 0xc8, 0x02}; + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + + asn1::rrc::dl_ccch_msg_s msg; + + TESTASSERT(msg.unpack(bref) == SRSASN_SUCCESS); + + return 0; +} + +int unrecognized_ext_group_test() +{ + uint8_t rrc_msg[] = {0x00, 0x81, 0x19, 0x8c, 0x37, 0x91, 0x90, 0x10, 0x22, 0xc1, 0x29, 0x40, 0x48, + 0x00, 0x82, 0x00, 0x32, 0x67, 0x29, 0x8a, 0x5a, 0xa8, 0x31, 0x00, 0x18, 0x01, + 0x2e, 0x38, 0x03, 0x84, 0x28, 0xc5, 0xb0, 0x9d, 0x4b, 0x48, 0x00}; + // 0081198c3791901022c12940480082003267298a5aa8310018012e38038428c5b09d4b4800 + uint32_t rrc_msg_len = sizeof(rrc_msg); + + bit_ref bref(&rrc_msg[0], sizeof(rrc_msg)); + + bcch_dl_sch_msg_s dl_sch_msg; + dl_sch_msg.unpack(bref); + + TESTASSERT(dl_sch_msg.msg.type() == bcch_dl_sch_msg_type_c::types::c1); + TESTASSERT(dl_sch_msg.msg.c1().type() == bcch_dl_sch_msg_type_c::c1_c_::types::sys_info); + + return 0; +} + +int main() +{ + srsasn_log_register_handler(&asn_logger, print_console); + rrc_log_register_handler(&rrc_logger, print_console); + + TESTASSERT(test_generic() == 0); + TESTASSERT(test_json_printer() == 0); + TESTASSERT(test_mib_msg() == 0); + TESTASSERT(test_bcch_dl_sch_msg() == 0); + TESTASSERT(test_bcch_dl_sch_msg2() == 0); + TESTASSERT(test_bcch_dl_sch_msg3() == 0); + TESTASSERT(test_dl_dcch_msg() == 0); + TESTASSERT(ue_rrc_conn_recfg_r15_v10_test() == 0); + TESTASSERT(failed_dl_ccch_unpack() == 0); + TESTASSERT(unrecognized_ext_group_test() == 0); + + printf("Success\n"); + return 0; +} diff --git a/lib/test/asn1/srslte_asn1_rrc_dl_ccch_test.cc b/lib/test/asn1/srslte_asn1_rrc_dl_ccch_test.cc index cf35bc7cf..c074d3432 100644 --- a/lib/test/asn1/srslte_asn1_rrc_dl_ccch_test.cc +++ b/lib/test/asn1/srslte_asn1_rrc_dl_ccch_test.cc @@ -19,7 +19,6 @@ * */ -#include "../../../srsue/hdr/stack/rrc/rrc.h" #include "srslte/asn1/rrc_asn1.h" #include "srslte/common/bcd_helpers.h" #include "srslte/common/log_filter.h" diff --git a/lib/test/asn1/srslte_asn1_rrc_dl_dcch_test.cc b/lib/test/asn1/srslte_asn1_rrc_dl_dcch_test.cc index e20c6d770..3b0e9b1eb 100644 --- a/lib/test/asn1/srslte_asn1_rrc_dl_dcch_test.cc +++ b/lib/test/asn1/srslte_asn1_rrc_dl_dcch_test.cc @@ -19,7 +19,6 @@ * */ -#include "../../../srsue/hdr/stack/rrc/rrc.h" #include "srslte/asn1/rrc_asn1.h" #include "srslte/common/bcd_helpers.h" #include "srslte/common/log_filter.h" diff --git a/lib/test/asn1/srslte_asn1_rrc_ul_dcch_test.cc b/lib/test/asn1/srslte_asn1_rrc_ul_dcch_test.cc index df6d01223..f9377806c 100644 --- a/lib/test/asn1/srslte_asn1_rrc_ul_dcch_test.cc +++ b/lib/test/asn1/srslte_asn1_rrc_ul_dcch_test.cc @@ -19,7 +19,7 @@ * */ -#include "../../../srsue/hdr/stack/rrc/rrc.h" +#include "../../../srsue/hdr/stack/rrc/rrc.h" // for rrc_args_t #include "srslte/asn1/rrc_asn1.h" #include "srslte/common/bcd_helpers.h" #include "srslte/common/log_filter.h" diff --git a/lib/test/common/CMakeLists.txt b/lib/test/common/CMakeLists.txt index c358b0993..72da402aa 100644 --- a/lib/test/common/CMakeLists.txt +++ b/lib/test/common/CMakeLists.txt @@ -33,6 +33,10 @@ add_executable(test_eia1 test_eia1.cc) target_link_libraries(test_eia1 srslte_common srslte_phy ${CMAKE_THREAD_LIBS_INIT}) add_test(test_eia1 test_eia1) +add_executable(test_eia3 test_eia3.cc) +target_link_libraries(test_eia3 srslte_common) +add_test(test_eia3 test_eia3) + add_executable(test_eea1 test_eea1.cc) target_link_libraries(test_eea1 srslte_common srslte_phy ${CMAKE_THREAD_LIBS_INIT}) add_test(test_eea1 test_eea1) @@ -41,6 +45,10 @@ add_executable(test_eea2 test_eea2.cc) target_link_libraries(test_eea2 srslte_common srslte_phy ${CMAKE_THREAD_LIBS_INIT}) add_test(test_eea2 test_eea2) +add_executable(test_eea3 test_eea3.cc) +target_link_libraries(test_eea3 srslte_common srslte_phy ${CMAKE_THREAD_LIBS_INIT}) +add_test(test_eea3 test_eea3) + add_executable(test_f12345 test_f12345.cc) target_link_libraries(test_f12345 srslte_common ${CMAKE_THREAD_LIBS_INIT}) add_test(test_f12345 test_f12345) @@ -55,4 +63,14 @@ add_executable(bcd_helpers_test bcd_helpers_test.cc) add_executable(pdu_test pdu_test.cc) target_link_libraries(pdu_test srslte_phy srslte_common ${CMAKE_THREAD_LIBS_INIT}) -add_test(pdu_test pdu_test) \ No newline at end of file +add_test(pdu_test pdu_test) + +add_executable(mac_nr_pdu_test mac_nr_pdu_test.cc) +target_link_libraries(mac_nr_pdu_test srslte_phy srslte_common ${CMAKE_THREAD_LIBS_INIT}) +add_test(mac_nr_pdu_test mac_nr_pdu_test) + +add_executable(stack_procedure_test stack_procedure_test.cc) + +add_executable(queue_test queue_test.cc) +target_link_libraries(queue_test srslte_common ${CMAKE_THREAD_LIBS_INIT}) +add_test(queue_test queue_test) diff --git a/lib/test/common/logger_test.cc b/lib/test/common/logger_test.cc index 573144c6e..a63a650e0 100644 --- a/lib/test/common/logger_test.cc +++ b/lib/test/common/logger_test.cc @@ -39,7 +39,7 @@ void* thread_loop(void *a) { for(int i=0;ithread_id, i); - args->l->log(new std::string(buf)); + args->l->log_char(buf); } return NULL; } diff --git a/lib/test/common/mac_nr_pdu_test.cc b/lib/test/common/mac_nr_pdu_test.cc new file mode 100644 index 000000000..e79e0dac0 --- /dev/null +++ b/lib/test/common/mac_nr_pdu_test.cc @@ -0,0 +1,330 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/common/log_filter.h" +#include "srslte/common/mac_nr_pcap.h" +#include "srslte/common/mac_nr_pdu.h" +#include "srslte/config.h" + +#include +#include +#include +#include + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ + return -1; \ + } \ + } + +#define PCAP 0 +#define PCAP_CRNTI (0x1001) +#define PCAP_TTI (666) + +using namespace srslte; + +static std::unique_ptr pcap_handle = nullptr; + +int mac_dl_sch_pdu_unpack_and_pack_test1() +{ + // MAC PDU with DL-SCH subheader with 8-bit length field + // Bit 1-8 + // | | | | | | | | | + // | R |F=0| LCID | Octet 1 + // | L | Octet 1 + + // TV1 - MAC PDU with short subheader for CCCH, MAC SDU length is 8 B, total PDU is 10 B + uint8_t mac_dl_sch_pdu_1[] = {0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + + if (pcap_handle) { + pcap_handle->write_dl_crnti(mac_dl_sch_pdu_1, sizeof(mac_dl_sch_pdu_1), PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::mac_nr_sch_pdu pdu; + pdu.unpack(mac_dl_sch_pdu_1, sizeof(mac_dl_sch_pdu_1)); + TESTASSERT(pdu.get_num_subpdus() == 1); + + mac_nr_sch_subpdu subpdu = pdu.get_subpdu(0); + TESTASSERT(subpdu.get_total_length() == 10); + TESTASSERT(subpdu.get_sdu_length() == 8); + TESTASSERT(subpdu.get_lcid() == 0); + + // pack PDU again + byte_buffer_t tx_buffer; + + srslte::mac_nr_sch_pdu tx_pdu; + tx_pdu.init_tx(&tx_buffer, sizeof(mac_dl_sch_pdu_1)); + + // Add SDU part of TV from above + tx_pdu.add_sdu(0, &mac_dl_sch_pdu_1[2], 8); + + TESTASSERT(tx_pdu.get_remaing_len() == 0); + TESTASSERT(tx_buffer.N_bytes == sizeof(mac_dl_sch_pdu_1)); + TESTASSERT(memcmp(tx_buffer.msg, mac_dl_sch_pdu_1, tx_buffer.N_bytes) == 0); + + if (pcap_handle) { + pcap_handle->write_dl_crnti(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::log_filter log("MAC"); + log.set_level(srslte::LOG_LEVEL_DEBUG); + log.set_hex_limit(100000); + log.info_hex(tx_buffer.msg, tx_buffer.N_bytes, "Generated MAC PDU (%d B)\n", tx_buffer.N_bytes); + + return SRSLTE_SUCCESS; +} + +int mac_dl_sch_pdu_unpack_test2() +{ + // MAC PDU with DL-SCH subheader with 16-bit length field + // Bit 1-8 + // | | | | | | | | | + // | R |F=1| LCID | Octet 1 + // | L | Octet 2 + // | L | Octet 3 + + // Note: Pack test is not working in this case as it would generate a PDU with the short length field only + + // TV2 - MAC PDU with long subheader for LCID=2, MAC SDU length is 8 B, total PDU is 11 B + uint8_t mac_dl_sch_pdu_2[] = {0x42, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + + if (pcap_handle) { + pcap_handle->write_dl_crnti(mac_dl_sch_pdu_2, sizeof(mac_dl_sch_pdu_2), PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::mac_nr_sch_pdu pdu; + pdu.unpack(mac_dl_sch_pdu_2, sizeof(mac_dl_sch_pdu_2)); + TESTASSERT(pdu.get_num_subpdus() == 1); + mac_nr_sch_subpdu subpdu = pdu.get_subpdu(0); + TESTASSERT(subpdu.get_total_length() == 11); + TESTASSERT(subpdu.get_sdu_length() == 8); + TESTASSERT(subpdu.get_lcid() == 2); + + return SRSLTE_SUCCESS; +} + +int mac_dl_sch_pdu_pack_test3() +{ + // MAC PDU with DL-SCH subheader with 16-bit length field (512 B SDU + 3 B header) + // Bit 1-8 + // | | | | | | | | | + // | R |F=1| LCID | Octet 1 + // | L | Octet 2 + // | L | Octet 3 + + uint8_t sdu[512] = {}; + + // populate SDU payload + for (uint32_t i = 0; i < 512; i++) { + sdu[i] = i % 256; + } + + // pack buffer + byte_buffer_t tx_buffer; + + srslte::mac_nr_sch_pdu tx_pdu; + tx_pdu.init_tx(&tx_buffer, 1024); + + // Add SDU + tx_pdu.add_sdu(4, sdu, sizeof(sdu)); + + TESTASSERT(tx_pdu.get_remaing_len() == 509); + TESTASSERT(tx_buffer.N_bytes == 515); + + if (pcap_handle) { + pcap_handle->write_dl_crnti(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::log_filter log("MAC"); + log.set_level(srslte::LOG_LEVEL_DEBUG); + log.set_hex_limit(100000); + log.info_hex(tx_buffer.msg, tx_buffer.N_bytes, "Generated MAC PDU (%d B)\n", tx_buffer.N_bytes); + + return SRSLTE_SUCCESS; +} + +int mac_dl_sch_pdu_pack_test4() +{ + // MAC PDU with only padding + // Bit 1-8 + // | | | | | | | | | + // | R | R | LCID | Octet 1 + // | zeros | Octet .. + + // TV2 - MAC PDU with a single LCID with padding only + uint8_t tv[] = {0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + const uint32_t pdu_size = 8; + byte_buffer_t tx_buffer; + + // modify buffer (to be nulled during PDU packing + tx_buffer.msg[4] = 0xaa; + + srslte::mac_nr_sch_pdu tx_pdu; + tx_pdu.init_tx(&tx_buffer, pdu_size); + + TESTASSERT(tx_pdu.get_remaing_len() == pdu_size); + tx_pdu.pack(); + TESTASSERT(tx_buffer.N_bytes == pdu_size); + TESTASSERT(tx_buffer.N_bytes == sizeof(tv)); + + TESTASSERT(memcmp(tx_buffer.msg, tv, tx_buffer.N_bytes) == 0); + + if (pcap_handle) { + pcap_handle->write_dl_crnti(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::log_filter log("MAC"); + log.set_level(srslte::LOG_LEVEL_DEBUG); + log.set_hex_limit(100000); + log.info_hex(tx_buffer.msg, tx_buffer.N_bytes, "Generated MAC PDU (%d B)\n", tx_buffer.N_bytes); + + return SRSLTE_SUCCESS; +} + +int mac_dl_sch_pdu_pack_test5() +{ + // MAC PDU with DL-SCH subheader with 8-bit length field and padding after that + // Bit 1-8 + // | | | | | | | | | + // | R |F=0| LCID | Octet 1 + // | L | Octet 2 + // | zeros | Octet 3-10 + // | R | R | LCID | Octet 11 + // | zeros | Octet .. + + // TV2 - MAC PDU with a single LCID with padding only + uint8_t tv[] = {0x01, 0x08, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00}; + + const uint32_t pdu_size = 16; + byte_buffer_t tx_buffer; + tx_buffer.clear(); + + srslte::mac_nr_sch_pdu tx_pdu; + tx_pdu.init_tx(&tx_buffer, pdu_size); + + // Add SDU part of TV from above + tx_pdu.add_sdu(1, &tv[2], 8); + + TESTASSERT(tx_pdu.get_remaing_len() == 6); + + tx_pdu.pack(); + + TESTASSERT(tx_pdu.get_remaing_len() == 0); + TESTASSERT(tx_buffer.N_bytes == pdu_size); + TESTASSERT(tx_buffer.N_bytes == sizeof(tv)); + TESTASSERT(memcmp(tx_buffer.msg, tv, tx_buffer.N_bytes) == 0); + + if (pcap_handle) { + pcap_handle->write_dl_crnti(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::log_filter log("MAC"); + log.set_level(srslte::LOG_LEVEL_DEBUG); + log.set_hex_limit(100000); + log.info_hex(tx_buffer.msg, tx_buffer.N_bytes, "Generated MAC PDU (%d B)\n", tx_buffer.N_bytes); + + return SRSLTE_SUCCESS; +} + +int mac_ul_sch_pdu_unpack_test1() +{ + // UL-SCH MAC PDU with fixed-size CE and DL-SCH subheader with 16-bit length field + // Note: this is a malformed UL-SCH PDU has SDU is placed after the CE + // Bit 1-8 + // | | | | | | | | | + // | R | R | LCID | Octet 1 (C-RNTI LCID = 0x ) + // | C-RNTI | Octet 2 + // | C-RNTI | Octet 3 + // | R |F=1| LCID | Octet 4 + // | L | Octet 5 + // | L | Octet 6 + // | data | Octet 7-x + + // TV3 - UL-SCH MAC PDU with long subheader for LCID=2, MAC SDU length is 4 B, total PDU is 9 B + const uint8_t ul_sch_crnti[] = {0x11, 0x22}; + uint8_t mac_ul_sch_pdu_1[] = {0x3a, 0x11, 0x22, 0x43, 0x00, 0x04, 0x11, 0x22, 0x33, 0x44}; + + if (pcap_handle) { + pcap_handle->write_ul_crnti(mac_ul_sch_pdu_1, sizeof(mac_ul_sch_pdu_1), PCAP_CRNTI, true, PCAP_TTI); + } + + srslte::mac_nr_sch_pdu pdu(true); + pdu.unpack(mac_ul_sch_pdu_1, sizeof(mac_ul_sch_pdu_1)); + TESTASSERT(pdu.get_num_subpdus() == 2); + + // First subpdu is C-RNTI CE + mac_nr_sch_subpdu subpdu0 = pdu.get_subpdu(0); + TESTASSERT(subpdu0.get_total_length() == 3); + TESTASSERT(subpdu0.get_sdu_length() == 2); + TESTASSERT(subpdu0.get_lcid() == mac_nr_sch_subpdu::CRNTI); + TESTASSERT(memcmp(subpdu0.get_sdu(), (uint8_t*)&ul_sch_crnti, sizeof(ul_sch_crnti)) == 0); + + // Second subpdu is UL-SCH + mac_nr_sch_subpdu subpdu1 = pdu.get_subpdu(1); + TESTASSERT(subpdu1.get_total_length() == 7); + TESTASSERT(subpdu1.get_sdu_length() == 4); + TESTASSERT(subpdu1.get_lcid() == 3); + + return SRSLTE_SUCCESS; +} + +int main(int argc, char** argv) +{ +#if PCAP + pcap_handle = std::unique_ptr(new srslte::mac_nr_pcap()); + pcap_handle->open("mac_nr_pdu_test.pcap"); +#endif + + if (mac_dl_sch_pdu_unpack_and_pack_test1()) { + fprintf(stderr, "mac_dl_sch_pdu_unpack_and_pack_test1() failed.\n"); + return SRSLTE_ERROR; + } + + if (mac_dl_sch_pdu_unpack_test2()) { + fprintf(stderr, "mac_dl_sch_pdu_unpack_test2() failed.\n"); + return SRSLTE_ERROR; + } + + if (mac_dl_sch_pdu_pack_test3()) { + fprintf(stderr, "mac_dl_sch_pdu_pack_test3() failed.\n"); + return SRSLTE_ERROR; + } + + if (mac_dl_sch_pdu_pack_test4()) { + fprintf(stderr, "mac_dl_sch_pdu_pack_test4() failed.\n"); + return SRSLTE_ERROR; + } + + if (mac_dl_sch_pdu_pack_test5()) { + fprintf(stderr, "mac_dl_sch_pdu_pack_test5() failed.\n"); + return SRSLTE_ERROR; + } + + if (mac_ul_sch_pdu_unpack_test1()) { + fprintf(stderr, "mac_ul_sch_pdu_unpack_test1() failed.\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} diff --git a/lib/test/common/pdu_test.cc b/lib/test/common/pdu_test.cc index cff2e993e..a60b3e4ec 100644 --- a/lib/test/common/pdu_test.cc +++ b/lib/test/common/pdu_test.cc @@ -456,6 +456,95 @@ int mac_sch_pdu_pack_test5() return SRSLTE_SUCCESS; } +// Test for BSR CE +int mac_sch_pdu_pack_test6() +{ + srslte::log_filter mac_log("MAC"); + mac_log.set_level(srslte::LOG_LEVEL_DEBUG); + mac_log.set_hex_limit(32); + + const uint32_t pdu_size = 8; + srslte::sch_pdu pdu(10, &mac_log); + + uint8_t tv[pdu_size] = {0x3e, 0x1f, 0x01, 0xfa, 0x7f, 0x00, 0x00, 0x00}; + + byte_buffer_t buffer; + pdu.init_tx(&buffer, pdu_size, true); + + TESTASSERT(pdu.rem_size() == pdu_size); + TESTASSERT(pdu.get_pdu_len() == pdu_size); + TESTASSERT(pdu.get_sdu_space() == pdu_size - 1); + TESTASSERT(pdu.get_current_sdu_ptr() == buffer.msg); + + // Try to Long BSR CE + uint32_t buff_size[4] = {0, 1000, 5000, 19200000}; + TESTASSERT(pdu.new_subh()); + TESTASSERT(pdu.get()->set_bsr(buff_size, srslte::sch_subh::LONG_BSR)); + + // write PDU + pdu.write_packet(&mac_log); + + // compare with tv + TESTASSERT(memcmp(buffer.msg, tv, buffer.N_bytes) == 0); + + // log + mac_log.info_hex(buffer.msg, buffer.N_bytes, "MAC PDU (%d B):\n", buffer.N_bytes); + +#if HAVE_PCAP + pcap_handle->write_ul_crnti(buffer.msg, buffer.N_bytes, 0x1001, true, 1); +#endif + + return SRSLTE_SUCCESS; +} + +// Test for short MAC PDU containing padding only +int mac_sch_pdu_pack_test7() +{ + srslte::log_filter mac_log("MAC"); + mac_log.set_level(srslte::LOG_LEVEL_DEBUG); + mac_log.set_hex_limit(32); + + rlc_dummy rlc; + rlc.write_sdu(1, 8); + + const uint32_t pdu_size = 2; + srslte::sch_pdu pdu(10, &mac_log); + + uint8_t tv[pdu_size] = {0x1f, 0x1f}; + + byte_buffer_t buffer; + pdu.init_tx(&buffer, pdu_size, true); + + TESTASSERT(pdu.rem_size() == pdu_size); + TESTASSERT(pdu.get_pdu_len() == pdu_size); + TESTASSERT(pdu.get_sdu_space() == pdu_size - 1); + TESTASSERT(pdu.get_current_sdu_ptr() == buffer.msg); + + // Try to add SDU, subheader is ok + TESTASSERT(pdu.new_subh()); + + // adding SDU fails + TESTASSERT(pdu.get()->set_sdu(2, 8, &rlc) == SRSLTE_ERROR); + + // remove subheader again + pdu.del_subh(); + + // write PDU + pdu.write_packet(&mac_log); + + // compare with tv + TESTASSERT(memcmp(buffer.msg, tv, buffer.N_bytes) == 0); + + // log + mac_log.info_hex(buffer.msg, buffer.N_bytes, "MAC PDU (%d B):\n", buffer.N_bytes); + +#if HAVE_PCAP + pcap_handle->write_ul_crnti(buffer.msg, buffer.N_bytes, 0x1001, true, 1); +#endif + + return SRSLTE_SUCCESS; +} + // Test for checking error cases int mac_sch_pdu_pack_error_test() { @@ -560,7 +649,7 @@ int mac_mch_pdu_pack_test1() { #endif // compare with TV - TESTASSERT(memcmp(buffer.msg, tv, sizeof(buffer.N_bytes)) == 0); + TESTASSERT(memcmp(buffer.msg, tv, buffer.N_bytes) == 0); #if HAVE_PCAP pcap_handle->write_ul_crnti(tv, sizeof(tv), 0x1001, true, 1); @@ -593,6 +682,30 @@ int mac_sch_pdu_unpack_test1() return SRSLTE_SUCCESS; } +// Parsing a (corrupted) MAC PDU that only contains padding +int mac_sch_pdu_unpack_test2() +{ + static uint8_t tv[] = {0x3f, 0x3f}; + + srslte::log_filter mac_log("MAC"); + mac_log.set_level(srslte::LOG_LEVEL_DEBUG); + mac_log.set_hex_limit(100000); + + srslte::sch_pdu pdu(20, &mac_log); + pdu.init_rx(sizeof(tv), false); + pdu.parse_packet(tv); + + // make sure this PDU is reset and will not be further processed + TESTASSERT(pdu.nof_subh() == 0); + TESTASSERT(pdu.next() == false); + +#if HAVE_PCAP + pcap_handle->write_ul_crnti(tv, sizeof(tv), 0x1001, true, 1); +#endif + + return SRSLTE_SUCCESS; +} + int main(int argc, char** argv) { #if HAVE_PCAP @@ -645,6 +758,16 @@ int main(int argc, char** argv) return SRSLTE_ERROR; } + if (mac_sch_pdu_pack_test6()) { + fprintf(stderr, "mac_sch_pdu_pack_test6 failed.\n"); + return SRSLTE_ERROR; + } + + if (mac_sch_pdu_pack_test7()) { + fprintf(stderr, "mac_sch_pdu_pack_test7 failed.\n"); + return SRSLTE_ERROR; + } + if (mac_sch_pdu_pack_error_test()) { fprintf(stderr, "mac_sch_pdu_pack_error_test failed.\n"); return SRSLTE_ERROR; @@ -660,5 +783,10 @@ int main(int argc, char** argv) return SRSLTE_ERROR; } + if (mac_sch_pdu_unpack_test2()) { + fprintf(stderr, "mac_sch_pdu_unpack_test2 failed.\n"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; } diff --git a/lib/test/common/queue_test.cc b/lib/test/common/queue_test.cc new file mode 100644 index 000000000..97c2f50cf --- /dev/null +++ b/lib/test/common/queue_test.cc @@ -0,0 +1,333 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/common/multiqueue.h" +#include "srslte/common/thread_pool.h" +#include +#include +#include + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ + return -1; \ + } \ + } + +using namespace srslte; + +int test_multiqueue() +{ + std::cout << "\n======= TEST multiqueue test: start =======\n"; + + int number = 2; + + multiqueue_handler multiqueue; + TESTASSERT(multiqueue.nof_queues() == 0) + + // test push/pop and size for one queue + int qid1 = multiqueue.add_queue(); + TESTASSERT(qid1 == 0 and multiqueue.is_queue_active(qid1)) + TESTASSERT(multiqueue.size(qid1) == 0 and multiqueue.empty(qid1)) + TESTASSERT(multiqueue.nof_queues() == 1) + TESTASSERT(multiqueue.try_push(qid1, 5).first) + TESTASSERT(multiqueue.try_push(qid1, number)) + TESTASSERT(multiqueue.size(qid1) == 2 and not multiqueue.empty(qid1)) + TESTASSERT(multiqueue.wait_pop(&number) == qid1) + TESTASSERT(number == 5) + TESTASSERT(multiqueue.wait_pop(&number) == qid1) + TESTASSERT(number == 2 and multiqueue.empty(qid1) and multiqueue.size(qid1) == 0) + + // test push/pop and size for two queues + int qid2 = multiqueue.add_queue(); + TESTASSERT(qid2 == 1) + TESTASSERT(multiqueue.nof_queues() == 2 and multiqueue.is_queue_active(qid1)) + TESTASSERT(multiqueue.try_push(qid2, 3).first) + TESTASSERT(multiqueue.size(qid2) == 1 and not multiqueue.empty(qid2)) + TESTASSERT(multiqueue.empty(qid1) and multiqueue.size(qid1) == 0) + + // check if erasing a queue breaks anything + multiqueue.erase_queue(qid1); + TESTASSERT(multiqueue.nof_queues() == 1 and not multiqueue.is_queue_active(qid1)) + qid1 = multiqueue.add_queue(); + TESTASSERT(qid1 == 0) + TESTASSERT(multiqueue.empty(qid1) and multiqueue.is_queue_active(qid1)) + multiqueue.wait_pop(&number); + + // check round-robin + for (int i = 0; i < 10; ++i) { + TESTASSERT(multiqueue.try_push(qid1, i)) + } + for (int i = 20; i < 35; ++i) { + TESTASSERT(multiqueue.try_push(qid2, i)) + } + TESTASSERT(multiqueue.size(qid1) == 10) + TESTASSERT(multiqueue.size(qid2) == 15) + TESTASSERT(multiqueue.wait_pop(&number) == qid1 and number == 0) + TESTASSERT(multiqueue.wait_pop(&number) == qid2 and number == 20) + TESTASSERT(multiqueue.wait_pop(&number) == qid1 and number == 1) + TESTASSERT(multiqueue.wait_pop(&number) == qid2 and number == 21) + TESTASSERT(multiqueue.size(qid1) == 8) + TESTASSERT(multiqueue.size(qid2) == 13) + for (int i = 0; i < 8 * 2; ++i) { + multiqueue.wait_pop(&number); + } + TESTASSERT(multiqueue.size(qid1) == 0) + TESTASSERT(multiqueue.size(qid2) == 5) + TESTASSERT(multiqueue.wait_pop(&number) == qid2 and number == 30) + + std::cout << "outcome: Success\n"; + std::cout << "===========================================\n"; + + return 0; +} + +int test_multiqueue_threading() +{ + std::cout << "\n===== TEST multiqueue threading test: start =====\n"; + + int capacity = 4, number = 0, start_number = 2, nof_pushes = capacity + 1; + multiqueue_handler multiqueue(capacity); + int qid1 = multiqueue.add_queue(); + auto push_blocking_func = [&multiqueue](int qid, int start_value, int nof_pushes, bool* is_running) { + for (int i = 0; i < nof_pushes; ++i) { + multiqueue.push(qid, start_value + i); + std::cout << "t1: pushed item " << i << std::endl; + } + std::cout << "t1: pushed all items\n"; + *is_running = false; + }; + + bool t1_running = true; + std::thread t1(push_blocking_func, qid1, start_number, nof_pushes, &t1_running); + + // Wait for queue to fill + while ((int)multiqueue.size(qid1) != capacity) { + usleep(1000); + TESTASSERT(t1_running) + } + + for (int i = 0; i < nof_pushes; ++i) { + TESTASSERT(multiqueue.wait_pop(&number) == qid1) + TESTASSERT(number == start_number + i) + std::cout << "main: popped item " << i << "\n"; + } + std::cout << "main: popped all items\n"; + + // wait for thread to finish + while (t1_running) { + usleep(1000); + } + TESTASSERT(multiqueue.size(qid1) == 0) + + multiqueue.reset(); + t1.join(); + + std::cout << "outcome: Success\n"; + std::cout << "==================================================\n"; + + return 0; +} + +int test_multiqueue_threading2() +{ + std::cout << "\n===== TEST multiqueue threading test 2: start =====\n"; + // Description: push items until blocking in thread t1. Unblocks in main thread by calling multiqueue.reset() + + int capacity = 4, start_number = 2, nof_pushes = capacity + 1; + multiqueue_handler multiqueue(capacity); + int qid1 = multiqueue.add_queue(); + auto push_blocking_func = [&multiqueue](int qid, int start_value, int nof_pushes, bool* is_running) { + for (int i = 0; i < nof_pushes; ++i) { + multiqueue.push(qid, start_value + i); + } + std::cout << "t1: pushed all items\n"; + *is_running = false; + }; + + bool t1_running = true; + std::thread t1(push_blocking_func, qid1, start_number, nof_pushes, &t1_running); + + // Wait for queue to fill + while ((int)multiqueue.size(qid1) != capacity) { + usleep(1000); + TESTASSERT(t1_running) + } + + multiqueue.reset(); + t1.join(); + + std::cout << "outcome: Success\n"; + std::cout << "===================================================\n"; + + return 0; +} + +int test_multiqueue_threading3() +{ + std::cout << "\n===== TEST multiqueue threading test 3: start =====\n"; + // pop will block in a separate thread, but multiqueue.reset() will unlock it + + int capacity = 4; + multiqueue_handler multiqueue(capacity); + int qid1 = multiqueue.add_queue(); + auto pop_blocking_func = [&multiqueue](int qid, bool* success) { + int number = 0; + int id = multiqueue.wait_pop(&number); + *success = id < 0; + }; + + bool t1_success = false; + std::thread t1(pop_blocking_func, qid1, &t1_success); + + TESTASSERT(not t1_success) + usleep(1000); + TESTASSERT(not t1_success) + TESTASSERT((int)multiqueue.size(qid1) == 0) + + // Should be able to unlock all + multiqueue.reset(); + t1.join(); + TESTASSERT(t1_success); + + std::cout << "outcome: Success\n"; + std::cout << "===================================================\n"; + + return 0; +} + +int test_task_thread_pool() +{ + std::cout << "\n====== TEST task thread pool test 1: start ======\n"; + // Description: check whether the tasks are successfully distributed between workers + + uint32_t nof_workers = 4, nof_runs = 10000; + std::vector count_worker(nof_workers, 0); + std::vector count_mutex(nof_workers); + + task_thread_pool thread_pool(nof_workers); + thread_pool.start(); + + auto task = [&count_worker, &count_mutex](uint32_t worker_id) { + std::lock_guard lock(count_mutex[worker_id]); + // std::cout << "hello world from worker " << worker_id << std::endl; + count_worker[worker_id]++; + }; + + for (uint32_t i = 0; i < nof_runs; ++i) { + thread_pool.push_task(task); + } + + // wait for all tasks to be successfully processed + while (thread_pool.nof_pending_tasks() > 0) { + usleep(100); + } + + thread_pool.stop(); + + uint32_t total_count = 0; + for (uint32_t i = 0; i < nof_workers; ++i) { + if (count_worker[i] < 10) { + printf("WARNING: the number of tasks %d assigned to worker %d is too low\n", count_worker[i], i); + } + total_count += count_worker[i]; + printf("worker %d: %d runs\n", i, count_worker[i]); + } + if (total_count != nof_runs) { + printf("Number of task runs=%d does not match total=%d\n", total_count, nof_runs); + return -1; + } + + std::cout << "outcome: Success\n"; + std::cout << "===================================================\n"; + return 0; +} + +int test_task_thread_pool2() +{ + std::cout << "\n====== TEST task thread pool test 2: start ======\n"; + // Description: push a very long task to all workers, and call thread_pool.stop() to check if it waits for the tasks + // to be completed, and does not get stuck. + + uint32_t nof_workers = 4; + uint8_t workers_started = 0, workers_finished = 0; + std::mutex mut; + + task_thread_pool thread_pool(nof_workers); + thread_pool.start(); + + auto task = [&workers_started, &workers_finished, &mut](uint32_t worker_id) { + { + std::lock_guard lock(mut); + workers_started++; + } + sleep(1); + std::lock_guard lock(mut); + std::cout << "worker " << worker_id << " has finished\n"; + workers_finished++; + }; + + for (uint32_t i = 0; i < nof_workers; ++i) { + thread_pool.push_task(task); + } + + while (workers_started != nof_workers) { + usleep(10); + } + + std::cout << "stopping thread pool...\n"; + thread_pool.stop(); + std::cout << "thread pool stopped.\n"; + + TESTASSERT(workers_finished == nof_workers); + + std::cout << "outcome: Success\n"; + std::cout << "===================================================\n"; + return 0; +} + +int test_task_thread_pool3() +{ + std::cout << "\n====== TEST task thread pool test 3: start ======\n"; + // Description: create many workers and shut down the pool before all of them started yet. Should exit cleanly + + uint32_t nof_workers = 100; + + task_thread_pool thread_pool(nof_workers); + thread_pool.start(); + + std::cout << "outcome: Success\n"; + std::cout << "===================================================\n"; + return 0; +} + +int main() +{ + TESTASSERT(test_multiqueue() == 0); + TESTASSERT(test_multiqueue_threading() == 0); + TESTASSERT(test_multiqueue_threading2() == 0); + TESTASSERT(test_multiqueue_threading3() == 0); + + TESTASSERT(test_task_thread_pool() == 0); + TESTASSERT(test_task_thread_pool2() == 0); + TESTASSERT(test_task_thread_pool3() == 0); +} diff --git a/lib/test/common/stack_procedure_test.cc b/lib/test/common/stack_procedure_test.cc new file mode 100644 index 000000000..ccbdfa980 --- /dev/null +++ b/lib/test/common/stack_procedure_test.cc @@ -0,0 +1,312 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/common/stack_procedure.h" +#include + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ + return -1; \ + } \ + } + +using srslte::proc_outcome_t; + +enum class obj_state_t { default_ctor, move_ctor, copy_ctor, from_move_ctor, from_move_assign }; + +const char* to_string(obj_state_t o) +{ + switch (o) { + case obj_state_t::default_ctor: + return "default_ctor"; + case obj_state_t::move_ctor: + return "move_ctor"; + case obj_state_t::copy_ctor: + return "copy_ctor"; + case obj_state_t::from_move_ctor: + return "from_move_ctor"; + case obj_state_t::from_move_assign: + return "from_move_assign"; + } + return ""; +} + +class TestObj +{ +public: + TestObj() = default; + TestObj(const TestObj& other) + { + printf("TestObj copy ctor called: {%s,%d} <- {%s,%d}!!!\n", to_string(state), id, to_string(other.state), other.id); + id = other.id; + state = obj_state_t::copy_ctor; + copy_counter++; + } + TestObj(TestObj&& other) noexcept + { + printf("TestObj move ctor called: {%s,%d} <- {%s,%d}!!!\n", to_string(state), id, to_string(other.state), other.id); + id = other.id; + state = obj_state_t::move_ctor; + other.state = obj_state_t::from_move_ctor; + move_counter++; + } + ~TestObj() + { + dtor_counter++; + printf("TestObj {%s,%d} dtor called!!!\n", to_string(state), id); + } + TestObj& operator=(const TestObj& other) + { + printf("TestObj copy operator called: {%s,%d} <- {%s,%d}!!!\n", + to_string(state), + id, + to_string(other.state), + other.id); + id = other.id; + state = other.state; + copy_counter++; + return *this; + } + TestObj& operator=(TestObj&& other) noexcept + { + printf("TestObj move operator called: {%s,%d} <- {%s,%d}!!!\n", + to_string(state), + id, + to_string(other.state), + other.id); + if (&other != this) { + id = other.id; + state = other.state; + other.state = obj_state_t::from_move_assign; + move_counter++; + } + return *this; + } + + obj_state_t state = obj_state_t::default_ctor; + int id = 0; + static int copy_counter; + static int move_counter; + static int dtor_counter; +}; + +int TestObj::copy_counter = 0; +int TestObj::move_counter = 0; +int TestObj::dtor_counter = 0; + +void new_test() +{ + TestObj::copy_counter = 0; + TestObj::move_counter = 0; + TestObj::dtor_counter = 0; +} + +class custom_proc : public srslte::proc_impl_t +{ +public: + proc_outcome_t init(int a_) + { + if (a_ < 0) { + printf("Failed to initiate custom_proc\n"); + return proc_outcome_t::error; + } + obj.id = a_; + return proc_outcome_t::yield; + } + proc_outcome_t step() final + { + if (counter++ > 5) { + return proc_outcome_t::success; + } + return proc_outcome_t::yield; + } + void stop() final { printf("TestObj %d stop() was called\n", obj.id); } + const char* name() const { return "custom proc"; } + + TestObj obj; + +private: + int counter = 0; +}; + +int test_local_1() +{ + new_test(); + printf("\n--- Test %s ---\n", __func__); + srslte::proc_t proc; + TESTASSERT(not proc.is_active()); + + proc.launch(1); + TESTASSERT(proc.is_active()); + TESTASSERT(not proc.is_complete()); + + while (proc.run()) { + } + + TESTASSERT(proc.is_active()); + TESTASSERT(proc.is_complete()); + + printf("pop being called\n"); + custom_proc procobj = proc.pop(); + TESTASSERT(procobj.obj.id == 1); + TESTASSERT(procobj.is_success()); + TESTASSERT(not proc.is_active()); + TESTASSERT(proc.get()->obj.id == 0); // Proc is ready to be reused + + printf("EXIT\n"); + TESTASSERT(TestObj::copy_counter == 0); + TESTASSERT(TestObj::move_counter == 2); // pop() makes a swap which causes 2 moves + TESTASSERT(TestObj::dtor_counter == 2); // 2 dtors inside pop() (handler and popped obj not yet destructed) + return 0; +} + +int test_callback_1() +{ + new_test(); + printf("\n--- Test %s ---\n", __func__); + srslte::callback_list_t callbacks; + srslte::proc_t proc; + TESTASSERT(not proc.is_active()); + + proc.launch(2); + callbacks.add_proc(proc); // We have to call pop() explicitly to take the result + TESTASSERT(callbacks.size() == 1); + + while (callbacks.size() > 0) { + TESTASSERT(proc.is_active()); + TESTASSERT(not proc.is_complete()); + callbacks.run(); + } + TESTASSERT(proc.is_active()); + TESTASSERT(proc.is_complete()); + + printf("pop being called\n"); + custom_proc procobj = proc.pop(); + TESTASSERT(procobj.is_success()); + TESTASSERT(procobj.obj.id == 2); + TESTASSERT(not proc.is_active()); + + TESTASSERT(proc.get()->obj.id == 0); // Proc is ready to be reused + printf("EXIT\n"); + TESTASSERT(TestObj::copy_counter == 0); + TESTASSERT(TestObj::move_counter == 2); // pop makes two moves + TESTASSERT(TestObj::dtor_counter == 2); // handler not yet destructed + return 0; +} + +int test_callback_2() +{ + new_test(); + printf("\n--- Test %s ---\n", __func__); + srslte::callback_list_t callbacks; + srslte::proc_t proc; + TESTASSERT(not proc.is_active()); + + proc.launch(3); + TESTASSERT(proc.is_active()); + TESTASSERT(not proc.is_complete()); + callbacks.consume_proc(std::move(proc)); + TESTASSERT(callbacks.size() == 1); + + while (callbacks.size() > 0) { + callbacks.run(); + } + // since the proc was consumed, it is erased without the need for pop() + + printf("EXIT\n"); + TESTASSERT(TestObj::copy_counter == 0); + TESTASSERT(TestObj::move_counter == 0); // no pop() + TESTASSERT(TestObj::dtor_counter == 1); // handler not yet destructed + return 0; +} + +int test_callback_3() +{ + new_test(); + printf("\n--- Test %s ---\n", __func__); + srslte::callback_list_t callbacks; + srslte::proc_t proc; + TESTASSERT(not proc.is_active()); + + proc.launch(4); + TESTASSERT(proc.is_active()); + TESTASSERT(not proc.is_complete()); + callbacks.defer_proc(proc); // we still have access to proc, but we do not need to call pop() + TESTASSERT(callbacks.size() == 1); + TESTASSERT(proc.is_active()); + TESTASSERT(not proc.is_complete()); + + while (callbacks.size() > 0) { + TESTASSERT(proc.is_active()); + TESTASSERT(not proc.is_complete()); + callbacks.run(); + } + TESTASSERT(not proc.is_active()); + TESTASSERT(not proc.is_complete()); + TESTASSERT(proc.get()->obj.id == 0); // Proc is ready to be reused + + printf("EXIT\n"); + TESTASSERT(TestObj::copy_counter == 0); + TESTASSERT(TestObj::move_counter == 0); + TESTASSERT(TestObj::dtor_counter == 1); // handler not yet destructed + return 0; +} + +int test_callback_4() +{ + new_test(); + printf("\n--- Test %s ---\n", __func__); + srslte::callback_list_t callbacks; + int* counter = new int(5); + + { + callbacks.defer_task([counter]() { + printf("current counter=%d\n", *counter); + if (--(*counter) == 0) { + return proc_outcome_t::success; + } + return proc_outcome_t::yield; + }); + } + + while (callbacks.size() > 0) { + callbacks.run(); + } + + // printf("counter=%d\n", counter); + TESTASSERT(*counter == 0); + delete counter; + + return 0; +} + +int main() +{ + TESTASSERT(test_local_1() == 0); + TESTASSERT(test_callback_1() == 0); + TESTASSERT(test_callback_2() == 0); + TESTASSERT(test_callback_3() == 0); + TESTASSERT(test_callback_4() == 0); + + return 0; +} diff --git a/lib/test/common/test_eea2.cc b/lib/test/common/test_eea2.cc index c5bb6fa8c..c3969c080 100644 --- a/lib/test/common/test_eea2.cc +++ b/lib/test/common/test_eea2.cc @@ -19,13 +19,12 @@ * */ -#include -#include #include +#include +#include #include "srslte/common/liblte_security.h" #include "srslte/srslte.h" -#include "srslte/common/liblte_security.h" /* * Prototypes diff --git a/lib/test/common/test_eea3.cc b/lib/test/common/test_eea3.cc new file mode 100644 index 000000000..c78ef2794 --- /dev/null +++ b/lib/test/common/test_eea3.cc @@ -0,0 +1,412 @@ + + +#include +#include +#include + +#include "srslte/common/liblte_security.h" +#include "srslte/srslte.h" + +int32 arrcmp(uint8_t const* const a, uint8_t const* const b, uint32 len) +{ + uint32 i = 0; + + for (i = 0; i < len; i++) { + if (a[i] != b[i]) { + return a[i] - b[i]; + } + } + return 0; +} + +/* + * Tests + * + * Document Reference: Specification of the 3GPP Confidentiality and Integrity Algorithms 128-EEA3 & 128-EIA3: Document + * 3: Implementor’s Test Data https://www.gsma.com/aboutus/wp-content/uploads/2014/12/eea3eia3testdatav11.pdf + * + */ + +void test_set_1() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = {0x17, 0x3d, 0x14, 0xba, 0x50, 0x03, 0x73, 0x1d, 0x7a, 0x60, 0x04, 0x94, 0x70, 0xf0, 0x0a, 0x29}; + uint32_t count = 0x66035492; + uint8_t bearer = 0xf; + uint8_t direction = 0; + uint32_t len_bits = 193; + uint32_t len_bytes = (len_bits + 7) / 8; + + uint8_t msg[] = {0x6c, 0xf6, 0x53, 0x40, 0x73, 0x55, 0x52, 0xab, 0x0c, 0x97, 0x52, 0xfa, 0x6f, 0x90, + 0x25, 0xfe, 0x0b, 0xd6, 0x75, 0xd9, 0x00, 0x58, 0x75, 0xb2, 0x00, 0x00, 0x00, 0x00}; + + uint8_t ct[] = {0xa6, 0xc8, 0x5f, 0xc6, 0x6a, 0xfb, 0x85, 0x33, 0xaa, 0xfc, 0x25, 0x18, 0xdf, 0xe7, + 0x84, 0x94, 0x0e, 0xe1, 0xe4, 0xb0, 0x30, 0x23, 0x8c, 0xc8, 0x00, 0x00, 0x00, 0x00}; + + uint8_t* out = (uint8_t*)calloc(len_bytes, sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea3(key, count, bearer, direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + + if (err_cmp == 0) { + printf("Test Set 1 Encryption: Success\n"); + } else { + printf("Test Set 1 Encryption: Failed\n"); + } + + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea3(key, count, bearer, direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + if (err_cmp == 0) { + printf("Test Set 1 Decryption: Success\n"); + } else { + printf("Test Set 1 Decryption: Failed\n"); + } + + free(out); +} + +void test_set_2() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = {0xe5, 0xbd, 0x3e, 0xa0, 0xeb, 0x55, 0xad, 0xe8, 0x66, 0xc6, 0xac, 0x58, 0xbd, 0x54, 0x30, 0x2a}; + uint32_t count = 0x56823; + uint8_t bearer = 0x18; + uint8_t direction = 1; + uint32_t len_bits = 800; + uint32_t len_bytes = (len_bits + 7) / 8; + + uint8_t msg[] = {0x14, 0xa8, 0xef, 0x69, 0x3d, 0x67, 0x85, 0x07, 0xbb, 0xe7, 0x27, 0x0a, 0x7f, 0x67, 0xff, 0x50, 0x06, + 0xc3, 0x52, 0x5b, 0x98, 0x07, 0xe4, 0x67, 0xc4, 0xe5, 0x60, 0x00, 0xba, 0x33, 0x8f, 0x5d, 0x42, 0x95, + 0x59, 0x03, 0x67, 0x51, 0x82, 0x22, 0x46, 0xc8, 0x0d, 0x3b, 0x38, 0xf0, 0x7f, 0x4b, 0xe2, 0xd8, 0xff, + 0x58, 0x05, 0xf5, 0x13, 0x22, 0x29, 0xbd, 0xe9, 0x3b, 0xbb, 0xdc, 0xaf, 0x38, 0x2b, 0xf1, 0xee, 0x97, + 0x2f, 0xbf, 0x99, 0x77, 0xba, 0xda, 0x89, 0x45, 0x84, 0x7a, 0x2a, 0x6c, 0x9a, 0xd3, 0x4a, 0x66, 0x75, + 0x54, 0xe0, 0x4d, 0x1f, 0x7f, 0xa2, 0xc3, 0x32, 0x41, 0xbd, 0x8f, 0x01, 0xba, 0x22, 0x0d}; + + uint8_t ct[] = {0x13, 0x1d, 0x43, 0xe0, 0xde, 0xa1, 0xbe, 0x5c, 0x5a, 0x1b, 0xfd, 0x97, 0x1d, 0x85, 0x2c, 0xbf, 0x71, + 0x2d, 0x7b, 0x4f, 0x57, 0x96, 0x1f, 0xea, 0x32, 0x08, 0xaf, 0xa8, 0xbc, 0xa4, 0x33, 0xf4, 0x56, 0xad, + 0x09, 0xc7, 0x41, 0x7e, 0x58, 0xbc, 0x69, 0xcf, 0x88, 0x66, 0xd1, 0x35, 0x3f, 0x74, 0x86, 0x5e, 0x80, + 0x78, 0x1d, 0x20, 0x2d, 0xfb, 0x3e, 0xcf, 0xf7, 0xfc, 0xbc, 0x3b, 0x19, 0x0f, 0xe8, 0x2a, 0x20, 0x4e, + 0xd0, 0xe3, 0x50, 0xfc, 0x0f, 0x6f, 0x26, 0x13, 0xb2, 0xf2, 0xbc, 0xa6, 0xdf, 0x5a, 0x47, 0x3a, 0x57, + 0xa4, 0xa0, 0x0d, 0x98, 0x5e, 0xba, 0xd8, 0x80, 0xd6, 0xf2, 0x38, 0x64, 0xa0, 0x7b, 0x01}; + + uint8_t* out = (uint8_t*)calloc(len_bytes, sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea3(key, count, bearer, direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + + if (err_cmp == 0) { + printf("Test Set 2 Encryption: Success\n"); + } else { + printf("Test Set 2 Encryption: Failed\n"); + } + + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea3(key, count, bearer, direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + if (err_cmp == 0) { + printf("Test Set 2 Decryption: Success\n"); + } else { + printf("Test Set 2 Decryption: Failed\n"); + } + + free(out); +} + +void test_set_3() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = {0xd4, 0x55, 0x2a, 0x8f, 0xd6, 0xe6, 0x1c, 0xc8, 0x1a, 0x20, 0x09, 0x14, 0x1a, 0x29, 0xc1, 0x0b}; + uint32_t count = 0x76452ec1; + uint8_t bearer = 0x2; + uint8_t direction = 0x1; + uint32_t len_bits = 1570; + uint32_t len_bytes = (len_bits + 7) / 8; + + uint8_t msg[] = {0x38, 0xf0, 0x7f, 0x4b, 0xe2, 0xd8, 0xff, 0x58, 0x05, 0xf5, 0x13, 0x22, 0x29, 0xbd, 0xe9, 0x3b, 0xbb, + 0xdc, 0xaf, 0x38, 0x2b, 0xf1, 0xee, 0x97, 0x2f, 0xbf, 0x99, 0x77, 0xba, 0xda, 0x89, 0x45, 0x84, 0x7a, + 0x2a, 0x6c, 0x9a, 0xd3, 0x4a, 0x66, 0x75, 0x54, 0xe0, 0x4d, 0x1f, 0x7f, 0xa2, 0xc3, 0x32, 0x41, 0xbd, + 0x8f, 0x01, 0xba, 0x22, 0x0d, 0x3c, 0xa4, 0xec, 0x41, 0xe0, 0x74, 0x59, 0x5f, 0x54, 0xae, 0x2b, 0x45, + 0x4f, 0xd9, 0x71, 0x43, 0x20, 0x43, 0x60, 0x19, 0x65, 0xcc, 0xa8, 0x5c, 0x24, 0x17, 0xed, 0x6c, 0xbe, + 0xc3, 0xba, 0xda, 0x84, 0xfc, 0x8a, 0x57, 0x9a, 0xea, 0x78, 0x37, 0xb0, 0x27, 0x11, 0x77, 0x24, 0x2a, + 0x64, 0xdc, 0x0a, 0x9d, 0xe7, 0x1a, 0x8e, 0xde, 0xe8, 0x6c, 0xa3, 0xd4, 0x7d, 0x03, 0x3d, 0x6b, 0xf5, + 0x39, 0x80, 0x4e, 0xca, 0x86, 0xc5, 0x84, 0xa9, 0x05, 0x2d, 0xe4, 0x6a, 0xd3, 0xfc, 0xed, 0x65, 0x54, + 0x3b, 0xd9, 0x02, 0x07, 0x37, 0x2b, 0x27, 0xaf, 0xb7, 0x92, 0x34, 0xf5, 0xff, 0x43, 0xea, 0x87, 0x08, + 0x20, 0xe2, 0xc2, 0xb7, 0x8a, 0x8a, 0xae, 0x61, 0xcc, 0xe5, 0x2a, 0x05, 0x15, 0xe3, 0x48, 0xd1, 0x96, + 0x66, 0x4a, 0x34, 0x56, 0xb1, 0x82, 0xa0, 0x7c, 0x40, 0x6e, 0x4a, 0x20, 0x79, 0x12, 0x71, 0xcf, 0xed, + 0xa1, 0x65, 0xd5, 0x35, 0xec, 0x5e, 0xa2, 0xd4, 0xdf, 0x40, 0x00, 0x00, 0x00}; + + uint8_t ct[] = {0x83, 0x83, 0xb0, 0x22, 0x9f, 0xcc, 0x0b, 0x9d, 0x22, 0x95, 0xec, 0x41, 0xc9, 0x77, 0xe9, 0xc2, 0xbb, + 0x72, 0xe2, 0x20, 0x37, 0x81, 0x41, 0xf9, 0xc8, 0x31, 0x8f, 0x3a, 0x27, 0x0d, 0xfb, 0xcd, 0xee, 0x64, + 0x11, 0xc2, 0xb3, 0x04, 0x4f, 0x17, 0x6d, 0xc6, 0xe0, 0x0f, 0x89, 0x60, 0xf9, 0x7a, 0xfa, 0xcd, 0x13, + 0x1a, 0xd6, 0xa3, 0xb4, 0x9b, 0x16, 0xb7, 0xba, 0xbc, 0xf2, 0xa5, 0x09, 0xeb, 0xb1, 0x6a, 0x75, 0xdc, + 0xab, 0x14, 0xff, 0x27, 0x5d, 0xbe, 0xee, 0xa1, 0xa2, 0xb1, 0x55, 0xf9, 0xd5, 0x2c, 0x26, 0x45, 0x2d, + 0x01, 0x87, 0xc3, 0x10, 0xa4, 0xee, 0x55, 0xbe, 0xaa, 0x78, 0xab, 0x40, 0x24, 0x61, 0x5b, 0xa9, 0xf5, + 0xd5, 0xad, 0xc7, 0x72, 0x8f, 0x73, 0x56, 0x06, 0x71, 0xf0, 0x13, 0xe5, 0xe5, 0x50, 0x08, 0x5d, 0x32, + 0x91, 0xdf, 0x7d, 0x5f, 0xec, 0xed, 0xde, 0xd5, 0x59, 0x64, 0x1b, 0x6c, 0x2f, 0x58, 0x52, 0x33, 0xbc, + 0x71, 0xe9, 0x60, 0x2b, 0xd2, 0x30, 0x58, 0x55, 0xbb, 0xd2, 0x5f, 0xfa, 0x7f, 0x17, 0xec, 0xbc, 0x04, + 0x2d, 0xaa, 0xe3, 0x8c, 0x1f, 0x57, 0xad, 0x8e, 0x8e, 0xbd, 0x37, 0x34, 0x6f, 0x71, 0xbe, 0xfd, 0xbb, + 0x74, 0x32, 0xe0, 0xe0, 0xbb, 0x2c, 0xfc, 0x09, 0xbc, 0xd9, 0x65, 0x70, 0xcb, 0x0c, 0x0c, 0x39, 0xdf, + 0x5e, 0x29, 0x29, 0x4e, 0x82, 0x70, 0x3a, 0x63, 0x7f, 0x80, 0x00, 0x00, 0x00}; + + uint8_t* out = (uint8_t*)calloc(len_bytes, sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea3(key, count, bearer, direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + int i; + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + + if (err_cmp == 0) { + printf("Test Set 3 Encryption: Success\n"); + } else { + printf("Test Set 3 Encryption: Failed\n"); + } + + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea3(key, count, bearer, direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + if (err_cmp == 0) { + printf("Test Set 3 Decryption: Success\n"); + } else { + printf("Test Set 3 Decryption: Failed\n"); + } + + free(out); +} + +void test_set_4() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = {0xdb, 0x84, 0xb4, 0xfb, 0xcc, 0xda, 0x56, 0x3b, 0x66, 0x22, 0x7b, 0xfe, 0x45, 0x6f, 0x0f, 0x77}; + uint32_t count = 0xe4850fe1; + uint8_t bearer = 0x10; + uint8_t direction = 0x1; + uint32_t len_bits = 2798; + uint32_t len_bytes = (len_bits + 7) / 8; + + uint8_t msg[] = { + 0xe5, 0x39, 0xf3, 0xb8, 0x97, 0x32, 0x40, 0xda, 0x03, 0xf2, 0xb8, 0xaa, 0x05, 0xee, 0x0a, 0x00, 0xdb, 0xaf, 0xc0, + 0xe1, 0x82, 0x05, 0x5d, 0xfe, 0x3d, 0x73, 0x83, 0xd9, 0x2c, 0xef, 0x40, 0xe9, 0x29, 0x28, 0x60, 0x5d, 0x52, 0xd0, + 0x5f, 0x4f, 0x90, 0x18, 0xa1, 0xf1, 0x89, 0xae, 0x39, 0x97, 0xce, 0x19, 0x15, 0x5f, 0xb1, 0x22, 0x1d, 0xb8, 0xbb, + 0x09, 0x51, 0xa8, 0x53, 0xad, 0x85, 0x2c, 0xe1, 0x6c, 0xff, 0x07, 0x38, 0x2c, 0x93, 0xa1, 0x57, 0xde, 0x00, 0xdd, + 0xb1, 0x25, 0xc7, 0x53, 0x9f, 0xd8, 0x50, 0x45, 0xe4, 0xee, 0x07, 0xe0, 0xc4, 0x3f, 0x9e, 0x9d, 0x6f, 0x41, 0x4f, + 0xc4, 0xd1, 0xc6, 0x29, 0x17, 0x81, 0x3f, 0x74, 0xc0, 0x0f, 0xc8, 0x3f, 0x3e, 0x2e, 0xd7, 0xc4, 0x5b, 0xa5, 0x83, + 0x52, 0x64, 0xb4, 0x3e, 0x0b, 0x20, 0xaf, 0xda, 0x6b, 0x30, 0x53, 0xbf, 0xb6, 0x42, 0x3b, 0x7f, 0xce, 0x25, 0x47, + 0x9f, 0xf5, 0xf1, 0x39, 0xdd, 0x9b, 0x5b, 0x99, 0x55, 0x58, 0xe2, 0xa5, 0x6b, 0xe1, 0x8d, 0xd5, 0x81, 0xcd, 0x01, + 0x7c, 0x73, 0x5e, 0x6f, 0x0d, 0x0d, 0x97, 0xc4, 0xdd, 0xc1, 0xd1, 0xda, 0x70, 0xc6, 0xdb, 0x4a, 0x12, 0xcc, 0x92, + 0x77, 0x8e, 0x2f, 0xbb, 0xd6, 0xf3, 0xba, 0x52, 0xaf, 0x91, 0xc9, 0xc6, 0xb6, 0x4e, 0x8d, 0xa4, 0xf7, 0xa2, 0xc2, + 0x66, 0xd0, 0x2d, 0x00, 0x17, 0x53, 0xdf, 0x08, 0x96, 0x03, 0x93, 0xc5, 0xd5, 0x68, 0x88, 0xbf, 0x49, 0xeb, 0x5c, + 0x16, 0xd9, 0xa8, 0x04, 0x27, 0xa4, 0x16, 0xbc, 0xb5, 0x97, 0xdf, 0x5b, 0xfe, 0x6f, 0x13, 0x89, 0x0a, 0x07, 0xee, + 0x13, 0x40, 0xe6, 0x47, 0x6b, 0x0d, 0x9a, 0xa8, 0xf8, 0x22, 0xab, 0x0f, 0xd1, 0xab, 0x0d, 0x20, 0x4f, 0x40, 0xb7, + 0xce, 0x6f, 0x2e, 0x13, 0x6e, 0xb6, 0x74, 0x85, 0xe5, 0x07, 0x80, 0x4d, 0x50, 0x45, 0x88, 0xad, 0x37, 0xff, 0xd8, + 0x16, 0x56, 0x8b, 0x2d, 0xc4, 0x03, 0x11, 0xdf, 0xb6, 0x54, 0xcd, 0xea, 0xd4, 0x7e, 0x23, 0x85, 0xc3, 0x43, 0x62, + 0x03, 0xdd, 0x83, 0x6f, 0x9c, 0x64, 0xd9, 0x74, 0x62, 0xad, 0x5d, 0xfa, 0x63, 0xb5, 0xcf, 0xe0, 0x8a, 0xcb, 0x95, + 0x32, 0x86, 0x6f, 0x5c, 0xa7, 0x87, 0x56, 0x6f, 0xca, 0x93, 0xe6, 0xb1, 0x69, 0x3e, 0xe1, 0x5c, 0xf6, 0xf7, 0xa2, + 0xd6, 0x89, 0xd9, 0x74, 0x17, 0x98, 0xdc, 0x1c, 0x23, 0x8e, 0x1b, 0xe6, 0x50, 0x73, 0x3b, 0x18, 0xfb, 0x34, 0xff, + 0x88, 0x0e, 0x16, 0xbb, 0xd2, 0x1b, 0x47, 0xac, 0x00, 0x00}; + + uint8_t ct[] = { + 0x4b, 0xbf, 0xa9, 0x1b, 0xa2, 0x5d, 0x47, 0xdb, 0x9a, 0x9f, 0x19, 0x0d, 0x96, 0x2a, 0x19, 0xab, 0x32, 0x39, 0x26, + 0xb3, 0x51, 0xfb, 0xd3, 0x9e, 0x35, 0x1e, 0x05, 0xda, 0x8b, 0x89, 0x25, 0xe3, 0x0b, 0x1c, 0xce, 0x0d, 0x12, 0x21, + 0x10, 0x10, 0x95, 0x81, 0x5c, 0xc7, 0xcb, 0x63, 0x19, 0x50, 0x9e, 0xc0, 0xd6, 0x79, 0x40, 0x49, 0x19, 0x87, 0xe1, + 0x3f, 0x0a, 0xff, 0xac, 0x33, 0x2a, 0xa6, 0xaa, 0x64, 0x62, 0x6d, 0x3e, 0x9a, 0x19, 0x17, 0x51, 0x9e, 0x0b, 0x97, + 0xb6, 0x55, 0xc6, 0xa1, 0x65, 0xe4, 0x4c, 0xa9, 0xfe, 0xac, 0x07, 0x90, 0xd2, 0xa3, 0x21, 0xad, 0x3d, 0x86, 0xb7, + 0x9c, 0x51, 0x38, 0x73, 0x9f, 0xa3, 0x8d, 0x88, 0x7e, 0xc7, 0xde, 0xf4, 0x49, 0xce, 0x8a, 0xbd, 0xd3, 0xe7, 0xf8, + 0xdc, 0x4c, 0xa9, 0xe7, 0xb7, 0x33, 0x14, 0xad, 0x31, 0x0f, 0x90, 0x25, 0xe6, 0x19, 0x46, 0xb3, 0xa5, 0x6d, 0xc6, + 0x49, 0xec, 0x0d, 0xa0, 0xd6, 0x39, 0x43, 0xdf, 0xf5, 0x92, 0xcf, 0x96, 0x2a, 0x7e, 0xfb, 0x2c, 0x85, 0x24, 0xe3, + 0x5a, 0x2a, 0x6e, 0x78, 0x79, 0xd6, 0x26, 0x04, 0xef, 0x26, 0x86, 0x95, 0xfa, 0x40, 0x03, 0x02, 0x7e, 0x22, 0xe6, + 0x08, 0x30, 0x77, 0x52, 0x20, 0x64, 0xbd, 0x4a, 0x5b, 0x90, 0x6b, 0x5f, 0x53, 0x12, 0x74, 0xf2, 0x35, 0xed, 0x50, + 0x6c, 0xff, 0x01, 0x54, 0xc7, 0x54, 0x92, 0x8a, 0x0c, 0xe5, 0x47, 0x6f, 0x2c, 0xb1, 0x02, 0x0a, 0x12, 0x22, 0xd3, + 0x2c, 0x14, 0x55, 0xec, 0xae, 0xf1, 0xe3, 0x68, 0xfb, 0x34, 0x4d, 0x17, 0x35, 0xbf, 0xbe, 0xde, 0xb7, 0x1d, 0x0a, + 0x33, 0xa2, 0xa5, 0x4b, 0x1d, 0xa5, 0xa2, 0x94, 0xe6, 0x79, 0x14, 0x4d, 0xdf, 0x11, 0xeb, 0x1a, 0x3d, 0xe8, 0xcf, + 0x0c, 0xc0, 0x61, 0x91, 0x79, 0x74, 0xf3, 0x5c, 0x1d, 0x9c, 0xa0, 0xac, 0x81, 0x80, 0x7f, 0x8f, 0xcc, 0xe6, 0x19, + 0x9a, 0x6c, 0x77, 0x12, 0xda, 0x86, 0x50, 0x21, 0xb0, 0x4c, 0xe0, 0x43, 0x95, 0x16, 0xf1, 0xa5, 0x26, 0xcc, 0xda, + 0x9f, 0xd9, 0xab, 0xbd, 0x53, 0xc3, 0xa6, 0x84, 0xf9, 0xae, 0x1e, 0x7e, 0xe6, 0xb1, 0x1d, 0xa1, 0x38, 0xea, 0x82, + 0x6c, 0x55, 0x16, 0xb5, 0xaa, 0xdf, 0x1a, 0xbb, 0xe3, 0x6f, 0xa7, 0xff, 0xf9, 0x2e, 0x3a, 0x11, 0x76, 0x06, 0x4e, + 0x8d, 0x95, 0xf2, 0xe4, 0x88, 0x2b, 0x55, 0x00, 0xb9, 0x32, 0x28, 0xb2, 0x19, 0x4a, 0x47, 0x5c, 0x1a, 0x27, 0xf6, + 0x3f, 0x9f, 0xfd, 0x26, 0x49, 0x89, 0xa1, 0xbc, 0x00, 0x00}; + + uint8_t* out = (uint8_t*)calloc(len_bytes, sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea3(key, count, bearer, direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + int i; + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + + if (err_cmp == 0) { + printf("Test Set 4 Encryption: Success\n"); + } else { + printf("Test Set 4 Encryption: Failed\n"); + } + + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea3(key, count, bearer, direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + if (err_cmp == 0) { + printf("Test Set 4 Decryption: Success\n"); + } else { + printf("Test Set 4 Decryption: Failed\n"); + } + + free(out); +} + +void test_set_5() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = {0xe1, 0x3f, 0xed, 0x21, 0xb4, 0x6e, 0x4e, 0x7e, 0xc3, 0x12, 0x53, 0xb2, 0xbb, 0x17, 0xb3, 0xe0}; + uint32_t count = 0x2738cdaa; + uint8_t bearer = 0x1a; + uint8_t direction = 0x0; + uint32_t len_bits = 4019; + uint32_t len_bytes = (len_bits + 7) / 8; + + uint8_t msg[] = { + 0x8d, 0x74, 0xe2, 0x0d, 0x54, 0x89, 0x4e, 0x06, 0xd3, 0xcb, 0x13, 0xcb, 0x39, 0x33, 0x06, 0x5e, 0x86, 0x74, 0xbe, + 0x62, 0xad, 0xb1, 0xc7, 0x2b, 0x3a, 0x64, 0x69, 0x65, 0xab, 0x63, 0xcb, 0x7b, 0x78, 0x54, 0xdf, 0xdc, 0x27, 0xe8, + 0x49, 0x29, 0xf4, 0x9c, 0x64, 0xb8, 0x72, 0xa4, 0x90, 0xb1, 0x3f, 0x95, 0x7b, 0x64, 0x82, 0x7e, 0x71, 0xf4, 0x1f, + 0xbd, 0x42, 0x69, 0xa4, 0x2c, 0x97, 0xf8, 0x24, 0x53, 0x70, 0x27, 0xf8, 0x6e, 0x9f, 0x4a, 0xd8, 0x2d, 0x1d, 0xf4, + 0x51, 0x69, 0x0f, 0xdd, 0x98, 0xb6, 0xd0, 0x3f, 0x3a, 0x0e, 0xbe, 0x3a, 0x31, 0x2d, 0x6b, 0x84, 0x0b, 0xa5, 0xa1, + 0x82, 0x0b, 0x2a, 0x2c, 0x97, 0x09, 0xc0, 0x90, 0xd2, 0x45, 0xed, 0x26, 0x7c, 0xf8, 0x45, 0xae, 0x41, 0xfa, 0x97, + 0x5d, 0x33, 0x33, 0xac, 0x30, 0x09, 0xfd, 0x40, 0xeb, 0xa9, 0xeb, 0x5b, 0x88, 0x57, 0x14, 0xb7, 0x68, 0xb6, 0x97, + 0x13, 0x8b, 0xaf, 0x21, 0x38, 0x0e, 0xca, 0x49, 0xf6, 0x44, 0xd4, 0x86, 0x89, 0xe4, 0x21, 0x57, 0x60, 0xb9, 0x06, + 0x73, 0x9f, 0x0d, 0x2b, 0x3f, 0x09, 0x11, 0x33, 0xca, 0x15, 0xd9, 0x81, 0xcb, 0xe4, 0x01, 0xba, 0xf7, 0x2d, 0x05, + 0xac, 0xe0, 0x5c, 0xcc, 0xb2, 0xd2, 0x97, 0xf4, 0xef, 0x6a, 0x5f, 0x58, 0xd9, 0x12, 0x46, 0xcf, 0xa7, 0x72, 0x15, + 0xb8, 0x92, 0xab, 0x44, 0x1d, 0x52, 0x78, 0x45, 0x27, 0x95, 0xcc, 0xb7, 0xf5, 0xd7, 0x90, 0x57, 0xa1, 0xc4, 0xf7, + 0x7f, 0x80, 0xd4, 0x6d, 0xb2, 0x03, 0x3c, 0xb7, 0x9b, 0xed, 0xf8, 0xe6, 0x05, 0x51, 0xce, 0x10, 0xc6, 0x67, 0xf6, + 0x2a, 0x97, 0xab, 0xaf, 0xab, 0xbc, 0xd6, 0x77, 0x20, 0x18, 0xdf, 0x96, 0xa2, 0x82, 0xea, 0x73, 0x7c, 0xe2, 0xcb, + 0x33, 0x12, 0x11, 0xf6, 0x0d, 0x53, 0x54, 0xce, 0x78, 0xf9, 0x91, 0x8d, 0x9c, 0x20, 0x6c, 0xa0, 0x42, 0xc9, 0xb6, + 0x23, 0x87, 0xdd, 0x70, 0x96, 0x04, 0xa5, 0x0a, 0xf1, 0x6d, 0x8d, 0x35, 0xa8, 0x90, 0x6b, 0xe4, 0x84, 0xcf, 0x2e, + 0x74, 0xa9, 0x28, 0x99, 0x40, 0x36, 0x43, 0x53, 0x24, 0x9b, 0x27, 0xb4, 0xc9, 0xae, 0x29, 0xed, 0xdf, 0xc7, 0xda, + 0x64, 0x18, 0x79, 0x1a, 0x4e, 0x7b, 0xaa, 0x06, 0x60, 0xfa, 0x64, 0x51, 0x1f, 0x2d, 0x68, 0x5c, 0xc3, 0xa5, 0xff, + 0x70, 0xe0, 0xd2, 0xb7, 0x42, 0x92, 0xe3, 0xb8, 0xa0, 0xcd, 0x6b, 0x04, 0xb1, 0xc7, 0x90, 0xb8, 0xea, 0xd2, 0x70, + 0x37, 0x08, 0x54, 0x0d, 0xea, 0x2f, 0xc0, 0x9c, 0x3d, 0xa7, 0x70, 0xf6, 0x54, 0x49, 0xe8, 0x4d, 0x81, 0x7a, 0x4f, + 0x55, 0x10, 0x55, 0xe1, 0x9a, 0xb8, 0x50, 0x18, 0xa0, 0x02, 0x8b, 0x71, 0xa1, 0x44, 0xd9, 0x67, 0x91, 0xe9, 0xa3, + 0x57, 0x79, 0x33, 0x50, 0x4e, 0xee, 0x00, 0x60, 0x34, 0x0c, 0x69, 0xd2, 0x74, 0xe1, 0xbf, 0x9d, 0x80, 0x5d, 0xcb, + 0xcc, 0x1a, 0x6f, 0xaa, 0x97, 0x68, 0x00, 0xb6, 0xff, 0x2b, 0x67, 0x1d, 0xc4, 0x63, 0x65, 0x2f, 0xa8, 0xa3, 0x3e, + 0xe5, 0x09, 0x74, 0xc1, 0xc2, 0x1b, 0xe0, 0x1e, 0xab, 0xb2, 0x16, 0x74, 0x30, 0x26, 0x9d, 0x72, 0xee, 0x51, 0x1c, + 0x9d, 0xde, 0x30, 0x79, 0x7c, 0x9a, 0x25, 0xd8, 0x6c, 0xe7, 0x4f, 0x5b, 0x96, 0x1b, 0xe5, 0xfd, 0xfb, 0x68, 0x07, + 0x81, 0x40, 0x39, 0xe7, 0x13, 0x76, 0x36, 0xbd, 0x1d, 0x7f, 0xa9, 0xe0, 0x9e, 0xfd, 0x20, 0x07, 0x50, 0x59, 0x06, + 0xa5, 0xac, 0x45, 0xdf, 0xde, 0xed, 0x77, 0x57, 0xbb, 0xee, 0x74, 0x57, 0x49, 0xc2, 0x96, 0x33, 0x35, 0x0b, 0xee, + 0x0e, 0xa6, 0xf4, 0x09, 0xdf, 0x45, 0x80, 0x16, 0x00, 0x00}; + + uint8_t ct[] = { + 0x94, 0xea, 0xa4, 0xaa, 0x30, 0xa5, 0x71, 0x37, 0xdd, 0xf0, 0x9b, 0x97, 0xb2, 0x56, 0x18, 0xa2, 0x0a, 0x13, 0xe2, + 0xf1, 0x0f, 0xa5, 0xbf, 0x81, 0x61, 0xa8, 0x79, 0xcc, 0x2a, 0xe7, 0x97, 0xa6, 0xb4, 0xcf, 0x2d, 0x9d, 0xf3, 0x1d, + 0xeb, 0xb9, 0x90, 0x5c, 0xcf, 0xec, 0x97, 0xde, 0x60, 0x5d, 0x21, 0xc6, 0x1a, 0xb8, 0x53, 0x1b, 0x7f, 0x3c, 0x9d, + 0xa5, 0xf0, 0x39, 0x31, 0xf8, 0xa0, 0x64, 0x2d, 0xe4, 0x82, 0x11, 0xf5, 0xf5, 0x2f, 0xfe, 0xa1, 0x0f, 0x39, 0x2a, + 0x04, 0x76, 0x69, 0x98, 0x5d, 0xa4, 0x54, 0xa2, 0x8f, 0x08, 0x09, 0x61, 0xa6, 0xc2, 0xb6, 0x2d, 0xaa, 0x17, 0xf3, + 0x3c, 0xd6, 0x0a, 0x49, 0x71, 0xf4, 0x8d, 0x2d, 0x90, 0x93, 0x94, 0xa5, 0x5f, 0x48, 0x11, 0x7a, 0xce, 0x43, 0xd7, + 0x08, 0xe6, 0xb7, 0x7d, 0x3d, 0xc4, 0x6d, 0x8b, 0xc0, 0x17, 0xd4, 0xd1, 0xab, 0xb7, 0x7b, 0x74, 0x28, 0xc0, 0x42, + 0xb0, 0x6f, 0x2f, 0x99, 0xd8, 0xd0, 0x7c, 0x98, 0x79, 0xd9, 0x96, 0x00, 0x12, 0x7a, 0x31, 0x98, 0x5f, 0x10, 0x99, + 0xbb, 0xd7, 0xd6, 0xc1, 0x51, 0x9e, 0xde, 0x8f, 0x5e, 0xeb, 0x4a, 0x61, 0x0b, 0x34, 0x9a, 0xc0, 0x1e, 0xa2, 0x35, + 0x06, 0x91, 0x75, 0x6b, 0xd1, 0x05, 0xc9, 0x74, 0xa5, 0x3e, 0xdd, 0xb3, 0x5d, 0x1d, 0x41, 0x00, 0xb0, 0x12, 0xe5, + 0x22, 0xab, 0x41, 0xf4, 0xc5, 0xf2, 0xfd, 0xe7, 0x6b, 0x59, 0xcb, 0x8b, 0x96, 0xd8, 0x85, 0xcf, 0xe4, 0x08, 0x0d, + 0x13, 0x28, 0xa0, 0xd6, 0x36, 0xcc, 0x0e, 0xdc, 0x05, 0x80, 0x0b, 0x76, 0xac, 0xca, 0x8f, 0xef, 0x67, 0x20, 0x84, + 0xd1, 0xf5, 0x2a, 0x8b, 0xbd, 0x8e, 0x09, 0x93, 0x32, 0x09, 0x92, 0xc7, 0xff, 0xba, 0xe1, 0x7c, 0x40, 0x84, 0x41, + 0xe0, 0xee, 0x88, 0x3f, 0xc8, 0xa8, 0xb0, 0x5e, 0x22, 0xf5, 0xff, 0x7f, 0x8d, 0x1b, 0x48, 0xc7, 0x4c, 0x46, 0x8c, + 0x46, 0x7a, 0x02, 0x8f, 0x09, 0xfd, 0x7c, 0xe9, 0x11, 0x09, 0xa5, 0x70, 0xa2, 0xd5, 0xc4, 0xd5, 0xf4, 0xfa, 0x18, + 0xc5, 0xdd, 0x3e, 0x45, 0x62, 0xaf, 0xe2, 0x4e, 0xf7, 0x71, 0x90, 0x1f, 0x59, 0xaf, 0x64, 0x58, 0x98, 0xac, 0xef, + 0x08, 0x8a, 0xba, 0xe0, 0x7e, 0x92, 0xd5, 0x2e, 0xb2, 0xde, 0x55, 0x04, 0x5b, 0xb1, 0xb7, 0xc4, 0x16, 0x4e, 0xf2, + 0xd7, 0xa6, 0xca, 0xc1, 0x5e, 0xeb, 0x92, 0x6d, 0x7e, 0xa2, 0xf0, 0x8b, 0x66, 0xe1, 0xf7, 0x59, 0xf3, 0xae, 0xe4, + 0x46, 0x14, 0x72, 0x5a, 0xa3, 0xc7, 0x48, 0x2b, 0x30, 0x84, 0x4c, 0x14, 0x3f, 0xf8, 0x5b, 0x53, 0xf1, 0xe5, 0x83, + 0xc5, 0x01, 0x25, 0x7d, 0xdd, 0xd0, 0x96, 0xb8, 0x12, 0x68, 0xda, 0xa3, 0x03, 0xf1, 0x72, 0x34, 0xc2, 0x33, 0x35, + 0x41, 0xf0, 0xbb, 0x8e, 0x19, 0x06, 0x48, 0xc5, 0x80, 0x7c, 0x86, 0x6d, 0x71, 0x93, 0x22, 0x86, 0x09, 0xad, 0xb9, + 0x48, 0x68, 0x6f, 0x7d, 0xe2, 0x94, 0xa8, 0x02, 0xcc, 0x38, 0xf7, 0xfe, 0x52, 0x08, 0xf5, 0xea, 0x31, 0x96, 0xd0, + 0x16, 0x7b, 0x9b, 0xdd, 0x02, 0xf0, 0xd2, 0xa5, 0x22, 0x1c, 0xa5, 0x08, 0xf8, 0x93, 0xaf, 0x5c, 0x4b, 0x4b, 0xb9, + 0xf4, 0xf5, 0x20, 0xfd, 0x84, 0x28, 0x9b, 0x3d, 0xbe, 0x7e, 0x61, 0x49, 0x7a, 0x7e, 0x2a, 0x58, 0x40, 0x37, 0xea, + 0x63, 0x7b, 0x69, 0x81, 0x12, 0x71, 0x74, 0xaf, 0x57, 0xb4, 0x71, 0xdf, 0x4b, 0x27, 0x68, 0xfd, 0x79, 0xc1, 0x54, + 0x0f, 0xb3, 0xed, 0xf2, 0xea, 0x22, 0xcb, 0x69, 0xbe, 0xc0, 0xcf, 0x8d, 0x93, 0x3d, 0x9c, 0x6f, 0xdd, 0x64, 0x5e, + 0x85, 0x05, 0x91, 0xcc, 0xa3, 0xd6, 0x2c, 0x0c, 0xc0, 0x00}; + + uint8_t* out = (uint8_t*)calloc(len_bytes, sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea3(key, count, bearer, direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + int i; + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + + if (err_cmp == 0) { + printf("Test Set 5 Encryption: Success\n"); + } else { + printf("Test Set 5 Encryption: Failed\n"); + } + + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea3(key, count, bearer, direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + if (err_cmp == 0) { + printf("Test Set 5 Decryption: Success\n"); + } else { + printf("Test Set 5 Decryption: Failed\n"); + } + + free(out); +} + +int main(int argc, char* argv[]) +{ + test_set_1(); + test_set_2(); + test_set_3(); + test_set_4(); + test_set_5(); +} diff --git a/lib/test/common/test_eia3.cc b/lib/test/common/test_eia3.cc new file mode 100644 index 000000000..6fbdb9b30 --- /dev/null +++ b/lib/test/common/test_eia3.cc @@ -0,0 +1,236 @@ +/* + * Includes + */ + +#include +#include +#include +#include + +#include "srslte/common/liblte_security.h" +#include "srslte/common/security.h" +#include "srslte/srslte.h" + +/* + * Tests + * + * Document Reference: Specification of the 3GPP Confidentiality and Integrity Algorithms 128-EEA3 & 128-EIA3: Document + * 3: Implementor’s Test Data https://www.gsma.com/aboutus/wp-content/uploads/2014/12/eea3eia3testdatav11.pdf + * + */ + +void test_set_1() +{ + uint8_t key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint32_t count = 0x0; + uint8_t bearer = 0x0; + uint8_t direction = 0; + uint32_t len_bits = 1; + uint8_t msg[] = {0x00, 0x00, 0x00, 0x00}; + uint8_t expected_mac[] = {0xc8, 0xa9, 0x59, 0x5e}; + + uint8_t mac[4]; + + // gen mac + liblte_security_128_eia3(key, count, bearer, direction, msg, len_bits, mac); + int i; + + bool failed = false; + for (i = 0; i < 4; i++) { + if (mac[i] != expected_mac[i]) { + failed = true; + } + assert(mac[i] == expected_mac[i]); + } + if (failed == true) { + printf("Test Set 1: Failed\n"); + } else { + printf("Test Set 1: Success\n"); + } +} + +void test_set_2() +{ + uint8_t key[] = {0x47, 0x05, 0x41, 0x25, 0x56, 0x1e, 0xb2, 0xdd, 0xa9, 0x40, 0x59, 0xda, 0x05, 0x09, 0x78, 0x50}; + uint32_t count = 0x561eb2dd; + uint8_t bearer = 0x14; + uint8_t direction = 0; + uint32_t len_bits = 90; + uint8_t msg[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t expected_mac[] = {0x67, 0x19, 0xa0, 0x88}; + + uint8_t mac[4]; + + // gen mac + liblte_security_128_eia3(key, count, bearer, direction, msg, len_bits, mac); + int i; + + bool failed = false; + for (i = 0; i < 4; i++) { + if (mac[i] != expected_mac[i]) { + failed = true; + } + assert(mac[i] == expected_mac[i]); + } + if (failed == true) { + printf("Test Set 2: Failed\n"); + } else { + printf("Test Set 2: Success\n"); + } +} + +void test_set_3() +{ + uint8_t key[] = {0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb, 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a}; + uint32_t count = 0xa94059da; + uint8_t bearer = 0xa; + uint8_t direction = 1; + uint32_t len_bits = 577; + uint8_t msg[] = {0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e, 0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1, + 0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83, 0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0, + 0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9, 0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9, + 0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d, 0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c, + 0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81, 0x00, 0x00, 0x00, 0x00}; + uint8_t expected_mac[] = {0xfa, 0xe8, 0xff, 0x0b}; + + uint8_t mac[4]; + + // gen mac + liblte_security_128_eia3(key, count, bearer, direction, msg, len_bits, mac); + int i; + + bool failed = false; + for (i = 0; i < 4; i++) { + if (mac[i] != expected_mac[i]) { + failed = true; + } + assert(mac[i] == expected_mac[i]); + } + if (failed == true) { + printf("Test Set 3: Failed\n"); + } else { + printf("Test Set 3: Success\n"); + } +} + +void test_set_4() +{ + uint8_t key[] = {0xc8, 0xa4, 0x82, 0x62, 0xd0, 0xc2, 0xe2, 0xba, 0xc4, 0xb9, 0x6e, 0xf7, 0x7e, 0x80, 0xca, 0x59}; + uint32_t count = 0x05097850; + uint8_t bearer = 0x10; + uint8_t direction = 1; + uint32_t len_bits = 2079; + uint8_t msg[] = { + 0xb5, 0x46, 0x43, 0x0b, 0xf8, 0x7b, 0x4f, 0x1e, 0xe8, 0x34, 0x70, 0x4c, 0xd6, 0x95, 0x1c, 0x36, 0xe2, 0x6f, 0x10, + 0x8c, 0xf7, 0x31, 0x78, 0x8f, 0x48, 0xdc, 0x34, 0xf1, 0x67, 0x8c, 0x05, 0x22, 0x1c, 0x8f, 0xa7, 0xff, 0x2f, 0x39, + 0xf4, 0x77, 0xe7, 0xe4, 0x9e, 0xf6, 0x0a, 0x4e, 0xc2, 0xc3, 0xde, 0x24, 0x31, 0x2a, 0x96, 0xaa, 0x26, 0xe1, 0xcf, + 0xba, 0x57, 0x56, 0x38, 0x38, 0xb2, 0x97, 0xf4, 0x7e, 0x85, 0x10, 0xc7, 0x79, 0xfd, 0x66, 0x54, 0xb1, 0x43, 0x38, + 0x6f, 0xa6, 0x39, 0xd3, 0x1e, 0xdb, 0xd6, 0xc0, 0x6e, 0x47, 0xd1, 0x59, 0xd9, 0x43, 0x62, 0xf2, 0x6a, 0xee, 0xed, + 0xee, 0x0e, 0x4f, 0x49, 0xd9, 0xbf, 0x84, 0x12, 0x99, 0x54, 0x15, 0xbf, 0xad, 0x56, 0xee, 0x82, 0xd1, 0xca, 0x74, + 0x63, 0xab, 0xf0, 0x85, 0xb0, 0x82, 0xb0, 0x99, 0x04, 0xd6, 0xd9, 0x90, 0xd4, 0x3c, 0xf2, 0xe0, 0x62, 0xf4, 0x08, + 0x39, 0xd9, 0x32, 0x48, 0xb1, 0xeb, 0x92, 0xcd, 0xfe, 0xd5, 0x30, 0x0b, 0xc1, 0x48, 0x28, 0x04, 0x30, 0xb6, 0xd0, + 0xca, 0xa0, 0x94, 0xb6, 0xec, 0x89, 0x11, 0xab, 0x7d, 0xc3, 0x68, 0x24, 0xb8, 0x24, 0xdc, 0x0a, 0xf6, 0x68, 0x2b, + 0x09, 0x35, 0xfd, 0xe7, 0xb4, 0x92, 0xa1, 0x4d, 0xc2, 0xf4, 0x36, 0x48, 0x03, 0x8d, 0xa2, 0xcf, 0x79, 0x17, 0x0d, + 0x2d, 0x50, 0x13, 0x3f, 0xd4, 0x94, 0x16, 0xcb, 0x6e, 0x33, 0xbe, 0xa9, 0x0b, 0x8b, 0xf4, 0x55, 0x9b, 0x03, 0x73, + 0x2a, 0x01, 0xea, 0x29, 0x0e, 0x6d, 0x07, 0x4f, 0x79, 0xbb, 0x83, 0xc1, 0x0e, 0x58, 0x00, 0x15, 0xcc, 0x1a, 0x85, + 0xb3, 0x6b, 0x55, 0x01, 0x04, 0x6e, 0x9c, 0x4b, 0xdc, 0xae, 0x51, 0x35, 0x69, 0x0b, 0x86, 0x66, 0xbd, 0x54, 0xb7, + 0xa7, 0x03, 0xea, 0x7b, 0x6f, 0x22, 0x0a, 0x54, 0x69, 0xa5, 0x68, 0x02, 0x7e}; + uint8_t expected_mac[] = {0x00, 0x4a, 0xc4, 0xd6}; + + uint8_t mac[4]; + + // gen mac + liblte_security_128_eia3(key, count, bearer, direction, msg, len_bits, mac); + int i; + + bool failed = false; + for (i = 0; i < 4; i++) { + if (mac[i] != expected_mac[i]) { + failed = true; + } + assert(mac[i] == expected_mac[i]); + } + if (failed == true) { + printf("Test Set 4: Failed\n"); + } else { + printf("Test Set 4: Success\n"); + } +} + +void test_set_5() +{ + uint8_t key[] = {0x6b, 0x8b, 0x08, 0xee, 0x79, 0xe0, 0xb5, 0x98, 0x2d, 0x6d, 0x12, 0x8e, 0xa9, 0xf2, 0x20, 0xcb}; + uint32_t count = 0x561eb2dd; + uint8_t bearer = 0x1c; + uint8_t direction = 0; + uint32_t len_bits = 5670; + uint8_t msg[] = { + 0x5b, 0xad, 0x72, 0x47, 0x10, 0xba, 0x1c, 0x56, 0xd5, 0xa3, 0x15, 0xf8, 0xd4, 0x0f, 0x6e, 0x09, 0x37, 0x80, 0xbe, + 0x8e, 0x8d, 0xe0, 0x7b, 0x69, 0x92, 0x43, 0x20, 0x18, 0xe0, 0x8e, 0xd9, 0x6a, 0x57, 0x34, 0xaf, 0x8b, 0xad, 0x8a, + 0x57, 0x5d, 0x3a, 0x1f, 0x16, 0x2f, 0x85, 0x04, 0x5c, 0xc7, 0x70, 0x92, 0x55, 0x71, 0xd9, 0xf5, 0xb9, 0x4e, 0x45, + 0x4a, 0x77, 0xc1, 0x6e, 0x72, 0x93, 0x6b, 0xf0, 0x16, 0xae, 0x15, 0x74, 0x99, 0xf0, 0x54, 0x3b, 0x5d, 0x52, 0xca, + 0xa6, 0xdb, 0xea, 0xb6, 0x97, 0xd2, 0xbb, 0x73, 0xe4, 0x1b, 0x80, 0x75, 0xdc, 0xe7, 0x9b, 0x4b, 0x86, 0x04, 0x4f, + 0x66, 0x1d, 0x44, 0x85, 0xa5, 0x43, 0xdd, 0x78, 0x60, 0x6e, 0x04, 0x19, 0xe8, 0x05, 0x98, 0x59, 0xd3, 0xcb, 0x2b, + 0x67, 0xce, 0x09, 0x77, 0x60, 0x3f, 0x81, 0xff, 0x83, 0x9e, 0x33, 0x18, 0x59, 0x54, 0x4c, 0xfb, 0xc8, 0xd0, 0x0f, + 0xef, 0x1a, 0x4c, 0x85, 0x10, 0xfb, 0x54, 0x7d, 0x6b, 0x06, 0xc6, 0x11, 0xef, 0x44, 0xf1, 0xbc, 0xe1, 0x07, 0xcf, + 0xa4, 0x5a, 0x06, 0xaa, 0xb3, 0x60, 0x15, 0x2b, 0x28, 0xdc, 0x1e, 0xbe, 0x6f, 0x7f, 0xe0, 0x9b, 0x05, 0x16, 0xf9, + 0xa5, 0xb0, 0x2a, 0x1b, 0xd8, 0x4b, 0xb0, 0x18, 0x1e, 0x2e, 0x89, 0xe1, 0x9b, 0xd8, 0x12, 0x59, 0x30, 0xd1, 0x78, + 0x68, 0x2f, 0x38, 0x62, 0xdc, 0x51, 0xb6, 0x36, 0xf0, 0x4e, 0x72, 0x0c, 0x47, 0xc3, 0xce, 0x51, 0xad, 0x70, 0xd9, + 0x4b, 0x9b, 0x22, 0x55, 0xfb, 0xae, 0x90, 0x65, 0x49, 0xf4, 0x99, 0xf8, 0xc6, 0xd3, 0x99, 0x47, 0xed, 0x5e, 0x5d, + 0xf8, 0xe2, 0xde, 0xf1, 0x13, 0x25, 0x3e, 0x7b, 0x08, 0xd0, 0xa7, 0x6b, 0x6b, 0xfc, 0x68, 0xc8, 0x12, 0xf3, 0x75, + 0xc7, 0x9b, 0x8f, 0xe5, 0xfd, 0x85, 0x97, 0x6a, 0xa6, 0xd4, 0x6b, 0x4a, 0x23, 0x39, 0xd8, 0xae, 0x51, 0x47, 0xf6, + 0x80, 0xfb, 0xe7, 0x0f, 0x97, 0x8b, 0x38, 0xef, 0xfd, 0x7b, 0x2f, 0x78, 0x66, 0xa2, 0x25, 0x54, 0xe1, 0x93, 0xa9, + 0x4e, 0x98, 0xa6, 0x8b, 0x74, 0xbd, 0x25, 0xbb, 0x2b, 0x3f, 0x5f, 0xb0, 0xa5, 0xfd, 0x59, 0x88, 0x7f, 0x9a, 0xb6, + 0x81, 0x59, 0xb7, 0x17, 0x8d, 0x5b, 0x7b, 0x67, 0x7c, 0xb5, 0x46, 0xbf, 0x41, 0xea, 0xdc, 0xa2, 0x16, 0xfc, 0x10, + 0x85, 0x01, 0x28, 0xf8, 0xbd, 0xef, 0x5c, 0x8d, 0x89, 0xf9, 0x6a, 0xfa, 0x4f, 0xa8, 0xb5, 0x48, 0x85, 0x56, 0x5e, + 0xd8, 0x38, 0xa9, 0x50, 0xfe, 0xe5, 0xf1, 0xc3, 0xb0, 0xa4, 0xf6, 0xfb, 0x71, 0xe5, 0x4d, 0xfd, 0x16, 0x9e, 0x82, + 0xce, 0xcc, 0x72, 0x66, 0xc8, 0x50, 0xe6, 0x7c, 0x5e, 0xf0, 0xba, 0x96, 0x0f, 0x52, 0x14, 0x06, 0x0e, 0x71, 0xeb, + 0x17, 0x2a, 0x75, 0xfc, 0x14, 0x86, 0x83, 0x5c, 0xbe, 0xa6, 0x53, 0x44, 0x65, 0xb0, 0x55, 0xc9, 0x6a, 0x72, 0xe4, + 0x10, 0x52, 0x24, 0x18, 0x23, 0x25, 0xd8, 0x30, 0x41, 0x4b, 0x40, 0x21, 0x4d, 0xaa, 0x80, 0x91, 0xd2, 0xe0, 0xfb, + 0x01, 0x0a, 0xe1, 0x5c, 0x6d, 0xe9, 0x08, 0x50, 0x97, 0x3b, 0xdf, 0x1e, 0x42, 0x3b, 0xe1, 0x48, 0xa2, 0x37, 0xb8, + 0x7a, 0x0c, 0x9f, 0x34, 0xd4, 0xb4, 0x76, 0x05, 0xb8, 0x03, 0xd7, 0x43, 0xa8, 0x6a, 0x90, 0x39, 0x9a, 0x4a, 0xf3, + 0x96, 0xd3, 0xa1, 0x20, 0x0a, 0x62, 0xf3, 0xd9, 0x50, 0x79, 0x62, 0xe8, 0xe5, 0xbe, 0xe6, 0xd3, 0xda, 0x2b, 0xb3, + 0xf7, 0x23, 0x76, 0x64, 0xac, 0x7a, 0x29, 0x28, 0x23, 0x90, 0x0b, 0xc6, 0x35, 0x03, 0xb2, 0x9e, 0x80, 0xd6, 0x3f, + 0x60, 0x67, 0xbf, 0x8e, 0x17, 0x16, 0xac, 0x25, 0xbe, 0xba, 0x35, 0x0d, 0xeb, 0x62, 0xa9, 0x9f, 0xe0, 0x31, 0x85, + 0xeb, 0x4f, 0x69, 0x93, 0x7e, 0xcd, 0x38, 0x79, 0x41, 0xfd, 0xa5, 0x44, 0xba, 0x67, 0xdb, 0x09, 0x11, 0x77, 0x49, + 0x38, 0xb0, 0x18, 0x27, 0xbc, 0xc6, 0x9c, 0x92, 0xb3, 0xf7, 0x72, 0xa9, 0xd2, 0x85, 0x9e, 0xf0, 0x03, 0x39, 0x8b, + 0x1f, 0x6b, 0xba, 0xd7, 0xb5, 0x74, 0xf7, 0x98, 0x9a, 0x1d, 0x10, 0xb2, 0xdf, 0x79, 0x8e, 0x0d, 0xbf, 0x30, 0xd6, + 0x58, 0x74, 0x64, 0xd2, 0x48, 0x78, 0xcd, 0x00, 0xc0, 0xea, 0xee, 0x8a, 0x1a, 0x0c, 0xc7, 0x53, 0xa2, 0x79, 0x79, + 0xe1, 0x1b, 0x41, 0xdb, 0x1d, 0xe3, 0xd5, 0x03, 0x8a, 0xfa, 0xf4, 0x9f, 0x5c, 0x68, 0x2c, 0x37, 0x48, 0xd8, 0xa3, + 0xa9, 0xec, 0x54, 0xe6, 0xa3, 0x71, 0x27, 0x5f, 0x16, 0x83, 0x51, 0x0f, 0x8e, 0x4f, 0x90, 0x93, 0x8f, 0x9a, 0xb6, + 0xe1, 0x34, 0xc2, 0xcf, 0xdf, 0x48, 0x41, 0xcb, 0xa8, 0x8e, 0x0c, 0xff, 0x2b, 0x0b, 0xcc, 0x8e, 0x6a, 0xdc, 0xb7, + 0x11, 0x09, 0xb5, 0x19, 0x8f, 0xec, 0xf1, 0xbb, 0x7e, 0x5c, 0x53, 0x1a, 0xca, 0x50, 0xa5, 0x6a, 0x8a, 0x3b, 0x6d, + 0xe5, 0x98, 0x62, 0xd4, 0x1f, 0xa1, 0x13, 0xd9, 0xcd, 0x95, 0x78, 0x08, 0xf0, 0x85, 0x71, 0xd9, 0xa4, 0xbb, 0x79, + 0x2a, 0xf2, 0x71, 0xf6, 0xcc, 0x6d, 0xbb, 0x8d, 0xc7, 0xec, 0x36, 0xe3, 0x6b, 0xe1, 0xed, 0x30, 0x81, 0x64, 0xc3, + 0x1c, 0x7c, 0x0a, 0xfc, 0x54, 0x1c, 0x00, 0x00, 0x00}; + + uint8_t expected_mac[] = {0x0c, 0xa1, 0x27, 0x92}; + + uint8_t mac[4]; + + // gen mac + liblte_security_128_eia3(key, count, bearer, direction, msg, len_bits, mac); + int i; + + bool failed = false; + for (i = 0; i < 4; i++) { + if (mac[i] != expected_mac[i]) { + failed = true; + } + assert(mac[i] == expected_mac[i]); + } + if (failed == true) { + printf("Test Set 5: Failed\n"); + } else { + printf("Test Set 5: Success\n"); + } +} + +int main(int argc, char* argv[]) +{ + test_set_1(); + test_set_2(); + test_set_3(); + test_set_4(); + test_set_5(); +} \ No newline at end of file diff --git a/lib/test/phy/phy_dl_test.c b/lib/test/phy/phy_dl_test.c index 112f43e10..0da304c5e 100644 --- a/lib/test/phy/phy_dl_test.c +++ b/lib/test/phy/phy_dl_test.c @@ -593,8 +593,8 @@ int main(int argc, char **argv) { ue_dl_cfg.chest_cfg.cfo_estimate_enable = false; ue_dl_cfg.chest_cfg.cfo_estimate_sf_mask = false; ue_dl_cfg.chest_cfg.sync_error_enable = false; - ue_dl_cfg.dci_cfg = dci_cfg; - ue_dl_cfg.pdsch_use_tbs_index_alt = enable_256qam; + ue_dl_cfg.cfg.dci = dci_cfg; + ue_dl_cfg.cfg.pdsch.use_tbs_index_alt = enable_256qam; srslte_pdsch_res_t pdsch_res[SRSLTE_MAX_CODEWORDS]; for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { diff --git a/lib/test/upper/CMakeLists.txt b/lib/test/upper/CMakeLists.txt index 43e77ce01..797b963a5 100644 --- a/lib/test/upper/CMakeLists.txt +++ b/lib/test/upper/CMakeLists.txt @@ -51,6 +51,18 @@ add_executable(rlc_common_test rlc_common_test.cc) target_link_libraries(rlc_common_test srslte_upper srslte_phy) add_test(rlc_common_test rlc_common_test) +add_executable(rlc_um_nr_pdu_test rlc_um_nr_pdu_test.cc) +target_link_libraries(rlc_um_nr_pdu_test srslte_upper srslte_phy) +add_test(rlc_um_nr_pdu_test rlc_um_nr_pdu_test) + +add_executable(rlc_um_nr_test rlc_um_nr_test.cc) +target_link_libraries(rlc_um_nr_test srslte_upper srslte_phy) +add_test(rlc_um_nr_test rlc_um_nr_test) + +add_executable(pdcp_nr_test pdcp_nr_test.cc) +target_link_libraries(pdcp_nr_test srslte_upper srslte_common) +add_test(pdcp_nr_test pdcp_nr_test) + ######################################################################## # Option to run command after build (useful for remote builds) ######################################################################## diff --git a/lib/test/upper/pdcp_nr_test.cc b/lib/test/upper/pdcp_nr_test.cc new file mode 100644 index 000000000..6db148604 --- /dev/null +++ b/lib/test/upper/pdcp_nr_test.cc @@ -0,0 +1,338 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/common/buffer_pool.h" +#include "srslte/common/log_filter.h" +#include "srslte/common/security.h" +#include "srslte/upper/pdcp_entity_nr.h" +#include + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ + return -1; \ + } \ + } + +// Encryption and Integrity Keys +uint8_t k_int[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31}; +uint8_t k_enc[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31}; + +// Test SDUs for tx +uint8_t sdu1[] = {0x18, 0xE2}; +uint32_t SDU1_LEN = 2; + +// Test PDUs for rx +uint8_t pdu1[] = {0x80, 0x00, 0x8f, 0xe3, 0xe0, 0xdf, 0x82, 0x92}; +uint32_t PDU1_LEN = 8; + +uint8_t pdu2[] = {0x88, 0x00, 0x8d, 0x2c, 0x47, 0x5e, 0xb1, 0x5b}; +uint32_t PDU2_LEN = 8; + +uint8_t pdu3[] = {0x80, 0x00, 0x97, 0xbe, 0xa3, 0x32, 0xfa, 0x61}; +uint32_t PDU3_LEN = 8; + +uint8_t pdu4[] = {0x80, 0x00, 0x00, 0x8f, 0xe3, 0xe0, 0xdf, 0x82, 0x92}; +uint32_t PDU4_LEN = 9; + +uint8_t pdu5[] = {0x82, 0x00, 0x00, 0x15, 0x01, 0xf4, 0xb0, 0xfc, 0xc5}; +uint32_t PDU5_LEN = 9; + +uint8_t pdu6[] = {0x80, 0x00, 0x00, 0xc2, 0x47, 0xa8, 0xdd, 0xc0, 0x73}; +uint32_t PDU6_LEN = 9; + +// dummy classes +class rlc_dummy : public srsue::rlc_interface_pdcp +{ +public: + rlc_dummy(srslte::log* log_) : log(log_) {} + + void get_last_sdu(const srslte::unique_byte_buffer_t& pdu) + { + memcpy(pdu->msg, last_pdcp_pdu->msg, last_pdcp_pdu->N_bytes); + pdu->N_bytes = last_pdcp_pdu->N_bytes; + return; + } + void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true) + { + log->info_hex(sdu->msg, sdu->N_bytes, "RLC SDU"); + last_pdcp_pdu.swap(sdu); + } + +private: + srslte::log* log; + srslte::unique_byte_buffer_t last_pdcp_pdu; + + bool rb_is_um(uint32_t lcid) { return false; } +}; + +class rrc_dummy : public srsue::rrc_interface_pdcp +{ +public: + rrc_dummy(srslte::log* log_) : log(log_) {} + + void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} + void write_pdu_bcch_bch(srslte::unique_byte_buffer_t pdu) {} + void write_pdu_bcch_dlsch(srslte::unique_byte_buffer_t pdu) {} + void write_pdu_pcch(srslte::unique_byte_buffer_t pdu) {} + void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} + + std::string get_rb_name(uint32_t lcid) { return "None"; } + +private: + srslte::log* log; +}; + +class gw_dummy : public srsue::gw_interface_pdcp +{ +public: + gw_dummy(srslte::log* log_) : log(log_) {} + + void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} + uint32_t rx_count = 0; + + void get_last_pdu(const srslte::unique_byte_buffer_t& pdu) + { + memcpy(pdu->msg, last_pdu->msg, last_pdu->N_bytes); + pdu->N_bytes = last_pdu->N_bytes; + return; + } + void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) + { + log->info_hex(pdu->msg, pdu->N_bytes, "GW PDU"); + rx_count++; + last_pdu.swap(pdu); + } + +private: + srslte::log* log; + srslte::unique_byte_buffer_t last_pdu; +}; + +/* + * Genric function to test transmission of in-sequence packets + */ +int test_tx(uint32_t n_packets, + uint8_t pdcp_sn_len, + srslte::unique_byte_buffer_t pdu_exp, + srslte::byte_buffer_pool* pool, + srslte::log* log) +{ + srslte::pdcp_entity_nr pdcp; + srslte::pdcp_config_t cfg = { + 1, srslte::PDCP_RB_IS_DRB, srslte::SECURITY_DIRECTION_UPLINK, srslte::SECURITY_DIRECTION_DOWNLINK, pdcp_sn_len}; + + rlc_dummy rlc(log); + rrc_dummy rrc(log); + gw_dummy gw(log); + + pdcp.init(&rlc, &rrc, &gw, log, 0, cfg); + pdcp.config_security( + k_enc, k_int, k_enc, k_int, srslte::CIPHERING_ALGORITHM_ID_128_EEA2, srslte::INTEGRITY_ALGORITHM_ID_128_EIA2); + pdcp.enable_integrity(); + pdcp.enable_encryption(); + + // Test SDU + srslte::unique_byte_buffer_t sdu = allocate_unique_buffer(*pool); + memcpy(sdu->msg, sdu1, SDU1_LEN); + sdu->N_bytes = SDU1_LEN; + + // Run test + for (uint32_t i = 0; i < n_packets; ++i) { + // Test SDU + srslte::unique_byte_buffer_t sdu = allocate_unique_buffer(*pool); + memcpy(sdu->msg, sdu1, SDU1_LEN); + sdu->N_bytes = SDU1_LEN; + pdcp.write_sdu(std::move(sdu), true); + } + srslte::unique_byte_buffer_t pdu_act = allocate_unique_buffer(*pool); + rlc.get_last_sdu(pdu_act); + + TESTASSERT(pdu_act->N_bytes == pdu_exp->N_bytes); + for (uint32_t i = 0; i < pdu_exp->N_bytes; ++i) { + TESTASSERT(pdu_act->msg[i] == pdu_exp->msg[i]); + } + return 0; +} + +/* + * TX Test: PDCP Entity with SN LEN = 12 and 18. Tested COUNT = 0, 2048 and 4096 + * PDCP entity configured with EIA2 and EEA2 + */ +int test_tx_all(srslte::byte_buffer_pool* pool, srslte::log* log) +{ + /* + * TX Test 1: PDCP Entity with SN LEN = 12 + * PDCP entity configured with EIA2 and EEA2 + * TX_NEXT = 0. + * Input: {0x18, 0xE2} + * Output: PDCP Header {0x80, 0x00}, Ciphered Text {0x8f, 0xe3}, MAC-I {0xe0, 0xdf, 0x82, 0x92} + */ + srslte::unique_byte_buffer_t pdu_exp_sn0_len12 = allocate_unique_buffer(*pool); + memcpy(pdu_exp_sn0_len12->msg, pdu1, PDU1_LEN); + pdu_exp_sn0_len12->N_bytes = PDU1_LEN; + TESTASSERT(test_tx(1, srslte::PDCP_SN_LEN_12, std::move(pdu_exp_sn0_len12), pool, log) == 0); + + /* + * TX Test 2: PDCP Entity with SN LEN = 12 + * PDCP entity configured with EIA2 and EEA2 + * TX_NEXT = 2048. + * Input: {0x18, 0xE2} + * Output: PDCP Header {0x88, 0x00}, Ciphered Text {0x8d, 0x2c}, MAC-I {0x47, 0x5e, 0xb1, 0x5b} + */ + srslte::unique_byte_buffer_t pdu_exp_sn2048_len12 = allocate_unique_buffer(*pool); + memcpy(pdu_exp_sn2048_len12->msg, pdu2, PDU2_LEN); + pdu_exp_sn2048_len12->N_bytes = PDU2_LEN; + TESTASSERT(test_tx(2049, srslte::PDCP_SN_LEN_12, std::move(pdu_exp_sn2048_len12), pool, log) == 0); + + /* + * TX Test 3: PDCP Entity with SN LEN = 12 + * PDCP entity configured with EIA2 and EEA2 + * TX_NEXT = 4096. + * Input: {0x18, 0xE2} + * Output: PDCP Header {0x80,0x00}, Ciphered Text {0x97, 0xbe}, MAC-I {0xa3, 0x32, 0xfa, 0x61} + */ + srslte::unique_byte_buffer_t pdu_exp_sn4096_len12 = allocate_unique_buffer(*pool); + memcpy(pdu_exp_sn4096_len12->msg, pdu3, PDU3_LEN); + pdu_exp_sn4096_len12->N_bytes = PDU3_LEN; + TESTASSERT(test_tx(4097, srslte::PDCP_SN_LEN_12, std::move(pdu_exp_sn4096_len12), pool, log) == 0); + + /* + * TX Test 4: PDCP Entity with SN LEN = 18 + * PDCP entity configured with EIA2 and EEA2 + * TX_NEXT = 0. + * Input: {0x18, 0xE2} + * Output: PDCP Header {0x80, 0x80, 0x00}, Ciphered Text {0x8f, 0xe3}, MAC-I {0xe0, 0xdf, 0x82, 0x92} + */ + srslte::unique_byte_buffer_t pdu_exp_sn0_len18 = allocate_unique_buffer(*pool); + memcpy(pdu_exp_sn0_len18->msg, pdu4, PDU4_LEN); + pdu_exp_sn0_len18->N_bytes = PDU4_LEN; + TESTASSERT(test_tx(1, srslte::PDCP_SN_LEN_18, std::move(pdu_exp_sn0_len18), pool, log) == 0); + + /* + * TX Test 5: PDCP Entity with SN LEN = 18 + * PDCP entity configured with EIA2 and EEA2 + * TX_NEXT = 131072. + * Input: {0x18, 0xE2} + * Output: PDCP Header {0x82, 0x00, 0x00}, Ciphered Text {0x15, 0x01}, MAC-I {0xf4, 0xb0, 0xfc, 0xc5} + */ + srslte::unique_byte_buffer_t pdu_exp_sn131072_len18 = allocate_unique_buffer(*pool); + memcpy(pdu_exp_sn131072_len18->msg, pdu5, PDU5_LEN); + pdu_exp_sn131072_len18->N_bytes = PDU5_LEN; + TESTASSERT(test_tx(131073, srslte::PDCP_SN_LEN_18, std::move(pdu_exp_sn131072_len18), pool, log) == 0); + + /* + * TX Test 6: PDCP Entity with SN LEN = 18 + * PDCP entity configured with EIA2 and EEA2 + * TX_NEXT = 262144. + * Input: {0x18, 0xE2} + * Output: PDCP Header {0x80, 0x00, 0x00}, Ciphered Text {0xc2, 0x47}, MAC-I {0xa8, 0xdd, 0xc0, 0x73} + */ + srslte::unique_byte_buffer_t pdu_exp_sn262144_len18 = allocate_unique_buffer(*pool); + memcpy(pdu_exp_sn262144_len18->msg, pdu6, PDU6_LEN); + pdu_exp_sn262144_len18->N_bytes = PDU6_LEN; + TESTASSERT(test_tx(262145, srslte::PDCP_SN_LEN_18, std::move(pdu_exp_sn262144_len18), pool, log) == 0); + return 0; +} + +/* + * RX Test: PDCP Entity with SN LEN = 12 and 18. Tested 4097 packets received without losses. + * PDCP entity configured with EIA2 and EEA2 + */ +int test_rx_in_sequence(uint64_t n_packets, uint8_t pdcp_sn_len, srslte::byte_buffer_pool* pool, srslte::log* log) +{ + srslte::pdcp_entity_nr pdcp_tx; + srslte::pdcp_entity_nr pdcp_rx; + srslte::pdcp_config_t cfg_tx = { + 1, srslte::PDCP_RB_IS_DRB, srslte::SECURITY_DIRECTION_UPLINK, srslte::SECURITY_DIRECTION_DOWNLINK, pdcp_sn_len}; + srslte::pdcp_config_t cfg_rx = { + 1, srslte::PDCP_RB_IS_DRB, srslte::SECURITY_DIRECTION_DOWNLINK, srslte::SECURITY_DIRECTION_UPLINK, pdcp_sn_len}; + + rlc_dummy rlc_tx(log); + rrc_dummy rrc_tx(log); + gw_dummy gw_tx(log); + + rlc_dummy rlc_rx(log); + rrc_dummy rrc_rx(log); + gw_dummy gw_rx(log); + + pdcp_tx.init(&rlc_tx, &rrc_tx, &gw_tx, log, 0, cfg_tx); + pdcp_tx.config_security( + k_enc, k_int, k_enc, k_int, srslte::CIPHERING_ALGORITHM_ID_128_EEA2, srslte::INTEGRITY_ALGORITHM_ID_128_EIA2); + pdcp_tx.enable_integrity(); + pdcp_tx.enable_encryption(); + + pdcp_rx.init(&rlc_rx, &rrc_rx, &gw_rx, log, 0, cfg_rx); + pdcp_rx.config_security( + k_enc, k_int, k_enc, k_int, srslte::CIPHERING_ALGORITHM_ID_128_EEA2, srslte::INTEGRITY_ALGORITHM_ID_128_EIA2); + pdcp_rx.enable_integrity(); + pdcp_rx.enable_encryption(); + + srslte::unique_byte_buffer_t sdu_act = allocate_unique_buffer(*pool); + srslte::unique_byte_buffer_t sdu_exp = allocate_unique_buffer(*pool); + memcpy(sdu_exp->msg, sdu1, SDU1_LEN); + sdu_exp->N_bytes = SDU1_LEN; + + // Generate test message and + // decript and check matching SDUs + for (uint64_t i = 0; i < n_packets; ++i) { + srslte::unique_byte_buffer_t sdu = allocate_unique_buffer(*pool); + srslte::unique_byte_buffer_t pdu = allocate_unique_buffer(*pool); + memcpy(sdu->msg, sdu_exp->msg, SDU1_LEN); + sdu->N_bytes = SDU1_LEN; + + // Generate encripted and integrity protected PDU + pdcp_tx.write_sdu(std::move(sdu), true); + rlc_tx.get_last_sdu(pdu); + pdcp_rx.write_pdu(std::move(pdu)); + gw_rx.get_last_pdu(sdu_act); + + TESTASSERT(sdu_exp->N_bytes == sdu_act->N_bytes); + for (uint32_t j = 0; j < sdu_act->N_bytes; ++j) { + TESTASSERT(sdu_exp->msg[j] == sdu_act->msg[j]); + } + } + return 0; +} + +// Setup all tests +int run_all_tests(srslte::byte_buffer_pool* pool) +{ + // Setup log + srslte::log_filter log("PDCP NR Test"); + log.set_level(srslte::LOG_LEVEL_DEBUG); + log.set_hex_limit(128); + + TESTASSERT(test_tx_all(pool, &log) == 0); + TESTASSERT(test_rx_in_sequence(4097, srslte::PDCP_SN_LEN_12, pool, &log) == 0); + // TESTASSERT(test_rx_in_sequence(4294967297, srslte::PDCP_SN_LEN_12, pool, &log) == 0); + TESTASSERT(test_rx_in_sequence(262145, srslte::PDCP_SN_LEN_18, pool, &log) == 0); + return 0; +} + +int main(int argc, char** argv) +{ + run_all_tests(srslte::byte_buffer_pool::get_instance()); + srslte::byte_buffer_pool::cleanup(); +} diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index ea4ec4c09..90a619ec1 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -34,30 +34,7 @@ using namespace srsue; using namespace srslte; using namespace asn1::rrc; -class mac_dummy_timers - :public srslte::mac_interface_timers -{ -public: - mac_dummy_timers() : timers(8) {} - srslte::timers::timer* timer_get(uint32_t timer_id) { - return timers.get(timer_id); - } - void timer_release_id(uint32_t timer_id) { - timers.release_id(timer_id); - } - uint32_t timer_get_unique_id() { - return timers.get_unique_id(); - } - void step_all() { - timers.step_all(); - } -private: - srslte::timers timers; -}; - -class rlc_am_tester - :public pdcp_interface_rlc - ,public rrc_interface_rlc +class rlc_am_tester : public pdcp_interface_rlc, public rrc_interface_rlc { public: rlc_am_tester(rlc_pcap *pcap_ = NULL) @@ -162,9 +139,9 @@ bool basic_test() log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - byte_buffer_t pdu_bufs[NBUFS]; + rlc_am_tester tester; + timers timers(8); + byte_buffer_t pdu_bufs[NBUFS]; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -222,8 +199,8 @@ bool concat_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; + rlc_am_tester tester; + srslte::timers timers(8); rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -287,9 +264,9 @@ bool segment_test(bool in_seq_rx) log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + srslte::timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -381,9 +358,9 @@ bool retx_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -475,9 +452,9 @@ bool resegment_test_1() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -581,9 +558,9 @@ bool resegment_test_2() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -684,8 +661,8 @@ bool resegment_test_3() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; + rlc_am_tester tester; + srslte::timers timers(8); rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -781,8 +758,8 @@ bool resegment_test_4() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; + rlc_am_tester tester; + srslte::timers timers(8); rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -880,8 +857,8 @@ bool resegment_test_5() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; + rlc_am_tester tester; + srslte::timers timers(8); rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -979,9 +956,9 @@ bool resegment_test_6() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + srslte::timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -1115,9 +1092,9 @@ bool resegment_test_7() pcap.open("rlc_am_test7.pcap", 0); rlc_am_tester tester(&pcap); #else - rlc_am_tester tester(NULL); + rlc_am_tester tester(NULL); #endif - mac_dummy_timers timers; + srslte::timers timers(8); rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -1288,9 +1265,9 @@ bool resegment_test_8() pcap.open("rlc_am_test8.pcap", 0); rlc_am_tester tester(&pcap); #else - rlc_am_tester tester(NULL); + rlc_am_tester tester(NULL); #endif - mac_dummy_timers timers; + srslte::timers timers(8); rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -1433,9 +1410,9 @@ bool reset_test() srslte::log_filter log1("RLC_AM_1"); log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + srslte::timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); @@ -1478,9 +1455,9 @@ bool resume_test() srslte::log_filter log1("RLC_AM_1"); log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + srslte::timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); @@ -1523,8 +1500,8 @@ bool stop_test() srslte::log_filter log1("RLC_AM_1"); log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; + rlc_am_tester tester; + srslte::timers timers(8); rlc_am rlc1(&log1, 1, &tester, &tester, &timers); @@ -1555,9 +1532,9 @@ bool status_pdu_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_am_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_am_tester tester; + srslte::timers timers(8); + int len = 0; rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers); @@ -1609,11 +1586,18 @@ bool status_pdu_test() // Read status PDU from RLC2 byte_buffer_t status_buf; - len = rlc2.read_pdu(status_buf.msg, 3); // provide only small grant + len = rlc2.read_pdu(status_buf.msg, 5); // provide only small grant status_buf.N_bytes = len; assert(status_buf.N_bytes != 0); + // check status PDU doesn't contain ACK_SN in NACK list + rlc_status_pdu_t status_pdu = {}; + rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_pdu); + if (rlc_am_is_valid_status_pdu(status_pdu) == false) { + return -1; + } + // Write status PDU to RLC1 rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); diff --git a/lib/test/upper/rlc_common_test.cc b/lib/test/upper/rlc_common_test.cc index d6cbc5fd1..781ca06db 100644 --- a/lib/test/upper/rlc_common_test.cc +++ b/lib/test/upper/rlc_common_test.cc @@ -35,22 +35,9 @@ #define NBUFS 5 using namespace srslte; -using namespace srsue; using namespace asn1::rrc; -class mac_dummy_timers : public srslte::mac_interface_timers -{ -public: - srslte::timers::timer* timer_get(uint32_t timer_id) { return &t; } - uint32_t timer_get_unique_id() { return 0; } - void step() { t.step(); } - void timer_release_id(uint32_t timer_id) {} - -private: - srslte::timers::timer t; -}; - -class rlc_tester : public pdcp_interface_rlc, public rrc_interface_rlc +class rlc_tester : public srsue::pdcp_interface_rlc, public srsue::rrc_interface_rlc { public: rlc_tester() @@ -92,8 +79,8 @@ int basic_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_tester tester; - mac_dummy_timers timers; + rlc_tester tester; + srslte::timers timers(1); int len = 0; diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index 0a2526408..7caf6f586 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -111,21 +111,6 @@ void parse_args(stress_test_args_t *args, int argc, char *argv[]) { } } -// To provide timer services to RLC -class stack_dummy : public srslte::mac_interface_timers -{ -public: - stack_dummy() : timers(8) {} - - srslte::timers::timer* timer_get(uint32_t timer_id) { return timers.get(timer_id); } - uint32_t timer_get_unique_id() { return timers.get_unique_id(); } - void timer_release_id(uint32_t timer_id) { timers.release_id(timer_id); } - void step_timer() { timers.step_all(); } - -private: - srslte::timers timers; -}; - class mac_dummy : public thread { public: @@ -133,7 +118,7 @@ public: rlc_interface_mac* rlc2_, stress_test_args_t args_, uint32_t lcid_, - stack_dummy* stack_, + timers* timers_, rlc_pcap* pcap_ = NULL) : run_enable(true), rlc1(rlc1_), @@ -141,7 +126,7 @@ public: args(args_), pcap(pcap_), lcid(lcid_), - stack(stack_), + timers(timers_), log("MAC "), thread("MAC_DUMMY"), real_dist(0.0, 1.0) @@ -207,7 +192,7 @@ private: run_tti(rlc2, rlc1, false); // step timer - stack->step_timer(); + timers->step_all(); } } @@ -216,10 +201,10 @@ private: bool run_enable; stress_test_args_t args; - rlc_pcap *pcap; - uint32_t lcid; + rlc_pcap* pcap; + uint32_t lcid; srslte::log_filter log; - stack_dummy* stack = nullptr; + srslte::timers* timers = nullptr; std::mt19937 mt19937; std::uniform_real_distribution real_dist; @@ -354,17 +339,17 @@ void stress_test(stress_test_args_t args) exit(-1); } - stack_dummy stack; + srslte::timers timers(8); rlc rlc1(&log1); rlc rlc2(&log2); rlc_tester tester1(&rlc1, "tester1", args, lcid); rlc_tester tester2(&rlc2, "tester2", args, lcid); - mac_dummy mac(&rlc1, &rlc2, args, lcid, &stack, &pcap); + mac_dummy mac(&rlc1, &rlc2, args, lcid, &timers, &pcap); - rlc1.init(&tester1, &tester1, &stack, 0); - rlc2.init(&tester2, &tester2, &stack, 0); + rlc1.init(&tester1, &tester1, &timers, 0); + rlc2.init(&tester2, &tester2, &timers, 0); // only add AM and UM bearers if (args.mode != "TM") { diff --git a/lib/test/upper/rlc_test_common.h b/lib/test/upper/rlc_test_common.h new file mode 100644 index 000000000..92ae0e9b6 --- /dev/null +++ b/lib/test/upper/rlc_test_common.h @@ -0,0 +1,63 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSLTE_RLC_TEST_COMMON_H +#define SRSLTE_RLC_TEST_COMMON_H + +#include "srslte/interfaces/ue_interfaces.h" +#include + +namespace srslte { + +class rlc_um_tester : public srsue::pdcp_interface_rlc, public srsue::rrc_interface_rlc +{ +public: + rlc_um_tester() {} + + // PDCP interface + void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu) + { + if (lcid != 3 && sdu->N_bytes != expected_sdu_len) { + printf("Received PDU with size %d, expected %d. Exiting.\n", sdu->N_bytes, expected_sdu_len); + exit(-1); + } + sdus.push_back(std::move(sdu)); + } + void write_pdu_bcch_bch(unique_byte_buffer_t sdu) {} + void write_pdu_bcch_dlsch(unique_byte_buffer_t sdu) {} + void write_pdu_pcch(unique_byte_buffer_t sdu) {} + void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) { sdus.push_back(std::move(sdu)); } + + // RRC interface + void max_retx_attempted() {} + std::string get_rb_name(uint32_t lcid) { return std::string(""); } + void set_expected_sdu_len(uint32_t len) { expected_sdu_len = len; } + + uint32_t get_num_sdus() { return sdus.size(); } + + // TODO: this should be private + std::vector sdus; + uint32_t expected_sdu_len = 0; +}; + +} // namespace srslte + +#endif // SRSLTE_RLC_TEST_COMMON_H diff --git a/lib/test/upper/rlc_um_data_test.cc b/lib/test/upper/rlc_um_data_test.cc index 8ee7f7604..f70dacefe 100644 --- a/lib/test/upper/rlc_um_data_test.cc +++ b/lib/test/upper/rlc_um_data_test.cc @@ -31,8 +31,6 @@ uint32_t PDU1_LEN = 2; uint8_t pdu2[] = {0x1C ,0xE1 ,0x06 ,0x80}; uint32_t PDU2_LEN = 4; -using namespace srsue; - int main(int argc, char **argv) { srslte::rlc_umd_pdu_header_t h; srslte::byte_buffer_t b1,b2; diff --git a/lib/test/upper/rlc_um_nr_pdu_test.cc b/lib/test/upper/rlc_um_nr_pdu_test.cc new file mode 100644 index 000000000..7efe0d990 --- /dev/null +++ b/lib/test/upper/rlc_um_nr_pdu_test.cc @@ -0,0 +1,240 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/config.h" +#include "srslte/upper/rlc.h" +#include "srslte/upper/rlc_um.h" + +#include +#include +#include +#include + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ + return -1; \ + } \ + } + +#define PCAP 0 +#define PCAP_CRNTI (0x1001) +#define PCAP_TTI (666) + +using namespace srslte; + +#if PCAP +#include "srslte/common/mac_nr_pcap.h" +#include "srslte/common/mac_nr_pdu.h" +static std::unique_ptr pcap_handle = nullptr; +#endif + +int write_pdu_to_pcap(const uint32_t lcid, const uint8_t* payload, const uint32_t len) +{ +#if PCAP + if (pcap_handle) { + byte_buffer_t tx_buffer; + srslte::mac_nr_pdu tx_pdu; + tx_pdu.init_tx(&tx_buffer, len + 10); + tx_pdu.add_sdu(lcid, payload, len); + tx_pdu.pack(); + pcap_handle->write_dl_crnti(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI); + return SRSLTE_SUCCESS; + } +#endif + return SRSLTE_ERROR; +} + +template +srslte::byte_buffer_t make_pdu_and_log(const std::array& tv) +{ + srslte::byte_buffer_t pdu; + memcpy(pdu.msg, tv.data(), tv.size()); + pdu.N_bytes = tv.size(); + write_pdu_to_pcap(4, tv.data(), tv.size()); + return pdu; +} + +void corrupt_pdu_header(srslte::byte_buffer_t& pdu, const uint32_t header_len, const uint32_t payload_len) +{ + // clear header only + for (uint32_t i = 0; i < header_len; i++) { + pdu.msg[i] = 0xaa; + } + pdu.msg += header_len; + pdu.N_bytes = payload_len; +} + +// RLC UM PDU with complete SDU +int rlc_um_nr_pdu_test1() +{ + const int header_len = 1, payload_len = 4; + std::array tv = {0x00, 0x11, 0x22, 0x33, 0x44}; + srslte::byte_buffer_t pdu = make_pdu_and_log(tv); + + // unpack PDU + rlc_um_nr_pdu_header_t header = {}; + TESTASSERT(rlc_um_nr_read_data_pdu_header(&pdu, srslte::rlc_um_nr_sn_size_t::size6bits, &header) != 0); + TESTASSERT(header.si == rlc_nr_si_field_t::full_sdu); + + // clear header + corrupt_pdu_header(pdu, header_len, payload_len); + + // pack again + TESTASSERT(rlc_um_nr_write_data_pdu_header(header, &pdu) == header_len); + TESTASSERT(pdu.N_bytes == tv.size()); + TESTASSERT(memcmp(pdu.msg, tv.data(), pdu.N_bytes) == 0); + + return SRSLTE_SUCCESS; +} + +// RLC UM PDU with 6 Bit SN carrying the last segment of an SDU +int rlc_um_nr_pdu_test2() +{ + // SN = 1 + const int header_len = 3, payload_len = 4; + const std::array tv = {0x81, 0x01, 0x02, 0x11, 0x22, 0x33, 0x44}; + srslte::byte_buffer_t pdu = make_pdu_and_log(tv); + + // unpack PDU + rlc_um_nr_pdu_header_t header = {}; + TESTASSERT(rlc_um_nr_read_data_pdu_header(&pdu, srslte::rlc_um_nr_sn_size_t::size6bits, &header) != 0); + + TESTASSERT(header.si == rlc_nr_si_field_t::last_segment); + TESTASSERT(header.sn == 1); + TESTASSERT(header.so == 258); + TESTASSERT(header.sn_size == srslte::rlc_um_nr_sn_size_t::size6bits); + + // clear header + corrupt_pdu_header(pdu, header_len, payload_len); + + // pack again + TESTASSERT(rlc_um_nr_write_data_pdu_header(header, &pdu) == header_len); + TESTASSERT(pdu.N_bytes == tv.size()); + TESTASSERT(memcmp(pdu.msg, tv.data(), pdu.N_bytes) == 0); + + return SRSLTE_SUCCESS; +} + +// RLC UM PDU with 6 Bit SN carrying a middle segment of an SDU +int rlc_um_nr_pdu_test3() +{ + // SN = 3 + const int header_len = 3, payload_len = 4; + const std::array tv = {0xc3, 0x01, 0x02, 0x11, 0x22, 0x33, 0x44}; + srslte::byte_buffer_t pdu = make_pdu_and_log(tv); + + // unpack PDU + rlc_um_nr_pdu_header_t header = {}; + TESTASSERT(rlc_um_nr_read_data_pdu_header(&pdu, srslte::rlc_um_nr_sn_size_t::size6bits, &header) != 0); + + TESTASSERT(header.si == rlc_nr_si_field_t::neither_first_nor_last_segment); + TESTASSERT(header.so == 258); + TESTASSERT(header.sn == 3); + TESTASSERT(header.sn_size == srslte::rlc_um_nr_sn_size_t::size6bits); + + // clear header + corrupt_pdu_header(pdu, header_len, payload_len); + + // pack again + TESTASSERT(rlc_um_nr_write_data_pdu_header(header, &pdu) == header_len); + TESTASSERT(pdu.N_bytes == tv.size()); + TESTASSERT(memcmp(pdu.msg, tv.data(), pdu.N_bytes) == 0); + + return SRSLTE_SUCCESS; +} + +// RLC UM PDU with 6 Bit SN carrying a first segment of an SDU +int rlc_um_nr_pdu_test4() +{ + // SN = 31 + const int header_len = 1, payload_len = 4; + std::array tv = {0x5f, 0x11, 0x22, 0x33, 0x44}; + srslte::byte_buffer_t pdu = make_pdu_and_log(tv); + + // unpack PDU + rlc_um_nr_pdu_header_t header = {}; + TESTASSERT(rlc_um_nr_read_data_pdu_header(&pdu, srslte::rlc_um_nr_sn_size_t::size6bits, &header) != 0); + + TESTASSERT(header.si == rlc_nr_si_field_t::first_segment); + TESTASSERT(header.so == 0); + TESTASSERT(header.sn == 31); + TESTASSERT(header.sn_size == srslte::rlc_um_nr_sn_size_t::size6bits); + + // clear header + corrupt_pdu_header(pdu, header_len, payload_len); + + // pack again + TESTASSERT(rlc_um_nr_write_data_pdu_header(header, &pdu) == header_len); + TESTASSERT(pdu.N_bytes == tv.size()); + TESTASSERT(memcmp(pdu.msg, tv.data(), pdu.N_bytes) == 0); + + return SRSLTE_SUCCESS; +} + +// This should fail unpacking because the PDU has reserved bits set +int rlc_um_nr_pdu_unpack_test5() +{ + std::array tv = {0x33, 0x01, 0x02, 0x11, 0x22, 0x33, 0x44}; + srslte::byte_buffer_t pdu = make_pdu_and_log(tv); + + // unpack PDU + rlc_um_nr_pdu_header_t header = {}; + TESTASSERT(rlc_um_nr_read_data_pdu_header(&pdu, srslte::rlc_um_nr_sn_size_t::size6bits, &header) == 0); + + return SRSLTE_SUCCESS; +} + +int main(int argc, char** argv) +{ +#if PCAP + pcap_handle = std::unique_ptr(new srslte::mac_nr_pcap()); + pcap_handle->open("rlc_um_nr_pdu_test.pcap"); +#endif + + if (rlc_um_nr_pdu_test1()) { + fprintf(stderr, "rlc_um_nr_pdu_test1() failed.\n"); + return SRSLTE_ERROR; + } + + if (rlc_um_nr_pdu_test2()) { + fprintf(stderr, "rlc_um_nr_pdu_test2() failed.\n"); + return SRSLTE_ERROR; + } + + if (rlc_um_nr_pdu_test3()) { + fprintf(stderr, "rlc_um_nr_pdu_test3() failed.\n"); + return SRSLTE_ERROR; + } + + if (rlc_um_nr_pdu_test4()) { + fprintf(stderr, "rlc_um_nr_pdu_test4() failed.\n"); + return SRSLTE_ERROR; + } + + if (rlc_um_nr_pdu_unpack_test5()) { + fprintf(stderr, "rlc_um_nr_pdu_unpack_test5() failed.\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; +} diff --git a/lib/test/upper/rlc_um_nr_test.cc b/lib/test/upper/rlc_um_nr_test.cc new file mode 100644 index 000000000..21d6268be --- /dev/null +++ b/lib/test/upper/rlc_um_nr_test.cc @@ -0,0 +1,210 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "rlc_test_common.h" +#include "srslte/common/log_filter.h" +#include "srslte/config.h" +#include "srslte/upper/rlc.h" +#include "srslte/upper/rlc_um.h" + +#include +#include +#include +#include + +#define TESTASSERT(cond) \ + { \ + if (!(cond)) { \ + std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \ + return -1; \ + } \ + } + +#define PCAP 0 +#define PCAP_CRNTI (0x1001) +#define PCAP_TTI (666) + +using namespace srslte; + +#if PCAP +#include "srslte/common/mac_nr_pcap.h" +#include "srslte/common/mac_nr_pdu.h" +static std::unique_ptr pcap_handle = nullptr; +#endif + +int write_pdu_to_pcap(const uint32_t lcid, const uint8_t* payload, const uint32_t len) +{ +#if PCAP + if (pcap_handle) { + byte_buffer_t tx_buffer; + srslte::nr_mac_pdu tx_pdu; + tx_pdu.init_tx(&tx_buffer, len + 10); + tx_pdu.add_sdu(lcid, payload, len); + tx_pdu.pack(); + pcap_handle->write_dl_crnti(tx_buffer.msg, tx_buffer.N_bytes, PCAP_CRNTI, true, PCAP_TTI); + return SRSLTE_SUCCESS; + } +#endif + return SRSLTE_ERROR; +} + +template +srslte::byte_buffer_t make_pdu_and_log(const std::array& tv) +{ + srslte::byte_buffer_t pdu; + memcpy(pdu.msg, tv.data(), tv.size()); + pdu.N_bytes = tv.size(); + write_pdu_to_pcap(4, tv.data(), tv.size()); + return pdu; +} + +// Basic test to write UM PDU with 6 bit SN +int rlc_um_nr_test1() +{ + srslte::log_filter log1("RLC_UM_1"); + srslte::log_filter log2("RLC_UM_2"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log2.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(-1); + log2.set_hex_limit(-1); + rlc_um_tester tester; + srslte::timers timers(16); + const uint32_t num_sdus = 5; + int len = 0; + + rlc_um rlc1(&log1, 3, &tester, &tester, &timers); + rlc_um rlc2(&log2, 3, &tester, &tester, &timers); + + rlc_config_t cnfg = rlc_config_t::default_rlc_um_nr_config(6); + + TESTASSERT(rlc1.configure(cnfg) == true); + TESTASSERT(rlc2.configure(cnfg) == true); + + tester.set_expected_sdu_len(1); + + // Push 5 SDUs into RLC1 + byte_buffer_pool* pool = byte_buffer_pool::get_instance(); + unique_byte_buffer_t sdu_bufs[num_sdus]; + for (uint32_t i = 0; i < num_sdus; i++) { + sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true); + *sdu_bufs[i]->msg = i; // Write the index into the buffer + sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte + rlc1.write_sdu(std::move(sdu_bufs[i])); + } + + TESTASSERT(14 == rlc1.get_buffer_state()); + + // Read 5 PDUs from RLC1 (1 byte each) + unique_byte_buffer_t pdu_bufs[num_sdus]; + for (uint32_t i = 0; i < num_sdus; i++) { + pdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true); + len = rlc1.read_pdu(pdu_bufs[i]->msg, 4); // 3 bytes for header + payload + pdu_bufs[i]->N_bytes = len; + + // write PCAP + write_pdu_to_pcap(4, pdu_bufs[i]->msg, pdu_bufs[i]->N_bytes); + } + + TESTASSERT(0 == rlc1.get_buffer_state()); + + // TODO: add receive test + + return SRSLTE_SUCCESS; +} + +// Basic test for SDU segmentation +int rlc_um_nr_test2() +{ + srslte::log_filter log1("RLC_UM_1"); + srslte::log_filter log2("RLC_UM_2"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log2.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(-1); + log2.set_hex_limit(-1); + rlc_um_tester tester; + srslte::timers timers(16); + const uint32_t num_sdus = 1; + const uint32_t sdu_size = 100; + int len = 0; + + rlc_um rlc1(&log1, 3, &tester, &tester, &timers); + rlc_um rlc2(&log2, 3, &tester, &tester, &timers); + + rlc_config_t cnfg = rlc_config_t::default_rlc_um_nr_config(6); + + TESTASSERT(rlc1.configure(cnfg) == true); + TESTASSERT(rlc2.configure(cnfg) == true); + + tester.set_expected_sdu_len(1); + + // Push SDUs into RLC1 + byte_buffer_pool* pool = byte_buffer_pool::get_instance(); + unique_byte_buffer_t sdu_bufs[num_sdus]; + for (uint32_t i = 0; i < num_sdus; i++) { + sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true); + // Write the index into the buffer + for (uint32_t k = 0; k < sdu_size; ++k) { + sdu_bufs[i]->msg[k] = i; + } + sdu_bufs[i]->N_bytes = sdu_size; + rlc1.write_sdu(std::move(sdu_bufs[i])); + } + + // FIXME: check buffer state calculation + TESTASSERT(103 == rlc1.get_buffer_state()); + + // Read PDUs from RLC1 with grant of 25 Bytes each + const uint32_t max_num_pdus = 10; + unique_byte_buffer_t pdu_bufs[max_num_pdus]; + for (uint32_t i = 0; i < max_num_pdus; i++) { + pdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true); + len = rlc1.read_pdu(pdu_bufs[i]->msg, 25); // 3 bytes for header + payload + pdu_bufs[i]->N_bytes = len; + + // write PCAP + write_pdu_to_pcap(4, pdu_bufs[i]->msg, pdu_bufs[i]->N_bytes); + } + + TESTASSERT(0 == rlc1.get_buffer_state()); + + // TODO: add receive test + + return SRSLTE_SUCCESS; +} + +int main(int argc, char** argv) +{ +#if PCAP + pcap_handle = std::unique_ptr(new srslte::mac_nr_pcap()); + pcap_handle->open("rlc_um_nr_test.pcap"); +#endif + + if (rlc_um_nr_test1()) { + fprintf(stderr, "rlc_um_nr_test1() failed.\n"); + return SRSLTE_ERROR; + } + + if (rlc_um_nr_test2()) { + fprintf(stderr, "rlc_um_nr_test2() failed.\n"); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; +} diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/upper/rlc_um_test.cc index 55d0abc74..babd7e5eb 100644 --- a/lib/test/upper/rlc_um_test.cc +++ b/lib/test/upper/rlc_um_test.cc @@ -19,9 +19,10 @@ * */ -#include +#include "rlc_test_common.h" #include "srslte/common/log_filter.h" #include "srslte/upper/rlc_um.h" +#include #define TESTASSERT(cond) \ { \ @@ -38,63 +39,6 @@ using namespace srslte; using namespace srsue; using namespace asn1::rrc; -class mac_dummy_timers - :public srslte::mac_interface_timers -{ -public: - srslte::timers::timer* timer_get(uint32_t timer_id) - { - return &t; - } - uint32_t timer_get_unique_id(){return 0;} - void step() - { - t.step(); - } - void timer_release_id(uint32_t timer_id) {} -private: - srslte::timers::timer t; -}; - -class rlc_um_tester - :public pdcp_interface_rlc - ,public rrc_interface_rlc -{ -public: - rlc_um_tester(){ - bzero(sdus, sizeof(sdus)); - n_sdus = 0; - expected_sdu_len = 0; - } - - // PDCP interface - void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu) - { - if (lcid != 3 && sdu->N_bytes != expected_sdu_len) { - printf("Received PDU with size %d, expected %d. Exiting.\n", sdu->N_bytes, expected_sdu_len); - exit(-1); - } - sdus[n_sdus++] = std::move(sdu); - } - void write_pdu_bcch_bch(unique_byte_buffer_t sdu) {} - void write_pdu_bcch_dlsch(unique_byte_buffer_t sdu) {} - void write_pdu_pcch(unique_byte_buffer_t sdu) {} - void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) - { - sdus[n_sdus++] = std::move(sdu); - } - - // RRC interface - void max_retx_attempted(){} - std::string get_rb_name(uint32_t lcid) { return std::string(""); } - void set_expected_sdu_len(uint32_t len) { expected_sdu_len = len; } - - unique_byte_buffer_t sdus[MAX_NBUFS]; - int n_sdus; - uint32_t expected_sdu_len; -}; - - int basic_test() { srslte::log_filter log1("RLC_UM_1"); @@ -103,9 +47,9 @@ int basic_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_um_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_um_tester tester; + srslte::timers timers(16); + int len = 0; rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc2(&log2, 3, &tester, &tester, &timers); @@ -155,10 +99,9 @@ int basic_test() TESTASSERT(0 == rlc2.get_buffer_state()); - TESTASSERT(NBUFS == tester.n_sdus); - for(int i=0; iN_bytes == 1); + TESTASSERT(NBUFS == tester.get_num_sdus()); + for (uint32_t i = 0; i < tester.sdus.size(); i++) { + TESTASSERT(tester.sdus.at(i)->N_bytes == 1); TESTASSERT(*(tester.sdus[i]->msg) == i); } @@ -173,9 +116,9 @@ int loss_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_um_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_um_tester tester; + srslte::timers timers(16); + int len = 0; rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc2(&log2, 3, &tester, &tester, &timers); @@ -218,10 +161,10 @@ int loss_test() } // Step the reordering timer until expiry - while(!timers.timer_get(1)->is_expired()) - timers.timer_get(1)->step(); + while (!timers.get(1)->is_expired()) + timers.get(1)->step(); - TESTASSERT(NBUFS - 1 == tester.n_sdus); + TESTASSERT(NBUFS - 1 == tester.sdus.size()); return 0; } @@ -234,9 +177,9 @@ int basic_mbsfn_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_um_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_um_tester tester; + srslte::timers timers(16); + int len = 0; rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc2(&log2, 3, &tester, &tester, &timers); @@ -277,9 +220,8 @@ int basic_mbsfn_test() TESTASSERT(0 == rlc2.get_buffer_state()); - TESTASSERT(NBUFS == tester.n_sdus); - for(int i=0; iN_bytes == 1); TESTASSERT(*(tester.sdus[i]->msg) == i); } @@ -306,9 +248,9 @@ int reassmble_test() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_um_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_um_tester tester; + srslte::timers timers(16); + int len = 0; rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc2(&log2, 3, &tester, &tester, &timers); @@ -392,8 +334,8 @@ int reassmble_test() } // We should have received one SDU less than we tx'ed - TESTASSERT(tester.n_sdus == n_sdus - 1); - for (int i = 0; i < tester.n_sdus; ++i) { + TESTASSERT(tester.sdus.size() == n_sdus - 1); + for (uint32_t i = 0; i < tester.sdus.size(); ++i) { TESTASSERT(tester.sdus[i]->N_bytes == sdu_len); } @@ -415,9 +357,9 @@ int reassmble_test2() log2.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_hex_limit(-1); log2.set_hex_limit(-1); - rlc_um_tester tester; - mac_dummy_timers timers; - int len = 0; + rlc_um_tester tester; + srslte::timers timers(16); + int len = 0; rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc2(&log2, 3, &tester, &tester, &timers); @@ -496,8 +438,8 @@ int reassmble_test2() } // We should have received one SDU less than we tx'ed - TESTASSERT(tester.n_sdus == n_sdus - 1); - for (int i = 0; i < tester.n_sdus; ++i) { + TESTASSERT(tester.sdus.size() == n_sdus - 1); + for (uint32_t i = 0; i < tester.sdus.size(); ++i) { TESTASSERT(tester.sdus[i]->N_bytes == sdu_len); } diff --git a/run-clang-format-diff.sh b/run-clang-format-diff.sh new file mode 100755 index 000000000..a506d0891 --- /dev/null +++ b/run-clang-format-diff.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Copyright 2013-2019 Software Radio Systems Limited +# +# This file is part of srsLTE. +# +# srsLTE 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. +# +# srsLTE 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/. +# + +# make sure all commands are echoed +#set -x +set -o pipefail + +if ([ ! $1 ]) +then + echo "Please call script with target branch name or git hash to perform diff with." + echo "E.g. ./run-clang-format-diff.sh [HASH]" + exit 1 +fi + +# check for apps +app1=$(which clang-format-diff) +app2=$(which git) +app3=$(which colordiff) +if ([ ! -x "$app1" ] || [ ! -x "$app2" ] || [ ! -x "$app3" ]) +then + echo "Please install clang-format-diff, git and colordiff" + exit 1 +fi + +target=$1 + +echo "Running code format check between ${target} and ${commit} .." + +# run clang-format +diff="$(git diff ${target} | clang-format-diff -p1 | python3 -c 'data = open(0).read(); print(data); exit(1 if data else 0)')" + +# safe return code +ret=$? + +if ([ $ret == "0" ]) +then + echo "Code formatting is correct." +else + echo "The following code seems to be not formatted correctly:" + # print colorized version + echo "${diff}" | colordiff +fi + +exit ${ret} diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 262833977..7f68829e9 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -73,7 +73,10 @@ rx_gain = 40 #device_name = auto # For best performance in 2x2 MIMO and >= 15 MHz use the following device_args settings: -# USRP B210: pass num_recv_frames=64,num_send_frames=64 +# USRP B210: num_recv_frames=64,num_send_frames=64 + +# For best performance when BW<5 MHz (25 PRB), use the following device_args settings: +# USRP B210: send_frame_size=512,recv_frame_size=512 #device_args = auto #time_adv_nsamples = auto @@ -113,7 +116,7 @@ filename = /tmp/enb.pcap # configured. # Format: e.g. phy_hex_limit = 32 # -# Logging layers: phy, mac, rlc, pdcp, rrc, nas, gtpu, usim, all +# Logging layers: rf, phy, mac, rlc, pdcp, rrc, nas, gtpu, usim, all # Logging levels: debug, info, warning, error, none # # filename: File path to use for log output. Can be set to stdout diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 218f31e30..b4bd56417 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -86,7 +86,11 @@ public: // Radio-Link status void rl_failure(uint16_t rnti) final { mac.rl_failure(rnti); } void rl_ok(uint16_t rnti) final { mac.rl_ok(rnti); } - void tti_clock() final { mac.tti_clock(); } + void tti_clock() final + { + timers.step_all(); + mac.tti_clock(); + } private: stack_args_t args = {}; @@ -102,6 +106,7 @@ private: srsenb::s1ap s1ap; srslte::logger* logger = nullptr; + srslte::timers timers; // Radio and PHY log are in enb.cc srslte::log_filter mac_log; diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 60649e500..1b5c31bd1 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -54,10 +54,11 @@ typedef enum { static const char rrc_cfg_cqi_mode_text[RRC_CFG_CQI_MODE_N_ITEMS][20] = {"periodic", "aperiodic"}; typedef struct { - uint32_t sf_mapping[80]; - uint32_t nof_subframes; - uint32_t nof_prb; - uint32_t period; + uint32_t sf_mapping[80]; + uint32_t nof_subframes; + uint32_t nof_prb; + uint32_t period; + uint32_t m_ri; bool simultaneousAckCQI; rrc_cfg_cqi_mode_t mode; } rrc_cfg_cqi_t; @@ -245,6 +246,8 @@ public: void cqi_get(uint16_t* pmi_idx, uint16_t* n_pucch); int cqi_free(); + int ri_get(uint32_t m_ri, uint16_t* ri_idx); + bool select_security_algorithms(); void send_dl_ccch(asn1::rrc::dl_ccch_msg_s* dl_ccch_msg); void send_dl_dcch(asn1::rrc::dl_dcch_msg_s* dl_dcch_msg, diff --git a/srsenb/hdr/stack/upper/pdcp.h b/srsenb/hdr/stack/upper/pdcp.h index 6785e86d4..2b62b6d26 100644 --- a/srsenb/hdr/stack/upper/pdcp.h +++ b/srsenb/hdr/stack/upper/pdcp.h @@ -28,10 +28,8 @@ #define SRSENB_PDCP_H namespace srsenb { - -class pdcp : public pdcp_interface_rlc, - public pdcp_interface_gtpu, - public pdcp_interface_rrc + +class pdcp : public pdcp_interface_rlc, public pdcp_interface_gtpu, public pdcp_interface_rrc { public: pdcp(srslte::log* pdcp_log_); @@ -45,46 +43,46 @@ public: // pdcp_interface_rrc void reset(uint16_t rnti); - void add_user(uint16_t rnti); + void add_user(uint16_t rnti); void rem_user(uint16_t rnti); void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu); - void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cnfg); - void config_security(uint16_t rnti, - uint32_t lcid, - uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, - uint8_t *k_up_enc_, + void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg); + void config_security(uint16_t rnti, + uint32_t lcid, + uint8_t* k_rrc_enc_, + uint8_t* k_rrc_int_, + uint8_t* k_up_enc_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_); void enable_integrity(uint16_t rnti, uint32_t lcid); void enable_encryption(uint16_t rnti, uint32_t lcid); -private: - + +private: class user_interface_rlc : public srsue::rlc_interface_pdcp { public: - uint16_t rnti; - srsenb::rlc_interface_pdcp *rlc; + uint16_t rnti; + srsenb::rlc_interface_pdcp* rlc; // rlc_interface_pdcp void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking); bool rb_is_um(uint32_t lcid); }; - + class user_interface_gtpu : public srsue::gw_interface_pdcp { - public: - uint16_t rnti; - srsenb::gtpu_interface_pdcp *gtpu; + public: + uint16_t rnti; + srsenb::gtpu_interface_pdcp* gtpu; // gw_interface_pdcp void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) {} - }; - + }; + class user_interface_rrc : public srsue::rrc_interface_pdcp { - public: - uint16_t rnti; - srsenb::rrc_interface_pdcp *rrc; + public: + uint16_t rnti; + srsenb::rrc_interface_pdcp* rrc; // rrc_interface_pdcp void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void write_pdu_bcch_bch(srslte::unique_byte_buffer_t pdu); @@ -93,29 +91,28 @@ private: void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} std::string get_rb_name(uint32_t lcid); }; - - class user_interface + + class user_interface { - public: - user_interface_rlc rlc_itf; + public: + user_interface_rlc rlc_itf; user_interface_gtpu gtpu_itf; - user_interface_rrc rrc_itf; - srslte::pdcp *pdcp; + user_interface_rrc rrc_itf; + srslte::pdcp* pdcp; }; - void clear_user(user_interface *ue); - - std::map users; + void clear_user(user_interface* ue); + + std::map users; pthread_rwlock_t rwlock; - - rlc_interface_pdcp *rlc; - rrc_interface_pdcp *rrc; - gtpu_interface_pdcp *gtpu; - srslte::log *log_h; - srslte::byte_buffer_pool *pool; -}; -} + rlc_interface_pdcp* rlc; + rrc_interface_pdcp* rrc; + gtpu_interface_pdcp* gtpu; + srslte::log* log_h; + srslte::byte_buffer_pool* pool; +}; +} // namespace srsenb #endif // SRSENB_PDCP_H diff --git a/srsenb/hdr/stack/upper/rlc.h b/srsenb/hdr/stack/upper/rlc.h index 2a93e05e4..f4b8e325c 100644 --- a/srsenb/hdr/stack/upper/rlc.h +++ b/srsenb/hdr/stack/upper/rlc.h @@ -41,17 +41,20 @@ class rlc : public rlc_interface_mac, public rlc_interface_pdcp { public: - - void init(pdcp_interface_rlc *pdcp_, rrc_interface_rlc *rrc_, mac_interface_rlc *mac_, - srslte::mac_interface_timers *mac_timers_, srslte::log *log_h); - void stop(); - + void init(pdcp_interface_rlc* pdcp_, + rrc_interface_rlc* rrc_, + mac_interface_rlc* mac_, + srslte::timers* timers_, + srslte::log* log_h); + void stop(); + // rlc_interface_rrc void clear_buffer(uint16_t rnti); void add_user(uint16_t rnti); void rem_user(uint16_t rnti); void add_bearer(uint16_t rnti, uint32_t lcid, srslte::rlc_config_t cnfg); void add_bearer_mrb(uint16_t rnti, uint32_t lcid); + bool has_bearer(uint16_t rnti, uint32_t lcid); // rlc_interface_pdcp void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu); @@ -90,12 +93,12 @@ private: mac_interface_rlc *mac; pdcp_interface_rlc *pdcp; - rrc_interface_rlc *rrc; - srslte::log *log_h; - srslte::byte_buffer_pool *pool; - srslte::mac_interface_timers *mac_timers; + rrc_interface_rlc* rrc; + srslte::log* log_h; + srslte::byte_buffer_pool* pool; + srslte::timers* timers; }; -} +} // namespace srsenb #endif // SRSENB_RLC_H diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index 2d913f314..d5fe1d2ab 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -46,5 +46,6 @@ phy_cnfg = period = 40; // in ms subframe = [0]; nof_prb = 2; + m_ri = 8; // RI period in CQI period }; }; diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 92c8669e0..30058ee72 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -84,8 +84,8 @@ int enb::init(const all_args_t& args_) logger = &logger_stdout; } else { logger_file.init(args.log.filename, args.log.file_max_size); - logger_file.log("\n\n"); - logger_file.log(get_build_string().c_str()); + logger_file.log_char("\n\n"); + logger_file.log_char(get_build_string().c_str()); logger = &logger_file; } @@ -220,6 +220,9 @@ int enb::parse_args(const all_args_t& args_) } else if ((*it) == "EEA2") { rrc_cfg.eea_preference_list[i] = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; i++; + } else if ((*it) == "EEA3") { + rrc_cfg.eea_preference_list[i] = srslte::CIPHERING_ALGORITHM_ID_128_EEA3; + i++; } else { fprintf(stderr, "Failed to parse EEA prefence list %s \n", args.general.eea_pref_list.c_str()); return SRSLTE_ERROR; @@ -241,6 +244,9 @@ int enb::parse_args(const all_args_t& args_) } else if ((*it) == "EIA2") { rrc_cfg.eia_preference_list[i] = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2; i++; + } else if ((*it) == "EIA3") { + rrc_cfg.eia_preference_list[i] = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3; + i++; } else { fprintf(stderr, "Failed to parse EIA prefence list %s \n", args.general.eia_pref_list.c_str()); return SRSLTE_ERROR; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 5a61dd670..60c36d647 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -935,6 +935,7 @@ int enb::parse_rr(all_args_t* args, rrc_cfg_t* rrc_cfg) cqi_report_cnfg.add_field(new parser::field_enum_str( "mode", &rrc_cfg->cqi_cfg.mode, rrc_cfg_cqi_mode_text, RRC_CFG_CQI_MODE_N_ITEMS)); cqi_report_cnfg.add_field(new parser::field("period", &rrc_cfg->cqi_cfg.period)); + cqi_report_cnfg.add_field(new parser::field("m_ri", &rrc_cfg->cqi_cfg.m_ri)); cqi_report_cnfg.add_field(new parser::field("nof_prb", &rrc_cfg->cqi_cfg.nof_prb)); cqi_report_cnfg.add_field(new parser::field("simultaneousAckCQI", &rrc_cfg->cqi_cfg.simultaneousAckCQI)); cqi_report_cnfg.add_field(new field_sf_mapping(rrc_cfg->cqi_cfg.sf_mapping, &rrc_cfg->cqi_cfg.nof_subframes)); diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index e4b9b40e8..cdb0a7c17 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -102,6 +102,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { ("gui.enable", bpo::value(&args->gui.enable)->default_value(false), "Enable GUI plots") + ("log.rf_level", bpo::value(&args->rf.log_level), "RF log level") ("log.phy_level", bpo::value(&args->phy.log.phy_level), "PHY log level") ("log.phy_hex_limit", bpo::value(&args->phy.log.phy_hex_limit), "PHY log hex dump limit") ("log.phy_lib_level", bpo::value(&args->phy.log.phy_lib_level)->default_value("none"), "PHY lib log level") @@ -275,6 +276,9 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { // Apply all_level to any unset layers if (vm.count("log.all_level")) { + if (!vm.count("log.rf_level")) { + args->rf.log_level = args->log.all_level; + } if(!vm.count("log.phy_level")) { args->phy.log.phy_level = args->log.all_level; } diff --git a/srsenb/src/metrics_stdout.cc b/srsenb/src/metrics_stdout.cc index a0d4054e6..a93ec0d31 100644 --- a/srsenb/src/metrics_stdout.cc +++ b/srsenb/src/metrics_stdout.cc @@ -62,7 +62,15 @@ void metrics_stdout::toggle_print(bool b) void metrics_stdout::set_metrics(enb_metrics_t &metrics, const uint32_t period_usec) { - if (!do_print || enb == NULL || metrics.stack.rrc.n_ues == 0) { + if (!do_print || enb == nullptr) { + return; + } + + if (metrics.rf.rf_error) { + printf("RF status: O=%d, U=%d, L=%d\n", metrics.rf.rf_o, metrics.rf.rf_u, metrics.rf.rf_l); + } + + if (metrics.stack.rrc.n_ues == 0) { return; } @@ -130,10 +138,6 @@ void metrics_stdout::set_metrics(enb_metrics_t &metrics, const uint32_t period_u cout << endl; } - if (metrics.rf.rf_error) { - printf("RF status: O=%d, U=%d, L=%d\n", metrics.rf.rf_o, metrics.rf.rf_u, metrics.rf.rf_l); - } - cout.flags(f); // For avoiding Coverity defect: Not restoring ostream format } diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 77d259f98..4994af0da 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -283,8 +283,9 @@ void phy::configure_mbsfn(sib_type2_s* sib2, sib_type13_r9_s* sib13, mcch_msg_s } // Start GUI -void phy::start_plot() { - ((sf_worker)workers[0]).start_plot(); +void phy::start_plot() +{ + workers[0].start_plot(); } -} +} // namespace srsenb diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index cd8a4b103..d13b7533f 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -488,10 +488,10 @@ bool sf_worker::fill_uci_cfg(uint16_t rnti, bool aperiodic_cqi_request, srslte_u // Get pending ACKs with an associated PUSCH transmission // TODO: Use ue_dl procedures to compute uci_ack_cfg for TDD and CA for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - uci_cfg->ack.pending_tb[tb] = phy->ue_db_is_ack_pending(tti_rx, rnti, tb, &uci_cfg->ack.ncce[0]); - Debug("ACK: is pending tti=%d, mod=%d, value=%d\n", tti_rx, TTIMOD(tti_rx), uci_cfg->ack.pending_tb[tb]); - if (uci_cfg->ack.pending_tb[tb]) { - uci_cfg->ack.nof_acks++; + uci_cfg->ack[0].pending_tb[tb] = phy->ue_db_is_ack_pending(tti_rx, rnti, tb, &uci_cfg->ack[0].ncce[0]); + Debug("ACK: is pending tti=%d, mod=%d, value=%d\n", tti_rx, TTIMOD(tti_rx), uci_cfg->ack[0].pending_tb[tb]); + if (uci_cfg->ack[0].pending_tb[tb]) { + uci_cfg->ack[0].nof_acks++; uci_required = true; } } @@ -518,7 +518,7 @@ void sf_worker::send_uci_data(uint16_t rnti, srslte_uci_cfg_t* uci_cfg, srslte_u /* If only one ACK is required, it can be for TB0 or TB1 */ uint32_t ack_idx = 0; for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - if (uci_cfg->ack.pending_tb[tb]) { + if (uci_cfg->ack[0].pending_tb[tb]) { bool ack = uci_value->ack.ack_value[ack_idx]; bool valid = uci_value->ack.valid; phy->stack->ack_info(tti_rx, rnti, tb, ack && valid); diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index af5719d1c..b44dfc608 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -28,7 +28,7 @@ using namespace srslte; namespace srsenb { -enb_stack_lte::enb_stack_lte(srslte::logger* logger_) : logger(logger_), pdcp(&pdcp_log) {} +enb_stack_lte::enb_stack_lte(srslte::logger* logger_) : logger(logger_), pdcp(&pdcp_log), timers(128) {} enb_stack_lte::~enb_stack_lte() { @@ -115,7 +115,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) // Init all layers mac.init(args.mac, &cell_cfg, phy, &rlc, &rrc, &mac_log); - rlc.init(&pdcp, &rrc, &mac, &mac, &rlc_log); + rlc.init(&pdcp, &rrc, &mac, &timers, &rlc_log); pdcp.init(&rlc, &rrc, >pu); rrc.init(&rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &rrc_log); s1ap.init(args.s1ap, &rrc, &s1ap_log); diff --git a/srsenb/src/stack/mac/scheduler.cc b/srsenb/src/stack/mac/scheduler.cc index e5c02fbf9..95a3bdbbb 100644 --- a/srsenb/src/stack/mac/scheduler.cc +++ b/srsenb/src/stack/mac/scheduler.cc @@ -214,7 +214,7 @@ alloc_outcome_t sched::tti_sched_t::alloc_ul(sched_ue* use return ret; } - ul_alloc_t ul_alloc; + ul_alloc_t ul_alloc = {}; ul_alloc.type = alloc_type; ul_alloc.dci_idx = tti_alloc.get_pdcch_grid().nof_allocs() - 1; ul_alloc.user_ptr = user; diff --git a/srsenb/src/stack/mac/scheduler_ue.cc b/srsenb/src/stack/mac/scheduler_ue.cc index 8a831bbf2..266ddb3c3 100644 --- a/srsenb/src/stack/mac/scheduler_ue.cc +++ b/srsenb/src/stack/mac/scheduler_ue.cc @@ -278,8 +278,8 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2]) // Pending ACKs for (int i = 0; i < SCHED_MAX_HARQ_PROC; i++) { if (TTI_TX(dl_harq[i].get_tti()) == current_tti) { - cfg.pucch_cfg.uci_cfg.ack.ncce[0] = dl_harq[i].get_n_cce(); - cfg.pucch_cfg.uci_cfg.ack.nof_acks = 1; + cfg.pucch_cfg.uci_cfg.ack[0].ncce[0] = dl_harq[i].get_n_cce(); + cfg.pucch_cfg.uci_cfg.ack[0].nof_acks = 1; ret = true; } } @@ -299,7 +299,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2]) prb_idx[0], prb_idx[1], cfg.pucch_cfg.n_pucch, - cfg.pucch_cfg.uci_cfg.ack.ncce[0], + cfg.pucch_cfg.uci_cfg.ack[0].ncce[0], cfg.pucch_cfg.uci_cfg.is_scheduling_request_tti); } } @@ -896,9 +896,8 @@ uint32_t sched_ue::get_required_prb_dl(uint32_t req_bytes, uint32_t nof_ctrl_sym uint32_t sched_ue::get_required_prb_ul(uint32_t req_bytes) { - int mcs = 0; - int tbs = 0; - uint32_t nbytes = 0; + int mcs = 0; + uint32_t nbytes = 0; uint32_t N_srs = 0; uint32_t n = 0; diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index f561bdc84..63647d43e 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -193,11 +193,14 @@ void rrc::add_user(uint16_t rnti) } if (rnti == SRSLTE_MRNTI) { - srslte::srslte_pdcp_config_t cfg; - cfg.is_control = false; - cfg.is_data = true; - cfg.sn_len = 12; - cfg.direction = SECURITY_DIRECTION_DOWNLINK; + srslte::pdcp_config_t cfg = { + .bearer_id = 1, + .rb_type = srslte::PDCP_RB_IS_DRB, + .tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK, + .rx_direction = srslte::SECURITY_DIRECTION_UPLINK, + .sn_len = srslte::PDCP_SN_LEN_12, + }; + uint32_t teid_in = 1; for (uint32_t i = 0; i < mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9.size(); @@ -399,6 +402,7 @@ bool rrc::modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIO if (err) { // maybe pass a cause value? + pthread_mutex_unlock(&user_mutex); return false; } @@ -1608,12 +1612,11 @@ void rrc::ue::send_connection_setup(bool is_setup) parent->rlc->add_bearer(rnti, 1, srslte::rlc_config_t::srb_config(1)); // Configure SRB1 in PDCP - srslte::srslte_pdcp_config_t pdcp_cnfg; - pdcp_cnfg.bearer_id = 1; - pdcp_cnfg.is_control = true; - pdcp_cnfg.is_data = false; - pdcp_cnfg.sn_len = 5; - pdcp_cnfg.direction = SECURITY_DIRECTION_DOWNLINK; + srslte::pdcp_config_t pdcp_cnfg{.bearer_id = 1, + .rb_type = srslte::PDCP_RB_IS_SRB, + .tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK, + .rx_direction = srslte::SECURITY_DIRECTION_UPLINK, + .sn_len = srslte::PDCP_SN_LEN_5}; parent->pdcp->add_bearer(rnti, 1, pdcp_cnfg); // Configure PHY layer @@ -1623,7 +1626,7 @@ void rrc::ue::send_connection_setup(bool is_setup) rr_cfg->drb_to_add_mod_list_present = false; rr_cfg->drb_to_release_list_present = false; - rr_cfg->rlf_timers_and_consts_r9_present = false; + rr_cfg->rlf_timers_and_consts_r9.set_present(false); rr_cfg->sps_cfg_present = false; // rr_cfg->rlf_timers_and_constants_present = false; @@ -1777,10 +1780,14 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) if (phy_cfg->ant_info_present and ((phy_cfg->ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm3) || (phy_cfg->ant_info.explicit_value().tx_mode == ant_info_ded_s::tx_mode_e_::tm4))) { - phy_cfg->cqi_report_cfg.cqi_report_periodic.set_setup(); - phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present = true; - phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx = 483; - parent->rrc_log->console("\nWarning: Only 1 user is supported in TM3 and TM4\n\n"); + uint16_t ri_idx = 0; + if (ri_get(parent->cfg.cqi_cfg.m_ri, &ri_idx) == SRSLTE_SUCCESS) { + phy_cfg->cqi_report_cfg.cqi_report_periodic.set_setup(); + phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present = true; + phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx = ri_idx; + } else { + parent->rrc_log->console("\nWarning: Configured wrong M_ri parameter.\n\n"); + } } else { phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present = false; } @@ -1824,13 +1831,12 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) parent->rlc->add_bearer(rnti, 2, srslte::rlc_config_t::srb_config(2)); // Configure SRB2 in PDCP - srslte::srslte_pdcp_config_t pdcp_cnfg; - pdcp_cnfg.bearer_id = 2; - pdcp_cnfg.direction = SECURITY_DIRECTION_DOWNLINK; - pdcp_cnfg.is_control = true; - pdcp_cnfg.is_data = false; - pdcp_cnfg.sn_len = 5; - parent->pdcp->add_bearer(rnti, 2, pdcp_cnfg); + srslte::pdcp_config_t pdcp_cnfg_srb = {.bearer_id = 2, + .rb_type = srslte::PDCP_RB_IS_SRB, + .tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK, + .rx_direction = srslte::SECURITY_DIRECTION_UPLINK, + .sn_len = srslte::PDCP_SN_LEN_5}; + parent->pdcp->add_bearer(rnti, 2, pdcp_cnfg_srb); parent->pdcp->config_security(rnti, 2, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); parent->pdcp->enable_integrity(rnti, 2); parent->pdcp->enable_encryption(rnti, 2); @@ -1839,17 +1845,18 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) parent->rlc->add_bearer(rnti, 3, srslte::make_rlc_config_t(conn_reconf->rr_cfg_ded.drb_to_add_mod_list[0].rlc_cfg)); // Configure DRB1 in PDCP - pdcp_cnfg.is_control = false; - pdcp_cnfg.is_data = true; - pdcp_cnfg.sn_len = 12; - pdcp_cnfg.bearer_id = 1; // TODO: Review all ID mapping LCID DRB ERAB EPSBID Mapping + srslte::pdcp_config_t pdcp_cnfg_drb = {.bearer_id = 1, + .rb_type = srslte::PDCP_RB_IS_DRB, + .tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK, + .rx_direction = srslte::SECURITY_DIRECTION_UPLINK, + .sn_len = srslte::PDCP_SN_LEN_12}; if (conn_reconf->rr_cfg_ded.drb_to_add_mod_list[0].pdcp_cfg.rlc_um_present) { if (conn_reconf->rr_cfg_ded.drb_to_add_mod_list[0].pdcp_cfg.rlc_um.pdcp_sn_size.value == pdcp_cfg_s::rlc_um_s_::pdcp_sn_size_e_::len7bits) { - pdcp_cnfg.sn_len = 7; + pdcp_cnfg_drb.sn_len = srslte::PDCP_SN_LEN_7; } } - parent->pdcp->add_bearer(rnti, 3, pdcp_cnfg); + parent->pdcp->add_bearer(rnti, 3, pdcp_cnfg_drb); parent->pdcp->config_security(rnti, 3, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); parent->pdcp->enable_integrity(rnti, 3); parent->pdcp->enable_encryption(rnti, 3); @@ -1906,12 +1913,12 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE parent->rlc->add_bearer(rnti, lcid, srslte::make_rlc_config_t(drb_item.rlc_cfg)); // Configure DRB in PDCP - srslte::srslte_pdcp_config_t pdcp_config; - pdcp_config.bearer_id = drb_item.drb_id - 1; // TODO: Review all ID mapping LCID DRB ERAB EPSBID Mapping - pdcp_config.is_control = false; - pdcp_config.is_data = true; - pdcp_config.sn_len = 12; - pdcp_config.direction = SECURITY_DIRECTION_DOWNLINK; + srslte::pdcp_config_t pdcp_config = { + .bearer_id = (uint8_t)(drb_item.drb_id - 1), // TODO: Review all ID mapping LCID DRB ERAB EPSBID Mapping + .rb_type = srslte::PDCP_RB_IS_DRB, + .tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK, + .rx_direction = srslte::SECURITY_DIRECTION_UPLINK, + .sn_len = srslte::PDCP_SN_LEN_12}; parent->pdcp->add_bearer(rnti, lcid, pdcp_config); // DRB has already been configured in GTPU through bearer setup @@ -2011,6 +2018,17 @@ bool rrc::ue::select_security_algorithms() parent->rrc_log->info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm\n"); } break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: + // “third bit” – 128-EEA3, + if (security_capabilities.encryptionAlgorithms.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA3 - 1]) { + cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA3; + enc_algo_found = true; + parent->rrc_log->info("Selected EEA3 as RRC encryption algorithm\n"); + break; + } else { + parent->rrc_log->info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; default: enc_algo_found = false; break; @@ -2046,6 +2064,16 @@ bool rrc::ue::select_security_algorithms() parent->rrc_log->info("Failed to selected EIA2 as RRC encryption algorithm, due to unsupported algorithm\n"); } break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + // “third bit” – 128-EIA3, + if (security_capabilities.integrityProtectionAlgorithms.buffer[srslte::INTEGRITY_ALGORITHM_ID_128_EIA3 - 1]) { + integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3; + integ_algo_found = true; + parent->rrc_log->info("Selected EIA3 as RRC integrity algorithm.\n"); + } else { + parent->rrc_log->info("Failed to selected EIA3 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; default: integ_algo_found = false; break; @@ -2092,10 +2120,15 @@ void rrc::ue::send_dl_dcch(dl_dcch_msg_s* dl_dcch_msg, srslte::unique_byte_buffe dl_dcch_msg->pack(bref); pdu->N_bytes = 1u + (uint32_t)bref.distance_bytes(pdu->msg); + // send on SRB2 if user is fully registered (after RRC reconfig complete) + uint32_t lcid = + parent->rlc->has_bearer(rnti, RB_ID_SRB2) && state == RRC_STATE_REGISTERED ? RB_ID_SRB2 : RB_ID_SRB1; + char buf[32] = {}; - sprintf(buf, "SRB1 - rnti=0x%x", rnti); + sprintf(buf, "SRB%d - rnti=0x%x", lcid, rnti); parent->log_rrc_message(buf, Tx, pdu.get(), *dl_dcch_msg); - parent->pdcp->write_sdu(rnti, RB_ID_SRB1, std::move(pdu)); + + parent->pdcp->write_sdu(rnti, lcid, std::move(pdu)); } else { parent->rrc_log->error("Allocating pdu\n"); } @@ -2271,4 +2304,43 @@ int rrc::ue::cqi_allocate(uint32_t period, uint16_t* pmi_idx, uint16_t* n_pucch) return 0; } +int rrc::ue::ri_get(uint32_t m_ri, uint16_t* ri_idx) +{ + int32_t ret = SRSLTE_SUCCESS; + + uint32_t I_ri = 0; + int32_t N_offset_ri = 0; // Naivest approach: overlap RI with PMI + switch (m_ri) { + case 0: + // Disabled + break; + case 1: + I_ri = -N_offset_ri; + break; + case 2: + I_ri = 161 - N_offset_ri; + break; + case 4: + I_ri = 322 - N_offset_ri; + break; + case 8: + I_ri = 483 - N_offset_ri; + break; + case 16: + I_ri = 644 - N_offset_ri; + break; + case 32: + I_ri = 805 - N_offset_ri; + break; + default: + parent->rrc_log->error("Allocating RI: invalid m_ri=%d\n", m_ri); + } + + // If ri_dix is available, copy + if (ri_idx) { + *ri_idx = I_ri; + } + + return ret; +} } diff --git a/srsenb/src/stack/upper/pdcp.cc b/srsenb/src/stack/upper/pdcp.cc index c75a81b48..685633236 100644 --- a/srsenb/src/stack/upper/pdcp.cc +++ b/srsenb/src/stack/upper/pdcp.cc @@ -82,7 +82,7 @@ void pdcp::rem_user(uint16_t rnti) pthread_rwlock_unlock(&rwlock); } -void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cfg) +void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cfg) { pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { diff --git a/srsenb/src/stack/upper/rlc.cc b/srsenb/src/stack/upper/rlc.cc index 4b63db6b7..529c25780 100644 --- a/srsenb/src/stack/upper/rlc.cc +++ b/srsenb/src/stack/upper/rlc.cc @@ -23,17 +23,20 @@ #include "srsenb/hdr/stack/upper/common_enb.h" namespace srsenb { - -void rlc::init(pdcp_interface_rlc* pdcp_, rrc_interface_rlc* rrc_, mac_interface_rlc *mac_, - srslte::mac_interface_timers *mac_timers_, srslte::log* log_h_) + +void rlc::init(pdcp_interface_rlc* pdcp_, + rrc_interface_rlc* rrc_, + mac_interface_rlc* mac_, + srslte::timers* timers_, + srslte::log* log_h_) { - pdcp = pdcp_; - rrc = rrc_, - log_h = log_h_; - mac = mac_; - mac_timers = mac_timers_; + pdcp = pdcp_; + rrc = rrc_; + log_h = log_h_; + mac = mac_; + timers = timers_; - pool = srslte::byte_buffer_pool::get_instance(); + pool = srslte::byte_buffer_pool::get_instance(); pthread_rwlock_init(&rwlock, NULL); } @@ -54,9 +57,9 @@ void rlc::add_user(uint16_t rnti) pthread_rwlock_rdlock(&rwlock); if (users.count(rnti) == 0) { std::unique_ptr obj(new srslte::rlc(log_h)); - obj->init(&users[rnti], &users[rnti], mac_timers, RB_ID_SRB0); - users[rnti].rnti = rnti; - users[rnti].pdcp = pdcp; + obj->init(&users[rnti], &users[rnti], timers, RB_ID_SRB0); + users[rnti].rnti = rnti; + users[rnti].pdcp = pdcp; users[rnti].rrc = rrc; users[rnti].rlc = std::move(obj); users[rnti].parent = this; @@ -107,6 +110,17 @@ void rlc::add_bearer_mrb(uint16_t rnti, uint32_t lcid) pthread_rwlock_unlock(&rwlock); } +bool rlc::has_bearer(uint16_t rnti, uint32_t lcid) +{ + pthread_rwlock_rdlock(&rwlock); + bool result = false; + if (users.count(rnti)) { + result = users[rnti].rlc->has_bearer(lcid); + } + pthread_rwlock_unlock(&rwlock); + return result; +} + void rlc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) { rrc->read_pdu_pcch(payload, buffer_size); diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index c3f9ac0c2..84db27013 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -81,7 +81,7 @@ private: fd_set m_set; // Timer map - std::vector m_timers; + std::vector timers; // Timer Methods void handle_timer_expire(int timer_fd); diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 18a4c5d2d..966ff4d21 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -89,8 +89,8 @@ void parse_args(all_args_t* args, int argc, char* argv[]) string mme_apn; string encryption_algo; string integrity_algo; - uint16_t paging_timer; - uint32_t max_paging_queue; + uint16_t paging_timer = 0; + uint32_t max_paging_queue = 0; string spgw_bind_addr; string sgi_if_addr; string sgi_if_name; @@ -249,9 +249,11 @@ void parse_args(all_args_t* args, int argc, char* argv[]) args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1; } else if (boost::iequals(encryption_algo, "eea2")) { args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; + } else if (boost::iequals(encryption_algo, "eea3")) { + args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA3; } else { args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; - cout << "Error parsing mme.encryption_algo:" << encryption_algo << " - must be EEA0, EEA1, or EEA2." << endl; + cout << "Error parsing mme.encryption_algo:" << encryption_algo << " - must be EEA0, EEA1, EEA2 or EEA3." << endl; cout << "Using default mme.encryption_algo: EEA0" << endl; } @@ -263,9 +265,11 @@ void parse_args(all_args_t* args, int argc, char* argv[]) args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; } else if (boost::iequals(integrity_algo, "eia2")) { args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2; + } else if (boost::iequals(integrity_algo, "eia3")) { + args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3; } else { args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; - cout << "Error parsing mme.integrity_algo:" << encryption_algo << " - must be EIA0, EIA1, or EIA2." << endl; + cout << "Error parsing mme.integrity_algo:" << encryption_algo << " - must be EIA0, EIA1, EIA2 or EIA3." << endl; cout << "Using default mme.integrity_algo: EIA1" << endl; } @@ -401,9 +405,9 @@ int main(int argc, char* argv[]) logger = &logger_stdout; } else { logger_file.init(args.log_args.filename); - logger_file.log("\n\n"); - logger_file.log(get_build_string().c_str()); - logger_file.log("\n--- Software Radio Systems EPC log ---\n\n"); + logger_file.log_char("\n\n"); + logger_file.log_char(get_build_string().c_str()); + logger_file.log_char("\n--- Software Radio Systems EPC log ---\n\n"); logger = &logger_file; } diff --git a/srsepc/src/mbms-gw/main.cc b/srsepc/src/mbms-gw/main.cc index 3f2312b18..309cc7e0a 100644 --- a/srsepc/src/mbms-gw/main.cc +++ b/srsepc/src/mbms-gw/main.cc @@ -204,7 +204,7 @@ main (int argc,char * argv[] ) logger = &logger_stdout; } else { logger_file.init(args.log_args.filename); - logger_file.log("\n--- Software Radio Systems MBMS log ---\n\n"); + logger_file.log_char("\n--- Software Radio Systems MBMS log ---\n\n"); logger = &logger_file; } diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 6f480d5ef..2f3495263 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -132,7 +132,7 @@ void mme::run_thread() FD_SET(s11, &m_set); // Add timers to select - for (std::vector::iterator it = m_timers.begin(); it != m_timers.end(); ++it) { + for (std::vector::iterator it = timers.begin(); it != timers.end(); ++it) { FD_SET(it->fd, &m_set); max_fd = std::max(max_fd, it->fd); m_s1ap_log->debug("Adding Timer fd %d to fd_set\n", it->fd); @@ -174,14 +174,14 @@ void mme::run_thread() m_mme_gtpc->handle_s11_pdu(pdu); } // Handle NAS Timers - for (std::vector::iterator it = m_timers.begin(); it != m_timers.end();) { + for (std::vector::iterator it = timers.begin(); it != timers.end();) { if (FD_ISSET(it->fd, &m_set)) { m_s1ap_log->info("Timer expired\n"); uint64_t exp; rd_sz = read(it->fd, &exp, sizeof(uint64_t)); m_s1ap->expire_nas_timer(it->type, it->imsi); close(it->fd); - m_timers.erase(it); + timers.erase(it); } else { ++it; } @@ -205,14 +205,14 @@ bool mme::add_nas_timer(int timer_fd, nas_timer_type type, uint64_t imsi) timer.type = type; timer.imsi = imsi; - m_timers.push_back(timer); + timers.push_back(timer); return true; } bool mme::is_nas_timer_running(nas_timer_type type, uint64_t imsi) { std::vector::iterator it; - for (it = m_timers.begin(); it != m_timers.end(); ++it) { + for (it = timers.begin(); it != timers.end(); ++it) { if (it->type == type && it->imsi == imsi) { return true; // found timer } @@ -223,12 +223,12 @@ bool mme::is_nas_timer_running(nas_timer_type type, uint64_t imsi) bool mme::remove_nas_timer(nas_timer_type type, uint64_t imsi) { std::vector::iterator it; - for (it = m_timers.begin(); it != m_timers.end(); ++it) { + for (it = timers.begin(); it != timers.end(); ++it) { if (it->type == type && it->imsi == imsi) { break; // found timer to remove } } - if (it == m_timers.end()) { + if (it == timers.end()) { m_s1ap_log->warning("Could not find timer to remove. IMSI %" PRIu64 ", Type %d\n", imsi, type); return false; } @@ -237,7 +237,7 @@ bool mme::remove_nas_timer(nas_timer_type type, uint64_t imsi) m_s1ap_log->debug("Removing NAS timer from MME. IMSI %" PRIu64 ", Type %d, Fd: %d\n", imsi, type, it->fd); FD_CLR(it->fd, &m_set); close(it->fd); - m_timers.erase(it); + timers.erase(it); return true; } diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index 2fac230b1..03942d934 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -1554,12 +1554,31 @@ bool nas::short_integrity_check(srslte::byte_buffer_t* pdu) case srslte::INTEGRITY_ALGORITHM_ID_EIA0: break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: - srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], m_sec_ctx.ul_nas_count, 0, SECURITY_DIRECTION_UPLINK, - &pdu->msg[0], 2, &exp_mac[0]); + srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[0], + 2, + &exp_mac[0]); break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: - srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], m_sec_ctx.ul_nas_count, 0, SECURITY_DIRECTION_UPLINK, - &pdu->msg[0], 2, &exp_mac[0]); + srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[0], + 2, + &exp_mac[0]); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + srslte::security_128_eia3(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[0], + 2, + &exp_mac[0]); break; default: break; @@ -1592,7 +1611,7 @@ bool nas::integrity_check(srslte::byte_buffer_t* pdu) srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], m_sec_ctx.ul_nas_count, 0, - SECURITY_DIRECTION_UPLINK, + srslte::SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &exp_mac[0]); @@ -1601,7 +1620,16 @@ bool nas::integrity_check(srslte::byte_buffer_t* pdu) srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], m_sec_ctx.ul_nas_count, 0, - SECURITY_DIRECTION_UPLINK, + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + srslte::security_128_eia3(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + srslte::SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &exp_mac[0]); @@ -1633,7 +1661,7 @@ void nas::integrity_generate(srslte::byte_buffer_t* pdu, uint8_t* mac) srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], m_sec_ctx.dl_nas_count, 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, + srslte::SECURITY_DIRECTION_DOWNLINK, &pdu->msg[5], pdu->N_bytes - 5, mac); @@ -1642,7 +1670,16 @@ void nas::integrity_generate(srslte::byte_buffer_t* pdu, uint8_t* mac) srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], m_sec_ctx.dl_nas_count, 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, + srslte::SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + mac); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + srslte::security_128_eia3(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.dl_nas_count, + 0, // Bearer always 0 for NAS + srslte::SECURITY_DIRECTION_DOWNLINK, &pdu->msg[5], pdu->N_bytes - 5, mac); @@ -1665,7 +1702,7 @@ void nas::cipher_decrypt(srslte::byte_buffer_t* pdu) srslte::security_128_eea1(&m_sec_ctx.k_nas_enc[16], pdu->msg[5], 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, + srslte::SECURITY_DIRECTION_UPLINK, &pdu->msg[6], pdu->N_bytes - 6, &tmp_pdu.msg[6]); @@ -1676,7 +1713,18 @@ void nas::cipher_decrypt(srslte::byte_buffer_t* pdu) srslte::security_128_eea2(&m_sec_ctx.k_nas_enc[16], pdu->msg[5], 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, + srslte::SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); + m_nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: + srslte::security_128_eea3(&m_sec_ctx.k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + srslte::SECURITY_DIRECTION_UPLINK, &pdu->msg[6], pdu->N_bytes - 6, &tmp_pdu.msg[6]); @@ -1699,7 +1747,7 @@ void nas::cipher_encrypt(srslte::byte_buffer_t* pdu) srslte::security_128_eea1(&m_sec_ctx.k_nas_enc[16], pdu->msg[5], 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, + srslte::SECURITY_DIRECTION_DOWNLINK, &pdu->msg[6], pdu->N_bytes - 6, &pdu_tmp.msg[6]); @@ -1710,7 +1758,18 @@ void nas::cipher_encrypt(srslte::byte_buffer_t* pdu) srslte::security_128_eea2(&m_sec_ctx.k_nas_enc[16], pdu->msg[5], 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, + srslte::SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); + m_nas_log->debug_hex(pdu_tmp.msg, pdu->N_bytes, "Encrypted"); + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: + srslte::security_128_eea3(&m_sec_ctx.k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + srslte::SECURITY_DIRECTION_DOWNLINK, &pdu->msg[6], pdu->N_bytes - 6, &pdu_tmp.msg[6]); diff --git a/srsue/hdr/phy/cc_worker.h b/srsue/hdr/phy/cc_worker.h index 9ca206611..ba8f3ea77 100644 --- a/srsue/hdr/phy/cc_worker.h +++ b/srsue/hdr/phy/cc_worker.h @@ -23,6 +23,7 @@ #define SRSLTE_CC_WORKER_H #include "phy_common.h" +#include "srslte/interfaces/ue_interfaces.h" #include "srslte/srslte.h" namespace srsue { @@ -45,8 +46,7 @@ public: float get_ref_cfo(); void set_tdd_config(srslte_tdd_config_t config); - void set_pcell_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg); - void set_scell_config(asn1::rrc::scell_to_add_mod_r10_s* phy_cfg); + void set_config(srslte::phy_cfg_t& phy_cfg); void set_crnti(uint16_t rnti); void enable_pregen_signals(bool enabled); @@ -68,16 +68,6 @@ private: uint32_t pid, bool ul_grant_available, mac_interface_phy_lte::mac_grant_ul_t* mac_grant); - void fill_dci_cfg(srslte_dci_cfg_t* cfg, bool rel10 = false); - - // Cross-carried grants scheduled from PCell - void set_dl_pending_grant(uint32_t cc_idx, srslte_dci_dl_t* dl_dci); - bool get_dl_pending_grant(uint32_t cc_idx, srslte_dci_dl_t* dl_dci); - typedef struct { - bool enable; - srslte_dci_dl_t dl_dci; - } pending_dl_grant_t; - pending_dl_grant_t pending_dl_grant[SRSLTE_MAX_CARRIERS]; // Only for the current TTI /* Methods for DL... */ int decode_pdcch_ul(); @@ -96,39 +86,36 @@ private: void set_uci_aperiodic_cqi(srslte_uci_data_t* uci_data); void set_uci_ack(srslte_uci_data_t* uci_data, bool is_grant_available, uint32_t dai_ul, bool is_pusch_available); uint32_t get_wideband_cqi(); - srslte_cqi_report_mode_t aperiodic_mode(asn1::rrc::cqi_report_mode_aperiodic_e mode); - void parse_antenna_info(asn1::rrc::phys_cfg_ded_s* dedicated); - void parse_pucch_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg); /* Common objects */ - phy_common* phy; - srslte::log* log_h; + phy_common* phy = nullptr; + srslte::log* log_h = nullptr; - srslte_cell_t cell; - srslte_dl_sf_cfg_t sf_cfg_dl; - srslte_ul_sf_cfg_t sf_cfg_ul; + srslte_cell_t cell = {}; + srslte_dl_sf_cfg_t sf_cfg_dl = {}; + srslte_ul_sf_cfg_t sf_cfg_ul = {}; - uint32_t cc_idx; - bool pregen_enabled; - bool cell_initiated; - cf_t* signal_buffer_rx[SRSLTE_MAX_PORTS]; - cf_t* signal_buffer_tx[SRSLTE_MAX_PORTS]; + uint32_t cc_idx = 0; + bool pregen_enabled = false; + bool cell_initiated = false; + cf_t* signal_buffer_rx[SRSLTE_MAX_PORTS] = {}; + cf_t* signal_buffer_tx[SRSLTE_MAX_PORTS] = {}; /* Objects for DL */ - srslte_ue_dl_t ue_dl; - srslte_ue_dl_cfg_t ue_dl_cfg; - srslte_pmch_cfg_t pmch_cfg; + srslte_ue_dl_t ue_dl = {}; + srslte_ue_dl_cfg_t ue_dl_cfg = {}; + srslte_pmch_cfg_t pmch_cfg = {}; - srslte_chest_dl_cfg_t chest_mbsfn_cfg; - srslte_chest_dl_cfg_t chest_default_cfg; + srslte_chest_dl_cfg_t chest_mbsfn_cfg = {}; + srslte_chest_dl_cfg_t chest_default_cfg = {}; /* Objects for UL */ - srslte_ue_ul_t ue_ul; - srslte_ue_ul_cfg_t ue_ul_cfg; + srslte_ue_ul_t ue_ul = {}; + srslte_ue_ul_cfg_t ue_ul_cfg = {}; // Metrics - dl_metrics_t dl_metrics; - ul_metrics_t ul_metrics; + dl_metrics_t dl_metrics = {}; + ul_metrics_t ul_metrics = {}; }; } // namespace srsue diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 0f906b1b6..3ba0588b0 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -107,12 +107,12 @@ public: void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti) final; /* Get/Set PHY parameters interface from RRC */ - void set_config(phy_cfg_t* phy_cfg) final; - void set_config_scell(asn1::rrc::scell_to_add_mod_r10_s* scell_config) final; - void set_config_tdd(asn1::rrc::tdd_cfg_s* tdd) final; - void set_config_mbsfn_sib2(asn1::rrc::sib_type2_s* sib2) final; - void set_config_mbsfn_sib13(asn1::rrc::sib_type13_r9_s* sib13) final; - void set_config_mbsfn_mcch(asn1::rrc::mcch_msg_s* mcch) final; + void set_config(srslte::phy_cfg_t& config, uint32_t cc_idx, uint32_t earfcn, srslte_cell_t* cell_info) final; + void set_config_tdd(srslte_tdd_config_t& tdd_config) final; + + void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) final; + void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) final; + void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) final; /*Set MAC->PHY MCH period stopping point*/ void set_mch_period_stop(uint32_t stop) final; @@ -142,7 +142,7 @@ private: const static int SF_RECV_THREAD_PRIO = 1; const static int WORKERS_THREAD_PRIO = 2; - srslte::radio_interface_phy* radio = nullptr; + srslte::radio_interface_phy* radio = nullptr; std::vector > log_vec; srslte::logger* logger = nullptr; @@ -160,8 +160,8 @@ private: srslte_prach_cfg_t prach_cfg = {}; srslte_tdd_config_t tdd_config = {}; - phy_interface_rrc_lte::phy_cfg_t config = {}; - phy_args_t args = {}; + srslte::phy_cfg_t config = {}; + phy_args_t args = {}; /* Current time advance */ uint32_t n_ta = 0; diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index 89714ab29..a96eebc0a 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -22,8 +22,6 @@ #ifndef SRSUE_PHCH_COMMON_H #define SRSUE_PHCH_COMMON_H -#define TX_MODE_CONTINUOUS 1 - #include "phy_metrics.h" #include "srslte/common/gen_mch_tables.h" #include "srslte/common/log.h" @@ -31,7 +29,8 @@ #include "srslte/interfaces/ue_interfaces.h" #include "srslte/radio/radio.h" #include "srslte/srslte.h" -#include +#include +#include #include #include #include @@ -53,30 +52,23 @@ class phy_common { public: /* Common variables used by all phy workers */ - phy_args_t* args; - stack_interface_phy_lte* stack; + phy_args_t* args = nullptr; + stack_interface_phy_lte* stack = nullptr; - phy_interface_rrc_lte::phy_cfg_mbsfn_t mbsfn_config; + srslte::phy_cfg_mbsfn_t mbsfn_config = {}; /* Power control variables */ - float pathloss[SRSLTE_MAX_CARRIERS]; - float cur_pathloss; - float p0_preamble; - float cur_radio_power; - float cur_pusch_power; - float avg_rsrp[SRSLTE_MAX_CARRIERS]; - float avg_rsrp_dbm[SRSLTE_MAX_CARRIERS]; - float avg_rsrq_db; - float avg_rssi_dbm; - float rx_gain_offset; - float avg_snr_db_cqi[SRSLTE_MAX_CARRIERS]; - float avg_snr_db_sync; - - float avg_noise[SRSLTE_MAX_CARRIERS]; - bool pcell_meas_enabled; - - uint32_t pcell_report_period; - bool pcell_first_measurement; + float pathloss[SRSLTE_MAX_CARRIERS] = {}; + float cur_pathloss = 0.0f; + float cur_pusch_power = 0.0f; + float avg_rsrp[SRSLTE_MAX_CARRIERS] = {}; + float avg_rsrp_dbm[SRSLTE_MAX_CARRIERS] = {}; + float avg_rsrq_db = 0.0f; + float avg_rssi_dbm = 0.0f; + float rx_gain_offset = 0.0f; + float avg_snr_db_cqi[SRSLTE_MAX_CARRIERS] = {}; + float avg_noise[SRSLTE_MAX_CARRIERS] = {}; + uint32_t pcell_report_period = 0; // SCell EARFCN, PCI, configured and enabled list typedef struct { @@ -87,17 +79,13 @@ public: } scell_cfg_t; scell_cfg_t scell_cfg[SRSLTE_MAX_CARRIERS]; - bool multiple_csi_request_enabled; /* True means cross scheduling enabled */ - bool cif_enabled; /* True means cross scheduling enabled */ - bool srs_request_enabled; - // Save last TBS for uplink (mcs >= 28) - srslte_ra_tb_t last_ul_tb[SRSLTE_MAX_HARQ_PROC][SRSLTE_MAX_CARRIERS]; + srslte_ra_tb_t last_ul_tb[SRSLTE_MAX_HARQ_PROC][SRSLTE_MAX_CARRIERS] = {}; // Save last TBS for DL (Format1C) - int last_dl_tbs[SRSLTE_MAX_HARQ_PROC][SRSLTE_MAX_CARRIERS][SRSLTE_MAX_CODEWORDS]; + int last_dl_tbs[SRSLTE_MAX_HARQ_PROC][SRSLTE_MAX_CARRIERS][SRSLTE_MAX_CODEWORDS] = {}; - phy_common(uint32_t max_workers); + explicit phy_common(uint32_t max_workers); ~phy_common(); @@ -112,6 +100,9 @@ public: void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti, srslte_tdd_config_t tdd_config); + void set_dl_pending_grant(uint32_t tti, uint32_t cc_idx, uint32_t grant_cc_idx, const srslte_dci_dl_t* dl_dci); + bool get_dl_pending_grant(uint32_t tti, uint32_t cc_idx, uint32_t* grant_cc_idx, srslte_dci_dl_t* dl_dci); + void set_ul_pending_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, srslte_phich_grant_t phich_grant, @@ -143,24 +134,23 @@ public: uint32_t nof_samples[SRSLTE_MAX_RADIOS], srslte_timestamp_t tx_time[SRSLTE_MAX_RADIOS]); + void set_cell(const srslte_cell_t& c); void set_nof_workers(uint32_t nof_workers); - bool sr_enabled; - int sr_last_tx_tti; + bool sr_enabled = false; + int sr_last_tx_tti = -1; srslte::radio_interface_phy* get_radio(); - void set_cell(const srslte_cell_t& c); - uint32_t get_nof_prb(); - - void set_dl_metrics(const dl_metrics_t m, uint32_t cc_idx); + void set_dl_metrics(dl_metrics_t m, uint32_t cc_idx); void get_dl_metrics(dl_metrics_t m[SRSLTE_MAX_CARRIERS]); - void set_ul_metrics(const ul_metrics_t m, uint32_t cc_idx); + void set_ul_metrics(ul_metrics_t m, uint32_t cc_idx); void get_ul_metrics(ul_metrics_t m[SRSLTE_MAX_CARRIERS]); void set_sync_metrics(const uint32_t& cc_idx, const sync_metrics_t& m); void get_sync_metrics(sync_metrics_t m[SRSLTE_MAX_CARRIERS]); void reset(); + void reset_radio(); /* SCell Management */ void enable_scell(uint32_t cc_idx, bool enable); @@ -172,75 +162,84 @@ public: void set_mch_period_stop(uint32_t stop); private: - bool have_mtch_stop; - pthread_mutex_t mtch_mutex; - pthread_cond_t mtch_cvar; + bool have_mtch_stop = false; + std::mutex mtch_mutex; + std::condition_variable mtch_cvar; std::vector tx_sem; - uint32_t nof_workers; - uint32_t max_workers; + uint32_t nof_workers = 0; + uint32_t max_workers = 0; - bool is_first_of_burst[SRSLTE_MAX_RADIOS]; - srslte::radio_interface_phy* radio_h; - float cfo; - srslte::log* log_h; - srslte::channel_ptr ul_channel = nullptr; + bool is_pending_tx_end = false; - int rar_grant_tti; + srslte::radio_interface_phy* radio_h = nullptr; + float cfo = 0.0f; + srslte::log* log_h = nullptr; + srslte::channel_ptr ul_channel = nullptr; + + int rar_grant_tti = -1; typedef struct { bool enable; srslte_phich_grant_t phich_grant; srslte_dci_ul_t dci_ul; } pending_ul_ack_t; - pending_ul_ack_t pending_ul_ack[TTIMOD_SZ][SRSLTE_MAX_CARRIERS][2]; - pthread_mutex_t pending_ul_ack_mutex; + pending_ul_ack_t pending_ul_ack[TTIMOD_SZ][SRSLTE_MAX_CARRIERS][2] = {}; + std::mutex pending_ul_ack_mutex; typedef struct { bool hi_value; bool hi_present; srslte_dci_ul_t dci_ul; } received_ul_ack_t; - received_ul_ack_t received_ul_ack[TTIMOD_SZ][SRSLTE_MAX_CARRIERS]; - pthread_mutex_t received_ul_ack_mutex; + received_ul_ack_t received_ul_ack[TTIMOD_SZ][SRSLTE_MAX_CARRIERS] = {}; + std::mutex received_ul_ack_mutex; typedef struct { bool enable; uint32_t pid; srslte_dci_ul_t dci; } pending_ul_grant_t; - pending_ul_grant_t pending_ul_grant[TTIMOD_SZ][SRSLTE_MAX_CARRIERS]; - pthread_mutex_t pending_ul_grant_mutex; + pending_ul_grant_t pending_ul_grant[TTIMOD_SZ][SRSLTE_MAX_CARRIERS] = {}; + std::mutex pending_ul_grant_mutex; typedef struct { bool enable; uint8_t value[SRSLTE_MAX_CODEWORDS]; // 0/1 or 2 for DTX srslte_pdsch_ack_resource_t resource; } received_ack_t; - received_ack_t pending_dl_ack[TTIMOD_SZ][SRSLTE_MAX_CARRIERS]; - uint32_t pending_dl_dai[TTIMOD_SZ][SRSLTE_MAX_CARRIERS]; - pthread_mutex_t pending_dl_ack_mutex; + received_ack_t pending_dl_ack[TTIMOD_SZ][SRSLTE_MAX_CARRIERS] = {}; + uint32_t pending_dl_dai[TTIMOD_SZ][SRSLTE_MAX_CARRIERS] = {}; + std::mutex pending_dl_ack_mutex; + + // Cross-carried grants scheduled from PCell + typedef struct { + bool enable; + uint32_t grant_cc_idx; + srslte_dci_dl_t dl_dci; + } pending_dl_grant_t; + pending_dl_grant_t pending_dl_grant[FDD_HARQ_DELAY_MS][SRSLTE_MAX_CARRIERS] = {}; - bool is_first_tx; + bool is_first_tx = true; - srslte_cell_t cell; + srslte_cell_t cell = {}; - dl_metrics_t dl_metrics[SRSLTE_MAX_CARRIERS]; - uint32_t dl_metrics_count; - bool dl_metrics_read; - ul_metrics_t ul_metrics[SRSLTE_MAX_CARRIERS]; - uint32_t ul_metrics_count; - bool ul_metrics_read; - sync_metrics_t sync_metrics[SRSLTE_MAX_CARRIERS]; - uint32_t sync_metrics_count; - bool sync_metrics_read; + dl_metrics_t dl_metrics[SRSLTE_MAX_CARRIERS] = {}; + uint32_t dl_metrics_count = 0; + bool dl_metrics_read = true; + ul_metrics_t ul_metrics[SRSLTE_MAX_CARRIERS] = {}; + uint32_t ul_metrics_count = 0; + bool ul_metrics_read = true; + sync_metrics_t sync_metrics[SRSLTE_MAX_CARRIERS] = {}; + uint32_t sync_metrics_count = 0; + bool sync_metrics_read = true; // MBSFN - bool sib13_configured; - bool mcch_configured; - uint32_t mch_period_stop; - uint8_t mch_table[40]; - uint8_t mcch_table[10]; + bool sib13_configured = false; + bool mcch_configured = false; + uint32_t mch_period_stop = 0; + uint8_t mch_table[40] = {}; + uint8_t mcch_table[10] = {}; bool is_mch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti); diff --git a/srsue/hdr/phy/scell/intra_measure.h b/srsue/hdr/phy/scell/intra_measure.h index 66564ac00..4282e04c7 100644 --- a/srsue/hdr/phy/scell/intra_measure.h +++ b/srsue/hdr/phy/scell/intra_measure.h @@ -50,27 +50,29 @@ private: void run_thread(); const static int INTRA_FREQ_MEAS_PRIO = DEFAULT_PRIORITY + 5; - scell_recv scell; - rrc_interface_phy_lte* rrc; - srslte::log* log_h; - phy_common* common; - uint32_t current_earfcn; - uint32_t current_sflen; - srslte_cell_t primary_cell; + scell_recv scell = {}; + rrc_interface_phy_lte* rrc = nullptr; + srslte::log* log_h = nullptr; + phy_common* common = nullptr; + uint32_t current_earfcn = 0; + uint32_t current_sflen = 0; + srslte_cell_t primary_cell = {}; std::vector active_pci; srslte::tti_sync_cv tti_sync; - cf_t* search_buffer; + cf_t* search_buffer = nullptr; - scell_recv::cell_info_t info[scell_recv::MAX_CELLS]; + scell_recv::cell_info_t info[scell_recv::MAX_CELLS] = {}; - bool running; - bool receive_enabled; - bool receiving; - uint32_t measure_tti; - uint32_t receive_cnt; - srslte_ringbuffer_t ring_buffer; + bool running = false; + bool receive_enabled = false; + bool receiving = false; + uint32_t measure_tti = 0; + uint32_t receive_cnt = 0; + srslte_ringbuffer_t ring_buffer = {}; + + srslte_refsignal_dl_sync_t refsignal_dl_sync = {}; }; } // namespace scell diff --git a/srsue/hdr/phy/scell/measure.h b/srsue/hdr/phy/scell/measure.h index 310b21dcd..287306d08 100644 --- a/srsue/hdr/phy/scell/measure.h +++ b/srsue/hdr/phy/scell/measure.h @@ -51,6 +51,7 @@ public: float rsrp(); float rsrq(); float snr(); + float cfo(); uint32_t frame_st_idx(); void set_rx_gain_offset(float rx_gain_offset); @@ -63,7 +64,7 @@ private: uint32_t nof_subframes; uint32_t current_prb; float rx_gain_offset; - float mean_rsrp, mean_rsrq, mean_snr, mean_rssi; + float mean_rsrp, mean_rsrq, mean_snr, mean_rssi, mean_cfo; uint32_t final_offset; const static int RSRP_MEASURE_NOF_FRAMES = 5; }; diff --git a/srsue/hdr/phy/sf_worker.h b/srsue/hdr/phy/sf_worker.h index 77bd39082..8ba4e31c3 100644 --- a/srsue/hdr/phy/sf_worker.h +++ b/srsue/hdr/phy/sf_worker.h @@ -56,8 +56,7 @@ public: void set_cfo(const uint32_t& cc_idx, float cfo); void set_tdd_config(srslte_tdd_config_t config); - void set_pcell_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg); - void set_scell_config(uint32_t cc_idx, asn1::rrc::scell_to_add_mod_r10_s* scell_config); + void set_config(uint32_t cc_idx, srslte::phy_cfg_t& phy_cfg); void set_crnti(uint16_t rnti); void enable_pregen_signals(bool enabled); @@ -79,35 +78,37 @@ public: private: /* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */ - void work_imp(); - void reset_(); + void work_imp() final; void update_measurements(); void reset_uci(srslte_uci_data_t* uci_data); std::vector cc_workers; - phy_common* phy; - srslte::log* log_h; - srslte::log* log_phy_lib_h; - chest_feedback_itf* chest_loop; + phy_common* phy = nullptr; + ; + srslte::log* log_h = nullptr; + ; + srslte::log* log_phy_lib_h = nullptr; + ; + chest_feedback_itf* chest_loop = nullptr; - pthread_mutex_t mutex; + std::mutex mutex; - srslte_cell_t cell; - srslte_tdd_config_t tdd_config; + srslte_cell_t cell = {}; + srslte_tdd_config_t tdd_config = {}; - bool cell_initiated; + bool cell_initiated = false; - cf_t* prach_ptr; - float prach_power; + cf_t* prach_ptr = nullptr; + float prach_power = 0; - uint32_t tti; - srslte_timestamp_t tx_time[SRSLTE_MAX_RADIOS]; - uint32_t tx_sem_id; - int next_offset[SRSLTE_MAX_RADIOS]; + uint32_t tti = 0; + uint32_t tx_sem_id = 0; + srslte_timestamp_t tx_time[SRSLTE_MAX_RADIOS] = {}; + int next_offset[SRSLTE_MAX_RADIOS] = {}; - uint32_t rssi_read_cnt; + uint32_t rssi_read_cnt = 0; }; } // namespace srsue diff --git a/srsue/hdr/phy/sync.h b/srsue/hdr/phy/sync.h index 40be6b405..8e69416b8 100644 --- a/srsue/hdr/phy/sync.h +++ b/srsue/hdr/phy/sync.h @@ -104,7 +104,7 @@ private: void reset(); float get_last_cfo(); void set_agc_enable(bool enable); - ret_code run(srslte_cell_t* cell); + ret_code run(srslte_cell_t* cell, std::array& bch_payload); private: sync* p = nullptr; @@ -128,9 +128,15 @@ private: uint32_t nof_subframes = SFN_SYNC_NOF_SUBFRAMES); void reset(); bool set_cell(srslte_cell_t cell); - ret_code run_subframe(srslte_cell_t* cell, uint32_t* tti_cnt, bool sfidx_only = false); - ret_code - decode_mib(srslte_cell_t* cell, uint32_t* tti_cnt, cf_t* ext_buffer[SRSLTE_MAX_PORTS], bool sfidx_only = false); + ret_code run_subframe(srslte_cell_t* cell, + uint32_t* tti_cnt, + std::array& bch_payload, + bool sfidx_only = false); + ret_code decode_mib(srslte_cell_t* cell, + uint32_t* tti_cnt, + cf_t* ext_buffer[SRSLTE_MAX_PORTS], + std::array& bch_payload, + bool sfidx_only = false); private: const static int SFN_SYNC_NOF_SUBFRAMES = 100; @@ -215,7 +221,7 @@ private: */ state_t run_state() { - std::lock_guard lg(inside); + std::lock_guard lock(inside); cur_state = next_state; if (state_setting) { state_setting = false; @@ -228,7 +234,7 @@ private: // Called by the main thread at the end of each state to indicate it has finished. void state_exit(bool exit_ok = true) { - std::lock_guard lg(inside); + std::lock_guard lock(inside); if (cur_state == SFN_SYNC && exit_ok == true) { next_state = CAMPING; } else { @@ -239,7 +245,7 @@ private: } void force_sfn_sync() { - std::lock_guard lg(inside); + std::lock_guard lock(inside); next_state = SFN_SYNC; } @@ -250,19 +256,19 @@ private: */ void go_idle() { - std::lock_guard lg(outside); + std::lock_guard lock(outside); go_state(IDLE); } void run_cell_search() { - std::lock_guard lg(outside); + std::lock_guard lock(outside); go_state(CELL_SEARCH); wait_state_run(); wait_state_next(); } void run_sfn_sync() { - std::lock_guard lg(outside); + std::lock_guard lock(outside); go_state(SFN_SYNC); wait_state_run(); wait_state_next(); @@ -342,6 +348,7 @@ private: float time_adv_sec = 0; float next_time_adv_sec = 0; uint32_t tti = 0; + std::array mib; uint32_t tx_worker_cnt = 0; uint32_t nof_workers = 0; diff --git a/srsue/hdr/phy/ue_lte_phy_base.h b/srsue/hdr/phy/ue_lte_phy_base.h index b1b6005db..1c5ce809f 100644 --- a/srsue/hdr/phy/ue_lte_phy_base.h +++ b/srsue/hdr/phy/ue_lte_phy_base.h @@ -28,6 +28,7 @@ #define SRSUE_UE_LTE_PHY_BASE_H #include "srslte/common/log_filter.h" +#include "srslte/interfaces/common_interfaces.h" #include "srsue/hdr/phy/ue_phy_base.h" namespace srsue { diff --git a/srsue/hdr/stack/mac/mac.h b/srsue/hdr/stack/mac/mac.h index 18e373453..48697d463 100644 --- a/srsue/hdr/stack/mac/mac.h +++ b/srsue/hdr/stack/mac/mac.h @@ -51,7 +51,11 @@ class mac : public mac_interface_phy_lte, public: mac(srslte::log* log_); ~mac(); - bool init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc); + bool init(phy_interface_mac_lte* phy, + rlc_interface_mac* rlc, + rrc_interface_mac* rrc, + srslte::timers* timers_, + stack_interface_mac* stack); void stop(); void get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS]); @@ -95,9 +99,13 @@ public: void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask); void start_cont_ho(); - void get_rntis(ue_rnti_t *rntis); + void get_rntis(ue_rnti_t* rntis); void set_ho_rnti(uint16_t crnti, uint16_t target_pci); + /*********** interface for stack ******************/ + void process_pdus(); + void notify_ra_completed(); + void start_pcap(srslte::mac_pcap* pcap); // Timer callback interface @@ -118,11 +126,12 @@ private: static const int MAC_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD static const int MAC_PDU_THREAD_PRIO = 5; - // Interaction with PHY - phy_interface_mac_lte *phy_h; - rlc_interface_mac *rlc_h; - rrc_interface_mac *rrc_h; - srslte::log *log_h; + // Interaction with PHY + phy_interface_mac_lte* phy_h = nullptr; + rlc_interface_mac* rlc_h = nullptr; + rrc_interface_mac* rrc_h = nullptr; + stack_interface_mac* stack_h = nullptr; + srslte::log* log_h; mac_interface_phy_lte::mac_phy_cfg_mbsfn_t phy_mbsfn_cfg; // RNTI search window scheduling @@ -163,7 +172,7 @@ private: uint32_t timer_alignment = 0; void setup_timers(int time_alignment_timer); void timer_alignment_expire(); - srslte::timers timers; + srslte::timers* timers = nullptr; // pointer to MAC PCAP object srslte::mac_pcap* pcap = nullptr; @@ -172,23 +181,6 @@ private: mac_metrics_t metrics[SRSLTE_MAX_CARRIERS] = {}; bool initialized = false; - - /* Class to process MAC PDUs from DEMUX unit */ - class pdu_process : public thread { - public: - explicit pdu_process(demux* demux_unit); - ~pdu_process(); - void notify(); - void stop(); - private: - void run_thread() final; - bool running = false; - bool have_data = false; - std::mutex mutex; - std::condition_variable cvar; - demux* demux_unit = nullptr; - }; - pdu_process pdu_process_thread; }; } // namespace srsue diff --git a/srsue/hdr/stack/mac/proc_bsr.h b/srsue/hdr/stack/mac/proc_bsr.h index 9e4281717..d6231a55e 100644 --- a/srsue/hdr/stack/mac/proc_bsr.h +++ b/srsue/hdr/stack/mac/proc_bsr.h @@ -33,6 +33,24 @@ namespace srsue { +// BSR interface for MUX +class bsr_interface_mux +{ +public: + typedef enum { LONG_BSR, SHORT_BSR, TRUNC_BSR } bsr_format_t; + + typedef struct { + bsr_format_t format; + uint32_t buff_size[4]; + } bsr_t; + + /* MUX calls BSR to check if it can fit a BSR into PDU */ + virtual bool need_to_send_bsr_on_ul_grant(uint32_t grant_size, bsr_t* bsr) = 0; + + /* MUX calls BSR to let it generate a padding BSR if there is space in PDU */ + virtual bool generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t* bsr) = 0; +}; + class bsr_proc : public srslte::timer_callback, public bsr_interface_mux { public: @@ -40,7 +58,7 @@ public: void init(rlc_interface_mac* rlc, srslte::log* log_h, srslte::timers* timers_db); void step(uint32_t tti); void reset(); - void set_config(mac_interface_rrc::bsr_cfg_t& bsr_cfg); + void set_config(srslte::bsr_cfg_t& bsr_cfg); void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority); void timer_expired(uint32_t timer_id); @@ -60,7 +78,7 @@ private: srslte::log *log_h; rlc_interface_mac *rlc; - mac_interface_rrc::bsr_cfg_t bsr_cfg; + srslte::bsr_cfg_t bsr_cfg; bool initiated; @@ -74,7 +92,7 @@ private: std::map lcgs[NOF_LCG]; // groups LCID in LCG - uint32_t find_max_priority_lcg(); + uint32_t find_max_priority_lcg_with_data(); typedef enum {NONE, REGULAR, PADDING, PERIODIC} triggered_bsr_type_t; triggered_bsr_type_t triggered_bsr_type; diff --git a/srsue/hdr/stack/mac/proc_phr.h b/srsue/hdr/stack/mac/proc_phr.h index 0ed5aa939..2804ee304 100644 --- a/srsue/hdr/stack/mac/proc_phr.h +++ b/srsue/hdr/stack/mac/proc_phr.h @@ -38,7 +38,7 @@ class phr_proc : public srslte::timer_callback public: phr_proc(); void init(phy_interface_mac_lte* phy_h, srslte::log* log_h_, srslte::timers* timers_db_); - void set_config(mac_interface_rrc::phr_cfg_t& cfg); + void set_config(srslte::phr_cfg_t& cfg); void step(uint32_t tti); void reset(); @@ -55,7 +55,7 @@ private: srslte::log* log_h; phy_interface_mac_lte* phy_h; srslte::timers* timers_db; - mac_interface_rrc::phr_cfg_t phr_cfg; + srslte::phr_cfg_t phr_cfg; bool initiated; int last_pathloss_db; bool phr_is_triggered; diff --git a/srsue/hdr/stack/mac/proc_ra.h b/srsue/hdr/stack/mac/proc_ra.h index e985e9436..b4ca0af2b 100644 --- a/srsue/hdr/stack/mac/proc_ra.h +++ b/srsue/hdr/stack/mac/proc_ra.h @@ -75,11 +75,12 @@ public: mac_interface_rrc::ue_rnti_t* rntis, srslte::timers::timer* time_alignment_timer_, srslte::timers::timer* contention_resolution_timer_, - mux* mux_unit); + mux* mux_unit, + stack_interface_mac* stack_); void reset(); - void set_config(mac_interface_rrc::rach_cfg_t& rach_cfg); + void set_config(srslte::rach_cfg_t& rach_cfg); void start_pdcch_order(); void start_mac_order(uint32_t msg_len_bits = 56, bool is_ho = false); @@ -92,12 +93,14 @@ public: void pdcch_to_crnti(bool is_new_uplink_transmission); void timer_expired(uint32_t timer_id); void new_grant_dl(mac_interface_phy_lte::mac_grant_dl_t grant, mac_interface_phy_lte::tb_action_dl_t* action); - void tb_decoded_ok(); + void tb_decoded_ok(const uint32_t tti); void start_noncont(uint32_t preamble_index, uint32_t prach_mask); bool contention_resolution_id_received(uint64_t uecri); void start_pcap(srslte::mac_pcap* pcap); + void notify_ra_completed(); + private: void state_pdcch_setup(); void state_response_reception(uint32_t tti); @@ -118,7 +121,7 @@ private: srslte::rar_pdu rar_pdu_msg; // Random Access parameters provided by higher layers defined in 5.1.1 - mac_interface_rrc::rach_cfg_t rach_cfg, new_cfg; + srslte::rach_cfg_t rach_cfg, new_cfg; int delta_preamble_db; uint32_t maskIndex; @@ -143,7 +146,15 @@ private: srslte_softbuffer_rx_t softbuffer_rar; - enum { IDLE = 0, PDCCH_SETUP, RESPONSE_RECEPTION, BACKOFF_WAIT, CONTENTION_RESOLUTION, COMPLETITION } state; + enum { + IDLE = 0, + PDCCH_SETUP, + RESPONSE_RECEPTION, + BACKOFF_WAIT, + CONTENTION_RESOLUTION, + START_WAIT_COMPLETION, + WAITING_COMPLETION + } state; typedef enum { RA_GROUP_A, RA_GROUP_B } ra_group_t; @@ -155,12 +166,13 @@ private: phy_interface_mac_lte* phy_h; srslte::log* log_h; - mux *mux_unit; - srslte::mac_pcap *pcap; - rrc_interface_mac *rrc; + mux* mux_unit; + srslte::mac_pcap* pcap; + rrc_interface_mac* rrc; + stack_interface_mac* stack; - srslte::timers::timer *time_alignment_timer; - srslte::timers::timer *contention_resolution_timer; + srslte::timers::timer* time_alignment_timer; + srslte::timers::timer* contention_resolution_timer; mac_interface_rrc::ue_rnti_t *rntis; diff --git a/srsue/hdr/stack/mac/proc_sr.h b/srsue/hdr/stack/mac/proc_sr.h index bbdf9e7aa..4a6fe4dd0 100644 --- a/srsue/hdr/stack/mac/proc_sr.h +++ b/srsue/hdr/stack/mac/proc_sr.h @@ -37,7 +37,7 @@ public: sr_proc(); void init(phy_interface_mac_lte* phy_h, rrc_interface_mac* rrc, srslte::log* log_h); void step(uint32_t tti); - void set_config(mac_interface_rrc::sr_cfg_t& cfg); + void set_config(srslte::sr_cfg_t& cfg); void reset(); void start(); bool need_random_access(); @@ -48,7 +48,7 @@ private: int sr_counter; bool is_pending_sr; - mac_interface_rrc::sr_cfg_t sr_cfg; + srslte::sr_cfg_t sr_cfg; rrc_interface_mac *rrc; phy_interface_mac_lte* phy_h; diff --git a/srsue/hdr/stack/mac/ul_harq.h b/srsue/hdr/stack/mac/ul_harq.h index 73681d42e..f422cb11d 100644 --- a/srsue/hdr/stack/mac/ul_harq.h +++ b/srsue/hdr/stack/mac/ul_harq.h @@ -48,7 +48,7 @@ public: void reset(); void reset_ndi(); - void set_config(mac_interface_rrc_common::ul_harq_cfg_t& harq_cfg); + void set_config(srslte::ul_harq_cfg_t& harq_cfg); void start_pcap(srslte::mac_pcap* pcap_); @@ -112,7 +112,7 @@ private: srslte::log* log_h; mac_interface_rrc_common::ue_rnti_t* rntis; - mac_interface_rrc_common::ul_harq_cfg_t harq_cfg; + srslte::ul_harq_cfg_t harq_cfg; float average_retx; uint64_t nof_pkts; diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index faaa60cb1..c4687291b 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -26,6 +26,7 @@ #include "rrc_common.h" #include "rrc_metrics.h" +#include "srslte/asn1/rrc_asn1.h" #include "srslte/asn1/rrc_asn1_utils.h" #include "srslte/common/bcd_helpers.h" #include "srslte/common/block_queue.h" @@ -33,11 +34,12 @@ #include "srslte/common/common.h" #include "srslte/common/log.h" #include "srslte/common/security.h" +#include "srslte/common/stack_procedure.h" #include "srslte/common/threads.h" #include "srslte/interfaces/ue_interfaces.h" -#include #include +#include #include #define SRSLTE_RRC_N_BANDS 43 @@ -183,6 +185,7 @@ class cell_t has_valid_sib13 = true; } + // TODO: replace with TTI count uint32_t timeout_secs(struct timeval now) { struct timeval t[3]; memcpy(&t[2], &now, sizeof(struct timeval)); @@ -282,22 +285,22 @@ class rrc : public rrc_interface_nas, public rrc_interface_mac, public rrc_interface_pdcp, public rrc_interface_rlc, - public srslte::timer_callback, - public thread + public srslte::timer_callback { public: rrc(srslte::log* rrc_log_); ~rrc(); - void init(phy_interface_rrc_lte* phy_, - mac_interface_rrc* mac_, - rlc_interface_rrc* rlc_, - pdcp_interface_rrc* pdcp_, - nas_interface_rrc* nas_, - usim_interface_rrc* usim_, - gw_interface_rrc* gw_, - srslte::mac_interface_timers* mac_timers_, - const rrc_args_t& args_); + void init(phy_interface_rrc_lte* phy_, + mac_interface_rrc* mac_, + rlc_interface_rrc* rlc_, + pdcp_interface_rrc* pdcp_, + nas_interface_rrc* nas_, + usim_interface_rrc* usim_, + gw_interface_rrc* gw_, + srslte::timers* timers_, + stack_interface_rrc* stack_, + const rrc_args_t& args_); void stop(); @@ -319,10 +322,11 @@ public: void enable_capabilities(); uint16_t get_mcc(); uint16_t get_mnc(); - int plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]); + bool plmn_search() final; void plmn_select(srslte::plmn_id_t plmn_id); bool connection_request(srslte::establishment_cause_t cause, srslte::unique_byte_buffer_t dedicated_info_nas); void set_ue_identity(srslte::s_tmsi_t s_tmsi); + void paging_completed(bool outcome) final; // PHY interface void in_sync(); @@ -346,17 +350,19 @@ public: void write_pdu_pcch(srslte::unique_byte_buffer_t pdu); void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu); -private: + // STACK interface + void cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, + const phy_interface_rrc_lte::phy_cell_t& found_cell); +private: typedef struct { - enum { PDU, PCCH, STOP, MBMS_START } command; + enum { PDU, PCCH, PDU_MCH, RLF, PDU_BCCH_DLSCH, STOP } command; srslte::unique_byte_buffer_t pdu; uint16_t lcid; } cmd_msg_t; bool running = false; srslte::block_queue cmd_q; - void run_thread(); void process_pcch(srslte::unique_byte_buffer_t pdu); @@ -369,6 +375,7 @@ private: nas_interface_rrc* nas = nullptr; usim_interface_rrc* usim = nullptr; gw_interface_rrc* gw = nullptr; + stack_interface_rrc* stack = nullptr; srslte::unique_byte_buffer_t dedicated_info_nas; @@ -377,8 +384,6 @@ private: srslte::bit_buffer_t bit_buf; - pthread_mutex_t mutex; - rrc_state_t state, last_state = RRC_STATE_IDLE; uint8_t transaction_id = 0; srslte::s_tmsi_t ue_identity; @@ -392,8 +397,8 @@ private: uint16_t ho_src_rnti = 0; cell_t ho_src_cell = {}; - phy_interface_rrc_lte::phy_cfg_t current_phy_cfg, previous_phy_cfg = {}; - mac_interface_rrc::mac_cfg_t current_mac_cfg, previous_mac_cfg = {}; + srslte::phy_cfg_t current_phy_cfg, previous_phy_cfg = {}; + srslte::mac_cfg_t current_mac_cfg, previous_mac_cfg = {}; bool pending_mob_reconf = false; asn1::rrc::rrc_conn_recfg_s mob_reconf = {}; @@ -409,10 +414,10 @@ private: std::map drbs; // RRC constants and timers - srslte::mac_interface_timers* mac_timers = nullptr; - uint32_t n310_cnt, N310 = 0; - uint32_t n311_cnt, N311 = 0; - uint32_t t300, t301, t302, t310, t311, t304 = 0; + srslte::timers* timers = nullptr; + uint32_t n310_cnt, N310 = 0; + uint32_t n311_cnt, N311 = 0; + uint32_t t300, t301, t302, t310, t311, t304 = 0; // Radio bearers typedef enum{ @@ -444,37 +449,30 @@ private: // List of strongest neighbour cell const static int NEIGHBOUR_TIMEOUT = 5; const static int NOF_NEIGHBOUR_CELLS = 8; - std::vector neighbour_cells; - cell_t* serving_cell = nullptr; + + typedef std::unique_ptr unique_cell_t; + std::vector neighbour_cells; + unique_cell_t serving_cell = nullptr; void set_serving_cell(uint32_t cell_idx); - void set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell); + void set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell); + unique_cell_t remove_neighbour_cell(const uint32_t earfcn, const uint32_t pci); + cell_t* get_neighbour_cell_handle(const uint32_t earfcn, const uint32_t pci); + bool has_neighbour_cell(const uint32_t earfcn, const uint32_t pci); int find_neighbour_cell(uint32_t earfcn, uint32_t pci); bool add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp); bool add_neighbour_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, float rsrp); - bool add_neighbour_cell(cell_t *cell); + bool add_neighbour_cell(unique_cell_t new_cell); void sort_neighbour_cells(); void clean_neighbours(); - std::vector::iterator delete_neighbour(std::vector::iterator it); - void delete_neighbour(uint32_t cell_idx); - - bool configure_serving_cell(); - - bool si_acquire(uint32_t index); - uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf); - const static int SIB_SEARCH_TIMEOUT_MS = 1000; + void delete_last_neighbour(); bool initiated = false; - bool ho_start = false; - bool go_idle = false; - asn1::rrc::reest_cause_e m_reest_cause = {}; + asn1::rrc::reest_cause_e m_reest_cause = asn1::rrc::reest_cause_e::nulltype; uint16_t m_reest_rnti = 0; bool reestablishment_started = false; bool reestablishment_successful = false; - uint32_t rlc_flush_counter = 0; - uint32_t rlc_flush_timeout = 0; - // Measurements sub-class class rrc_meas { public: @@ -536,10 +534,10 @@ private: std::map reports_cfg; std::map active; - rrc* parent = nullptr; - srslte::log* log_h = nullptr; - phy_interface_rrc_lte* phy = nullptr; - srslte::mac_interface_timers* mac_timers = nullptr; + rrc* parent = nullptr; + srslte::log* log_h = nullptr; + phy_interface_rrc_lte* phy = nullptr; + srslte::timers* timers = nullptr; uint32_t filter_k_rsrp, filter_k_rsrq = 0; float filter_a[NOF_MEASUREMENTS] = {}; @@ -602,20 +600,38 @@ private: float get_srxlev(float Qrxlevmeas); float get_squal(float Qqualmeas); - typedef enum { - CHANGED_CELL = 0, - SAME_CELL = 1, - NO_CELL = 2 - } cs_ret_t; - - cs_ret_t cell_selection(); - bool cell_selection_criteria(float rsrp, float rsrq = 0); - void cell_reselection(float rsrp, float rsrq); - - phy_interface_rrc_lte::cell_search_ret_t cell_search(); - - srslte::plmn_id_t selected_plmn_id = {}; - bool plmn_is_selected = false; + /******************** + * RRC Procedures + *******************/ + + enum class cs_result_t { changed_cell, same_cell, no_cell }; + + // RRC procedures (fwd declared) + class cell_search_proc; + class si_acquire_proc; + class serving_cell_config_proc; + class cell_selection_proc; + class connection_request_proc; + class plmn_search_proc; + class process_pcch_proc; + class go_idle_proc; + srslte::proc_t cell_searcher; + srslte::proc_t si_acquirer; + srslte::proc_t serv_cell_cfg; + srslte::proc_t cell_selector; + srslte::proc_t idle_setter; + srslte::proc_t pcch_processor; + srslte::proc_t conn_req_proc; + srslte::proc_t plmn_searcher; + + srslte::callback_list_t callback_list; + + bool cell_selection_criteria(float rsrp, float rsrq = 0); + void cell_reselection(float rsrp, float rsrq); + + std::vector ue_required_sibs; + srslte::plmn_id_t selected_plmn_id = {}; + bool plmn_is_selected = false; bool security_is_activated = false; @@ -623,20 +639,21 @@ private: void max_retx_attempted(); // Senders - void send_con_request(asn1::rrc::establishment_cause_e cause); + void send_con_request(srslte::establishment_cause_t cause); void send_con_restablish_request(); void send_con_restablish_complete(); void send_con_setup_complete(srslte::unique_byte_buffer_t nas_msg); void send_ul_info_transfer(srslte::unique_byte_buffer_t nas_msg); void send_security_mode_complete(); void send_rrc_con_reconfig_complete(); - void send_rrc_ue_cap_info(); // Parsers void process_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void parse_dl_ccch(srslte::unique_byte_buffer_t pdu); void parse_dl_dcch(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void parse_dl_info_transfer(uint32_t lcid, srslte::unique_byte_buffer_t pdu); + void parse_pdu_bcch_dlsch(srslte::unique_byte_buffer_t pdu); + void parse_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu); // Helpers bool con_reconfig(asn1::rrc::rrc_conn_recfg_s* reconfig); @@ -644,12 +661,15 @@ private: bool con_reconfig_ho(asn1::rrc::rrc_conn_recfg_s* reconfig); bool ho_prepare(); void ho_failed(); + void start_ho(); + void start_go_idle(); void rrc_connection_release(); void radio_link_failure(); void leave_connected(); void stop_timers(); void init_con_restablish_request(asn1::rrc::reest_cause_e cause); void proc_con_restablish_request(); + void start_cell_reselection(); void log_rr_config_common(); void log_phy_config_dedicated(); @@ -659,9 +679,9 @@ private: bool apply_rr_config_dedicated(asn1::rrc::rr_cfg_ded_s* cnfg); void apply_scell_config(asn1::rrc::rrc_conn_recfg_r8_ies_s* reconfig_r8); void apply_phy_config_dedicated(const asn1::rrc::phys_cfg_ded_s& phy_cnfg); + void apply_phy_scell_config(const asn1::rrc::scell_to_add_mod_r10_s& scell_config); void apply_mac_config_dedicated_default(); - void apply_mac_config_dedicated_explicit(asn1::rrc::mac_main_cfg_s mac_cfg); void handle_sib1(); void handle_sib2(); @@ -671,6 +691,7 @@ private: void handle_con_setup(asn1::rrc::rrc_conn_setup_s* setup); void handle_con_reest(asn1::rrc::rrc_conn_reest_s* setup); void handle_rrc_con_reconfig(uint32_t lcid, asn1::rrc::rrc_conn_recfg_s* reconfig); + void handle_ue_capability_enquiry(const asn1::rrc::ue_cap_enquiry_s& enquiry); void add_srb(asn1::rrc::srb_to_add_mod_s* srb_cnfg); void add_drb(asn1::rrc::drb_to_add_mod_s* drb_cnfg); void release_drb(uint32_t drb_id); @@ -679,7 +700,6 @@ private: // Helpers for setting default values void set_phy_default_pucch_srs(); - void set_phy_config_common_default(); void set_phy_config_dedicated_default(); void set_phy_default(); void set_mac_default(); diff --git a/srsue/hdr/stack/rrc/rrc_procedures.h b/srsue/hdr/stack/rrc/rrc_procedures.h new file mode 100644 index 000000000..be3272bfa --- /dev/null +++ b/srsue/hdr/stack/rrc/rrc_procedures.h @@ -0,0 +1,210 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/common/log.h" +#include "srsue/hdr/stack/rrc/rrc.h" +#include +#include + +#ifndef SRSLTE_RRC_PROCEDURES_H +#define SRSLTE_RRC_PROCEDURES_H + +namespace srsue { + +class rrc::cell_search_proc : public srslte::proc_impl_t +{ +public: + struct cell_search_event_t { + phy_interface_rrc_lte::cell_search_ret_t cs_ret; + phy_interface_rrc_lte::phy_cell_t found_cell; + }; + enum class state_t { phy_cell_search, si_acquire }; + + srslte::proc_outcome_t init(rrc* parent_); + srslte::proc_outcome_t step() final; + srslte::proc_outcome_t trigger_event(const cell_search_event_t& event); + + phy_interface_rrc_lte::cell_search_ret_t get_cs_ret() { return search_result.cs_ret; } + static const char* name() { return "Cell Search"; } + +private: + srslte::proc_outcome_t handle_cell_found(const phy_interface_rrc_lte::phy_cell_t& new_cell); + + // conts + rrc* rrc_ptr; + srslte::log* log_h; + + // state vars + cell_search_event_t search_result; + state_t state; +}; + +class rrc::si_acquire_proc : public srslte::proc_impl_t +{ +public: + const static int SIB_SEARCH_TIMEOUT_MS = 1000; + + srslte::proc_outcome_t init(rrc* parent_, uint32_t sib_index_); + srslte::proc_outcome_t step() final; + static const char* name() { return "SI Acquire"; } + +private: + static uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf); + + // conts + rrc* rrc_ptr; + srslte::log* log_h; + + // state + uint32_t period, sched_index; + uint32_t start_tti = 0; + uint32_t sib_index = 0; + uint32_t last_win_start = 0; +}; + +class rrc::serving_cell_config_proc : public srslte::proc_impl_t +{ +public: + srslte::proc_outcome_t init(rrc* parent_, const std::vector& required_sibs_); + srslte::proc_outcome_t step() final; + static const char* name() { return "Serving Cell Configuration"; } + +private: + // consts + std::vector required_sibs; + rrc* rrc_ptr; + srslte::log* log_h; + + // state variables + enum class search_state_t { next_sib, si_acquire } search_state; + uint32_t req_idx = 0; +}; + +class rrc::cell_selection_proc : public srslte::proc_impl_t +{ +public: + srslte::proc_outcome_t init(rrc* parent_); + srslte::proc_outcome_t step() final; + void stop() final; + cs_result_t get_cs_result() { return cs_result; } + static const char* name() { return "Cell Selection"; } + +private: + srslte::proc_outcome_t step_cell_selection(); + srslte::proc_outcome_t step_cell_search(); + srslte::proc_outcome_t step_cell_config(); + + // consts + rrc* rrc_ptr; + srslte::log* log_h; + + // state variables + enum class search_state_t { cell_selection, cell_config, cell_search }; + cs_result_t cs_result; + search_state_t state; + uint32_t neigh_index; +}; + +class rrc::plmn_search_proc : public srslte::proc_impl_t +{ +public: + srslte::proc_outcome_t init(rrc* parent_); + srslte::proc_outcome_t step() final; + void stop() final; + static const char* name() { return "PLMN Search"; } + +private: + // consts + rrc* rrc_ptr; + srslte::log* log_h; + + // state variables + found_plmn_t found_plmns[MAX_FOUND_PLMNS]; + int nof_plmns; +}; + +class rrc::connection_request_proc : public srslte::proc_impl_t +{ +public: + struct cell_selection_complete { + bool is_success; + cs_result_t cs_result; + }; + + srslte::proc_outcome_t + init(rrc* parent_, srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t dedicated_info_nas_); + srslte::proc_outcome_t step() final; + void stop() final; + srslte::proc_outcome_t trigger_event(const cell_selection_complete& e); + static const char* name() { return "Connection Request"; } + +private: + // args + rrc* rrc_ptr; + srslte::log* log_h; + srslte::establishment_cause_t cause; + srslte::unique_byte_buffer_t dedicated_info_nas; + + // state variables + enum class state_t { cell_selection, config_serving_cell, wait_t300 } state; + cs_result_t cs_ret; +}; + +class rrc::process_pcch_proc : public srslte::proc_impl_t +{ +public: + struct paging_complete { + bool outcome; + }; + + srslte::proc_outcome_t init(rrc* parent_, const asn1::rrc::paging_s& paging_); + srslte::proc_outcome_t step() final; + srslte::proc_outcome_t trigger_event(paging_complete e); + static const char* name() { return "Process PCCH"; } + +private: + // args + rrc* rrc_ptr; + srslte::log* log_h; + asn1::rrc::paging_s paging; + + // vars + uint32_t paging_idx = 0; + enum class state_t { next_record, nas_paging, serv_cell_cfg } state; +}; + +class rrc::go_idle_proc : public srslte::proc_impl_t +{ +public: + srslte::proc_outcome_t init(rrc* rrc_); + srslte::proc_outcome_t step() final; + static const char* name() { return "Go Idle"; } + +private: + rrc* rrc_ptr; + static const uint32_t rlc_flush_timeout = 2000; + + uint32_t rlc_flush_counter; +}; + +} // namespace srsue + +#endif // SRSLTE_RRC_PROCEDURES_H diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 89b79147c..eccb23217 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -40,8 +40,10 @@ #include "upper/usim.h" #include "srslte/common/buffer_pool.h" -#include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/log_filter.h" +#include "srslte/common/multiqueue.h" +#include "srslte/common/thread_pool.h" +#include "srslte/interfaces/ue_interfaces.h" #include "srsue/hdr/ue_metrics_interface.h" #include "ue_stack_base.h" @@ -51,18 +53,22 @@ namespace srsue { class ue_stack_lte final : public ue_stack_base, public stack_interface_phy_lte, public stack_interface_gw, + public stack_interface_mac, + public stack_interface_rrc, public thread { public: ue_stack_lte(); ~ue_stack_lte(); - std::string get_type(); + std::string get_type() final; int init(const stack_args_t& args_, srslte::logger* logger_); int init(const stack_args_t& args_, srslte::logger* logger_, phy_interface_stack_lte* phy_, gw_interface_stack* gw_); bool switch_on() final; bool switch_off(); + bool enable_data(); + bool disable_data(); void stop(); bool get_metrics(stack_metrics_t* metrics); @@ -106,13 +112,17 @@ public: void run_tti(uint32_t tti) final; // Interface for GW - void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) final - { - pdcp.write_sdu(lcid, std::move(sdu), blocking); - } + void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) final; bool is_lcid_enabled(uint32_t lcid) final { return pdcp.is_lcid_enabled(lcid); } + // Interface to upper MAC + void process_pdus() final; + void wait_ra_completion(uint16_t rnti) final; + + // Interface for RRC + void start_cell_search() final; + private: void run_thread() final; void run_tti_impl(uint32_t tti); @@ -121,6 +131,9 @@ private: bool running; srsue::stack_args_t args; + // timers + srslte::timers timers; + // UE stack logging srslte::logger* logger = nullptr; srslte::log_filter mac_log; @@ -146,8 +159,19 @@ private: gw_interface_stack* gw = nullptr; // Thread - static const int STACK_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD - srslte::block_queue > pending_tasks; + static const int STACK_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD + + // NOTE: we use this struct instead of a std::function bc lambdas can't capture by move in C++11 + struct task_t { + std::function func; + srslte::unique_byte_buffer_t pdu; + task_t() = default; + explicit task_t(std::function f_) : func(std::move(f_)) {} + void operator()() { func(this); } + }; + srslte::multiqueue_handler pending_tasks; + int sync_queue_id = -1, ue_queue_id = -1, gw_queue_id = -1, mac_queue_id = -1, background_queue_id = -1; + srslte::task_thread_pool background_tasks; ///< Thread pool used for long, low-priority tasks }; } // namespace srsue diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index e596319f2..b0d3e6f1f 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -28,6 +28,7 @@ #include "srslte/common/log.h" #include "srslte/common/nas_pcap.h" #include "srslte/common/security.h" +#include "srslte/common/stack_procedure.h" #include "srslte/interfaces/ue_interfaces.h" #include "srsue/hdr/stack/upper/nas_common.h" #include "srsue/hdr/stack/upper/nas_metrics.h" @@ -36,21 +37,19 @@ using srslte::byte_buffer_t; namespace srsue { -class nas - : public nas_interface_rrc, - public nas_interface_ue, - public nas_interface_gw +class nas : public nas_interface_rrc, public nas_interface_ue { public: nas(srslte::log* log_); void init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& args_); void stop(); + void run_tti(uint32_t tti) final; void get_metrics(nas_metrics_t* m); emm_state_t get_state(); // RRC interface - void leave_connected(); + void left_rrc_connected(); void paging(srslte::s_tmsi_t* ue_identity); void set_barring(barring_t barring); void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu); @@ -61,8 +60,14 @@ public: bool get_ipv6_addr(uint8_t* ipv6_addr); // UE interface - bool attach_request(); - bool detach_request(); + void start_attach_request(srslte::proc_state_t* result) final; + bool detach_request(const bool switch_off) final; + + void plmn_search_completed(rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS], + int nof_plmns) final; + bool start_connection_request(srslte::establishment_cause_t establish_cause, + srslte::unique_byte_buffer_t ded_info_nas); + bool connection_request_completed(bool outcome) final; // PCAP void start_pcap(srslte::nas_pcap *pcap_); @@ -135,8 +140,6 @@ private: bool running = false; - bool rrc_connect(); - void integrity_generate(uint8_t *key_128, uint32_t count, uint8_t direction, @@ -157,7 +160,7 @@ private: void parse_attach_reject(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void parse_authentication_request(uint32_t lcid, srslte::unique_byte_buffer_t pdu, const uint8_t sec_hdr_type); void parse_authentication_reject(uint32_t lcid, srslte::unique_byte_buffer_t pdu); - void parse_identity_request(uint32_t lcid, srslte::unique_byte_buffer_t pdu); + void parse_identity_request(srslte::unique_byte_buffer_t pdu, const uint8_t sec_hdr_type); void parse_security_mode_command(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void parse_service_reject(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void parse_esm_information_request(uint32_t lcid, srslte::unique_byte_buffer_t pdu); @@ -175,7 +178,7 @@ private: // Senders void send_attach_complete(const uint8_t& transaction_id, const uint8_t& eps_bearer_id); - void send_identity_response(uint32_t lcid, uint8 id_type); + void send_identity_response(uint8 id_type, const uint8_t sec_hdr_type); void send_service_request(); void send_esm_information_response(const uint8 proc_transaction_id); void send_authentication_response(const uint8_t* res, const size_t res_len, const uint8_t sec_hdr_type); @@ -190,6 +193,9 @@ private: void send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_id, const uint8_t& eps_bearer_id); void send_activate_test_mode_complete(const uint8_t sec_hdr_type); + // Other internal helpers + void enter_emm_deregistered(); + // security context persistence file bool read_ctxt_file(nas_sec_ctxt *ctxt); bool write_ctxt_file(nas_sec_ctxt ctxt); @@ -240,6 +246,50 @@ private: } return list; } + + class rrc_connect_proc : public srslte::proc_impl_t + { + public: + struct connection_request_completed_t { + bool outcome; + }; + + srslte::proc_outcome_t init(nas* nas_ptr_, srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t pdu); + srslte::proc_outcome_t step() final; + static const char* name() { return "RRC Connect"; } + + private: + nas* nas_ptr; + enum class state_t { conn_req, wait_attach } state; + uint32_t wait_timeout; + }; + class plmn_search_proc : public srslte::proc_impl_t + { + public: + struct plmn_search_complete_t { + rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS]; + int nof_plmns; + plmn_search_complete_t(rrc_interface_nas::found_plmn_t* plmns_, int nof_plmns_) : nof_plmns(nof_plmns_) + { + if (nof_plmns > 0) { + std::copy(&plmns_[0], &plmns_[nof_plmns], found_plmns); + } + } + }; + + srslte::proc_outcome_t init(nas* nas_ptr_); + srslte::proc_outcome_t step() final; + srslte::proc_outcome_t trigger_event(const plmn_search_complete_t& t); + static const char* name() { return "PLMN Search"; } + + private: + nas* nas_ptr; + enum class state_t { plmn_search, rrc_connect } state; + }; + srslte::callback_list_t callbacks; + srslte::proc_t plmn_searcher; + srslte::proc_t rrc_connector; + srslte::proc_t > conn_req_proc; }; } // namespace srsue diff --git a/srsue/src/main.cc b/srsue/src/main.cc index e13ef88a5..1127dfd0c 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -109,8 +109,8 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("nas.user", bpo::value(&args->stack.nas.apn_user)->default_value(""), "Username for CHAP authentication") ("nas.pass", bpo::value(&args->stack.nas.apn_pass)->default_value(""), "Password for CHAP authentication") ("nas.force_imsi_attach", bpo::value(&args->stack.nas.force_imsi_attach)->default_value(false), "Whether to always perform an IMSI attach") - ("nas.eia", bpo::value(&args->stack.nas.eia)->default_value("1,2"), "List of integrity algorithms included in UE capabilities") - ("nas.eea", bpo::value(&args->stack.nas.eea)->default_value("0,1,2"), "List of ciphering algorithms included in UE capabilities") + ("nas.eia", bpo::value(&args->stack.nas.eia)->default_value("1,2,3"), "List of integrity algorithms included in UE capabilities") + ("nas.eea", bpo::value(&args->stack.nas.eea)->default_value("0,1,2,3"), "List of ciphering algorithms included in UE capabilities") ("pcap.enable", bpo::value(&args->stack.pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark") ("pcap.filename", bpo::value(&args->stack.pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename") @@ -162,24 +162,34 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("channel.dl.fading.enable", bpo::value(&args->phy.dl_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model") ("channel.dl.fading.model", bpo::value(&args->phy.dl_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") ("channel.dl.delay.enable", bpo::value(&args->phy.dl_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator") - ("channel.dl.delay.period", bpo::value(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.dl.delay.period_s", bpo::value(&args->phy.dl_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.dl.delay.init_time_s", bpo::value(&args->phy.dl_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds") ("channel.dl.delay.maximum_us", bpo::value(&args->phy.dl_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds") ("channel.dl.delay.minimum_us", bpo::value(&args->phy.dl_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds") ("channel.dl.rlf.enable", bpo::value(&args->phy.dl_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator") ("channel.dl.rlf.t_on_ms", bpo::value(&args->phy.dl_channel_args.rlf_t_on_ms)->default_value(10000), "Time for On state of the channel (ms)") ("channel.dl.rlf.t_off_ms", bpo::value(&args->phy.dl_channel_args.rlf_t_off_ms)->default_value(2000), "Time for Off state of the channel (ms)") + ("channel.dl.hst.enable", bpo::value(&args->phy.dl_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator") + ("channel.dl.hst.period_s", bpo::value(&args->phy.dl_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds") + ("channel.dl.hst.fd_hz", bpo::value(&args->phy.dl_channel_args.hst_fd_hz)->default_value(+750.0f), "Doppler frequency in Hz") + ("channel.dl.hst.init_time_s", bpo::value(&args->phy.dl_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds") /* Uplink Channel emulator section */ ("channel.ul.enable", bpo::value(&args->phy.ul_channel_args.enable)->default_value(false), "Enable/Disable internal Uplink channel emulator") ("channel.ul.fading.enable", bpo::value(&args->phy.ul_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model") ("channel.ul.fading.model", bpo::value(&args->phy.ul_channel_args.fading_model)->default_value("none"), "Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)") ("channel.ul.delay.enable", bpo::value(&args->phy.ul_channel_args.delay_enable)->default_value(false), "Enable/Disable Delay simulator") - ("channel.ul.delay.period", bpo::value(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.ul.delay.period_s", bpo::value(&args->phy.ul_channel_args.delay_period_s)->default_value(3600), "Delay period in seconds (integer)") + ("channel.ul.delay.init_time_s", bpo::value(&args->phy.ul_channel_args.delay_init_time_s)->default_value(0), "Initial time in seconds") ("channel.ul.delay.maximum_us", bpo::value(&args->phy.ul_channel_args.delay_max_us)->default_value(100.0f), "Maximum delay in microseconds") ("channel.ul.delay.minimum_us", bpo::value(&args->phy.ul_channel_args.delay_min_us)->default_value(10.0f), "Minimum delay in microseconds") ("channel.ul.rlf.enable", bpo::value(&args->phy.ul_channel_args.rlf_enable)->default_value(false), "Enable/Disable Radio-Link Failure simulator") ("channel.ul.rlf.t_on_ms", bpo::value(&args->phy.ul_channel_args.rlf_t_on_ms)->default_value(10000), "Time for On state of the channel (ms)") ("channel.ul.rlf.t_off_ms", bpo::value(&args->phy.ul_channel_args.rlf_t_off_ms)->default_value(2000), "Time for Off state of the channel (ms)") + ("channel.ul.hst.enable", bpo::value(&args->phy.ul_channel_args.hst_enable)->default_value(false), "Enable/Disable HST simulator") + ("channel.ul.hst.period_s", bpo::value(&args->phy.ul_channel_args.hst_period_s)->default_value(7.2f), "HST simulation period in seconds") + ("channel.ul.hst.fd_hz", bpo::value(&args->phy.ul_channel_args.hst_fd_hz)->default_value(-750.0f), "Doppler frequency in Hz") + ("channel.ul.hst.init_time_s", bpo::value(&args->phy.ul_channel_args.hst_init_time_s)->default_value(0), "Initial time in seconds") /* PHY section */ ("phy.worker_cpu_mask", diff --git a/srsue/src/phy/cc_worker.cc b/srsue/src/phy/cc_worker.cc index 36c94052b..2687e72d2 100644 --- a/srsue/src/phy/cc_worker.cc +++ b/srsue/src/phy/cc_worker.cc @@ -21,7 +21,6 @@ #include "srslte/srslte.h" #include "srsue/hdr/phy/cc_worker.h" -#include "srslte/interfaces/ue_interfaces.h" #define Error(fmt, ...) \ if (SRSLTE_DEBUG_ENABLED) \ @@ -50,30 +49,11 @@ namespace srsue { * */ -cc_worker::cc_worker(uint32_t cc_idx, uint32_t max_prb, srsue::phy_common* phy, srslte::log* log_h) +cc_worker::cc_worker(uint32_t cc_idx_, uint32_t max_prb, srsue::phy_common* phy_, srslte::log* log_h_) { - ZERO_OBJECT(signal_buffer_rx); - ZERO_OBJECT(signal_buffer_tx); - ZERO_OBJECT(pending_dl_grant); - ZERO_OBJECT(cell); - ZERO_OBJECT(sf_cfg_dl); - ZERO_OBJECT(sf_cfg_ul); - ZERO_OBJECT(ue_dl); - ZERO_OBJECT(ue_dl_cfg); - ZERO_OBJECT(ue_dl_cfg.cfg.pdsch); - ZERO_OBJECT(pmch_cfg); - ZERO_OBJECT(chest_mbsfn_cfg); - ZERO_OBJECT(chest_default_cfg); - ZERO_OBJECT(ue_ul); - ZERO_OBJECT(ue_ul_cfg); - ZERO_OBJECT(dl_metrics); - ZERO_OBJECT(ul_metrics); - - cell_initiated = false; - - this->cc_idx = cc_idx; - this->phy = phy; - this->log_h = log_h; + cc_idx = cc_idx_; + phy = phy_; + log_h = log_h_; for (uint32_t i = 0; i < phy->args->nof_rx_ant; i++) { signal_buffer_rx[i] = (cf_t*)srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(max_prb)); @@ -111,11 +91,13 @@ cc_worker::cc_worker(uint32_t cc_idx, uint32_t max_prb, srsue::phy_common* phy, chest_default_cfg = ue_dl_cfg.chest_cfg; + // Set default PHY params + reset(); + if (phy->args->pdsch_8bit_decoder) { ue_dl.pdsch.llr_is_8bit = true; ue_dl.pdsch.dl_sch.llr_is_8bit = true; } - pregen_enabled = false; } cc_worker::~cc_worker() @@ -137,27 +119,15 @@ void cc_worker::reset() bzero(&dl_metrics, sizeof(dl_metrics_t)); bzero(&ul_metrics, sizeof(ul_metrics_t)); - phy_interface_rrc_lte::phy_cfg_t empty_cfg = {}; - // defaults - empty_cfg.common.pucch_cnfg.delta_pucch_shift.value = pucch_cfg_common_s::delta_pucch_shift_opts::ds1; - empty_cfg.common.ul_pwr_ctrl.alpha.value = alpha_r12_opts::al0; - empty_cfg.common.ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format1.value = - delta_flist_pucch_s::delta_f_pucch_format1_opts::delta_f0; - empty_cfg.common.ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format1b.value = - delta_flist_pucch_s::delta_f_pucch_format1b_opts::delta_f1; - empty_cfg.common.ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2.value = - delta_flist_pucch_s::delta_f_pucch_format2_opts::delta_f0; - empty_cfg.common.ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2a.value = - delta_flist_pucch_s::delta_f_pucch_format2a_opts::delta_f0; - empty_cfg.common.ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2b.value = - delta_flist_pucch_s::delta_f_pucch_format2b_opts::delta_f0; - set_pcell_config(&empty_cfg); + // constructor sets defaults + srslte::phy_cfg_t empty_cfg; + set_config(empty_cfg); } -bool cc_worker::set_cell(srslte_cell_t cell) +bool cc_worker::set_cell(srslte_cell_t cell_) { - if (this->cell.id != cell.id || !cell_initiated) { - this->cell = cell; + if (cell.id != cell_.id || !cell_initiated) { + cell = cell_; if (srslte_ue_dl_set_cell(&ue_dl, cell)) { Error("Initiating UE DL\n"); @@ -227,37 +197,6 @@ void cc_worker::enable_pregen_signals(bool enabled) this->pregen_enabled = enabled; } -void cc_worker::fill_dci_cfg(srslte_dci_cfg_t* cfg, bool rel10) -{ - bzero(cfg, sizeof(srslte_dci_cfg_t)); - if (rel10 && phy->cif_enabled) { - cfg->cif_enabled = phy->cif_enabled; - } - cfg->multiple_csi_request_enabled = phy->multiple_csi_request_enabled; - cfg->srs_request_enabled = phy->srs_request_enabled; -} - -void cc_worker::set_dl_pending_grant(uint32_t cc_idx, srslte_dci_dl_t* dl_dci) -{ - if (!pending_dl_grant[cc_idx].enable) { - pending_dl_grant[cc_idx].dl_dci = *dl_dci; - pending_dl_grant[cc_idx].enable = true; - } else { - Warning("set_dl_pending_grant: cc=%d already exists\n", cc_idx); - } -} - -bool cc_worker::get_dl_pending_grant(uint32_t cc_idx, srslte_dci_dl_t* dl_dci) -{ - if (pending_dl_grant[cc_idx].enable) { - *dl_dci = pending_dl_grant[cc_idx].dl_dci; - pending_dl_grant[cc_idx].enable = false; - return true; - } else { - return false; - } -} - /************ * * Downlink Functions @@ -266,9 +205,9 @@ bool cc_worker::get_dl_pending_grant(uint32_t cc_idx, srslte_dci_dl_t* dl_dci) bool cc_worker::work_dl_regular() { - bool dl_ack[SRSLTE_MAX_CODEWORDS]; + bool dl_ack[SRSLTE_MAX_CODEWORDS] = {}; - mac_interface_phy_lte::tb_action_dl_t dl_action; + mac_interface_phy_lte::tb_action_dl_t dl_action = {}; bool found_dl_grant = false; @@ -303,14 +242,15 @@ bool cc_worker::work_dl_regular() } /* Look for DL and UL dci(s) if this is PCell, or no cross-carrier scheduling is enabled */ - if ((cc_idx == 0) || (!phy->cif_enabled)) { + if ((cc_idx == 0) || (!ue_dl_cfg.cfg.dci.cif_present)) { found_dl_grant = decode_pdcch_dl() > 0; decode_pdcch_ul(); } } - srslte_dci_dl_t dci_dl; - bool has_dl_grant = get_dl_pending_grant(cc_idx, &dci_dl); + srslte_dci_dl_t dci_dl = {}; + uint32_t grant_cc_idx = 0; + bool has_dl_grant = phy->get_dl_pending_grant(CURRENT_TTI, cc_idx, &grant_cc_idx, &dci_dl); // If found a dci for this carrier, generate a grant, pass it to MAC and decode the associated PDSCH if (has_dl_grant) { @@ -334,11 +274,11 @@ bool cc_worker::work_dl_regular() ue_dl_cfg.cfg.pdsch.rnti = dci_dl.rnti; // Generate MAC grant - mac_interface_phy_lte::mac_grant_dl_t mac_grant; + mac_interface_phy_lte::mac_grant_dl_t mac_grant = {}; dl_phy_to_mac_grant(&ue_dl_cfg.cfg.pdsch.grant, &dci_dl, &mac_grant); // Save ACK resource configuration - srslte_pdsch_ack_resource_t ack_resource = {dci_dl.dai, dci_dl.location.ncce}; + srslte_pdsch_ack_resource_t ack_resource = {dci_dl.dai, dci_dl.location.ncce, grant_cc_idx, dci_dl.tpc_pucch}; // Send grant to MAC and get action for this TB, then call tb_decoded to unlock MAC phy->stack->new_grant_dl(cc_idx, mac_grant, &dl_action); @@ -354,7 +294,7 @@ bool cc_worker::work_dl_regular() bool cc_worker::work_dl_mbsfn(srslte_mbsfn_cfg_t mbsfn_cfg) { - mac_interface_phy_lte::tb_action_dl_t dl_action; + mac_interface_phy_lte::tb_action_dl_t dl_action = {}; // Configure MBSFN settings srslte_ue_dl_set_mbsfn_area_id(&ue_dl, mbsfn_cfg.mbsfn_area_id); @@ -403,6 +343,7 @@ void cc_worker::dl_phy_to_mac_grant(srslte_pdsch_grant_t* /* Fill MAC dci structure */ mac_grant->pid = dl_dci->pid; mac_grant->rnti = dl_dci->rnti; + mac_grant->tti = CURRENT_TTI; for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { mac_grant->tb[i].ndi = dl_dci->tb[i].ndi; @@ -421,16 +362,15 @@ int cc_worker::decode_pdcch_dl() { int nof_grants = 0; - srslte_dci_dl_t dci[SRSLTE_MAX_CARRIERS]; - ZERO_OBJECT(dci); + srslte_dci_dl_t dci[SRSLTE_MAX_CARRIERS] = {}; uint16_t dl_rnti = phy->stack->get_dl_sched_rnti(CURRENT_TTI); if (dl_rnti) { /* Blind search first without cross scheduling then with it if enabled */ - for (int i = 0; i < (phy->cif_enabled ? 2 : 1) && !nof_grants; i++) { - fill_dci_cfg(&ue_dl_cfg.dci_cfg, i > 0); + for (int i = 0; i < (ue_dl_cfg.cfg.dci.cif_present ? 2 : 1) && !nof_grants; i++) { Debug("PDCCH looking for rnti=0x%x\n", dl_rnti); + ue_dl_cfg.cfg.dci.cif_enabled = i > 0; nof_grants = srslte_ue_dl_find_dl_dci(&ue_dl, &sf_cfg_dl, &ue_dl_cfg, dl_rnti, dci); if (nof_grants < 0) { Error("Looking for DL grants\n"); @@ -445,10 +385,10 @@ int cc_worker::decode_pdcch_dl() for (int k = 0; k < nof_grants; k++) { // Save dci to CC index - set_dl_pending_grant(dci[k].cif_present ? dci[k].cif : cc_idx, &dci[k]); + phy->set_dl_pending_grant(CURRENT_TTI, dci[k].cif_present ? dci[k].cif : cc_idx, cc_idx, &dci[k]); // Logging - char str[512]; + char str[512] = {}; srslte_dci_dl_info(&dci[k], str, 512); Info("PDCCH: cc=%d, %s, snr=%.1f dB\n", cc_idx, str, ue_dl.chest_res.snr_db); } @@ -461,12 +401,11 @@ int cc_worker::decode_pdsch(srslte_pdsch_ack_resource_t ack_resource, bool mac_acks[SRSLTE_MAX_CODEWORDS]) { - srslte_pdsch_res_t pdsch_dec[SRSLTE_MAX_CODEWORDS]; - ZERO_OBJECT(pdsch_dec); + srslte_pdsch_res_t pdsch_dec[SRSLTE_MAX_CODEWORDS] = {}; // See if at least 1 codeword needs to be decoded. If not need to be decode, resend ACK bool decode_enable = false; - bool tb_enable[SRSLTE_MAX_CODEWORDS]; + bool tb_enable[SRSLTE_MAX_CODEWORDS] = {}; for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { tb_enable[tb] = ue_dl_cfg.cfg.pdsch.grant.tb[tb].enabled; if (action->tb[tb].enabled) { @@ -493,7 +432,7 @@ int cc_worker::decode_pdsch(srslte_pdsch_ack_resource_t ack_resource, } // Generate ACKs for MAC and PUCCH - uint8_t pending_acks[SRSLTE_MAX_CODEWORDS]; + uint8_t pending_acks[SRSLTE_MAX_CODEWORDS] = {}; for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { // For MAC, set to true if it's a duplicate mac_acks[tb] = action->tb[tb].enabled ? pdsch_dec[tb].crc : true; @@ -513,7 +452,7 @@ int cc_worker::decode_pdsch(srslte_pdsch_ack_resource_t ack_resource, dl_metrics.turbo_iters = pdsch_dec->avg_iterations_block / 2; // Logging - char str[512]; + char str[512] = {}; srslte_pdsch_rx_info(&ue_dl_cfg.cfg.pdsch, pdsch_dec, str, 512); Info("PDSCH: cc=%d, %s, snr=%.1f dB\n", cc_idx, str, ue_dl.chest_res.snr_db); } @@ -523,7 +462,7 @@ int cc_worker::decode_pdsch(srslte_pdsch_ack_resource_t ack_resource, int cc_worker::decode_pmch(mac_interface_phy_lte::tb_action_dl_t* action, srslte_mbsfn_cfg_t* mbsfn_cfg) { - srslte_pdsch_res_t pmch_dec; + srslte_pdsch_res_t pmch_dec = {}; pmch_cfg.area_id = mbsfn_cfg->mbsfn_area_id; pmch_cfg.pdsch_cfg.softbuffers.rx[0] = action->tb[0].softbuffer.rx; @@ -597,7 +536,7 @@ void cc_worker::update_measurements() // Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC float rsrq_db = ue_dl.chest_res.rsrq_db; if (std::isnormal(rsrq_db)) { - if (!(CURRENT_TTI % phy->pcell_report_period) || !phy->avg_rsrq_db) { + if (!(CURRENT_TTI % phy->pcell_report_period) || !std::isnormal(phy->avg_rsrq_db)) { phy->avg_rsrq_db = rsrq_db; } else { phy->avg_rsrq_db = SRSLTE_VEC_CMA(rsrq_db, phy->avg_rsrq_db, CURRENT_TTI % phy->pcell_report_period); @@ -607,10 +546,10 @@ void cc_worker::update_measurements() // Average RSRP taken from CRS float rsrp_lin = ue_dl.chest_res.rsrp; if (std::isnormal(rsrp_lin)) { - if (!phy->avg_rsrp[cc_idx] && !std::isnan(phy->avg_rsrp[cc_idx])) { - phy->avg_rsrp[cc_idx] = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp[cc_idx], snr_ema_coeff); - } else { + if (!std::isnormal(phy->avg_rsrp[cc_idx])) { phy->avg_rsrp[cc_idx] = rsrp_lin; + } else { + phy->avg_rsrp[cc_idx] = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp[cc_idx], snr_ema_coeff); } } @@ -619,7 +558,7 @@ void cc_worker::update_measurements() // Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC if (std::isnormal(rsrp_dbm)) { - if (!(CURRENT_TTI % phy->pcell_report_period) || !phy->avg_rsrp_dbm[cc_idx]) { + if (!(CURRENT_TTI % phy->pcell_report_period) || !std::isnormal(phy->avg_rsrp_dbm[cc_idx])) { phy->avg_rsrp_dbm[cc_idx] = rsrp_dbm; } else { phy->avg_rsrp_dbm[cc_idx] = @@ -634,7 +573,7 @@ void cc_worker::update_measurements() // Average noise float cur_noise = ue_dl.chest_res.noise_estimate; if (std::isnormal(cur_noise)) { - if (!phy->avg_noise) { + if (!std::isnormal(phy->avg_noise[cc_idx])) { phy->avg_noise[cc_idx] = cur_noise; } else { phy->avg_noise[cc_idx] = SRSLTE_VEC_EMA(cur_noise, phy->avg_noise[cc_idx], snr_ema_coeff); @@ -643,7 +582,7 @@ void cc_worker::update_measurements() // Average snr in the log domain if (std::isnormal(ue_dl.chest_res.snr_db)) { - if (!phy->avg_noise) { + if (!std::isnormal(phy->avg_snr_db_cqi[cc_idx])) { phy->avg_snr_db_cqi[cc_idx] = ue_dl.chest_res.snr_db; } else { phy->avg_snr_db_cqi[cc_idx] = SRSLTE_VEC_EMA(ue_dl.chest_res.snr_db, phy->avg_snr_db_cqi[cc_idx], snr_ema_coeff); @@ -681,7 +620,7 @@ bool cc_worker::work_ul(srslte_uci_data_t* uci_data) bool ul_grant_available = phy->get_ul_pending_grant(&sf_cfg_ul, cc_idx, &pid, &dci_ul); ul_mac_grant.phich_available = - phy->get_ul_received_ack(&sf_cfg_ul, cc_idx, &ul_mac_grant.hi_value, ul_grant_available ? NULL : &dci_ul); + phy->get_ul_received_ack(&sf_cfg_ul, cc_idx, &ul_mac_grant.hi_value, ul_grant_available ? nullptr : &dci_ul); // If there is no grant, pid is from current TX TTI if (!ul_grant_available) { @@ -695,6 +634,8 @@ bool cc_worker::work_ul(srslte_uci_data_t* uci_data) } else { /* Check PCell and enabled secondary cells */ if (cc_idx == 0 || phy->scell_cfg[cc_idx].enabled) { + // 3GPP 36.213 Section 7.2 + // If the UE is configured with more than one serving cell, it transmits CSI for activated serving cell(s) only. set_uci_periodic_cqi(uci_data); } } @@ -738,7 +679,7 @@ bool cc_worker::work_ul(srslte_uci_data_t* uci_data) } // Generate uplink signal, include uci data on only PCell - signal_ready = encode_uplink(&ul_action, (cc_idx == 0) ? uci_data : NULL); + signal_ready = encode_uplink(&ul_action, (cc_idx == 0) ? uci_data : nullptr); // Prepare to receive ACK through PHICH if (ul_action.expect_ack) { @@ -774,6 +715,7 @@ void cc_worker::ul_phy_to_mac_grant(srslte_pusch_grant_t* mac_grant->tb.tbs = phy_grant->tb.tbs / (uint32_t)8; mac_grant->tb.rv = phy_grant->tb.rv; mac_grant->pid = pid; + mac_grant->tti_tx = CURRENT_TTI_TX; } int cc_worker::decode_pdcch_ul() @@ -787,8 +729,8 @@ int cc_worker::decode_pdcch_ul() if (ul_rnti) { /* Blind search first without cross scheduling then with it if enabled */ - for (int i = 0; i < (phy->cif_enabled ? 2 : 1) && !nof_grants; i++) { - fill_dci_cfg(&ue_dl_cfg.dci_cfg, i > 0); + for (int i = 0; i < (ue_dl_cfg.cfg.dci.cif_present ? 2 : 1) && !nof_grants; i++) { + ue_dl_cfg.cfg.dci.cif_enabled = i > 0; nof_grants = srslte_ue_dl_find_ul_dci(&ue_dl, &sf_cfg_dl, &ue_dl_cfg, ul_rnti, dci); if (nof_grants < 0) { Error("Looking for UL grants\n"); @@ -824,6 +766,12 @@ bool cc_worker::encode_uplink(mac_interface_phy_lte::tb_action_ul_t* action, srs if (action) { data.ptr = action->tb.payload; ue_ul_cfg.ul_cfg.pusch.softbuffers.tx = action->tb.softbuffer.tx; + + // Use RV from higher layers + ue_ul_cfg.ul_cfg.pusch.grant.tb.rv = action->tb.rv; + + // Setup PUSCH grant + ue_ul_cfg.grant_available = action->tb.enabled; } // Set UCI data and configuration @@ -836,12 +784,6 @@ bool cc_worker::encode_uplink(mac_interface_phy_lte::tb_action_ul_t* action, srs ZERO_OBJECT(ue_ul_cfg.ul_cfg.pucch.uci_cfg); } - // Use RV from higher layers - ue_ul_cfg.ul_cfg.pusch.grant.tb.rv = action->tb.rv; - - // Setup PUSCH grant - ue_ul_cfg.grant_available = action->tb.enabled; - // Set UL RNTI ue_ul_cfg.ul_cfg.pucch.rnti = phy->stack->get_ul_sched_rnti(CURRENT_TTI_TX); @@ -917,29 +859,18 @@ void cc_worker::set_uci_ack(srslte_uci_data_t* uci_data, uint32_t nof_configured_carriers = 0; // Only PCell generates ACK for all SCell - for (uint32_t cc_idx = 0; cc_idx < phy->args->nof_carriers; cc_idx++) { - if (cc_idx == 0 || phy->scell_cfg[cc_idx].configured) { - phy->get_dl_pending_ack(&sf_cfg_ul, cc_idx, &ack_info.cc[cc_idx]); + for (uint32_t i = 0; i < phy->args->nof_carriers; i++) { + if (i == 0 || phy->scell_cfg[i].configured) { + phy->get_dl_pending_ack(&sf_cfg_ul, i, &ack_info.cc[i]); nof_configured_carriers++; } } - // Set ACK length for CA (default value is set to DTX) - if (ue_ul_cfg.ul_cfg.pucch.ack_nack_feedback_mode != SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL) { - if (ue_dl_cfg.cfg.tm > SRSLTE_TM2) { - /* TM3, TM4 */ - uci_data->cfg.ack.nof_acks = nof_configured_carriers * SRSLTE_MAX_CODEWORDS; - } else { - /* TM1, TM2 */ - uci_data->cfg.ack.nof_acks = nof_configured_carriers; - } - } - // Configure ACK parameters ack_info.is_grant_available = is_grant_available; ack_info.is_pusch_available = is_pusch_available; ack_info.V_dai_ul = V_dai_ul; - ack_info.tdd_ack_bundle = ue_ul_cfg.ul_cfg.pucch.tdd_ack_bundle; + ack_info.tdd_ack_multiplex = ue_ul_cfg.ul_cfg.pucch.tdd_ack_multiplex; ack_info.simul_cqi_ack = ue_ul_cfg.ul_cfg.pucch.simul_cqi_ack; ack_info.ack_nack_feedback_mode = ue_ul_cfg.ul_cfg.pucch.ack_nack_feedback_mode; ack_info.nof_cc = nof_configured_carriers; @@ -955,290 +886,15 @@ void cc_worker::set_uci_ack(srslte_uci_data_t* uci_data, * */ -srslte_cqi_report_mode_t cc_worker::aperiodic_mode(cqi_report_mode_aperiodic_e mode) -{ - switch (mode) { - case cqi_report_mode_aperiodic_e::rm12: - return SRSLTE_CQI_MODE_12; - case cqi_report_mode_aperiodic_e::rm20: - return SRSLTE_CQI_MODE_20; - case cqi_report_mode_aperiodic_e::rm22: - return SRSLTE_CQI_MODE_22; - case cqi_report_mode_aperiodic_e::rm30: - return SRSLTE_CQI_MODE_30; - case cqi_report_mode_aperiodic_e::rm31: - return SRSLTE_CQI_MODE_31; - case cqi_report_mode_aperiodic_e::rm10_v1310: - case cqi_report_mode_aperiodic_e::rm11_v1310: - case cqi_report_mode_aperiodic_e::rm32_v1250: - fprintf(stderr, "Aperiodic mode %s not handled\n", mode.to_string().c_str()); - default: - return SRSLTE_CQI_MODE_NA; - } -} - -void cc_worker::parse_antenna_info(phys_cfg_ded_s* dedicated) -{ - if (dedicated->ant_info_r10_present) { - // Parse Release 10 - ant_info_ded_r10_s::tx_mode_r10_e_::options tx_mode = - dedicated->ant_info_r10->explicit_value_r10().tx_mode_r10.value; - if ((srslte_tm_t)tx_mode < SRSLTE_TMINV) { - ue_dl_cfg.cfg.tm = (srslte_tm_t)tx_mode; - } else { - fprintf(stderr, - "Transmission mode (R10) %s is not supported\n", - dedicated->ant_info_r10->explicit_value_r10().tx_mode_r10.to_string().c_str()); - } - } else if (dedicated->ant_info_present && - dedicated->ant_info.type() == phys_cfg_ded_s::ant_info_c_::types::explicit_value) { - // Parse Release 8 - ant_info_ded_s::tx_mode_e_::options tx_mode = dedicated->ant_info.explicit_value().tx_mode.value; - if ((srslte_tm_t)tx_mode < SRSLTE_TMINV) { - ue_dl_cfg.cfg.tm = (srslte_tm_t)tx_mode; - } else { - fprintf(stderr, - "Transmission mode (R8) %s is not supported\n", - dedicated->ant_info.explicit_value().tx_mode.to_string().c_str()); - } - } else { - if (cell.nof_ports == 1) { - // No antenna info provided - ue_dl_cfg.cfg.tm = SRSLTE_TM1; - } else { - // No antenna info provided - ue_dl_cfg.cfg.tm = SRSLTE_TM2; - } - } -} - -void cc_worker::parse_pucch_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg) -{ - phy_interface_rrc_lte::phy_cfg_common_t* common = &phy_cfg->common; - phys_cfg_ded_s* dedicated = &phy_cfg->dedicated; - - /* PUCCH configuration */ - bzero(&ue_ul_cfg.ul_cfg.pucch, sizeof(srslte_pucch_cfg_t)); - ue_ul_cfg.ul_cfg.pucch.delta_pucch_shift = common->pucch_cnfg.delta_pucch_shift.to_number(); - ue_ul_cfg.ul_cfg.pucch.N_cs = common->pucch_cnfg.n_cs_an; - ue_ul_cfg.ul_cfg.pucch.n_rb_2 = common->pucch_cnfg.n_rb_cqi; - - /* PUCCH Scheduling configuration */ - ue_ul_cfg.ul_cfg.pucch.n_pucch_1[0] = 0; // TODO: n_pucch_1 for SPS - ue_ul_cfg.ul_cfg.pucch.n_pucch_1[1] = 0; - ue_ul_cfg.ul_cfg.pucch.n_pucch_1[2] = 0; - ue_ul_cfg.ul_cfg.pucch.n_pucch_1[3] = 0; - ue_ul_cfg.ul_cfg.pucch.N_pucch_1 = common->pucch_cnfg.n1_pucch_an; - if (dedicated->cqi_report_cfg.cqi_report_periodic_present and - dedicated->cqi_report_cfg.cqi_report_periodic.type().value == setup_e::setup) { - ue_ul_cfg.ul_cfg.pucch.n_pucch_2 = dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx; - ue_ul_cfg.ul_cfg.pucch.simul_cqi_ack = dedicated->cqi_report_cfg.cqi_report_periodic.setup().simul_ack_nack_and_cqi; - } else { - // FIXME: put is_pucch_configured flag here? - ue_ul_cfg.ul_cfg.pucch.n_pucch_2 = 0; - ue_ul_cfg.ul_cfg.pucch.simul_cqi_ack = false; - } - - /* SR configuration */ - if (dedicated->sched_request_cfg_present and dedicated->sched_request_cfg.type() == setup_e::setup) { - ue_ul_cfg.ul_cfg.pucch.I_sr = dedicated->sched_request_cfg.setup().sr_cfg_idx; - ue_ul_cfg.ul_cfg.pucch.n_pucch_sr = dedicated->sched_request_cfg.setup().sr_pucch_res_idx; - ue_ul_cfg.ul_cfg.pucch.sr_configured = true; - } else { - ue_ul_cfg.ul_cfg.pucch.I_sr = 0; - ue_ul_cfg.ul_cfg.pucch.n_pucch_sr = 0; - ue_ul_cfg.ul_cfg.pucch.sr_configured = false; - } - - if (dedicated->pucch_cfg_ded.tdd_ack_nack_feedback_mode_present) { - ue_ul_cfg.ul_cfg.pucch.tdd_ack_bundle = - dedicated->pucch_cfg_ded.tdd_ack_nack_feedback_mode == pucch_cfg_ded_s::tdd_ack_nack_feedback_mode_e_::bundling; - } else { - ue_ul_cfg.ul_cfg.pucch.tdd_ack_bundle = false; - } - - if (dedicated->pucch_cfg_ded_v1020_present) { - pucch_cfg_ded_v1020_s* pucch_cfg_ded = dedicated->pucch_cfg_ded_v1020.get(); - - if (pucch_cfg_ded->pucch_format_r10_present) { - - typedef pucch_cfg_ded_v1020_s::pucch_format_r10_c_ pucch_format_r10_t; - pucch_format_r10_t* pucch_format_r10 = &pucch_cfg_ded->pucch_format_r10; - - if (pucch_format_r10->type() == pucch_format_r10_t::types::format3_r10) { - // Select feedback mode - ue_ul_cfg.ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_PUCCH3; - - pucch_format3_conf_r13_s* format3_r13 = &pucch_format_r10->format3_r10(); - for (uint32_t n = 0; n < SRSLTE_MIN(format3_r13->n3_pucch_an_list_r13.size(), SRSLTE_PUCCH_SIZE_AN_CS); n++) { - ue_ul_cfg.ul_cfg.pucch.n3_pucch_an_list[n] = format3_r13->n3_pucch_an_list_r13[n]; - } - if (format3_r13->two_ant_port_activ_pucch_format3_r13_present) { - if (format3_r13->two_ant_port_activ_pucch_format3_r13.type() == setup_e::setup) { - // TODO: UL MIMO Configure PUCCH two antenna port - } else { - // TODO: UL MIMO Disable two antenna port - } - } - } else if (pucch_format_r10->type() == pucch_cfg_ded_v1020_s::pucch_format_r10_c_::types::ch_sel_r10) { - - typedef pucch_format_r10_t::ch_sel_r10_s_ ch_sel_r10_t; - ch_sel_r10_t* ch_sel_r10 = &pucch_format_r10->ch_sel_r10(); - - if (ch_sel_r10->n1_pucch_an_cs_r10_present) { - typedef ch_sel_r10_t::n1_pucch_an_cs_r10_c_ n1_pucch_an_cs_r10_t; - n1_pucch_an_cs_r10_t* n1_pucch_an_cs_r10 = &ch_sel_r10->n1_pucch_an_cs_r10; - - if (n1_pucch_an_cs_r10->type() == setup_e::setup) { - // Select feedback mode - ue_ul_cfg.ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_CS; - - typedef n1_pucch_an_cs_r10_t::setup_s_::n1_pucch_an_cs_list_r10_l_ n1_pucch_an_cs_list_r10_t; - n1_pucch_an_cs_list_r10_t n1_pucch_an_cs_list = - ch_sel_r10->n1_pucch_an_cs_r10.setup().n1_pucch_an_cs_list_r10; - for (uint32_t i = 0; i < SRSLTE_MIN(n1_pucch_an_cs_list.size(), SRSLTE_PUCCH_NOF_AN_CS); i++) { - n1_pucch_an_cs_r10_l n1_pucch_an_cs = n1_pucch_an_cs_list[i]; - for (uint32_t j = 0; j < SRSLTE_PUCCH_SIZE_AN_CS; j++) { - ue_ul_cfg.ul_cfg.pucch.n1_pucch_an_cs[j][i] = n1_pucch_an_cs[j]; - } - } - } else { - ue_ul_cfg.ul_cfg.pucch.ack_nack_feedback_mode = SRSLTE_PUCCH_ACK_NACK_FEEDBACK_MODE_NORMAL; - } - } - } else { - // Do nothing - } - } - } -} - /* Translates RRC structs into PHY structs */ -void cc_worker::set_pcell_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg) +void cc_worker::set_config(srslte::phy_cfg_t& phy_cfg) { - phy_interface_rrc_lte::phy_cfg_common_t* common = &phy_cfg->common; - phys_cfg_ded_s* dedicated = &phy_cfg->dedicated; - - // Configure PDSCH - if (dedicated->pdsch_cfg_ded_present && common->pdsch_cnfg.p_b < 4) { - ue_dl_cfg.cfg.pdsch.p_a = dedicated->pdsch_cfg_ded.p_a.to_number(); - ue_dl_cfg.cfg.pdsch.p_b = common->pdsch_cnfg.p_b; - ue_dl_cfg.cfg.pdsch.power_scale = true; - } else { - ue_dl_cfg.cfg.pdsch.power_scale = false; - } - ue_dl_cfg.cfg.pdsch.rs_power = (float)common->pdsch_cnfg.ref_sig_pwr; - parse_antenna_info(dedicated); - - // Configure PUSCH - ue_ul_cfg.ul_cfg.pusch.enable_64qam = - phy_cfg->common.pusch_cnfg.pusch_cfg_basic.enable64_qam && phy_cfg->common.rrc_enable_64qam; - - /* PUSCH DMRS signal configuration */ - bzero(&ue_ul_cfg.ul_cfg.dmrs, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); - ue_ul_cfg.ul_cfg.dmrs.group_hopping_en = common->pusch_cnfg.ul_ref_sigs_pusch.group_hop_enabled; - ue_ul_cfg.ul_cfg.dmrs.sequence_hopping_en = common->pusch_cnfg.ul_ref_sigs_pusch.seq_hop_enabled; - ue_ul_cfg.ul_cfg.dmrs.cyclic_shift = common->pusch_cnfg.ul_ref_sigs_pusch.cyclic_shift; - ue_ul_cfg.ul_cfg.dmrs.delta_ss = common->pusch_cnfg.ul_ref_sigs_pusch.group_assign_pusch; - - /* PUSCH Hopping configuration */ - bzero(&ue_ul_cfg.ul_cfg.hopping, sizeof(srslte_pusch_hopping_cfg_t)); - ue_ul_cfg.ul_cfg.hopping.n_sb = common->pusch_cnfg.pusch_cfg_basic.n_sb; - ue_ul_cfg.ul_cfg.hopping.hop_mode = - common->pusch_cnfg.pusch_cfg_basic.hop_mode.value == - pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame - ? ue_ul_cfg.ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF - : ue_ul_cfg.ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; - ue_ul_cfg.ul_cfg.hopping.hopping_offset = common->pusch_cnfg.pusch_cfg_basic.pusch_hop_offset; - - /* PUSCH UCI configuration */ - bzero(&ue_ul_cfg.ul_cfg.pusch.uci_offset, sizeof(srslte_uci_offset_cfg_t)); - ue_ul_cfg.ul_cfg.pusch.uci_offset.I_offset_ack = dedicated->pusch_cfg_ded.beta_offset_ack_idx; - ue_ul_cfg.ul_cfg.pusch.uci_offset.I_offset_cqi = dedicated->pusch_cfg_ded.beta_offset_cqi_idx; - ue_ul_cfg.ul_cfg.pusch.uci_offset.I_offset_ri = dedicated->pusch_cfg_ded.beta_offset_ri_idx; - - parse_pucch_config(phy_cfg); - - /* SRS Configuration */ - bzero(&ue_ul_cfg.ul_cfg.srs, sizeof(srslte_refsignal_srs_cfg_t)); - ue_ul_cfg.ul_cfg.srs.configured = dedicated->srs_ul_cfg_ded_present and - dedicated->srs_ul_cfg_ded.type() == setup_e::setup and - common->srs_ul_cnfg.type() == setup_e::setup; - if (ue_ul_cfg.ul_cfg.srs.configured) { - ue_ul_cfg.ul_cfg.srs.I_srs = dedicated->srs_ul_cfg_ded.setup().srs_cfg_idx; - ue_ul_cfg.ul_cfg.srs.B = dedicated->srs_ul_cfg_ded.setup().srs_bw; - ue_ul_cfg.ul_cfg.srs.b_hop = dedicated->srs_ul_cfg_ded.setup().srs_hop_bw; - ue_ul_cfg.ul_cfg.srs.n_rrc = dedicated->srs_ul_cfg_ded.setup().freq_domain_position; - ue_ul_cfg.ul_cfg.srs.k_tc = dedicated->srs_ul_cfg_ded.setup().tx_comb; - ue_ul_cfg.ul_cfg.srs.n_srs = dedicated->srs_ul_cfg_ded.setup().cyclic_shift; - ue_ul_cfg.ul_cfg.srs.simul_ack = common->srs_ul_cnfg.setup().ack_nack_srs_simul_tx; - ue_ul_cfg.ul_cfg.srs.bw_cfg = common->srs_ul_cnfg.setup().srs_bw_cfg.to_number(); - ue_ul_cfg.ul_cfg.srs.subframe_config = common->srs_ul_cnfg.setup().srs_sf_cfg.to_number(); - } - - /* UL power control configuration */ - bzero(&ue_ul_cfg.ul_cfg.power_ctrl, sizeof(srslte_ue_ul_powerctrl_t)); - ue_ul_cfg.ul_cfg.power_ctrl.p0_nominal_pusch = common->ul_pwr_ctrl.p0_nominal_pusch; - ue_ul_cfg.ul_cfg.power_ctrl.alpha = common->ul_pwr_ctrl.alpha.to_number(); - ue_ul_cfg.ul_cfg.power_ctrl.p0_nominal_pucch = common->ul_pwr_ctrl.p0_nominal_pucch; - ue_ul_cfg.ul_cfg.power_ctrl.delta_f_pucch[0] = - common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format1.to_number(); - ue_ul_cfg.ul_cfg.power_ctrl.delta_f_pucch[1] = - common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format1b.to_number(); - ue_ul_cfg.ul_cfg.power_ctrl.delta_f_pucch[2] = - common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2.to_number(); - ue_ul_cfg.ul_cfg.power_ctrl.delta_f_pucch[3] = - common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2a.to_number(); - ue_ul_cfg.ul_cfg.power_ctrl.delta_f_pucch[4] = - common->ul_pwr_ctrl.delta_flist_pucch.delta_f_pucch_format2b.to_number(); - - ue_ul_cfg.ul_cfg.power_ctrl.delta_preamble_msg3 = common->ul_pwr_ctrl.delta_preamb_msg3; - - ue_ul_cfg.ul_cfg.power_ctrl.p0_ue_pusch = dedicated->ul_pwr_ctrl_ded.p0_ue_pusch; - ue_ul_cfg.ul_cfg.power_ctrl.delta_mcs_based = - dedicated->ul_pwr_ctrl_ded.delta_mcs_enabled == ul_pwr_ctrl_ded_s::delta_mcs_enabled_e_::en0; - ue_ul_cfg.ul_cfg.power_ctrl.acc_enabled = dedicated->ul_pwr_ctrl_ded.accumulation_enabled; - ue_ul_cfg.ul_cfg.power_ctrl.p0_ue_pucch = dedicated->ul_pwr_ctrl_ded.p0_ue_pucch; - ue_ul_cfg.ul_cfg.power_ctrl.p_srs_offset = dedicated->ul_pwr_ctrl_ded.p_srs_offset; - - /* CQI configuration */ - bzero(&ue_dl_cfg.cfg.cqi_report, sizeof(srslte_cqi_report_cfg_t)); - ue_dl_cfg.cfg.cqi_report.periodic_configured = dedicated->cqi_report_cfg.cqi_report_periodic_present and - dedicated->cqi_report_cfg.cqi_report_periodic.type() == setup_e::setup; - if (ue_dl_cfg.cfg.cqi_report.periodic_configured) { - ue_dl_cfg.cfg.cqi_report.pmi_idx = dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx; - ue_dl_cfg.cfg.cqi_report.format_is_subband = - dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.type().value == - cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::subband_cqi; - if (ue_dl_cfg.cfg.cqi_report.format_is_subband) { - ue_dl_cfg.cfg.cqi_report.subband_size = - dedicated->cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.subband_cqi().k; - } - if (dedicated->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx_present) { - if (cell.nof_ports == 1) { - log_h->warning("Received Rank Indication report configuration but only 1 antenna is available\n"); - } - ue_dl_cfg.cfg.cqi_report.ri_idx = dedicated->cqi_report_cfg.cqi_report_periodic.setup().ri_cfg_idx; - ue_dl_cfg.cfg.cqi_report.ri_idx_present = true; - } else { - ue_dl_cfg.cfg.cqi_report.ri_idx_present = false; - } - } - - if (dedicated->cqi_report_cfg.cqi_report_mode_aperiodic_present) { - ue_dl_cfg.cfg.cqi_report.aperiodic_configured = true; - ue_dl_cfg.cfg.cqi_report.aperiodic_mode = aperiodic_mode(dedicated->cqi_report_cfg.cqi_report_mode_aperiodic); - } - if (dedicated->cqi_report_cfg_pcell_v1250_present) { - auto cqi_report_cfg_pcell_v1250 = dedicated->cqi_report_cfg_pcell_v1250.get(); - if (cqi_report_cfg_pcell_v1250->alt_cqi_table_r12_present) { - ue_dl_cfg.pdsch_use_tbs_index_alt = true; - } - } else { - ue_dl_cfg.pdsch_use_tbs_index_alt = false; - } + // Save configuration + ue_dl_cfg.cfg = phy_cfg.dl_cfg; + ue_ul_cfg.ul_cfg = phy_cfg.ul_cfg; + // Update signals if (pregen_enabled) { Info("Pre-generating UL signals...\n"); srslte_ue_ul_pregen_signals(&ue_ul, &ue_ul_cfg); @@ -1246,165 +902,6 @@ void cc_worker::set_pcell_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg) } } -void cc_worker::set_scell_config(asn1::rrc::scell_to_add_mod_r10_s* phy_cfg) -{ - if (phy_cfg->rr_cfg_common_scell_r10_present) { - rr_cfg_common_scell_r10_s* rr_cfg_common_scell_r10 = &phy_cfg->rr_cfg_common_scell_r10; - - if (rr_cfg_common_scell_r10->ul_cfg_r10_present) { - typedef rr_cfg_common_scell_r10_s::ul_cfg_r10_s_ ul_cfg_r10_t; - ul_cfg_r10_t* ul_cfg_r10 = &rr_cfg_common_scell_r10->ul_cfg_r10; - - // Parse Power control - ul_pwr_ctrl_common_scell_r10_s* ul_pwr_ctrl_common_scell_r10 = &ul_cfg_r10->ul_pwr_ctrl_common_scell_r10; - bzero(&ue_ul_cfg.ul_cfg.power_ctrl, sizeof(srslte_ue_ul_powerctrl_t)); - ue_ul_cfg.ul_cfg.power_ctrl.p0_nominal_pusch = ul_pwr_ctrl_common_scell_r10->p0_nominal_pusch_r10; - ue_ul_cfg.ul_cfg.power_ctrl.alpha = ul_pwr_ctrl_common_scell_r10->alpha_r10.to_number(); - - // Parse SRS - typedef srs_ul_cfg_common_c::setup_s_ srs_ul_cfg_common_t; - if (ul_cfg_r10->srs_ul_cfg_common_r10.type() == setup_e::setup) { - srs_ul_cfg_common_t* srs_ul_cfg_common = &ul_cfg_r10->srs_ul_cfg_common_r10.setup(); - ue_ul_cfg.ul_cfg.srs.configured = true; - ue_ul_cfg.ul_cfg.srs.simul_ack = srs_ul_cfg_common->ack_nack_srs_simul_tx; - ue_ul_cfg.ul_cfg.srs.bw_cfg = srs_ul_cfg_common->srs_bw_cfg.to_number(); - ue_ul_cfg.ul_cfg.srs.subframe_config = srs_ul_cfg_common->srs_sf_cfg.to_number(); - } else { - ue_ul_cfg.ul_cfg.srs.configured = false; - } - - // Parse PUSCH - pusch_cfg_common_s* pusch_cfg_common = &ul_cfg_r10->pusch_cfg_common_r10; - bzero(&ue_ul_cfg.ul_cfg.hopping, sizeof(srslte_pusch_hopping_cfg_t)); - ue_ul_cfg.ul_cfg.hopping.n_sb = pusch_cfg_common->pusch_cfg_basic.n_sb; - ue_ul_cfg.ul_cfg.hopping.hop_mode = - pusch_cfg_common->pusch_cfg_basic.hop_mode.value == - pusch_cfg_common_s::pusch_cfg_basic_s_::hop_mode_e_::intra_and_inter_sub_frame - ? ue_ul_cfg.ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF - : ue_ul_cfg.ul_cfg.hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF; - ue_ul_cfg.ul_cfg.hopping.hopping_offset = pusch_cfg_common->pusch_cfg_basic.pusch_hop_offset; - ue_ul_cfg.ul_cfg.pusch.enable_64qam = pusch_cfg_common->pusch_cfg_basic.enable64_qam; - } - } - - if (phy_cfg->rr_cfg_ded_scell_r10_present) { - rr_cfg_ded_scell_r10_s* rr_cfg_ded_scell_r10 = &phy_cfg->rr_cfg_ded_scell_r10; - if (rr_cfg_ded_scell_r10->phys_cfg_ded_scell_r10_present) { - phys_cfg_ded_scell_r10_s* phys_cfg_ded_scell_r10 = &rr_cfg_ded_scell_r10->phys_cfg_ded_scell_r10; - - // Parse nonUL Configuration - if (phys_cfg_ded_scell_r10->non_ul_cfg_r10_present) { - - typedef phys_cfg_ded_scell_r10_s::non_ul_cfg_r10_s_ non_ul_cfg_t; - non_ul_cfg_t* non_ul_cfg = &phys_cfg_ded_scell_r10->non_ul_cfg_r10; - - // Parse Transmission mode - if (non_ul_cfg->ant_info_r10_present) { - ant_info_ded_r10_s::tx_mode_r10_e_::options tx_mode = non_ul_cfg->ant_info_r10.tx_mode_r10.value; - if ((srslte_tm_t)tx_mode < SRSLTE_TMINV) { - ue_dl_cfg.cfg.tm = (srslte_tm_t)tx_mode; - } else { - fprintf(stderr, - "Transmission mode (R10) %s is not supported\n", - non_ul_cfg->ant_info_r10.tx_mode_r10.to_string().c_str()); - } - } - - // Parse Cross carrier scheduling - if (non_ul_cfg->cross_carrier_sched_cfg_r10_present) { - typedef cross_carrier_sched_cfg_r10_s::sched_cell_info_r10_c_ sched_info_t; - - typedef sched_info_t::types cross_carrier_type_e; - sched_info_t* sched_info = &non_ul_cfg->cross_carrier_sched_cfg_r10.sched_cell_info_r10; - - cross_carrier_type_e cross_carrier_type = sched_info->type(); - if (cross_carrier_type == cross_carrier_type_e::own_r10) { - ue_dl_cfg.dci_cfg.cif_enabled = sched_info->own_r10().cif_presence_r10; - } else { - ue_dl_cfg.dci_cfg.cif_enabled = false; // This CC does not have Carrier Indicator Field - // ue_dl_cfg.blablabla = sched_info->other_r10().pdsch_start_r10; - // ue_dl_cfg.blablabla = sched_info->other_r10().sched_cell_id_r10; - } - } - - // Parse pdsch config dedicated - if (non_ul_cfg->pdsch_cfg_ded_r10_present) { - ue_dl_cfg.cfg.pdsch.p_b = phy_cfg->rr_cfg_common_scell_r10.non_ul_cfg_r10.pdsch_cfg_common_r10.p_b; - ue_dl_cfg.cfg.pdsch.p_a = non_ul_cfg->pdsch_cfg_ded_r10.p_a.to_number(); - ue_dl_cfg.cfg.pdsch.power_scale = true; - } - } - - // Parse UL Configuration - if (phys_cfg_ded_scell_r10->ul_cfg_r10_present) { - typedef phys_cfg_ded_scell_r10_s::ul_cfg_r10_s_ ul_cfg_t; - ul_cfg_t* ul_cfg = &phys_cfg_ded_scell_r10->ul_cfg_r10; - - // Parse CQI param - if (ul_cfg->cqi_report_cfg_scell_r10_present) { - cqi_report_cfg_scell_r10_s* cqi_report_cfg = &ul_cfg->cqi_report_cfg_scell_r10; - - // Aperiodic report - if (cqi_report_cfg->cqi_report_mode_aperiodic_r10_present) { - ue_dl_cfg.cfg.cqi_report.aperiodic_configured = true; - ue_dl_cfg.cfg.cqi_report.aperiodic_mode = aperiodic_mode(cqi_report_cfg->cqi_report_mode_aperiodic_r10); - } - - // Periodic report - if (cqi_report_cfg->cqi_report_periodic_scell_r10_present) { - if (cqi_report_cfg->cqi_report_periodic_scell_r10.type() == setup_e::setup) { - typedef cqi_report_periodic_r10_c::setup_s_ cqi_cfg_t; - cqi_cfg_t cqi_cfg = cqi_report_cfg->cqi_report_periodic_scell_r10.setup(); - ue_dl_cfg.cfg.cqi_report.periodic_configured = true; - ue_dl_cfg.cfg.cqi_report.pmi_idx = cqi_cfg.cqi_pmi_cfg_idx; - ue_dl_cfg.cfg.cqi_report.format_is_subband = - cqi_cfg.cqi_format_ind_periodic_r10.type().value == - cqi_cfg_t::cqi_format_ind_periodic_r10_c_::types::subband_cqi_r10; - if (ue_dl_cfg.cfg.cqi_report.format_is_subband) { - ue_dl_cfg.cfg.cqi_report.subband_size = cqi_cfg.cqi_format_ind_periodic_r10.subband_cqi_r10().k; - } - if (cqi_cfg.ri_cfg_idx_present) { - ue_dl_cfg.cfg.cqi_report.ri_idx = cqi_cfg.ri_cfg_idx; - ue_dl_cfg.cfg.cqi_report.ri_idx_present = true; - } else { - ue_dl_cfg.cfg.cqi_report.ri_idx_present = false; - } - } else { - // Release, disable periodic reporting - ue_dl_cfg.cfg.cqi_report.periodic_configured = false; - } - } - } - - if (ul_cfg->srs_ul_cfg_ded_r10_present) { - // Sounding reference signals - if (ul_cfg->srs_ul_cfg_ded_r10.type() == setup_e::setup) { - srs_ul_cfg_ded_c::setup_s_* srs_ul_cfg_ded_r10 = &ul_cfg->srs_ul_cfg_ded_r10.setup(); - ue_ul_cfg.ul_cfg.srs.I_srs = srs_ul_cfg_ded_r10->srs_cfg_idx; - ue_ul_cfg.ul_cfg.srs.B = srs_ul_cfg_ded_r10->srs_bw; - ue_ul_cfg.ul_cfg.srs.b_hop = srs_ul_cfg_ded_r10->srs_hop_bw; - ue_ul_cfg.ul_cfg.srs.n_rrc = srs_ul_cfg_ded_r10->freq_domain_position; - ue_ul_cfg.ul_cfg.srs.k_tc = srs_ul_cfg_ded_r10->tx_comb; - ue_ul_cfg.ul_cfg.srs.n_srs = srs_ul_cfg_ded_r10->cyclic_shift; - } else { - ue_ul_cfg.ul_cfg.srs.configured = false; - } - } - } - - if (phys_cfg_ded_scell_r10->cqi_report_cfg_scell_v1250_present) { - auto cqi_report_cfg_scell = phys_cfg_ded_scell_r10->cqi_report_cfg_scell_v1250.get(); - - // Enable/disable PDSCH 256QAM - ue_dl_cfg.pdsch_use_tbs_index_alt = cqi_report_cfg_scell->alt_cqi_table_r12_present; - } else { - // Assume there is no PDSCH 256QAM - ue_dl_cfg.pdsch_use_tbs_index_alt = false; - } - } - } -} - int cc_worker::read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna) { uint32_t i = 0; diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 5558d1257..e023dbbc0 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -341,7 +341,9 @@ uint32_t phy::get_current_earfcn() { void phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) { + n_ta = 0; sfsync.set_time_adv_sec(0.0f); + common.reset_radio(); if (!prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm)) { Error("Preparing PRACH to send\n"); } @@ -421,130 +423,99 @@ void phy::enable_pregen_signals(bool enable) } } -void phy::set_config(phy_interface_rrc_lte::phy_cfg_t* phy_cfg) +void phy::set_config(srslte::phy_cfg_t& config, uint32_t cc_idx, uint32_t earfcn, srslte_cell_t* cell_info) { - if (is_initiated()) { - for (uint32_t i = 0; i < nof_workers; i++) { - workers[i]->set_pcell_config(phy_cfg); - } + if (!is_initiated()) { + fprintf(stderr, "Error calling set_config(): PHY not initialized\n"); + return; } - // Save PRACH configuration - prach_cfg.config_idx = phy_cfg->common.prach_cnfg.prach_cfg_info.prach_cfg_idx; - prach_cfg.root_seq_idx = phy_cfg->common.prach_cnfg.root_seq_idx; - prach_cfg.zero_corr_zone = phy_cfg->common.prach_cnfg.prach_cfg_info.zero_correlation_zone_cfg; - prach_cfg.freq_offset = phy_cfg->common.prach_cnfg.prach_cfg_info.prach_freq_offset; - prach_cfg.hs_flag = phy_cfg->common.prach_cnfg.prach_cfg_info.high_speed_flag; -} - -void phy::set_config_scell(asn1::rrc::scell_to_add_mod_r10_s* scell_config) -{ - // Enable CSI request extra bit - common.multiple_csi_request_enabled = true; - - uint32_t cc_idx = scell_config->s_cell_idx_r10; // Component carrier index zero should be reserved for PCell - if (cc_idx != 0 && cc_idx < args.nof_carriers) { + if (cc_idx < args.nof_carriers) { carrier_map_t* m = &args.carrier_map[cc_idx]; - srslte_cell_t cell = {}; - uint32_t earfcn = 0; - - // Initialise default parameters from primary cell - sfsync.get_current_cell(&cell, &earfcn); - - // Parse identification - if (scell_config->cell_identif_r10_present) { - cell.id = scell_config->cell_identif_r10.pci_r10; - earfcn = scell_config->cell_identif_r10.dl_carrier_freq_r10; - } - - // Parse radio resource - if (scell_config->rr_cfg_common_scell_r10_present) { - rr_cfg_common_scell_r10_s* rr_cfg = &scell_config->rr_cfg_common_scell_r10; - cell.frame_type = (rr_cfg->tdd_cfg_v1130_present) ? SRSLTE_TDD : SRSLTE_FDD; - cell.nof_prb = rr_cfg->non_ul_cfg_r10.dl_bw_r10.to_number(); - cell.nof_ports = rr_cfg->non_ul_cfg_r10.ant_info_common_r10.ant_ports_count.to_number(); - cell.phich_length = (srslte_phich_length_t)rr_cfg->non_ul_cfg_r10.phich_cfg_r10.phich_dur.value; - cell.phich_resources = (srslte_phich_r_t)rr_cfg->non_ul_cfg_r10.phich_cfg_r10.phich_res.value; - } // Send configuration to workers for (uint32_t i = 0; i < nof_workers; i++) { - workers[i]->set_cell(cc_idx, cell); - workers[i]->set_scell_config(cc_idx, scell_config); + if (cell_info) { + workers[i]->set_cell(cc_idx, *cell_info); + } + workers[i]->set_config(cc_idx, config); } - // If SCell does not share synchronism with PCell ... - if (m->radio_idx > 0) { - scell_sync.at(m->radio_idx - 1)->set_scell_cell(cc_idx, &cell, earfcn); - } else { - // Change frequency only if the earfcn was modified - if (common.scell_cfg[cc_idx].earfcn != earfcn) { - float dl_freq = srslte_band_fd(earfcn) * 1e6f; - float ul_freq = srslte_band_fu(srslte_band_ul_earfcn(earfcn)) * 1e6f; - for (uint32_t p = 0; p < common.args->nof_rx_ant; p++) { - radio->set_rx_freq(m->radio_idx, m->channel_idx + p, dl_freq); - radio->set_tx_freq(m->radio_idx, m->channel_idx + p, ul_freq); + if (cc_idx == 0) { + prach_cfg = config.prach_cfg; + } else if (cell_info) { + // If SCell does not share synchronism with PCell ... + if (m->radio_idx > 0) { + scell_sync.at(m->radio_idx - 1)->set_scell_cell(cc_idx, cell_info, earfcn); + } else { + // Change frequency only if the earfcn was modified + if (common.scell_cfg[cc_idx].earfcn != earfcn) { + float dl_freq = srslte_band_fd(earfcn) * 1e6f; + float ul_freq = srslte_band_fu(srslte_band_ul_earfcn(earfcn)) * 1e6f; + for (uint32_t p = 0; p < common.args->nof_rx_ant; p++) { + radio->set_rx_freq(m->radio_idx, m->channel_idx + p, dl_freq); + radio->set_tx_freq(m->radio_idx, m->channel_idx + p, ul_freq); + } } } + + // Store SCell earfcn and pci + common.scell_cfg[cc_idx].earfcn = earfcn; + common.scell_cfg[cc_idx].pci = cell_info->id; + common.scell_cfg[cc_idx].configured = true; + common.scell_cfg[cc_idx].enabled = false; + } else { + Error("Configuring Scell index %d but cell_info not provided\n", cc_idx); } - // Store SCell earfcn and pci - common.scell_cfg[cc_idx].earfcn = earfcn; - common.scell_cfg[cc_idx].pci = cell.id; - common.scell_cfg[cc_idx].configured = true; - common.scell_cfg[cc_idx].enabled = false; } else { - log_h->console("Received SCell configuration for index %d but there are not enough CC workers available\n", - scell_config->s_cell_idx_r10); + log_h->console("Received SCell configuration for index %d but there are not enough CC workers available\n", cc_idx); } } -void phy::set_config_tdd(tdd_cfg_s* tdd) +void phy::set_config_tdd(srslte_tdd_config_t& tdd_config_) { - tdd_config.sf_config = tdd->sf_assign.to_number(); - tdd_config.ss_config = tdd->special_sf_patterns.to_number(); - tdd_config.configured = true; + tdd_config = tdd_config_; if (!tdd_config.configured) { log_h->console("Setting TDD-config: %d, SS config: %d\n", tdd_config.sf_config, tdd_config.ss_config); } + tdd_config.configured = true; for (uint32_t i = 0; i < nof_workers; i++) { workers[i]->set_tdd_config(tdd_config); } } -void phy::set_config_mbsfn_sib2(sib_type2_s* sib2) +void phy::set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) { - if (sib2->mbsfn_sf_cfg_list_present and sib2->mbsfn_sf_cfg_list.size() > 1) { - Warning("SIB2 has %d MBSFN subframe configs - only 1 supported\n", sib2->mbsfn_sf_cfg_list.size()); + if (nof_cfgs > 1) { + Warning("SIB2 has %d MBSFN subframe configs - only 1 supported\n", nof_cfgs); } - if (sib2->mbsfn_sf_cfg_list_present and sib2->mbsfn_sf_cfg_list.size() > 0) { - common.mbsfn_config.mbsfn_subfr_cnfg = sib2->mbsfn_sf_cfg_list[0]; + if (nof_cfgs > 0) { + common.mbsfn_config.mbsfn_subfr_cnfg = cfg_list[0]; common.build_mch_table(); } } -void phy::set_config_mbsfn_sib13(sib_type13_r9_s* sib13) +void phy::set_config_mbsfn_sib13(const srslte::sib13_t& sib13) { - common.mbsfn_config.mbsfn_notification_cnfg = sib13->notif_cfg_r9; - if (sib13->mbsfn_area_info_list_r9.size() > 1) { - Warning("SIB13 has %d MBSFN area info elements - only 1 supported\n", sib13->mbsfn_area_info_list_r9.size()); + common.mbsfn_config.mbsfn_notification_cnfg = sib13.notif_cfg; + if (sib13.nof_mbsfn_area_info > 1) { + Warning("SIB13 has %d MBSFN area info elements - only 1 supported\n", sib13.nof_mbsfn_area_info); } - if (sib13->mbsfn_area_info_list_r9.size() > 0) { - common.mbsfn_config.mbsfn_area_info = sib13->mbsfn_area_info_list_r9[0]; + if (sib13.nof_mbsfn_area_info > 0) { + common.mbsfn_config.mbsfn_area_info = sib13.mbsfn_area_info_list[0]; common.build_mcch_table(); } } -void phy::set_config_mbsfn_mcch(mcch_msg_s* mcch) +void phy::set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) { - common.mbsfn_config.mcch = *mcch; - stack->set_mbsfn_config( - common.mbsfn_config.mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9.size()); - common.set_mch_period_stop( - common.mbsfn_config.mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].pmch_cfg_r9.sf_alloc_end_r9); + common.mbsfn_config.mcch = mcch; + stack->set_mbsfn_config(common.mbsfn_config.mcch.pmch_info_list[0].nof_mbms_session_info); + common.set_mch_period_stop(common.mbsfn_config.mcch.pmch_info_list[0].sf_alloc_end); common.set_mcch(); } diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index f7eac17ed..d3938ae94 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -42,65 +42,22 @@ using namespace asn1::rrc; namespace srsue { -static cf_t zeros[50000]; -static cf_t* zeros_multi[SRSLTE_MAX_PORTS]; - -phy_common::phy_common(uint32_t max_workers) : tx_sem(max_workers) -{ - args = NULL; - log_h = NULL; - radio_h = NULL; - stack = NULL; - this->max_workers = max_workers; - rx_gain_offset = 0; - // have_mtch_stop = false; - - pthread_mutex_init(&pending_ul_ack_mutex, NULL); - pthread_mutex_init(&pending_dl_ack_mutex, NULL); - pthread_mutex_init(&pending_ul_grant_mutex, NULL); - pthread_mutex_init(&received_ul_ack_mutex, NULL); - pthread_mutex_init(&mtch_mutex, NULL); - pthread_cond_init(&mtch_cvar, NULL); - - bzero(&dl_metrics, sizeof(dl_metrics_t) * SRSLTE_MAX_CARRIERS); - dl_metrics_read = true; - dl_metrics_count = 0; - bzero(&ul_metrics, sizeof(ul_metrics_t) * SRSLTE_MAX_CARRIERS); - ul_metrics_read = true; - ul_metrics_count = 0; - ZERO_OBJECT(sync_metrics); - sync_metrics_read = true; - sync_metrics_count = 0; +static cf_t zeros[50000] = {}; +static cf_t* zeros_multi[SRSLTE_MAX_PORTS] = {zeros, zeros, zeros, zeros}; - rar_grant_tti = -1; - - bzero(zeros, 50000 * sizeof(cf_t)); - for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { - zeros_multi[p] = zeros; - } - - for (int i = 0; i < TTIMOD_SZ; i++) { - for (int j = 0; j < SRSLTE_MAX_CARRIERS; j++) { - bzero(&received_ul_ack[i][j], sizeof(received_ul_ack_t)); - } - } +phy_common::phy_common(uint32_t max_workers_) : tx_sem(max_workers_) +{ + max_workers = max_workers_; for (uint32_t i = 0; i < max_workers; i++) { sem_init(&tx_sem[i], 0, 0); // All semaphores start blocked } reset(); - - sib13_configured = false; - mcch_configured = false; } phy_common::~phy_common() { - pthread_mutex_destroy(&pending_ul_ack_mutex); - pthread_mutex_destroy(&pending_dl_ack_mutex); - pthread_mutex_destroy(&pending_ul_grant_mutex); - pthread_mutex_destroy(&received_ul_ack_mutex); for (uint32_t i = 0; i < max_workers; i++) { sem_post(&tx_sem[i]); } @@ -109,9 +66,9 @@ phy_common::~phy_common() } } -void phy_common::set_nof_workers(uint32_t nof_workers) +void phy_common::set_nof_workers(uint32_t nof_workers_) { - this->nof_workers = nof_workers; + nof_workers = nof_workers_; } void phy_common::init(phy_args_t* _args, @@ -150,9 +107,9 @@ void phy_common::set_ue_dl_cfg(srslte_ue_dl_cfg_t* ue_dl_cfg) } chest_cfg->filter_type = SRSLTE_CHEST_FILTER_GAUSS; - if (!args->snr_estim_alg.compare("refs")) { + if (args->snr_estim_alg == "refs") { chest_cfg->noise_alg = SRSLTE_NOISE_ALG_REFS; - } else if (!args->snr_estim_alg.compare("empty")) { + } else if (args->snr_estim_alg == "empty") { chest_cfg->noise_alg = SRSLTE_NOISE_ALG_EMPTY; } else { chest_cfg->noise_alg = SRSLTE_NOISE_ALG_PSS; @@ -170,7 +127,7 @@ void phy_common::set_pdsch_cfg(srslte_pdsch_cfg_t* pdsch_cfg) bzero(pdsch_cfg, sizeof(srslte_pdsch_cfg_t)); pdsch_cfg->csi_enable = args->pdsch_csi_enabled; pdsch_cfg->max_nof_iterations = args->pdsch_max_its; - pdsch_cfg->decoder_type = !args->equalizer_mode.compare("zf") ? SRSLTE_MIMO_DECODER_ZF : SRSLTE_MIMO_DECODER_MMSE; + pdsch_cfg->decoder_type = (args->equalizer_mode == "zf") ? SRSLTE_MIMO_DECODER_ZF : SRSLTE_MIMO_DECODER_MMSE; } void phy_common::set_ue_ul_cfg(srslte_ue_ul_cfg_t* ue_ul_cfg) @@ -198,9 +155,9 @@ void phy_common::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRAN srslte_tdd_config_t tdd_config) { - if (MSG3_DELAY_MS < 0) { - ERROR("Error MSG3_DELAY_MS can't be negative\n"); - } +#if MSG3_DELAY_MS < 0 +#error "Error MSG3_DELAY_MS can't be negative" +#endif /* MSG3_DELAY_MS < 0 */ if (rar_grant_tti < 0) { Error("Must call set_rar_grant_tti before set_rar_grant\n"); @@ -230,7 +187,7 @@ void phy_common::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRAN } // Save Msg3 UL dci - pthread_mutex_lock(&pending_ul_grant_mutex); + std::lock_guard lock(pending_ul_grant_mutex); if (!pending_ul_grant[TTIMOD(msg3_tx_tti)][0].enable) { Debug("RAR grant rar_grant=%d, msg3_tti=%d, stored in index=%d\n", rar_grant_tti, msg3_tx_tti, TTIMOD(msg3_tx_tti)); pending_ul_grant[TTIMOD(msg3_tx_tti)][0].pid = ul_pidof(msg3_tx_tti, &tdd_config); @@ -239,7 +196,6 @@ void phy_common::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRAN } else { Warning("set_rar_grant: sf->tti=%d, cc=%d already in use\n", msg3_tx_tti, 0); } - pthread_mutex_unlock(&pending_ul_grant_mutex); rar_grant_tti = -1; } @@ -324,7 +280,7 @@ void phy_common::set_ul_pending_ack(srslte_ul_sf_cfg_t* sf, srslte_dci_ul_t* dci_ul) { // Use a lock here because subframe 4 and 9 of TDD config 0 accept multiple PHICH from multiple frames - pthread_mutex_lock(&pending_ul_ack_mutex); + std::lock_guard lock(pending_ul_ack_mutex); if (!pending_ul_ack[TTIMOD(tti_phich(sf))][cc_idx][phich_grant.I_phich].enable) { pending_ul_ack[TTIMOD(tti_phich(sf))][cc_idx][phich_grant.I_phich].dci_ul = *dci_ul; @@ -338,7 +294,6 @@ void phy_common::set_ul_pending_ack(srslte_ul_sf_cfg_t* sf, } else { Warning("set_ul_pending_ack: sf->tti=%d, cc=%d already in use\n", sf->tti, cc_idx); } - pthread_mutex_unlock(&pending_ul_ack_mutex); } // Here SF->TTI is when PHICH is being transmitted so that's DL subframe @@ -347,7 +302,7 @@ bool phy_common::get_ul_pending_ack(srslte_dl_sf_cfg_t* sf, srslte_phich_grant_t* phich_grant, srslte_dci_ul_t* dci_ul) { - pthread_mutex_lock(&pending_ul_ack_mutex); + std::lock_guard lock(pending_ul_ack_mutex); bool ret = false; if (pending_ul_ack[TTIMOD(sf->tti)][cc_idx][phich_grant->I_phich].enable) { *phich_grant = pending_ul_ack[TTIMOD(sf->tti)][cc_idx][phich_grant->I_phich].phich_grant; @@ -356,26 +311,20 @@ bool phy_common::get_ul_pending_ack(srslte_dl_sf_cfg_t* sf, pending_ul_ack[TTIMOD(sf->tti)][cc_idx][phich_grant->I_phich].enable = false; Debug("Get pending ACK for sf->tti=%d n_dmrs=%d, I_phich=%d\n", sf->tti, phich_grant->n_dmrs, phich_grant->I_phich); } - pthread_mutex_unlock(&pending_ul_ack_mutex); return ret; } bool phy_common::is_any_ul_pending_ack() { - pthread_mutex_lock(&pending_ul_ack_mutex); + std::lock_guard lock(pending_ul_ack_mutex); bool ret = false; - for (int i = 0; i < TTIMOD_SZ; i++) { - for (int n = 0; n < SRSLTE_MAX_CARRIERS; n++) { - for (int j = 0; j < 2; j++) { - if (pending_ul_ack[i][n][j].enable) { - ret = true; - goto unlock_exit; - } + for (int i = 0; i < TTIMOD_SZ && !ret; i++) { + for (int n = 0; n < SRSLTE_MAX_CARRIERS && !ret; n++) { + for (int j = 0; j < 2 && !ret; j++) { + ret = pending_ul_ack[i][n][j].enable; } } } -unlock_exit: - pthread_mutex_unlock(&pending_ul_ack_mutex); return ret; } @@ -394,8 +343,7 @@ unlock_exit: // SF->TTI is at which Format0 dci is received void phy_common::set_ul_pending_grant(srslte_dl_sf_cfg_t* sf, uint32_t cc_idx, srslte_dci_ul_t* dci) { - - pthread_mutex_lock(&pending_ul_grant_mutex); + std::lock_guard lock(pending_ul_grant_mutex); // Calculate PID for this SF->TTI uint32_t pid = ul_pidof(tti_pusch_gr(sf), &sf->tdd_config); @@ -408,13 +356,12 @@ void phy_common::set_ul_pending_grant(srslte_dl_sf_cfg_t* sf, uint32_t cc_idx, s } else { Warning("set_ul_pending_grant: sf->tti=%d, cc=%d already in use\n", sf->tti, cc_idx); } - pthread_mutex_unlock(&pending_ul_grant_mutex); } // SF->TTI at which PUSCH should be transmitted bool phy_common::get_ul_pending_grant(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, uint32_t* pid, srslte_dci_ul_t* dci) { - pthread_mutex_lock(&pending_ul_grant_mutex); + std::lock_guard lock(pending_ul_grant_mutex); bool ret = false; if (pending_ul_grant[TTIMOD(sf->tti)][cc_idx].enable) { Debug("Reading grant sf->tti=%d idx=%d\n", sf->tti, TTIMOD(sf->tti)); @@ -427,7 +374,7 @@ bool phy_common::get_ul_pending_grant(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, u pending_ul_grant[TTIMOD(sf->tti)][cc_idx].enable = false; ret = true; } - pthread_mutex_unlock(&pending_ul_grant_mutex); + return ret; } @@ -435,18 +382,17 @@ bool phy_common::get_ul_pending_grant(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, u void phy_common::set_ul_received_ack( srslte_dl_sf_cfg_t* sf, uint32_t cc_idx, bool ack_value, uint32_t I_phich, srslte_dci_ul_t* dci_ul) { - pthread_mutex_lock(&received_ul_ack_mutex); + std::lock_guard lock(received_ul_ack_mutex); received_ul_ack[TTIMOD(tti_pusch_hi(sf))][cc_idx].hi_present = true; received_ul_ack[TTIMOD(tti_pusch_hi(sf))][cc_idx].hi_value = ack_value; received_ul_ack[TTIMOD(tti_pusch_hi(sf))][cc_idx].dci_ul = *dci_ul; Debug("Set ul received ack for sf->tti=%d, current_tti=%d\n", tti_pusch_hi(sf), sf->tti); - pthread_mutex_unlock(&received_ul_ack_mutex); } // SF->TTI at which PUSCH will be transmitted bool phy_common::get_ul_received_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, bool* ack_value, srslte_dci_ul_t* dci_ul) { - pthread_mutex_lock(&received_ul_ack_mutex); + std::lock_guard lock(received_ul_ack_mutex); bool ret = false; if (received_ul_ack[TTIMOD(sf->tti)][cc_idx].hi_present) { if (ack_value) { @@ -459,7 +405,6 @@ bool phy_common::get_ul_received_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, bo received_ul_ack[TTIMOD(sf->tti)][cc_idx].hi_present = false; ret = true; } - pthread_mutex_unlock(&received_ul_ack_mutex); return ret; } @@ -469,7 +414,7 @@ void phy_common::set_dl_pending_ack(srslte_dl_sf_cfg_t* sf, uint8_t value[SRSLTE_MAX_CODEWORDS], srslte_pdsch_ack_resource_t resource) { - pthread_mutex_lock(&pending_dl_ack_mutex); + std::lock_guard lock(pending_dl_ack_mutex); if (!pending_dl_ack[TTIMOD(sf->tti)][cc_idx].enable) { pending_dl_ack[TTIMOD(sf->tti)][cc_idx].enable = true; pending_dl_ack[TTIMOD(sf->tti)][cc_idx].resource = resource; @@ -478,7 +423,6 @@ void phy_common::set_dl_pending_ack(srslte_dl_sf_cfg_t* sf, } else { Warning("pending_dl_ack: sf->tti=%d, cc=%d already in use\n", sf->tti, cc_idx); } - pthread_mutex_unlock(&pending_dl_ack_mutex); } void phy_common::set_rar_grant_tti(uint32_t tti) @@ -486,6 +430,38 @@ void phy_common::set_rar_grant_tti(uint32_t tti) rar_grant_tti = tti; } +void phy_common::set_dl_pending_grant(uint32_t tti, + uint32_t cc_idx, + uint32_t grant_cc_idx, + const srslte_dci_dl_t* dl_dci) +{ + if (!pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].enable) { + pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].dl_dci = *dl_dci; + pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].grant_cc_idx = grant_cc_idx; + pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].enable = true; + } else { + Warning("set_dl_pending_grant: cc=%d already exists\n", cc_idx); + } +} + +bool phy_common::get_dl_pending_grant(uint32_t tti, uint32_t cc_idx, uint32_t* grant_cc_idx, srslte_dci_dl_t* dl_dci) +{ + if (pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].enable) { + // Read grant + if (dl_dci) { + *dl_dci = pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].dl_dci; + } + if (grant_cc_idx) { + *grant_cc_idx = pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].grant_cc_idx; + } + // Reset read flag + pending_dl_grant[tti % FDD_HARQ_DELAY_MS][cc_idx].enable = false; + return true; + } else { + return false; + } +} + typedef struct { uint32_t M; uint32_t K[9]; @@ -513,7 +489,7 @@ das_index_t das_table[7][10] = { // SF->TTI at which ACK/NACK would be transmitted bool phy_common::get_dl_pending_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, srslte_pdsch_ack_cc_t* ack) { - pthread_mutex_lock(&pending_dl_ack_mutex); + std::lock_guard lock(pending_dl_ack_mutex); bool ret = false; uint32_t M; if (cell.frame_type == SRSLTE_FDD) { @@ -544,7 +520,6 @@ bool phy_common::get_dl_pending_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, srs bzero(&pending_dl_ack[TTIMOD(pdsch_tti)][cc_idx], sizeof(received_ack_t)); } ack->M = ret ? M : 0; - pthread_mutex_unlock(&pending_dl_ack_mutex); return ret; } @@ -582,22 +557,25 @@ void phy_common::worker_end(uint32_t tti, } radio_h->tx(i, buffer[i], nof_samples[i], tx_time[i]); - is_first_of_burst[i] = false; } else { if (radio_h->is_continuous_tx()) { - if (!is_first_of_burst[i]) { + if (is_pending_tx_end) { + radio_h->tx_end(); + is_pending_tx_end = false; + } else { + if (!radio_h->get_is_start_of_burst(i)) { - if (ul_channel && !srslte_timestamp_iszero(&tx_time[i])) { - bzero(zeros_multi[0], sizeof(cf_t) * nof_samples[i]); - ul_channel->run(zeros_multi, zeros_multi, nof_samples[i], tx_time[i]); - } + if (ul_channel && !srslte_timestamp_iszero(&tx_time[i])) { + bzero(zeros_multi[0], sizeof(cf_t) * nof_samples[i]); + ul_channel->run(zeros_multi, zeros_multi, nof_samples[i], tx_time[i]); + } - radio_h->tx(i, zeros_multi, nof_samples[i], tx_time[i]); + radio_h->tx(i, zeros_multi, nof_samples[i], tx_time[i]); + } } } else { - if (!is_first_of_burst[i]) { + if (i == 0) { radio_h->tx_end(); - is_first_of_burst[i] = true; } } } @@ -616,11 +594,6 @@ void phy_common::set_cell(const srslte_cell_t& c) } } -uint32_t phy_common::get_nof_prb() -{ - return cell.nof_prb; -} - void phy_common::set_dl_metrics(const dl_metrics_t m, uint32_t cc_idx) { if (dl_metrics_read) { @@ -692,14 +665,24 @@ void phy_common::get_sync_metrics(sync_metrics_t m[SRSLTE_MAX_CARRIERS]) sync_metrics_read = true; } +void phy_common::reset_radio() +{ + is_first_tx = true; + + // End Tx streams even if they are continuous + // Since is_first_of_burst is set to true, the radio need to send + // end of burst in order to stall correctly the Tx stream. + // This is required for UHD version 3.10 and newer. + is_pending_tx_end = true; +} + void phy_common::reset() { + reset_radio(); + sr_enabled = false; - is_first_tx = true; cur_pathloss = 0; cur_pusch_power = 0; - p0_preamble = 0; - cur_radio_power = 0; sr_last_tx_tti = -1; cur_pusch_power = 0; ZERO_OBJECT(pathloss); @@ -711,13 +694,6 @@ void phy_common::reset() pcell_report_period = 20; - for (int i = 0; i < SRSLTE_MAX_RADIOS; i++) { - is_first_of_burst[i] = true; - } - - multiple_csi_request_enabled = false; - cif_enabled = false; - srs_request_enabled = false; ZERO_OBJECT(pending_dl_ack); ZERO_OBJECT(pending_dl_dai); ZERO_OBJECT(pending_ul_ack); @@ -734,11 +710,10 @@ void phy_common::build_mch_table() bzero(&mch_table[0], sizeof(uint8_t) * 40); // 40 element table represents 4 frames (40 subframes) - if (mbsfn_config.mbsfn_subfr_cnfg.sf_alloc.type() == asn1::rrc::mbsfn_sf_cfg_s::sf_alloc_c_::types::one_frame) { - generate_mch_table(&mch_table[0], (uint32_t)mbsfn_config.mbsfn_subfr_cnfg.sf_alloc.one_frame().to_number(), 1u); - } else if (mbsfn_config.mbsfn_subfr_cnfg.sf_alloc.type() == - asn1::rrc::mbsfn_sf_cfg_s::sf_alloc_c_::types::four_frames) { - generate_mch_table(&mch_table[0], (uint32_t)mbsfn_config.mbsfn_subfr_cnfg.sf_alloc.four_frames().to_number(), 4u); + if (mbsfn_config.mbsfn_subfr_cnfg.nof_alloc_subfrs == srslte::mbsfn_sf_cfg_t::sf_alloc_type_t::one_frame) { + generate_mch_table(&mch_table[0], (uint32_t)mbsfn_config.mbsfn_subfr_cnfg.sf_alloc, 1u); + } else if (mbsfn_config.mbsfn_subfr_cnfg.nof_alloc_subfrs == srslte::mbsfn_sf_cfg_t::sf_alloc_type_t::four_frames) { + generate_mch_table(&mch_table[0], (uint32_t)mbsfn_config.mbsfn_subfr_cnfg.sf_alloc, 4u); } else { log_h->error("The subframe config has not been set for MBSFN\n"); } @@ -756,7 +731,7 @@ void phy_common::build_mcch_table() { // First reset tables bzero(&mcch_table[0], sizeof(uint8_t) * 10); - generate_mcch_table(&mcch_table[0], (uint32_t)mbsfn_config.mbsfn_area_info.mcch_cfg_r9.sf_alloc_info_r9.to_number()); + generate_mcch_table(&mcch_table[0], (uint32_t)mbsfn_config.mbsfn_area_info.mcch_cfg.sf_alloc_info); // Debug std::stringstream ss; ss << "|"; @@ -774,11 +749,10 @@ void phy_common::set_mcch() void phy_common::set_mch_period_stop(uint32_t stop) { - pthread_mutex_lock(&mtch_mutex); + std::lock_guard lock(mtch_mutex); have_mtch_stop = true; mch_period_stop = stop; - pthread_cond_signal(&mtch_cvar); - pthread_mutex_unlock(&mtch_mutex); + mtch_cvar.notify_one(); } bool phy_common::is_mch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti) @@ -806,32 +780,32 @@ bool phy_common::is_mch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti) // Not MCCH, check for MCH if (sib13_configured) { - mbsfn_sf_cfg_s* subfr_cnfg = &mbsfn_config.mbsfn_subfr_cnfg; - asn1::rrc::mbsfn_area_info_r9_s* area_info = &mbsfn_config.mbsfn_area_info; - offset = subfr_cnfg->radioframe_alloc_offset; - period = subfr_cnfg->radioframe_alloc_period.to_number(); + srslte::mbsfn_sf_cfg_t& subfr_cnfg = mbsfn_config.mbsfn_subfr_cnfg; + srslte::mbsfn_area_info_t& area_info = mbsfn_config.mbsfn_area_info; + offset = subfr_cnfg.radioframe_alloc_offset; + period = srslte::enum_to_number(subfr_cnfg.radioframe_alloc_period); - if (subfr_cnfg->sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::one_frame) { + if (subfr_cnfg.nof_alloc_subfrs == srslte::mbsfn_sf_cfg_t::sf_alloc_type_t::one_frame) { if ((sfn % period == offset) && (mch_table[sf] > 0)) { - cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; - cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number(); + cfg->mbsfn_area_id = area_info.mbsfn_area_id; + cfg->non_mbsfn_region_length = enum_to_number(area_info.non_mbsfn_region_len); if (mcch_configured) { // Iterate through PMCH configs to see which one applies in the current frame - mbsfn_area_cfg_r9_s* mcch = &mbsfn_config.mcch.msg.c1().mbsfn_area_cfg_r9(); - uint32_t mbsfn_per_frame = mcch->pmch_info_list_r9[0].pmch_cfg_r9.sf_alloc_end_r9 / - mcch->pmch_info_list_r9[0].pmch_cfg_r9.mch_sched_period_r9.to_number(); - uint32_t frame_alloc_idx = sfn % mcch->common_sf_alloc_period_r9.to_number(); + srslte::mcch_msg_t& mcch = mbsfn_config.mcch; + uint32_t mbsfn_per_frame = + mcch.pmch_info_list[0].sf_alloc_end / enum_to_number(mcch.pmch_info_list[0].mch_sched_period); + uint32_t frame_alloc_idx = sfn % enum_to_number(mcch.common_sf_alloc_period); uint32_t sf_alloc_idx = frame_alloc_idx * mbsfn_per_frame + ((sf < 4) ? sf - 1 : sf - 3); - pthread_mutex_lock(&mtch_mutex); + std::unique_lock lock(mtch_mutex); while (!have_mtch_stop) { - pthread_cond_wait(&mtch_cvar, &mtch_mutex); + mtch_cvar.wait(lock); } - pthread_mutex_unlock(&mtch_mutex); + lock.unlock(); - for (uint32_t i = 0; i < mcch->pmch_info_list_r9.size(); i++) { + for (uint32_t i = 0; i < mcch.nof_pmch_info; i++) { if (sf_alloc_idx <= mch_period_stop) { // trigger conditional variable, has ot be untriggered by mtch stop location - cfg->mbsfn_mcs = mcch->pmch_info_list_r9[i].pmch_cfg_r9.data_mcs_r9; + cfg->mbsfn_mcs = mcch.pmch_info_list[i].data_mcs; cfg->enable = true; } else { // have_mtch_stop = false; @@ -841,12 +815,12 @@ bool phy_common::is_mch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti) } return true; } - } else if (subfr_cnfg->sf_alloc.type() == mbsfn_sf_cfg_s::sf_alloc_c_::types::four_frames) { + } else if (subfr_cnfg.nof_alloc_subfrs == srslte::mbsfn_sf_cfg_t::sf_alloc_type_t::four_frames) { uint8_t idx = sfn % period; if ((idx >= offset) && (idx < offset + 4)) { if (mch_table[(idx * 10) + sf] > 0) { - cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; - cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number(); + cfg->mbsfn_area_id = area_info.mbsfn_area_id; + cfg->non_mbsfn_region_length = enum_to_number(area_info.non_mbsfn_region_len); // TODO: check for MCCH configuration, set MCS and decode return true; } @@ -870,15 +844,15 @@ bool phy_common::is_mcch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti) sf = (uint8_t)(phy_tti % 10); if (sib13_configured) { - mbsfn_area_info_r9_s* area_info = &mbsfn_config.mbsfn_area_info; + srslte::mbsfn_area_info_t& area_info = mbsfn_config.mbsfn_area_info; - offset = area_info->mcch_cfg_r9.mcch_offset_r9; - period = area_info->mcch_cfg_r9.mcch_repeat_period_r9.to_number(); + offset = area_info.mcch_cfg.mcch_offset; + period = enum_to_number(area_info.mcch_cfg.mcch_repeat_period); if ((sfn % period == offset) && mcch_table[sf] > 0) { - cfg->mbsfn_area_id = area_info->mbsfn_area_id_r9; - cfg->non_mbsfn_region_length = area_info->non_mbsfn_region_len.to_number(); - cfg->mbsfn_mcs = area_info->mcch_cfg_r9.sig_mcs_r9.to_number(); + cfg->mbsfn_area_id = area_info.mbsfn_area_id; + cfg->non_mbsfn_region_length = enum_to_number(area_info.non_mbsfn_region_len); + cfg->mbsfn_mcs = enum_to_number(area_info.mcch_cfg.sig_mcs); cfg->enable = true; have_mtch_stop = false; Debug("MCCH subframe TTI:%d\n", phy_tti); diff --git a/srsue/src/phy/prach.cc b/srsue/src/phy/prach.cc index 524bfb586..0fa4c84d0 100644 --- a/srsue/src/phy/prach.cc +++ b/srsue/src/phy/prach.cc @@ -167,7 +167,7 @@ bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, float } else { if (!cell_initiated) { Error("PRACH: Cell not configured\n"); - } else if (preamble_idx_ >= 64) { + } else { Error("PRACH: Invalid preamble %d\n", preamble_idx_); } return false; diff --git a/srsue/src/phy/scell/intra_measure.cc b/srsue/src/phy/scell/intra_measure.cc index e1fffbca9..d650feea5 100644 --- a/srsue/src/phy/scell/intra_measure.cc +++ b/srsue/src/phy/scell/intra_measure.cc @@ -38,24 +38,6 @@ namespace scell { intra_measure::intra_measure() : scell(), thread("SYNC_INTRA_MEASURE") { - - rrc = nullptr; - common = nullptr; - search_buffer = nullptr; - log_h = nullptr; - - current_earfcn = 0; - current_sflen = 0; - measure_tti = 0; - receive_cnt = 0; - - running = false; - receive_enabled = false; - receiving = false; - - ZERO_OBJECT(info); - ZERO_OBJECT(ring_buffer); - ZERO_OBJECT(primary_cell); } intra_measure::~intra_measure() @@ -72,6 +54,9 @@ void intra_measure::init(phy_common* common, rrc_interface_phy_lte* rrc, srslte: this->common = common; receive_enabled = false; + // Initialise Reference signal measurement + srslte_refsignal_dl_sync_init(&refsignal_dl_sync); + // Start scell scell.init(log_h, common->args->sic_pss_enabled, common->args->intra_freq_meas_len_ms, common); @@ -93,6 +78,7 @@ void intra_measure::stop() srslte_ringbuffer_stop(&ring_buffer); tti_sync.increase(); wait_thread_finish(); + srslte_refsignal_dl_sync_free(&refsignal_dl_sync); } void intra_measure::set_primay_cell(uint32_t earfcn, srslte_cell_t cell) @@ -187,10 +173,71 @@ void intra_measure::run_thread() search_buffer, common->rx_gain_offset, primary_cell, common->args->intra_freq_meas_len_ms, info); receiving = false; + // Look for other cells not found automatically + // Using Cell Reference signal synchronization for all known active PCI + for (auto q : active_pci) { + srslte_cell_t cell = primary_cell; + cell.id = q; + + srslte_refsignal_dl_sync_set_cell(&refsignal_dl_sync, cell); + srslte_refsignal_dl_sync_run( + &refsignal_dl_sync, search_buffer, common->args->intra_freq_meas_len_ms * current_sflen); + + if (refsignal_dl_sync.found) { + Info("INTRA: Found neighbour cell: PCI=%03d, RSRP=%5.1f dBm, RSRQ=%5.1f, peak_idx=%5d, CFO=%+.1fHz\n", + cell.id, + refsignal_dl_sync.rsrp_dBfs, + refsignal_dl_sync.rsrq_dB, + refsignal_dl_sync.peak_index, + refsignal_dl_sync.cfo_Hz); + + bool found = false; + float weakest_rsrp_value = +INFINITY; + uint32_t weakest_rsrp_index = 0; + + // Try to find PCI in info list + for (int i = 0; i < found_cells && !found; i++) { + // Finds cell, update + if (info[i].pci == cell.id) { + info[i].rsrp = refsignal_dl_sync.rsrp_dBfs; + info[i].rsrq = refsignal_dl_sync.rsrq_dB; + info[i].offset = refsignal_dl_sync.peak_index; + found = true; + } else if (weakest_rsrp_value > info[i].rsrp) { + // Update weakest + weakest_rsrp_value = info[i].rsrp; + weakest_rsrp_index = i; + } + } + + if (!found) { + // If number of cells exceeds + if (found_cells >= scell_recv::MAX_CELLS) { + // overwrite weakest cell if stronger + if (refsignal_dl_sync.rsrp_dBfs > weakest_rsrp_value) { + info[weakest_rsrp_index].pci = cell.id; + info[weakest_rsrp_index].rsrp = refsignal_dl_sync.rsrp_dBfs; + info[weakest_rsrp_index].rsrq = refsignal_dl_sync.rsrq_dB; + info[weakest_rsrp_index].offset = refsignal_dl_sync.peak_index; + } else { + // Ignore measurement + } + } else { + // Otherwise append cell + info[found_cells].pci = cell.id; + info[found_cells].rsrp = refsignal_dl_sync.rsrp_dBfs; + info[found_cells].rsrq = refsignal_dl_sync.rsrq_dB; + info[found_cells].offset = refsignal_dl_sync.peak_index; + found_cells++; + } + } + } + } + + // Send measurements to RRC for (int i = 0; i < found_cells; i++) { rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci); } - // Look for other cells not found automatically } } } diff --git a/srsue/src/phy/scell/measure.cc b/srsue/src/phy/scell/measure.cc index f5c8f4e17..f1dd0a149 100644 --- a/srsue/src/phy/scell/measure.cc +++ b/srsue/src/phy/scell/measure.cc @@ -70,6 +70,7 @@ void measure::reset() mean_rsrq = 0; mean_snr = 0; mean_rssi = 0; + mean_cfo = 0; } void measure::set_cell(srslte_cell_t cell) @@ -101,6 +102,11 @@ float measure::snr() return mean_snr; } +float measure::cfo() +{ + return mean_cfo; +} + uint32_t measure::frame_st_idx() { return final_offset; @@ -196,6 +202,7 @@ measure::ret_code measure::run_subframe(uint32_t sf_idx) float rsrp = ue_dl.chest_res.rsrp_neigh; float rsrq = ue_dl.chest_res.rsrq; float snr = ue_dl.chest_res.snr_db; + float cfo = ue_dl.chest_res.cfo; float rssi = srslte_vec_avg_power_cf(buffer[0], (uint32_t)SRSLTE_SF_LEN_PRB(current_prb)); if (cnt == 0) { @@ -203,11 +210,13 @@ measure::ret_code measure::run_subframe(uint32_t sf_idx) mean_rsrq = rsrq; mean_snr = snr; mean_rssi = rssi; + mean_cfo = cfo; } else { mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt); + mean_cfo = SRSLTE_VEC_CMA(cfo, mean_cfo, cnt); } cnt++; diff --git a/srsue/src/phy/scell/scell_recv.cc b/srsue/src/phy/scell/scell_recv.cc index ac2c00da2..c5c8a5169 100644 --- a/srsue/src/phy/scell/scell_recv.cc +++ b/srsue/src/phy/scell/scell_recv.cc @@ -64,15 +64,16 @@ void scell_recv::init(srslte::log* _log_h, bool _sic_pss_enabled, uint32_t max_s return; } srslte_sync_set_sss_algorithm(&sync_find, SSS_FULL); + srslte_sync_set_cfo_cp_enable(&sync_find, false, 0); srslte_sync_cp_en(&sync_find, false); - srslte_sync_set_cfo_pss_enable(&sync_find, true); - srslte_sync_set_threshold(&sync_find, 1.7); - srslte_sync_set_em_alpha(&sync_find, 0.3); + srslte_sync_set_cfo_pss_enable(&sync_find, false); + srslte_sync_set_threshold(&sync_find, 2.0f); // The highest the best for avoiding ghost cells + srslte_sync_set_em_alpha(&sync_find, 0.3f); + srslte_sss_set_threshold(&sync_find.sss, 300.0); // A higher value will avoid false alarms but reduce detection // Configure FIND object behaviour (this configuration is always the same) srslte_sync_set_cfo_ema_alpha(&sync_find, 1.0); srslte_sync_set_cfo_i_enable(&sync_find, false); - srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_pss_filt_enable(&sync_find, true); srslte_sync_set_sss_eq_enable(&sync_find, true); @@ -132,29 +133,48 @@ int scell_recv::find_cells( srslte_sync_cfo_reset(&sync_find); sync_res = SRSLTE_SYNC_NOFOUND; + bool sss_detected = false; cell_id = 0; float max_peak = -1; uint32_t max_sf5 = 0; uint32_t max_sf_idx = 0; + float sss_correlation_peak_max = 0.0f; + for (uint32_t sf5_cnt = 0; sf5_cnt < nof_sf / 5; sf5_cnt++) { sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt * 5 * sf_len, &peak_idx); - Debug("INTRA: n_id_2=%d, cnt=%d/%d, sync_res=%d, sf_idx=%d, peak_idx=%d, peak_value=%f\n", + Debug("INTRA: n_id_2=%d, cnt=%d/%d, sync_res=%d, sf_idx=%d, peak_idx=%d, peak_value=%f, sss_detected=%d\n", n_id_2, sf5_cnt, nof_sf / 5, sync_res, srslte_sync_get_sf_idx(&sync_find), peak_idx, - sync_find.peak_value); + sync_find.peak_value, + srslte_sync_sss_detected(&sync_find)); - if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND) { + if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND && + srslte_sync_sss_detected(&sync_find)) { max_sf5 = sf5_cnt; max_sf_idx = srslte_sync_get_sf_idx(&sync_find); - cell_id = srslte_sync_get_cell_id(&sync_find); + + // Uses the cell ID from the highest SSS correlation peak + if (sss_correlation_peak_max < srslte_sync_sss_correlation_peak(&sync_find)) { + // Set the cell ID + cell_id = srslte_sync_get_cell_id(&sync_find); + + // Update the maximum value + sss_correlation_peak_max = srslte_sync_sss_correlation_peak(&sync_find); + } + sss_detected = true; } } + // If the SSS was not detected, the cell id is not reliable. So, consider no sync found + if (!sss_detected) { + sync_res = SRSLTE_SYNC_NOFOUND; + } + switch (sync_res) { case SRSLTE_SYNC_ERROR: return SRSLTE_ERROR; @@ -196,17 +216,20 @@ int scell_recv::find_cells( cells[nof_cells].rsrq = measure_p.rsrq(); cells[nof_cells].offset = measure_p.frame_st_idx(); - Info("INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, " - "sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", + Info("INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, SNR=%5.1f dB, peak_idx=%5d, " + "peak_value=%3.2f, " + "sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f/%6.1fHz\n", nof_cells, cell_id, measure_p.rsrp(), + measure_p.snr(), measure_p.frame_st_idx(), sync_find.peak_value, sf_idx, max_sf5, n_id_2, - 15000 * srslte_sync_get_cfo(&sync_find)); + 15000 * srslte_sync_get_cfo(&sync_find), + 15000 * measure_p.cfo()); nof_cells++; diff --git a/srsue/src/phy/sf_worker.cc b/srsue/src/phy/sf_worker.cc index 156cd2230..7e8ae3c75 100644 --- a/srsue/src/phy/sf_worker.cc +++ b/srsue/src/phy/sf_worker.cc @@ -60,21 +60,15 @@ sf_worker::sf_worker(uint32_t max_prb, srslte::log* log_phy_lib_h_, chest_feedback_itf* chest_loop_) { - cell_initiated = false; phy = phy_; log_h = log_h_; log_phy_lib_h = log_phy_lib_h_; chest_loop = chest_loop_; - bzero(&tdd_config, sizeof(srslte_tdd_config_t)); - // ue_sync in phy.cc requires a buffer for 3 subframes for (uint32_t r = 0; r < phy->args->nof_carriers; r++) { cc_workers.push_back(new cc_worker(r, max_prb, phy, log_h)); } - - pthread_mutex_init(&mutex, NULL); - reset_(); } sf_worker::~sf_worker() @@ -82,31 +76,24 @@ sf_worker::~sf_worker() for (uint32_t r = 0; r < phy->args->nof_carriers; r++) { delete cc_workers[r]; } - pthread_mutex_destroy(&mutex); } void sf_worker::reset() { - pthread_mutex_lock(&mutex); - reset_(); - pthread_mutex_unlock(&mutex); -} - -void sf_worker::reset_() -{ + std::lock_guard lock(mutex); rssi_read_cnt = 0; - for (uint32_t i = 0; i < cc_workers.size(); i++) { - cc_workers[i]->reset(); + for (auto& cc_worker : cc_workers) { + cc_worker->reset(); } } -bool sf_worker::set_cell(uint32_t cc_idx, srslte_cell_t cell) +bool sf_worker::set_cell(uint32_t cc_idx, srslte_cell_t cell_) { bool ret = false; - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); if (cc_idx < cc_workers.size()) { - if (!cc_workers[cc_idx]->set_cell(cell)) { + if (!cc_workers[cc_idx]->set_cell(cell_)) { Error("Setting cell for cc=%d\n", cc_idx); goto unlock; } @@ -115,13 +102,12 @@ bool sf_worker::set_cell(uint32_t cc_idx, srslte_cell_t cell) } if (cc_idx == 0) { - this->cell = cell; + cell = cell_; cell_initiated = true; } ret = true; unlock: - pthread_mutex_unlock(&mutex); return ret; } @@ -130,13 +116,13 @@ cf_t* sf_worker::get_buffer(uint32_t carrier_idx, uint32_t antenna_idx) return cc_workers[carrier_idx]->get_rx_buffer(antenna_idx); } -void sf_worker::set_tti(uint32_t tti, uint32_t tx_worker_cnt) +void sf_worker::set_tti(uint32_t tti_, uint32_t tx_worker_cnt) { - for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) { - cc_workers[cc_idx]->set_tti(tti); - } + tti = tti_; - this->tti = tti; + for (auto& cc_worker : cc_workers) { + cc_worker->set_tti(tti); + } tx_sem_id = tx_worker_cnt; log_h->step(tti); @@ -146,16 +132,16 @@ void sf_worker::set_tti(uint32_t tti, uint32_t tx_worker_cnt) } } -void sf_worker::set_tx_time(uint32_t radio_idx, srslte_timestamp_t tx_time, int next_offset) +void sf_worker::set_tx_time(uint32_t radio_idx, srslte_timestamp_t tx_time_, int next_offset_) { - this->next_offset[radio_idx] = next_offset; - this->tx_time[radio_idx] = tx_time; + next_offset[radio_idx] = next_offset_; + tx_time[radio_idx] = tx_time_; } -void sf_worker::set_prach(cf_t* prach_ptr, float prach_power) +void sf_worker::set_prach(cf_t* prach_ptr_, float prach_power_) { - this->prach_ptr = prach_ptr; - this->prach_power = prach_power; + prach_ptr = prach_ptr_; + prach_power = prach_power_; } void sf_worker::set_cfo(const uint32_t& cc_idx, float cfo) @@ -165,54 +151,44 @@ void sf_worker::set_cfo(const uint32_t& cc_idx, float cfo) void sf_worker::set_crnti(uint16_t rnti) { - for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) { - cc_workers[cc_idx]->set_crnti(rnti); + for (auto& cc_worker : cc_workers) { + cc_worker->set_crnti(rnti); } } void sf_worker::set_tdd_config(srslte_tdd_config_t config) { - for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) { - cc_workers[cc_idx]->set_tdd_config(config); + for (auto& cc_worker : cc_workers) { + cc_worker->set_tdd_config(config); } tdd_config = config; } void sf_worker::enable_pregen_signals(bool enabled) { - for (uint32_t cc_idx = 0; cc_idx < cc_workers.size(); cc_idx++) { - cc_workers[cc_idx]->enable_pregen_signals(enabled); + for (auto& cc_worker : cc_workers) { + cc_worker->enable_pregen_signals(enabled); } } -void sf_worker::set_pcell_config(srsue::phy_interface_rrc_lte::phy_cfg_t* phy_cfg) -{ - pthread_mutex_lock(&mutex); - Info("Setting PCell configuration for cc_worker=%d, cc=%d\n", get_id(), 0); - cc_workers[0]->set_pcell_config(phy_cfg); - pthread_mutex_unlock(&mutex); -} - -void sf_worker::set_scell_config(uint32_t cc_idx, asn1::rrc::scell_to_add_mod_r10_s* scell_config) +void sf_worker::set_config(uint32_t cc_idx, srslte::phy_cfg_t& phy_cfg) { - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); if (cc_idx < cc_workers.size()) { - Info("Setting SCell configuration for cc_worker=%d, cc=%d\n", get_id(), cc_idx); - cc_workers[cc_idx]->set_scell_config(scell_config); + Info("Setting configuration for cc_worker=%d, cc=%d\n", get_id(), cc_idx); + cc_workers[cc_idx]->set_config(phy_cfg); } else { - Error("Setting scell config for cc=%d; Not enough CC workers;\n", cc_idx); + Error("Setting config for cc=%d; Invalid cc_idx\n", cc_idx); } - pthread_mutex_unlock(&mutex); } void sf_worker::work_imp() { + std::lock_guard lock(mutex); if (!cell_initiated) { return; } - pthread_mutex_lock(&mutex); - /***** Downlink Processing *******/ bool rx_signal_ok = false; @@ -237,8 +213,12 @@ void sf_worker::work_imp() /***** Uplink Generation + Transmission *******/ - bool tx_signal_ready = false; - cf_t* tx_signal_ptr[SRSLTE_MAX_RADIOS][SRSLTE_MAX_PORTS] = {}; + bool tx_signal_ready = false; + cf_t* tx_signal_ptr[SRSLTE_MAX_RADIOS][SRSLTE_MAX_PORTS] = {}; + uint32_t nof_samples[SRSLTE_MAX_RADIOS] = {}; + for (uint32_t i = 0; i < phy->args->nof_radios; i++) { + nof_samples[i] = SRSLTE_SF_LEN_PRB(cell.nof_prb); + } /* If TTI+4 is an uplink subframe (TODO: Support short PRACH and SRS in UpPts special subframes) */ if ((srslte_sfidx_tdd_type(tdd_config, TTI_TX(tti) % 10) == SRSLTE_TDD_SF_U) || cell.frame_type == SRSLTE_FDD) { @@ -271,12 +251,11 @@ void sf_worker::work_imp() if (prach_ptr) { tx_signal_ready = true; tx_signal_ptr[0][0] = prach_ptr; - prach_ptr = NULL; - } - - uint32_t nof_samples[SRSLTE_MAX_RADIOS]; - for (uint32_t i = 0; i < phy->args->nof_radios; i++) { - nof_samples[i] = SRSLTE_SF_LEN_PRB(cell.nof_prb) + next_offset[i]; + prach_ptr = nullptr; + } else { + for (uint32_t i = 0; i < phy->args->nof_radios; i++) { + nof_samples[i] += next_offset[i]; + } } // Call worker_end to transmit the signal @@ -286,10 +265,8 @@ void sf_worker::work_imp() update_measurements(); } - pthread_mutex_unlock(&mutex); - // Call feedback loop for chest - if (chest_loop && ((1 << (tti % 10)) & phy->args->cfo_ref_mask)) { + if (chest_loop && ((1U << (tti % 10U)) & phy->args->cfo_ref_mask)) { chest_loop->set_cfo(cc_workers[0]->get_ref_cfo()); } @@ -305,10 +282,7 @@ void sf_worker::work_imp() void sf_worker::reset_uci(srslte_uci_data_t* uci_data) { - bzero(uci_data, sizeof(srslte_uci_data_t)); - - /* Set all ACKs to DTX */ - memset(uci_data->value.ack.ack_value, 2, SRSLTE_UCI_MAX_ACK_BITS); + srslte_uci_data_reset(uci_data); } /**************************** Measurements **************************/ @@ -432,6 +406,7 @@ plot_scatter_t pconst; #define SCATTER_PDSCH_PLOT_LEN 4000 float tmp_plot[SCATTER_PDSCH_BUFFER_LEN]; cf_t tmp_plot2[SRSLTE_SF_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)]; +bool plot_quit = false; #define CFO_PLOT_LEN 0 /* Set to non zero for enabling CFO plot */ #if CFO_PLOT_LEN > 0 @@ -449,7 +424,7 @@ static float sync_buffer[SYNC_PLOT_LEN]; void* plot_thread_run(void* arg) { - srsue::sf_worker* worker = (srsue::sf_worker*)arg; + auto worker = (srsue::sf_worker*)arg; uint32_t row_count = 0; sdrgui_init(); @@ -494,7 +469,7 @@ void* plot_thread_run(void* arg) int n; int readed_pdsch_re = 0; - while (1) { + while (!plot_quit) { sem_wait(&plot_sem); if (readed_pdsch_re < SCATTER_PDSCH_PLOT_LEN) { @@ -521,7 +496,7 @@ void* plot_thread_run(void* arg) plot_real_setNewData(&pcfo, cfo_buffer, CFO_PLOT_LEN); #endif /* CFO_PLOT_LEN > 0 */ } - return NULL; + return nullptr; } void init_plots(srsue::sf_worker* worker) @@ -533,7 +508,7 @@ void init_plots(srsue::sf_worker* worker) } pthread_attr_t attr; - struct sched_param param; + struct sched_param param = {}; param.sched_priority = 0; pthread_attr_init(&attr); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 39f8ffc81..d404b28fe 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -93,9 +93,16 @@ void sync::init(srslte::radio_interface_phy* _radio, reset(); running = true; - // Enable AGC + // Enable AGC for primary cell receiver set_agc_enable(worker_com->args->agc_enable); + // Enable AGC for secondary asynchronous receiver + if (scell_sync) { + for (auto& q : *scell_sync) { + q->set_agc_enable(worker_com->args->agc_enable); + } + } + // Start main thread if (sync_cpu_affinity < 0) { start(prio); @@ -336,22 +343,19 @@ bool sync::cell_is_camping() return phy_state.is_camping(); } - - - /** * MAIN THREAD - * + * * The main thread process the SYNC state machine. Every state except IDLE must have exclusive access to * all variables. If any change of cell configuration must be done, the thread must be in IDLE. * * On each state except campling, 1 function is called and the thread jumps to the next state based on the output. * - * It has 3 states: Cell search, SFN syncrhonization, intial measurement and camping. + * It has 3 states: Cell search, SFN synchronization, initial measurement and camping. * - CELL_SEARCH: Initial Cell id and MIB acquisition. Uses 1.92 MHz sampling rate * - CELL_SYNC: Full sampling rate, uses MIB to obtain SFN. When SFN is obtained, moves to CELL_CAMP - * - CELL_CAMP: Cell camping state. Calls the PHCH workers to process subframes and mantains cell synchronization. - * - IDLE: Receives and discards received samples. Does not mantain synchronization. + * - CELL_CAMP: Cell camping state. Calls the PHCH workers to process subframes and maintains cell synchronization. + * - IDLE: Receives and discards received samples. Does not maintain synchronization. * */ @@ -393,7 +397,10 @@ void sync::run_thread() /* Search for a cell in the current frequency and go to IDLE. * The function search_p.run() will not return until the search finishes */ - cell_search_ret = search_p.run(&cell); + cell_search_ret = search_p.run(&cell, mib); + if (cell_search_ret == search::CELL_FOUND) { + stack->bch_decoded_ok(mib.data(), mib.size() / 8); + } phy_state.state_exit(); break; case sync_state::SFN_SYNC: @@ -401,7 +408,7 @@ void sync::run_thread() /* SFN synchronization using MIB. run_subframe() receives and processes 1 subframe * and returns */ - switch(sfn_p.run_subframe(&cell, &tti)) { + switch (sfn_p.run_subframe(&cell, &tti, mib)) { case sfn_sync::SFN_FOUND: stack->in_sync(); phy_state.state_exit(); @@ -442,7 +449,7 @@ void sync::run_thread() // Force decode MIB if required if (force_camping_sfn_sync) { uint32_t _tti = 0; - sync::sfn_sync::ret_code ret = sfn_p.decode_mib(&cell, &_tti, buffer[0]); + sync::sfn_sync::ret_code ret = sfn_p.decode_mib(&cell, &_tti, buffer[0], mib); if (ret == sfn_sync::SFN_FOUND) { // Force tti @@ -493,11 +500,7 @@ void sync::run_thread() srslte_timestamp_t rx_time, tx_time; srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); srslte_timestamp_copy(&tx_time, &rx_time); - if (prach_ptr) { - srslte_timestamp_add(&tx_time, 0, TX_DELAY * 1e-3); - } else { - srslte_timestamp_add(&tx_time, 0, TX_DELAY * 1e-3 - time_adv_sec); - } + srslte_timestamp_add(&tx_time, 0, TX_DELAY * 1e-3 - time_adv_sec); worker->set_prach(prach_ptr?&prach_ptr[prach_sf_cnt*SRSLTE_SF_LEN_PRB(cell.nof_prb)]:NULL, prach_power); @@ -558,6 +561,7 @@ void sync::run_thread() Warning("SYNC: Out-of-sync detected in PSS/SSS\n"); out_of_sync(); worker->release(); + is_end_of_burst = true; // Force decoding MIB, for making sure that the TTI will be right if (!force_camping_sfn_sync) { @@ -995,15 +999,12 @@ void sync::search::set_agc_enable(bool enable) } } -sync::search::ret_code sync::search::run(srslte_cell_t* cell) +sync::search::ret_code sync::search::run(srslte_cell_t* cell, std::array& bch_payload) { - if (!cell) { return ERROR; } - uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; - srslte_ue_cellsearch_result_t found_cells[3]; bzero(cell, sizeof(srslte_cell_t)); @@ -1062,11 +1063,13 @@ sync::search::ret_code sync::search::run(srslte_cell_t* cell) /* Find and decode MIB */ int sfn_offset; - ret = srslte_ue_mib_sync_decode(&ue_mib_sync, - 40, - bch_payload, &cell->nof_ports, &sfn_offset); + ret = srslte_ue_mib_sync_decode(&ue_mib_sync, 40, bch_payload.data(), &cell->nof_ports, &sfn_offset); if (ret == 1) { - srslte_pbch_mib_unpack(bch_payload, cell, NULL); + srslte_pbch_mib_unpack(bch_payload.data(), cell, NULL); + // pack MIB and store inplace for PCAP dump + std::array mib_packed; + srslte_bit_pack_vector(bch_payload.data(), mib_packed.data(), SRSLTE_BCH_PAYLOAD_LEN); + std::copy(std::begin(mib_packed), std::end(mib_packed), std::begin(bch_payload)); fprintf(stdout, "Found Cell: Mode=%s, PCI=%d, PRB=%d, Ports=%d, CFO=%.1f KHz\n", @@ -1147,7 +1150,10 @@ void sync::sfn_sync::reset() srslte_ue_mib_reset(&ue_mib); } -sync::sfn_sync::ret_code sync::sfn_sync::run_subframe(srslte_cell_t* cell, uint32_t* tti_cnt, bool sfidx_only) +sync::sfn_sync::ret_code sync::sfn_sync::run_subframe(srslte_cell_t* cell, + uint32_t* tti_cnt, + std::array& bch_payload, + bool sfidx_only) { int ret = srslte_ue_sync_zerocopy(ue_sync, buffer); @@ -1157,7 +1163,7 @@ sync::sfn_sync::ret_code sync::sfn_sync::run_subframe(srslte_cell_t* cell, uint3 } if (ret == 1) { - sync::sfn_sync::ret_code ret2 = decode_mib(cell, tti_cnt, NULL, sfidx_only); + sync::sfn_sync::ret_code ret2 = decode_mib(cell, tti_cnt, NULL, bch_payload, sfidx_only); if (ret2 != SFN_NOFOUND) { return ret2; } @@ -1174,12 +1180,12 @@ sync::sfn_sync::ret_code sync::sfn_sync::run_subframe(srslte_cell_t* cell, uint3 return IDLE; } -sync::sfn_sync::ret_code -sync::sfn_sync::decode_mib(srslte_cell_t* cell, uint32_t* tti_cnt, cf_t* ext_buffer[SRSLTE_MAX_PORTS], bool sfidx_only) +sync::sfn_sync::ret_code sync::sfn_sync::decode_mib(srslte_cell_t* cell, + uint32_t* tti_cnt, + cf_t* ext_buffer[SRSLTE_MAX_PORTS], + std::array& bch_payload, + bool sfidx_only) { - - uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; - // If external buffer provided not equal to internal buffer, copy data if ((ext_buffer != NULL) && (ext_buffer != buffer)) { memcpy(buffer[0], ext_buffer[0], sizeof(cf_t) * ue_sync->sf_len); @@ -1196,14 +1202,14 @@ sync::sfn_sync::decode_mib(srslte_cell_t* cell, uint32_t* tti_cnt, cf_t* ext_buf } int sfn_offset = 0; - int n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset); + int n = srslte_ue_mib_decode(&ue_mib, bch_payload.data(), NULL, &sfn_offset); switch (n) { default: Error("SYNC: Error decoding MIB while synchronising SFN"); return ERROR; case SRSLTE_UE_MIB_FOUND: uint32_t sfn; - srslte_pbch_mib_unpack(bch_payload, cell, &sfn); + srslte_pbch_mib_unpack(bch_payload.data(), cell, &sfn); sfn = (sfn + sfn_offset) % 1024; if (tti_cnt) { diff --git a/srsue/src/stack/mac/dl_harq.cc b/srsue/src/stack/mac/dl_harq.cc index c60196f61..26d0698d0 100644 --- a/srsue/src/stack/mac/dl_harq.cc +++ b/srsue/src/stack/mac/dl_harq.cc @@ -345,13 +345,14 @@ void dl_harq_entity::dl_harq_process::dl_tb_process::tb_decoded(mac_interface_ph if (ack) { if (is_bcch) { if (harq_entity->pcap) { - harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.tb[tid].tbs, ack, 0); + harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.tb[tid].tbs, ack, cur_grant.tti); } Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.tb[tid].tbs); harq_entity->demux_unit->push_pdu_bcch(payload_buffer_ptr, cur_grant.tb[tid].tbs); } else { if (harq_entity->pcap) { - harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.tb[tid].tbs, cur_grant.rnti, ack, 0); + harq_entity->pcap->write_dl_crnti( + payload_buffer_ptr, cur_grant.tb[tid].tbs, cur_grant.rnti, ack, cur_grant.tti); } if (cur_grant.rnti == harq_entity->rntis->temp_rnti) { Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", cur_grant.tb[tid].tbs); diff --git a/srsue/src/stack/mac/mac.cc b/srsue/src/stack/mac/mac.cc index ea42c43bf..8b6b7fb0d 100644 --- a/srsue/src/stack/mac/mac.cc +++ b/srsue/src/stack/mac/mac.cc @@ -37,14 +37,7 @@ using namespace asn1::rrc; namespace srsue { -mac::mac(srslte::log* log_) : - timers(64), - pdu_process_thread(&demux_unit), - mch_msg(10, log_), - mux_unit(log_), - demux_unit(log_), - pcap(nullptr), - log_h(log_) +mac::mac(srslte::log* log_) : mch_msg(10, log_), mux_unit(log_), demux_unit(log_), pcap(nullptr), log_h(log_) { // Create PCell HARQ entities auto ul = ul_harq_entity_ptr(new ul_harq_entity()); @@ -72,29 +65,45 @@ mac::~mac() srslte_softbuffer_rx_free(&mch_softbuffer); } -bool mac::init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface_mac* rrc) +bool mac::init(phy_interface_mac_lte* phy, + rlc_interface_mac* rlc, + rrc_interface_mac* rrc, + srslte::timers* timers_, + stack_interface_mac* stack_) { - phy_h = phy; - rlc_h = rlc; - rrc_h = rrc; + phy_h = phy; + rlc_h = rlc; + rrc_h = rrc; + timers = timers_; + stack_h = stack_; - timer_alignment = timers.get_unique_id(); - uint32_t contention_resolution_timer = timers.get_unique_id(); + timer_alignment = timers->get_unique_id(); + uint32_t contention_resolution_timer = timers->get_unique_id(); - bsr_procedure.init(rlc_h, log_h, &timers); - phr_procedure.init(phy_h, log_h, &timers); + bsr_procedure.init(rlc_h, log_h, timers); + phr_procedure.init(phy_h, log_h, timers); mux_unit.init(rlc_h, &bsr_procedure, &phr_procedure); - demux_unit.init(phy_h, rlc_h, this, timers.get(timer_alignment)); - ra_procedure.init( - phy_h, rrc, log_h, &uernti, timers.get(timer_alignment), timers.get(contention_resolution_timer), &mux_unit); + demux_unit.init(phy_h, rlc_h, this, timers->get(timer_alignment)); + ra_procedure.init(phy_h, + rrc, + log_h, + &uernti, + timers->get(timer_alignment), + timers->get(contention_resolution_timer), + &mux_unit, + stack_h); sr_procedure.init(phy_h, rrc, log_h); // Create UL/DL unique HARQ pointers ul_harq.at(0)->init(log_h, &uernti, &ra_procedure, &mux_unit); - dl_harq.at(0)->init(log_h, &uernti, timers.get(timer_alignment), &demux_unit); + dl_harq.at(0)->init(log_h, &uernti, timers->get(timer_alignment), &demux_unit); reset(); + // Set default MAC parameters + mac_cfg_t default_cfg = {}; + set_config(default_cfg); + initialized = true; return true; @@ -103,7 +112,6 @@ bool mac::init(phy_interface_mac_lte* phy, rlc_interface_mac* rlc, rrc_interface void mac::stop() { if (initialized) { - pdu_process_thread.stop(); run_tti(0); // make sure it's not locked after last TTI initialized = false; } @@ -135,7 +143,7 @@ void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable) } while (dl_harq.size() < cc_idx + 1) { auto dl = dl_harq_entity_ptr(new dl_harq_entity()); - dl->init(log_h, &uernti, timers.get(timer_alignment), &demux_unit); + dl->init(log_h, &uernti, timers->get(timer_alignment), &demux_unit); if (pcap) { dl->start_pcap(pcap); @@ -162,7 +170,7 @@ void mac::reset() Info("Resetting MAC\n"); - timers.get(timer_alignment)->stop(); + timers->get(timer_alignment)->stop(); timer_alignment_expire(); @@ -233,7 +241,6 @@ void mac::run_tti(const uint32_t tti) ra_window_start = -1; ra_window_length = -1; ra_procedure.update_rar_window(&ra_window_start, &ra_window_length); - timers.step_all(); } void mac::bcch_start_rx(int si_window_start, int si_window_length) @@ -385,7 +392,7 @@ void mac::mch_decoded(uint32_t len, bool crc) } demux_unit.push_pdu_mch(mch_payload_buffer, len); - pdu_process_thread.notify(); + stack_h->process_pdus(); if (pcap) { pcap->write_dl_mch(mch_payload_buffer, len, true, phy_h->get_current_tti()); } @@ -400,19 +407,19 @@ void mac::tb_decoded(uint32_t cc_idx, mac_grant_dl_t grant, bool ack[SRSLTE_MAX_ { if (SRSLTE_RNTI_ISRAR(grant.rnti)) { if (ack[0]) { - ra_procedure.tb_decoded_ok(); + ra_procedure.tb_decoded_ok(grant.tti); } } else if (grant.rnti == SRSLTE_PRNTI) { // Send PCH payload to RLC rlc_h->write_pdu_pcch(pch_payload_buffer, grant.tb[0].tbs); if (pcap) { - pcap->write_dl_pch(pch_payload_buffer, grant.tb[0].tbs, true, phy_h->get_current_tti()); + pcap->write_dl_pch(pch_payload_buffer, grant.tb[0].tbs, true, grant.tti); } } else { dl_harq.at(cc_idx)->tb_decoded(grant, ack); - pdu_process_thread.notify(); + stack_h->process_pdus(); for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (grant.tb[tb].tbs) { @@ -458,6 +465,19 @@ void mac::new_grant_dl(uint32_t cc_idx, } } +void mac::process_pdus() +{ + bool have_data = true; + while (initialized and have_data) { + have_data = demux_unit.process_pdus(); + } +} + +void mac::notify_ra_completed() +{ + ra_procedure.notify_ra_completed(); +} + uint32_t mac::get_current_tti() { return phy_h->get_current_tti(); @@ -509,12 +529,12 @@ void mac::new_mch_dl(srslte_pdsch_grant_t phy_grant, tb_action_dl_t* action) void mac::setup_timers(int time_alignment_timer) { // stop currently running time alignment timer - if (timers.get(timer_alignment)->is_running()) { - timers.get(timer_alignment)->stop(); + if (timers->get(timer_alignment)->is_running()) { + timers->get(timer_alignment)->stop(); } if (time_alignment_timer > 0) { - timers.get(timer_alignment)->set(this, time_alignment_timer); + timers->get(timer_alignment)->set(this, time_alignment_timer); } } @@ -563,17 +583,17 @@ void mac::set_mbsfn_config(uint32_t nof_mbsfn_services) void mac::set_config(mac_cfg_t& mac_cfg) { // Set configuration for each module in MAC - bsr_procedure.set_config(mac_cfg.get_bsr_cfg()); - phr_procedure.set_config(mac_cfg.get_phr_cfg()); - sr_procedure.set_config(mac_cfg.get_sr_cfg()); - ra_procedure.set_config(mac_cfg.get_rach_cfg()); - ul_harq_cfg = mac_cfg.get_harq_cfg(); + bsr_procedure.set_config(mac_cfg.bsr_cfg); + phr_procedure.set_config(mac_cfg.phr_cfg); + sr_procedure.set_config(mac_cfg.sr_cfg); + ra_procedure.set_config(mac_cfg.rach_cfg); + ul_harq_cfg = mac_cfg.harq_cfg; for (auto& i : ul_harq) { if (i != nullptr) { i->set_config(ul_harq_cfg); } } - setup_timers(mac_cfg.get_time_alignment_timer()); + setup_timers(mac_cfg.time_alignment_timer); } void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) @@ -616,9 +636,7 @@ void mac::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS]) int rx_brate = 0; int ul_buffer = 0; float dl_avg_ret = 0; - float ul_avg_ret = 0; int dl_avg_ret_count = 0; - int ul_avg_ret_count = 0; for (uint32_t r = 0; r < dl_harq.size(); r++) { tx_pkts += metrics[r].tx_pkts; @@ -651,9 +669,6 @@ void mac::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS]) bzero(&metrics, sizeof(mac_metrics_t) * SRSLTE_MAX_CARRIERS); } - - - /******************************************************** * * Interface for timers used by upper layers @@ -661,72 +676,17 @@ void mac::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS]) *******************************************************/ srslte::timers::timer* mac::timer_get(uint32_t timer_id) { - return timers.get(timer_id); + return timers->get(timer_id); } void mac::timer_release_id(uint32_t timer_id) { - timers.release_id(timer_id); + timers->release_id(timer_id); } uint32_t mac::timer_get_unique_id() { - return timers.get_unique_id(); + return timers->get_unique_id(); } - -/******************************************************** - * - * Class that runs a thread to process DL MAC PDUs from - * DEMUX unit - * - *******************************************************/ -mac::pdu_process::pdu_process(demux* demux_unit_) : thread("MAC_PDU_PROCESS"), demux_unit(demux_unit_) -{ - running = true; - start(MAC_PDU_THREAD_PRIO); -} - -mac::pdu_process::~pdu_process() -{ - if (running) { - stop(); - } -} - -void mac::pdu_process::stop() -{ - if (running) { - { - std::lock_guard ul(mutex); - running = false; - cvar.notify_all(); - } - wait_thread_finish(); - } -} - -void mac::pdu_process::notify() -{ - std::unique_lock ul(mutex); - have_data = true; - cvar.notify_all(); -} - -void mac::pdu_process::run_thread() -{ - while(running) { - have_data = demux_unit->process_pdus(); - if (!have_data) { - std::unique_lock ul(mutex); - while(!have_data && running) { - cvar.wait(ul); - } - } - } -} - -} - - - +} // namespace srsue diff --git a/srsue/src/stack/mac/mux.cc b/srsue/src/stack/mac/mux.cc index 16585ee74..b67ee4283 100644 --- a/srsue/src/stack/mac/mux.cc +++ b/srsue/src/stack/mac/mux.cc @@ -96,8 +96,11 @@ bool priority_compare(const logical_channel_config_t& u1, const logical_channel_ return u1.priority <= u2.priority; } +// This is called by RRC (stack thread) during bearer addition void mux::setup_lcid(const logical_channel_config_t& config) { + std::lock_guard lock(mutex); + if (has_logical_channel(config.lcid)) { // update settings for (auto& channel : logical_channels) { @@ -121,6 +124,7 @@ void mux::setup_lcid(const logical_channel_config_t& config) std::sort(logical_channels.begin(), logical_channels.end(), priority_compare); } +// mutex should be hold by caller void mux::print_logical_channel_state(const std::string& info) { std::string logline = info; @@ -261,8 +265,9 @@ uint8_t* mux::pdu_get(srslte::byte_buffer_t* payload, uint32_t pdu_sz) return ret; } -void mux::append_crnti_ce_next_tx(uint16_t crnti) { - pending_crnti_ce = crnti; +void mux::append_crnti_ce_next_tx(uint16_t crnti) +{ + pending_crnti_ce = crnti; } bool mux::sched_sdu(logical_channel_config_t* ch, int* sdu_space, int max_sdu_sz) diff --git a/srsue/src/stack/mac/proc_bsr.cc b/srsue/src/stack/mac/proc_bsr.cc index dba0b7b3d..cb65cb342 100644 --- a/srsue/src/stack/mac/proc_bsr.cc +++ b/srsue/src/stack/mac/proc_bsr.cc @@ -75,7 +75,7 @@ void bsr_proc::reset() trigger_tti = 0; } -void bsr_proc::set_config(srsue::mac_interface_rrc::bsr_cfg_t& bsr_cfg) +void bsr_proc::set_config(srslte::bsr_cfg_t& bsr_cfg) { pthread_mutex_lock(&mutex); @@ -223,7 +223,7 @@ bool bsr_proc::generate_bsr(bsr_t* bsr, uint32_t nof_padding_bytes) // If space only for short if (nof_lcg > 1) { bsr->format = TRUNC_BSR; - uint32_t max_prio_lcg = find_max_priority_lcg(); + uint32_t max_prio_lcg = find_max_priority_lcg_with_data(); for (uint32_t i = 0; i < NOF_LCG; i++) { if (max_prio_lcg != i) { bsr->buff_size[i] = 0; @@ -383,7 +383,6 @@ bool bsr_proc::generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t* bsr) set_trigger(NONE); ret = true; } - pthread_mutex_unlock(&mutex); return ret; @@ -434,13 +433,13 @@ void bsr_proc::setup_lcid(uint32_t lcid, uint32_t new_lcg, uint32_t priority) } } -uint32_t bsr_proc::find_max_priority_lcg() +uint32_t bsr_proc::find_max_priority_lcg_with_data() { int32_t max_prio = 99; uint32_t max_idx = 0; for (int i = 0; i < NOF_LCG; i++) { for (std::map::iterator iter = lcgs[i].begin(); iter != lcgs[i].end(); ++iter) { - if (iter->second.priority < max_prio) { + if (iter->second.priority < max_prio && iter->second.old_buffer > 0) { max_prio = iter->second.priority; max_idx = i; } diff --git a/srsue/src/stack/mac/proc_phr.cc b/srsue/src/stack/mac/proc_phr.cc index d0082737a..4906b4e88 100644 --- a/srsue/src/stack/mac/proc_phr.cc +++ b/srsue/src/stack/mac/proc_phr.cc @@ -58,7 +58,7 @@ void phr_proc::reset() phr_is_triggered = false; } -void phr_proc::set_config(srsue::mac_interface_rrc::phr_cfg_t& cfg) +void phr_proc::set_config(srslte::phr_cfg_t& cfg) { phr_cfg = cfg; diff --git a/srsue/src/stack/mac/proc_ra.cc b/srsue/src/stack/mac/proc_ra.cc index b27dc4f3b..acadef930 100644 --- a/srsue/src/stack/mac/proc_ra.cc +++ b/srsue/src/stack/mac/proc_ra.cc @@ -35,11 +35,15 @@ /* Random access procedure as specified in Section 5.1 of 36.321 */ - namespace srsue { -const char* state_str[6] = { - "RA: INIT: ", "RA: PDCCH: ", "RA: Rx: ", "RA: Backof: ", "RA: ConRes: ", "RA: Complt: "}; +const char* state_str[] = {"RA: INIT: ", + "RA: PDCCH: ", + "RA: Rx: ", + "RA: Backof: ", + "RA: ConRes: ", + "RA: WaitComplt: ", + "RA: Complt: "}; #define rError(fmt, ...) Error("%s" fmt, state_str[state], ##__VA_ARGS__) #define rInfo(fmt, ...) Info("%s" fmt, state_str[state], ##__VA_ARGS__) @@ -58,17 +62,19 @@ void ra_proc::init(phy_interface_mac_lte* phy_h_, mac_interface_rrc::ue_rnti_t* rntis_, srslte::timers::timer* time_alignment_timer_, srslte::timers::timer* contention_resolution_timer_, - mux* mux_unit_) + mux* mux_unit_, + stack_interface_mac* stack_) { - phy_h = phy_h_; - log_h = log_h_; - rntis = rntis_; - mux_unit = mux_unit_; - rrc = rrc_; + phy_h = phy_h_; + log_h = log_h_; + rntis = rntis_; + mux_unit = mux_unit_; + rrc = rrc_; + stack = stack_; time_alignment_timer = time_alignment_timer_; contention_resolution_timer = contention_resolution_timer_; - + srslte_softbuffer_rx_init(&softbuffer_rar, 10); reset(); @@ -91,7 +97,7 @@ void ra_proc::start_pcap(srslte::mac_pcap* pcap_) } /* Sets a new configuration. The configuration is applied by initialization() function */ -void ra_proc::set_config(srsue::mac_interface_rrc::rach_cfg_t& rach_cfg) +void ra_proc::set_config(srslte::rach_cfg_t& rach_cfg) { std::unique_lock ul(mutex); new_cfg = rach_cfg; @@ -145,9 +151,12 @@ void ra_proc::step(uint32_t tti_) case CONTENTION_RESOLUTION: state_contention_resolution(); break; - case COMPLETITION: + case START_WAIT_COMPLETION: state_completition(); break; + case WAITING_COMPLETION: + // do nothing, bc we are waiting for the phy to finish + break; } } @@ -155,7 +164,6 @@ void ra_proc::step(uint32_t tti_) */ void ra_proc::state_pdcch_setup() { - phy_interface_mac_lte::prach_info_t info = phy_h->prach_get_info(); if (info.is_transmitted) { ra_tti = info.tti_ra; @@ -227,7 +235,19 @@ void ra_proc::state_contention_resolution() */ void ra_proc::state_completition() { - phy_h->set_crnti(rntis->crnti); + state = WAITING_COMPLETION; + stack->wait_ra_completion(rntis->crnti); + // phy_h->set_crnti(rntis->crnti); + // state = IDLE; +} + +void ra_proc::notify_ra_completed() +{ + if (state != WAITING_COMPLETION) { + rError("Received unexpected notification of RA completion\n"); + } else { + rInfo("RA waiting procedure completed\n"); + } state = IDLE; } @@ -372,9 +392,10 @@ void ra_proc::new_grant_dl(mac_interface_phy_lte::mac_grant_dl_t grant, mac_inte /* Called upon the successful decoding of a TB addressed to RA-RNTI. * Processes the reception of a RAR as defined in 5.1.4 */ -void ra_proc::tb_decoded_ok() { +void ra_proc::tb_decoded_ok(const uint32_t tti) +{ if (pcap) { - pcap->write_dl_ranti(rar_pdu_buffer, rar_grant_nbytes, ra_rnti, true, 0); + pcap->write_dl_ranti(rar_pdu_buffer, rar_grant_nbytes, ra_rnti, true, tti); } rDebug("RAR decoded successfully TBS=%d\n", rar_grant_nbytes); @@ -501,10 +522,11 @@ void ra_proc::complete() log_h->console("Random Access Complete. c-rnti=0x%x, ta=%d\n", rntis->crnti, current_ta); rInfo("Random Access Complete. c-rnti=0x%x, ta=%d\n", rntis->crnti, current_ta); - state = COMPLETITION; + state = START_WAIT_COMPLETION; } -void ra_proc::start_noncont(uint32_t preamble_index, uint32_t prach_mask) { +void ra_proc::start_noncont(uint32_t preamble_index, uint32_t prach_mask) +{ next_preamble_idx = preamble_index; next_prach_mask = prach_mask; noncontention_enabled = true; diff --git a/srsue/src/stack/mac/proc_sr.cc b/srsue/src/stack/mac/proc_sr.cc index 94748d5fc..97d516815 100644 --- a/srsue/src/stack/mac/proc_sr.cc +++ b/srsue/src/stack/mac/proc_sr.cc @@ -66,7 +66,7 @@ bool sr_proc::need_tx(uint32_t tti) return false; } -void sr_proc::set_config(srsue::mac_interface_rrc::sr_cfg_t& cfg) +void sr_proc::set_config(srslte::sr_cfg_t& cfg) { sr_cfg = cfg; } diff --git a/srsue/src/stack/mac/ul_harq.cc b/srsue/src/stack/mac/ul_harq.cc index a2bca04a2..5202dcf03 100644 --- a/srsue/src/stack/mac/ul_harq.cc +++ b/srsue/src/stack/mac/ul_harq.cc @@ -77,7 +77,7 @@ void ul_harq_entity::reset_ndi() } } -void ul_harq_entity::set_config(srsue::mac_interface_rrc_common::ul_harq_cfg_t& harq_cfg) +void ul_harq_entity::set_config(srslte::ul_harq_cfg_t& harq_cfg) { this->harq_cfg = harq_cfg; } @@ -110,7 +110,7 @@ void ul_harq_entity::new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t grant, Info("Not implemented\n"); } } else { - Warning("Received grant for unknnown rnti=0x%x\n", grant.rnti); + Warning("Received grant for unknown rnti=0x%x\n", grant.rnti); } } @@ -286,7 +286,7 @@ void ul_harq_entity::ul_harq_process::new_grant_ul(mac_interface_phy_lte::mac_gr } else { rnti = harq_entity->rntis->crnti; } - harq_entity->pcap->write_ul_crnti(pdu_ptr, grant.tb.tbs, rnti, get_nof_retx(), 0); + harq_entity->pcap->write_ul_crnti(pdu_ptr, grant.tb.tbs, rnti, get_nof_retx(), grant.tti_tx); } } else if (has_grant()) { // Non-Adaptive Re-Tx diff --git a/srsue/src/stack/rrc/CMakeLists.txt b/srsue/src/stack/rrc/CMakeLists.txt index 91fc5224f..e8d85f2db 100644 --- a/srsue/src/stack/rrc/CMakeLists.txt +++ b/srsue/src/stack/rrc/CMakeLists.txt @@ -18,9 +18,8 @@ # and at http://www.gnu.org/licenses/. # -set(SOURCES rrc.cc) +set(SOURCES rrc.cc rrc_procedures.cc) add_library(srsue_rrc STATIC ${SOURCES}) install(TARGETS srsue_rrc DESTINATION ${LIBRARY_DIR}) - diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index e7a9e5338..2324518ec 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -23,6 +23,7 @@ #include "srslte/asn1/rrc_asn1.h" #include "srslte/common/bcd_helpers.h" #include "srslte/common/security.h" +#include "srsue/hdr/stack/rrc/rrc_procedures.h" #include #include #include // for printing uint64_t @@ -46,42 +47,17 @@ const static uint32_t required_sibs[NOF_REQUIRED_SIBS] = {0,1,2,12}; // SIB1, SI Base functions *******************************************************************************/ -rrc::rrc(srslte::log* log_) : - rrc_log(log_), +rrc::rrc(srslte::log* rrc_log_) : state(RRC_STATE_IDLE), last_state(RRC_STATE_CONNECTED), drb_up(false), - rlc_flush_timeout(2000), - rlc_flush_counter(0), - thread("RRC") -{ - n310_cnt = 0; - n311_cnt = 0; - serving_cell = new cell_t(); - neighbour_cells.reserve(NOF_NEIGHBOUR_CELLS); - initiated = false; - running = false; - go_idle = false; - m_reest_cause = asn1::rrc::reest_cause_e::nulltype; - m_reest_rnti = 0; - reestablishment_successful = false; - - current_mac_cfg = {}; - previous_mac_cfg = {}; - current_phy_cfg = {}; - previous_phy_cfg = {}; + rrc_log(rrc_log_), + serving_cell(unique_cell_t(new cell_t({}, 0.0))) +{ } rrc::~rrc() { - if (serving_cell) { - delete(serving_cell); - } - - std::vector::iterator it; - for (it = neighbour_cells.begin(); it != neighbour_cells.end(); ++it) { - delete(*it); - } } static void srslte_rrc_handler(asn1::srsasn_logger_level_t level, void* ctx, const char* str) @@ -110,7 +86,7 @@ void rrc::log_rrc_message(const std::string source, const direction_t dir, const msg.to_json(json_writer); rrc_log->debug_hex(pdu->msg, pdu->N_bytes, "%s - %s %s (%d B)\n", source.c_str(), (dir == Rx) ? "Rx" : "Tx", msg.msg.c1().type().to_string().c_str(), pdu->N_bytes); - rrc_log->debug("Content:\n%s\n", json_writer.to_string().c_str()); + rrc_log->debug_long("Content:\n%s\n", json_writer.to_string().c_str()); } } @@ -121,35 +97,35 @@ void rrc::init(phy_interface_rrc_lte* phy_, nas_interface_rrc* nas_, usim_interface_rrc* usim_, gw_interface_rrc* gw_, - mac_interface_timers* mac_timers_, + srslte::timers* timers_, + stack_interface_rrc* stack_, const rrc_args_t& args_) { - pool = byte_buffer_pool::get_instance(); + pool = byte_buffer_pool::get_instance(); phy = phy_; mac = mac_; rlc = rlc_; pdcp = pdcp_; - nas = nas_; - usim = usim_; - gw = gw_; + nas = nas_; + usim = usim_; + gw = gw_; + stack = stack_; args = args_; // Use MAC timers - mac_timers = mac_timers_; + timers = timers_; state = RRC_STATE_IDLE; plmn_is_selected = false; security_is_activated = false; - pthread_mutex_init(&mutex, NULL); - - t300 = mac_timers->timer_get_unique_id(); - t301 = mac_timers->timer_get_unique_id(); - t302 = mac_timers->timer_get_unique_id(); - t310 = mac_timers->timer_get_unique_id(); - t311 = mac_timers->timer_get_unique_id(); - t304 = mac_timers->timer_get_unique_id(); + t300 = timers->get_unique_id(); + t301 = timers->get_unique_id(); + t302 = timers->get_unique_id(); + t310 = timers->get_unique_id(); + t311 = timers->get_unique_id(); + t304 = timers->get_unique_id(); ue_identity_configured = false; @@ -160,14 +136,10 @@ void rrc::init(phy_interface_rrc_lte* phy_, cell_clean_cnt = 0; - ho_start = false; - pending_mob_reconf = false; - // Set default values for all layers + // Set default values for RRC. MAC and PHY are set to default themselves set_rrc_default(); - set_phy_default(); - set_mac_default(); measurements.init(this); @@ -178,8 +150,10 @@ void rrc::init(phy_interface_rrc_lte* phy_, // set seed (used in CHAP auth and attach) srand(tv.tv_usec); + // initiate unique procedures + ue_required_sibs.assign(&required_sibs[0], &required_sibs[NOF_REQUIRED_SIBS]); + running = true; - start(); initiated = true; } @@ -189,7 +163,6 @@ void rrc::stop() { cmd_msg_t msg; msg.command = cmd_msg_t::STOP; cmd_q.push(std::move(msg)); - wait_thread_finish(); } void rrc::get_metrics(rrc_metrics_t& m) @@ -201,30 +174,9 @@ bool rrc::is_connected() { return (RRC_STATE_CONNECTED == state); } -/* - * Low priority thread to run functions that can not be executed from main thread - */ -void rrc::run_thread() { - while(running) { - cmd_msg_t msg = cmd_q.wait_pop(); - switch(msg.command) { - case cmd_msg_t::PDU: - process_pdu(msg.lcid, std::move(msg.pdu)); - break; - case cmd_msg_t::PCCH: - process_pcch(std::move(msg.pdu)); - break; - case cmd_msg_t::MBMS_START: - if (args.mbms_service_id >= 0) { - rrc_log->info("Attempting to auto-start MBMS service %d\n", - args.mbms_service_id); - mbms_service_start(args.mbms_service_id, args.mbms_service_port); - } - break; - case cmd_msg_t::STOP: - return; - } - } +bool rrc::have_drb() +{ + return drb_up; } /* @@ -234,7 +186,6 @@ void rrc::run_thread() { */ void rrc::run_tti(uint32_t tti) { - if (!initiated) { return; } @@ -244,90 +195,75 @@ void rrc::run_tti(uint32_t tti) simulate_rlf = false; } - /* We can not block in this thread because it is called from - * the MAC TTI timer and needs to return immediatly to perform other - * tasks. Therefore in this function we use trylock() instead of lock() and - * skip function if currently locked, since none of the functions here is urgent - */ - if (!pthread_mutex_trylock(&mutex)) { - - // Process pending PHY measurements in IDLE/CONNECTED - process_phy_meas(); - - // Log state changes - if (state != last_state) { - rrc_log->debug("State %s\n", rrc_state_text[state]); - last_state = state; - } - - // Run state machine - switch (state) { - case RRC_STATE_IDLE: - - /* CAUTION: The execution of cell_search() and cell_selection() take more than 1 ms - * and will slow down MAC TTI ticks. This has no major effect at the moment because - * the UE is in IDLE but we could consider splitting MAC and RRC threads to avoid this - */ - - // If attached but not camping on the cell, perform cell reselection - if (nas->is_attached()) { - rrc_log->debug("Running cell selection and reselection in IDLE\n"); - switch(cell_selection()) { - case rrc::CHANGED_CELL: - // New cell has been selected, start receiving PCCH - mac->pcch_start_rx(); - break; - case rrc::NO_CELL: - rrc_log->warning("Could not find any cell to camp on\n"); - break; - case rrc::SAME_CELL: - if (!phy->cell_is_camping()) { - rrc_log->warning("Did not reselect cell but serving cell is out-of-sync.\n"); - serving_cell->in_sync = false; - } - break; - } - } - break; - case RRC_STATE_CONNECTED: - if (ho_start) { - ho_start = false; - if (!ho_prepare()) { - con_reconfig_failed(); - } - } + // Process pending PHY measurements in IDLE/CONNECTED + process_phy_meas(); - // Performing reestablishment cell selection - if (m_reest_cause != asn1::rrc::reest_cause_e::nulltype) { - proc_con_restablish_request(); - } + // Process on-going callbacks, and clear finished callbacks + callback_list.run(); - measurements.run_tti(tti); - if (go_idle) { - // wait for max. 2s for RLC on SRB1 to be flushed - if (not rlc->has_data(RB_ID_SRB1) || ++rlc_flush_counter > rlc_flush_timeout) { - go_idle = false; - leave_connected(); - } else { - rrc_log->debug("Postponing transition to RRC IDLE (%d ms < %d ms)\n", rlc_flush_counter, rlc_flush_timeout); - } - } - break; - default:break; - } + // Log state changes + if (state != last_state) { + rrc_log->debug("State %s\n", rrc_state_text[state]); + last_state = state; + } - // Clean old neighbours - cell_clean_cnt++; - if (cell_clean_cnt == 1000) { - clean_neighbours(); - cell_clean_cnt = 0; - } - pthread_mutex_unlock(&mutex); + // Run state machine + switch (state) { + case RRC_STATE_IDLE: - // allow other threads to ackquire mutex. - usleep(100); + /* CAUTION: The execution of cell_search() and cell_selection() take more than 1 ms + * and will slow down MAC TTI ticks. This has no major effect at the moment because + * the UE is in IDLE but we could consider splitting MAC and RRC threads to avoid this + */ - } // Skip TTI if mutex is locked + // If attached but not camping on the cell, perform cell reselection + if (nas->is_attached()) { + start_cell_reselection(); + } + break; + case RRC_STATE_CONNECTED: + // Performing reestablishment cell selection + if (m_reest_cause != asn1::rrc::reest_cause_e::nulltype) { + proc_con_restablish_request(); + } + measurements.run_tti(tti); + break; + default: + break; + } + + // Handle Received Messages + if (running) { + cmd_msg_t msg; + if (cmd_q.try_pop(&msg)) { + switch (msg.command) { + case cmd_msg_t::PDU: + process_pdu(msg.lcid, std::move(msg.pdu)); + break; + case cmd_msg_t::PCCH: + process_pcch(std::move(msg.pdu)); + break; + case cmd_msg_t::PDU_MCH: + parse_pdu_mch(msg.lcid, std::move(msg.pdu)); + break; + case cmd_msg_t::RLF: + radio_link_failure(); + break; + case cmd_msg_t::PDU_BCCH_DLSCH: + parse_pdu_bcch_dlsch(std::move(msg.pdu)); + break; + case cmd_msg_t::STOP: + return; + } + } + } + + // Clean old neighbours + cell_clean_cnt++; + if (cell_clean_cnt == 1000) { + clean_neighbours(); + cell_clean_cnt = 0; + } } @@ -363,45 +299,14 @@ uint16_t rrc::get_mnc() { * * This function is thread-safe with connection_request() */ -int rrc::plmn_search(found_plmn_t found_plmns[MAX_FOUND_PLMNS]) -{ - // Mutex with connect - pthread_mutex_lock(&mutex); - - rrc_log->info("Starting PLMN search\n"); - uint32_t nof_plmns = 0; - phy_interface_rrc_lte::cell_search_ret_t ret; - do { - ret = cell_search(); - if (ret.found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) { - if (serving_cell->has_sib1()) { - // Save PLMN and TAC to NAS - for (uint32_t i = 0; i < serving_cell->nof_plmns(); i++) { - if (nof_plmns < MAX_FOUND_PLMNS) { - found_plmns[nof_plmns].plmn_id = serving_cell->get_plmn(i); - found_plmns[nof_plmns].tac = serving_cell->get_tac(); - nof_plmns++; - } else { - rrc_log->error("No more space for plmns (%d)\n", nof_plmns); - } - } - } else { - rrc_log->error("SIB1 not acquired\n"); - } - } - } while (ret.last_freq == phy_interface_rrc_lte::cell_search_ret_t::MORE_FREQS && - ret.found != phy_interface_rrc_lte::cell_search_ret_t::ERROR); - - // Process all pending measurements before returning - process_phy_meas(); - - pthread_mutex_unlock(&mutex); - - if (ret.found == phy_interface_rrc_lte::cell_search_ret_t::ERROR) { - return -1; - } else { - return nof_plmns; +bool rrc::plmn_search() +{ + if (not plmn_searcher.launch(this)) { + rrc_log->error("Unable to initiate PLMN search\n"); + return false; } + callback_list.defer_proc(plmn_searcher); + return true; } /* This is the NAS interface. When NAS requests to select a PLMN we have to @@ -423,106 +328,14 @@ void rrc::plmn_select(srslte::plmn_id_t plmn_id) * it. Sends connectionRequest message and returns if message transmitted successfully. * It does not wait until completition of Connection Establishment procedure */ -bool rrc::connection_request(srslte::establishment_cause_t cause, srslte::unique_byte_buffer_t dedicated_info_nas) +bool rrc::connection_request(srslte::establishment_cause_t cause, srslte::unique_byte_buffer_t dedicated_info_nas_) { - - if (!plmn_is_selected) { - rrc_log->error("Trying to connect but PLMN not selected.\n"); - return false; - } - - if (state != RRC_STATE_IDLE) { - rrc_log->warning("Requested RRC connection establishment while not in IDLE\n"); - return false; - } - - if (mac_timers->timer_get(t302)->is_running()) { - rrc_log->info("Requested RRC connection establishment while T302 is running\n"); - nas->set_barring(nas_interface_rrc::BARRING_MO_DATA); + if (not conn_req_proc.launch(this, cause, std::move(dedicated_info_nas_))) { + rrc_log->error("Failed to initiate connection request procedure\n"); return false; } - - bool ret = false; - - pthread_mutex_lock(&mutex); - - rrc_log->info("Initiation of Connection establishment procedure\n"); - - // Perform cell selection & reselection for the selected PLMN - cs_ret_t cs_ret = cell_selection(); - - // .. and SI acquisition - if (phy->cell_is_camping()) { - - // Set default configurations - set_phy_default(); - set_mac_default(); - - // CCCH configuration applied already at start - // timeAlignmentCommon applied in configure_serving_cell - - rrc_log->info("Configuring serving cell...\n"); - if (configure_serving_cell()) { - - mac_timers->timer_get(t300)->reset(); - mac_timers->timer_get(t300)->run(); - - // Send connectionRequest message to lower layers - establishment_cause_e asn1cause((establishment_cause_e::options)cause); - send_con_request(asn1cause); - - // Save dedicatedInfoNAS SDU - if (this->dedicated_info_nas.get()) { - rrc_log->warning("Received a new dedicatedInfoNAS SDU but there was one still in queue. Removing it\n"); - } - this->dedicated_info_nas = std::move(dedicated_info_nas); - - // Wait until t300 stops due to RRCConnectionSetup/Reject or expiry - while (mac_timers->timer_get(t300)->is_running()) { - usleep(1000); - } - - if (state == RRC_STATE_CONNECTED) { - // Received ConnectionSetup - ret = true; - } else if (mac_timers->timer_get(t300)->is_expired()) { - // T300 is expired: 5.3.3.6 - rrc_log->info("Timer T300 expired: ConnectionRequest timed out\n"); - mac->reset(); - set_mac_default(); - rlc->reestablish(); - } else { - // T300 is stopped but RRC not Connected is because received Reject: Section 5.3.3.8 - rrc_log->info("Timer T300 stopped: Received ConnectionReject\n"); - mac->reset(); - set_mac_default(); - } - - } else { - rrc_log->error("Configuring serving cell\n"); - } - } else { - switch(cs_ret) { - case SAME_CELL: - rrc_log->warning("Did not reselect cell but serving cell is out-of-sync.\n"); - serving_cell->in_sync = false; - break; - case CHANGED_CELL: - rrc_log->warning("Selected a new cell but could not camp on. Setting out-of-sync.\n"); - serving_cell->in_sync = false; - break; - default: - rrc_log->warning("Could not find any suitable cell to connect\n"); - } - } - - if (!ret) { - rrc_log->warning("Could not establish connection. Deallocating dedicatedInfoNAS PDU\n"); - this->dedicated_info_nas.reset(); - } - - pthread_mutex_unlock(&mutex); - return ret; + callback_list.defer_proc(conn_req_proc); + return true; } void rrc::set_ue_identity(srslte::s_tmsi_t s_tmsi) @@ -533,45 +346,6 @@ void rrc::set_ue_identity(srslte::s_tmsi_t s_tmsi) "Set ue-Identity to 0x%" PRIu64 ":0x%" PRIu64 "\n", (uint64_t)ue_identity.mmec, (uint64_t)ue_identity.m_tmsi); } -/* Retrieves all required SIB or configures them if already retrieved before - */ -bool rrc::configure_serving_cell() { - - if (!phy->cell_is_camping()) { - rrc_log->error("Trying to configure Cell while not camping on it\n"); - return false; - } - serving_cell->has_mcch = false; - // Obtain the SIBs if not available or apply the configuration if available - for (uint32_t i = 0; i < NOF_REQUIRED_SIBS; i++) { - if (!serving_cell->has_sib(required_sibs[i])) { - rrc_log->info("Cell has no SIB%d. Obtaining SIB%d\n", required_sibs[i]+1, required_sibs[i]+1); - if (!si_acquire(required_sibs[i])) { - rrc_log->info("Timeout while acquiring SIB%d\n", required_sibs[i]+1); - if (required_sibs[i] < 2) { - return false; - } - } - } else { - rrc_log->info("Cell has SIB%d\n", required_sibs[i]+1); - switch(required_sibs[i]) { - case 1: - handle_sib2(); - break; - case 12: - handle_sib13(); - break; - } - } - } - return true; -} - - - - - - /******************************************************************************* * * @@ -625,20 +399,17 @@ void rrc::process_new_phy_meas(phy_meas_t meas) uint32_t earfcn = meas.earfcn; uint32_t pci = meas.pci; - // Measurements in RRC_CONNECTED go through measurement class to log reports etc. - if (state != RRC_STATE_IDLE) { - measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); - - // Measurements in RRC_IDLE update serving cell - } else { - + if (state == RRC_STATE_IDLE) { // Update serving cell if (serving_cell->equals(earfcn, pci)) { serving_cell->set_rsrp(rsrp); - // Or update/add neighbour cell } else { + // Or update/add neighbour cell add_neighbour_cell(earfcn, pci, rsrp); } + } else { + // Measurements in RRC_CONNECTED go through measurement class to log reports etc. + measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); } } @@ -653,20 +424,20 @@ void rrc::out_of_sync() // upon receiving N310 consecutive "out-of-sync" indications for the PCell from lower layers while neither T300, // T301, T304 nor T311 is running: if (state == RRC_STATE_CONNECTED) { - if (!mac_timers->timer_get(t300)->is_running() && !mac_timers->timer_get(t301)->is_running() && - !mac_timers->timer_get(t304)->is_running() && !mac_timers->timer_get(t310)->is_running() && - !mac_timers->timer_get(t311)->is_running()) { + if (!timers->get(t300)->is_running() && !timers->get(t301)->is_running() && !timers->get(t304)->is_running() && + !timers->get(t310)->is_running() && !timers->get(t311)->is_running()) { rrc_log->info("Received out-of-sync while in state %s. n310=%d, t311=%s, t310=%s\n", rrc_state_text[state], n310_cnt, - mac_timers->timer_get(t311)->is_running() ? "running" : "stop", - mac_timers->timer_get(t310)->is_running() ? "running" : "stop"); + timers->get(t311)->is_running() ? "running" : "stop", + timers->get(t310)->is_running() ? "running" : "stop"); n310_cnt++; if (n310_cnt == N310) { rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", - N310, mac_timers->timer_get(t310)->get_timeout()); - mac_timers->timer_get(t310)->reset(); - mac_timers->timer_get(t310)->run(); + N310, + timers->get(t310)->get_timeout()); + timers->get(t310)->reset(); + timers->get(t310)->run(); n310_cnt = 0; } } @@ -676,14 +447,12 @@ void rrc::out_of_sync() // Recovery of physical layer problems (5.3.11.2) void rrc::in_sync() { - // CAUTION: We do not lock in this function since they are called from real-time threads - serving_cell->in_sync = true; - if (mac_timers->timer_get(t310)->is_running()) { + if (timers->get(t310)->is_running()) { n311_cnt++; if (n311_cnt == N311) { - mac_timers->timer_get(t310)->stop(); + timers->get(t310)->stop(); n311_cnt = 0; rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311); } @@ -704,123 +473,6 @@ void rrc::in_sync() - -/******************************************************************************* -* -* -* -* System Information Acquisition procedure -* -* -* -*******************************************************************************/ - - -// Determine SI messages scheduling as in 36.331 5.2.3 Acquisition of an SI message -uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf) { - return (period*10*(1+tti/(period*10))+(offset*10)+sf)%10240; // the 1 means next opportunity -} - -/* Implemnets the SI acquisition procedure - * Configures the MAC/PHY scheduling to retrieve SI messages. The function is blocking and will not - * return until SIB is correctly received or timeout - */ -bool rrc::si_acquire(uint32_t sib_index) -{ - uint32_t tti = 0; - uint32_t si_win_start=0, si_win_len=0; - uint16_t period = 0; - uint32_t sched_index = 0; - uint32_t x, sf, offset; - - uint32_t last_win_start = 0; - uint32_t timeout = 0; - - while(timeout < SIB_SEARCH_TIMEOUT_MS && !serving_cell->has_sib(sib_index)) { - - bool instruct_phy = false; - - if (sib_index == 0) { - - // Instruct MAC to look for SIB1 - tti = mac->get_current_tti(); - si_win_start = sib_start_tti(tti, 2, 0, 5); - if (last_win_start == 0 || - (srslte_tti_interval(tti, last_win_start) >= 20 && srslte_tti_interval(tti, last_win_start) < 1000)) { - - last_win_start = si_win_start; - si_win_len = 1; - instruct_phy = true; - } - period = 20; - sched_index = 0; - } else { - // Instruct MAC to look for SIB2..13 - if (serving_cell->has_sib1()) { - - asn1::rrc::sib_type1_s* sib1 = serving_cell->sib1ptr(); - - // SIB2 scheduling - if (sib_index == 1) { - period = sib1->sched_info_list[0].si_periodicity.to_number(); - sched_index = 0; - } else { - // SIB3+ scheduling Section 5.2.3 - if (sib_index >= 2) { - bool found = false; - for (uint32_t i = 0; i < sib1->sched_info_list.size() && !found; i++) { - for (uint32_t j = 0; j < sib1->sched_info_list[i].sib_map_info.size() && !found; j++) { - if (sib1->sched_info_list[i].sib_map_info[j].to_number() == sib_index + 1) { - period = sib1->sched_info_list[i].si_periodicity.to_number(); - sched_index = i; - found = true; - } - } - } - if (!found) { - rrc_log->info("Could not find SIB%d scheduling in SIB1\n", sib_index+1); - return false; - } - } - } - si_win_len = sib1->si_win_len.to_number(); - x = sched_index * si_win_len; - sf = x % 10; - offset = x / 10; - - tti = mac->get_current_tti(); - si_win_start = sib_start_tti(tti, period, offset, sf); - - if (last_win_start == 0 || (srslte_tti_interval(tti, last_win_start) > period * 5 && - srslte_tti_interval(tti, last_win_start) < 1000)) { - last_win_start = si_win_start; - instruct_phy = true; - } - } else { - rrc_log->error("Trying to receive SIB%d but SIB1 not received\n", sib_index + 1); - } - } - - // Instruct MAC to decode SIB - if (instruct_phy && !serving_cell->has_sib(sib_index)) { - mac->bcch_start_rx(si_win_start, si_win_len); - rrc_log->info("Instructed MAC to search for SIB%d, win_start=%d, win_len=%d, period=%d, sched_index=%d\n", - sib_index+1, si_win_start, si_win_len, period, sched_index); - } - usleep(1000); - timeout++; - } - return serving_cell->has_sib(sib_index); -} - - - - - - - - - /******************************************************************************* * * @@ -831,113 +483,10 @@ bool rrc::si_acquire(uint32_t sib_index) * *******************************************************************************/ -/* Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet - */ -phy_interface_rrc_lte::cell_search_ret_t rrc::cell_search() -{ - phy_interface_rrc_lte::phy_cell_t new_cell; - - phy_interface_rrc_lte::cell_search_ret_t ret = phy->cell_search(&new_cell); - - switch(ret.found) { - case phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND: - rrc_log->info("Cell found in this frequency. Setting new serving cell...\n"); - - // Create cell with NaN RSRP. Will be updated by new_phy_meas() during SIB search. - if (!add_neighbour_cell(new_cell, NAN)) { - rrc_log->info("No more space for neighbour cells\n"); - break; - } - set_serving_cell(new_cell); - - if (phy->cell_is_camping()) { - if (!serving_cell->has_sib1()) { - rrc_log->info("Cell has no SIB1. Obtaining SIB1\n"); - if (!si_acquire(0)) { - rrc_log->error("Timeout while acquiring SIB1\n"); - } - } else { - rrc_log->info("Cell has SIB1\n"); - } - } else { - rrc_log->warning("Could not camp on found cell. Trying next one...\n"); - } - break; - case phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND: - rrc_log->info("No cells found.\n"); - break; - case phy_interface_rrc_lte::cell_search_ret_t::ERROR: - rrc_log->error("In cell search. Finishing PLMN search\n"); - break; - } - return ret; -} - -/* Cell selection procedure 36.304 5.2.3 - * Select the best cell to camp on among the list of known cells - */ -rrc::cs_ret_t rrc::cell_selection() -{ - // Neighbour cells are sorted in descending order of RSRP - for (uint32_t i = 0; i < neighbour_cells.size(); i++) { - if (/*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells - * neighbour_cells[i]->plmn_equals(selected_plmn_id) && */ - neighbour_cells[i]->in_sync) // matches S criteria - { - // If currently connected, verify cell selection criteria - if (!serving_cell->in_sync || - (cell_selection_criteria(neighbour_cells[i]->get_rsrp()) && - neighbour_cells[i]->get_rsrp() > serving_cell->get_rsrp() + 5)) - { - // Try to select Cell - set_serving_cell(i); - rrc_log->info("Selected cell idx=%d, PCI=%d, EARFCN=%d\n", - i, serving_cell->get_pci(), serving_cell->get_earfcn()); - rrc_log->console("Selected cell PCI=%d, EARFCN=%d\n", - serving_cell->get_pci(), serving_cell->get_earfcn()); - - if (phy->cell_select(&serving_cell->phy_cell)) { - if (configure_serving_cell()) { - rrc_log->info("Selected and configured cell successfully\n"); - return CHANGED_CELL; - } else { - rrc_log->error("While configuring serving cell\n"); - } - } else { - serving_cell->in_sync = false; - rrc_log->warning("Could not camp on selected cell\n"); - } - } - } - } - if (serving_cell->in_sync) { - if (!phy->cell_is_camping()) { - rrc_log->info("Serving cell is in-sync but not camping. Selecting it...\n"); - if (phy->cell_select(&serving_cell->phy_cell)) { - rrc_log->info("Selected serving cell OK.\n"); - } else { - serving_cell->in_sync = false; - rrc_log->error("Could not camp on serving cell.\n"); - } - } - return SAME_CELL; - } - // If can not find any suitable cell, search again - rrc_log->info("Cell selection and reselection in IDLE did not find any suitable cell. Searching again\n"); - // If can not camp on any cell, search again for new cells - phy_interface_rrc_lte::cell_search_ret_t ret = cell_search(); - - return (ret.found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) ? CHANGED_CELL : NO_CELL; -} - // Cell selection criteria Section 5.2.3.2 of 36.304 bool rrc::cell_selection_criteria(float rsrp, float rsrq) { - if (get_srxlev(rsrp) > 0 || !serving_cell->has_sib3()) { - return true; - } else { - return false; - } + return (get_srxlev(rsrp) > 0 || !serving_cell->has_sib3()); } float rrc::get_srxlev(float Qrxlevmeas) { @@ -971,70 +520,42 @@ void rrc::cell_reselection(float rsrp, float rsrq) // Set new serving cell void rrc::set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell) { - int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); - if (cell_idx >= 0) { - set_serving_cell(cell_idx); - } else { - rrc_log->error("Setting serving cell: Unkonwn cell with earfcn=%d, PCI=%d\n", phy_cell.earfcn, phy_cell.cell.id); - } -} - -// Set new serving cell -void rrc::set_serving_cell(uint32_t cell_idx) { - - if (cell_idx < neighbour_cells.size()) - { + if (has_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id)) { // Remove future serving cell from neighbours to make space for current serving cell - cell_t *new_serving_cell = neighbour_cells[cell_idx]; - if (!new_serving_cell) { - rrc_log->error("Setting serving cell. Index %d is empty\n", cell_idx); - return; - } - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), - neighbour_cells.end()); + unique_cell_t new_serving_cell = remove_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); // Move serving cell to neighbours list if (serving_cell->is_valid()) { - // Make sure it does not exist already - int serving_idx = find_neighbour_cell(serving_cell->get_earfcn(), serving_cell->get_pci()); - if (serving_idx >= 0 && (uint32_t) serving_idx < neighbour_cells.size()) { - rrc_log->error("Error serving cell is already in the neighbour list. Removing it\n"); - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[serving_idx]), neighbour_cells.end()); - } - // If not in the list, add it to the list of neighbours (sorted inside the function) - if (!add_neighbour_cell(serving_cell)) { - rrc_log->info("Serving cell not added to list of neighbours. Worse than current neighbours\n"); + if (has_neighbour_cell(serving_cell->get_earfcn(), serving_cell->get_pci())) { + rrc_log->error("Error serving cell is already in the neighbour list.\n"); + // note, removing it here is not an option + } else { + if (add_neighbour_cell(std::move(serving_cell)) == false) { + rrc_log->info("Serving cell not added to list of neighbours. Worse than current neighbours\n"); + } } - } else { - // Do not leak it if we are not adding to neighbour list - delete serving_cell; } // Set new serving cell - serving_cell = new_serving_cell; - - rrc_log->info("Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%zd\n", cell_idx, - serving_cell->get_earfcn(), serving_cell->get_pci(), neighbour_cells.size()); - + serving_cell = std::move(new_serving_cell); + rrc_log->info("Setting serving cell earfcn=%d, PCI=%d, rsrp=%.2f, nof_neighbours=%zd\n", + serving_cell->get_earfcn(), + serving_cell->get_pci(), + serving_cell->get_rsrp(), + neighbour_cells.size()); } else { - rrc_log->error("Setting invalid serving cell idx %d\n", cell_idx); + rrc_log->error("Setting serving cell: Unknown cell with earfcn=%d, PCI=%d\n", phy_cell.earfcn, phy_cell.cell.id); } } -bool sort_rsrp(cell_t *u1, cell_t *u2) { - return u1->greater(u2); -} - -void rrc::delete_neighbour(uint32_t cell_idx) { - measurements.delete_report(neighbour_cells[cell_idx]->get_earfcn(), neighbour_cells[cell_idx]->get_pci()); - delete neighbour_cells[cell_idx]; - neighbour_cells.erase(std::remove(neighbour_cells.begin(), neighbour_cells.end(), neighbour_cells[cell_idx]), neighbour_cells.end()); -} - -std::vector::iterator rrc::delete_neighbour(std::vector::iterator it) { - measurements.delete_report((*it)->get_earfcn(), (*it)->get_pci()); - delete (*it); - return neighbour_cells.erase(it); +void rrc::delete_last_neighbour() +{ + if (not neighbour_cells.empty()) { + auto& it = neighbour_cells.back(); + rrc_log->debug("Delete cell earfcn=%d, pci=%d from neighbor list.\n", (*it).get_earfcn(), (*it).get_pci()); + measurements.delete_report((*it).get_earfcn(), (*it).get_pci()); + neighbour_cells.pop_back(); + } } /* Called by main RRC thread to remove neighbours from which measurements have not been received in a while @@ -1044,39 +565,49 @@ void rrc::clean_neighbours() struct timeval now; gettimeofday(&now, NULL); - std::vector::iterator it = neighbour_cells.begin(); - while(it != neighbour_cells.end()) { + for (auto it = neighbour_cells.begin(); it != neighbour_cells.end();) { if ((*it)->timeout_secs(now) > NEIGHBOUR_TIMEOUT) { rrc_log->info("Neighbour PCI=%d timed out. Deleting\n", (*it)->get_pci()); - it = delete_neighbour(it); + it = neighbour_cells.erase(it); } else { ++it; } } } -// Sort neighbour cells by decreasing order of RSRP +// Sort neighbour cells by decreasing order of RSRP and remove old cells from neighbor list void rrc::sort_neighbour_cells() { // Remove out-of-sync cells - std::vector::iterator it = neighbour_cells.begin(); - while(it != neighbour_cells.end()) { + for (auto it = neighbour_cells.begin(); it != neighbour_cells.end();) { if ((*it)->in_sync == false) { rrc_log->info("Neighbour PCI=%d is out-of-sync. Deleting\n", (*it)->get_pci()); - it = delete_neighbour(it); + it = neighbour_cells.erase(it); } else { ++it; } } - std::sort(neighbour_cells.begin(), neighbour_cells.end(), sort_rsrp); + std::sort(std::begin(neighbour_cells), std::end(neighbour_cells), [](const unique_cell_t& a, const unique_cell_t& b) { + return a->greater(b.get()); + }); if (neighbour_cells.size() > 0) { - char ordered[512]; - int n=0; - n += snprintf(ordered, 512, "[pci=%d, rsrp=%.2f", neighbour_cells[0]->phy_cell.cell.id, neighbour_cells[0]->get_rsrp()); + char ordered[512] = {}; + int n = 0; + n += snprintf(ordered, + 512, + "[earfcn=%d, pci=%d, rsrp=%.2f", + neighbour_cells[0]->get_earfcn(), + neighbour_cells[0]->phy_cell.cell.id, + neighbour_cells[0]->get_rsrp()); for (uint32_t i=1;iget_pci(), neighbour_cells[i]->get_rsrp()); + n += snprintf(&ordered[n], + 512 - n, + " | earfcn=%d, pci=%d, rsrp=%.2f", + neighbour_cells[i]->get_earfcn(), + neighbour_cells[i]->get_pci(), + neighbour_cells[i]->get_rsrp()); } rrc_log->info("Neighbours: %s]\n", ordered); } else { @@ -1084,64 +615,82 @@ void rrc::sort_neighbour_cells() } } -bool rrc::add_neighbour_cell(cell_t *new_cell) { +bool rrc::add_neighbour_cell(unique_cell_t new_cell) +{ bool ret = false; if (neighbour_cells.size() < NOF_NEIGHBOUR_CELLS) { ret = true; - } else if (new_cell->greater(neighbour_cells[neighbour_cells.size()-1])) { - // Replace old one by new one - delete_neighbour(neighbour_cells.size()-1); + } else if (new_cell->greater(neighbour_cells.back().get())) { + // delete last neighbour cell + delete_last_neighbour(); ret = true; } if (ret) { - neighbour_cells.push_back(new_cell); + rrc_log->info("Adding neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%zd\n", + new_cell->get_earfcn(), + new_cell->get_pci(), + neighbour_cells.size() + 1); + neighbour_cells.push_back(std::move(new_cell)); } - rrc_log->info("Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%zd\n", - new_cell->get_earfcn(), new_cell->get_pci(), neighbour_cells.size()); + sort_neighbour_cells(); return ret; } // If only neighbour PCI is provided, copy full cell from serving cell -bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { - phy_interface_rrc_lte::phy_cell_t phy_cell; - phy_cell = serving_cell->phy_cell; - phy_cell.earfcn = earfcn; - phy_cell.cell.id = pci; - return add_neighbour_cell(phy_cell, rsrp); +bool rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) +{ + if (serving_cell->is_valid()) { + phy_interface_rrc_lte::phy_cell_t phy_cell; + phy_cell = serving_cell->phy_cell; + phy_cell.earfcn = earfcn; + phy_cell.cell.id = pci; + return add_neighbour_cell(phy_cell, rsrp); + } + return false; } bool rrc::add_neighbour_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, float rsrp) { - if (phy_cell.earfcn == 0) { - phy_cell.earfcn = serving_cell->get_earfcn(); - } - - // First check if already exists - int cell_idx = find_neighbour_cell(phy_cell.earfcn, phy_cell.cell.id); - - rrc_log->info("Adding PCI=%d, earfcn=%d, cell_idx=%d\n", phy_cell.cell.id, phy_cell.earfcn, cell_idx); - - // If exists, update RSRP if provided, sort again and return - if (cell_idx >= 0 && std::isnormal(rsrp)) { - neighbour_cells[cell_idx]->set_rsrp(rsrp); + // if cell exists, update RSRP, if provided, sort again and return + cell_t* cell = get_neighbour_cell_handle(phy_cell.earfcn, phy_cell.cell.id); + if (cell && std::isnormal(rsrp)) { + cell->set_rsrp(rsrp); sort_neighbour_cells(); return true; } - // If not, create a new one - cell_t *new_cell = new cell_t(phy_cell, rsrp); + // if cell doesn't exist, add it + return add_neighbour_cell(unique_cell_t(new cell_t(phy_cell, rsrp))); +} - return add_neighbour_cell(new_cell); +// This will remove the cell from the current neighbour list +rrc::unique_cell_t rrc::remove_neighbour_cell(const uint32_t earfcn, const uint32_t pci) +{ + auto it = find_if(neighbour_cells.begin(), neighbour_cells.end(), [&](const unique_cell_t& cell) { + return cell->equals(earfcn, pci); + }); + if (it != neighbour_cells.end()) { + auto retval = std::move(*it); + it = neighbour_cells.erase(it); + return retval; + } + return nullptr; } -int rrc::find_neighbour_cell(uint32_t earfcn, uint32_t pci) { - for (uint32_t i = 0; i < neighbour_cells.size(); i++) { - if (neighbour_cells[i]->equals(earfcn, pci)) { - return (int) i; +cell_t* rrc::get_neighbour_cell_handle(const uint32_t earfcn, const uint32_t pci) +{ + for (auto& cell : neighbour_cells) { + if (cell->equals(earfcn, pci)) { + return cell.get(); } } - return -1; + return nullptr; +} + +bool rrc::has_neighbour_cell(const uint32_t earfcn, const uint32_t pci) +{ + return get_neighbour_cell_handle(earfcn, pci) != nullptr; } /******************************************************************************* @@ -1240,7 +789,9 @@ void rrc::ra_problem() { void rrc::max_retx_attempted() { //TODO: Handle the radio link failure rrc_log->warning("Max RLC reTx attempted\n"); - radio_link_failure(); + cmd_msg_t msg; + msg.command = cmd_msg_t::RLF; + cmd_q.push(std::move(msg)); } void rrc::timer_expired(uint32_t timeout_id) { @@ -1249,13 +800,13 @@ void rrc::timer_expired(uint32_t timeout_id) { radio_link_failure(); } else if (timeout_id == t311) { rrc_log->info("Timer T311 expired: Going to RRC IDLE\n"); - go_idle = true; + start_go_idle(); } else if (timeout_id == t301) { if (state == RRC_STATE_IDLE) { rrc_log->info("Timer T301 expired: Already in IDLE.\n"); } else { rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); - go_idle = true; + start_go_idle(); } } else if (timeout_id == t302) { rrc_log->info("Timer T302 expired. Informing NAS about barrier alleviation\n"); @@ -1288,7 +839,7 @@ void rrc::timer_expired(uint32_t timeout_id) { * *******************************************************************************/ -void rrc::send_con_request(asn1::rrc::establishment_cause_e cause) +void rrc::send_con_request(srslte::establishment_cause_t cause) { rrc_log->debug("Preparing RRC Connection Request\n"); @@ -1309,7 +860,7 @@ void rrc::send_con_request(asn1::rrc::establishment_cause_e cause) } rrc_conn_req->ue_id.random_value().from_number(random_id); } - rrc_conn_req->establishment_cause = cause; + rrc_conn_req->establishment_cause = (asn1::rrc::establishment_cause_opts::options)cause; send_ul_ccch_msg(ul_ccch_msg); } @@ -1367,9 +918,18 @@ void rrc::send_con_restablish_request() break; case INTEGRITY_ALGORITHM_ID_128_EIA2: security_128_eia2(&k_rrc_int[16], - 0xffffffff, // 32-bit all to ones - 0x1f, // 5-bit all to ones - 1, // 1-bit to one + 0xffffffff, // 32-bit all to ones + 0x1f, // 5-bit all to ones + 1, // 1-bit to one + varShortMAC_packed, + N_bytes, + mac_key); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(&k_rrc_int[16], + 0xffffffff, // 32-bit all to ones + 0x1f, // 5-bit all to ones + 1, // 1-bit to one varShortMAC_packed, N_bytes, mac_key); @@ -1467,8 +1027,10 @@ bool rrc::ho_prepare() asn1::rrc::mob_ctrl_info_s* mob_ctrl_info = &mob_reconf_r8->mob_ctrl_info; rrc_log->info("Processing HO command to target PCell=%d\n", mob_ctrl_info->target_pci); - int target_cell_idx = find_neighbour_cell(serving_cell->get_earfcn(), mob_ctrl_info->target_pci); - if (target_cell_idx < 0) { + uint32_t target_earfcn = (mob_ctrl_info->carrier_freq_present) ? mob_ctrl_info->carrier_freq.dl_carrier_freq + : serving_cell->get_earfcn(); + + if (not has_neighbour_cell(target_earfcn, mob_ctrl_info->target_pci)) { rrc_log->console("Received HO command to unknown PCI=%d\n", mob_ctrl_info->target_pci); rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->get_earfcn(), mob_ctrl_info->target_pci); @@ -1476,13 +1038,8 @@ bool rrc::ho_prepare() } // Section 5.3.5.4 - mac_timers->timer_get(t310)->stop(); - mac_timers->timer_get(t304)->set(this, mob_ctrl_info->t304.to_number()); - if (mob_ctrl_info->carrier_freq_present && - mob_ctrl_info->carrier_freq.dl_carrier_freq != serving_cell->get_earfcn()) { - rrc_log->error("Received mobilityControlInfo for inter-frequency handover\n"); - return false; - } + timers->get(t310)->stop(); + timers->get(t304)->set(this, mob_ctrl_info->t304.to_number()); // Save serving cell and current configuration ho_src_cell = *serving_cell; @@ -1491,11 +1048,11 @@ bool rrc::ho_prepare() ho_src_rnti = uernti.crnti; // Reset/Reestablish stack - mac->clear_rntis(); - phy->meas_reset(); - mac->wait_uplink(); pdcp->reestablish(); rlc->reestablish(); + mac->wait_uplink(); + mac->clear_rntis(); + phy->meas_reset(); mac->reset(); phy->reset(); @@ -1508,16 +1065,17 @@ bool rrc::ho_prepare() apply_rr_config_dedicated(&mob_reconf_r8->rr_cfg_ded); } - // Extract and apply scell config if any - apply_scell_config(mob_reconf_r8); - - if (!phy->cell_select(&neighbour_cells[target_cell_idx]->phy_cell)) { + cell_t* target_cell = get_neighbour_cell_handle(target_earfcn, mob_ctrl_info->target_pci); + if (!phy->cell_select(&target_cell->phy_cell)) { rrc_log->error("Could not synchronize with target cell pci=%d. Trying to return to source PCI\n", - neighbour_cells[target_cell_idx]->get_pci()); + target_cell->get_pci()); return false; } - set_serving_cell(target_cell_idx); + set_serving_cell(target_cell->phy_cell); + + // Extract and apply scell config if any + apply_scell_config(mob_reconf_r8); if (mob_ctrl_info->rach_cfg_ded_present) { rrc_log->info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n", @@ -1555,8 +1113,8 @@ bool rrc::ho_prepare() return true; } -void rrc::ho_ra_completed(bool ra_successful) { - +void rrc::ho_ra_completed(bool ra_successful) +{ if (pending_mob_reconf) { asn1::rrc::rrc_conn_recfg_r8_ies_s* mob_reconf_r8 = &mob_reconf.crit_exts.c1().rrc_conn_recfg_r8(); if (ra_successful) { @@ -1566,7 +1124,7 @@ void rrc::ho_ra_completed(bool ra_successful) { measurements.parse_meas_config(&mob_reconf_r8->meas_cfg); } - mac_timers->timer_get(t304)->stop(); + timers->get(t304)->stop(); } // T304 will expiry and send ho_failure @@ -1596,8 +1154,32 @@ bool rrc::con_reconfig_ho(asn1::rrc::rrc_conn_recfg_s* reconfig) mob_reconf = *reconfig; pending_mob_reconf = true; - ho_start = true; - return true; + start_ho(); + return true; +} + +void rrc::start_ho() +{ + callback_list.defer_task([this]() { + if (state != RRC_STATE_CONNECTED) { + rrc_log->info("HO interrupted, since RRC is no longer in connected state\n"); + return srslte::proc_outcome_t::success; + } + if (not ho_prepare()) { + con_reconfig_failed(); + return srslte::proc_outcome_t::error; + } + return srslte::proc_outcome_t::success; + }); +} + +void rrc::start_go_idle() +{ + if (not idle_setter.launch(this)) { + rrc_log->info("Failed to set RRC to IDLE\n"); + return; + } + callback_list.defer_proc(idle_setter); } // Handle RRC Reconfiguration without MobilityInformation Section 5.3.5.3 @@ -1669,7 +1251,7 @@ void rrc::ho_failed() void rrc::con_reconfig_failed() { // Set previous PHY/MAC configuration - phy->set_config(&previous_phy_cfg); + phy->set_config(previous_phy_cfg); mac->set_config(previous_mac_cfg); // And restore current configs @@ -1680,7 +1262,7 @@ void rrc::con_reconfig_failed() // Start the Reestablishment Procedure init_con_restablish_request(asn1::rrc::reest_cause_e::recfg_fail); } else { - go_idle = true; + start_go_idle(); } } @@ -1705,7 +1287,7 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, asn1::rrc::rrc_conn_recfg_s* re void rrc::rrc_connection_release() { // Save idleModeMobilityControlInfo, etc. rrc_log->console("Received RRC Connection Release\n"); - go_idle = true; + start_go_idle(); } /* Actions upon leaving RRC_CONNECTED 5.3.12 */ @@ -1715,15 +1297,14 @@ void rrc::leave_connected() rrc_log->info("Leaving RRC_CONNECTED state\n"); m_reest_cause = asn1::rrc::reest_cause_e::nulltype; state = RRC_STATE_IDLE; - rlc_flush_counter = 0; drb_up = false; security_is_activated = false; measurements.reset(); - nas->leave_connected(); + nas->left_rrc_connected(); pdcp->reset(); rlc->reset(); - phy->reset(); mac->reset(); + phy->reset(); set_phy_default(); set_mac_default(); stop_timers(); @@ -1738,11 +1319,11 @@ void rrc::leave_connected() void rrc::stop_timers() { - mac_timers->timer_get(t300)->stop(); - mac_timers->timer_get(t301)->stop(); - mac_timers->timer_get(t310)->stop(); - mac_timers->timer_get(t311)->stop(); - mac_timers->timer_get(t304)->stop(); + timers->get(t300)->stop(); + timers->get(t301)->stop(); + timers->get(t310)->stop(); + timers->get(t311)->stop(); + timers->get(t304)->stop(); } /* Implementation of procedure in 3GPP 36.331 Section 5.3.7.2: Initiation @@ -1775,7 +1356,7 @@ void rrc::init_con_restablish_request(asn1::rrc::reest_cause_e cause) // 3GPP 36.331 Section 5.3.7.1 // If AS security has not been activated, the UE does not initiate the procedure but instead // moves to RRC_IDLE directly - go_idle = true; + start_go_idle(); } } @@ -1790,11 +1371,11 @@ void rrc::proc_con_restablish_request() rrc_log->info("Resetting timers and MAC in RRC Connection Reestablishment Procedure\n"); // stop timer T310, if running; - mac_timers->timer_get(t310)->stop(); + timers->get(t310)->stop(); // start timer T311; - mac_timers->timer_get(t311)->reset(); - mac_timers->timer_get(t311)->run(); + timers->get(t311)->reset(); + timers->get(t311)->run(); // Suspend all RB except SRB0 for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) { @@ -1820,7 +1401,7 @@ void rrc::proc_con_restablish_request() } // Check timer... - if (mac_timers->timer_get(t311)->is_running()) { + if (timers->get(t311)->is_running()) { // Check for synchronism if (serving_cell->in_sync) { // Perform cell selection in accordance to 36.304 @@ -1828,16 +1409,16 @@ void rrc::proc_con_restablish_request() // Actions following cell reselection while T311 is running 5.3.7.3 // Upon selecting a suitable E-UTRA cell, the UE shall: rrc_log->info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n", - mac_timers->timer_get(t311)->value()); + timers->get(t311)->value()); // stop timer T311; - mac_timers->timer_get(t301)->reset(); + timers->get(t301)->reset(); // start timer T301; - mac_timers->timer_get(t301)->run(); + timers->get(t301)->run(); // apply the timeAlignmentTimerCommon included in SystemInformationBlockType2; - mac_timers->timer_get(t311)->stop(); + timers->get(t311)->stop(); // initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4; send_con_restablish_request(); @@ -1858,22 +1439,95 @@ void rrc::proc_con_restablish_request() } } +void rrc::start_cell_reselection() +{ + if (neighbour_cells.empty() and serving_cell->in_sync and phy->cell_is_camping()) { + // don't bother with cell selection if there are no neighbours and we are already camping + return; + } + + if (not cell_selector.launch(this)) { + rrc_log->error("Failed to initiate a Cell Selection procedure...\n"); + return; + } + + rrc_log->info("Cell Reselection - Starting...\n"); + callback_list.defer_task([this]() { + if (cell_selector.run()) { + return srslte::proc_outcome_t::yield; + } + cell_selection_proc ret = cell_selector.pop(); + if (ret.is_error()) { + rrc_log->error("Cell Reselection - Error while selecting a cell\n"); + return srslte::proc_outcome_t::error; + } else { + switch (ret.get_cs_result()) { + case cs_result_t::changed_cell: + // New cell has been selected, start receiving PCCH + mac->pcch_start_rx(); + break; + case cs_result_t::no_cell: + rrc_log->warning("Could not find any cell to camp on\n"); + break; + case cs_result_t::same_cell: + if (!phy->cell_is_camping()) { + rrc_log->warning("Did not reselect cell but serving cell is out-of-sync.\n"); + serving_cell->in_sync = false; + } + break; + } + } + rrc_log->info("Cell Reselection - Finished successfully\n"); + return srslte::proc_outcome_t::success; + }); +} + +void rrc::cell_search_completed(const phy_interface_rrc_lte::cell_search_ret_t& cs_ret, + const phy_interface_rrc_lte::phy_cell_t& found_cell) +{ + cell_searcher.trigger_event(cell_search_proc::cell_search_event_t{cs_ret, found_cell}); +} + /******************************************************************************* -* -* -* -* Reception of Broadcast messages (MIB and SIBs) -* -* -* -*******************************************************************************/ + * + * + * + * Reception of Broadcast messages (MIB and SIBs) + * + * + * + *******************************************************************************/ void rrc::write_pdu_bcch_bch(unique_byte_buffer_t pdu) { + asn1::rrc::bcch_bch_msg_s bch_msg; + asn1::bit_ref bch_bref(pdu->msg, pdu->N_bytes); + asn1::SRSASN_CODE err = bch_msg.unpack(bch_bref); + if (err != asn1::SRSASN_SUCCESS) { + rrc_log->error("Could not unpack BCCH-BCH message.\n"); + return; + } + + if (rrc_log->get_level() == srslte::LOG_LEVEL_INFO) { + rrc_log->info("BCCH-BCH - Rx (%d B)\n", pdu->N_bytes); + } else if (rrc_log->get_level() >= srslte::LOG_LEVEL_DEBUG) { + asn1::json_writer json_writer; + bch_msg.to_json(json_writer); + rrc_log->debug_hex(pdu->msg, pdu->N_bytes, "BCCH-BCH - Rx (%d B)\n", pdu->N_bytes); + rrc_log->debug("Content:\n%s\n", json_writer.to_string().c_str()); + } + // Do we need to do something with BCH? - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH BCH message received."); } void rrc::write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) +{ + cmd_msg_t msg; + msg.command = cmd_msg_t::PDU_BCCH_DLSCH; + msg.pdu = std::move(pdu); + cmd_q.push(std::move(msg)); +} + +void rrc::parse_pdu_bcch_dlsch(unique_byte_buffer_t pdu) { // Stop BCCH search after successful reception of 1 BCCH block mac->bcch_stop_rx(); @@ -1886,7 +1540,7 @@ void rrc::write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) return; } - log_rrc_message("BCCH", Rx, pdu.get(), dlsch_msg); + log_rrc_message("BCCH-DLSCH", Rx, pdu.get(), dlsch_msg); if (dlsch_msg.msg.c1().type() == bcch_dl_sch_msg_type_c::c1_c_::types::sib_type1) { rrc_log->info("Processing SIB1 (1/1)\n"); @@ -1940,7 +1594,10 @@ void rrc::handle_sib1() // Set TDD Config if (sib1->tdd_cfg_present) { - phy->set_config_tdd(&sib1->tdd_cfg); + srslte_tdd_config_t tdd_config; + tdd_config.sf_config = sib1->tdd_cfg.sf_assign.to_number(); + tdd_config.ss_config = sib1->tdd_cfg.special_sf_patterns.to_number(); + phy->set_config_tdd(tdd_config); } } @@ -1951,20 +1608,27 @@ void rrc::handle_sib2() sib_type2_s* sib2 = serving_cell->sib2ptr(); // Apply RACH and timeAlginmentTimer configuration - current_mac_cfg.set_rach_cfg_common(sib2->rr_cfg_common.rach_cfg_common); - current_mac_cfg.set_time_alignment(sib2->time_align_timer_common); + set_mac_cfg_t_rach_cfg_common(¤t_mac_cfg, sib2->rr_cfg_common.rach_cfg_common); + set_mac_cfg_t_time_alignment(¤t_mac_cfg, sib2->time_align_timer_common); mac->set_config(current_mac_cfg); // Set MBSFN configs - phy->set_config_mbsfn_sib2(sib2); + if (sib2->mbsfn_sf_cfg_list_present) { + srslte::mbsfn_sf_cfg_t list[ASN1_RRC_MAX_MBSFN_ALLOCS]; + for (uint32_t i = 0; i < sib2->mbsfn_sf_cfg_list.size(); ++i) { + list[i] = srslte::make_mbsfn_sf_cfg(sib2->mbsfn_sf_cfg_list[i]); + } + phy->set_config_mbsfn_sib2(&list[0], sib2->mbsfn_sf_cfg_list.size()); + } // Apply PHY RR Config Common - current_phy_cfg.common.pdsch_cnfg = sib2->rr_cfg_common.pdsch_cfg_common; - current_phy_cfg.common.pusch_cnfg = sib2->rr_cfg_common.pusch_cfg_common; - current_phy_cfg.common.pucch_cnfg = sib2->rr_cfg_common.pucch_cfg_common; - current_phy_cfg.common.ul_pwr_ctrl = sib2->rr_cfg_common.ul_pwr_ctrl_common; - current_phy_cfg.common.prach_cnfg = sib2->rr_cfg_common.prach_cfg; - current_phy_cfg.common.srs_ul_cnfg = sib2->rr_cfg_common.srs_ul_cfg_common; + set_phy_cfg_t_common_pdsch(¤t_phy_cfg, sib2->rr_cfg_common.pdsch_cfg_common); + set_phy_cfg_t_common_pusch(¤t_phy_cfg, sib2->rr_cfg_common.pusch_cfg_common); + set_phy_cfg_t_common_pucch(¤t_phy_cfg, sib2->rr_cfg_common.pucch_cfg_common); + set_phy_cfg_t_common_pwr_ctrl(¤t_phy_cfg, sib2->rr_cfg_common.ul_pwr_ctrl_common); + set_phy_cfg_t_common_prach( + ¤t_phy_cfg, &sib2->rr_cfg_common.prach_cfg.prach_cfg_info, sib2->rr_cfg_common.prach_cfg.root_seq_idx); + set_phy_cfg_t_common_srs(¤t_phy_cfg, sib2->rr_cfg_common.srs_ul_cfg_common); // According to 3GPP 36.331 v12 UE-EUTRA-Capability field descriptions // Allow 64QAM for: @@ -1972,36 +1636,36 @@ void rrc::handle_sib2() // ue-CategoryUL 5 and 13 when enable64QAM (with suffix) // enable64QAM-v1270 shall be ignored if enable64QAM (without suffix) is false if (args.ue_category == 5 || (args.release >= 10 && args.ue_category == 8)) { - current_phy_cfg.common.rrc_enable_64qam = sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam; + set_phy_cfg_t_enable_64qam(¤t_phy_cfg, sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam); } else if (args.release >= 12 && sib2->rr_cfg_common.pusch_cfg_common.pusch_cfg_basic.enable64_qam) { if (args.ue_category_ul == 5 || args.ue_category_ul == 13) { // ASN1 Generator simplifies enable64QAM-v1270 because it is an enumeration that is always true - current_phy_cfg.common.rrc_enable_64qam = sib2->rr_cfg_common.pusch_cfg_common_v1270_present; + set_phy_cfg_t_enable_64qam(¤t_phy_cfg, sib2->rr_cfg_common.pusch_cfg_common_v1270.is_present()); } else { - current_phy_cfg.common.rrc_enable_64qam = false; + set_phy_cfg_t_enable_64qam(¤t_phy_cfg, false); } } else { - current_phy_cfg.common.rrc_enable_64qam = false; + set_phy_cfg_t_enable_64qam(¤t_phy_cfg, false); } - phy->set_config(¤t_phy_cfg); + phy->set_config(current_phy_cfg); log_rr_config_common(); - mac_timers->timer_get(t300)->set(this, sib2->ue_timers_and_consts.t300.to_number()); - mac_timers->timer_get(t301)->set(this, sib2->ue_timers_and_consts.t301.to_number()); - mac_timers->timer_get(t310)->set(this, sib2->ue_timers_and_consts.t310.to_number()); - mac_timers->timer_get(t311)->set(this, sib2->ue_timers_and_consts.t311.to_number()); + timers->get(t300)->set(this, sib2->ue_timers_and_consts.t300.to_number()); + timers->get(t301)->set(this, sib2->ue_timers_and_consts.t301.to_number()); + timers->get(t310)->set(this, sib2->ue_timers_and_consts.t310.to_number()); + timers->get(t311)->set(this, sib2->ue_timers_and_consts.t311.to_number()); N310 = sib2->ue_timers_and_consts.n310.to_number(); N311 = sib2->ue_timers_and_consts.n311.to_number(); rrc_log->info("Set Constants and Timers: N310=%d, N311=%d, t300=%d, t301=%d, t310=%d, t311=%d\n", N310, N311, - mac_timers->timer_get(t300)->get_timeout(), - mac_timers->timer_get(t301)->get_timeout(), - mac_timers->timer_get(t310)->get_timeout(), - mac_timers->timer_get(t311)->get_timeout()); + timers->get(t300)->get_timeout(), + timers->get(t301)->get_timeout(), + timers->get(t310)->get_timeout(), + timers->get(t311)->get_timeout()); } void rrc::handle_sib3() @@ -2031,7 +1695,7 @@ void rrc::handle_sib13() sib_type13_r9_s* sib13 = serving_cell->sib13ptr(); - phy->set_config_mbsfn_sib13(sib13); + phy->set_config_mbsfn_sib13(srslte::make_sib13(*sib13)); add_mrb(0, 0); // Add MRB0 } @@ -2052,87 +1716,78 @@ void rrc::write_pdu_pcch(unique_byte_buffer_t pdu) cmd_q.push(std::move(msg)); } +void rrc::paging_completed(bool outcome) +{ + pcch_processor.trigger_event(process_pcch_proc::paging_complete{outcome}); +} + void rrc::process_pcch(unique_byte_buffer_t pdu) { - if (pdu->N_bytes > 0 && pdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES) { - pcch_msg_s pcch_msg; - asn1::bit_ref bref(pdu->msg, pdu->N_bytes); - if (pcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or pcch_msg.msg.type().value != pcch_msg_type_c::types_opts::c1) { - rrc_log->error("Failed to unpack PCCH message\n"); - return; - } + if (pdu->N_bytes <= 0 or pdu->N_bytes >= SRSLTE_MAX_BUFFER_SIZE_BITS) { + rrc_log->error_hex(pdu->buffer, pdu->N_bytes, "Dropping PCCH message with %d B\n", pdu->N_bytes); + return; + } - log_rrc_message("PCCH", Rx, pdu.get(), pcch_msg); + pcch_msg_s pcch_msg; + asn1::bit_ref bref(pdu->msg, pdu->N_bytes); + if (pcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or pcch_msg.msg.type().value != pcch_msg_type_c::types_opts::c1) { + rrc_log->error_hex(pdu->buffer, pdu->N_bytes, "Failed to unpack PCCH message (%d B)\n", pdu->N_bytes); + return; + } - paging_s* paging = &pcch_msg.msg.c1().paging(); - if (paging->paging_record_list.size() > ASN1_RRC_MAX_PAGE_REC) { - paging->paging_record_list.resize(ASN1_RRC_MAX_PAGE_REC); - } + log_rrc_message("PCCH", Rx, pdu.get(), pcch_msg); - if (not ue_identity_configured) { - rrc_log->warning("Received paging message but no ue-Identity is configured\n"); - return; - } + if (not ue_identity_configured) { + rrc_log->warning("Received paging message but no ue-Identity is configured\n"); + return; + } - for (uint32_t i = 0; i < paging->paging_record_list.size(); i++) { - s_tmsi_t s_tmsi_paged = make_s_tmsi_t(paging->paging_record_list[i].ue_id.s_tmsi()); - rrc_log->info("Received paging (%d/%d) for UE %" PRIu64 ":%" PRIu64 "\n", - i + 1, - paging->paging_record_list.size(), - (uint64_t)s_tmsi_paged.mmec, - (uint64_t)s_tmsi_paged.m_tmsi); - if (ue_identity.mmec == s_tmsi_paged.mmec && ue_identity.m_tmsi == s_tmsi_paged.m_tmsi) { - if (RRC_STATE_IDLE == state) { - rrc_log->info("S-TMSI match in paging message\n"); - rrc_log->console("S-TMSI match in paging message\n"); - nas->paging(&s_tmsi_paged); - } else { - rrc_log->warning("Received paging while in CONNECT\n"); - } - } else { - rrc_log->info("Received paging for unknown identity\n"); - } - } + paging_s* paging = &pcch_msg.msg.c1().paging(); + if (paging->paging_record_list.size() > ASN1_RRC_MAX_PAGE_REC) { + paging->paging_record_list.resize(ASN1_RRC_MAX_PAGE_REC); + } - if (paging->sys_info_mod_present) { - rrc_log->info("Received System Information notification update request.\n"); - // invalidate and then update all SIBs of serving cell - serving_cell->reset_sibs(); - if (configure_serving_cell()) { - rrc_log->info("All SIBs of serving cell obtained successfully\n"); - } else { - rrc_log->error("While obtaining SIBs of serving cell.\n"); - } - } - } else { - rrc_log->error_hex(pdu->buffer, pdu->N_bytes, "Dropping PCCH message with %d B\n", pdu->N_bytes); + if (not pcch_processor.launch(this, *paging)) { + rrc_log->error("Failed to launch process PCCH procedure\n"); + return; } + + // we do not care about the outcome + callback_list.defer_proc(pcch_processor); } void rrc::write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) { - if (pdu->N_bytes > 0 && pdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES) { - //TODO: handle MCCH notifications and update MCCH - if (0 == lcid && !serving_cell->has_mcch) { - asn1::bit_ref bref(pdu->msg, pdu->N_bytes); - if (serving_cell->mcch.unpack(bref) != asn1::SRSASN_SUCCESS or - serving_cell->mcch.msg.type().value != mcch_msg_type_c::types_opts::c1) { - rrc_log->error("Failed to unpack MCCH message\n"); - return; - } - serving_cell->has_mcch = true; - phy->set_config_mbsfn_mcch(&serving_cell->mcch); - log_rrc_message("MCH", Rx, pdu.get(), serving_cell->mcch); - cmd_msg_t msg; - msg.command = cmd_msg_t::MBMS_START; - cmd_q.push(std::move(msg)); - } + if (pdu->N_bytes <= 0 or pdu->N_bytes >= SRSLTE_MAX_BUFFER_SIZE_BITS) { + return; + } + // TODO: handle MCCH notifications and update MCCH + if (0 != lcid or serving_cell->has_mcch) { + return; } + cmd_msg_t msg; + msg.command = cmd_msg_t::PDU_MCH; + msg.pdu = std::move(pdu); + msg.lcid = lcid; + cmd_q.push(std::move(msg)); } - - - +void rrc::parse_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) +{ + asn1::bit_ref bref(pdu->msg, pdu->N_bytes); + if (serving_cell->mcch.unpack(bref) != asn1::SRSASN_SUCCESS or + serving_cell->mcch.msg.type().value != mcch_msg_type_c::types_opts::c1) { + rrc_log->error("Failed to unpack MCCH message\n"); + return; + } + serving_cell->has_mcch = true; + phy->set_config_mbsfn_mcch(srslte::make_mcch_msg(serving_cell->mcch)); + log_rrc_message("MCH", Rx, pdu.get(), serving_cell->mcch); + if (args.mbms_service_id >= 0) { + rrc_log->info("Attempting to auto-start MBMS service %d\n", args.mbms_service_id); + mbms_service_start(args.mbms_service_id, args.mbms_service_port); + } +} /******************************************************************************* * @@ -2196,7 +1851,6 @@ void rrc::send_ul_dcch_msg(uint32_t lcid, const asn1::rrc::ul_dcch_msg_s& msg) void rrc::write_sdu(srslte::unique_byte_buffer_t sdu) { - if (state == RRC_STATE_IDLE) { rrc_log->warning("Received ULInformationTransfer SDU when in IDLE\n"); return; @@ -2206,26 +1860,6 @@ void rrc::write_sdu(srslte::unique_byte_buffer_t sdu) void rrc::write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) { - // If the message contains a ConnectionSetup, acknowledge the transmission to avoid blocking of paging procedure - if (lcid == 0) { - // FIXME: We unpack and process this message twice to check if it's ConnectionSetup - asn1::bit_ref bref(pdu->msg, pdu->N_bytes); - asn1::rrc::dl_ccch_msg_s dl_ccch_msg; - if (dl_ccch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or - dl_ccch_msg.msg.type().value != dl_ccch_msg_type_c::types_opts::c1) { - rrc_log->error("Failed to unpack DL-CCCH message\n"); - return; - } - if (dl_ccch_msg.msg.c1().type() == dl_ccch_msg_type_c::c1_c_::types::rrc_conn_setup) { - // Must enter CONNECT before stopping T300 - state = RRC_STATE_CONNECTED; - - mac_timers->timer_get(t300)->stop(); - mac_timers->timer_get(t302)->stop(); - rrc_log->console("RRC Connected\n"); - } - } - // add PDU to command queue cmd_msg_t msg; msg.pdu = std::move(pdu); @@ -2269,16 +1903,16 @@ void rrc::parse_dl_ccch(unique_byte_buffer_t pdu) rrc_log->info("Received ConnectionReject. Wait time: %d\n", reject_r8->wait_time); rrc_log->console("Received ConnectionReject. Wait time: %d\n", reject_r8->wait_time); - mac_timers->timer_get(t300)->stop(); + timers->get(t300)->stop(); if (reject_r8->wait_time) { nas->set_barring(nas_interface_rrc::BARRING_ALL); - mac_timers->timer_get(t302)->set(this, reject_r8->wait_time * 1000u); - mac_timers->timer_get(t302)->run(); + timers->get(t302)->set(this, reject_r8->wait_time * 1000u); + timers->get(t302)->run(); } else { // Perform the actions upon expiry of T302 if wait time is zero nas->set_barring(nas_interface_rrc::BARRING_NONE); - go_idle = true; + start_go_idle(); } } break; case dl_ccch_msg_type_c::c1_c_::types::rrc_conn_setup: @@ -2293,7 +1927,7 @@ void rrc::parse_dl_ccch(unique_byte_buffer_t pdu) /* Reception of RRCConnectionReestablishmentReject 5.3.7.8 */ case dl_ccch_msg_type_c::c1_c_::types::rrc_conn_reest_reject: rrc_log->console("Reestablishment Reject\n"); - go_idle = true; + start_go_idle(); break; default: rrc_log->error("The provided DL-CCCH message type is not recognized\n"); @@ -2365,12 +1999,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, unique_byte_buffer_t pdu) break; case dl_dcch_msg_type_c::c1_c_::types::ue_cap_enquiry: transaction_id = c1->ue_cap_enquiry().rrc_transaction_id; - for (uint32_t i = 0; i < c1->ue_cap_enquiry().crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request.size(); i++) { - if (c1->ue_cap_enquiry().crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request[i] == rat_type_e::eutra) { - send_rrc_ue_cap_info(); - break; - } - } + handle_ue_capability_enquiry(c1->ue_cap_enquiry()); break; case dl_dcch_msg_type_c::c1_c_::types::rrc_conn_release: rrc_connection_release(); @@ -2397,7 +2026,7 @@ void rrc::enable_capabilities() rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling"); } -void rrc::send_rrc_ue_cap_info() +void rrc::handle_ue_capability_enquiry(const asn1::rrc::ue_cap_enquiry_s& enquiry) { rrc_log->debug("Preparing UE Capability Info\n"); @@ -2405,225 +2034,238 @@ void rrc::send_rrc_ue_cap_info() ue_cap_info_r8_ies_s* info = &ul_dcch_msg.msg.set_c1().set_ue_cap_info().crit_exts.set_c1().set_ue_cap_info_r8(); ul_dcch_msg.msg.c1().ue_cap_info().rrc_transaction_id = transaction_id; - info->ue_cap_rat_container_list.resize(1); - info->ue_cap_rat_container_list[0].rat_type = rat_type_e::eutra; - - // Check UE config arguments bounds - if (args.release < SRSLTE_RELEASE_MIN || args.release > SRSLTE_RELEASE_MAX) { - uint32_t new_release = SRSLTE_MIN(SRSLTE_RELEASE_MAX, SRSLTE_MAX(SRSLTE_RELEASE_MIN, args.release)); - rrc_log->error("Release is %d. It is out of bounds (%d ... %d), setting it to %d\n", - args.release, - SRSLTE_RELEASE_MIN, - SRSLTE_RELEASE_MAX, - new_release); - args.release = new_release; - } - - args.ue_category = (uint32_t)strtol(args.ue_category_str.c_str(), NULL, 10); - if (args.ue_category < SRSLTE_UE_CATEGORY_MIN || args.ue_category > SRSLTE_UE_CATEGORY_MAX) { - uint32_t new_category = SRSLTE_MIN(SRSLTE_UE_CATEGORY_MAX, SRSLTE_MAX(SRSLTE_UE_CATEGORY_MIN, args.ue_category)); - rrc_log->error("UE Category is %d. It is out of bounds (%d ... %d), setting it to %d\n", - args.ue_category, - SRSLTE_UE_CATEGORY_MIN, - SRSLTE_UE_CATEGORY_MAX, - new_category); - args.ue_category = new_category; - } - - ue_eutra_cap_s cap; - cap.access_stratum_release = (access_stratum_release_e::options)(args.release - SRSLTE_RELEASE_MIN); - cap.ue_category = (uint8_t)((args.ue_category < 1 || args.ue_category > 5) ? 4 : args.ue_category); - cap.pdcp_params.max_num_rohc_context_sessions_present = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0001_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0002_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0003_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0004_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0006_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0101_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0102_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0103_r15 = false; - cap.pdcp_params.supported_rohc_profiles.profile0x0104_r15 = false; - - cap.phy_layer_params.ue_specific_ref_sigs_supported = false; - cap.phy_layer_params.ue_tx_ant_sel_supported = false; - - cap.rf_params.supported_band_list_eutra.resize(args.nof_supported_bands); - cap.meas_params.band_list_eutra.resize(args.nof_supported_bands); - for (uint32_t i = 0; i < args.nof_supported_bands; i++) { - cap.rf_params.supported_band_list_eutra[i].band_eutra = args.supported_bands[i]; - cap.rf_params.supported_band_list_eutra[i].half_duplex = false; - cap.meas_params.band_list_eutra[i].inter_freq_band_list.resize(1); - cap.meas_params.band_list_eutra[i].inter_freq_band_list[0].inter_freq_need_for_gaps = true; - } - - cap.feature_group_inds_present = true; - cap.feature_group_inds.from_number(args.feature_group); - - if (args.release > 8) { - ue_eutra_cap_v920_ies_s cap_v920; - - cap_v920.phy_layer_params_v920.enhanced_dual_layer_fdd_r9_present = false; - cap_v920.phy_layer_params_v920.enhanced_dual_layer_tdd_r9_present = false; - cap_v920.inter_rat_params_geran_v920.dtm_r9_present = false; - cap_v920.inter_rat_params_geran_v920.e_redirection_geran_r9_present = false; - cap_v920.csg_proximity_ind_params_r9.inter_freq_proximity_ind_r9_present = false; - cap_v920.csg_proximity_ind_params_r9.intra_freq_proximity_ind_r9_present = false; - cap_v920.csg_proximity_ind_params_r9.utran_proximity_ind_r9_present = false; - cap_v920.neigh_cell_si_acquisition_params_r9.inter_freq_si_acquisition_for_ho_r9_present = false; - cap_v920.neigh_cell_si_acquisition_params_r9.intra_freq_si_acquisition_for_ho_r9_present = false; - cap_v920.neigh_cell_si_acquisition_params_r9.utran_si_acquisition_for_ho_r9_present = false; - cap_v920.son_params_r9.rach_report_r9_present = false; - - cap.non_crit_ext_present = true; - cap.non_crit_ext = cap_v920; - } - - if (args.release > 9) { - - phy_layer_params_v1020_s phy_layer_params_v1020; - phy_layer_params_v1020.two_ant_ports_for_pucch_r10_present = false; - phy_layer_params_v1020.tm9_with_minus8_tx_fdd_r10_present = false; - phy_layer_params_v1020.pmi_disabling_r10_present = false; - phy_layer_params_v1020.cross_carrier_sched_r10_present = args.support_ca; - phy_layer_params_v1020.simul_pucch_pusch_r10_present = false; - phy_layer_params_v1020.multi_cluster_pusch_within_cc_r10_present = false; - phy_layer_params_v1020.non_contiguous_ul_ra_within_cc_list_r10_present = false; - - band_combination_params_r10_l combination_params; - if (args.support_ca) { - for (uint32_t i = 0; i < args.nof_supported_bands; i++) { - ca_mimo_params_dl_r10_s ca_mimo_params_dl; - ca_mimo_params_dl.ca_bw_class_dl_r10 = ca_bw_class_r10_e::f; - ca_mimo_params_dl.supported_mimo_cap_dl_r10_present = false; - - ca_mimo_params_ul_r10_s ca_mimo_params_ul; - ca_mimo_params_ul.ca_bw_class_ul_r10 = ca_bw_class_r10_e::f; - ca_mimo_params_ul.supported_mimo_cap_ul_r10_present = false; - - band_params_r10_s band_params; - band_params.band_eutra_r10 = args.supported_bands[i]; - band_params.band_params_dl_r10_present = true; - band_params.band_params_dl_r10.push_back(ca_mimo_params_dl); - band_params.band_params_ul_r10_present = true; - band_params.band_params_ul_r10.push_back(ca_mimo_params_ul); - - combination_params.push_back(band_params); + // resize container to fit all requested RATs + info->ue_cap_rat_container_list.resize(enquiry.crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request.size()); + uint32_t rat_idx = 0; + + for (uint32_t i = 0; i < enquiry.crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request.size(); i++) { + if (enquiry.crit_exts.c1().ue_cap_enquiry_r8().ue_cap_request[i] == rat_type_e::eutra) { + // adding EUTRA caps + info->ue_cap_rat_container_list[0].rat_type = rat_type_e::eutra; + + // Check UE config arguments bounds + if (args.release < SRSLTE_RELEASE_MIN || args.release > SRSLTE_RELEASE_MAX) { + uint32_t new_release = SRSLTE_MIN(SRSLTE_RELEASE_MAX, SRSLTE_MAX(SRSLTE_RELEASE_MIN, args.release)); + rrc_log->error("Release is %d. It is out of bounds (%d ... %d), setting it to %d\n", + args.release, + SRSLTE_RELEASE_MIN, + SRSLTE_RELEASE_MAX, + new_release); + args.release = new_release; } - } - rf_params_v1020_s rf_params; - rf_params.supported_band_combination_r10.push_back(combination_params); + args.ue_category = (uint32_t)strtol(args.ue_category_str.c_str(), nullptr, 10); + if (args.ue_category < SRSLTE_UE_CATEGORY_MIN || args.ue_category > SRSLTE_UE_CATEGORY_MAX) { + uint32_t new_category = + SRSLTE_MIN(SRSLTE_UE_CATEGORY_MAX, SRSLTE_MAX(SRSLTE_UE_CATEGORY_MIN, args.ue_category)); + rrc_log->error("UE Category is %d. It is out of bounds (%d ... %d), setting it to %d\n", + args.ue_category, + SRSLTE_UE_CATEGORY_MIN, + SRSLTE_UE_CATEGORY_MAX, + new_category); + args.ue_category = new_category; + } - ue_eutra_cap_v1020_ies_s cap_v1020; - if (args.ue_category >= 6 && args.ue_category <= 8) { - cap_v1020.ue_category_v1020_present = true; - cap_v1020.ue_category_v1020 = (uint8_t)args.ue_category; - } else { - // Do not populate UE category for this release if the category is out of range - } - cap_v1020.phy_layer_params_v1020_present = true; - cap_v1020.phy_layer_params_v1020 = phy_layer_params_v1020; - cap_v1020.rf_params_v1020_present = args.support_ca; - cap_v1020.rf_params_v1020 = rf_params; + ue_eutra_cap_s cap; + cap.access_stratum_release = (access_stratum_release_e::options)(args.release - SRSLTE_RELEASE_MIN); + cap.ue_category = (uint8_t)((args.ue_category < 1 || args.ue_category > 5) ? 4 : args.ue_category); + cap.pdcp_params.max_num_rohc_context_sessions_present = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0001_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0002_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0003_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0004_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0006_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0101_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0102_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0103_r15 = false; + cap.pdcp_params.supported_rohc_profiles.profile0x0104_r15 = false; + + cap.phy_layer_params.ue_specific_ref_sigs_supported = false; + cap.phy_layer_params.ue_tx_ant_sel_supported = false; + + cap.rf_params.supported_band_list_eutra.resize(args.nof_supported_bands); + cap.meas_params.band_list_eutra.resize(args.nof_supported_bands); + for (uint32_t k = 0; k < args.nof_supported_bands; k++) { + cap.rf_params.supported_band_list_eutra[k].band_eutra = args.supported_bands[k]; + cap.rf_params.supported_band_list_eutra[k].half_duplex = false; + cap.meas_params.band_list_eutra[k].inter_freq_band_list.resize(1); + cap.meas_params.band_list_eutra[k].inter_freq_band_list[0].inter_freq_need_for_gaps = true; + } - ue_eutra_cap_v940_ies_s cap_v940; - cap_v940.non_crit_ext_present = true; - cap_v940.non_crit_ext = cap_v1020; + cap.feature_group_inds_present = true; + cap.feature_group_inds.from_number(args.feature_group); + + if (args.release > 8) { + ue_eutra_cap_v920_ies_s cap_v920; + + cap_v920.phy_layer_params_v920.enhanced_dual_layer_fdd_r9_present = false; + cap_v920.phy_layer_params_v920.enhanced_dual_layer_tdd_r9_present = false; + cap_v920.inter_rat_params_geran_v920.dtm_r9_present = false; + cap_v920.inter_rat_params_geran_v920.e_redirection_geran_r9_present = false; + cap_v920.csg_proximity_ind_params_r9.inter_freq_proximity_ind_r9_present = false; + cap_v920.csg_proximity_ind_params_r9.intra_freq_proximity_ind_r9_present = false; + cap_v920.csg_proximity_ind_params_r9.utran_proximity_ind_r9_present = false; + cap_v920.neigh_cell_si_acquisition_params_r9.inter_freq_si_acquisition_for_ho_r9_present = false; + cap_v920.neigh_cell_si_acquisition_params_r9.intra_freq_si_acquisition_for_ho_r9_present = false; + cap_v920.neigh_cell_si_acquisition_params_r9.utran_si_acquisition_for_ho_r9_present = false; + cap_v920.son_params_r9.rach_report_r9_present = false; + + cap.non_crit_ext_present = true; + cap.non_crit_ext = cap_v920; + } - cap.non_crit_ext.non_crit_ext_present = true; - cap.non_crit_ext.non_crit_ext = cap_v940; - } + if (args.release > 9) { + + phy_layer_params_v1020_s phy_layer_params_v1020; + phy_layer_params_v1020.two_ant_ports_for_pucch_r10_present = false; + phy_layer_params_v1020.tm9_with_minus8_tx_fdd_r10_present = false; + phy_layer_params_v1020.pmi_disabling_r10_present = false; + phy_layer_params_v1020.cross_carrier_sched_r10_present = args.support_ca; + phy_layer_params_v1020.simul_pucch_pusch_r10_present = false; + phy_layer_params_v1020.multi_cluster_pusch_within_cc_r10_present = false; + phy_layer_params_v1020.non_contiguous_ul_ra_within_cc_list_r10_present = false; + + band_combination_params_r10_l combination_params; + if (args.support_ca) { + for (uint32_t k = 0; k < args.nof_supported_bands; k++) { + ca_mimo_params_dl_r10_s ca_mimo_params_dl; + ca_mimo_params_dl.ca_bw_class_dl_r10 = ca_bw_class_r10_e::f; + ca_mimo_params_dl.supported_mimo_cap_dl_r10_present = false; + + ca_mimo_params_ul_r10_s ca_mimo_params_ul; + ca_mimo_params_ul.ca_bw_class_ul_r10 = ca_bw_class_r10_e::f; + ca_mimo_params_ul.supported_mimo_cap_ul_r10_present = false; + + band_params_r10_s band_params; + band_params.band_eutra_r10 = args.supported_bands[i]; + band_params.band_params_dl_r10_present = true; + band_params.band_params_dl_r10.push_back(ca_mimo_params_dl); + band_params.band_params_ul_r10_present = true; + band_params.band_params_ul_r10.push_back(ca_mimo_params_ul); + + combination_params.push_back(band_params); + } + } - if (args.release > 10) { - ue_eutra_cap_v11a0_ies_s cap_v11a0; - if (args.ue_category >= 11 && args.ue_category <= 12) { - cap_v11a0.ue_category_v11a0 = (uint8_t)args.ue_category; - cap_v11a0.ue_category_v11a0_present = true; - } else { - // Do not populate UE category for this release if the category is out of range - } + rf_params_v1020_s rf_params; + rf_params.supported_band_combination_r10.push_back(combination_params); - ue_eutra_cap_v1180_ies_s cap_v1180; - cap_v1180.non_crit_ext_present = true; - cap_v1180.non_crit_ext = cap_v11a0; + ue_eutra_cap_v1020_ies_s cap_v1020; + if (args.ue_category >= 6 && args.ue_category <= 8) { + cap_v1020.ue_category_v1020_present = true; + cap_v1020.ue_category_v1020 = (uint8_t)args.ue_category; + } else { + // Do not populate UE category for this release if the category is out of range + } + cap_v1020.phy_layer_params_v1020_present = true; + cap_v1020.phy_layer_params_v1020 = phy_layer_params_v1020; + cap_v1020.rf_params_v1020_present = args.support_ca; + cap_v1020.rf_params_v1020 = rf_params; - ue_eutra_cap_v1170_ies_s cap_v1170; - cap_v1170.non_crit_ext_present = true; - cap_v1170.non_crit_ext = cap_v1180; - if (args.ue_category >= 9 && args.ue_category <= 10) { - cap_v1170.ue_category_v1170 = (uint8_t)args.ue_category; - cap_v1170.ue_category_v1170_present = true; - } else { - // Do not populate UE category for this release if the category is out of range - } + ue_eutra_cap_v940_ies_s cap_v940; + cap_v940.non_crit_ext_present = true; + cap_v940.non_crit_ext = cap_v1020; - ue_eutra_cap_v1130_ies_s cap_v1130; - cap_v1130.non_crit_ext_present = true; - cap_v1130.non_crit_ext = cap_v1170; + cap.non_crit_ext.non_crit_ext_present = true; + cap.non_crit_ext.non_crit_ext = cap_v940; + } - ue_eutra_cap_v1090_ies_s cap_v1090; - cap_v1090.non_crit_ext_present = true; - cap_v1090.non_crit_ext = cap_v1130; + if (args.release > 10) { + ue_eutra_cap_v11a0_ies_s cap_v11a0; + if (args.ue_category >= 11 && args.ue_category <= 12) { + cap_v11a0.ue_category_v11a0 = (uint8_t)args.ue_category; + cap_v11a0.ue_category_v11a0_present = true; + } else { + // Do not populate UE category for this release if the category is out of range + } - ue_eutra_cap_v1060_ies_s cap_v1060; - cap_v1060.non_crit_ext_present = true; - cap_v1060.non_crit_ext = cap_v1090; + ue_eutra_cap_v1180_ies_s cap_v1180; + cap_v1180.non_crit_ext_present = true; + cap_v1180.non_crit_ext = cap_v11a0; - cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true; - cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext = cap_v1060; - } + ue_eutra_cap_v1170_ies_s cap_v1170; + cap_v1170.non_crit_ext_present = true; + cap_v1170.non_crit_ext = cap_v1180; + if (args.ue_category >= 9 && args.ue_category <= 10) { + cap_v1170.ue_category_v1170 = (uint8_t)args.ue_category; + cap_v1170.ue_category_v1170_present = true; + } else { + // Do not populate UE category for this release if the category is out of range + } - if (args.release > 11) { - supported_band_list_eutra_v1250_l supported_band_list_eutra_v1250; - for (uint32_t i = 0; i < args.nof_supported_bands; i++) { - supported_band_eutra_v1250_s supported_band_eutra_v1250; - // According to 3GPP 36.306 v12 Table 4.1A-1, 256QAM is supported for ue_category_dl 11-16 - supported_band_eutra_v1250.dl_minus256_qam_r12_present = true; + ue_eutra_cap_v1130_ies_s cap_v1130; + cap_v1130.non_crit_ext_present = true; + cap_v1130.non_crit_ext = cap_v1170; - // According to 3GPP 36.331 v12 UE-EUTRA-Capability field descriptions - // This field is only present when the field ue-CategoryUL is considered to 5 or 13. - supported_band_eutra_v1250.ul_minus64_qam_r12_present = true; + ue_eutra_cap_v1090_ies_s cap_v1090; + cap_v1090.non_crit_ext_present = true; + cap_v1090.non_crit_ext = cap_v1130; - supported_band_list_eutra_v1250.push_back(supported_band_eutra_v1250); - } + ue_eutra_cap_v1060_ies_s cap_v1060; + cap_v1060.non_crit_ext_present = true; + cap_v1060.non_crit_ext = cap_v1090; + + cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext_present = true; + cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext = cap_v1060; + } - rf_params_v1250_s rf_params_v1250; - rf_params_v1250.supported_band_list_eutra_v1250_present = true; - rf_params_v1250.supported_band_list_eutra_v1250 = supported_band_list_eutra_v1250; + if (args.release > 11) { + supported_band_list_eutra_v1250_l supported_band_list_eutra_v1250; + for (uint32_t k = 0; k < args.nof_supported_bands; k++) { + supported_band_eutra_v1250_s supported_band_eutra_v1250; + // According to 3GPP 36.306 v12 Table 4.1A-1, 256QAM is supported for ue_category_dl 11-16 + supported_band_eutra_v1250.dl_minus256_qam_r12_present = (args.ue_category_dl >= 11); - ue_eutra_cap_v1250_ies_s cap_v1250; + // According to 3GPP 36.331 v12 UE-EUTRA-Capability field descriptions + // This field is only present when the field ue-CategoryUL is considered to 5 or 13. + supported_band_eutra_v1250.ul_minus64_qam_r12_present = true; - // Optional UE Category UL/DL - // Warning: Make sure the UE Category UL/DL matches with 3GPP 36.306 Table 4.1A-6 - if (args.ue_category_dl >= 0) { - cap_v1250.ue_category_dl_r12_present = true; - cap_v1250.ue_category_dl_r12 = (uint8_t)args.ue_category_dl; - } else { - // Do not populate UE category for this release if the category is not available - } - if (args.ue_category_ul >= 0) { - cap_v1250.ue_category_ul_r12_present = true; - cap_v1250.ue_category_ul_r12 = (uint8_t)args.ue_category_ul; - } else { - // Do not populate UE category for this release if the category is not available - } - cap_v1250.rf_params_v1250_present = true; - cap_v1250.rf_params_v1250 = rf_params_v1250; + supported_band_list_eutra_v1250.push_back(supported_band_eutra_v1250); + } + + rf_params_v1250_s rf_params_v1250; + rf_params_v1250.supported_band_list_eutra_v1250_present = true; + rf_params_v1250.supported_band_list_eutra_v1250 = supported_band_list_eutra_v1250; + + ue_eutra_cap_v1250_ies_s cap_v1250; - cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext - .non_crit_ext.non_crit_ext_present = true; - cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext - .non_crit_ext.non_crit_ext = cap_v1250; + // Optional UE Category UL/DL + // Warning: Make sure the UE Category UL/DL matches with 3GPP 36.306 Table 4.1A-6 + if (args.ue_category_dl >= 0) { + cap_v1250.ue_category_dl_r12_present = true; + cap_v1250.ue_category_dl_r12 = (uint8_t)args.ue_category_dl; + } else { + // Do not populate UE category for this release if the category is not available + } + if (args.ue_category_ul >= 0) { + cap_v1250.ue_category_ul_r12_present = true; + cap_v1250.ue_category_ul_r12 = (uint8_t)args.ue_category_ul; + } else { + // Do not populate UE category for this release if the category is not available + } + cap_v1250.rf_params_v1250_present = true; + cap_v1250.rf_params_v1250 = rf_params_v1250; + + cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.non_crit_ext_present = true; + cap.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext.non_crit_ext + .non_crit_ext.non_crit_ext = cap_v1250; + } + + // Pack caps and copy to cap info + uint8_t buf[64] = {}; + asn1::bit_ref bref(buf, sizeof(buf)); + cap.pack(bref); + bref.align_bytes_zero(); + auto cap_len = (uint32_t)bref.distance_bytes(buf); + info->ue_cap_rat_container_list[rat_idx].ue_cap_rat_container.resize(cap_len); + memcpy(info->ue_cap_rat_container_list[rat_idx].ue_cap_rat_container.data(), buf, cap_len); + rat_idx++; + } } - // Pack caps and copy to cap info - uint8_t buf[64]; - asn1::bit_ref bref(buf, sizeof(buf)); - cap.pack(bref); - bref.align_bytes_zero(); - uint32_t cap_len = (uint32_t)bref.distance_bytes(buf); - info->ue_cap_rat_container_list[0].ue_cap_rat_container.resize(cap_len); - memcpy(info->ue_cap_rat_container_list[0].ue_cap_rat_container.data(), buf, cap_len); + // resize container back to the actually filled items + info->ue_cap_rat_container_list.resize(rat_idx); send_ul_dcch_msg(RB_ID_SRB1, ul_dcch_msg); } @@ -2641,73 +2283,76 @@ void rrc::send_rrc_ue_cap_info() void rrc::log_rr_config_common() { rrc_log->info("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms\n", - current_mac_cfg.get_rach_cfg().nof_preambles, - current_mac_cfg.get_rach_cfg().responseWindowSize, - current_mac_cfg.get_rach_cfg().contentionResolutionTimer); + current_mac_cfg.rach_cfg.nof_preambles, + current_mac_cfg.rach_cfg.responseWindowSize, + current_mac_cfg.rach_cfg.contentionResolutionTimer); - rrc_log->info("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d, N_sb=%d\n", - current_phy_cfg.common.pusch_cnfg.pusch_cfg_basic.pusch_hop_offset, - current_phy_cfg.common.pusch_cnfg.ul_ref_sigs_pusch.group_assign_pusch, - current_phy_cfg.common.pusch_cnfg.ul_ref_sigs_pusch.cyclic_shift, - current_phy_cfg.common.pusch_cnfg.pusch_cfg_basic.n_sb); + rrc_log->info("Set PUSCH ConfigCommon: P0_pusch=%f, DMRS cs=%d, delta_ss=%d, N_sb=%d\n", + current_phy_cfg.ul_cfg.power_ctrl.p0_ue_pusch, + current_phy_cfg.ul_cfg.dmrs.cyclic_shift, + current_phy_cfg.ul_cfg.dmrs.delta_ss, + current_phy_cfg.ul_cfg.hopping.n_sb); rrc_log->info("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n", - current_phy_cfg.common.pucch_cnfg.delta_pucch_shift.to_number(), - current_phy_cfg.common.pucch_cnfg.n_cs_an, - current_phy_cfg.common.pucch_cnfg.n1_pucch_an, - current_phy_cfg.common.pucch_cnfg.n_rb_cqi); + current_phy_cfg.ul_cfg.pucch.delta_pucch_shift, + current_phy_cfg.ul_cfg.pucch.N_cs, + current_phy_cfg.ul_cfg.pucch.n1_pucch_an_cs[0][0], + current_phy_cfg.ul_cfg.pucch.n_rb_2); rrc_log->info("Set PRACH ConfigCommon: SeqIdx=%d, HS=%s, FreqOffset=%d, ZC=%d, ConfigIndex=%d\n", - current_phy_cfg.common.prach_cnfg.root_seq_idx, - current_phy_cfg.common.prach_cnfg.prach_cfg_info.high_speed_flag ? "yes" : "no", - current_phy_cfg.common.prach_cnfg.prach_cfg_info.prach_freq_offset, - current_phy_cfg.common.prach_cnfg.prach_cfg_info.zero_correlation_zone_cfg, - current_phy_cfg.common.prach_cnfg.prach_cfg_info.prach_cfg_idx); + current_phy_cfg.prach_cfg.root_seq_idx, + current_phy_cfg.prach_cfg.hs_flag ? "yes" : "no", + current_phy_cfg.prach_cfg.freq_offset, + current_phy_cfg.prach_cfg.zero_corr_zone, + current_phy_cfg.prach_cfg.config_idx); - if (current_phy_cfg.common.srs_ul_cnfg.type() == setup_e::setup) { - rrc_log->info("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, ACKNACK=%s\n", - current_phy_cfg.common.srs_ul_cnfg.setup().srs_bw_cfg.to_number(), - current_phy_cfg.common.srs_ul_cnfg.setup().srs_sf_cfg.to_number(), - current_phy_cfg.common.srs_ul_cnfg.setup().ack_nack_srs_simul_tx ? "yes" : "no"); + if (current_phy_cfg.ul_cfg.srs.configured) { + rrc_log->info("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, Simult-ACKNACK=%s\n", + current_phy_cfg.ul_cfg.srs.bw_cfg, + current_phy_cfg.ul_cfg.srs.subframe_config, + current_phy_cfg.ul_cfg.srs.simul_ack ? "yes" : "no"); } } void rrc::apply_rr_config_common(rr_cfg_common_s* config, bool send_lower_layers) { if (config->rach_cfg_common_present) { - current_mac_cfg.set_rach_cfg_common(config->rach_cfg_common); + set_mac_cfg_t_rach_cfg_common(¤t_mac_cfg, config->rach_cfg_common); } - phy_interface_rrc_lte::phy_cfg_common_t* common = ¤t_phy_cfg.common; - if (config->prach_cfg.prach_cfg_info_present) { - common->prach_cnfg.prach_cfg_info = config->prach_cfg.prach_cfg_info; + set_phy_cfg_t_common_prach(¤t_phy_cfg, &config->prach_cfg.prach_cfg_info, config->prach_cfg.root_seq_idx); + } else { + set_phy_cfg_t_common_prach(¤t_phy_cfg, NULL, config->prach_cfg.root_seq_idx); } - common->prach_cnfg.root_seq_idx = config->prach_cfg.root_seq_idx; + if (config->pdsch_cfg_common_present) { - common->pdsch_cnfg = config->pdsch_cfg_common; + set_phy_cfg_t_common_pdsch(¤t_phy_cfg, config->pdsch_cfg_common); } - common->pusch_cnfg = config->pusch_cfg_common; + + set_phy_cfg_t_common_pusch(¤t_phy_cfg, config->pusch_cfg_common); + if (config->phich_cfg_present) { - common->phich_cnfg = config->phich_cfg; + // TODO } if (config->pucch_cfg_common_present) { - common->pucch_cnfg = config->pucch_cfg_common; + set_phy_cfg_t_common_pucch(¤t_phy_cfg, config->pucch_cfg_common); } + if (config->srs_ul_cfg_common_present) { - common->srs_ul_cnfg = config->srs_ul_cfg_common; + set_phy_cfg_t_common_srs(¤t_phy_cfg, config->srs_ul_cfg_common); } + if (config->ul_pwr_ctrl_common_present) { - common->ul_pwr_ctrl = config->ul_pwr_ctrl_common; + set_phy_cfg_t_common_pwr_ctrl(¤t_phy_cfg, config->ul_pwr_ctrl_common); } - // TODO: p_max, antenna_info, tdd... log_rr_config_common(); if (send_lower_layers) { mac->set_config(current_mac_cfg); - phy->set_config(¤t_phy_cfg); + phy->set_config(current_phy_cfg); } } @@ -2716,69 +2361,41 @@ void rrc::log_phy_config_dedicated() if (!rrc_log) { return; } - phys_cfg_ded_s* current_cfg = ¤t_phy_cfg.dedicated; - if (current_cfg->pdsch_cfg_ded_present) { - rrc_log->info("Set PDSCH-Config p_a=%s\n", current_cfg->pdsch_cfg_ded.p_a.to_string().c_str()); + if (current_phy_cfg.dl_cfg.cqi_report.periodic_configured) { + rrc_log->info("Set cqi-PUCCH-ResourceIndex=%d, cqi-pmi-ConfigIndex=%d, cqi-FormatIndicatorPeriodic=%d\n", + current_phy_cfg.ul_cfg.pucch.n_pucch_2, + current_phy_cfg.dl_cfg.cqi_report.pmi_idx, + current_phy_cfg.dl_cfg.cqi_report.periodic_mode); } - - if (current_cfg->cqi_report_cfg_present) { - if (current_cfg->cqi_report_cfg.cqi_report_periodic_present and - current_cfg->cqi_report_cfg.cqi_report_periodic.type() == setup_e::setup) { - rrc_log->info( - "Set cqi-PUCCH-ResourceIndex=%d, cqi-pmi-ConfigIndex=%d, cqi-FormatIndicatorPeriodic=%s\n", - current_cfg->cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx, - current_cfg->cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx, - current_cfg->cqi_report_cfg.cqi_report_periodic.setup().cqi_format_ind_periodic.type().to_string().c_str()); - } - if (current_cfg->cqi_report_cfg.cqi_report_mode_aperiodic_present) { - rrc_log->info("Set cqi-ReportModeAperiodic=%s\n", - current_cfg->cqi_report_cfg.cqi_report_mode_aperiodic.to_string().c_str()); - } + if (current_phy_cfg.dl_cfg.cqi_report.aperiodic_configured) { + rrc_log->info("Set cqi-ReportModeAperiodic=%d\n", current_phy_cfg.dl_cfg.cqi_report.aperiodic_mode); } - if (current_cfg->sched_request_cfg_present and current_cfg->sched_request_cfg.type() == setup_e::setup) { + if (current_phy_cfg.ul_cfg.pucch.sr_configured) { rrc_log->info("Set PHY config ded: SR-n_pucch=%d, SR-ConfigIndex=%d, SR-TransMax=%d\n", - current_cfg->sched_request_cfg.setup().sr_pucch_res_idx, - current_cfg->sched_request_cfg.setup().sr_cfg_idx, - current_cfg->sched_request_cfg.setup().dsr_trans_max.to_number()); - } - - if (current_cfg->srs_ul_cfg_ded_present and current_cfg->srs_ul_cfg_ded.type() == setup_e::setup) { - rrc_log->info("Set PHY config ded: SRS-ConfigIndex=%d, SRS-bw=%s, SRS-Nrcc=%d, SRS-hop=%s, SRS-Ncs=%s\n", - current_cfg->srs_ul_cfg_ded.setup().srs_cfg_idx, - current_cfg->srs_ul_cfg_ded.setup().srs_bw.to_string().c_str(), - current_cfg->srs_ul_cfg_ded.setup().freq_domain_position, - current_cfg->srs_ul_cfg_ded.setup().srs_hop_bw.to_string().c_str(), - current_cfg->srs_ul_cfg_ded.setup().cyclic_shift.to_string().c_str()); - } -} - -// Apply default physical common -void rrc::set_phy_config_common_default() -{ - // Get PUCCH config and reset - pucch_cfg_common_s* pucch_cnfg = ¤t_phy_cfg.common.pucch_cnfg; - *pucch_cnfg = {}; - pucch_cnfg->delta_pucch_shift = pucch_cfg_common_s::delta_pucch_shift_opts::ds1; - - // Get UL power control, reset and set defaults - ul_pwr_ctrl_common_s* ul_pwr_ctrl = ¤t_phy_cfg.common.ul_pwr_ctrl; - *ul_pwr_ctrl = {}; - ul_pwr_ctrl->alpha.value = alpha_r12_opts::al0; - ul_pwr_ctrl->delta_flist_pucch.delta_f_pucch_format1.value = - delta_flist_pucch_s::delta_f_pucch_format1_opts::delta_f0; - ul_pwr_ctrl->delta_flist_pucch.delta_f_pucch_format1b.value = - delta_flist_pucch_s::delta_f_pucch_format1b_opts::delta_f1; - ul_pwr_ctrl->delta_flist_pucch.delta_f_pucch_format2.value = - delta_flist_pucch_s::delta_f_pucch_format2_opts::delta_f0; - ul_pwr_ctrl->delta_flist_pucch.delta_f_pucch_format2a.value = - delta_flist_pucch_s::delta_f_pucch_format2a_opts::delta_f0; - ul_pwr_ctrl->delta_flist_pucch.delta_f_pucch_format2b.value = - delta_flist_pucch_s::delta_f_pucch_format2b_opts::delta_f0; + current_phy_cfg.ul_cfg.pucch.n_pucch_sr, + current_phy_cfg.ul_cfg.pucch.I_sr, + current_mac_cfg.sr_cfg.dsr_transmax); + } + + if (current_phy_cfg.ul_cfg.srs.configured) { + rrc_log->info("Set PHY config ded: SRS-ConfigIndex=%d, SRS-bw=%d, SRS-Nrcc=%d, SRS-hop=%d, SRS-Ncs=%d\n", + current_phy_cfg.ul_cfg.srs.I_srs, + current_phy_cfg.ul_cfg.srs.B, + current_phy_cfg.ul_cfg.srs.n_rrc, + current_phy_cfg.ul_cfg.srs.b_hop, + current_phy_cfg.ul_cfg.srs.n_srs); + } +} + +// Apply default physical common and dedicated configuration +void rrc::set_phy_default() +{ + current_phy_cfg.set_defaults(); if (phy != nullptr) { - phy->set_config(¤t_phy_cfg); + phy->set_config(current_phy_cfg); } else { rrc_log->info("RRC not initialized. Skipping default PHY config.\n"); } @@ -2787,62 +2404,10 @@ void rrc::set_phy_config_common_default() // Apply default physical channel configs (9.2.4) void rrc::set_phy_config_dedicated_default() { - // Get current configuration - phys_cfg_ded_s* current_cfg = ¤t_phy_cfg.dedicated; - - // Reset all present flags - *current_cfg = {}; - - // Set defaults - current_cfg->pdsch_cfg_ded_present = true; - current_cfg->pdsch_cfg_ded.p_a = pdsch_cfg_ded_s::p_a_e_::db0; - - current_cfg->pucch_cfg_ded_present = true; - current_cfg->pucch_cfg_ded.tdd_ack_nack_feedback_mode_present = true; - current_cfg->pucch_cfg_ded.tdd_ack_nack_feedback_mode = pucch_cfg_ded_s::tdd_ack_nack_feedback_mode_e_::bundling; - current_cfg->pucch_cfg_ded.ack_nack_repeat.set(setup_e::release); - - current_cfg->pusch_cfg_ded_present = true; - current_cfg->pusch_cfg_ded.beta_offset_ack_idx = 10; - current_cfg->pusch_cfg_ded.beta_offset_ri_idx = 12; - current_cfg->pusch_cfg_ded.beta_offset_cqi_idx = 15; - - current_cfg->ul_pwr_ctrl_ded_present = true; - current_cfg->ul_pwr_ctrl_ded.p0_ue_pusch = 0; - current_cfg->ul_pwr_ctrl_ded.delta_mcs_enabled = ul_pwr_ctrl_ded_s::delta_mcs_enabled_e_::en0; - current_cfg->ul_pwr_ctrl_ded.accumulation_enabled = true; - current_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0; - current_cfg->ul_pwr_ctrl_ded.p_srs_offset = 7; - - current_cfg->ul_pwr_ctrl_ded.filt_coef_present = true; - current_cfg->ul_pwr_ctrl_ded.filt_coef = filt_coef_e::fc4; - - current_cfg->tpc_pdcch_cfg_pucch_present = true; - current_cfg->tpc_pdcch_cfg_pucch.set(setup_e::release); - - current_cfg->tpc_pdcch_cfg_pusch_present = true; - current_cfg->tpc_pdcch_cfg_pusch.set(setup_e::release); - - current_cfg->cqi_report_cfg_present = true; - current_cfg->cqi_report_cfg.cqi_report_periodic_present = true; - current_cfg->cqi_report_cfg.cqi_report_periodic.set(setup_e::release); - - current_cfg->srs_ul_cfg_ded_present = true; - current_cfg->srs_ul_cfg_ded.set(setup_e::release); - - current_cfg->ant_info_present = true; - current_cfg->ant_info.set_explicit_value(); - current_cfg->ant_info.explicit_value().tx_mode = ant_info_ded_s::tx_mode_e_::tm1; - current_cfg->ant_info.explicit_value().codebook_subset_restrict_present = false; - current_cfg->ant_info.explicit_value().ue_tx_ant_sel.set(setup_e::release); - - current_cfg->sched_request_cfg_present = true; - current_cfg->sched_request_cfg.set(setup_e::release); - - log_phy_config_dedicated(); + current_phy_cfg.set_defaults_dedicated(); if (phy != nullptr) { - phy->set_config(¤t_phy_cfg); + phy->set_config(current_phy_cfg); } else { rrc_log->info("RRC not initialized. Skipping default PHY config.\n"); } @@ -2851,105 +2416,83 @@ void rrc::set_phy_config_dedicated_default() // Apply provided PHY config void rrc::apply_phy_config_dedicated(const phys_cfg_ded_s& phy_cnfg) { - // Get current configuration - phys_cfg_ded_s* current_cfg = ¤t_phy_cfg.dedicated; + set_phy_cfg_t_dedicated_cfg(¤t_phy_cfg, phy_cnfg); - if (phy_cnfg.pucch_cfg_ded_present) { - current_cfg->pucch_cfg_ded_present = true; - current_cfg->pucch_cfg_ded = phy_cnfg.pucch_cfg_ded; - } - - if (phy_cnfg.cqi_report_cfg_pcell_v1250_present) { - current_cfg->cqi_report_cfg_pcell_v1250_present = true; - current_cfg->cqi_report_cfg_pcell_v1250 = phy_cnfg.cqi_report_cfg_pcell_v1250; - } - - if (phy_cnfg.pucch_cfg_ded_v1020_present) { - current_cfg->pucch_cfg_ded_v1020_present = true; - current_cfg->pucch_cfg_ded_v1020 = phy_cnfg.pucch_cfg_ded_v1020; - } + log_phy_config_dedicated(); - if (phy_cnfg.pusch_cfg_ded_present) { - current_cfg->pusch_cfg_ded_present = true; - current_cfg->pusch_cfg_ded = phy_cnfg.pusch_cfg_ded; + if (phy != nullptr) { + phy->set_config(current_phy_cfg); + } else { + rrc_log->info("RRC not initialized. Skipping PHY config.\n"); } +} - if (phy_cnfg.ul_pwr_ctrl_ded_present) { - current_cfg->ul_pwr_ctrl_ded_present = true; - current_cfg->ul_pwr_ctrl_ded = phy_cnfg.ul_pwr_ctrl_ded; - } +void rrc::apply_phy_scell_config(const asn1::rrc::scell_to_add_mod_r10_s& scell_config) +{ + srslte_cell_t scell = {}; + uint32_t earfcn = 0; - if (phy_cnfg.ul_pwr_ctrl_ded.filt_coef_present) { - current_cfg->ul_pwr_ctrl_ded.filt_coef_present = true; - current_cfg->ul_pwr_ctrl_ded.filt_coef = phy_cnfg.ul_pwr_ctrl_ded.filt_coef; + if (phy == nullptr) { + rrc_log->info("RRC not initialized. Skipping PHY config.\n"); + return; } - if (phy_cnfg.tpc_pdcch_cfg_pucch_present) { - current_cfg->tpc_pdcch_cfg_pucch_present = true; - current_cfg->tpc_pdcch_cfg_pucch = phy_cnfg.tpc_pdcch_cfg_pucch; - } + // Initialise default parameters from primary cell + phy->get_current_cell(&scell, &earfcn); - if (phy_cnfg.tpc_pdcch_cfg_pusch_present) { - current_cfg->tpc_pdcch_cfg_pusch_present = true; - current_cfg->tpc_pdcch_cfg_pusch = phy_cnfg.tpc_pdcch_cfg_pusch; + // Parse identification + if (scell_config.cell_identif_r10_present) { + scell.id = scell_config.cell_identif_r10.pci_r10; + earfcn = scell_config.cell_identif_r10.dl_carrier_freq_r10; } - if (phy_cnfg.cqi_report_cfg_present) { - current_cfg->cqi_report_cfg_present = true; - - if (phy_cnfg.cqi_report_cfg.cqi_report_periodic_present) { + // Parse radio resource + if (scell_config.rr_cfg_common_scell_r10_present) { + const rr_cfg_common_scell_r10_s* rr_cfg = &scell_config.rr_cfg_common_scell_r10; + auto non_ul_cfg = &rr_cfg->non_ul_cfg_r10; + scell.frame_type = (rr_cfg->tdd_cfg_v1130.is_present()) ? SRSLTE_TDD : SRSLTE_FDD; + scell.nof_prb = non_ul_cfg->dl_bw_r10.to_number(); + scell.nof_ports = non_ul_cfg->ant_info_common_r10.ant_ports_count.to_number(); + scell.phich_length = (non_ul_cfg->phich_cfg_r10.phich_dur.value == phich_cfg_s::phich_dur_opts::normal) + ? SRSLTE_PHICH_NORM + : SRSLTE_PHICH_EXT; - current_cfg->cqi_report_cfg.cqi_report_periodic_present = true; - current_cfg->cqi_report_cfg.cqi_report_periodic = phy_cnfg.cqi_report_cfg.cqi_report_periodic; - } - - if (phy_cnfg.cqi_report_cfg.cqi_report_mode_aperiodic_present) { - current_cfg->cqi_report_cfg.cqi_report_mode_aperiodic_present = true; - current_cfg->cqi_report_cfg.cqi_report_mode_aperiodic = phy_cnfg.cqi_report_cfg.cqi_report_mode_aperiodic; + // Avoid direct conversion between different phich resource enum + switch (non_ul_cfg->phich_cfg_r10.phich_res.value) { + case phich_cfg_s::phich_res_opts::one_sixth: + scell.phich_resources = SRSLTE_PHICH_R_1_6; + break; + case phich_cfg_s::phich_res_opts::half: + scell.phich_resources = SRSLTE_PHICH_R_1_2; + break; + case phich_cfg_s::phich_res_opts::one: + scell.phich_resources = SRSLTE_PHICH_R_1; + break; + case phich_cfg_s::phich_res_opts::two: + case phich_cfg_s::phich_res_opts::nulltype: + scell.phich_resources = SRSLTE_PHICH_R_2; + break; } - current_cfg->cqi_report_cfg.nom_pdsch_rs_epre_offset = phy_cnfg.cqi_report_cfg.nom_pdsch_rs_epre_offset; - } - - if (phy_cnfg.srs_ul_cfg_ded_present) { - current_cfg->srs_ul_cfg_ded_present = true; - current_cfg->srs_ul_cfg_ded = phy_cnfg.srs_ul_cfg_ded; } - if (phy_cnfg.ant_info_present) { - current_cfg->ant_info_present = true; - current_cfg->ant_info = phy_cnfg.ant_info; - } - - if (phy_cnfg.sched_request_cfg_present) { - current_cfg->sched_request_cfg_present = true; - current_cfg->sched_request_cfg = phy_cnfg.sched_request_cfg; - } - - if (phy_cnfg.pdsch_cfg_ded_present) { - current_cfg->pdsch_cfg_ded_present = true; - current_cfg->pdsch_cfg_ded = phy_cnfg.pdsch_cfg_ded; - } - - log_phy_config_dedicated(); + // Initialize scell config with pcell cfg + srslte::phy_cfg_t scell_phy_cfg = current_phy_cfg; + set_phy_cfg_t_scell_config(&scell_phy_cfg, scell_config); - if (phy != nullptr) { - phy->set_config(¤t_phy_cfg); - } else { - rrc_log->info("RRC not initialized. Skipping PHY config.\n"); - } + phy->set_config(scell_phy_cfg, scell_config.s_cell_idx_r10, earfcn, &scell); } void rrc::log_mac_config_dedicated() { rrc_log->info("Set MAC main config: harq-MaxReTX=%d, bsr-TimerReTX=%d, bsr-TimerPeriodic=%d\n", - current_mac_cfg.get_harq_cfg().max_harq_msg3_tx, - current_mac_cfg.get_bsr_cfg().retx_timer, - current_mac_cfg.get_bsr_cfg().periodic_timer); - if (current_mac_cfg.get_phr_cfg().enabled) { + current_mac_cfg.harq_cfg.max_harq_msg3_tx, + current_mac_cfg.bsr_cfg.retx_timer, + current_mac_cfg.bsr_cfg.periodic_timer); + if (current_mac_cfg.phr_cfg.enabled) { rrc_log->info("Set MAC PHR config: periodicPHR-Timer=%d, prohibitPHR-Timer=%d, dl-PathlossChange=%d\n", - current_mac_cfg.get_phr_cfg().periodic_timer, - current_mac_cfg.get_phr_cfg().prohibit_timer, - current_mac_cfg.get_phr_cfg().db_pathloss_change); + current_mac_cfg.phr_cfg.periodic_timer, + current_mac_cfg.phr_cfg.prohibit_timer, + current_mac_cfg.phr_cfg.db_pathloss_change); } } @@ -2962,48 +2505,46 @@ void rrc::apply_mac_config_dedicated_default() log_mac_config_dedicated(); } -void rrc::apply_mac_config_dedicated_explicit(mac_main_cfg_s mac_cnfg) -{ - current_mac_cfg.set_mac_main_cfg(mac_cnfg); - mac->set_config(current_mac_cfg); - log_mac_config_dedicated(); -} - bool rrc::apply_rr_config_dedicated(rr_cfg_ded_s* cnfg) { if (cnfg->phys_cfg_ded_present) { apply_phy_config_dedicated(cnfg->phys_cfg_ded); // Apply SR configuration to MAC if (cnfg->phys_cfg_ded.sched_request_cfg_present) { - current_mac_cfg.set_sched_request_cfg(cnfg->phys_cfg_ded.sched_request_cfg); + set_mac_cfg_t_sched_request_cfg(¤t_mac_cfg, cnfg->phys_cfg_ded.sched_request_cfg); } } if (cnfg->mac_main_cfg_present) { if (cnfg->mac_main_cfg.type() == rr_cfg_ded_s::mac_main_cfg_c_::types::default_value) { - apply_mac_config_dedicated_default(); + current_mac_cfg.set_mac_main_cfg_default(); } else { - apply_mac_config_dedicated_explicit(cnfg->mac_main_cfg.explicit_value()); + set_mac_cfg_t_main_cfg(¤t_mac_cfg, cnfg->mac_main_cfg.explicit_value()); } + mac->set_config(current_mac_cfg); } else if (cnfg->phys_cfg_ded.sched_request_cfg_present) { - // If MAC-main not set but SR config is set, use directly mac->set_config to update confi + // If MAC-main not set but SR config is set, use directly mac->set_config to update config mac->set_config(current_mac_cfg); log_mac_config_dedicated(); } if (cnfg->sps_cfg_present) { - //TODO + // TODO } - if (cnfg->rlf_timers_and_consts_r9_present and cnfg->rlf_timers_and_consts_r9->type() == setup_e::setup) { - mac_timers->timer_get(t301)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t301_r9.to_number()); - mac_timers->timer_get(t310)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t310_r9.to_number()); - mac_timers->timer_get(t311)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t311_r9.to_number()); + if (cnfg->rlf_timers_and_consts_r9.is_present() and cnfg->rlf_timers_and_consts_r9->type() == setup_e::setup) { + timers->get(t301)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t301_r9.to_number()); + timers->get(t310)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t310_r9.to_number()); + timers->get(t311)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t311_r9.to_number()); N310 = cnfg->rlf_timers_and_consts_r9->setup().n310_r9.to_number(); N311 = cnfg->rlf_timers_and_consts_r9->setup().n311_r9.to_number(); rrc_log->info("Updated Constants and Timers: N310=%d, N311=%d, t300=%u, t301=%u, t310=%u, t311=%u\n", - N310, N311, mac_timers->timer_get(t300)->get_timeout(), mac_timers->timer_get(t301)->get_timeout(), - mac_timers->timer_get(t310)->get_timeout(), mac_timers->timer_get(t311)->get_timeout()); + N310, + N311, + timers->get(t300)->get_timeout(), + timers->get(t301)->get_timeout(), + timers->get(t310)->get_timeout(), + timers->get(t311)->get_timeout()); } for (uint32_t i = 0; i < cnfg->srb_to_add_mod_list.size(); i++) { // TODO: handle SRB modification @@ -3060,7 +2601,7 @@ void rrc::apply_scell_config(asn1::rrc::rrc_conn_recfg_r8_ies_s* reconfig_r8) mac->reconfiguration(scell_config->s_cell_idx_r10, true); // Call phy reconfiguration - phy->set_config_scell(scell_config); + apply_phy_scell_config(*scell_config); } } @@ -3081,6 +2622,12 @@ void rrc::apply_scell_config(asn1::rrc::rrc_conn_recfg_r8_ies_s* reconfig_r8) void rrc::handle_con_setup(rrc_conn_setup_s* setup) { + // Must enter CONNECT before stopping T300 + state = RRC_STATE_CONNECTED; + timers->get(t300)->stop(); + timers->get(t302)->stop(); + rrc_log->console("RRC Connected\n"); + // Apply the Radio Resource configuration apply_rr_config_dedicated(&setup->crit_exts.c1().rrc_conn_setup_r8().rr_cfg_ded); @@ -3097,7 +2644,7 @@ void rrc::handle_con_setup(rrc_conn_setup_s* setup) void rrc::handle_con_reest(rrc_conn_reest_s* setup) { - mac_timers->timer_get(t301)->stop(); + timers->get(t301)->stop(); // Reestablish PDCP and RLC for SRB1 pdcp->reestablish(1); @@ -3131,11 +2678,11 @@ void rrc::handle_con_reest(rrc_conn_reest_s* setup) void rrc::add_srb(srb_to_add_mod_s* srb_cnfg) { // Setup PDCP - srslte_pdcp_config_t pdcp_cfg; - pdcp_cfg.is_control = true; - pdcp_cfg.is_data = false; - pdcp_cfg.sn_len = 5; - pdcp_cfg.bearer_id = srb_cnfg->srb_id; + pdcp_config_t pdcp_cfg = {.bearer_id = srb_cnfg->srb_id, + .rb_type = PDCP_RB_IS_SRB, + .tx_direction = SECURITY_DIRECTION_UPLINK, + .rx_direction = SECURITY_DIRECTION_DOWNLINK, + .sn_len = PDCP_SN_LEN_5}; pdcp->add_bearer(srb_cnfg->srb_id, pdcp_cfg); if (RB_ID_SRB2 == srb_cnfg->srb_id) { pdcp->config_security(srb_cnfg->srb_id, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); @@ -3208,9 +2755,11 @@ void rrc::add_drb(drb_to_add_mod_s* drb_cnfg) } // Setup PDCP - srslte_pdcp_config_t pdcp_cfg = {}; - pdcp_cfg.is_data = true; - pdcp_cfg.bearer_id = drb_cnfg->drb_id; + pdcp_config_t pdcp_cfg = {.bearer_id = drb_cnfg->drb_id, + .rb_type = PDCP_RB_IS_DRB, + .tx_direction = SECURITY_DIRECTION_UPLINK, + .rx_direction = SECURITY_DIRECTION_DOWNLINK, + .sn_len = PDCP_SN_LEN_12}; if (drb_cnfg->pdcp_cfg.rlc_um_present) { if (drb_cnfg->pdcp_cfg.rlc_um.pdcp_sn_size == pdcp_cfg_s::rlc_um_s_::pdcp_sn_size_e_::len7bits) { pdcp_cfg.sn_len = 7; @@ -3279,51 +2828,22 @@ void rrc::add_mrb(uint32_t lcid, uint32_t port) // PHY CONFIG DEDICATED Defaults (3GPP 36.331 v10 9.2.4) void rrc::set_phy_default_pucch_srs() { - // FIXME: Check 5.3.13 again, there are some fields that are not reset - // Set defaults to CQI, SRS and SR - current_phy_cfg.dedicated.cqi_report_cfg_present = false; - current_phy_cfg.dedicated.srs_ul_cfg_ded_present = false; - current_phy_cfg.dedicated.sched_request_cfg_present = false; - rrc_log->info("Setting default PHY config dedicated\n"); set_phy_config_dedicated_default(); } -void rrc::set_phy_default() -{ - set_phy_config_common_default(); - set_phy_config_dedicated_default(); -} - void rrc::set_mac_default() { apply_mac_config_dedicated_default(); } -void rrc::set_rrc_default() { +void rrc::set_rrc_default() +{ N310 = 1; N311 = 1; - mac_timers->timer_get(t310)->set(this, 1000); - mac_timers->timer_get(t311)->set(this, 1000); + timers->get(t310)->set(this, 1000); + timers->get(t311)->set(this, 1000); } - - - - - - - - - - - - - - - - - - /************************************************************************ * * @@ -3332,11 +2852,12 @@ void rrc::set_rrc_default() { * ************************************************************************/ -void rrc::rrc_meas::init(rrc *parent) { - this->parent = parent; - this->log_h = parent->rrc_log; - this->phy = parent->phy; - this->mac_timers = parent->mac_timers; +void rrc::rrc_meas::init(rrc* parent_) +{ + this->parent = parent_; + this->log_h = parent_->rrc_log; + this->phy = parent_->phy; + this->timers = parent_->timers; s_measure_enabled = false; reset(); } @@ -3499,11 +3020,11 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id) report->meas_result_neigh_cells_present = neigh_list.size() > 0; m->nof_reports_sent++; - mac_timers->timer_get(m->periodic_timer)->stop(); + timers->get(m->periodic_timer)->stop(); if (m->nof_reports_sent < cfg->amount) { - mac_timers->timer_get(m->periodic_timer)->reset(); - mac_timers->timer_get(m->periodic_timer)->run(); + timers->get(m->periodic_timer)->reset(); + timers->get(m->periodic_timer)->run(); } else { if (cfg->trigger_type == report_cfg_t::PERIODIC) { m->triggered = false; @@ -3534,9 +3055,9 @@ bool rrc::rrc_meas::process_event(eutra_event_s* event, uint32_t tti, bool enter cell->timer_exit_triggered = true; cell->exit_tti = tti; } else if (srslte_tti_interval(tti, cell->exit_tti) >= event->time_to_trigger) { - m->triggered = false; - cell->triggered = false; - mac_timers->timer_get(m->periodic_timer)->stop(); + m->triggered = false; + cell->triggered = false; + timers->get(m->periodic_timer)->stop(); if (event) { if (event->event_id.type() == eutra_event_s::event_id_c_::types::event_a3 && event->event_id.event_a3().report_on_leave) { @@ -3712,8 +3233,9 @@ bool rrc::rrc_meas::timer_expired(uint32_t timer_id) { return false; } -void rrc::rrc_meas::stop_reports(meas_t *m) { - mac_timers->timer_get(m->periodic_timer)->stop(); +void rrc::rrc_meas::stop_reports(meas_t* m) +{ + timers->get(m->periodic_timer)->stop(); m->triggered = false; } @@ -3747,10 +3269,11 @@ void rrc::rrc_meas::remove_meas_report(uint32_t report_id) { } } -void rrc::rrc_meas::remove_meas_id(uint32_t measId) { +void rrc::rrc_meas::remove_meas_id(uint32_t measId) +{ if (active.count(measId)) { - mac_timers->timer_get(active[measId].periodic_timer)->stop(); - mac_timers->timer_release_id(active[measId].periodic_timer); + timers->get(active[measId].periodic_timer)->stop(); + timers->release_id(active[measId].periodic_timer); log_h->info("MEAS: Removed measId=%d\n", measId); active.erase(measId); } else { @@ -3758,9 +3281,10 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId) { } } -void rrc::rrc_meas::remove_meas_id(std::map::iterator it) { - mac_timers->timer_get(it->second.periodic_timer)->stop(); - mac_timers->timer_release_id(it->second.periodic_timer); +void rrc::rrc_meas::remove_meas_id(std::map::iterator it) +{ + timers->get(it->second.periodic_timer)->stop(); + timers->release_id(it->second.periodic_timer); log_h->info("MEAS: Removed measId=%d\n", it->first); active.erase(it); } @@ -3909,10 +3433,10 @@ bool rrc::rrc_meas::parse_meas_config(meas_cfg_s* cfg) // Stop the timer if the entry exists or create the timer if not bool is_new = false; if (active.count(meas_id->meas_id)) { - mac_timers->timer_get(active[meas_id->meas_id].periodic_timer)->stop(); + timers->get(active[meas_id->meas_id].periodic_timer)->stop(); } else { is_new = true; - active[meas_id->meas_id].periodic_timer = mac_timers->timer_get_unique_id(); + active[meas_id->meas_id].periodic_timer = timers->get_unique_id(); } active[meas_id->meas_id].object_id = meas_id->meas_obj_id; active[meas_id->meas_id].report_id = meas_id->report_cfg_id; diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc new file mode 100644 index 000000000..22259df47 --- /dev/null +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -0,0 +1,829 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srsue/hdr/stack/rrc/rrc_procedures.h" +#include // for printing uint64_t + +#define Error(fmt, ...) rrc_ptr->rrc_log->error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define Warning(fmt, ...) rrc_ptr->rrc_log->warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define Info(fmt, ...) rrc_ptr->rrc_log->info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define Debug(fmt, ...) rrc_ptr->rrc_log->debug("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) + +namespace srsue { + +using srslte::proc_outcome_t; + +/************************************** + * Cell Search Procedure + *************************************/ + +/* Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet */ +proc_outcome_t rrc::cell_search_proc::init(srsue::rrc* parent_) +{ + rrc_ptr = parent_; + log_h = parent_->rrc_log; + + Info("Starting...\n"); + state = state_t::phy_cell_search; + rrc_ptr->stack->start_cell_search(); + return proc_outcome_t::repeat; +} + +/* Implements the SI acquisition procedure. Configures MAC/PHY scheduling to retrieve SI messages.*/ +proc_outcome_t rrc::cell_search_proc::step() +{ + if (state == state_t::phy_cell_search) { + // Waits for cell search to complete + return proc_outcome_t::yield; + } else if (state == state_t::si_acquire) { + if (not rrc_ptr->si_acquirer.run()) { + // SI Acquire has completed + si_acquire_proc ret = rrc_ptr->si_acquirer.pop(); + if (ret.is_error()) { + Error("Failed to trigger SI acquire for SIB0\n"); + return proc_outcome_t::error; + } else { + // if(parent->serving_cell->has_sib(0)) { + // } + return proc_outcome_t::success; + } + } + } + return proc_outcome_t::yield; +} + +proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_interface_rrc_lte::phy_cell_t& new_cell) +{ + Info("Cell found in this frequency. Setting new serving cell...\n"); + + // Create a cell with NaN RSRP. Will be updated by new_phy_meas() during SIB search. + if (not rrc_ptr->add_neighbour_cell(new_cell, NAN)) { + Info("No more space for neighbour cells\n"); + return proc_outcome_t::success; + } + + rrc_ptr->set_serving_cell(new_cell); + + if (not rrc_ptr->phy->cell_is_camping()) { + log_h->warning("Could not camp on found cell.\n"); + return proc_outcome_t::error; + } + + if (rrc_ptr->serving_cell->has_sib1()) { + Info("Cell has SIB1\n"); + // What do we do???? + return proc_outcome_t::success; + } + + if (not rrc_ptr->si_acquirer.launch(rrc_ptr, 0)) { + // disallow concurrent si_acquire + Error("SI Acquire is already running...\n"); + return proc_outcome_t::error; + } + + // instruct MAC to look for SIB1 + Info("Cell has no SIB1. Obtaining SIB1...\n"); + state = state_t::si_acquire; + return proc_outcome_t::repeat; +} + +proc_outcome_t rrc::cell_search_proc::trigger_event(const cell_search_event_t& event) +{ + if (state != state_t::phy_cell_search) { + Error("Received unexpected cell search result\n"); + return proc_outcome_t::error; + } + search_result = event; + + Info("PHY cell search completed.\n"); + // Transition to SI Acquire or finish + switch (search_result.cs_ret.found) { + case phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND: { + return handle_cell_found(search_result.found_cell); + } + case phy_interface_rrc_lte::cell_search_ret_t::CELL_NOT_FOUND: + Info("No cells found.\n"); + // do nothing + return proc_outcome_t::success; + case phy_interface_rrc_lte::cell_search_ret_t::ERROR: + Error("Error while performing cell search\n"); + // TODO: check what errors can happen (currently not handled in our code) + return proc_outcome_t::error; + } + return proc_outcome_t::yield; +} + +/************************************** + * SI Acquire Procedure + *************************************/ + +proc_outcome_t rrc::si_acquire_proc::init(rrc* parent_, uint32_t sib_index_) +{ + rrc_ptr = parent_; + log_h = parent_->rrc_log; + + Info("Starting SI Acquire procedure for SIB%d\n", sib_index_ + 1); + sib_index = sib_index_; + start_tti = rrc_ptr->mac->get_current_tti(); + + // set period/sched_index + if (sib_index == 0) { + period = 20; + sched_index = 0; + } else { + // Instruct MAC to look for SIB2..13 + if (not rrc_ptr->serving_cell->has_sib1()) { + Error("Trying to acquire SIB%d but SIB1 not received yet\n", sib_index + 1); + return proc_outcome_t::error; + } + asn1::rrc::sib_type1_s* sib1 = rrc_ptr->serving_cell->sib1ptr(); + + if (sib_index == 1) { + // SIB2 scheduling + period = sib1->sched_info_list[0].si_periodicity.to_number(); + sched_index = 0; + } else { + // SIB3+ scheduling Section 5.2.3 + bool found = false; + for (uint32_t i = 0; i < sib1->sched_info_list.size() && not found; ++i) { + for (uint32_t j = 0; j < sib1->sched_info_list[i].sib_map_info.size() && not found; ++j) { + if (sib1->sched_info_list[i].sib_map_info[j].to_number() == sib_index + 1) { + period = sib1->sched_info_list[i].si_periodicity.to_number(); + sched_index = i; + found = true; + } + } + } + if (not found) { + Info("Could not find SIB%d scheduling in SIB1\n", sib_index + 1); + return proc_outcome_t::success; + } + } + } + + return proc_outcome_t::repeat; +} + +proc_outcome_t rrc::si_acquire_proc::step() +{ + uint32_t tti = rrc_ptr->mac->get_current_tti(); + uint32_t tti_diff1 = srslte_tti_interval(tti, start_tti); + bool has_timeout = tti_diff1 >= SIB_SEARCH_TIMEOUT_MS and tti_diff1 < 10240 / 2; + if (has_timeout or rrc_ptr->serving_cell->has_sib(sib_index)) { + if (rrc_ptr->serving_cell->has_sib(sib_index)) { + Info("SIB%d acquired successfully\n", sib_index + 1); + return proc_outcome_t::success; + } else { + Error("Timeout while acquiring SIB1\n"); + return proc_outcome_t::error; + } + } else { + + uint32_t tti_diff2 = srslte_tti_interval(tti, last_win_start); + + // If first time or inside retry window, trigger MAC to decode SIB + uint32_t retry_period = (sib_index == 0) ? 20 : period * 5; + if (last_win_start == 0 or (tti_diff2 > retry_period and tti_diff2 < 1000)) { + + // compute win start and len + uint32_t si_win_start, si_win_len; + if (sib_index == 0) { + si_win_len = 1; + si_win_start = sib_start_tti(tti, 2, 0, 5); + } else { + asn1::rrc::sib_type1_s* sib1 = rrc_ptr->serving_cell->sib1ptr(); + + si_win_len = sib1->si_win_len.to_number(); + uint32_t x = sched_index * si_win_len; + uint32_t sf = x % 10, offset = x / 10; + si_win_start = sib_start_tti(tti, period, offset, sf); + } + last_win_start = si_win_start; + + // Instruct MAC to decode SIB + rrc_ptr->mac->bcch_start_rx(si_win_start, si_win_len); + Info("Instructed MAC to search for SIB%d, win_start=%d, win_len=%d, period=%d, sched_index=%d\n", + sib_index + 1, + si_win_start, + si_win_len, + period, + sched_index); + } + } + + return proc_outcome_t::yield; +} + +// Determine SI messages scheduling as in 36.331 5.2.3 Acquisition of an SI message +uint32_t rrc::si_acquire_proc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf) +{ + return (period * 10 * (1 + tti / (period * 10)) + (offset * 10) + sf) % 10240; // the 1 means next opportunity +} + +/************************************** + * Serving Cell Config Procedure + *************************************/ + +/* + * Retrieves all required SIB or configures them if already retrieved before + */ +proc_outcome_t rrc::serving_cell_config_proc::init(srsue::rrc* parent_, const std::vector& required_sibs_) +{ + rrc_ptr = parent_; + log_h = parent_->rrc_log; + required_sibs = required_sibs_; + + Info("Starting a Serving Cell Configuration Procedure\n"); + + if (not rrc_ptr->phy->cell_is_camping()) { + Error("Trying to configure Cell while not camping on it\n"); + return proc_outcome_t::error; + } + + rrc_ptr->serving_cell->has_mcch = false; + + req_idx = 0; + search_state = search_state_t::next_sib; + return proc_outcome_t::repeat; +} + +proc_outcome_t rrc::serving_cell_config_proc::step() +{ + if (search_state == search_state_t::next_sib) { + // Obtain the SIBs if not available or apply the configuration if available + for (; req_idx < required_sibs.size(); req_idx++) { + uint32_t required_sib = required_sibs[req_idx]; + + if (not rrc_ptr->serving_cell->has_sib(required_sib)) { + Info("Cell has no SIB%d. Obtaining SIB%d\n", required_sib + 1, required_sib + 1); + if (not rrc_ptr->si_acquirer.launch(rrc_ptr, required_sib)) { + Error("SI Acquire is already running...\n"); + return proc_outcome_t::error; + } + search_state = search_state_t::si_acquire; + return proc_outcome_t::repeat; + } else { + // UE had SIB already. Handle its SIB + Info("Cell has SIB%d\n", required_sib + 1); + switch (required_sib) { + case 1: + rrc_ptr->handle_sib2(); + break; + case 12: + rrc_ptr->handle_sib13(); + break; + default: + break; + } + } + } + if (req_idx == required_sibs.size()) { + Info("Serving Cell Configuration Procedure has finished successfully\n"); + return proc_outcome_t::success; + } + } else if (search_state == search_state_t::si_acquire) { + uint32_t required_sib = required_sibs[req_idx]; + if (not rrc_ptr->si_acquirer.run()) { + si_acquire_proc ret = rrc_ptr->si_acquirer.pop(); + if (ret.is_error() or not rrc_ptr->serving_cell->has_sib(required_sib)) { + if (required_sib < 2) { + log_h->warning("Serving Cell Configuration has failed\n"); + return proc_outcome_t::error; + } + } + // continue with remaining SIBs + search_state = search_state_t::next_sib; + req_idx++; + return proc_outcome_t::repeat; + } + } + return proc_outcome_t::yield; +} + +/************************************** + * Cell Selection Procedure + *************************************/ + +/* + * Cell selection procedure 36.304 5.2.3 + * Select the best cell to camp on among the list of known cells + */ +proc_outcome_t rrc::cell_selection_proc::init(srsue::rrc* parent_) +{ + rrc_ptr = parent_; + log_h = parent_->rrc_log; + + if (rrc_ptr->neighbour_cells.empty() and rrc_ptr->serving_cell->in_sync and rrc_ptr->phy->cell_is_camping()) { + // don't bother with cell selection if there are no neighbours and we are already camping + Debug("Skipping Cell Selection Procedure ..\n"); + return proc_outcome_t::success; + } + + Info("Starting a Cell Selection Procedure...\n"); + neigh_index = 0; + cs_result = cs_result_t::no_cell; + state = search_state_t::cell_selection; + return proc_outcome_t::repeat; +} + +proc_outcome_t rrc::cell_selection_proc::step_cell_selection() +{ + // Neighbour cells are sorted in descending order of RSRP + for (; neigh_index < rrc_ptr->neighbour_cells.size(); ++neigh_index) { + /*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells + * neighbour_cells[i]->plmn_equals(selected_plmn_id) && */ + if (rrc_ptr->neighbour_cells.at(neigh_index)->in_sync) { + // Matches S criteria + float rsrp = rrc_ptr->neighbour_cells.at(neigh_index)->get_rsrp(); + + if (not rrc_ptr->serving_cell->in_sync or + (rrc_ptr->cell_selection_criteria(rsrp) and rsrp > rrc_ptr->serving_cell->get_rsrp() + 5)) { + // currently connected and verifies cell selection criteria + // Try to select Cell + rrc_ptr->set_serving_cell(rrc_ptr->neighbour_cells.at(neigh_index)->phy_cell); + Info( + "Selected cell PCI=%d, EARFCN=%d\n", rrc_ptr->serving_cell->get_pci(), rrc_ptr->serving_cell->get_earfcn()); + log_h->console( + "Selected cell PCI=%d, EARFCN=%d\n", rrc_ptr->serving_cell->get_pci(), rrc_ptr->serving_cell->get_earfcn()); + + /* BLOCKING CALL */ + if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { + if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr, rrc_ptr->ue_required_sibs)) { + return proc_outcome_t::error; + } + state = search_state_t::cell_config; + return proc_outcome_t::repeat; + } else { + rrc_ptr->serving_cell->in_sync = false; + Error("Could not camp on serving cell.\n"); + // Continue to next neighbour cell + } + } + } + } + if (rrc_ptr->serving_cell->in_sync) { + if (not rrc_ptr->phy->cell_is_camping()) { + Info("Serving cell is in-sync but not camping. Selecting it...\n"); + + /* BLOCKING CALL */ + if (rrc_ptr->phy->cell_select(&rrc_ptr->serving_cell->phy_cell)) { + Info("Selected serving cell OK.\n"); + } else { + rrc_ptr->serving_cell->in_sync = false; + Error("Could not camp on serving cell.\n"); + } + } + cs_result = cs_result_t::same_cell; + return proc_outcome_t::success; + } + + // If can not find any suitable cell, search again + Info("Cell selection and reselection in IDLE did not find any suitable cell. Searching again\n"); + if (not rrc_ptr->cell_searcher.launch(rrc_ptr)) { + return proc_outcome_t::error; + } + state = search_state_t::cell_search; + return proc_outcome_t::repeat; +} + +proc_outcome_t rrc::cell_selection_proc::step_cell_search() +{ + + if (rrc_ptr->cell_searcher.run()) { + return proc_outcome_t::yield; + } + cell_search_proc ret = rrc_ptr->cell_searcher.pop(); + if (ret.is_error()) { + cs_result = cs_result_t::no_cell; + return proc_outcome_t::error; + } else { + cs_result = (ret.get_cs_ret().found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) + ? cs_result_t::changed_cell + : cs_result_t::no_cell; + Info("Cell Search of cell selection run successfully\n"); + return proc_outcome_t::success; + } +} + +proc_outcome_t rrc::cell_selection_proc::step_cell_config() +{ + if (rrc_ptr->serv_cell_cfg.run()) { + return proc_outcome_t::yield; + } + serving_cell_config_proc ret = rrc_ptr->serv_cell_cfg.pop(); + if (ret.is_success()) { + Info("All SIBs of serving cell obtained successfully\n"); + cs_result = cs_result_t::changed_cell; + return proc_outcome_t::success; + } else { + Error("While configuring serving cell\n"); + // resume cell selection + state = search_state_t::cell_selection; + ++neigh_index; + return proc_outcome_t::repeat; + } +} + +proc_outcome_t rrc::cell_selection_proc::step() +{ + switch (state) { + case search_state_t::cell_selection: + return step_cell_selection(); + case search_state_t::cell_config: + return step_cell_config(); + case search_state_t::cell_search: + return step_cell_search(); + } + return proc_outcome_t::error; +} + +void rrc::cell_selection_proc::stop() +{ + // Inform Connection Request Procedure + Info("Completed with %s. Informing proc %s\n", + is_success() ? "success" : "failure", + rrc_ptr->conn_req_proc.get()->name()); + rrc_ptr->conn_req_proc.trigger_event(connection_request_proc::cell_selection_complete{is_success(), cs_result}); +} + +/************************************** + * PLMN search Procedure + *************************************/ + +proc_outcome_t rrc::plmn_search_proc::init(srsue::rrc* parent_) +{ + rrc_ptr = parent_; + log_h = parent_->rrc_log; + + Info("Starting PLMN search\n"); + nof_plmns = 0; + if (not rrc_ptr->cell_searcher.launch(rrc_ptr)) { + Error("Failed due to fail to init cell search...\n"); + return proc_outcome_t::error; + } + return proc_outcome_t::repeat; +} + +/* NAS interface to search for available PLMNs. + * It goes through all known frequencies, synchronizes and receives SIB1 for each to extract PLMN. + * The function is blocking and waits until all frequencies have been + * searched and PLMNs are obtained. + */ +proc_outcome_t rrc::plmn_search_proc::step() +{ + if (rrc_ptr->cell_searcher.run()) { + // wait for new TTI + return proc_outcome_t::yield; + } + cell_search_proc ret = rrc_ptr->cell_searcher.pop(); + phy_interface_rrc_lte::cell_search_ret_t cs_ret = ret.get_cs_ret(); + if (ret.is_error() or cs_ret.found == phy_interface_rrc_lte::cell_search_ret_t::ERROR) { + // stop search + nof_plmns = -1; + Error("Failed due to failed cell search sub-procedure\n"); + return proc_outcome_t::error; + } + + if (cs_ret.found == phy_interface_rrc_lte::cell_search_ret_t::CELL_FOUND) { + if (rrc_ptr->serving_cell->has_sib1()) { + // Save PLMN and TAC to NAS + for (uint32_t i = 0; i < rrc_ptr->serving_cell->nof_plmns(); i++) { + if (nof_plmns < MAX_FOUND_PLMNS) { + found_plmns[nof_plmns].plmn_id = rrc_ptr->serving_cell->get_plmn(i); + found_plmns[nof_plmns].tac = rrc_ptr->serving_cell->get_tac(); + nof_plmns++; + } else { + Error("No more space for plmns (%d)\n", nof_plmns); + } + } + } else { + Error("SIB1 not acquired\n"); + } + } + + if (cs_ret.last_freq == phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS) { + Info("completed PLMN search\n"); + return proc_outcome_t::success; + } + + if (not rrc_ptr->cell_searcher.launch(rrc_ptr)) { + Error("Failed due to fail to init cell search...\n"); + return proc_outcome_t::error; + } + + // run again + return proc_outcome_t::repeat; +} + +void rrc::plmn_search_proc::stop() +{ + // on cleanup, call plmn_search_completed + if (is_success()) { + Info("completed with success\n"); + rrc_ptr->nas->plmn_search_completed(found_plmns, nof_plmns); + } else if (is_error()) { + Error("PLMN Search completed with an error\n"); + rrc_ptr->nas->plmn_search_completed(nullptr, -1); + } +} + +/************************************** + * Connection Request Procedure + *************************************/ + +proc_outcome_t rrc::connection_request_proc::init(rrc* parent_, + srslte::establishment_cause_t cause_, + srslte::unique_byte_buffer_t dedicated_info_nas_) +{ + rrc_ptr = parent_; + log_h = parent_->rrc_log; + cause = cause_; + dedicated_info_nas = std::move(dedicated_info_nas_); + + if (!rrc_ptr->plmn_is_selected) { + Error("Trying to connect but PLMN not selected.\n"); + return proc_outcome_t::error; + } + + if (rrc_ptr->state != RRC_STATE_IDLE) { + log_h->warning("Requested RRC connection establishment while not in IDLE\n"); + return proc_outcome_t::error; + } + + if (rrc_ptr->timers->get(rrc_ptr->t302)->is_running()) { + Info("Requested RRC connection establishment while T302 is running\n"); + rrc_ptr->nas->set_barring(nas_interface_rrc::BARRING_MO_DATA); + return proc_outcome_t::error; + } + + Info("Initiation of Connection establishment procedure\n"); + + cs_ret = cs_result_t::no_cell; + + state = state_t::cell_selection; + if (not rrc_ptr->cell_selector.launch(rrc_ptr)) { + if (not rrc_ptr->cell_selector.is_active()) { + // Launch failed but cell selection was not already running + Error("Failed to initiate cell selection procedure...\n"); + return proc_outcome_t::error; + } + // In case it was already running, just wait for an cell_selection_complete event trigger + Info("Cell selection proc already on-going. Wait for its result\n"); + } else { + // In case we were able to launch it, let the callback list handle it + rrc_ptr->callback_list.defer_proc(rrc_ptr->cell_selector); + } + return proc_outcome_t::repeat; +} + +proc_outcome_t rrc::connection_request_proc::step() +{ + if (state == state_t::cell_selection) { + // NOTE: cell selection will signal back with an event trigger + return proc_outcome_t::yield; + } else if (state == state_t::config_serving_cell) { + if (rrc_ptr->serv_cell_cfg.run()) { + return proc_outcome_t::yield; + } + serving_cell_config_proc ret = rrc_ptr->serv_cell_cfg.pop(); + + if (ret.is_error()) { + Error("Configuring serving cell\n"); + return proc_outcome_t::error; + } + + rrc_ptr->timers->get(rrc_ptr->t300)->reset(); + rrc_ptr->timers->get(rrc_ptr->t300)->run(); + + // Send connectionRequest message to lower layers + rrc_ptr->send_con_request(cause); + + // Save dedicatedInfoNAS SDU + if (rrc_ptr->dedicated_info_nas.get()) { + log_h->warning("Received a new dedicatedInfoNAS SDU but there was one still in queue. Removing it\n"); + } + + Info("Waiting for RRCConnectionSetup/Reject or expiry\n"); + rrc_ptr->dedicated_info_nas = std::move(dedicated_info_nas); + state = state_t::wait_t300; + return proc_outcome_t::repeat; + + } else if (state == state_t::wait_t300) { + // Wait until t300 stops due to RRCConnectionSetup/Reject or expiry + if (rrc_ptr->timers->get(rrc_ptr->t300)->is_running()) { + return proc_outcome_t::yield; + } + + if (rrc_ptr->state == RRC_STATE_CONNECTED) { + // Received ConnectionSetup + return proc_outcome_t::success; + } else if (rrc_ptr->timers->get(rrc_ptr->t300)->is_expired()) { + // T300 is expired: 5.3.3.6 + Info("Timer T300 expired: ConnectionRequest timed out\n"); + rrc_ptr->mac->reset(); + rrc_ptr->set_mac_default(); + rrc_ptr->rlc->reestablish(); + } else { + // T300 is stopped but RRC not Connected is because received Reject: Section 5.3.3.8 + Info("Timer T300 stopped: Received ConnectionReject\n"); + rrc_ptr->mac->reset(); + rrc_ptr->set_mac_default(); + } + } + + return proc_outcome_t::error; +} + +void rrc::connection_request_proc::stop() +{ + if (is_error()) { + log_h->warning("Could not establish connection. Deallocating dedicatedInfoNAS PDU\n"); + this->dedicated_info_nas.reset(); + rrc_ptr->nas->connection_request_completed(false); + } else if (is_success()) { + Info("Finished connection request procedure successfully.\n"); + rrc_ptr->nas->connection_request_completed(true); + } +} + +srslte::proc_outcome_t rrc::connection_request_proc::trigger_event(const cell_selection_complete& e) +{ + if (state != state_t::cell_selection) { + // ignore if we are not expecting an cell selection result + return proc_outcome_t::yield; + } + if (not e.is_success) { + return proc_outcome_t::error; + } + cs_ret = e.cs_result; + // .. and SI acquisition + if (rrc_ptr->phy->cell_is_camping()) { + + // Set default configurations + rrc_ptr->set_phy_default(); + rrc_ptr->set_mac_default(); + + // CCCH configuration applied already at start + // timeAlignmentCommon applied in configure_serving_cell + + Info("Configuring serving cell...\n"); + if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr, rrc_ptr->ue_required_sibs)) { + Error("Attach request failed to configure serving cell...\n"); + return proc_outcome_t::error; + } + state = state_t::config_serving_cell; + return proc_outcome_t::repeat; + } else { + switch (cs_ret) { + case cs_result_t::same_cell: + log_h->warning("Did not reselect cell but serving cell is out-of-sync.\n"); + rrc_ptr->serving_cell->in_sync = false; + break; + case cs_result_t::changed_cell: + log_h->warning("Selected a new cell but could not camp on. Setting out-of-sync.\n"); + rrc_ptr->serving_cell->in_sync = false; + break; + default: + log_h->warning("Could not find any suitable cell to connect\n"); + } + return proc_outcome_t::error; + } +} + +/************************************** + * Process PCCH procedure + *************************************/ + +proc_outcome_t rrc::process_pcch_proc::init(rrc* parent_, const asn1::rrc::paging_s& paging_) +{ + rrc_ptr = parent_; + log_h = parent_->rrc_log; + paging = paging_; + + paging_idx = 0; + state = state_t::next_record; + Info("starting...\n"); + return proc_outcome_t::repeat; +} + +proc_outcome_t rrc::process_pcch_proc::step() +{ + if (state == state_t::next_record) { + for (; paging_idx < paging.paging_record_list.size(); ++paging_idx) { + srslte::s_tmsi_t s_tmsi_paged = srslte::make_s_tmsi_t(paging.paging_record_list[paging_idx].ue_id.s_tmsi()); + Info("Received paging (%d/%d) for UE %" PRIu64 ":%" PRIu64 "\n", + paging_idx + 1, + paging.paging_record_list.size(), + paging.paging_record_list[paging_idx].ue_id.s_tmsi().mmec.to_number(), + paging.paging_record_list[paging_idx].ue_id.s_tmsi().m_tmsi.to_number()); + if (rrc_ptr->ue_identity == s_tmsi_paged) { + if (RRC_STATE_IDLE == rrc_ptr->state) { + Info("S-TMSI match in paging message\n"); + log_h->console("S-TMSI match in paging message\n"); + rrc_ptr->nas->paging(&s_tmsi_paged); + state = state_t::nas_paging; + return proc_outcome_t::repeat; + } else { + log_h->warning("Received paging while in CONNECT\n"); + } + } else { + Info("Received paging for unknown identity\n"); + } + } + if (paging.sys_info_mod_present) { + Info("Received System Information notification update request.\n"); + // invalidate and then update all SIBs of serving cell + rrc_ptr->serving_cell->reset_sibs(); + + // create a serving cell config procedure and push it to callback list + if (not rrc_ptr->serv_cell_cfg.launch(rrc_ptr, rrc_ptr->ue_required_sibs)) { + Error("Failed to initiate a serving cell configuration procedure\n"); + return proc_outcome_t::error; + } + } else { + Info("Completed successfully\n"); + return proc_outcome_t::success; + } + state = state_t::serv_cell_cfg; + return proc_outcome_t::repeat; + } else if (state == state_t::nas_paging) { + // wait for trigger + return proc_outcome_t::yield; + } else if (state == state_t::serv_cell_cfg) { + if (rrc_ptr->serv_cell_cfg.run()) { + return proc_outcome_t::yield; + } + serving_cell_config_proc ret = rrc_ptr->serv_cell_cfg.pop(); + if (ret.is_success()) { + Info("All SIBs of serving cell obtained successfully\n"); + return proc_outcome_t::success; + } else { + Error("While obtaining SIBs of serving cell\n"); + return proc_outcome_t::error; + } + } + return proc_outcome_t::yield; +} + +proc_outcome_t rrc::process_pcch_proc::trigger_event(paging_complete e) +{ + if (not e.outcome) { + Info("NAS Paging has failed\n"); + return proc_outcome_t::error; + } + paging_idx++; + state = state_t::next_record; + Info("Received paging complete event\n"); + return proc_outcome_t::repeat; +} + +/************************************** + * Go Idle procedure + *************************************/ + +proc_outcome_t rrc::go_idle_proc::init(rrc* rrc_) +{ + rrc_ptr = rrc_; + + rlc_flush_counter = 0; + Info("Starting...\n"); + return proc_outcome_t::yield; +} + +proc_outcome_t rrc::go_idle_proc::step() +{ + if (rrc_ptr->state == RRC_STATE_IDLE) { + Info("Interrupting as RRC has already became IDLE\n"); + return proc_outcome_t::success; + } + + // wait for max. 2s for RLC on SRB1 to be flushed + if (not rrc_ptr->rlc->has_data(RB_ID_SRB1) || ++rlc_flush_counter > rlc_flush_timeout) { + rrc_ptr->leave_connected(); + return proc_outcome_t::success; + } else { + rrc_ptr->rrc_log->debug( + "Postponing transition to RRC IDLE (%d ms < %d ms)\n", rlc_flush_counter, rlc_flush_timeout); + } + return proc_outcome_t::yield; +} + +} // namespace srsue diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 98738aa44..631909b05 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -27,6 +27,7 @@ using namespace srslte; namespace srsue { ue_stack_lte::ue_stack_lte() : + timers(64), running(false), args(), logger(nullptr), @@ -37,8 +38,17 @@ ue_stack_lte::ue_stack_lte() : rrc(&rrc_log), pdcp(&pdcp_log), nas(&nas_log), - thread("STACK") + thread("STACK"), + pending_tasks(1024), + background_tasks(2) { + ue_queue_id = pending_tasks.add_queue(); + sync_queue_id = pending_tasks.add_queue(); + gw_queue_id = pending_tasks.add_queue(); + mac_queue_id = pending_tasks.add_queue(); + background_queue_id = pending_tasks.add_queue(); + + background_tasks.start(); } ue_stack_lte::~ue_stack_lte() @@ -114,11 +124,11 @@ int ue_stack_lte::init(const stack_args_t& args_, srslte::logger* logger_) return SRSLTE_ERROR; } - mac.init(phy, &rlc, &rrc); - rlc.init(&pdcp, &rrc, &mac, 0 /* RB_ID_SRB0 */); + mac.init(phy, &rlc, &rrc, &timers, this); + rlc.init(&pdcp, &rrc, &timers, 0 /* RB_ID_SRB0 */); pdcp.init(&rlc, &rrc, gw); nas.init(usim.get(), &rrc, gw, args.nas); - rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, &mac, args.rrc); + rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, &timers, this, args.rrc); running = true; start(STACK_MAIN_THREAD_PRIO); @@ -129,7 +139,7 @@ int ue_stack_lte::init(const stack_args_t& args_, srslte::logger* logger_) void ue_stack_lte::stop() { if (running) { - pending_tasks.push([this]() { stop_impl(); }); + pending_tasks.try_push(ue_queue_id, task_t{[this](task_t*) { stop_impl(); }}); wait_thread_finish(); } } @@ -157,7 +167,13 @@ void ue_stack_lte::stop_impl() bool ue_stack_lte::switch_on() { if (running) { - return nas.attach_request(); + proc_state_t proc_result = proc_state_t::on_going; + pending_tasks.try_push(ue_queue_id, + task_t{[this, &proc_result](task_t*) { nas.start_attach_request(&proc_result); }}); + while (proc_result == proc_state_t::on_going) { + usleep(1000); + } + return proc_result == proc_state_t::success; } return false; @@ -165,8 +181,8 @@ bool ue_stack_lte::switch_on() bool ue_stack_lte::switch_off() { - // generate detach request - nas.detach_request(); + // generate detach request with switch-off flag + nas.detach_request(true); // wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) const uint32_t RB_ID_SRB1 = 1; @@ -184,6 +200,18 @@ bool ue_stack_lte::switch_off() return detach_sent; } +bool ue_stack_lte::enable_data() +{ + // perform attach request + return switch_on(); +} + +bool ue_stack_lte::disable_data() +{ + // generate detach request + return nas.detach_request(false); +} + bool ue_stack_lte::get_metrics(stack_metrics_t* metrics) { mac.get_metrics(metrics->mac); @@ -196,31 +224,99 @@ bool ue_stack_lte::get_metrics(stack_metrics_t* metrics) void ue_stack_lte::run_thread() { while (running) { - // FIXME: For now it is a single queue - std::function func = pending_tasks.wait_pop(); - func(); + task_t task{}; + if (pending_tasks.wait_pop(&task) >= 0) { + task(); + } } } +/*********************************************************************************************************************** + * Stack Interfaces + **********************************************************************************************************************/ + +/******************** + * GW Interface + *******************/ + +/** + * Push GW SDU to stack + * @param lcid + * @param sdu + * @param blocking + */ +void ue_stack_lte::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) +{ + task_t task{}; + task.pdu = std::move(sdu); + task.func = [this, lcid, blocking](task_t* task_ctxt) { pdcp.write_sdu(lcid, std::move(task_ctxt->pdu), blocking); }; + std::pair ret = pending_tasks.try_push(gw_queue_id, std::move(task)); + if (not ret.first) { + pdcp_log.warning("GW SDU with lcid=%d was discarded.\n", lcid); + } +} + +/******************** + * SYNC Interface + *******************/ + +/** + * Sync thread signal that it is in sync + */ void ue_stack_lte::in_sync() { - pending_tasks.push([this]() { rrc.in_sync(); }); + pending_tasks.push(sync_queue_id, task_t{[this](task_t*) { rrc.in_sync(); }}); } void ue_stack_lte::out_of_sync() { - pending_tasks.push([this]() { rrc.out_of_sync(); }); + pending_tasks.push(sync_queue_id, task_t{[this](task_t*) { rrc.out_of_sync(); }}); } void ue_stack_lte::run_tti(uint32_t tti) { - pending_tasks.push([this, tti]() { run_tti_impl(tti); }); + pending_tasks.push(sync_queue_id, task_t{[this, tti](task_t*) { run_tti_impl(tti); }}); } void ue_stack_lte::run_tti_impl(uint32_t tti) { mac.run_tti(tti); rrc.run_tti(tti); + nas.run_tti(tti); + timers.step_all(); +} + +/******************** + * low MAC Interface + *******************/ + +void ue_stack_lte::process_pdus() +{ + pending_tasks.push(mac_queue_id, task_t{[this](task_t*) { mac.process_pdus(); }}); +} + +void ue_stack_lte::wait_ra_completion(uint16_t rnti) +{ + background_tasks.push_task([this, rnti](uint32_t worker_id) { + phy->set_crnti(rnti); + // signal MAC RA proc to go back to idle + mac.notify_ra_completed(); + }); +} + +/******************** + * RRC Interface + *******************/ + +void ue_stack_lte::start_cell_search() +{ + background_tasks.push_task([this](uint32_t worker_id) { + phy_interface_rrc_lte::phy_cell_t found_cell; + phy_interface_rrc_lte::cell_search_ret_t ret = phy->cell_search(&found_cell); + // notify back RRC + pending_tasks.push(background_queue_id, + task_t{[this, found_cell, ret](task_t*) { rrc.cell_search_completed(ret, found_cell); }}); + }); } } // namespace srsue diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 043a4519b..f2f8702e1 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -36,8 +36,174 @@ using namespace srslte; +#define Error(fmt, ...) nas_ptr->nas_log->error("%s - " fmt, name(), ##__VA_ARGS__) +#define Warning(fmt, ...) nas_ptr->nas_log->warning("%s - " fmt, name(), ##__VA_ARGS__) +#define Info(fmt, ...) nas_ptr->nas_log->info("%s - " fmt, name(), ##__VA_ARGS__) + namespace srsue { +using srslte::proc_outcome_t; + +proc_outcome_t nas::plmn_search_proc::init(nas* nas_ptr_) +{ + nas_ptr = nas_ptr_; + + // start RRC + state = state_t::plmn_search; + if (not nas_ptr->rrc->plmn_search()) { + Error("Error while searching for PLMNs\n"); + return proc_outcome_t::error; + } + + Info("Starting...\n"); + return proc_outcome_t::yield; +} + +proc_outcome_t nas::plmn_search_proc::step() +{ + if (state == state_t::rrc_connect) { + if (nas_ptr->rrc_connector.run()) { + return proc_outcome_t::yield; + } + rrc_connect_proc ret = nas_ptr->rrc_connector.pop(); + if (ret.is_success()) { + return proc_outcome_t::success; + } + nas_ptr->enter_emm_deregistered(); + return proc_outcome_t::error; + } + return proc_outcome_t::yield; +} + +proc_outcome_t nas::plmn_search_proc::trigger_event(const plmn_search_complete_t& t) +{ + if (state != state_t::plmn_search) { + Warning("PLMN Search Complete was received but PLMN Search is not running.\n"); + return proc_outcome_t::yield; // ignore + } + + // check whether the state hasn't changed + if (nas_ptr->state != EMM_STATE_DEREGISTERED or nas_ptr->plmn_is_selected) { + Error("Error while searching for PLMNs\n"); + return proc_outcome_t::error; + } + + if (t.nof_plmns < 0) { + Error("Error while searching for PLMNs\n"); + return proc_outcome_t::error; + } else if (t.nof_plmns == 0) { + Warning("Did not find any PLMN in the set of frequencies.\n"); + return proc_outcome_t::error; + } + + // Save PLMNs + nas_ptr->known_plmns.clear(); + for (int i = 0; i < t.nof_plmns; i++) { + nas_ptr->known_plmns.push_back(t.found_plmns[i].plmn_id); + nas_ptr->nas_log->info( + "Found PLMN: Id=%s, TAC=%d\n", t.found_plmns[i].plmn_id.to_string().c_str(), t.found_plmns[i].tac); + nas_ptr->nas_log->console( + "Found PLMN: Id=%s, TAC=%d\n", t.found_plmns[i].plmn_id.to_string().c_str(), t.found_plmns[i].tac); + } + nas_ptr->select_plmn(); + + // Select PLMN in request establishment of RRC connection + if (not nas_ptr->plmn_is_selected) { + Error("PLMN is not selected because no suitable PLMN was found\n"); + return proc_outcome_t::error; + } + + nas_ptr->rrc->plmn_select(nas_ptr->current_plmn); + + if (not nas_ptr->rrc_connector.launch(nas_ptr, srslte::establishment_cause_t ::mo_data, nullptr)) { + Error("Unable to initiate RRC connection.\n"); + return proc_outcome_t::error; + } + + state = state_t::rrc_connect; + return proc_outcome_t::yield; +} + +proc_outcome_t +nas::rrc_connect_proc::init(nas* nas_ptr_, srslte::establishment_cause_t cause_, srslte::unique_byte_buffer_t pdu) +{ + nas_ptr = nas_ptr_; + + if (nas_ptr->rrc->is_connected()) { + Info("Stopping. Reason: Already connected\n"); + return proc_outcome_t::success; + } + + if (pdu == nullptr) { + // Generate service request or attach request message + pdu = srslte::allocate_unique_buffer(*nas_ptr->pool, true); + if (!pdu) { + Error("Fatal Error: Couldn't allocate PDU.\n"); + return proc_outcome_t::error; + } + + if (nas_ptr->state == EMM_STATE_REGISTERED) { + nas_ptr->gen_service_request(pdu.get()); + } else { + nas_ptr->gen_attach_request(pdu.get()); + } + } + + // Provide UE-Identity to RRC if have one + if (nas_ptr->have_guti) { + srslte::s_tmsi_t s_tmsi; + s_tmsi.mmec = nas_ptr->ctxt.guti.mme_code; + s_tmsi.m_tmsi = nas_ptr->ctxt.guti.m_tmsi; + nas_ptr->rrc->set_ue_identity(s_tmsi); + } + + state = state_t::conn_req; + if (not nas_ptr->start_connection_request(cause_, std::move(pdu))) { + return proc_outcome_t::error; + } + + Info("Starting...\n"); + return proc_outcome_t::yield; +} + +proc_outcome_t nas::rrc_connect_proc::step() +{ + if (state == state_t::conn_req) { + if (nas_ptr->conn_req_proc.run()) { + return proc_outcome_t::yield; + } + query_proc_t ret = nas_ptr->conn_req_proc.pop(); + if (not ret.result()) { + Error("Could not establish RRC connection\n"); + return proc_outcome_t::error; + } + Info("Connection established correctly. Waiting for Attach\n"); + wait_timeout = 0; + // Wait until attachment. If doing a service request is already attached + state = state_t::wait_attach; + return proc_outcome_t::repeat; + } else if (state == state_t::wait_attach) { + wait_timeout++; + // Wait until attachment. If doing a service request is already attached + if (wait_timeout >= 5000 or nas_ptr->state == EMM_STATE_REGISTERED or not nas_ptr->running or + not nas_ptr->rrc->is_connected()) { + if (nas_ptr->state == EMM_STATE_REGISTERED) { + Info("EMM Registered correctly\n"); + return proc_outcome_t::success; + } else if (nas_ptr->state == EMM_STATE_DEREGISTERED) { + Error("Timeout or received attach reject while trying to attach\n"); + nas_ptr->nas_log->console("Failed to Attach\n"); + } else if (!nas_ptr->rrc->is_connected()) { + Error("Was disconnected while attaching\n"); + } else { + Error("Timed out while trying to attach\n"); + } + return proc_outcome_t::error; + } + } + return proc_outcome_t::yield; +} + /********************************************************************* * NAS ********************************************************************/ @@ -62,7 +228,7 @@ void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_ nas_log->error("Empty EIA list. Select at least one EIA algorithm.\n"); } for (std::vector::const_iterator it = cap_list.begin(); it != cap_list.end(); ++it) { - if (*it != 0 && *it < 3) { + if (*it != 0 && *it < 4) { eia_caps[*it] = true; } else { nas_log->error("EIA%d is not a valid EIA algorithm.\n", *it); @@ -75,16 +241,16 @@ void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_ nas_log->error("Empty EEA list. Select at least one EEA algorithm.\n"); } for (std::vector::const_iterator it = cap_list.begin(); it != cap_list.end(); ++it) { - if (*it < 3) { + if (*it < 4) { eea_caps[*it] = true; } else { nas_log->error("EEA%d is not a valid EEA algorithm.\n", *it); } } - cfg = cfg_; + cfg = cfg_; - if((read_ctxt_file(&ctxt))) { + if ((read_ctxt_file(&ctxt))) { usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); @@ -96,7 +262,8 @@ void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_ running = true; } -void nas::stop() { +void nas::stop() +{ running = false; write_ctxt_file(ctxt); } @@ -109,10 +276,16 @@ void nas::get_metrics(nas_metrics_t* m) *m = metrics; } -emm_state_t nas::get_state() { +emm_state_t nas::get_state() +{ return state; } +void nas::run_tti(uint32_t tti) +{ + callbacks.run(); +} + /******************************************************************************* * UE interface ******************************************************************************/ @@ -121,82 +294,83 @@ emm_state_t nas::get_state() { * The function returns true if the UE could attach correctly or false in case of error or timeout during attachment. * */ -bool nas::attach_request() { - rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS]; - int nof_plmns = 0; - +void nas::start_attach_request(srslte::proc_state_t* result) +{ nas_log->info("Attach Request\n"); switch (state) { case EMM_STATE_DEREGISTERED: - // Search PLMN is not selected if (!plmn_is_selected) { nas_log->info("No PLMN selected. Starting PLMN Search...\n"); - nof_plmns = rrc->plmn_search(found_plmns); - if (nof_plmns > 0) { - // Save PLMNs - known_plmns.clear(); - for (int i=0;iinfo( - "Found PLMN: Id=%s, TAC=%d\n", found_plmns[i].plmn_id.to_string().c_str(), found_plmns[i].tac); - nas_log->console( - "Found PLMN: Id=%s, TAC=%d\n", found_plmns[i].plmn_id.to_string().c_str(), found_plmns[i].tac); - } - select_plmn(); - } else if (nof_plmns == 0) { - nas_log->warning("Did not find any PLMN in the set of frequencies\n"); - return false; - } else if (nof_plmns < 0) { - nas_log->error("Error while searching for PLMNs\n"); - return false; - } - } - // Select PLMN in request establishment of RRC connection - if (plmn_is_selected) { - rrc->plmn_select(current_plmn); - if (rrc_connect()) { - nas_log->info("NAS attached successfully.\n"); - return true; - } else { - nas_log->error("Could not attach in attach request\n"); + if (not plmn_searcher.launch(this)) { + *result = proc_state_t::error; + return; } + callbacks.defer_task([this, result]() { + if (plmn_searcher.run()) { + return proc_outcome_t::yield; + } + plmn_search_proc p = plmn_searcher.pop(); + nas_log->info("Attach Request from PLMN Search %s\n", p.is_success() ? "finished successfully" : "failed"); + *result = p.is_success() ? proc_state_t::success : proc_state_t::error; + // stay in this state if attach failed + if (not p.is_success()) { + enter_emm_deregistered(); + } + return proc_outcome_t::success; + }); } else { - nas_log->error("PLMN is not selected because no suitable PLMN was found\n"); + nas_log->error("PLMN selected in state %s\n", emm_state_text[state]); + *result = proc_state_t::error; } break; case EMM_STATE_REGISTERED: if (rrc->is_connected()) { nas_log->info("NAS is already registered and RRC connected\n"); - return true; + *result = proc_state_t::success; } else { nas_log->info("NAS is already registered but RRC disconnected. Connecting now...\n"); - if (rrc_connect()) { - nas_log->info("NAS attached successfully.\n"); - return true; - } else { - nas_log->error("Could not attach from attach_request\n"); + if (not rrc_connector.launch(this, srslte::establishment_cause_t ::mo_data, nullptr)) { + nas_log->error("Cannot initiate concurrent rrc connection procedures\n"); + *result = proc_state_t::error; + return; } + callbacks.defer_task([this, result]() { + if (rrc_connector.run()) { + return proc_outcome_t::yield; + } + rrc_connect_proc proc = rrc_connector.pop(); + if (proc.is_success()) { + nas_log->info("NAS attached successfully.\n"); + } else { + nas_log->error("Could not attach from attach_request\n"); + } + *result = proc.is_success() ? proc_state_t::success : proc_state_t::error; + return proc_outcome_t::success; + }); } break; default: nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]); + *result = proc_state_t::error; } - return false; } -bool nas::detach_request() { - // attempt detach for 5s - nas_log->info("Detach Request\n"); +void nas::plmn_search_completed(rrc_interface_nas::found_plmn_t found_plmns[rrc_interface_nas::MAX_FOUND_PLMNS], + int nof_plmns) +{ + plmn_searcher.trigger_event(plmn_search_proc::plmn_search_complete_t(found_plmns, nof_plmns)); +} +bool nas::detach_request(const bool switch_off) +{ switch (state) { case EMM_STATE_DEREGISTERED: // do nothing .. break; case EMM_STATE_REGISTERED: // send detach request - send_detach_request(true); - state = EMM_STATE_DEREGISTERED; + send_detach_request(switch_off); break; case EMM_STATE_DEREGISTERED_INITIATED: // do nothing .. @@ -207,12 +381,24 @@ bool nas::detach_request() { return false; } -void nas::leave_connected() { +void nas::enter_emm_deregistered() +{ + // Deactivate EPS bearer according to Sec. 5.5.2.2.2 + nas_log->debug("Clearing EPS bearer context\n"); + eps_bearer.clear(); + + plmn_is_selected = false; + state = EMM_STATE_DEREGISTERED; +} + +void nas::left_rrc_connected() +{ return; } -bool nas::is_attached() { +bool nas::is_attached() +{ return state == EMM_STATE_REGISTERED; } @@ -220,11 +406,23 @@ void nas::paging(s_tmsi_t* ue_identity) { if (state == EMM_STATE_REGISTERED) { nas_log->info("Received paging: requesting RRC connection establishment\n"); - if (rrc_connect()) { - nas_log->info("Attached successfully\n"); - } else { - nas_log->error("Could not attach from paging\n"); + if (rrc_connector.is_active()) { + nas_log->error("Cannot initiate concurrent RRC connection establishment procedures\n"); + return; + } + if (not rrc_connector.launch(this, srslte::establishment_cause_t ::mt_access, nullptr)) { + nas_log->error("Could not launch RRC Connect()\n"); + return; } + // once completed, call paging complete + callbacks.defer_task([this]() { + if (rrc_connector.run()) { + return proc_outcome_t::yield; + } + bool success = rrc_connector.pop().is_success(); + rrc->paging_completed(success); + return proc_outcome_t::success; + }); } else { nas_log->warning("Received paging while in state %s\n", emm_state_text[state]); } @@ -234,66 +432,25 @@ void nas::set_barring(barring_t barring) { current_barring = barring; } -/* Internal function that requests RRC connection, waits for positive or negative response and returns true/false - */ -bool nas::rrc_connect() { - if (rrc->is_connected()) { - nas_log->info("Already connected\n"); - return true; - } - - // Generate service request or attach request message - unique_byte_buffer_t dedicatedInfoNAS = srslte::allocate_unique_buffer(*pool, true); - if (!dedicatedInfoNAS) { - nas_log->error("Fatal Error: Couldn't allocate PDU in rrc_connect().\n"); +bool nas::start_connection_request(srslte::establishment_cause_t establish_cause, + srslte::unique_byte_buffer_t ded_info_nas) +{ + if (not conn_req_proc.launch()) { + nas_log->error("Failed to initiate a connection request procedure\n"); return false; } - - if (state == EMM_STATE_REGISTERED) { - gen_service_request(dedicatedInfoNAS.get()); - } else { - gen_attach_request(dedicatedInfoNAS.get()); - } - - // Provide UE-Identity to RRC if have one - if (have_guti) { - s_tmsi_t s_tmsi; - s_tmsi.m_tmsi = ctxt.guti.m_tmsi; - s_tmsi.mmec = ctxt.guti.mme_code; - rrc->set_ue_identity(s_tmsi); - } - - // Set establishment cause - srslte::establishment_cause_t establish_cause = srslte::establishment_cause_t::mo_sig; - if (state == EMM_STATE_REGISTERED) { - // FIXME: only need to use MT_ACCESS for establishment after paging - establish_cause = establishment_cause_t::mt_access; + if (not rrc->connection_request(establish_cause, std::move(ded_info_nas))) { + nas_log->error("Failed to initiate a connection request procedure\n"); + conn_req_proc.pop(); + return false; } + return true; +} - if (rrc->connection_request(establish_cause, std::move(dedicatedInfoNAS))) { - nas_log->info("Connection established correctly. Waiting for Attach\n"); - - // Wait until attachment. If doing a service request is already attached - uint32_t tout = 0; - while (tout < 5000 && state != EMM_STATE_REGISTERED && running && rrc->is_connected()) { - usleep(1000); - tout++; - } - if (state == EMM_STATE_REGISTERED) { - nas_log->info("EMM Registered correctly\n"); - return true; - } else if (state == EMM_STATE_DEREGISTERED) { - nas_log->error("Timeout or received attach reject while trying to attach\n"); - nas_log->console("Failed to Attach\n"); - } else if (!rrc->is_connected()) { - nas_log->error("Was disconnected while attaching\n"); - } else { - nas_log->error("Timed out while trying to attach\n"); - } - } else { - nas_log->error("Could not establish RRC connection\n"); - } - return false; +bool nas::connection_request_completed(bool outcome) +{ + conn_req_proc.trigger_event(outcome); + return conn_req_proc.is_active(); } void nas::select_plmn() { @@ -311,7 +468,7 @@ void nas::select_plmn() { } // If not, select the first available PLMN - if (known_plmns.size() > 0) { + if (not known_plmns.empty()) { nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", home_plmn.to_string().c_str(), known_plmns[0].to_string().c_str()); @@ -359,7 +516,7 @@ void nas::write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) } // Write NAS pcap - if(pcap != NULL) { + if (pcap != nullptr) { pcap->write_nas(pdu->msg, pdu->N_bytes); } @@ -382,7 +539,7 @@ void nas::write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) parse_authentication_reject(lcid, std::move(pdu)); break; case LIBLTE_MME_MSG_TYPE_IDENTITY_REQUEST: - parse_identity_request(lcid, std::move(pdu)); + parse_identity_request(std::move(pdu), sec_hdr_type); break; case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMMAND: parse_security_mode_command(lcid, std::move(pdu)); @@ -424,7 +581,6 @@ void nas::set_k_enb_count(uint32_t count) { // UL count for RRC key derivation depends on UL Count of the Attach Request or Service Request. // On the case of an Authentication Request, the UL count used to generate K_enb must be reset to zero. ctxt.k_enb_count = count; - return; } uint32_t nas::get_k_enb_count() { @@ -436,7 +592,7 @@ bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) { nas_log->error("K_asme requested before security context established\n"); return false; } - if(NULL == k_asme_ || n < 32) { + if (nullptr == k_asme_ || n < 32) { nas_log->error("Invalid parameters to get_k_asme"); return false; } @@ -494,7 +650,16 @@ void nas::integrity_generate(uint8_t *key_128, case INTEGRITY_ALGORITHM_ID_128_EIA2: security_128_eia2(key_128, count, - 0, // Bearer always 0 for NAS + 0, // Bearer always 0 for NAS + direction, + msg, + msg_len, + mac); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA3: + security_128_eia3(key_128, + count, + 0, // Bearer always 0 for NAS direction, msg, msg_len, @@ -516,14 +681,13 @@ bool nas::integrity_check(byte_buffer_t* pdu) } if (pdu->N_bytes > 5) { - uint8_t exp_mac[4] = {0}; + uint8_t exp_mac[4] = {0}; uint8_t *mac = &pdu->msg[1]; - integrity_generate(&k_nas_int[16], - ctxt.rx_count, - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[5], - pdu->N_bytes-5, - &exp_mac[0]); + + // generate expected MAC + uint32_t count_est = (ctxt.rx_count & 0x0FF0) | pdu->msg[5]; + integrity_generate( + &k_nas_int[16], count_est, SECURITY_DIRECTION_DOWNLINK, &pdu->msg[5], pdu->N_bytes - 5, &exp_mac[0]); // Check if expected mac equals the sent mac for (int i = 0; i < 4; i++) { @@ -537,6 +701,12 @@ bool nas::integrity_check(byte_buffer_t* pdu) } nas_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", ctxt.rx_count, pdu->msg[5]); + + // Updated local count (according to TS 24.301 Sec. 4.4.3.3) + if (pdu->msg[5] != ctxt.rx_count) { + nas_log->info("Update local count to received value %d\n", pdu->msg[5]); + ctxt.rx_count = count_est; + } return true; } else { nas_log->error("Invalid integrity check PDU size (%d)\n", pdu->N_bytes); @@ -559,21 +729,31 @@ void nas::cipher_encrypt(byte_buffer_t* pdu) &pdu->msg[6], pdu->N_bytes-6, &pdu_tmp.msg[6]); - memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); break; case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&k_nas_enc[16], - pdu->msg[5], - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, - &pdu->msg[6], - pdu->N_bytes-6, - &pdu_tmp.msg[6]); - memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); - break; + security_128_eea2(&k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); + break; default: - nas_log->error("Ciphering algorithm not known\n"); - break; + nas_log->error("Ciphering algorithm not known\n"); + break; } } @@ -595,19 +775,30 @@ void nas::cipher_decrypt(byte_buffer_t* pdu) memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); break; case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&k_nas_enc[16], - pdu->msg[5], - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[6], - pdu->N_bytes-6, - &tmp_pdu.msg[6]); - nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); - memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); - break; - default: - nas_log->error("Ciphering algorithms not known\n"); - break; + security_128_eea2(&k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); + nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA3: + security_128_eea3(&k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); + nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); + break; + default: + nas_log->error("Ciphering algorithms not known\n"); + break; } } @@ -834,18 +1025,21 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) eps_bearer_t bearer = {}; bearer.type = DEFAULT_EPS_BEARER; bearer.eps_bearer_id = act_def_eps_bearer_context_req.eps_bearer_id; - if (not eps_bearer.insert(eps_bearer_map_pair_t(bearer.eps_bearer_id, bearer)).second) { + if (eps_bearer.insert(eps_bearer_map_pair_t(bearer.eps_bearer_id, bearer)).second) { + // bearer added successfully + state = EMM_STATE_REGISTERED; + + // send attach complete + send_attach_complete(transaction_id, bearer.eps_bearer_id); + } else { + // bearer already exists (perhaps the attach complete got lost and this is a retx?) + // FIXME: what are we supposed to do in this case? nas_log->error("Error adding EPS bearer.\n"); - return; } - state = EMM_STATE_REGISTERED; - - // send attach complete - send_attach_complete(transaction_id, bearer.eps_bearer_id); } else { nas_log->info("Not handling attach type %u\n", attach_accept.eps_attach_result); - state = EMM_STATE_DEREGISTERED; + enter_emm_deregistered(); } ctxt.rx_count++; @@ -859,7 +1053,7 @@ void nas::parse_attach_reject(uint32_t lcid, unique_byte_buffer_t pdu) liblte_mme_unpack_attach_reject_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &attach_rej); nas_log->warning("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause); nas_log->console("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause); - state = EMM_STATE_DEREGISTERED; + enter_emm_deregistered(); // FIXME: Command RRC to release? } @@ -912,26 +1106,25 @@ void nas::parse_authentication_request(uint32_t lcid, unique_byte_buffer_t pdu, void nas::parse_authentication_reject(uint32_t lcid, unique_byte_buffer_t pdu) { nas_log->warning("Received Authentication Reject\n"); - state = EMM_STATE_DEREGISTERED; + enter_emm_deregistered(); // FIXME: Command RRC to release? } -void nas::parse_identity_request(uint32_t lcid, unique_byte_buffer_t pdu) +void nas::parse_identity_request(unique_byte_buffer_t pdu, const uint8_t sec_hdr_type) { - LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req; - ZERO_OBJECT(id_req); - LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; - ZERO_OBJECT(id_resp); - + LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req = {}; liblte_mme_unpack_identity_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &id_req); - // Deallocate PDU after parsing - - ctxt.rx_count++; - nas_log->info("Received Identity Request. ID type: %d\n", id_req.id_type); + ctxt.rx_count++; - send_identity_response(lcid, id_req.id_type); + // do not respond if request is not protected (TS 24.301 Sec. 4.4.4.2) + if (sec_hdr_type >= LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || + (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS && id_req.id_type == LIBLTE_MME_MOBILE_ID_TYPE_IMSI)) { + send_identity_response(id_req.id_type, sec_hdr_type); + } else { + nas_log->info("Not sending identity response due to missing integrity protection.\n"); + } } void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu) @@ -1007,7 +1200,7 @@ void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu) nas_log->debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d\n", ctxt.integ_algo, ctxt.rx_count, lcid); - if (integrity_check(pdu.get()) != true) { + if (not integrity_check(pdu.get())) { nas_log->warning("Sending Security Mode Reject due to integrity check failure\n"); send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_MAC_FAILURE); return; @@ -1068,8 +1261,7 @@ void nas::parse_service_reject(uint32_t lcid, unique_byte_buffer_t pdu) // FIXME: handle NAS backoff-timers correctly - // Mark state as EMM-DEREGISTERED - state = EMM_STATE_DEREGISTERED; + enter_emm_deregistered(); // Reset security context ctxt = {}; @@ -1109,13 +1301,19 @@ void nas::parse_detach_request(uint32_t lcid, unique_byte_buffer_t pdu) liblte_mme_unpack_detach_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &detach_request); ctxt.rx_count++; - if (state == EMM_STATE_REGISTERED) { - nas_log->info("Received Detach request (type=%d)\n", detach_request.detach_type.type_of_detach); - state = EMM_STATE_DEREGISTERED; - // send accept - send_detach_accept(); - } else { - nas_log->warning("Received detach request in invalid state (state=%d)\n", state); + switch (state) { + case EMM_STATE_DEREGISTERED_INITIATED: + nas_log->info("Received detach from network while performing UE initiated detach. Aborting UE detach.\n"); + case EMM_STATE_REGISTERED: + nas_log->info("Received detach request (type=%d)\n", detach_request.detach_type.type_of_detach); + + // send accept and leave state + send_detach_accept(); + enter_emm_deregistered(); + break; + default: + nas_log->warning("Received detach request in invalid state (%s)\n", emm_state_text[state]); + break; } } @@ -1463,7 +1661,7 @@ void nas::send_detach_request(bool switch_off) detach_request.detach_type.type_of_detach = LIBLTE_MME_SO_FLAG_SWITCH_OFF; } else { detach_request.detach_type.switch_off = 0; - detach_request.detach_type.type_of_detach = LIBLTE_MME_SO_FLAG_NORMAL_DETACH; + detach_request.detach_type.type_of_detach = LIBLTE_MME_TOD_UL_EPS_DETACH; } // GUTI or IMSI detach @@ -1472,7 +1670,7 @@ void nas::send_detach_request(bool switch_off) memcpy(&detach_request.eps_mobile_id.guti, &ctxt.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; detach_request.nas_ksi.nas_ksi = ctxt.ksi; - nas_log->info("Requesting Detach with GUTI\n"); //If sent as an Initial UE message, it cannot be chiphered + nas_log->info("Sending detach request with GUTI\n"); // If sent as an Initial UE message, it cannot be chiphered liblte_mme_pack_detach_request_msg(&detach_request, rrc->is_connected() ? LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED : LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, @@ -1503,7 +1701,7 @@ void nas::send_detach_request(bool switch_off) detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; detach_request.nas_ksi.nas_ksi = 0; usim->get_imsi_vec(detach_request.eps_mobile_id.imsi, 15); - nas_log->info("Requesting IMSI detach (IMSI=%s)\n", usim->get_imsi_str().c_str()); + nas_log->info("Sending detach request with IMSI\n"); liblte_mme_pack_detach_request_msg( &detach_request, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); @@ -1512,11 +1710,20 @@ void nas::send_detach_request(bool switch_off) } } - nas_log->info("Sending detach request\n"); + if (switch_off) { + enter_emm_deregistered(); + } else { + // we are expecting a response from the core + state = EMM_STATE_DEREGISTERED_INITIATED; + } + if (rrc->is_connected()) { rrc->write_sdu(std::move(pdu)); } else { - rrc->connection_request(establishment_cause_t::mo_sig, std::move(pdu)); + if (not rrc_connector.launch(this, establishment_cause_t::mo_sig, std::move(pdu))) { + nas_log->error("Failed to initiate RRC Connection Request\n"); + } + callbacks.defer_proc(rrc_connector); } } @@ -1652,13 +1859,11 @@ void nas::send_authentication_failure(const uint8_t cause, const uint8_t* auth_f rrc->write_sdu(std::move(msg)); } - -void nas::send_identity_response(uint32_t lcid, uint8 id_type) +void nas::send_identity_response(const uint8 id_type, const uint8_t sec_hdr_type) { - LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; - ZERO_OBJECT(id_resp); + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp = {}; - switch(id_type) { + switch (id_type) { case LIBLTE_MME_MOBILE_ID_TYPE_IMSI: id_resp.mobile_id.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMSI; usim->get_imsi_vec(id_resp.mobile_id.imsi, 15); @@ -1678,9 +1883,16 @@ void nas::send_identity_response(uint32_t lcid, uint8 id_type) return; } - liblte_mme_pack_identity_response_msg(&id_resp, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); + liblte_mme_pack_identity_response_msg(&id_resp, sec_hdr_type, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); - if(pcap != NULL) { + // add security if needed + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && pdu->N_bytes > 5) { + cipher_encrypt(pdu.get()); + integrity_generate( + &k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]); + } + + if (pcap != NULL) { pcap->write_nas(pdu->msg, pdu->N_bytes); } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 18b74fafc..7d3c5b9f9 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -44,6 +44,9 @@ ue::ue() : logger(nullptr) // load FFTW wisdom srslte_dft_load(); + // save FFTW wisdom when UE exits + atexit(srslte_dft_exit); + pool = byte_buffer_pool::get_instance(); } @@ -53,8 +56,6 @@ ue::~ue() stack.reset(); byte_buffer_pool::cleanup(); - // save FFTW wisdom - srslte_dft_exit(); } int ue::init(const all_args_t& args_, srslte::logger* logger_) diff --git a/srsue/test/CMakeLists.txt b/srsue/test/CMakeLists.txt index 01136b8d5..08fca4333 100644 --- a/srsue/test/CMakeLists.txt +++ b/srsue/test/CMakeLists.txt @@ -18,8 +18,13 @@ # and at http://www.gnu.org/licenses/. # +add_subdirectory(phy) add_subdirectory(upper) +if (ENABLE_TTCN3) + add_subdirectory(ttcn3) +endif (ENABLE_TTCN3) + add_executable(metrics_test metrics_test.cc ../src/metrics_stdout.cc ../src/metrics_csv.cc) target_link_libraries(metrics_test srslte_phy srslte_common) add_test(metrics_test metrics_test -o ${CMAKE_CURRENT_BINARY_DIR}/ue_metrics.csv) diff --git a/srsue/test/mac_test.cc b/srsue/test/mac_test.cc index 9ee5a24b0..6f6631dd9 100644 --- a/srsue/test/mac_test.cc +++ b/srsue/test/mac_test.cc @@ -19,6 +19,8 @@ * */ +#include "srslte/asn1/rrc_asn1.h" +#include "srslte/asn1/rrc_asn1_utils.h" #include "srslte/common/log_filter.h" #include "srslte/common/mac_pcap.h" #include "srslte/interfaces/ue_interfaces.h" @@ -54,6 +56,9 @@ public: uint32_t get_buffer_state(const uint32_t lcid) { return ul_queues[lcid]; } int read_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) { + if (!read_enable) { + return 0; + } uint32_t len = SRSLTE_MIN(ul_queues[lcid], nof_bytes); // set payload bytes to LCID so we can check later if the scheduling was correct @@ -77,7 +82,10 @@ public: void write_pdu_mch(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes){}; uint32_t get_received_bytes() { return received_bytes; } + void disable_read() { read_enable = false; } + private: + bool read_enable = true; uint32_t received_bytes; srslte::log_filter* log; // UL queues where key is LCID and value the queue length @@ -319,6 +327,26 @@ public: uint32_t rach_problem = 0; }; +class stack_dummy : public stack_interface_mac +{ +public: + void init(mac* mac_, phy_interface_mac_lte* phy_) + { + mac_h = mac_; + phy_h = phy_; + } + void process_pdus() final { mac_h->process_pdus(); } + void wait_ra_completion(uint16_t rnti) final + { + phy_h->set_crnti(rnti); + mac_h->notify_ra_completed(); + } + +private: + phy_interface_mac_lte* phy_h; + mac* mac_h = nullptr; +}; + } // namespace srslte int mac_unpack_test() @@ -343,6 +371,7 @@ int mac_unpack_test() srslte::log_filter rlc_log("RLC"); srslte::log_filter mac_log("MAC"); + srslte::timers timers(64); mac_log.set_level(srslte::LOG_LEVEL_DEBUG); mac_log.set_hex_limit(100000); @@ -350,13 +379,15 @@ int mac_unpack_test() rlc_log.set_hex_limit(100000); // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); // create dummy DL action and grant and push MAC PDU mac_interface_phy_lte::tb_action_dl_t dl_action; @@ -379,6 +410,7 @@ int mac_unpack_test() // make sure MAC PDU thread picks up before stopping sleep(1); mac.run_tti(0); + timers.step_all(); mac.stop(); // check length of both received RLC PDUs @@ -403,14 +435,18 @@ int mac_ul_sch_pdu_test1() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -469,14 +505,18 @@ int mac_ul_logical_channel_prioritization_test1() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -580,14 +620,18 @@ int mac_ul_logical_channel_prioritization_test2() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -678,14 +722,18 @@ int mac_ul_logical_channel_prioritization_test3() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -764,14 +812,18 @@ int mac_ul_sch_pdu_with_short_bsr_test() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -840,8 +892,6 @@ int mac_ul_sch_pdu_with_short_bsr_test() // PDU with only padding BSR (long BSR) and the rest padding int mac_ul_sch_pdu_with_padding_bsr_test() { - const uint8_t tv[] = {0x3e, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - srslte::log_filter mac_log("MAC"); mac_log.set_level(srslte::LOG_LEVEL_DEBUG); mac_log.set_hex_limit(100000); @@ -850,19 +900,26 @@ int mac_ul_sch_pdu_with_padding_bsr_test() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); // create UL action and grant and push MAC PDU { + + const uint8_t tv[] = {0x3e, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + mac_interface_phy_lte::tb_action_ul_t ul_action = {}; mac_interface_phy_lte::mac_grant_ul_t mac_grant = {}; @@ -884,6 +941,41 @@ int mac_ul_sch_pdu_with_padding_bsr_test() TESTASSERT(memcmp(ul_action.tb.payload, tv, sizeof(tv)) == 0); } + // create UL action and grant and push MAC PDU + { + + const uint8_t tv[] = {0x1c, 0x42}; + + mac_interface_phy_lte::tb_action_ul_t ul_action = {}; + mac_interface_phy_lte::mac_grant_ul_t mac_grant = {}; + + mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant + mac_grant.tb.ndi_present = true; + mac_grant.tb.ndi = true; + mac_grant.pid = 2; + mac_grant.tb.tbs = 2; // give enough room for Padding BSR + int cc_idx = 0; + + // Add data to multiple LCID + mac.setup_lcid(1, 1, 1, -1, 0); + mac.setup_lcid(2, 2, 2, -1, 0); + rlc.disable_read(); + rlc.write_sdu(1, 10); + rlc.write_sdu(2, 100); + mac.run_tti(1); + + // Send grant to MAC and get action for this TB, then call tb_decoded to unlock MAC + mac.new_grant_ul(cc_idx, mac_grant, &ul_action); + + // print generated PDU + mac_log.info_hex(ul_action.tb.payload, mac_grant.tb.tbs, "Generated PDU (%d B)\n", mac_grant.tb.tbs); +#if HAVE_PCAP + pcap_handle->write_ul_crnti(ul_action.tb.payload, mac_grant.tb.tbs, 0x1001, true, 1); +#endif + + TESTASSERT(memcmp(ul_action.tb.payload, tv, sizeof(tv)) == 0); + } + // make sure MAC PDU thread picks up before stopping sleep(1); mac.run_tti(0); @@ -905,14 +997,18 @@ int mac_ul_sch_pdu_one_byte_test() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -963,14 +1059,18 @@ int mac_ul_sch_pdu_two_byte_test() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -1021,14 +1121,18 @@ int mac_ul_sch_pdu_three_byte_test() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers - phy_dummy phy; - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + phy_dummy phy; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // the actual MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); const uint16_t crnti = 0x1001; mac.set_ho_rnti(crnti, 0); @@ -1084,7 +1188,7 @@ struct ra_test { struct ra_test test; -int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti_state) +int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti_state, srslte::timers* timers) { uint32_t tti = *tti_state; @@ -1106,6 +1210,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti if (test.assume_prach_transmitted != (int)j) { phy->set_prach_tti(tti + phy->prach_delay); mac->run_tti(tti++); + timers->step_all(); } // Check MAC instructs PHY to transmit PRACH @@ -1125,6 +1230,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti mac->run_tti(tti); TESTASSERT(!SRSLTE_RNTI_ISRAR(mac->get_dl_sched_rnti(tti))); tti++; + timers->step_all(); } bool rapid_found = false; @@ -1133,6 +1239,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti mac->run_tti(tti); TESTASSERT(mac->get_dl_sched_rnti(tti) == phy->get_rar_rnti()); tti++; + timers->step_all(); // Receive RAR if (test.rar_nof_rapid > 0) { @@ -1158,6 +1265,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti mac->run_tti(tti); TESTASSERT(mac->get_dl_sched_rnti(tti) == (test.crnti ? test.crnti : test.temp_rnti)); tti++; + timers->step_all(); } if (i == test.rach_cfg.max_harq_msg3_tx) { @@ -1180,6 +1288,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti mac->run_tti(tti); TESTASSERT(mac->get_dl_sched_rnti(tti) == (test.crnti ? test.crnti : test.temp_rnti)); tti++; + timers->step_all(); if (test.msg4_enable) { if (test.crnti) { @@ -1216,6 +1325,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti phy->set_prach_tti(tti + phy->prach_delay, false); TESTASSERT(mac->get_dl_sched_rnti(tti) != temp_rnti); mac->run_tti(tti++); + timers->step_all(); } } @@ -1225,6 +1335,7 @@ int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti TESTASSERT(phy->get_crnti() == (test.crnti ? test.crnti : test.temp_rnti)); TESTASSERT(mac->get_dl_sched_rnti(tti) == (test.crnti ? test.crnti : test.temp_rnti)); tti++; + timers->step_all(); } *tti_state = tti; @@ -1254,14 +1365,17 @@ int mac_random_access_test() rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_hex_limit(100000); + srslte::timers timers(64); + // dummy layers phy_dummy phy; phy.set_log(&phy_log); - rlc_dummy rlc(&rlc_log); - rrc_dummy rrc; + rlc_dummy rlc(&rlc_log); + rrc_dummy rrc; + stack_dummy stack; // Configure default RACH parameters - asn1::rrc::rach_cfg_common_s rach_cfg = {}; + asn1::rrc::rach_cfg_common_s rach_cfg = {}; rach_cfg.preamb_info.nof_ra_preambs = asn1::rrc::rach_cfg_common_s::preamb_info_s_::nof_ra_preambs_opts::n12; rach_cfg.ra_supervision_info.preamb_trans_max = asn1::rrc::preamb_trans_max_opts::n8; rach_cfg.ra_supervision_info.ra_resp_win_size = @@ -1272,9 +1386,10 @@ int mac_random_access_test() // Configure MAC mac mac(&mac_log); - mac.init(&phy, &rlc, &rrc); - mac_interface_rrc::mac_cfg_t mac_cfg; - mac_cfg.set_rach_cfg_common(rach_cfg); + stack.init(&mac, &phy); + mac.init(&phy, &rlc, &rrc, &timers, &stack); + srslte::mac_cfg_t mac_cfg; + set_mac_cfg_t_rach_cfg_common(&mac_cfg, rach_cfg); mac.set_config(mac_cfg); // generate config for LCIDs in different LCGs than CCCH @@ -1311,11 +1426,12 @@ int mac_random_access_test() mac_log.info("\n=========== Test %d =============\n", test_id++); my_test.rach_cfg = rach_cfg; my_test.nof_prachs = rach_cfg.ra_supervision_info.preamb_trans_max.to_number(); - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); // Make sure it triggers RRC signal mac.run_tti(tti++); TESTASSERT(rrc.rach_problem == 1); + timers.step_all(); // Reset MAC mac.reset(); @@ -1329,7 +1445,7 @@ int mac_random_access_test() my_test.rar_nof_rapid = 1; my_test.nof_prachs = 1; my_test.rar_nof_invalid_rapid = rach_cfg.ra_supervision_info.ra_resp_win_size.to_number(); - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); // Test 3: RAR received but no matching RAPID. Test Msg3 retransmissions // On each HARQ retx, contention resolution timer must be restarted (5.1.5) @@ -1337,7 +1453,7 @@ int mac_random_access_test() mac_log.info("\n=========== Test %d =============\n", test_id++); my_test.rar_nof_invalid_rapid = 0; my_test.nof_msg3_retx = rach_cfg.max_harq_msg3_tx; - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); // Test 4: RAR with valid RAPID. Msg3 transmitted, Msg4 received but invalid ConRes // Contention resolution is defined in 5.1.5. If ConResID does not match, the ConRes is considered @@ -1346,7 +1462,7 @@ int mac_random_access_test() phy.reset(); my_test.nof_msg3_retx = 0; my_test.msg4_enable = true; - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); // Test 5: Msg4 received and valid ConRes. In this case a valid ConResID is received and RA procedure is successful mac_log.info("\n=========== Test %d =============\n", test_id++); @@ -1354,7 +1470,7 @@ int mac_random_access_test() my_test.msg4_valid_conres = true; my_test.check_ra_successful = true; my_test.assume_prach_transmitted = 0; - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); // Test 6: RA with existing C-RNTI (Sends C-RNTI MAC CE) // The transmission of C-RNTI MAC CE is only done if no CCCH is present (5.1.4). @@ -1366,7 +1482,7 @@ int mac_random_access_test() my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate my_test.assume_prach_transmitted = -1; my_test.send_valid_ul_grant = true; - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); // Test 7: Test Contention based Random Access. This is used eg in HO where preamble is chosen by UE. // It is similar to Test 5 because C-RNTI is available to the UE when start the RA but @@ -1377,6 +1493,7 @@ int mac_random_access_test() phy.set_crnti(0); mac.start_cont_ho(); mac.run_tti(tti++); + timers.step_all(); rrc.ho_finish = false; my_test.nof_prachs = rach_cfg.ra_supervision_info.preamb_trans_max.to_number(); my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate @@ -1384,7 +1501,7 @@ int mac_random_access_test() my_test.assume_prach_transmitted = 0; my_test.check_ra_successful = false; my_test.send_valid_ul_grant = false; - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); TESTASSERT(!rrc.ho_finish_successful && rrc.ho_finish); // Test 8: Test Contention based Random Access. Same as above but we let the procedure finish successfully. @@ -1393,11 +1510,12 @@ int mac_random_access_test() phy.set_crnti(0); mac.start_cont_ho(); mac.run_tti(tti++); + timers.step_all(); rrc.ho_finish = false; my_test.nof_prachs = 1; my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate my_test.send_valid_ul_grant = true; - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); TESTASSERT(rrc.ho_finish_successful && rrc.ho_finish); // Test 9: Test non-Contention based HO. Used in HO but preamble is given by the network. In addition to checking @@ -1406,6 +1524,7 @@ int mac_random_access_test() mac_log.info("\n=========== Test %d =============\n", test_id++); phy.set_prach_tti(tti + phy.prach_delay); mac.run_tti(tti++); + timers.step_all(); phy.set_crnti(0); rrc.ho_finish = false; my_test.preamble_idx = 3; @@ -1413,8 +1532,9 @@ int mac_random_access_test() my_test.nof_prachs = rach_cfg.ra_supervision_info.preamb_trans_max.to_number(); my_test.rar_nof_invalid_rapid = rach_cfg.ra_supervision_info.ra_resp_win_size.to_number(); my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); mac.run_tti(tti++); + timers.step_all(); TESTASSERT(!rrc.ho_finish_successful && rrc.ho_finish); // Test 10: Test non-Contention based HO. Used in HO but preamble is given by the network. We check that @@ -1422,6 +1542,7 @@ int mac_random_access_test() mac_log.info("\n=========== Test %d =============\n", test_id++); phy.set_prach_tti(tti + phy.prach_delay); mac.run_tti(tti++); + timers.step_all(); phy.set_crnti(0); rrc.ho_finish = false; my_test.preamble_idx = 3; @@ -1430,8 +1551,9 @@ int mac_random_access_test() my_test.rar_nof_invalid_rapid = 0; my_test.check_ra_successful = true; my_test.temp_rnti++; // Temporal C-RNTI has to change to avoid duplicate - TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti)); + TESTASSERT(!run_mac_ra_test(my_test, &mac, &phy, &tti, &timers)); mac.run_tti(tti++); + timers.step_all(); TESTASSERT(rrc.ho_finish_successful && rrc.ho_finish); mac.stop(); diff --git a/srsue/test/phy/CMakeLists.txt b/srsue/test/phy/CMakeLists.txt new file mode 100644 index 000000000..77dc5cff5 --- /dev/null +++ b/srsue/test/phy/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# Copyright 2013-2019 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE 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. +# +# srsLTE 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_directories( + ${Boost_INCLUDE_DIRS} + ${SEC_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR} +) + +link_directories( + ${Boost_LIBRARY_DIRS} + ${SEC_LIBRARY_DIRS} +) + +add_executable(scell_search_test scell_search_test.cc) +target_link_libraries(scell_search_test + srsue_phy + srsue_stack + srsue_upper + srsue_mac + srsue_rrc + srslte_common + srslte_phy + srslte_radio + srslte_upper + rrc_asn1 + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES}) +add_test(scell_search_test scell_search_test --duration=1 --phy_lib_log_level=0 --intra_meas_log_level=none --nof_enb=2 --cell.nof_prb=25) diff --git a/srsue/test/phy/scell_search_test.cc b/srsue/test/phy/scell_search_test.cc new file mode 100644 index 000000000..909db0fe6 --- /dev/null +++ b/srsue/test/phy/scell_search_test.cc @@ -0,0 +1,653 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Common execution parameters +static uint32_t duration_execution_s; +static srslte_cell_t cell_base = {.nof_prb = 6, + .nof_ports = 1, + .id = 0, + .cp = SRSLTE_CP_NORM, + .phich_length = SRSLTE_PHICH_NORM, + .phich_resources = SRSLTE_PHICH_R_1_6, + .frame_type = SRSLTE_FDD}; +static std::string intra_meas_log_level; +static std::string cell_list; +static int phy_lib_log_level; + +// On the Fly parameters +static int earfcn_dl; +static std::string radio_device_args; +static std::string radio_device_name; +static std::string radio_log_level; +static float rx_gain; + +// Simulation parameters +static uint32_t nof_enb; +static uint16_t cell_id_start; +static uint16_t cell_id_step; +static float channel_period_s; +static uint32_t cfi; +static float ncell_attenuation_dB; +static float channel_hst_fd_hz; +static float channel_delay_max_us; +static std::string channel_log_level; + +// Simulation Serving cell PDSCH parameters +static bool serving_cell_pdsch_enable; +static uint16_t serving_cell_pdsch_rnti; +static srslte_tm_t serving_cell_pdsch_tm; +static uint16_t serving_cell_pdsch_mcs; + +// PRB allocation helpers +static uint32_t prbset_num = 1, last_prbset_num = 1; +static uint32_t prbset_orig = 0; + +unsigned int reverse(unsigned int x) +{ + x = (((x & (uint32_t)0xaaaaaaaa) >> (uint32_t)1) | ((x & (uint32_t)0x55555555) << (uint32_t)1)); + x = (((x & (uint32_t)0xcccccccc) >> (uint32_t)2) | ((x & (uint32_t)0x33333333) << (uint32_t)2)); + x = (((x & (uint32_t)0xf0f0f0f0) >> (uint32_t)4) | ((x & (uint32_t)0x0f0f0f0f) << (uint32_t)4)); + x = (((x & (uint32_t)0xff00ff00) >> (uint32_t)8) | ((x & (uint32_t)0x00ff00ff) << (uint32_t)8)); + return ((x >> (uint32_t)16) | (x << (uint32_t)16)); +} + +uint32_t prbset_to_bitmask() +{ + uint32_t mask = 0; + auto nb = (uint32_t)ceilf((float)cell_base.nof_prb / srslte_ra_type0_P(cell_base.nof_prb)); + for (uint32_t i = 0; i < nb; i++) { + if (i >= prbset_orig && i < prbset_orig + prbset_num) { + mask = mask | ((uint32_t)0x1 << i); + } + } + return reverse(mask) >> (uint32_t)(32 - nb); +} + +// Test eNb class +class test_enb +{ +private: + srslte_enb_dl_t enb_dl; + srslte::channel_ptr channel; + cf_t* signal_buffer[SRSLTE_MAX_PORTS] = {}; + srslte::log_filter channel_log; + +public: + test_enb(const srslte_cell_t& cell, const srslte::channel::args_t& channel_args) : + enb_dl(), + channel_log("Channel pci=" + std::to_string(cell.id)) + { + channel_log.set_level(channel_log_level); + + channel = srslte::channel_ptr(new srslte::channel(channel_args, cell_base.nof_ports)); + channel->set_srate(srslte_sampling_freq_hz(cell.nof_prb)); + channel->set_logger(&channel_log); + + // Allocate buffer for eNb + for (uint32_t i = 0; i < cell_base.nof_ports; i++) { + signal_buffer[i] = (cf_t*)srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell_base.nof_prb)); + if (!signal_buffer[i]) { + ERROR("Error allocating buffer\n"); + } + } + + if (srslte_enb_dl_init(&enb_dl, signal_buffer, cell.nof_prb)) { + ERROR("Error initiating eNb downlink\n"); + } + + if (srslte_enb_dl_set_cell(&enb_dl, cell)) { + ERROR("Error setting eNb DL cell\n"); + } + + if (srslte_enb_dl_add_rnti(&enb_dl, serving_cell_pdsch_rnti)) { + ERROR("Error adding RNTI\n"); + } + } + + int work(srslte_dl_sf_cfg_t* dl_sf, + srslte_dci_cfg_t* dci_cfg, + srslte_dci_dl_t* dci, + srslte_softbuffer_tx_t** softbuffer_tx, + uint8_t** data_tx, + cf_t* baseband_buffer, + const srslte_timestamp_t& ts) + { + + int ret = SRSLTE_SUCCESS; + uint32_t sf_len = SRSLTE_SF_LEN_PRB(enb_dl.cell.nof_prb); + + srslte_enb_dl_put_base(&enb_dl, dl_sf); + + // Put PDSCH only if it is required + if (dci && dci_cfg && softbuffer_tx && data_tx) { + if (srslte_enb_dl_put_pdcch_dl(&enb_dl, dci_cfg, dci)) { + ERROR("Error putting PDCCH sf_idx=%d\n", dl_sf->tti); + ret = SRSLTE_ERROR; + } + + // Create pdsch config + srslte_pdsch_cfg_t pdsch_cfg; + if (srslte_ra_dl_dci_to_grant(&enb_dl.cell, dl_sf, serving_cell_pdsch_tm, false, dci, &pdsch_cfg.grant)) { + ERROR("Computing DL grant sf_idx=%d\n", dl_sf->tti); + ret = SRSLTE_ERROR; + } + char str[512]; + srslte_dci_dl_info(dci, str, 512); + INFO("eNb PDCCH: rnti=0x%x, %s\n", serving_cell_pdsch_rnti, str); + + for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + pdsch_cfg.softbuffers.tx[i] = softbuffer_tx[i]; + } + + // Enable power allocation + pdsch_cfg.power_scale = true; + pdsch_cfg.p_a = 0.0f; // 0 dB + pdsch_cfg.p_b = (serving_cell_pdsch_tm > SRSLTE_TM1) ? 1 : 0; // 0 dB + pdsch_cfg.rnti = serving_cell_pdsch_rnti; + pdsch_cfg.meas_time_en = false; + + if (srslte_enb_dl_put_pdsch(&enb_dl, &pdsch_cfg, data_tx) < 0) { + ERROR("Error putting PDSCH sf_idx=%d\n", dl_sf->tti); + ret = SRSLTE_ERROR; + } + srslte_pdsch_tx_info(&pdsch_cfg, str, 512); + INFO("eNb PDSCH: rnti=0x%x, %s\n", serving_cell_pdsch_rnti, str); + } + + srslte_enb_dl_gen_signal(&enb_dl); + + // Apply channel + channel->run(signal_buffer, signal_buffer, sf_len, ts); + + // Combine Tx ports + for (uint32_t i = 1; i < enb_dl.cell.nof_ports; i++) { + srslte_vec_sum_ccc(signal_buffer[0], signal_buffer[i], signal_buffer[0], sf_len); + } + + // Undo srslte_enb_dl_gen_signal scaling + float scale = sqrt(cell_base.nof_prb) / 0.05f / enb_dl.ifft->symbol_sz; + + // Apply Neighbour cell attenuation + if (enb_dl.cell.id != cell_id_start) { + float scale_dB = -ncell_attenuation_dB; + scale *= powf(10.0f, scale_dB / 20.0f); + } + + // Scale signal + srslte_vec_sc_prod_cfc(signal_buffer[0], scale, signal_buffer[0], sf_len); + + // Add signal to baseband buffer + srslte_vec_sum_ccc(signal_buffer[0], baseband_buffer, baseband_buffer, sf_len); + + return ret; + } + + ~test_enb() + { + for (uint32_t i = 0; i < enb_dl.cell.nof_ports; i++) { + if (signal_buffer[i]) { + free(signal_buffer[i]); + signal_buffer[i] = nullptr; + } + } + + srslte_enb_dl_free(&enb_dl); + } +}; + +class dummy_rrc : public srsue::rrc_interface_phy_lte +{ +public: + typedef struct { + float rsrp_avg; + float rsrp_min; + float rsrp_max; + float rsrq_avg; + float rsrq_min; + float rsrq_max; + uint32_t count; + } cell_meas_t; + + std::map cells; + + void in_sync() override {} + void out_of_sync() override {} + void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn, int pci) override + { + if (!cells.count(pci)) { + cells[pci].rsrp_min = rsrp; + cells[pci].rsrp_max = rsrp; + cells[pci].rsrp_avg = rsrp; + cells[pci].rsrq_min = rsrq; + cells[pci].rsrq_max = rsrq; + cells[pci].rsrq_avg = rsrq; + cells[pci].count = 1; + } else { + cells[pci].rsrp_min = SRSLTE_MIN(cells[pci].rsrp_min, rsrp); + cells[pci].rsrp_max = SRSLTE_MAX(cells[pci].rsrp_max, rsrp); + cells[pci].rsrp_avg = (rsrp + cells[pci].rsrp_avg * cells[pci].count) / (cells[pci].count + 1); + + cells[pci].rsrq_min = SRSLTE_MIN(cells[pci].rsrq_min, rsrq); + cells[pci].rsrq_max = SRSLTE_MAX(cells[pci].rsrq_max, rsrq); + cells[pci].rsrq_avg = (rsrq + cells[pci].rsrq_avg * cells[pci].count) / (cells[pci].count + 1); + cells[pci].count++; + } + } + + void print_stats() + { + printf("\n-- Statistics:\n"); + for (auto& e : cells) { + bool false_alarm = true; + + for (uint32_t i = 0; false_alarm && (i < nof_enb); i++) { + if (e.first == cell_id_start + cell_id_step * i) { + false_alarm = false; + } + } + + printf(" pci=%03d; count=%3d; false=%s; rsrp=%+.1f|%+.1f|%+.1fdBfs; rsrq=%+.1f|%+.1f|%+.1fdB;\n", + e.first, + e.second.count, + false_alarm ? "y" : "n", + e.second.rsrp_min, + e.second.rsrp_avg, + e.second.rsrp_max, + e.second.rsrq_min, + e.second.rsrq_avg, + e.second.rsrq_max); + } + } +}; + +// shorten boost program options namespace +namespace bpo = boost::program_options; + +int parse_args(int argc, char** argv, srsue::phy_args_t* phy_args) +{ + int ret = SRSLTE_SUCCESS; + + bpo::options_description options; + bpo::options_description common("Common execution options"); + bpo::options_description over_the_air("Over the air execution options"); + bpo::options_description simulation("Over the air execution options"); + + // clang-format off + common.add_options() + ("duration", bpo::value(&duration_execution_s)->default_value(60), "Duration of the execution in seconds") + ("cell.nof_prb", bpo::value(&cell_base.nof_prb)->default_value(100), "Cell Number of PRB") + ("intra_meas_log_level", bpo::value(&intra_meas_log_level)->default_value("none"), "Intra measurement log level (none, warning, info, debug)") + ("intra_freq_meas_len_ms", bpo::value(&phy_args->intra_freq_meas_len_ms)->default_value(20), "Intra measurement measurement length") + ("intra_freq_meas_period_ms", bpo::value(&phy_args->intra_freq_meas_period_ms)->default_value(200), "Intra measurement measurement period") + ("phy_lib_log_level", bpo::value(&phy_lib_log_level)->default_value(SRSLTE_VERBOSE_NONE), "Phy lib log level (0: none, 1: info, 2: debug)") + ("cell_list", bpo::value(&cell_list)->default_value("10,17,24,31,38,45,52"), "Comma separated neighbour PCI cell list") + ; + + over_the_air.add_options() + ("rf.dl_earfcn", bpo::value(&earfcn_dl)->default_value(-1), "DL EARFCN (setting this param enables over-the-air execution)") + ("rf.device_name", bpo::value(&radio_device_name)->default_value("auto"), "RF Device Name") + ("rf.device_args", bpo::value(&radio_device_args)->default_value("auto"), "RF Device arguments") + ("rf.log_level", bpo::value(&radio_log_level)->default_value("info"), "RF Log level (none, warning, info, debug)") + ("rf.rx_gain", bpo::value(&rx_gain)->default_value(30.0f), "RF Receiver gain in dB") + ("radio_log_level", bpo::value(&radio_log_level)->default_value("info"), "RF Log level") + ; + + simulation.add_options() + ("nof_enb", bpo::value(&nof_enb)->default_value(4), "Number of eNb") + ("cell_id_start", bpo::value(&cell_id_start)->default_value(10), "Cell id start") + ("cell_id_step", bpo::value(&cell_id_step)->default_value(7), "Cell id step") + ("cell_cfi", bpo::value(&cfi)->default_value(1), "Cell CFI") + ("channel_period_s", bpo::value(&channel_period_s)->default_value(16.8), "Channel period for HST and delay") + ("ncell_attenuation", bpo::value(&ncell_attenuation_dB)->default_value(3.0f), "Neighbour cell attenuation relative to serving cell in dB") + ("channel.hst.fd", bpo::value(&channel_hst_fd_hz)->default_value(750.0f), "Channel High Speed Train doppler in Hz. Set to 0 for disabling") + ("channel.delay_max", bpo::value(&channel_delay_max_us)->default_value(4.7f), "Maximum simulated delay in microseconds. Set to 0 for disabling") + ("channel.log_level", bpo::value(&channel_log_level)->default_value("info"), "Channel simulator logging level") + ("serving_cell_pdsch_enable", bpo::value(&serving_cell_pdsch_enable)->default_value(true), "Enable simulated PDSCH in serving cell") + ("serving_cell_pdsch_rnti", bpo::value(&serving_cell_pdsch_rnti)->default_value(0x1234), "Simulated PDSCH RNTI") + ("serving_cell_pdsch_tm", bpo::value((int*) &serving_cell_pdsch_tm)->default_value(SRSLTE_TM1), "Simulated Transmission mode 0: TM1, 1: TM2, 2: TM3, 3: TM4") + ("serving_cell_pdsch_mcs", bpo::value(&serving_cell_pdsch_mcs)->default_value(20), "Simulated PDSCH MCS") + ; + + options.add(common).add(over_the_air).add(simulation).add_options() + ("help", "Show this message") + ; + // clang-format on + + bpo::variables_map vm; + try { + bpo::store(bpo::command_line_parser(argc, argv).options(options).run(), vm); + bpo::notify(vm); + } catch (bpo::error& e) { + std::cerr << e.what() << std::endl; + ret = SRSLTE_ERROR; + } + + // help option was given or error - print usage and exit + if (vm.count("help") || ret) { + std::cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << std::endl << std::endl; + std::cout << options << std::endl << std::endl; + ret = SRSLTE_ERROR; + } + + return ret; +} + +int main(int argc, char** argv) +{ + int ret = SRSLTE_SUCCESS; + srsue::phy_args_t phy_args = {}; + + // Parse args + if (parse_args(argc, argv, &phy_args)) { + return SRSLTE_ERROR; + } + + srslte_dft_load(); + + // Common for simulation and over-the-air + auto baseband_buffer = (cf_t*)srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_MAX); + srslte_timestamp_t ts = {}; + srsue::scell::intra_measure intra_measure; + srslte::log_filter logger("intra_measure"); + dummy_rrc rrc; + srsue::phy_common common(1); + + // Simulation only + std::vector > test_enb_v; + uint8_t* data_tx[SRSLTE_MAX_TB] = {}; + srslte_softbuffer_tx_t* softbuffer_tx[SRSLTE_MAX_TB] = {}; + + // Over-the-air only + std::unique_ptr radio = nullptr; + std::unique_ptr radio_log = nullptr; + + // Set Receiver args + common.args = &phy_args; + phy_args.estimator_fil_auto = false; + phy_args.estimator_fil_order = 4; + phy_args.estimator_fil_stddev = 1.0f; + phy_args.sic_pss_enabled = false; + phy_args.interpolate_subframe_enabled = false; + phy_args.nof_rx_ant = 1; + phy_args.cfo_is_doppler = true; + phy_args.cfo_integer_enabled = false; + phy_args.cfo_correct_tol_hz = 1.0f; + phy_args.cfo_pss_ema = DEFAULT_CFO_EMA_TRACK; + phy_args.cfo_ref_mask = 1023; + phy_args.cfo_loop_bw_pss = DEFAULT_CFO_BW_PSS; + phy_args.cfo_loop_bw_ref = DEFAULT_CFO_BW_REF; + phy_args.cfo_loop_pss_tol = DEFAULT_CFO_PSS_MIN; + phy_args.cfo_loop_ref_min = DEFAULT_CFO_REF_MIN; + phy_args.cfo_loop_pss_conv = DEFAULT_PSS_STABLE_TIMEOUT; + phy_args.snr_estim_alg = "refs"; + phy_args.snr_ema_coeff = 0.1f; + + // Set phy-lib logging level + srslte_verbose = phy_lib_log_level; + + // Allocate PDSCH data and tx-soft-buffers only if pdsch is enabled and radio is not available + for (int i = 0; i < SRSLTE_MAX_TB && serving_cell_pdsch_enable && radio == nullptr; i++) { + srslte_random_t random_gen = srslte_random_init(serving_cell_pdsch_rnti); + + const size_t nof_bytes = (6144 * 16 * 3 / 8); + softbuffer_tx[i] = (srslte_softbuffer_tx_t*)calloc(sizeof(srslte_softbuffer_tx_t), 1); + if (!softbuffer_tx[i]) { + ERROR("Error allocating softbuffer_tx\n"); + ret = SRSLTE_ERROR; + } + + if (srslte_softbuffer_tx_init(softbuffer_tx[i], cell_base.nof_prb)) { + ERROR("Error initiating softbuffer_tx\n"); + ret = SRSLTE_ERROR; + } + + data_tx[i] = (uint8_t*)srslte_vec_malloc(sizeof(uint8_t) * nof_bytes); + if (!data_tx[i]) { + ERROR("Error allocating data tx\n"); + ret = SRSLTE_ERROR; + } else { + for (uint32_t j = 0; j < nof_bytes; j++) { + data_tx[i][j] = (uint8_t)srslte_random_uniform_int_dist(random_gen, 0, 255); + } + } + + srslte_random_free(random_gen); + } + + // Set cell_base id with the serving cell + uint32_t serving_cell_id = (nof_enb == 1) ? (cell_id_start + cell_id_step) : cell_id_start; + cell_base.id = serving_cell_id; + + logger.set_level(intra_meas_log_level); + + intra_measure.init(&common, &rrc, &logger); + intra_measure.set_primay_cell(serving_cell_id, cell_base); + + if (earfcn_dl >= 0) { + // Create radio log + radio_log = std::unique_ptr(new srslte::log_filter("Radio")); + radio_log->set_level(radio_log_level); + + // Create radio + radio = std::unique_ptr(new srslte::radio()); + + // Init radio + radio->init(radio_log.get(), (char*)radio_device_args.c_str(), (char*)radio_device_name.c_str(), 1); + + // Set sampling rate + radio->set_rx_srate(srslte_sampling_freq_hz(cell_base.nof_prb)); + + // Set frequency + radio->set_rx_freq(0, srslte_band_fd(earfcn_dl) * 1e6); + + } else { + // Create test eNb's if radio is not available + for (uint32_t enb_idx = 0; enb_idx < nof_enb; enb_idx++) { + // Initialise cell + srslte_cell_t cell = cell_base; + cell.id = (cell_id_start + enb_idx * cell_id_step) % 504; + + // Initialise channel and push back + srslte::channel::args_t channel_args; + channel_args.enable = true; + channel_args.hst_enable = (channel_hst_fd_hz != 0.0f); + channel_args.hst_init_time_s = (float)(enb_idx * channel_period_s) / (float)nof_enb; + channel_args.hst_period_s = (float)channel_period_s; + channel_args.hst_fd_hz = channel_hst_fd_hz; + channel_args.delay_enable = (channel_delay_max_us != 0.0f); + channel_args.delay_min_us = 0; + channel_args.delay_max_us = channel_delay_max_us; + channel_args.delay_period_s = (uint32)channel_period_s; + channel_args.delay_init_time_s = (enb_idx * channel_period_s) / nof_enb; + test_enb_v.push_back(std::unique_ptr(new test_enb(cell, channel_args))); + + // Add cell to known cells + if (cell_list.empty()) { + intra_measure.add_cell(cell.id); + } + } + } + + // Parse cell list + if (cell_list == "all") { + // Add all possible cells + for (int i = 0; i < 504; i++) { + intra_measure.add_cell(i); + } + } else if (cell_list == "none") { + // Do nothing + } else if (!cell_list.empty()) { + // Remove spaces from neightbour cell list + std::size_t p1 = cell_list.find(' '); + while (p1 != std::string::npos) { + cell_list.erase(p1); + p1 = cell_list.find(' '); + } + + // Add cell to known cells + std::stringstream ss(cell_list); + while (ss.good()) { + std::string substr; + getline(ss, substr, ','); + intra_measure.add_cell((uint32_t)strtoul(substr.c_str(), nullptr, 10)); + } + } + + // Run loop + for (uint32_t sf_idx = 0; sf_idx < duration_execution_s * 1000; sf_idx++) { + srslte_dl_sf_cfg_t sf_cfg_dl = {}; + sf_cfg_dl.tti = sf_idx % 10240; + sf_cfg_dl.cfi = cfi; + sf_cfg_dl.sf_type = SRSLTE_SF_NORM; + + // Clean buffer + bzero(baseband_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_MAX); + + if (radio) { + // Receive radio + radio->rx_now(&baseband_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb), &ts); + } else { + // Run eNb simulator + bool put_pdsch = serving_cell_pdsch_enable; + + for (auto& enb : test_enb_v) { + if (put_pdsch) { + // Reset pdsch put flag + put_pdsch = false; + + // DCI Configuration + srslte_dci_dl_t dci; + srslte_dci_cfg_t dci_cfg; + dci_cfg.srs_request_enabled = false; + dci_cfg.ra_format_enabled = false; + dci_cfg.multiple_csi_request_enabled = false; + + // DCI Fixed values + dci.pid = 0; + dci.pinfo = 0; + dci.rnti = serving_cell_pdsch_rnti; + dci.is_tdd = false; + dci.is_dwpts = false; + dci.is_ra_order = false; + dci.tb_cw_swap = false; + dci.pconf = false; + dci.power_offset = false; + dci.tpc_pucch = false; + dci.ra_preamble = false; + dci.ra_mask_idx = false; + dci.srs_request = false; + dci.srs_request_present = false; + dci.cif_present = false; + dci_cfg.cif_enabled = false; + + // Set PRB Allocation type + dci.alloc_type = SRSLTE_RA_ALLOC_TYPE0; + prbset_num = (int)ceilf((float)cell_base.nof_prb / srslte_ra_type0_P(cell_base.nof_prb)); + last_prbset_num = prbset_num; + dci.type0_alloc.rbg_bitmask = prbset_to_bitmask(); + dci.location.L = 0; + dci.location.ncce = 0; + + // Set TB + if (serving_cell_pdsch_tm < SRSLTE_TM3) { + dci.format = SRSLTE_DCI_FORMAT1; + dci.tb[0].mcs_idx = serving_cell_pdsch_mcs; + dci.tb[0].rv = 0; + dci.tb[0].ndi = false; + dci.tb[0].cw_idx = 0; + dci.tb[1].mcs_idx = 0; + dci.tb[1].rv = 1; + } else if (serving_cell_pdsch_tm == SRSLTE_TM3) { + dci.format = SRSLTE_DCI_FORMAT2A; + for (uint32_t i = 0; i < SRSLTE_MAX_TB; i++) { + dci.tb[i].mcs_idx = serving_cell_pdsch_mcs; + dci.tb[i].rv = 0; + dci.tb[i].ndi = false; + dci.tb[i].cw_idx = i; + } + } else if (serving_cell_pdsch_tm == SRSLTE_TM4) { + dci.format = SRSLTE_DCI_FORMAT2; + dci.pinfo = 0; + for (uint32_t i = 0; i < SRSLTE_MAX_TB; i++) { + dci.tb[i].mcs_idx = serving_cell_pdsch_mcs; + dci.tb[i].rv = 0; + dci.tb[i].ndi = false; + dci.tb[i].cw_idx = i; + } + } else { + ERROR("Wrong transmission mode (%d)\n", serving_cell_pdsch_tm); + } + enb->work(&sf_cfg_dl, &dci_cfg, &dci, softbuffer_tx, data_tx, baseband_buffer, ts); + } else { + enb->work(&sf_cfg_dl, nullptr, nullptr, nullptr, nullptr, baseband_buffer, ts); + } + } + } + + srslte_timestamp_add(&ts, 0, 0.001f); + + intra_measure.write(sf_idx, baseband_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb)); + if (sf_idx % 1000 == 0) { + printf("Done %.1f%%\n", (double)sf_idx * 100.0 / ((double)duration_execution_s * 1000.0)); + } + } + + // Stop + intra_measure.stop(); + + rrc.print_stats(); + if (baseband_buffer) { + free(baseband_buffer); + } + + for (auto& ptr : data_tx) { + if (ptr) { + free(ptr); + } + } + for (auto& sb : softbuffer_tx) { + if (sb) { + srslte_softbuffer_tx_free(sb); + free(sb); + } + } + + atexit(srslte_dft_exit); + + if (ret) { + printf("Error\n"); + } else { + printf("Ok\n"); + } + + return ret; +} diff --git a/srsue/test/ttcn3/CMakeLists.txt b/srsue/test/ttcn3/CMakeLists.txt new file mode 100644 index 000000000..b9add7c2e --- /dev/null +++ b/srsue/test/ttcn3/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# Copyright 2013-2019 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE 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. +# +# srsLTE 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/. +# + +add_subdirectory(src) +add_subdirectory(test) diff --git a/srsue/test/ttcn3/README.md b/srsue/test/ttcn3/README.md new file mode 100644 index 000000000..4364d7222 --- /dev/null +++ b/srsue/test/ttcn3/README.md @@ -0,0 +1,23 @@ +srsUE conformance testing +========================= + +This folder includes an srsUE extension that allows to test +the upper-layer protocol stack against the UE conformance tests specified +by 3GPP/ETSI in TS 36.523 [1]. + +The tester itself is built with Eclipse Titan [2] using the 3GPP EUTRA (LTE/EPC) UE Test Suites [3]. It is, however, +not part of the srsLTE repository. + +The extensions present in this folder add a basic system simulator (SS) that talks over an ideal PHY to the +fully unmodified UE upper-layer stack. It SS itself interfaces over multiple TCP/IP sockets to the TTCN3 tester, i.e., +implements (a subset of) the interfaces specified in [1]. + + +Resources +--------- + +[1] https://www.etsi.org/deliver/etsi_ts/136500_136599/13652301 + +[2] https://projects.eclipse.org/projects/tools.titan + +[3] http://www.ttcn-3.org/index.php/downloads/publicts/publicts-3gpp diff --git a/srsue/test/ttcn3/hdr/dut_utils.h b/srsue/test/ttcn3/hdr/dut_utils.h new file mode 100644 index 000000000..eb7d3d7c0 --- /dev/null +++ b/srsue/test/ttcn3/hdr/dut_utils.h @@ -0,0 +1,77 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +/*! \brief Utility functions for the DUT. + * + */ + +#ifndef SRSUE_TTCN3_DUT_UTILS_H +#define SRSUE_TTCN3_DUT_UTILS_H + +#include +#include + +std::string get_filename_with_tc_name(const std::string& str, const uint32_t run_id, const std::string tc_name) +{ + // split base path into components + std::set delims; + delims.insert('/'); + std::vector result; + char const* pch = str.c_str(); + char const* start = pch; + for (; *pch; ++pch) { + if (delims.find(*pch) != delims.end()) { + if (start != pch) { + std::string str(start, pch); + result.push_back(str); + } else { + result.push_back(""); + } + start = pch + 1; + } + } + result.push_back(start); + + // prepend TC name to last element (the actual filename) + stringstream filename_ss; + filename_ss << tc_name << "_" + << "run" << run_id << "_" << result.back(); + + std::string final_path; + std::vector::iterator path_it; + for (path_it = result.begin() + 1; path_it != --result.end(); ++path_it) { + final_path += "/"; + final_path += *path_it; + } + final_path += "/"; + final_path += filename_ss.str(); + + return final_path; +} + +std::string get_tc_name(const std::string& str) +{ + // split after dot + std::string::size_type pos = str.find('.'); + return (pos == str.npos ? str : str.substr(pos + 1, -1)); +} + +#endif // SRSUE_TTCN3_DUT_UTILS_H diff --git a/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h b/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h new file mode 100644 index 000000000..de2e97931 --- /dev/null +++ b/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h @@ -0,0 +1,151 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_LTE_PHY_H +#define SRSUE_TTCN3_LTE_PHY_H + +#include "srsue/hdr/phy/ue_lte_phy_base.h" +#include "srsue/hdr/ue.h" +#include "ttcn3_interfaces.h" +#include +#include + +using namespace srsue; +using namespace srslte; + +namespace srsue { + +class lte_ttcn3_phy : public ue_lte_phy_base +{ +public: + typedef struct { + srslte_cell_t info; + float power; + uint32_t earfcn; + } cell_t; + typedef std::vector cell_list_t; + + lte_ttcn3_phy(srslte::logger* logger_); + ~lte_ttcn3_phy(); + + int init(const phy_args_t& args_, stack_interface_phy_lte* stack_, syssim_interface_phy* syssim_); + + int init(const phy_args_t& args_, stack_interface_phy_lte* stack_, radio_interface_phy* radio_); + + // ue_phy_base interface + int init(const phy_args_t& args_); + void stop(); + void set_earfcn(std::vector earfcns); + void force_freq(float dl_freq, float ul_freq); + void wait_initialize(); + void start_plot(); + void get_metrics(phy_metrics_t* m); + std::string get_type(); + + // The interface for the SS + void set_cell_map(const cell_list_t& cells_); + + // phy_interface_rrc_lte + void get_current_cell(srslte_cell_t* cell_, uint32_t* earfcn_ = NULL); + uint32_t get_current_earfcn(); + uint32_t get_current_pci(); + void set_config_scell(asn1::rrc::scell_to_add_mod_r10_s* scell_config); + void enable_pregen_signals(bool enable); + void set_activation_deactivation_scell(uint32_t cmd); + void + set_config(srslte::phy_cfg_t& config, uint32_t cc_idx = 0, uint32_t earfcn = 0, srslte_cell_t* cell_info = nullptr); + void set_config_tdd(srslte_tdd_config_t& tdd_config); + void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs){}; + void set_config_mbsfn_sib13(const srslte::sib13_t& sib13){}; + void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch){}; + + // Measurements interface + void meas_reset(); + int meas_start(uint32_t earfcn, int pci = -1); + int meas_stop(uint32_t earfcn, int pci = -1); + + // phy_interface_mac_lte + void set_mch_period_stop(uint32_t stop){}; + + // Cell search and selection procedures + cell_search_ret_t cell_search(phy_cell_t* found_cell); + bool cell_select(phy_cell_t* cell); + bool cell_is_camping(); + void reset(); + + // phy_interface_mac_lte + void configure_prach_params(); + void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm); + prach_info_t prach_get_info(); + void sr_send(); + int sr_last_tx_tti(); + + // phy_interface_mac_common + void set_crnti(uint16_t rnti); + void set_timeadv_rar(uint32_t ta_cmd); + void set_timeadv(uint32_t ta_cmd); + void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti); + uint32_t get_current_tti(); + float get_phr(); + float get_pathloss_db(); + + // phy_interface_syssim + void set_current_tti(uint32_t tti); + + void new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t ul_mac_grant); + void new_tb(const srsue::mac_interface_phy_lte::mac_grant_dl_t, const uint8_t* data); + + // Radio interface + void radio_overflow(); + void radio_failure(); + + void run_tti(); + +private: + srslte::logger* logger = nullptr; + srslte::log_filter log; + + // The current cell + cell_list_t cells; + cell_t pcell = {}; + + phy_cfg_t phy_cfg = {}; + + uint32_t current_tti = 0; + uint16_t current_temp_rnti = 0; + uint32_t cc_idx = 0; + + int prach_tti_tx = -1; + + int sr_tx_tti = -1; + bool sr_pending = false; + + std::mutex mutex; + + uint32_t ra_trans_cnt = 0; + + stack_interface_phy_lte* stack = nullptr; + syssim_interface_phy* syssim = nullptr; +}; + +} // namespace srsue + +#endif \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_helpers.h b/srsue/test/ttcn3/hdr/ttcn3_helpers.h new file mode 100644 index 000000000..940e45edd --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_helpers.h @@ -0,0 +1,360 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +/*! \brief This class provides helpers for encoding JSON-formated responses + * for TTCN3. + * + */ + +#ifndef SRSUE_TTCN3_HELPERS_H +#define SRSUE_TTCN3_HELPERS_H + +#include "rapidjson/document.h" // rapidjson's DOM-style API +#include "rapidjson/prettywriter.h" // for stringify JSON +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace rapidjson; + +class ttcn3_helpers +{ +public: + typedef struct { + bool rb_is_srb; + uint8_t rb_id; + uint32_t ul_value; + uint32_t dl_value; + } pdcp_count_t; + + static std::string get_ctrl_cnf(const std::string protocol_, const std::string version_, const std::string addr_) + { + Document resp; + resp.SetObject(); + + // Create members of common object + Value ctrl(kObjectType); + + // The connection ID object + Value conn_id(kObjectType); + + // Protocol + Value protocol(protocol_.c_str(), resp.GetAllocator()); + conn_id.AddMember("Protocol", protocol, resp.GetAllocator()); + + // Version + + Value ipAddr(kObjectType); + Value version(version_.c_str(), resp.GetAllocator()); + Value addr(addr_.c_str(), resp.GetAllocator()); + + if (version_ == "V4") { + Value v4(kObjectType); + v4.AddMember("Addr", addr, resp.GetAllocator()); + ipAddr.AddMember("V4", v4, resp.GetAllocator()); + } else if (version_ == "V6") { + Value v6(kObjectType); + v6.AddMember("Addr", addr, resp.GetAllocator()); + ipAddr.AddMember("V6", v6, resp.GetAllocator()); + } else { + fprintf(stderr, "Unsupported protocol version: %s.\n", version_.c_str()); + return std::string(""); + } + + // Local + Value local(kObjectType); + local.AddMember("IpAddr", ipAddr, resp.GetAllocator()); + + if (protocol_ == "udp") { + local.AddMember("Port", 33, resp.GetAllocator()); + } + + // Remote + Value rem(kObjectType); + + // Add members to Connection ID + conn_id.AddMember("Local", local, resp.GetAllocator()); + conn_id.AddMember("Remote", rem, resp.GetAllocator()); + + // The Indication object + Value ind(kObjectType); + Value ind_protocol_val(kObjectType); + ind_protocol_val.AddMember("SocketCnf", true, resp.GetAllocator()); + if (protocol_ == "udp") { + ind.AddMember("UDP", ind_protocol_val, resp.GetAllocator()); + } else if (protocol_ == "icmpv6") { + ind.AddMember("ICMP", ind_protocol_val, resp.GetAllocator()); + } else { + fprintf(stderr, "Unsupported protocol %s.\n", protocol_.c_str()); + return std::string(""); + } + + ctrl.AddMember("ConnectionId", conn_id, resp.GetAllocator()); + ctrl.AddMember("Ind", ind, resp.GetAllocator()); + + resp.AddMember("CTRL", ctrl, resp.GetAllocator()); + + // JSON-ize + StringBuffer buffer; + Writer writer(buffer); + resp.Accept(writer); + + // Return as std::string + return std::string(buffer.GetString()); + } + + static std::string get_drbmux_common_ind_cnf() + { + Document resp; + resp.SetObject(); + + resp.AddMember("Confirm", true, resp.GetAllocator()); + + // JSON-ize + StringBuffer buffer; + Writer writer(buffer); + resp.Accept(writer); + + // Return as std::string + return std::string(buffer.GetString()); + } + + static std::string get_pdcp_count_response(const std::string cell_, + const std::vector& bearers) + { + Document resp; + resp.SetObject(); + + // Create members of common object + + // Cell + Value cell(cell_.c_str(), resp.GetAllocator()); + + // RoutingInfo + Value routing_info(kObjectType); + routing_info.AddMember("None", true, resp.GetAllocator()); + + // TimingInfo + Value timing_info(kObjectType); + timing_info.AddMember("Now", true, resp.GetAllocator()); + + // Result + Value result(kObjectType); + result.AddMember("Success", true, resp.GetAllocator()); + + // Now, create the common object itself and add members + Value common(kObjectType); + common.AddMember("CellId", cell, resp.GetAllocator()); + common.AddMember("RoutingInfo", routing_info, resp.GetAllocator()); + common.AddMember("TimingInfo", timing_info, resp.GetAllocator()); + common.AddMember("Result", result, resp.GetAllocator()); + + // Add all bearers + rapidjson::Value bearer_array(rapidjson::kArrayType); + std::vector::const_iterator it; + for (it = bearers.begin(); it != bearers.end(); ++it) { + // SRB0 + Value radio_bearer_id(kObjectType); + radio_bearer_id.AddMember(it->rb_is_srb ? "Srb" : "Drb", it->rb_id, resp.GetAllocator()); + + Value ul(kObjectType); + Value rb_format_ul(it->rb_is_srb ? "PdcpCount_Srb" : "PdcpCount_DrbLongSQN", resp.GetAllocator()); + ul.AddMember("Format", rb_format_ul, resp.GetAllocator()); + + // convert int to sstream, then to RapidJSON value and add as member + stringstream value_ss; + value_ss << std::bitset<32>(it->ul_value); + Value ul_value(value_ss.str().c_str(), resp.GetAllocator()); + ul.AddMember("Value", ul_value, resp.GetAllocator()); + + Value dl(kObjectType); + Value rb_format_dl(it->rb_is_srb ? "PdcpCount_Srb" : "PdcpCount_DrbLongSQN", resp.GetAllocator()); + dl.AddMember("Format", rb_format_dl, resp.GetAllocator()); + + // do the same conversion for the DL value + value_ss.str(""); + value_ss.clear(); + value_ss << std::bitset<32>(it->dl_value); + Value dl_value(value_ss.str().c_str(), resp.GetAllocator()); + dl.AddMember("Value", dl_value, resp.GetAllocator()); + + // The Get object combines the information of all requested bearer + Value get_element(kObjectType); + get_element.AddMember("RadioBearerId", radio_bearer_id, resp.GetAllocator()); + get_element.AddMember("UL", ul, resp.GetAllocator()); + get_element.AddMember("DL", dl, resp.GetAllocator()); + + bearer_array.PushBack(get_element, resp.GetAllocator()); + } + + // The confirm object + Value confirm_key(kObjectType); + + // Add array + confirm_key.AddMember("Get", bearer_array, resp.GetAllocator()); + + Value confirm(kObjectType); + confirm.AddMember("PdcpCount", confirm_key, resp.GetAllocator()); + + resp.AddMember("Common", common, resp.GetAllocator()); + resp.AddMember("Confirm", confirm, resp.GetAllocator()); + + // JSON-ize + StringBuffer buffer; + Writer writer(buffer); + resp.Accept(writer); + + // Return as std::string + return std::string(buffer.GetString()); + } + + static std::string get_basic_sys_req_cnf(const std::string cell_, const std::string confirm_key_) + { + Document resp; + resp.SetObject(); + + // Create members of common object + + // Cell + Value cell(cell_.c_str(), resp.GetAllocator()); + + // RoutingInfo + Value routing_info(kObjectType); + routing_info.AddMember("None", true, resp.GetAllocator()); + + // TimingInfo + Value timing_info(kObjectType); + timing_info.AddMember("Now", true, resp.GetAllocator()); + + // Result + Value result(kObjectType); + result.AddMember("Success", true, resp.GetAllocator()); + + // Now, create the common object itself and add members + Value common(kObjectType); + common.AddMember("CellId", cell, resp.GetAllocator()); + common.AddMember("RoutingInfo", routing_info, resp.GetAllocator()); + common.AddMember("TimingInfo", timing_info, resp.GetAllocator()); + common.AddMember("Result", result, resp.GetAllocator()); + + // The confirm object + Value confirm_key(confirm_key_.c_str(), resp.GetAllocator()); + Value confirm_val(true); + Value confirm(kObjectType); + confirm.AddMember(confirm_key, confirm_val, resp.GetAllocator()); + + resp.AddMember("Common", common, resp.GetAllocator()); + resp.AddMember("Confirm", confirm, resp.GetAllocator()); + + // JSON-ize + StringBuffer buffer; + Writer writer(buffer); + resp.Accept(writer); + + // Return as std::string + return std::string(buffer.GetString()); + } + + static std::string + get_sys_req_cnf_with_time(const std::string cell_, const std::string confirm_key_, const uint32_t tti) + { + Document resp; + resp.SetObject(); + + // Create members of common object + + // Cell + Value cell(cell_.c_str(), resp.GetAllocator()); + + // RoutingInfo + Value routing_info(kObjectType); + routing_info.AddMember("None", true, resp.GetAllocator()); + + // TimingInfo + + // SFN + uint32_t sfn = tti / 10; + Value sfn_key(kObjectType); + sfn_key.AddMember("Number", sfn, resp.GetAllocator()); + + // Actual subframe index + uint32_t sf_idx = tti % 10; + Value sf_idx_key(kObjectType); + sf_idx_key.AddMember("Number", sf_idx, resp.GetAllocator()); + + // Put it all together + Value subframe_key(kObjectType); + subframe_key.AddMember("SFN", sfn_key, resp.GetAllocator()); + subframe_key.AddMember("Subframe", sf_idx_key, resp.GetAllocator()); + + Value timing_info(kObjectType); + timing_info.AddMember("SubFrame", subframe_key, resp.GetAllocator()); + + // Result + Value result(kObjectType); + result.AddMember("Success", true, resp.GetAllocator()); + + // Now, create the common object itself and add members + Value common(kObjectType); + common.AddMember("CellId", cell, resp.GetAllocator()); + common.AddMember("RoutingInfo", routing_info, resp.GetAllocator()); + common.AddMember("TimingInfo", timing_info, resp.GetAllocator()); + common.AddMember("Result", result, resp.GetAllocator()); + + // The confirm object + Value confirm_key(confirm_key_.c_str(), resp.GetAllocator()); + Value confirm_val(true); + Value confirm(kObjectType); + confirm.AddMember(confirm_key, confirm_val, resp.GetAllocator()); + + resp.AddMember("Common", common, resp.GetAllocator()); + resp.AddMember("Confirm", confirm, resp.GetAllocator()); + + // JSON-ize + StringBuffer buffer; + Writer writer(buffer); + resp.Accept(writer); + + // Return as std::string + return std::string(buffer.GetString()); + } + + static bool requires_confirm(Document& document) + { + const Value& a = document["Common"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + const Value& config_flag = b["CnfFlag"]; + assert(config_flag.IsBool()); + + return config_flag.GetBool(); + } +}; + +#endif // SRSUE_TTCN3_HELPERS_H diff --git a/srsue/test/ttcn3/hdr/ttcn3_interfaces.h b/srsue/test/ttcn3/hdr/ttcn3_interfaces.h new file mode 100644 index 000000000..3f0177c7f --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_interfaces.h @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_INTERFACES_H +#define SRSUE_TTCN3_INTERFACES_H + +#include "srslte/common/common.h" +#include "srslte/interfaces/ue_interfaces.h" + +// Interface used by system interface to communicate with main component +class syssim_interface +{ +public: + virtual void tc_start(const char* name) = 0; + virtual void tc_end() = 0; + virtual void power_off_ue() = 0; + virtual void switch_on_ue() = 0; + virtual void switch_off_ue() = 0; + virtual void enable_data() = 0; + virtual void disable_data() = 0; + virtual void set_cell_config(std::string cell_name, uint32_t earfcn, srslte_cell_t cell, const float power) = 0; + virtual void set_cell_attenuation(std::string cell_name, const float attenuation) = 0; + virtual void add_bcch_pdu(srslte::unique_byte_buffer_t pdu) = 0; + virtual void add_ccch_pdu(srslte::unique_byte_buffer_t pdu) = 0; + virtual void add_dcch_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0; + virtual void add_pch_pdu(srslte::unique_byte_buffer_t pdu) = 0; + virtual void add_srb(uint32_t lcid, srslte::pdcp_config_t pdcp_config) = 0; + virtual void del_srb(uint32_t lcid) = 0; + virtual uint32_t get_tti() = 0; + virtual int set_as_security(const uint32_t lcid, + const std::array k_rrc_enc, + const std::array k_rrc_int, + const std::array k_up_enc, + const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0; +}; + +class syssim_interface_phy +{ +public: + virtual void prach_indication(uint32_t preamble_index, const uint32_t& cell_id) = 0; + virtual void sr_req(uint32_t tti_tx) = 0; + // 0; virtual void + virtual void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti) = 0; +}; + +class phy_interface_syssim +{ +public: + virtual void set_current_tti(uint32_t tti) = 0; + virtual uint16_t get_dl_sched_rnti(uint32_t tti) = 0; + virtual void new_grant_ul(const srsue::mac_interface_phy_lte::mac_grant_ul_t grant) = 0; + virtual void new_tb(const srsue::mac_interface_phy_lte::mac_grant_dl_t mac_grant, const uint8_t* data) = 0; +}; + +#endif // SRSUE_TTCN3_INTERFACES_H \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h b/srsue/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h new file mode 100644 index 000000000..78f0ee1f0 --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_ip_ctrl_interface.h @@ -0,0 +1,125 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_IP_CTRL_INTERFACE_H +#define SRSUE_TTCN3_IP_CTRL_INTERFACE_H + +#include "rapidjson/document.h" +#include "rapidjson/prettywriter.h" +#include "srslte/common/netsource_handler.h" +#include "srslte/phy/io/netsource.h" +#include "ttcn3_helpers.h" + +using namespace rapidjson; + +// The IP CTRL interface to the IP_PTC +class ttcn3_ip_ctrl_interface : public netsource_handler +{ +public: + ttcn3_ip_ctrl_interface() : netsource_handler("TTCN3_IP_CTRL_IF"){}; + ~ttcn3_ip_ctrl_interface(){}; + + void init(srslte::log* log_, std::string net_ip_, uint32_t net_port_) + { + net_ip = net_ip_; + net_port = net_port_; + log = log_; + initialized = true; + log->debug("Initialized.\n"); + } + +private: + void run_thread() + { + // open TCP socket + if (srslte_netsource_init(&net_source, net_ip.c_str(), net_port, SRSLTE_NETSOURCE_TCP)) { + fprintf(stderr, "Error creating input TCP socket at port %d\n", net_port); + exit(-1); + } + + log->info("Listening on %s:%d for incoming connections ..\n", net_ip.c_str(), net_port); + + running = true; + + int n; + while (run_enable) { + log->debug("Reading from IP_CTRL port ..\n"); + n = srslte_netsource_read(&net_source, rx_buf->begin(), RX_BUF_SIZE); + if (n > 0) { + rx_buf->at(n) = '\0'; + + Document document; + if (document.Parse((char*)rx_buf->begin()).HasParseError()) { + log->error_hex(rx_buf->begin(), n, "Error parsing incoming data.\n"); + break; + } + assert(document.IsObject()); + + // Pretty-print + StringBuffer buffer; + PrettyWriter writer(buffer); + document.Accept(writer); + log->info("Received %d bytes\n%s\n", n, (char*)buffer.GetString()); + + // Get message + if (document.HasMember("RoutingInfo")) { + log->info("Received RoutingInfo\n"); + handle_routing_info(document); + } else { + log->error("Received unknown request.\n"); + } + } else if (n == 0) { + log->error("Receiving null from network\n"); + } else { + log->error("Error receiving from network\n"); + } + } + + running = false; + + srslte_netsource_free(&net_source); + } + + void handle_routing_info(Document& document) + { + // get CTRL + const Value& routes = document["RoutingInfo"]; + assert(routes.IsArray()); + + // iterate over all routes + for (Value::ConstValueIterator itr = routes.Begin(); itr != routes.End(); ++itr) { + assert(itr->HasMember("IpInfo")); + + // printf("Configuring attenuation of %s to %ddB\n", id.GetString(), att["Value"].GetInt()); + + // FIXME: actually do configuration + } + + // What else to check? + + std::string resp = ttcn3_helpers::get_drbmux_common_ind_cnf(); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } +}; + +#endif // SRSUE_TTCN3_IP_CTRL_INTERFACE_H \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_ip_sock_interface.h b/srsue/test/ttcn3/hdr/ttcn3_ip_sock_interface.h new file mode 100644 index 000000000..00951f056 --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_ip_sock_interface.h @@ -0,0 +1,134 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_IP_SOCK_INTERFACE_H +#define SRSUE_TTCN3_IP_SOCK_INTERFACE_H + +// The IP Socket interface to the IP_PTC +class ttcn3_ip_sock_interface : public netsource_handler +{ +public: + ttcn3_ip_sock_interface() : netsource_handler("TTCN3_IP_SOCK_IF"){}; + ~ttcn3_ip_sock_interface(){}; + + void init(srslte::log* log_, std::string net_ip_, uint32_t net_port_) + { + net_ip = net_ip_; + net_port = net_port_; + log = log_; + initialized = true; + log->debug("Initialized.\n"); + } + +private: + void run_thread() + { + if (!initialized) { + fprintf(stderr, "IP_SOCK interface not initialized. Exiting.\n"); + exit(-1); + } + + // open TCP socket + if (srslte_netsource_init(&net_source, net_ip.c_str(), net_port, SRSLTE_NETSOURCE_TCP)) { + fprintf(stderr, "Error creating input TCP socket at port %d\n", net_port); + exit(-1); + } + + log->info("Listening on %s:%d for incoming connections ..\n", net_ip.c_str(), net_port); + + running = true; + + int n; + while (run_enable) { + log->debug("Reading from IP_SOCK port ..\n"); + n = srslte_netsource_read(&net_source, rx_buf->begin(), RX_BUF_SIZE); + if (n > 0) { + rx_buf->at(n) = '\0'; + + Document document; + if (document.Parse((char*)rx_buf->begin()).HasParseError()) { + log->error_hex(rx_buf->begin(), n, "Error parsing incoming data.\n"); + break; + } + assert(document.IsObject()); + + // Pretty-print + StringBuffer buffer; + PrettyWriter writer(buffer); + document.Accept(writer); + log->info("Received %d bytes\n%s\n", n, (char*)buffer.GetString()); + + // Get message + if (document.HasMember("CTRL")) { + log->info("Received CTRL command.\n"); + handle_ctrl(document); + } else { + log->error("Received unknown request.\n"); + } + } else if (n == 0) { + log->error("Receiving null from network\n"); + } else { + log->error("Error receiving from network\n"); + // exit(-1); + } + } + + running = false; + + srslte_netsource_free(&net_source); + } + + void handle_ctrl(Document& document) + { + // get CTRL + const Value& ctrl = document["CTRL"]; + assert(ctrl.HasMember("ConnectionId")); + + const Value& conn_id = ctrl["ConnectionId"]; + assert(conn_id.HasMember("Protocol")); + + const Value& protocol = conn_id["Protocol"]; + assert(protocol.IsString()); + + // Get IP version and addr + std::string ip_version; + const Value& local = conn_id["Local"]; + assert(local.HasMember("IpAddr")); + const Value& ipAddr = local["IpAddr"]; + if (ipAddr.HasMember("V4")) { + ip_version = "V4"; + } else if (ipAddr.HasMember("V6")) { + ip_version = "V6"; + } + assert(ipAddr[ip_version.c_str()].HasMember("Addr")); + const Value& addr = ipAddr[ip_version.c_str()]["Addr"]; + + // Todo: Handle command + + // Send response + string resp = ttcn3_helpers::get_ctrl_cnf(protocol.GetString(), ip_version, addr.GetString()); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } +}; + +#endif // SRSUE_TTCN3_IP_SOCK_INTERFACE_H \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h b/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h new file mode 100644 index 000000000..0f2cf8dad --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h @@ -0,0 +1,173 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_SRB_INTERFACE_H +#define SRSUE_TTCN3_SRB_INTERFACE_H + +#include "srslte/common/buffer_pool.h" +#include "srslte/common/common.h" +#include "srslte/common/pdu.h" +#include "ttcn3_interfaces.h" +#include + +using namespace srslte; + +// The SRB interface +class ttcn3_srb_interface : public netsource_handler +{ +public: + ttcn3_srb_interface() : syssim(nullptr), pool(byte_buffer_pool::get_instance()), netsource_handler("TTCN3_SRB_IF"){}; + ~ttcn3_srb_interface(){}; + + void init(syssim_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_) + { + syssim = syssim_; + log = log_; + net_ip = net_ip_; + net_port = net_port_; + + initialized = true; + log->debug("Initialized.\n"); + } + + void tx(unique_byte_buffer_t pdu) + { + if (running) { + log->info_hex(pdu->msg, pdu->N_bytes, "Sending %d B to Titan\n", pdu->N_bytes); + srslte_netsource_write(&net_source, (void*)pdu->msg, pdu->N_bytes); + } else { + log->error("Trying to transmit but port not connected.\n"); + } + } + +private: + void run_thread() + { + if (!initialized) { + fprintf(stderr, "SRB interface not initialized. Exiting.\n"); + exit(-1); + } + + // open TCP socket + if (srslte_netsource_init(&net_source, net_ip.c_str(), net_port, SRSLTE_NETSOURCE_TCP)) { + fprintf(stderr, "Error creating input TCP socket at port %d\n", net_port); + exit(-1); + } + + running = true; + + int n; + while (run_enable) { + log->debug("Reading from SRB port ..\n"); + n = srslte_netsource_read(&net_source, rx_buf->begin(), RX_BUF_SIZE); + if (n > 0) { + rx_buf->at(n) = '\0'; + + log->debug_hex(rx_buf->begin(), n, "Received %d B from remote.\n", n); + + // Chop incoming msg, first two bytes are length of the JSON + // (see IPL4_EUTRA_SYSTEM_Definitions.ttcn + uint16_t json_len = ((uint16_t)rx_buf->at(0) << 8) | rx_buf->at(1); + + // Copy JSON from received buffer and null-terminate + char json[json_len + 1]; + memcpy(json, &rx_buf->at(2), json_len); + json[json_len] = '\0'; + + // The data part after the JSON starts right here but handling + // is done in the respective functions + uint16_t rx_buf_offset = json_len + 2; + + Document document; + if (document.Parse(json).HasParseError()) { + log->error_hex((uint8*)json, json_len, "Error parsing incoming data.\n"); + break; + } + assert(document.IsObject()); + + // Pretty-print + StringBuffer buffer; + PrettyWriter writer(buffer); + document.Accept(writer); + log->info("Received JSON with %d B\n%s\n", json_len, (char*)buffer.GetString()); + + // check for common + assert(document.HasMember("Common")); + assert(document["Common"].IsObject()); + + // Check for request type + assert(document.HasMember("RrcPdu")); + assert(document["RrcPdu"].IsObject()); + + // Get request type + const Value& rrcpdu = document["RrcPdu"]; + if (rrcpdu.HasMember("Ccch")) { + rx_buf_offset += 2; + handle_ccch_pdu(document, &rx_buf->at(rx_buf_offset), n - rx_buf_offset); + } else if (rrcpdu.HasMember("Dcch")) { + rx_buf_offset += 2; + uint32_t lcid = 1; + handle_dcch_pdu(document, lcid, &rx_buf->at(rx_buf_offset), n - rx_buf_offset); + } else { + log->error("Received unknown request.\n"); + } + } else if (n == 0) { + log->error("Receiving null from network\n"); + } else { + log->error("Error receiving from network\n"); + } + } + running = false; + + srslte_netsource_free(&net_source); + } + + // Todo: move to SYSSIM + void handle_ccch_pdu(Document& document, const uint8_t* payload, const uint16_t len) + { + log->info_hex(payload, len, "Received CCCH RRC PDU\n"); + + // pack into byte buffer + unique_byte_buffer_t pdu = pool_allocate_blocking; + pdu->N_bytes = len; + memcpy(pdu->msg, payload, pdu->N_bytes); + + syssim->add_ccch_pdu(std::move(pdu)); + } + + // Todo: move to SYSSIM + void handle_dcch_pdu(Document& document, const uint16_t lcid, const uint8_t* payload, const uint16_t len) + { + log->info_hex(payload, len, "Received DCCH RRC PDU\n"); + + // pack into byte buffer + unique_byte_buffer_t pdu = pool_allocate_blocking; + pdu->N_bytes = len; + memcpy(pdu->msg, payload, pdu->N_bytes); + + syssim->add_dcch_pdu(lcid, std::move(pdu)); + } + + syssim_interface* syssim = nullptr; + byte_buffer_pool* pool = nullptr; +}; + +#endif // SRSUE_TTCN3_SRB_INTERFACE_H \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h b/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h new file mode 100644 index 000000000..c85bb3252 --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h @@ -0,0 +1,603 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_SYS_INTERFACE_H +#define SRSUE_TTCN3_SYS_INTERFACE_H + +#include "srslte/common/buffer_pool.h" +#include "ttcn3_helpers.h" +#include "ttcn3_interfaces.h" + +using namespace srslte; + +// The EUTRA.SYS interface +class ttcn3_sys_interface : public netsource_handler +{ +public: + ttcn3_sys_interface() : netsource_handler("TTCN3_SYS_IF"){}; + ~ttcn3_sys_interface(){}; + + void init(syssim_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_) + { + syssim = syssim_; + net_ip = net_ip_; + net_port = net_port_; + log = log_; + initialized = true; + log->debug("Initialized.\n"); + pool = byte_buffer_pool::get_instance(); + } + +private: + void handle_request_cell_basic(Document& document, const uint8_t* payload, const uint16_t len) + { + if (document["Request"]["Cell"]["AddOrReconfigure"]["Basic"].HasMember("StaticCellInfo")) { + // Extract EARFCN + const Value& earfcn = + document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["StaticCellInfo"]["Downlink"]["Earfcn"]; + assert(earfcn.IsInt()); + + // Extract cell config + const Value& common_config = document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["StaticCellInfo"]["Common"]; + const Value& dl_config = document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["StaticCellInfo"]["Downlink"]; + const Value& phy_dl_config = document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["PhysicalLayerConfigDL"]; + + srslte_cell_t cell = {}; + cell.id = common_config["PhysicalCellId"].GetInt(); + cell.cp = (strcmp(dl_config["CyclicPrefix"].GetString(), "normal") == 0) ? SRSLTE_CP_NORM : SRSLTE_CP_EXT; + cell.nof_ports = + (strcmp(phy_dl_config["AntennaGroup"]["AntennaInfoCommon"]["R8"]["antennaPortsCount"].GetString(), "an1") == + 0) + ? 1 + : 2; + cell.nof_prb = (strcmp(dl_config["Bandwidth"].GetString(), "n25") == 0) ? 25 : 0; + cell.phich_length = + (strcmp(phy_dl_config["Phich"]["PhichConfig"]["R8"]["phich_Duration"].GetString(), "normal") == 0) + ? SRSLTE_PHICH_NORM + : SRSLTE_PHICH_EXT; + cell.phich_resources = + (strcmp(phy_dl_config["Phich"]["PhichConfig"]["R8"]["phich_Resource"].GetString(), "one") == 0) + ? SRSLTE_PHICH_R_1 + : SRSLTE_PHICH_R_1_6; + log->info("DL EARFCN is %d with n_prb=%d\n", earfcn.GetInt(), cell.nof_prb); + + const Value& ref_power = + document["Request"]["Cell"]["AddOrReconfigure"]["Basic"]["InitialCellPower"]["MaxReferencePower"]; + assert(ref_power.IsInt()); + + // That is the cellId or name that the testsuites uses to refer to a specific cell + const Value& cell_name = document["Common"]["CellId"]; + assert(cell_name.IsString()); + + // Now configure cell + syssim->set_cell_config(cell_name.GetString(), earfcn.GetInt(), cell, ref_power.GetInt()); + + // Pull out SIBs and send to syssim + uint16_t consumed_bytes = 0; + const uint8_t* payload_ptr = payload; + while (consumed_bytes < len) { + uint16_t tb_len = ((uint16_t)payload_ptr[0] << 8) | payload_ptr[1]; + payload_ptr += 2; + + unique_byte_buffer_t sib = pool_allocate_blocking; + memcpy(sib->msg, payload_ptr, tb_len); + payload_ptr += tb_len; + sib->N_bytes = tb_len; + + // Push to main component + log->info_hex(sib->msg, sib->N_bytes, "Received BCCH DL-SCH\n"); + syssim->add_bcch_pdu(std::move(sib)); + + consumed_bytes = payload_ptr - payload; + } + + // Create response for template car_CellConfig_CNF(CellId_Type p_CellId) + std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_name.GetString(), "Cell"); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } + } + + void handle_request_cell_active(Document& document, const uint8_t* payload, const uint16_t len) + { + // Create response for template car_CellConfig_CNF(CellId_Type p_CellId) + std::string cell_id = document["Common"]["CellId"].GetString(); + + std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id, "Cell"); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } + + void handle_request_cell(Document& document, const uint8_t* payload, const uint16_t len) + { + // get Cmd and make sure it has MMI + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + // Handle cell creation + if (document["Request"]["Cell"].HasMember("AddOrReconfigure")) { + if (document["Request"]["Cell"]["AddOrReconfigure"].HasMember("Basic")) { + // basic information for a cell (e.g. broadcasting) + handle_request_cell_basic(document, payload, len); + } else if (document["Request"]["Cell"]["AddOrReconfigure"].HasMember("Active")) { + // additional configuration for active cell (i.e. cell being capable to receive RACH preamble) + handle_request_cell_active(document, payload, len); + } + } else if (document["Request"]["Cell"].HasMember("Release")) { + log->info("Received cell release command\n"); + // do nothing more + } + } + + void handle_request_l1_mac_ind_ctrl(Document& document) + { + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + const Value& cell_id = a["CellId"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + // check request + const Value& req = document["Request"]; + assert(req.HasMember("L1MacIndCtrl")); + + const Value& mac_ind_ctrl = req["L1MacIndCtrl"]; + + if (mac_ind_ctrl.HasMember("HarqError")) { + assert(mac_ind_ctrl["HarqError"].IsString()); + bool harq_error = (strcmp(mac_ind_ctrl["HarqError"].GetString(), "enable") == 0) ? true : false; + log->info("Setting HarqError to %s\n", harq_error ? "True" : "False"); + } + + if (ttcn3_helpers::requires_confirm(document)) { + std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id.GetString(), "L1MacIndCtrl"); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } + } + + void handle_request_radio_bearer_list(Document& document) + { + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + const Value& cell_id = a["CellId"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + // check request + const Value& req = document["Request"]; + assert(req.HasMember("RadioBearerList")); + + const Value& bearers = req["RadioBearerList"]; + assert(bearers.IsArray()); + + // iterate over all bearers and configure them + for (Value::ConstValueIterator itr = bearers.Begin(); itr != bearers.End(); ++itr) { + assert(itr->HasMember("Id")); + const Value& id = (*itr)["Id"]; + if (id.HasMember("Srb")) { + const Value& config = (*itr)["Config"]; + if (config.HasMember("AddOrReconfigure")) { + uint32_t lcid = id["Srb"].GetInt(); + if (lcid > 0) { + log->info("Configure SRB%d\n", lcid); + pdcp_config_t pdcp_cfg = {.bearer_id = static_cast(lcid), + .rb_type = PDCP_RB_IS_SRB, + .tx_direction = SECURITY_DIRECTION_DOWNLINK, + .rx_direction = SECURITY_DIRECTION_UPLINK, + .sn_len = PDCP_SN_LEN_5}; + syssim->add_srb(lcid, pdcp_cfg); + } + } else if (config.HasMember("Release")) { + log->info("Releasing SRB%d\n", id["Srb"].GetInt()); + uint32_t lcid = id["Srb"].GetInt(); + syssim->del_srb(lcid); + } else { + log->error("Unknown config.\n"); + } + } else if (id.HasMember("Drb")) { + log->info("Configure DRB%d\n", id["Drb"].GetInt()); + } + + // FIXME: actually do configuration + } + + std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id.GetString(), "RadioBearerList"); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } + + void handle_request_cell_attenuation_list(Document& document) + { + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + const Value& cell_id = a["CellId"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + // check request + const Value& req = document["Request"]; + assert(req.HasMember("CellAttenuationList")); + + const Value& cells = req["CellAttenuationList"]; + assert(cells.IsArray()); + + // iterate over all bearers and configure them + for (Value::ConstValueIterator itr = cells.Begin(); itr != cells.End(); ++itr) { + assert(itr->HasMember("CellId")); + const Value& id = (*itr)["CellId"]; + + assert(itr->HasMember("Attenuation")); + const Value& att = (*itr)["Attenuation"]; + + float att_value = 0; + if (att.HasMember("Value")) { + att_value = att["Value"].GetInt(); + } else if (att.HasMember("Off")) { + // is there other values than Off=True? + assert(att["Off"].GetBool() == true); + if (att["Off"].GetBool() == true) { + // use high attenuation value (-145dB RX power as per TS 36.508 Sec 6.2.2.1-1 is a non-suitable Off cell) + att_value = 90.0; + } + } + + log->info("Configuring attenuation of %s to %.2f dB\n", id.GetString(), att_value); + syssim->set_cell_attenuation(id.GetString(), att_value); + } + + std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id.GetString(), "CellAttenuationList"); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } + + void handle_request_pdcp_count(Document& document) + { + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + const Value& cell_id = a["CellId"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + // check request + const Value& req = document["Request"]; + assert(req.HasMember("PdcpCount")); + + const Value& pdcp_count = req["PdcpCount"]; + assert(pdcp_count.HasMember("Get")); + + const Value& get = pdcp_count["Get"]; + assert(get.HasMember("AllRBs")); + + // prepare response to SS + std::vector bearers; + ttcn3_helpers::pdcp_count_t srb1; + srb1.rb_is_srb = true; + srb1.rb_id = 1; + srb1.dl_value = 0; + srb1.ul_value = 1; + bearers.push_back(srb1); + + std::string resp = ttcn3_helpers::get_pdcp_count_response(cell_id.GetString(), bearers); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } + + void handle_request_as_security(Document& document) + { + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + const Value& cell_id = a["CellId"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + const Value& config_flag = b["CnfFlag"]; + assert(config_flag.IsBool()); + + // check request + const Value& req = document["Request"]; + assert(req.HasMember("AS_Security")); + + // check AS security start + const Value& as_sec = req["AS_Security"]; + if (as_sec.HasMember("StartRestart")) { + // get integrity algo + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo = {}; + std::string int_algo_string = as_sec["StartRestart"]["Integrity"]["Algorithm"].GetString(); + if (int_algo_string == "eia0") { + integ_algo = srslte::INTEGRITY_ALGORITHM_ID_EIA0; + } else if (int_algo_string == "eia1") { + integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; + } else if (int_algo_string == "eia2") { + integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2; + } else { + log->error("Unsupported integrity algorithm %s\n", int_algo_string.c_str()); + } + + // get integrity key + std::string integ_key_string = as_sec["StartRestart"]["Integrity"]["KRRCint"].GetString(); + std::array k_rrc_int = get_key_from_string(integ_key_string); + log->debug_hex(k_rrc_int.data(), k_rrc_int.size(), "K_rrc_int"); + + // get enc algo + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo = {}; + std::string cipher_algo_string = as_sec["StartRestart"]["Ciphering"]["Algorithm"].GetString(); + if (cipher_algo_string == "eea0") { + cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; + } else if (int_algo_string == "eea1") { + cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1; + } else if (int_algo_string == "eea2") { + cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; + } else { + log->error("Unsupported ciphering algorithm %s\n", cipher_algo_string.c_str()); + } + + // get cipher key + std::string cipher_key_string = as_sec["StartRestart"]["Ciphering"]["KRRCenc"].GetString(); + std::array k_rrc_enc = get_key_from_string(cipher_key_string); + log->debug_hex(k_rrc_enc.data(), k_rrc_enc.size(), "K_rrc_enc"); + + // get UP enc key + std::string up_enc_key_string = as_sec["StartRestart"]["Ciphering"]["KUPenc"].GetString(); + std::array k_up_enc = get_key_from_string(up_enc_key_string); + log->debug_hex(k_up_enc.data(), k_up_enc.size(), "K_UP_enc"); + + // get LCID + uint32_t lcid = 0; + if (as_sec["StartRestart"]["Ciphering"].HasMember("ActTimeList")) { + const Value& act_time_list = as_sec["StartRestart"]["Ciphering"]["ActTimeList"]; + if (act_time_list.IsArray()) { + for (Value::ConstValueIterator itr = act_time_list.Begin(); itr != act_time_list.End(); ++itr) { + if (itr->HasMember("RadioBearerId") && (*itr)["RadioBearerId"].HasMember("Srb")) { + lcid = (*itr)["RadioBearerId"]["Srb"].GetInt(); + } + } + } + } + + // configure SS to use AS security + syssim->set_as_security(lcid, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); + } + + if (config_flag.GetBool() == true) { + std::string resp = ttcn3_helpers::get_basic_sys_req_cnf(cell_id.GetString(), "AS_Security"); + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } else { + log->info("Skipping response for AS_Security message.\n"); + } + } + + std::array get_key_from_string(const std::string& str) + { + std::array key = {}; + if (str.size() == 128) { + for (int i = 0; i < 16; i++) { + std::string byte_string(str, i * 8, 8); + key.at(i + 16) = std::stoul(byte_string, 0, 2); + } + } + return key; + } + + void handle_request_enquire_timing(Document& document) + { + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + const Value& cell_id = a["CellId"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + // check request + const Value& req = document["Request"]; + assert(req.HasMember("EnquireTiming")); + + std::string resp = + ttcn3_helpers::get_sys_req_cnf_with_time(cell_id.GetString(), "EnquireTiming", syssim->get_tti()); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } + + void handle_request_paging(Document& document, const uint8_t* payload, const uint16_t len) + { + const Value& a = document["Common"]; + + assert(a.HasMember("CellId")); + const Value& cell_id = a["CellId"]; + + // check cnf flag + assert(a.HasMember("ControlInfo")); + const Value& b = a["ControlInfo"]; + assert(b.HasMember("CnfFlag")); + + // check request + const Value& req = document["Request"]; + assert(req.HasMember("Paging")); + + // Pack payload into + // Inform SYSSIM about paging + + uint16_t consumed_bytes = 0; + const uint8_t* payload_ptr = payload; + + uint16_t tb_len = ((uint16_t)payload_ptr[0] << 8) | payload_ptr[1]; + payload_ptr += 2; + + unique_byte_buffer_t pch = pool_allocate_blocking; + memcpy(pch->msg, payload_ptr, tb_len); + payload_ptr += tb_len; + pch->N_bytes = tb_len; + + // Push to main component + log->info_hex(pch->msg, pch->N_bytes, "Received PCH DL-SCH\n"); + syssim->add_pch_pdu(std::move(pch)); + + if (ttcn3_helpers::requires_confirm(document)) { + std::string resp = ttcn3_helpers::get_sys_req_cnf_with_time(cell_id.GetString(), "Paging", syssim->get_tti()); + + log->info("Sending %s to tester (%zd B)\n", resp.c_str(), resp.length()); + srslte_netsource_write(&net_source, (char*)resp.c_str(), resp.length()); + } else { + log->info("Skipping response for Paging message.\n"); + } + } + + void run_thread() + { + if (!initialized) { + fprintf(stderr, "SYS interface not initialized. Exiting.\n"); + exit(-1); + } + + // open TCP socket + if (srslte_netsource_init(&net_source, net_ip.c_str(), net_port, SRSLTE_NETSOURCE_TCP)) { + fprintf(stderr, "Error creating input TCP socket at port %d\n", net_port); + exit(-1); + } + + log->info("Listening on %s:%d for incoming connections ..\n", net_ip.c_str(), net_port); + + running = true; + + int n; + while (run_enable) { + log->debug("Reading from SYS port ..\n"); + n = srslte_netsource_read(&net_source, rx_buf->begin(), RX_BUF_SIZE); + if (n > 0) { + rx_buf->at(n) = '\0'; + + log->debug("Received %d B from remote.\n", n); + + // Chop incoming msg, first two bytes are length of the JSON + // (see IPL4_EUTRA_SYSTEM_Definitions.ttcn + uint16_t json_len = ((uint16_t)rx_buf->at(0) << 8) | rx_buf->at(1); + + // Copy JSON from received buffer and null-terminate + char json[json_len + 1]; + memcpy(json, &rx_buf->at(2), json_len); + json[json_len] = '\0'; + + // The data part after the JSON starts right here but handling + // is done in the respective functions + uint16_t rx_buf_offset = json_len + 2; + + Document document; + if (document.Parse(json).HasParseError()) { + log->error_hex((uint8*)json, json_len, "Error parsing incoming data.\n"); + break; + } + assert(document.IsObject()); + + // Pretty-print + StringBuffer buffer; + PrettyWriter writer(buffer); + document.Accept(writer); + log->info("Received %d bytes\n%s\n", json_len, (char*)buffer.GetString()); + + // check for common + assert(document.HasMember("Common")); + assert(document["Common"].IsObject()); + + // Check for request type + assert(document.HasMember("Request")); + assert(document["Request"].IsObject()); + + // Get request type + const Value& request = document["Request"]; + if (request.HasMember("Cell")) { + log->info("Received Cell request.\n"); + handle_request_cell(document, &rx_buf->at(rx_buf_offset), n - rx_buf_offset); + } else if (request.HasMember("L1MacIndCtrl")) { + log->info("Received L1MacIndCtrl request.\n"); + handle_request_l1_mac_ind_ctrl(document); + } else if (request.HasMember("RadioBearerList")) { + log->info("Received RadioBearerList request.\n"); + handle_request_radio_bearer_list(document); + } else if (request.HasMember("CellAttenuationList")) { + log->info("Received CellAttenuationList request.\n"); + handle_request_cell_attenuation_list(document); + } else if (request.HasMember("PdcpCount")) { + log->info("Received PdcpCount request.\n"); + handle_request_pdcp_count(document); + } else if (request.HasMember("AS_Security")) { + log->info("Received AS_Security request.\n"); + handle_request_as_security(document); + } else if (request.HasMember("EnquireTiming")) { + log->info("Received EnquireTiming request.\n"); + handle_request_enquire_timing(document); + } else if (request.HasMember("Paging")) { + log->info("Received Paging request.\n"); + handle_request_paging(document, &rx_buf->at(rx_buf_offset), n - rx_buf_offset); + } else { + log->error("Received unknown request.\n"); + } + } else { + log->error("Error receiving from network\n"); + } + } + running = false; + + srslte_netsource_free(&net_source); + } + + phy_interface_syssim* phy = nullptr; + syssim_interface* syssim = nullptr; + byte_buffer_pool* pool = nullptr; +}; + +#endif // SRSUE_TTCN3_SYS_INTERFACE_H \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_syssim.h b/srsue/test/ttcn3/hdr/ttcn3_syssim.h new file mode 100644 index 000000000..5fda05da5 --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_syssim.h @@ -0,0 +1,901 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_SYSSIM_H +#define SRSUE_TTCN3_SYSSIM_H + +#include "dut_utils.h" +#include "srslte/common/netsource_handler.h" +#include "srslte/common/pdu_queue.h" +#include "srslte/upper/pdcp.h" +#include "srslte/upper/rlc.h" +#include "ttcn3_ip_ctrl_interface.h" +#include "ttcn3_ip_sock_interface.h" +#include "ttcn3_srb_interface.h" +#include "ttcn3_sys_interface.h" +#include "ttcn3_ue.h" +#include "ttcn3_ut_interface.h" +#include +#include + +#define TTCN3_CRNTI (0x1001) + +class ttcn3_syssim : public thread, + public syssim_interface_phy, + public syssim_interface, + public rrc_interface_rlc, + public rlc_interface_pdcp, + public rrc_interface_pdcp, + public srslte::pdu_queue::process_callback +{ +public: + ttcn3_syssim(srslte::logger_file* logger_file_) : + mac_msg_ul(20, &ss_mac_log), + mac_msg_dl(20, &ss_mac_log), + timers(8), + pdus(128), + logger(logger_file_), + logger_file(logger_file_), + pool(byte_buffer_pool::get_instance()), + thread("TTCN3_SYSSIM"), + rlc(&ss_rlc_log), + pdcp(&ss_pdcp_log){}; + + ~ttcn3_syssim(){}; + + void init(const all_args_t& args_) + { + args = args_; + + // Make sure to get SS logging as well + if (args.log.filename == "stdout") { + logger = &logger_stdout; + } + + // init and configure logging + log.init("SS ", logger); + ut_log.init("UT ", logger); + sys_log.init("SYS ", logger); + ip_sock_log.init("IP_S", logger); + ip_ctrl_log.init("IP_C", logger); + srb_log.init("SRB ", logger); + ss_mac_log.init("SS-MAC", logger); + ss_rlc_log.init("SS-RLC", logger); + ss_pdcp_log.init("SS-PDCP", logger); + + log.set_level(args.log.all_level); + ut_log.set_level(args.log.all_level); + sys_log.set_level(args.log.all_level); + ip_sock_log.set_level(args.log.all_level); + ip_ctrl_log.set_level(args.log.all_level); + srb_log.set_level(args.log.all_level); + ss_mac_log.set_level(args.log.all_level); + ss_rlc_log.set_level(args.log.all_level); + ss_pdcp_log.set_level(args.log.all_level); + + log.set_hex_limit(args.log.all_hex_limit); + ut_log.set_hex_limit(args.log.all_hex_limit); + sys_log.set_hex_limit(args.log.all_hex_limit); + ip_sock_log.set_hex_limit(args.log.all_hex_limit); + ip_ctrl_log.set_hex_limit(args.log.all_hex_limit); + srb_log.set_hex_limit(args.log.all_hex_limit); + ss_mac_log.set_hex_limit(args.log.all_hex_limit); + ss_rlc_log.set_hex_limit(args.log.all_hex_limit); + ss_pdcp_log.set_hex_limit(args.log.all_hex_limit); + + // init system interfaces to tester + ut.init(this, &ut_log, "0.0.0.0", 2222); + sys.init(this, &sys_log, "0.0.0.0", 2223); + ip_sock.init(&ip_sock_log, "0.0.0.0", 2224); + ip_ctrl.init(&ip_ctrl_log, "0.0.0.0", 2225); + srb.init(this, &srb_log, "0.0.0.0", 2226); + + ut.start(-2); + sys.start(-2); + ip_sock.start(-2); + ip_ctrl.start(-2); + srb.start(-2); + + pdus.init(this, &log); + rlc.init(&pdcp, this, &timers, 0 /* RB_ID_SRB0 */); + pdcp.init(&rlc, this, nullptr); + } + + void stop() + { + + running = false; + + if (ue != NULL) { + ue->stop(); + } + + // Stopping system interface + ut.stop(); + sys.stop(); + ip_sock.stop(); + ip_ctrl.stop(); + srb.stop(); + } + + void reset() + { + rlc.reset(); + pdcp.reset(); + cells.clear(); + pcell = {}; + } + + // Called from UT before starting testcase + void tc_start(const char* name) + { + if (ue == nullptr) { + // strip testsuite name + std::string tc_name = get_tc_name(name); + + // Make a copy of the UE args for this run + all_args_t local_args = args; + + // set up logging + if (args.log.filename == "stdout") { + logger = &logger_stdout; + } else { + logger_file->init(get_filename_with_tc_name(local_args.log.filename, run_id, tc_name).c_str(), -1); + logger = logger_file; + } + + log.info("Initializing UE ID=%d for TC=%s\n", run_id, tc_name.c_str()); + log.console("Initializing UE ID=%d for TC=%s\n", run_id, tc_name.c_str()); + + // Patch UE config + local_args.stack.pcap.filename = get_filename_with_tc_name(args.stack.pcap.filename, run_id, tc_name); + local_args.stack.pcap.nas_filename = get_filename_with_tc_name(args.stack.pcap.nas_filename, run_id, tc_name); + + // bring up UE + ue = std::unique_ptr(new ttcn3_ue()); + if (ue->init(local_args, logger, this, tc_name)) { + ue->stop(); + ue.reset(nullptr); + std::string err("Couldn't initialize UE.\n"); + log.error("%s\n", err.c_str()); + log.console("%s\n", err.c_str()); + return; + } + + // Start simulator thread + running = true; + start(); + } else { + log.error("UE hasn't been deallocated properly because TC didn't finish correctly.\n"); + log.console("UE hasn't been deallocated properly because TC didn't finish correctly.\n"); + } + } + + void tc_end() + { + if (ue != NULL) { + // ask periodic thread to stop + running = false; + + log.info("Deinitializing UE ID=%d\n", run_id); + log.console("Deinitializing UE ID=%d\n", run_id); + ue->stop(); + + // wait until SS main thread has terminated before resetting UE + wait_thread_finish(); + ue.reset(); + + // Reset SS' RLC and PDCP + reset(); + + logger_file->stop(); + + run_id++; + } else { + log.error("UE is not allocated. Nothing needs to be done.\n"); + log.console("UE is not allocated. Nothing needs to be done.\n"); + } + } + + void power_off_ue() + { + // only return after new UE instance is up and running + } + + void switch_on_ue() + { + if (ue != nullptr) { + log.info("Switching on UE ID=%d\n", run_id); + log.console("Switching on UE ID=%d\n", run_id); + + // Trigger attach procedure + ue->switch_on(); + } else { + log.error("UE not initialized. Can't switch UE on.\n"); + } + } + + void switch_off_ue() + { + if (ue != nullptr) { + log.info("Switching off UE ID=%d\n", run_id); + log.console("Switching off UE ID=%d\n", run_id); + ue->switch_off(); + } else { + log.error("UE not initialized. Can't switch UE off.\n"); + } + } + + void enable_data() + { + if (ue) { + log.info("Enabling data services on UE ID=%d\n", run_id); + ue->enable_data(); + } + } + + void disable_data() + { + if (ue) { + log.info("Disabling data services on UE ID=%d\n", run_id); + ue->disable_data(); + } + } + + // Interface for PHY + void prach_indication(uint32_t preamble_index_, const uint32_t& cell_id) + { + // store TTI for providing UL grant for Msg3 transmission + prach_tti = tti; + prach_preamble_index = preamble_index_; + + // update active pcell (chosen by UE) in syssim + for (auto& cell : cells) { + if (cell.cell.id == cell_id) { + pcell = cell; + break; + } + } + } + + void send_rar(uint32_t preamble_index) + { + log.info("Sending RAR for RAPID=%d\n", preamble_index); + + // Prepare RAR grant + uint8_t grant_buffer[64] = {}; + srslte_dci_rar_grant_t rar_grant = {}; + rar_grant.tpc_pusch = 3; + srslte_dci_rar_pack(&rar_grant, grant_buffer); + + // Create MAC PDU and add RAR subheader + srslte::rar_pdu rar_pdu; + rar_buffer.clear(); + + const int rar_pdu_len = 64; + rar_pdu.init_tx(&rar_buffer, rar_pdu_len); + rar_pdu.set_backoff(11); // Backoff of 480ms to prevent UE from PRACHing too fast + if (rar_pdu.new_subh()) { + rar_pdu.get()->set_rapid(preamble_index); + rar_pdu.get()->set_ta_cmd(0); + rar_pdu.get()->set_temp_crnti(crnti); + rar_pdu.get()->set_sched_grant(grant_buffer); + } + rar_pdu.write_packet(rar_buffer.msg); + rar_buffer.N_bytes = rar_pdu_len; + + // Prepare grant and pass all to MAC + mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; + dl_grant.pid = get_pid(tti); + dl_grant.rnti = 0x1; // must be a valid RAR-RNTI + dl_grant.tb[0].tbs = rar_buffer.N_bytes; + dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); + + // send grant and pass payload to TB data (grant contains length) + ue->new_tb(dl_grant, rar_buffer.msg); + + // reset last PRACH transmission tti + prach_tti = -1; + } + + void send_msg3_grant() + { + log.info("Sending Msg3 grant for C-RNTI=%d\n", crnti); + mac_interface_phy_lte::mac_grant_ul_t ul_grant = {}; + + ul_grant.tb.tbs = 32; + ul_grant.tb.ndi_present = true; + ul_grant.tb.ndi = get_ndi_for_new_ul_tx(tti); + ul_grant.rnti = crnti; + ul_grant.pid = get_pid(tti); + + ue->new_grant_ul(ul_grant); + } + + void sr_req(uint32_t tti_tx) + { + log.info("Received SR from PHY\n"); + + // Provide new UL grant to UE + mac_interface_phy_lte::mac_grant_ul_t ul_grant = {}; + ul_grant.tb.tbs = 100; // FIXME: reasonable size? + ul_grant.tb.ndi_present = true; + ul_grant.tb.ndi = get_ndi_for_new_ul_tx(tti); + ul_grant.rnti = crnti; + ul_grant.pid = get_pid(tti); + + ue->new_grant_ul(ul_grant); + } + + void tx_pdu(const uint8_t* payload, const int len, const uint32_t tx_tti) + { + + if (payload == NULL) { + ss_mac_log.error("Received NULL as PDU payload. Dropping.\n"); + return; + } + + // Parse MAC + mac_msg_ul.init_rx(len, true); + mac_msg_ul.parse_packet((uint8_t*)payload); + + while (mac_msg_ul.next()) { + assert(mac_msg_ul.get()); + if (mac_msg_ul.get()->is_sdu()) { + // Route logical channel + ss_mac_log.info_hex(mac_msg_ul.get()->get_sdu_ptr(), + mac_msg_ul.get()->get_payload_size(), + "PDU: rnti=0x%x, lcid=%d, %d bytes\n", + 0xdead, + mac_msg_ul.get()->get_sdu_lcid(), + mac_msg_ul.get()->get_payload_size()); + + // Push PDU to our own RLC (needed to handle status reporting, etc. correctly + ss_mac_log.info_hex(mac_msg_ul.get()->get_sdu_ptr(), + mac_msg_ul.get()->get_payload_size(), + "Route PDU to LCID=%d (%d B)\n", + mac_msg_ul.get()->get_sdu_lcid(), + mac_msg_ul.get()->get_payload_size()); + rlc.write_pdu( + mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size()); + + // Save contention resolution if lcid == 0 + if (mac_msg_ul.get()->get_sdu_lcid() == 0) { + int nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN; + if (mac_msg_ul.get()->get_payload_size() >= (uint32_t)nbytes) { + uint8_t* ue_cri_ptr = (uint8_t*)&conres_id; + uint8_t* pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the + for (int i = 0; i < nbytes; i++) { + ue_cri_ptr[nbytes - i - 1] = pkt_ptr[i]; + } + ss_mac_log.info_hex(ue_cri_ptr, nbytes, "Contention resolution ID:\n"); + } else { + ss_mac_log.error("Received CCCH UL message of invalid size=%d bytes\n", + mac_msg_ul.get()->get_payload_size()); + } + } + } + } + mac_msg_ul.reset(); + + /* Process CE after all SDUs because we need to update BSR after */ + bool bsr_received = false; + while (mac_msg_ul.next()) { + assert(mac_msg_ul.get()); + if (!mac_msg_ul.get()->is_sdu()) { + // Process MAC Control Element + bsr_received |= process_ce(mac_msg_ul.get()); + } + } + } + + bool process_ce(srslte::sch_subh* subh) + { + + uint16_t rnti = dl_rnti; + + uint32_t buff_size[4] = {0, 0, 0, 0}; + float phr = 0; + int32_t idx = 0; + uint16_t old_rnti = 0; + bool is_bsr = false; + switch (subh->ce_type()) { + case srslte::sch_subh::PHR_REPORT: + phr = subh->get_phr(); + ss_mac_log.info("CE: Received PHR from rnti=0x%x, value=%.0f\n", rnti, phr); +#if 0 + //sched->ul_phr(rnti, (int) phr); + //metrics_phr(phr); +#endif + break; + case srslte::sch_subh::CRNTI: + old_rnti = subh->get_c_rnti(); + ss_mac_log.info("CE: Received C-RNTI from temp_rnti=0x%x, rnti=0x%x\n", rnti, old_rnti); +#if 0 + if (sched->ue_exists(old_rnti)) { + rrc->upd_user(rnti, old_rnti); + rnti = old_rnti; + } else { + Error("Updating user C-RNTI: rnti=0x%x already released\n", old_rnti); + } +#endif + break; + case srslte::sch_subh::TRUNC_BSR: + case srslte::sch_subh::SHORT_BSR: + idx = subh->get_bsr(buff_size); + if (idx == -1) { + ss_mac_log.error("Invalid Index Passed to lc groups\n"); + break; + } +#if 0 + for (uint32_t i=0;iul_bsr(rnti, lc_groups[idx][i], buff_size[idx]); + + } +#endif + ss_mac_log.info("CE: Received %s BSR rnti=0x%x, lcg=%d, value=%d\n", + subh->ce_type() == srslte::sch_subh::SHORT_BSR ? "Short" : "Trunc", + rnti, + idx, + buff_size[idx]); + is_bsr = true; + break; + case srslte::sch_subh::LONG_BSR: + subh->get_bsr(buff_size); +#if 0 + for (idx=0;idx<4;idx++) { + for (uint32_t i=0;iul_bsr(rnti, lc_groups[idx][i], buff_size[idx]); + } + } +#endif + is_bsr = true; + ss_mac_log.info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", + rnti, + buff_size[0], + buff_size[1], + buff_size[2], + buff_size[3]); + break; + case srslte::sch_subh::PADDING: + ss_mac_log.debug("CE: Received padding for rnti=0x%x\n", rnti); + break; + default: + ss_mac_log.error("CE: Invalid lcid=0x%x\n", subh->ce_type()); + break; + } + return is_bsr; + } + + uint32_t get_pid(const uint32_t tti) { return tti % (2 * FDD_HARQ_DELAY_MS); } + + bool get_ndi_for_new_ul_tx(const uint32_t tti_) + { + // toggle NDI to always create new Tx + const uint32_t pid = get_pid(tti_); + last_ul_ndi[pid] = !last_ul_ndi[pid]; + log.info("UL-PID=%d NDI=%s\n", pid, last_ul_ndi[pid] ? "1" : "0"); + return last_ul_ndi[pid]; + } + + bool get_ndi_for_new_dl_tx(const uint32_t tti_) + { + // toggle NDI to always create new Tx + const uint32_t pid = get_pid(tti_); + last_dl_ndi[pid] = !last_dl_ndi[pid]; + log.info("DL-PID=%d NDI=%s\n", pid, last_dl_ndi[pid] ? "1" : "0"); + return last_dl_ndi[pid]; + } + + void run_thread() + { + uint32_t sib_idx = 0; + + while (running) { + log.debug("SYSSIM-TTI=%d\n", tti); + ue->set_current_tti(tti); + dl_rnti = ue->get_dl_sched_rnti(tti); + + if (SRSLTE_RNTI_ISSI(dl_rnti)) { + // deliver SIBs one after another + mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; + dl_grant.pid = get_pid(tti); + dl_grant.rnti = dl_rnti; + dl_grant.tb[0].tbs = sibs[sib_idx]->N_bytes; + dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); + ue->new_tb(dl_grant, sibs[sib_idx]->msg); + + sib_idx = (sib_idx + 1) % sibs.size(); + } else if (SRSLTE_RNTI_ISRAR(dl_rnti)) { + if (prach_tti != -1) { + rar_tti = (prach_tti + 3) % 10240; + if (tti == rar_tti) { + send_rar(prach_preamble_index); + } + } + } else if (SRSLTE_RNTI_ISPA(dl_rnti)) { + log.debug("Searching for paging RNTI\n"); + // PCH will be triggered from SYSSIM after receiving Paging + } else if (SRSLTE_RNTI_ISUSER(dl_rnti)) { + // check if this is for contention resolution after PRACH/RAR + if (dl_rnti == crnti) { + log.debug("Searching for C-RNTI=%d\n", crnti); + + if (rar_tti != -1) { + msg3_tti = (rar_tti + 3) % 10240; + if (tti == msg3_tti) { + send_msg3_grant(); + rar_tti = -1; + } + } + } + if (dl_rnti != 0) { + log.debug("Searching for RNTI=%d\n", dl_rnti); + + // look for DL data to be send in each bearer and provide grant accordingly + for (int lcid = 0; lcid < SRSLTE_N_RADIO_BEARERS; lcid++) { + uint32_t buf_state = rlc.get_buffer_state(lcid); + if (buf_state > 0) { + log.debug("LCID=%d, buffer_state=%d\n", lcid, buf_state); + const uint32_t mac_header_size = 10; // Add MAC header (10 B for all subheaders, etc) + if (tmp_rlc_buffer.get_tailroom() > (buf_state + mac_header_size)) { + uint32_t pdu_size = rlc.read_pdu(lcid, tmp_rlc_buffer.msg, buf_state); + tx_payload_buffer.clear(); + mac_msg_dl.init_tx(&tx_payload_buffer, pdu_size + mac_header_size, false); + + // check if this is Msg4 that needs to contain the contention resolution ID CE + if (msg3_tti != -1) { + if (lcid == 0) { + if (mac_msg_dl.new_subh()) { + if (mac_msg_dl.get()->set_con_res_id(conres_id)) { + log.info("CE: Added Contention Resolution ID=0x%lx\n", conres_id); + } else { + log.error("CE: Setting Contention Resolution ID CE\n"); + } + } else { + log.error("CE: Setting Contention Resolution ID CE. No space for a subheader\n"); + } + msg3_tti = -1; + } + } + + // Add payload + if (mac_msg_dl.new_subh()) { + int n = mac_msg_dl.get()->set_sdu(lcid, pdu_size, tmp_rlc_buffer.msg); + if (n == -1) { + log.error("Error while adding SDU (%d B) to MAC PDU\n", pdu_size); + mac_msg_dl.del_subh(); + } + } + + uint8_t* mac_pdu_ptr = mac_msg_dl.write_packet(&log); + if (mac_pdu_ptr != nullptr) { + log.info_hex(mac_pdu_ptr, mac_msg_dl.get_pdu_len(), "DL MAC PDU (%d B):\n", mac_msg_dl.get_pdu_len()); + + // Prepare MAC grant for CCCH + mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; + dl_grant.pid = get_pid(tti); + dl_grant.rnti = dl_rnti; + dl_grant.tb[0].tbs = mac_msg_dl.get_pdu_len(); + dl_grant.tb[0].ndi_present = true; + dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); + + ue->new_tb(dl_grant, (const uint8_t*)mac_pdu_ptr); + } else { + log.error("Error writing DL MAC PDU\n"); + } + mac_msg_dl.reset(); + } else { + log.error("Can't fit RLC PDU into buffer (%d > %d)\n", buf_state, tmp_rlc_buffer.get_tailroom()); + } + } + } + // Check if we need to provide a UL grant as well + } + } else { + log.debug("Not handling RNTI=%d\n", dl_rnti); + } + + usleep(1000); + tti = (tti + 1) % 10240; + } + + log.info("Leaving main thread.\n"); + log.console("Leaving main thread.\n"); + } + + uint32_t get_tti() { return tti; } + + void process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel) { log.info("%s\n", __PRETTY_FUNCTION__); } + + void set_cell_config(std::string name, uint32_t earfcn_, srslte_cell_t cell_, const float power) + { + // check if cell already exists + if (not syssim_has_cell(name)) { + // insert new cell + log.info("Adding cell %s with cellId=%d and power=%.2f dBm\n", name.c_str(), cell_.id, power); + syssim_cell_t cell = {}; + cell.name = name; + cell.cell = cell_; + cell.initial_power = power; + cell.earfcn = earfcn_; + cells.push_back(cell); + } else { + // cell is already there + log.info("Cell already there, reconfigure\n"); + } + + update_cell_map(); + } + + bool syssim_has_cell(std::string cell_name) + { + for (uint32_t i = 0; i < cells.size(); ++i) { + if (cells[i].name == cell_name) { + return true; + } + } + return false; + } + + void set_cell_attenuation(std::string cell_name, const float value) + { + if (not syssim_has_cell(cell_name)) { + log.error("Can't set cell power. Cell not found.\n"); + } + + // update cell's power + for (uint32_t i = 0; i < cells.size(); ++i) { + if (cells[i].name == cell_name) { + cells[i].attenuation = value; + break; + } + } + + update_cell_map(); + } + + void update_cell_map() + { + // Find cell with highest power and select as serving cell + if (ue != NULL) { + // convert syssim cell list to phy cell list + lte_ttcn3_phy::cell_list_t phy_cells; + for (uint32_t i = 0; i < cells.size(); ++i) { + lte_ttcn3_phy::cell_t phy_cell = {}; + phy_cell.info = cells[i].cell; + phy_cell.power = cells[i].initial_power - cells[i].attenuation; + phy_cell.earfcn = cells[i].earfcn; + log.debug("Configuring cell %d with PCI=%d with TxPower=%f\n", i, phy_cell.info.id, phy_cell.power); + phy_cells.push_back(phy_cell); + } + + // SYSSIM defines what cells the UE can connect to + ue->set_cell_map(phy_cells); + } else { + log.error("Can't configure cell. UE not initialized.\n"); + } + } + + void add_bcch_pdu(unique_byte_buffer_t pdu) { sibs.push_back(std::move(pdu)); } + + void add_ccch_pdu(unique_byte_buffer_t pdu) + { + // Add to SRB0 Tx queue + rlc.write_sdu(0, std::move(pdu)); + } + + void add_dcch_pdu(uint32_t lcid, unique_byte_buffer_t pdu) + { + // push to PDCP and create DL grant for it + log.info("Writing PDU (%d B) to LCID=%d\n", pdu->N_bytes, lcid); + pdcp.write_sdu(lcid, std::move(pdu)); + } + + void add_pch_pdu(unique_byte_buffer_t pdu) + { + log.info("Received PCH PDU (%d B)\n", pdu->N_bytes); + + // Prepare MAC grant for PCH + mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; + dl_grant.pid = get_pid(tti); + dl_grant.rnti = SRSLTE_PRNTI; + dl_grant.tb[0].tbs = pdu->N_bytes; + dl_grant.tb[0].ndi_present = true; + dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); + ue->new_tb(dl_grant, (const uint8_t*)pdu->msg); + } + + srslte::timers::timer* timer_get(uint32_t timer_id) { return timers.get(timer_id); } + + uint32_t timer_get_unique_id() { return timers.get_unique_id(); } + + void timer_release_id(uint32_t timer_id) { timers.release_id(timer_id); } + + void step_timer() { timers.step_all(); } + + void add_srb(uint32_t lcid, pdcp_config_t pdcp_config) + { + pdcp.add_bearer(lcid, pdcp_config); + rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid)); + } + + void del_srb(uint32_t lcid) + { + // Only delete SRB1/2 + if (lcid > 0) { + pdcp.del_bearer(lcid); + rlc.del_bearer(lcid); + } + + // Reset HARQ to generate new transmissions + if (lcid == 0) { + log.info("Resetting UL/DL NDI counters\n"); + memset(last_dl_ndi, 0, sizeof(last_dl_ndi)); + memset(last_ul_ndi, 0, sizeof(last_ul_ndi)); + } + } + + // RRC interface for PDCP, PDCP calls RRC to push RRC SDU + void write_pdu(uint32_t lcid, unique_byte_buffer_t pdu) + { + log.info_hex(pdu->msg, pdu->N_bytes, "RRC SDU received for LCID=%d (%d B)\n", lcid, pdu->N_bytes); + + // We don't handle RRC, prepend LCID + pdu->msg--; + *pdu->msg = lcid; + pdu->N_bytes++; + + // prepend pcell PCID + pdu->msg--; + *pdu->msg = static_cast(pcell.cell.id); + pdu->N_bytes++; + + // push content to Titan + srb.tx(std::move(pdu)); + } + + // Not supported right now + void write_pdu_bcch_bch(unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); } + void write_pdu_bcch_dlsch(unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); } + void write_pdu_pcch(unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); } + void write_pdu_mch(uint32_t lcid, unique_byte_buffer_t pdu) { log.error("%s not implemented.\n", __FUNCTION__); } + + void max_retx_attempted() { log.debug("max_retx_attempted\n"); } + + std::string get_rb_name(uint32_t lcid) + { + if (lcid < rb_id_vec.size()) { + return rb_id_vec.at(lcid); + } + return std::string("RB"); + }; + + void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true) + { + log.info_hex(sdu->msg, sdu->N_bytes, "Received SDU on LCID=%d\n", lcid); + + uint8_t* mac_pdu_ptr; + mac_pdu_ptr = mac_msg_dl.write_packet(&log); + log.info_hex(mac_pdu_ptr, mac_msg_dl.get_pdu_len(), "DL MAC PDU:\n"); + + // Prepare MAC grant for CCCH + mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; + dl_grant.pid = get_pid(tti); + dl_grant.rnti = dl_rnti; + dl_grant.tb[0].tbs = mac_msg_dl.get_pdu_len(); + dl_grant.tb[0].ndi_present = true; + dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); + + ue->new_tb(dl_grant, (const uint8_t*)mac_pdu_ptr); + } + + bool rb_is_um(uint32_t lcid) { return false; } + + int set_as_security(const uint32_t lcid, + std::array k_rrc_enc, + std::array k_rrc_int, + std::array k_up_enc, + const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) + { + pdcp.config_security(lcid, k_rrc_enc.data(), k_rrc_int.data(), k_up_enc.data(), cipher_algo, integ_algo); + pdcp.enable_integrity(lcid); + pdcp.enable_encryption(lcid); + return 0; + } + +private: + // SYS interface + ttcn3_ut_interface ut; + ttcn3_sys_interface sys; + ttcn3_ip_sock_interface ip_sock; + ttcn3_ip_ctrl_interface ip_ctrl; + ttcn3_srb_interface srb; + + // Logging stuff + srslte::logger_stdout logger_stdout; + srslte::logger_file* logger_file = nullptr; + srslte::logger* logger = nullptr; + srslte::log_filter log; + srslte::log_filter ut_log; + srslte::log_filter sys_log; + srslte::log_filter ip_sock_log; + srslte::log_filter ip_ctrl_log; + srslte::log_filter srb_log; + srslte::log_filter ss_mac_log; + srslte::log_filter ss_rlc_log; + srslte::log_filter ss_pdcp_log; + + all_args_t args = {}; + + bool running = false; + + srslte::byte_buffer_pool* pool = nullptr; + + // Simulator vars + unique_ptr ue = nullptr; + + uint32_t run_id = 0; + + std::vector sibs; + int32_t tti = 0; + int32_t prach_tti = -1; + int32_t rar_tti = -1; + int32_t msg3_tti = -1; + uint32_t prach_preamble_index = 0; + uint16_t dl_rnti = 0; + uint16_t crnti = TTCN3_CRNTI; + srslte::timers timers; + bool last_dl_ndi[2 * FDD_HARQ_DELAY_MS] = {}; + bool last_ul_ndi[2 * FDD_HARQ_DELAY_MS] = {}; + + // Map between the cellId (name) used by 3GPP test suite and srsLTE cell struct + typedef struct { + std::string name; + srslte_cell_t cell; + float initial_power; + float attenuation; + uint32_t earfcn; + } syssim_cell_t; + std::vector cells; + syssim_cell_t pcell = {}; + + srslte::pdu_queue pdus; + srslte::sch_pdu mac_msg_dl, mac_msg_ul; + + // buffer for DL transmissions + srslte::byte_buffer_t rar_buffer; + srslte::byte_buffer_t tmp_rlc_buffer; // Used to buffer RLC PDU + srslte::byte_buffer_t tx_payload_buffer; // Used to buffer final MAC PDU + + uint64_t conres_id = 0; + + // Simulator objects + srslte::rlc rlc; + srslte::pdcp pdcp; + + std::vector rb_id_vec = { + "SRB0", "SRB1", "SRB2", "DRB1", "DRB2", "DRB3", "DRB4", "DRB5", "DRB6", "DRB7", "DRB8"}; +}; + +#endif // SRSUE_TTCN3_SYSSIM_H \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_ue.h b/srsue/test/ttcn3/hdr/ttcn3_ue.h new file mode 100644 index 000000000..7fe5555e1 --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_ue.h @@ -0,0 +1,151 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_UE_H +#define SRSUE_TTCN3_UE_H + +#include "lte_ttcn3_phy.h" +#include "srsue/hdr/stack/ue_stack_lte.h" +#include + +class ttcn3_ue : public phy_interface_syssim, public gw_interface_stack +{ +public: + ttcn3_ue() {} + + virtual ~ttcn3_ue() {} + + int init(all_args_t args, srslte::logger* logger_, syssim_interface_phy* syssim_, const std::string tc_name_) + { + logger = logger_; + + // Init UE log + log.init("UE ", logger); + log.set_level(srslte::LOG_LEVEL_INFO); + log.info("Built in %s mode using %s.\n", srslte_get_build_mode(), srslte_get_build_info()); + + // Patch args + args.stack.nas.force_imsi_attach = true; + args.stack.nas.eia = "1,2,3"; + args.stack.nas.eea = "0,1,2,3"; + + // Configure default parameters + args.stack.usim.algo = "xor"; + args.stack.usim.imei = "356092040793011"; + args.stack.usim.imsi = "001010123456789"; // Anritsu test USIM + args.stack.usim.k = "000102030405060708090A0B0C0D0E0F"; // fixed as per TS 34.108 Sec. 8.2 + + args.stack.rrc.feature_group = 0xe6041000; + args.stack.rrc.ue_category_str = SRSLTE_UE_CATEGORY_DEFAULT; + args.stack.rrc.ue_category = atoi(args.stack.rrc.ue_category_str.c_str()); + args.stack.rrc.nof_supported_bands = 1; + args.stack.rrc.supported_bands[0] = 7; + args.stack.rrc.release = 8; + args.stack.rrc.mbms_service_id = -1; + + args.phy.dl_earfcn = "3400"; + args.rf.type = "none"; + args.stack.type = "lte"; + args.phy.type = "lte_ttcn3"; + + // Instantiate layers and stack together our UE + if (args.stack.type == "lte") { + stack = std::unique_ptr(new ue_stack_lte()); + if (!stack) { + log.console("Error creating LTE stack instance.\n"); + return SRSLTE_ERROR; + } + + phy = std::unique_ptr(new srsue::lte_ttcn3_phy(logger)); + if (!phy) { + log.console("Error creating LTE PHY instance.\n"); + return SRSLTE_ERROR; + } + } else { + log.console("Invalid stack type %s. Supported values are [lte].\n", args.stack.type.c_str()); + return SRSLTE_ERROR; + } + + // init layers + if (phy->init(args.phy, stack.get(), syssim_)) { + log.console("Error initializing PHY.\n"); + return SRSLTE_ERROR; + } + + if (stack->init(args.stack, logger, phy.get(), this)) { + log.console("Error initializing stack.\n"); + return SRSLTE_ERROR; + } + + return SRSLTE_SUCCESS; + } + + void stop() + { + // nothing to do here + } + + bool switch_on() { return stack->switch_on(); } + + bool switch_off() { return stack->switch_off(); } + + bool enable_data() { return stack->enable_data(); } + + bool disable_data() { return stack->disable_data(); } + + // The interface for SYSSIM + void set_cell_map(lte_ttcn3_phy::cell_list_t phy_cell_map) { phy->set_cell_map(phy_cell_map); } + + void new_grant_ul(const srsue::mac_interface_phy_lte::mac_grant_ul_t grant) { phy->new_grant_ul(grant); } + + void new_tb(const srsue::mac_interface_phy_lte::mac_grant_dl_t mac_grant, const uint8_t* data) + { + phy->new_tb(mac_grant, data); + } + + void set_current_tti(uint32_t tti) { phy->set_current_tti(tti); } + + uint16_t get_dl_sched_rnti(uint32_t tti) { return stack->get_dl_sched_rnti(tti); } + + // GW interface + void add_mch_port(uint32_t lcid, uint32_t port) {} + void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} + void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} + int setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) { return 0; } + int apply_traffic_flow_template(const uint8_t& eps_bearer_id, + const uint8_t& lcid, + const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) + { + return 0; + } + +private: + std::unique_ptr phy; + std::unique_ptr stack; + + // Generic logger members + srslte::logger* logger = nullptr; + srslte::log_filter log; // Own logger for UE + + all_args_t args = {}; +}; + +#endif // SRSUE_TTCN3_UE_H \ No newline at end of file diff --git a/srsue/test/ttcn3/hdr/ttcn3_ut_interface.h b/srsue/test/ttcn3/hdr/ttcn3_ut_interface.h new file mode 100644 index 000000000..76ee08f91 --- /dev/null +++ b/srsue/test/ttcn3/hdr/ttcn3_ut_interface.h @@ -0,0 +1,187 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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/. + * + */ + +#ifndef SRSUE_TTCN3_UT_INTERFACE_H +#define SRSUE_TTCN3_UT_INTERFACE_H + +#include "rapidjson/document.h" +#include "rapidjson/prettywriter.h" +#include "srslte/common/log.h" +#include "srslte/common/netsource_handler.h" +#include "ttcn3_interfaces.h" + +using namespace rapidjson; + +// The UpperTester interface +class ttcn3_ut_interface : public netsource_handler +{ +public: + ttcn3_ut_interface() : netsource_handler("TTCN3_UT_IF") {} + ~ttcn3_ut_interface(){}; + + void init(syssim_interface* syssim_, srslte::log* log_, std::string net_ip_, uint32_t net_port_) + { + syssim = syssim_; + log = log_; + net_ip = net_ip_; + net_port = net_port_; + initialized = true; + log->debug("Initialized.\n"); + } + +private: + void run_thread() + { + if (!initialized) { + fprintf(stderr, "UT interface not initialized. Exiting.\n"); + exit(-1); + } + + // open TCP socket + if (srslte_netsource_init(&net_source, net_ip.c_str(), net_port, SRSLTE_NETSOURCE_TCP)) { + fprintf(stderr, "Error creating input TCP socket at port %d\n", net_port); + exit(-1); + } + + log->info("Listening on %s:%d for incoming connections ..\n", net_ip.c_str(), net_port); + + running = true; + + int n; + while (run_enable) { + log->debug("Reading from UT port ..\n"); + + n = srslte_netsource_read(&net_source, rx_buf->begin(), RX_BUF_SIZE); + if (n > 0) { + // Terminate + rx_buf->at(n) = '\0'; + + Document document; + if (document.Parse((char*)rx_buf->begin()).HasParseError()) { + log->error_hex(rx_buf->begin(), n, "Error parsing incoming data.\n"); + continue; + } + assert(document.IsObject()); + + // Pretty-print + StringBuffer buffer; + PrettyWriter writer(buffer); + document.Accept(writer); + log->info("Received %d bytes\n%s\n", n, (char*)buffer.GetString()); + + // check for command + assert(document.HasMember("Cmd")); + assert(document["Cmd"].IsObject()); + + // get Cmd + const Value& a = document["Cmd"]; + + if (a.HasMember("MMI")) { + assert(a.HasMember("MMI")); + + // get MMI and make sure it has another Cmd nested + const Value& mmi = a["MMI"]; + assert(mmi.HasMember("Cmd")); + + // get MMI cmd + const Value& mmi_cmd = mmi["Cmd"]; + assert(mmi_cmd.IsString()); + + // check for CnfRequired + assert(document.HasMember("CnfRequired")); + + if (strcmp(mmi_cmd.GetString(), "POWER_OFF") == 0) { + log->info("Received POWER_OFF command.\n"); + handle_power_off(document); + } else if (strcmp(mmi_cmd.GetString(), "SWITCH_ON") == 0) { + log->info("Received SWITCH_ON command.\n"); + syssim->switch_on_ue(); + } else if (strcmp(mmi_cmd.GetString(), "SWITCH_OFF") == 0) { + log->info("Received SWITCH_OFF command.\n"); + syssim->switch_off_ue(); + } else { + log->error("Received unknown command: %s\n", mmi_cmd.GetString()); + } + } else if (a.HasMember("AT")) { + handle_at_command(document); + } else if (a.HasMember("TC_START")) { + log->info("Received TC_START command.\n"); + const Value& cmd = a["TC_START"]; + assert(cmd.HasMember("Name")); + const Value& tc_name = cmd["Name"]; + syssim->tc_start(tc_name.GetString()); + } else if (a.HasMember("TC_END")) { + log->info("Received TC_END command.\n"); + syssim->tc_end(); + } else { + log->error("Unknown command type.\n"); + } + } else if (n == 0) { + log->error("Connection closed on UT interface.\n"); + } else { + log->error("Error receiving from network\n"); + exit(-1); + } + } + running = false; + + srslte_netsource_free(&net_source); + } + + void handle_power_off(Document& document) + { + syssim->power_off_ue(); + + // Create response + Document resp; + resp.SetObject(); + resp.AddMember("Result", true, resp.GetAllocator()); + + // Serialize and send to tester + StringBuffer buffer; + Writer writer(buffer); + resp.Accept(writer); + + log->info("Sending %s to tester (%zd B)\n", buffer.GetString(), buffer.GetSize()); + srslte_netsource_write(&net_source, (char*)buffer.GetString(), buffer.GetSize()); + } + + void handle_at_command(Document& document) + { + // We can assume the doc contains a AT CMD + const Value& at = document["Cmd"]["AT"]; + + // turn off data services + if (std::string(at.GetString()) == "AT+CGATT=0") { + log->info("Disabling data services\n"); + syssim->disable_data(); + } else if (std::string(at.GetString()) == "AT+CGATT=1") { + log->info("Enabling data services\n"); + syssim->enable_data(); + } else { + log->error("Not handling AT command %s\n", at.GetString()); + } + } + + syssim_interface* syssim = nullptr; +}; + +#endif // SRSUE_TTCN3_UT_INTERFACE_H \ No newline at end of file diff --git a/srsue/test/ttcn3/src/CMakeLists.txt b/srsue/test/ttcn3/src/CMakeLists.txt new file mode 100644 index 000000000..4bc87d373 --- /dev/null +++ b/srsue/test/ttcn3/src/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright 2013-2019 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE 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. +# +# srsLTE 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/. +# + +add_executable(ttcn3_dut ttcn3_dut.cc lte_ttcn3_phy.cc) +target_link_libraries(ttcn3_dut srsue_stack + srsue_upper + srsue_rrc + srslte_upper + srslte_common + srslte_phy + srslte_radio + srslte_upper + srsue_phy + srsue_mac + rrc_asn1 + ${Boost_LIBRARIES}) +include_directories(${PROJECT_SOURCE_DIR}/srsue/test/ttcn3/hdr) \ No newline at end of file diff --git a/srsue/test/ttcn3/src/lte_ttcn3_phy.cc b/srsue/test/ttcn3/src/lte_ttcn3_phy.cc new file mode 100644 index 000000000..eee6dff55 --- /dev/null +++ b/srsue/test/ttcn3/src/lte_ttcn3_phy.cc @@ -0,0 +1,380 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "lte_ttcn3_phy.h" + +namespace srsue { + +#define MIN_IN_SYNC_POWER (-100) +#define DEFAULT_RSRQ (-3.0) + +lte_ttcn3_phy::lte_ttcn3_phy(srslte::logger* logger_) : logger(logger_) {} + +lte_ttcn3_phy::~lte_ttcn3_phy() {} + +int lte_ttcn3_phy::init(const phy_args_t& args_, stack_interface_phy_lte* stack_, syssim_interface_phy* syssim_) +{ + stack = stack_; + syssim = syssim_; + + return init(args_); +} + +int lte_ttcn3_phy::init(const phy_args_t& args_, stack_interface_phy_lte* stack_, radio_interface_phy* radio_) +{ + + return init(args_); +} + +// ue_phy_base interface +int lte_ttcn3_phy::init(const phy_args_t& args_) +{ + log.init("PHY ", logger); + log.set_level(args_.log.phy_level); + + return SRSLTE_SUCCESS; +} + +void lte_ttcn3_phy::stop(){}; + +void lte_ttcn3_phy::set_earfcn(std::vector earfcns) {} + +void lte_ttcn3_phy::force_freq(float dl_freq, float ul_freq) {} + +void lte_ttcn3_phy::wait_initialize() {} + +void lte_ttcn3_phy::start_plot() {} + +void lte_ttcn3_phy::get_metrics(phy_metrics_t* m) {} + +// The interface for the SS +void lte_ttcn3_phy::set_cell_map(const cell_list_t& cells_) +{ + std::lock_guard lock(mutex); + cells = cells_; +} + +// The interface for RRC +void lte_ttcn3_phy::get_current_cell(srslte_cell_t* cell_, uint32_t* earfcn_) +{ + if (cell_) { + memcpy(cell_, &pcell.info, sizeof(srslte_cell_t)); + } + if (earfcn_) { + *earfcn_ = pcell.earfcn; + } +} + +uint32_t lte_ttcn3_phy::get_current_earfcn() +{ + return pcell.earfcn; +} + +uint32_t lte_ttcn3_phy::get_current_pci() +{ + return pcell.info.id; +} + +void lte_ttcn3_phy::set_config_tdd(srslte_tdd_config_t& tdd_config) {} + +void lte_ttcn3_phy::set_config_scell(asn1::rrc::scell_to_add_mod_r10_s* scell_config) +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +void lte_ttcn3_phy::enable_pregen_signals(bool enable) +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +void lte_ttcn3_phy::set_activation_deactivation_scell(uint32_t cmd) +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +void lte_ttcn3_phy::set_config(srslte::phy_cfg_t& config, uint32_t cc_idx, uint32_t earfcn, srslte_cell_t* cell_info) +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +// Measurements interface +void lte_ttcn3_phy::meas_reset(){}; + +int lte_ttcn3_phy::meas_start(uint32_t earfcn, int pci) +{ + return 0; +} + +int lte_ttcn3_phy::meas_stop(uint32_t earfcn, int pci) +{ + return 0; +}; + +/* Cell search and selection procedures */ +phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* found_cell) +{ + std::lock_guard lock(mutex); + + log.info("Running cell search in PHY\n"); + cell_search_ret_t ret = {}; + + // select strongest cell as PCell + float max_power = -145; + int max_index = 0; + for (uint32_t i = 0; i < cells.size(); ++i) { + if (cells[i].power > max_power) { + max_power = cells[i].power; + max_index = i; + } + } + + // Consider cell found if above -100dBm + if (max_power >= MIN_IN_SYNC_POWER) { + pcell = cells[max_index]; + log.info("Setting PCell to EARFCN=%d CellId=%d with RS power=%.2f\n", pcell.earfcn, pcell.info.id, max_power); + if (found_cell) { + found_cell->earfcn = pcell.earfcn; + found_cell->cell = pcell.info; + } + ret.found = cell_search_ret_t::CELL_FOUND; + ret.last_freq = cell_search_ret_t::NO_MORE_FREQS; + } else { + // no suitable cell found + ret.found = cell_search_ret_t::CELL_NOT_FOUND; + } + return ret; +}; + +bool lte_ttcn3_phy::cell_select(phy_cell_t* cell) +{ + log.debug("%s not implemented.\n", __FUNCTION__); + return true; +}; + +bool lte_ttcn3_phy::cell_is_camping() +{ + return true; +}; + +void lte_ttcn3_phy::reset() +{ + log.debug("%s not implemented.\n", __FUNCTION__); +}; + +// The interface for MAC +void lte_ttcn3_phy::configure_prach_params() +{ + log.debug("%s not implemented.\n", __FUNCTION__); +}; + +void lte_ttcn3_phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) +{ + log.info("Sending PRACH with preamble %d on PCID=%d\n", preamble_idx, pcell.info.id); + prach_tti_tx = current_tti; + ra_trans_cnt++; + + syssim->prach_indication(preamble_idx, pcell.info.id); +}; + +std::string lte_ttcn3_phy::get_type() +{ + return "lte_ttcn3"; +} + +phy_interface_mac_lte::prach_info_t lte_ttcn3_phy::prach_get_info() +{ + prach_info_t info = {}; + if (prach_tti_tx != -1) { + info.is_transmitted = true; + info.tti_ra = prach_tti_tx; + } + + log.info("Return prach_tti_tx=%d\n", prach_tti_tx); + return info; +} + +/* Indicates the transmission of a SR signal in the next opportunity */ +void lte_ttcn3_phy::sr_send() +{ + sr_pending = true; + sr_tx_tti = -1; +} + +int lte_ttcn3_phy::sr_last_tx_tti() +{ + return sr_tx_tti; +} + +// The RAT-agnostic interface for MAC + +/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ +void lte_ttcn3_phy::set_crnti(uint16_t rnti) +{ + current_temp_rnti = rnti; + log.info("Set Temp-RNTI=%d\n", rnti); +} + +/* Time advance commands */ +void lte_ttcn3_phy::set_timeadv_rar(uint32_t ta_cmd) +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +void lte_ttcn3_phy::set_timeadv(uint32_t ta_cmd) +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +// Sets RAR grant payload +void lte_ttcn3_phy::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti) +{ + // Empty, SYSSIM knows when to provide UL grant for Msg3 +} + +// Called from the SYSSIM to configure the current TTI +void lte_ttcn3_phy::set_current_tti(uint32_t tti) +{ + std::lock_guard lock(mutex); + + current_tti = tti; + run_tti(); +} + +// Called from MAC to retrieve the current TTI +uint32_t lte_ttcn3_phy::get_current_tti() +{ + return current_tti; +} + +float lte_ttcn3_phy::get_phr() +{ + log.debug("%s not implemented.\n", __FUNCTION__); + return 0.1; +} + +float lte_ttcn3_phy::get_pathloss_db() +{ + log.debug("%s not implemented.\n", __FUNCTION__); + return 85.0; +} + +// Only provides a new UL grant, Tx is then triggered +// Calling function hold mutex +void lte_ttcn3_phy::new_grant_ul(mac_interface_phy_lte::mac_grant_ul_t ul_mac_grant) +{ + mac_interface_phy_lte::tb_action_ul_t ul_action = {}; + + // Deliver grant and retrieve payload + stack->new_grant_ul(cc_idx, ul_mac_grant, &ul_action); + + // Deliver MAC PDU to SYSSIM + if (ul_action.tb.enabled and ul_action.tb.payload != nullptr) { + syssim->tx_pdu(ul_action.tb.payload, ul_mac_grant.tb.tbs, ul_mac_grant.rnti); + } +} + +// Provides DL grant, copy data into DL action and pass up to MAC +void lte_ttcn3_phy::new_tb(const srsue::mac_interface_phy_lte::mac_grant_dl_t dl_grant, const uint8_t* data) +{ + std::lock_guard lock(mutex); + + if (data == nullptr) { + log.error("Invalid data buffer passed\n"); + return; + } + + // pass grant to MAC to retrieve DL action + mac_interface_phy_lte::tb_action_dl_t dl_action = {}; + + stack->new_grant_dl(cc_idx, dl_grant, &dl_action); + + bool dl_ack[SRSLTE_MAX_CODEWORDS] = {}; + + if (dl_action.tb[0].enabled && dl_action.tb[0].payload != nullptr) { + log.info_hex(data, + dl_grant.tb[0].tbs, + "TB received rnti=%d, tti=%d, n_bytes=%d\n", + dl_grant.rnti, + current_tti, + dl_grant.tb[0].tbs); + + if (dl_action.generate_ack) { + log.debug("Calling generate ACK callback\n"); + // action.generate_ack_callback(action.generate_ack_callback_arg); + } + memcpy(dl_action.tb->payload, data, dl_grant.tb[0].tbs); + + // ACK first TB and pass up + dl_ack[0] = true; + + log.info("TB processed correctly\n"); + } else { + log.error("Couldn't get buffer for TB\n"); + } + + stack->tb_decoded(cc_idx, dl_grant, dl_ack); +} + +void lte_ttcn3_phy::radio_overflow() +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +void lte_ttcn3_phy::radio_failure() +{ + log.debug("%s not implemented.\n", __FUNCTION__); +} + +// Calling function set_tti() is holding mutex +void lte_ttcn3_phy::run_tti() +{ + // send report for each cell + for (auto& cell : cells) { + stack->new_phy_meas(cell.power, DEFAULT_RSRQ, current_tti, cell.earfcn, cell.info.id); + } + + // check if Pcell is in sync + for (auto& cell : cells) { + if (cell.info.id == pcell.info.id) { + if (cell.power >= MIN_IN_SYNC_POWER) { + log.debug("PCell id=%d power=%.2f -> sync\n", pcell.info.id, cell.power); + stack->in_sync(); + } else { + log.debug("PCell id=%d power=%.2f -> out of sync\n", pcell.info.id, cell.power); + stack->out_of_sync(); + } + break; // make sure to call stack only once + } + } + + log.step(current_tti); + + // Check for SR + if (sr_pending) { + syssim->sr_req(current_tti); + sr_pending = false; + sr_tx_tti = current_tti; + } + + stack->run_tti(current_tti); +} + +} // namespace srsue diff --git a/srsue/test/ttcn3/src/ttcn3_dut.cc b/srsue/test/ttcn3/src/ttcn3_dut.cc new file mode 100644 index 000000000..e05ae522d --- /dev/null +++ b/srsue/test/ttcn3/src/ttcn3_dut.cc @@ -0,0 +1,154 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "rapidjson/document.h" // rapidjson's DOM-style API +#include "rapidjson/prettywriter.h" // for stringify JSON +#include "srslte/build_info.h" +#include "srslte/common/log_filter.h" +#include "srslte/common/logger_stdout.h" +#include "srsue/hdr/ue.h" +#include "ttcn3_helpers.h" +#include "ttcn3_syssim.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace srslte; +using namespace srsue; +; +using namespace std; +using namespace rapidjson; +namespace bpo = boost::program_options; + +typedef struct { + pcap_args_t pcap; + std::string log_filename; + std::string log_level; + int32_t log_hex_level; +} ttcn3_dut_args_t; + +all_args_t parse_args(ttcn3_dut_args_t* args, int argc, char* argv[]) +{ + // Command line only options + bpo::options_description general("General options"); + + general.add_options()("help,h", "Produce help message")("version,v", "Print version information and exit"); + + // Command line or config file options + bpo::options_description common("Configuration options"); + // clang-format off + common.add_options() + ("pcap.enable", bpo::value(&args->pcap.enable)->default_value(true), "Enable MAC packet captures for wireshark") + ("pcap.filename", bpo::value(&args->pcap.filename)->default_value("/tmp/ttcn3_ue.pcap"), "MAC layer capture filename") + ("pcap.nas_enable", bpo::value(&args->pcap.nas_enable)->default_value(false), "Enable NAS packet captures for wireshark") + ("pcap.nas_filename", bpo::value(&args->pcap.nas_filename)->default_value("/tmp/ttcn3_ue_nas.pcap"), "NAS layer capture filename (useful when NAS encryption is enabled)") + ("logfilename", bpo::value(&args->log_filename)->default_value("/tmp/ttcn3_ue.log"), "Filename of log file") + ("loglevel", bpo::value(&args->log_level)->default_value("warning"), "Log level (Error,Warning,Info,Debug)") + ("loghexlevel", bpo::value(&args->log_hex_level)->default_value(64), "Log hex level (-1 unbounded)"); + // clang-format on + + // these options are allowed on the command line + bpo::options_description cmdline_options; + cmdline_options.add(common).add(general); + + // parse the command line and store result in vm + bpo::variables_map vm; + bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).run(), vm); + bpo::notify(vm); + + // help option was given - print usage and exit + if (vm.count("help")) { + cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; + cout << common << endl << general << endl; + exit(0); + } + + all_args_t all_args = {}; + + all_args.stack.pcap.enable = args->pcap.enable; + all_args.stack.pcap.nas_enable = args->pcap.nas_enable; + + all_args.stack.pcap.filename = args->pcap.filename; + all_args.stack.pcap.nas_filename = args->pcap.nas_filename; + + all_args.log.filename = args->log_filename; + all_args.log.all_level = args->log_level; + all_args.log.all_hex_limit = args->log_hex_level; + + all_args.phy.log.phy_level = args->log_level; + all_args.stack.log.mac_level = args->log_level; + all_args.stack.log.rlc_level = args->log_level; + all_args.stack.log.pdcp_level = args->log_level; + all_args.stack.log.rrc_level = args->log_level; + all_args.stack.log.nas_level = args->log_level; + all_args.stack.log.gw_level = args->log_level; + all_args.stack.log.usim_level = args->log_level; + all_args.phy.log.phy_hex_limit = args->log_hex_level; + all_args.stack.log.mac_hex_limit = args->log_hex_level; + all_args.stack.log.rlc_hex_limit = args->log_hex_level; + all_args.stack.log.pdcp_hex_limit = args->log_hex_level; + all_args.stack.log.rrc_hex_limit = args->log_hex_level; + all_args.stack.log.nas_hex_limit = args->log_hex_level; + all_args.stack.log.gw_hex_limit = args->log_hex_level; + all_args.stack.log.usim_hex_limit = args->log_hex_level; + + return all_args; +} + +bool go_exit = false; +void sig_int_handler(int signo) +{ + printf("SIGINT received. Exiting...\n"); + if (signo == SIGINT) { + go_exit = true; + } +} + +int main(int argc, char** argv) +{ + std::cout << "Built in " << srslte_get_build_mode() << " mode using " << srslte_get_build_info() << "." << std::endl; + + ttcn3_dut_args_t dut_args; + + all_args_t ue_args = parse_args(&dut_args, argc, argv); + + signal(SIGINT, sig_int_handler); + + // Instantiate file logger + srslte::logger_file logger_file; + + // create and init SYSSIM + ttcn3_syssim syssim(&logger_file); + syssim.init(ue_args); + + // Loop until finished .. + while (!go_exit) { + sleep(1); + } + + syssim.stop(); + + return SRSLTE_SUCCESS; +} diff --git a/srsue/test/ttcn3/test/CMakeLists.txt b/srsue/test/ttcn3/test/CMakeLists.txt new file mode 100644 index 000000000..eedc56779 --- /dev/null +++ b/srsue/test/ttcn3/test/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# Copyright 2013-2019 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE 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. +# +# srsLTE 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_directories(${PROJECT_SOURCE_DIR}/srsue/test/ttcn3/hdr) + +add_executable(rapidjson_test rapidjson_test.cc) +add_test(rapidjson_test rapidjson_test) + +add_executable(ttcn3_if_handler_test ttcn3_if_handler_test.cc) +target_link_libraries(ttcn3_if_handler_test srslte_phy srslte_common) +add_test(ttcn3_if_handler_test ttcn3_if_handler_test) \ No newline at end of file diff --git a/srsue/test/ttcn3/test/rapidjson_test.cc b/srsue/test/ttcn3/test/rapidjson_test.cc new file mode 100644 index 000000000..f31dea255 --- /dev/null +++ b/srsue/test/ttcn3/test/rapidjson_test.cc @@ -0,0 +1,153 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "ttcn3_helpers.h" +#include +#include +#include +#include +#include + +int SYSTEM_CTRL_CNF_test() +{ + char titan_result[] = "{\"Common\":{\"CellId\":\"eutra_Cell1\",\"RoutingInfo\":{\"None\":true},\"TimingInfo\":{" + "\"Now\":true},\"Result\":{\"Success\":true}},\"Confirm\":{\"Cell\":true}}"; + + printf("%s\n", titan_result); + + printf("SYSTEM_CTRL_CNF_test()\n"); + + const char cellid[] = "eutra_Cell1"; + + Document resp; + resp.SetObject(); + + // Create members of common object + + // RoutingInfo + Value routing_info(kObjectType); + routing_info.AddMember("None", true, resp.GetAllocator()); + + // TimingInfo + Value timing_info(kObjectType); + timing_info.AddMember("Now", true, resp.GetAllocator()); + + // Result + Value result(kObjectType); + result.AddMember("Success", true, resp.GetAllocator()); + + // Now, create the common object itself and add members + Value common(kObjectType); + common.AddMember("CellId", cellid, resp.GetAllocator()); + common.AddMember("RoutingInfo", routing_info, resp.GetAllocator()); + common.AddMember("TimingInfo", timing_info, resp.GetAllocator()); + common.AddMember("Result", result, resp.GetAllocator()); + + // The confirm object + Value confirm(kObjectType); + confirm.AddMember("Cell", true, resp.GetAllocator()); + + resp.AddMember("Common", common, resp.GetAllocator()); + resp.AddMember("Confirm", confirm, resp.GetAllocator()); + + // printf("SYSTEM_CTRL_CNF\n%s\n", (char*)buffer.GetString()); + + return 0; +} + +void pretty_print(std::string json) +{ + Document document; + if (document.Parse((char*)json.c_str()).HasParseError()) { + fprintf(stderr, "Error parsing incoming data. Exiting\n"); + exit(-1); + } + assert(document.IsObject()); + + // Pretty-print + StringBuffer buffer; + PrettyWriter writer(buffer); + document.Accept(writer); + printf("%s\n", (char*)buffer.GetString()); +} + +// UDP v4 test +void IP_SOCK_CTRL_udp_v4_test() +{ + printf("IP_SOCK_CTRL_udp_v4_test()\n"); + char titan_result[] = "{\\\"CTRL\\\":{\\\"ConnectionId\\\":{\\\"Protocol\\\":\\\"udp\\\",\\\"Local\\\":{" + "\\\"IpAddr\\\":{\\\"V4\\\":{\\\"Addr\\\":\\\"127.0.0.1\\\"}},\\\"Port\\\":11},\\\"Remote\\\":{" + "\\\"Port\\\":22}},\\\"Ind\\\":{\\\"UDP\\\":{\\\"SocketCnf\\\":true}}}}\")"; + printf("%s\n", titan_result); + + string resp = ttcn3_helpers::get_ctrl_cnf("udp", "V4", "127.0.0.1"); + + pretty_print(resp); +}; + +// UDP v4 test +void IP_SOCK_CTRL_icmp_v6_test() +{ + printf("IP_SOCK_CTRL_icmp_v6_test()\n"); + // char titan_result[] = + // "{\\\"CTRL\\\":{\\\"ConnectionId\\\":{\\\"Protocol\\\":\\\"udp\\\",\\\"Local\\\":{\\\"IpAddr\\\":{\\\"V4\\\":{\\\"Addr\\\":\\\"127.0.0.1\\\"}},\\\"Port\\\":11},\\\"Remote\\\":{\\\"Port\\\":22}},\\\"Ind\\\":{\\\"UDP\\\":{\\\"SocketCnf\\\":true}}}}\")"; + // printf("%s\n", titan_result); + + //{ V6 := { Addr := "", ScopeId := omit } } + + string resp = ttcn3_helpers::get_ctrl_cnf("icmp6", "V6", "127.0.0.1"); + + pretty_print(resp); +}; + +void PdcpCountGetReq_test() +{ + // Titan encoding test + //"{\"Common\":{\"CellId\":\"eutra_Cell1\",\"RoutingInfo\":{\"None\":true},\"TimingInfo\":{\"Now\":true},\"Result\":{\"Success\":true}},\"Confirm\":{\"PdcpCount\":{\"Get\":[{\"RadioBearerId\":{\"Srb\":1},\"UL\":{\"Format\":\"PdcpCount_Srb\",\"Value\":\"00000000000000000000000000000000\"},\"DL\":{\"Format\":\"PdcpCount_Srb\",\"Value\":\"00000000000000000000000000000000\"}}]}}}") + + std::vector bearers; + ttcn3_helpers::pdcp_count_t srb1; + srb1.rb_is_srb = true; + srb1.rb_id = 1; + srb1.dl_value = 0; + srb1.ul_value = 1; + bearers.push_back(srb1); + + string resp = ttcn3_helpers::get_pdcp_count_response("cell1", bearers); + pretty_print(resp); +} + +void EnquireTiming_test() +{ + string resp = ttcn3_helpers::get_sys_req_cnf_with_time("cell1", "EnquireTiming", 7289); + pretty_print(resp); +} + +int main(int argc, char** argv) +{ + // SYSTEM_CTRL_CNF_test(); + // IP_SOCK_CTRL_udp_v4_test(); + // IP_SOCK_CTRL_icmp_v6_test(); + // PdcpCountGetReq_test(); + EnquireTiming_test(); + + return 0; +} diff --git a/srsue/test/ttcn3/test/ttcn3_if_handler_test.cc b/srsue/test/ttcn3/test/ttcn3_if_handler_test.cc new file mode 100644 index 000000000..ebb330c89 --- /dev/null +++ b/srsue/test/ttcn3/test/ttcn3_if_handler_test.cc @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE 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. + * + * srsLTE 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 "srslte/srslte.h" +#include "ttcn3_ip_ctrl_interface.h" +#include "ttcn3_ip_sock_interface.h" +#include "ttcn3_srb_interface.h" +#include "ttcn3_sys_interface.h" +#include "ttcn3_ut_interface.h" +#include +#include +#include + +int if_handler_test() +{ + ttcn3_ut_interface ut; + ttcn3_sys_interface sys; + ttcn3_ip_sock_interface ip_sock; + ttcn3_ip_ctrl_interface ip_ctrl; + ttcn3_srb_interface srb; + + return SRSLTE_SUCCESS; +} + +int main(int argc, char** argv) +{ + if_handler_test(); + + return SRSLTE_SUCCESS; +} diff --git a/srsue/test/upper/nas_test.cc b/srsue/test/upper/nas_test.cc index d8663ad44..f36cd7eb9 100644 --- a/srsue/test/upper/nas_test.cc +++ b/srsue/test/upper/nas_test.cc @@ -23,7 +23,7 @@ #include "srslte/common/log_filter.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/upper/pdcp.h" -#include "srslte/upper/pdcp_entity.h" +#include "srslte/upper/pdcp_entity_lte.h" #include "srslte/upper/rlc.h" #include "srsue/hdr/stack/mac/mac.h" #include "srsue/hdr/stack/rrc/rrc.h" @@ -47,24 +47,20 @@ using namespace asn1::rrc; } \ } -uint8_t auth_request_pdu[] = { 0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0xe6, 0xa4, - 0xce, 0xd9, 0x86, 0xfb, 0xe5, 0xce, 0x9b, 0x62, 0x5e, 0x10, - 0x67, 0x57, 0xb3, 0xc2, 0xb9, 0x70, 0x90, 0x01, 0x0c, 0x72, - 0x8a, 0x67, 0x57, 0x92, 0x52, 0xb8 }; +uint8_t auth_request_pdu[] = {0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0xe6, 0xa4, 0xce, 0xd9, + 0x86, 0xfb, 0xe5, 0xce, 0x9b, 0x62, 0x5e, 0x10, 0x67, 0x57, 0xb3, 0xc2, + 0xb9, 0x70, 0x90, 0x01, 0x0c, 0x72, 0x8a, 0x67, 0x57, 0x92, 0x52, 0xb8}; -uint8_t sec_mode_command_pdu[] = { 0x37, 0x37, 0xc7, 0x67, 0xae, 0x00, 0x07, 0x5d, 0x02, 0x01, - 0x02, 0xe0, 0x60, 0xc1 }; +uint8_t sec_mode_command_pdu[] = {0x37, 0x4e, 0xfd, 0x57, 0x11, 0x00, 0x07, 0x5d, 0x02, 0x01, 0x02, 0xf0, 0x70, 0xc1}; -uint8_t attach_accept_pdu[] = { 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0x01, 0x3e, - 0x06, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x2a, 0x52, - 0x01, 0xc1, 0x01, 0x04, 0x1b, 0x07, 0x74, 0x65, 0x73, 0x74, - 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, 0x30, 0x30, 0x31, - 0x06, 0x6d, 0x63, 0x63, 0x30, 0x30, 0x31, 0x04, 0x67, 0x70, - 0x72, 0x73, 0x05, 0x01, 0xc0, 0xa8, 0x05, 0x02, 0x27, 0x01, - 0x80, 0x50, 0x0b, 0xf6, 0x00, 0xf1, 0x10, 0x80, 0x01, 0x01, - 0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00 }; +uint8_t attach_accept_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0x01, 0x3e, 0x06, 0x00, 0x00, + 0xf1, 0x10, 0x00, 0x01, 0x00, 0x2a, 0x52, 0x01, 0xc1, 0x01, 0x04, 0x1b, 0x07, + 0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, 0x30, 0x30, + 0x31, 0x06, 0x6d, 0x63, 0x63, 0x30, 0x30, 0x31, 0x04, 0x67, 0x70, 0x72, 0x73, + 0x05, 0x01, 0xc0, 0xa8, 0x05, 0x02, 0x27, 0x01, 0x80, 0x50, 0x0b, 0xf6, 0x00, + 0xf1, 0x10, 0x80, 0x01, 0x01, 0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00}; -uint8_t esm_info_req_pdu[] = { 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5a, 0xd9 }; +uint8_t esm_info_req_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5a, 0xd9}; uint8_t activate_dedicated_eps_bearer_pdu[] = {0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0xc5, 0x05, 0x01, 0x01, 0x07, 0x21, 0x31, 0x00, 0x03, 0x40, 0x08, 0xae, @@ -90,7 +86,7 @@ public: void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) {} std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); } void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) {} - bool is_lcid_enabled(uint32_t lcid) { return false; } + bool is_lcid_enabled(uint32_t lcid) { return false; } }; class rrc_dummy : public rrc_interface_nas @@ -100,6 +96,7 @@ public: plmns.plmn_id.from_number(mcc, mnc); plmns.tac = 0xffff; } + void init(nas* nas_) { nas_ptr = nas_; } void write_sdu(unique_byte_buffer_t sdu) { last_sdu_len = sdu->N_bytes; @@ -110,10 +107,11 @@ public: uint32_t get_last_sdu_len() { return last_sdu_len; } void reset() { last_sdu_len = 0; } - int plmn_search(srsue::rrc_interface_nas::found_plmn_t* found) { - memcpy(found, &plmns, sizeof(found_plmn_t)); - return 1; - }; + bool plmn_search() + { + nas_ptr->plmn_search_completed(&plmns, 1); + return true; + } void plmn_select(srslte::plmn_id_t plmn_id){}; void set_ue_identity(srslte::s_tmsi_t s_tmsi) {} bool connection_request(srslte::establishment_cause_t cause, srslte::unique_byte_buffer_t sdu) @@ -121,6 +119,7 @@ public: printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); last_sdu_len = sdu->N_bytes; srslte_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); + nas_ptr->connection_request_completed(true); return true; } bool is_connected() {return false;} @@ -129,8 +128,10 @@ public: uint16_t get_mnc() { return mnc; } void enable_capabilities() {} uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) { return 0; } + void paging_completed(bool outcome) {} private: + nas* nas_ptr; uint32_t last_sdu_len; found_plmn_t plmns; }; @@ -140,13 +141,28 @@ class stack_dummy : public stack_interface_gw, public thread public: stack_dummy(pdcp_interface_gw* pdcp_, srsue::nas* nas_) : pdcp(pdcp_), nas(nas_), thread("DUMMY STACK") {} void init() { start(-1); } - bool switch_on() final { return nas->attach_request(); } + bool switch_on() final + { + proc_state_t proc_result = proc_state_t::on_going; + nas->start_attach_request(&proc_result); + while (proc_result == proc_state_t::on_going) { + usleep(1000); + } + return proc_result == proc_state_t::success; + } void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) { pdcp->write_sdu(lcid, std::move(sdu), blocking); } bool is_lcid_enabled(uint32_t lcid) { return pdcp->is_lcid_enabled(lcid); } - void run_thread() { running = true; } + void run_thread() + { + running = true; + uint32_t counter = 0; + while (running) { + nas->run_tti(counter++); + } + } void stop() { running = false; @@ -208,9 +224,10 @@ int security_command_test() { srsue::nas nas(&nas_log); nas_args_t cfg; - cfg.eia = "1,2"; - cfg.eea = "0,1,2"; + cfg.eia = "1,2,3"; + cfg.eea = "0,1,2,3"; nas.init(&usim, &rrc_dummy, &gw, cfg); + rrc_dummy.init(&nas); // push auth request PDU to NAS to generate security context byte_buffer_pool* pool = byte_buffer_pool::get_instance(); @@ -279,6 +296,7 @@ int mme_attach_request_test() stack_dummy stack(&pdcp_dummy, &nas); nas.init(&usim, &rrc_dummy, &gw, nas_cfg); + rrc_dummy.init(&nas); gw_args_t gw_args; gw_args.tun_dev_name = "tun0"; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index acb9345c2..5ae446691 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -40,7 +40,10 @@ tx_gain = 80 #nof_rx_ant = 1 # For best performance in 2x2 MIMO and >= 15 MHz use the following device_args settings: -# USRP B210: pass num_recv_frames=64,num_send_frames=64 +# USRP B210: num_recv_frames=64,num_send_frames=64 + +# For best performance when BW<5 MHz (25 PRB), use the following device_args settings: +# USRP B210: send_frame_size=512,recv_frame_size=512 #device_args = auto #time_adv_nsamples = auto @@ -183,45 +186,80 @@ enable = false ##################################################################### # Channel emulator options: -# dl.enable: Enable/Disable internal Downlink channel emulator +# enable: Enable/Disable internal Downlink/Uplink channel emulator # # -- Fading emulator -# dl.fading.enable: Enable/disable fading simulator -# dl.fading.model: Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc) +# fading.enable: Enable/disable fading simulator +# fading.model: Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc) # # -- Delay Emulator delay(t) = delay_min + (delay_max - delay_min) * (1 + sin(2pi*t/period)) / 2 # Maximum speed [m/s]: (delay_max - delay_min) * pi * 300 / period -# dl.delay.enable: Enable/disable delay simulator -# dl.delay.period: Delay period in seconds (integer). -# dl.delay.maximum_us: Maximum delay in microseconds -# dl.delay.minumum_us: Minimum delay in microseconds +# delay.enable: Enable/disable delay simulator +# delay.period_s: Delay period in seconds. +# delay.init_time_s: Delay initial time in seconds. +# delay.maximum_us: Maximum delay in microseconds +# delay.minumum_us: Minimum delay in microseconds # # -- Radio-Link Failure (RLF) Emulator -# dl.rlf.enable: Enable/disable RLF simulator -# dl.rlf.t_on_ms: Time for On state of the channel (ms) -# dl.rlf.t_off_ms: Time for Off state of the channel (ms) +# rlf.enable: Enable/disable RLF simulator +# rlf.t_on_ms: Time for On state of the channel (ms) +# rlf.t_off_ms: Time for Off state of the channel (ms) +# +# -- High Speed Train Doppler model simulator +# hst.enable: Enable/Disable HST simulator +# hst.period_s: HST simulation period in seconds +# hst.fd_hz: Doppler frequency in Hz +# hst.init_time_s: Initial time in seconds ##################################################################### -[channel] -#dl.enable = false -#dl.fading.enable = false -#dl.fading.model = none -#dl.delay.enable = false -#dl.delay.period = 3600 -#dl.delay.maximum_us = 100 -#dl.delay.minimum_us = 10 -#dl.rlf.enable = false -#dl.rlf.t_on_ms = 10000 -#dl.rlf.t_off_ms = 2000 -#ul.enable = false -#ul.fading.enable = false -#ul.fading.model = none -#ul.delay.enable = false -#ul.delay.period = 3600 -#ul.delay.maximum_us = 100 -#ul.delay.minimum_us = 10 -#ul.rlf.enable = false -#ul.rlf.t_on_ms = 10000 -#ul.rlf.t_off_ms = 2000 +[channel.dl] +#enable = false + +[channel.dl.fading] +#enable = false +#model = none + +[channel.dl.delay] +#enable = false +#period_s = 3600 +#init_time_s = 0 +#maximum_us = 100 +#minimum_us = 10 + +[channel.dl.rlf] +#enable = false +#t_on_ms = 10000 +#t_off_ms = 2000 + +[channel.dl.hst] +#enable = false +#period_s = 7.2 +#fd_hz = 750.0 +#init_time_s = 0.0 + +[channel.ul] +#enable = false + +[channel.ul.fading] +#enable = false +#model = none + +[channel.ul.delay] +#enable = false +#period_s = 3600 +#init_time_s = 0 +#maximum_us = 100 +#minimum_us = 10 + +[channel.ul.rlf] +#enable = false +#t_on_ms = 10000 +#t_off_ms = 2000 + +[channel.ul.hst] +#enable = false +#period_s = 7.2 +#fd_hz = -750.0 +#init_time_s = 0.0 ##################################################################### # PHY configuration options