Merge branch 'next' into agpl_next

# Conflicts:
#	lib/include/srslte/common/mac_nr_pcap.h
#	lib/include/srslte/phy/ue/ue_ul_nr_data.h
#	lib/src/common/mac_nr_pcap.cc
#	lib/src/phy/ue/ue_ul_nr_data.c
#	srsenb/hdr/phy/lte/worker_pool.h
#	srsenb/hdr/phy/nr/cc_worker.h
#	srsenb/hdr/phy/nr/sf_worker.h
#	srsenb/hdr/phy/nr/worker_pool.h
#	srsenb/src/phy/lte/worker_pool.cc
#	srsenb/src/phy/nr/cc_worker.cc
#	srsenb/src/phy/nr/sf_worker.cc
#	srsenb/src/phy/nr/worker_pool.cc
#	srsue/hdr/phy/lte/worker_pool.h
#	srsue/hdr/phy/nr/cc_worker.h
#	srsue/hdr/phy/nr/sf_worker.h
#	srsue/hdr/phy/nr/worker_pool.h
#	srsue/hdr/stack/mac/mac_nr.h
#	srsue/src/phy/lte/worker_pool.cc
#	srsue/src/phy/nr/cc_worker.cc
#	srsue/src/phy/nr/sf_worker.cc
#	srsue/src/phy/nr/worker_pool.cc
#	srsue/src/stack/mac/mac_nr.cc
master
srsLTE codebot 4 years ago committed by Your Name
commit 3daa9f3fc3

@ -75,7 +75,7 @@ IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1

@ -25,7 +25,7 @@ script:
fi
- mkdir build
- cd build
- cmake -DENABLE_5GNR=True -DENABLE_TTCN3=True -DRF_FOUND=True -G Ninja ..
- cmake -DENABLE_TTCN3=True -DRF_FOUND=True -G Ninja ..
- ninja
- ninja test
- sudo ninja install

@ -65,7 +65,6 @@ configure_file(
option(ENABLE_SRSUE "Build srsUE application" ON)
option(ENABLE_SRSENB "Build srsENB application" ON)
option(ENABLE_SRSEPC "Build srsEPC application" ON)
option(ENABLE_5GNR "Build with 5G-NR components" OFF)
option(DISABLE_SIMD "Disable SIMD instructions" OFF)
option(AUTO_DETECT_ISA "Autodetect supported ISA extensions" ON)
@ -106,9 +105,6 @@ else(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64")
set(GCC_ARCH native CACHE STRING "GCC compile for specific architecture.")
endif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64")
if (ENABLE_5GNR)
add_definitions(-DHAVE_5GNR)
endif (ENABLE_5GNR)
########################################################################
# Find dependencies
@ -281,6 +277,17 @@ if (ENABLE_TTCN3)
message(STATUS "Building with TTCN3 binaries")
endif (ENABLE_TTCN3)
# Backward-cpp
find_package(Backward)
if(Backward_FOUND)
if(BACKWARD_HAS_EXTERNAL_LIBRARIES)
add_definitions(-DHAVE_BACKWARD)
message(STATUS "Building with backward-cpp support")
else (BACKWARD_HAS_EXTERNAL_LIBRARIES)
message(STATUS "Backward-cpp found, but external libraries are missing.")
endif()
endif()
########################################################################
# Install Dirs
########################################################################
@ -541,6 +548,28 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "Building for version: ${VERSION}")
########################################################################
# Ctest function helpers
########################################################################
function(add_lte_test)
add_test(${ARGN})
set(TNAME ${ARGV0})
if(${TNAME} STREQUAL NAME)
set(TNAME ${ARGV1})
endif()
set_tests_properties(${TNAME} PROPERTIES LABELS "lte;${CTEST_LABELS}")
endfunction()
function(add_nr_test)
add_test(${ARGN})
set(TNAME ${ARGV0})
if(${TNAME} STREQUAL NAME)
set(TNAME ${ARGV1})
endif()
set_tests_properties(${TNAME} PROPERTIES LABELS "nr;${CTEST_LABELS}")
endfunction()
########################################################################
# Add general includes and dependencies
########################################################################

@ -46,6 +46,10 @@ Files: lib/include/srslte/srslog/bundled/fmt/chrono.h
Copyright: 2012-2020, Victor Zverovich
License: MIT
Files: lib/include/srslte/common/backward.hpp
cmake/modules/FindBackward.cmake
Copyright: 2013, Google Inc.
License: MIT
License: AGPL-3+
This program is free software: you can redistribute it and/or modify

@ -119,7 +119,7 @@ Build Instructions
For example, on Ubuntu, one can install the mandatory build dependencies with:
```
sudo apt-get install cmake libfftw3-dev libmbedtls-dev libboost-program-options-dev libconfig++-dev libsctp-dev
sudo apt-get install build-essential cmake libfftw3-dev libmbedtls-dev libboost-program-options-dev libconfig++-dev libsctp-dev
```
or on Fedora:
```
@ -132,6 +132,7 @@ Note that depending on your flavor and version of Linux, the actual package name
* Optional requirements:
* srsgui: https://github.com/srslte/srsgui - for real-time plotting.
* libpcsclite-dev: https://pcsclite.apdu.fr/ - for accessing smart card readers
* libdw-dev libdw - for truly informative backtraces using backward-cpp
* RF front-end driver:
* UHD: https://github.com/EttusResearch/uhd

@ -0,0 +1,243 @@
#
# BackwardMacros.cmake
# Copyright 2013 Google Inc. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
###############################################################################
# OPTIONS
###############################################################################
if(POLICY CMP0011)
cmake_policy(SET CMP0011 NEW)
cmake_policy(SET CMP0012 NEW)
endif()
set(STACK_WALKING_UNWIND TRUE CACHE BOOL
"Use compiler's unwind API")
set(STACK_WALKING_BACKTRACE FALSE CACHE BOOL
"Use backtrace from (e)glibc for stack walking")
set(STACK_WALKING_LIBUNWIND FALSE CACHE BOOL
"Use libunwind for stack walking")
set(STACK_DETAILS_AUTO_DETECT TRUE CACHE BOOL
"Auto detect backward's stack details dependencies")
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE CACHE BOOL
"Use backtrace from (e)glibc for symbols resolution")
set(STACK_DETAILS_DW FALSE CACHE BOOL
"Use libdw to read debug info")
set(STACK_DETAILS_BFD FALSE CACHE BOOL
"Use libbfd to read debug info")
set(STACK_DETAILS_DWARF FALSE CACHE BOOL
"Use libdwarf/libelf to read debug info")
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND NOT DEFINED BACKWARD_TESTS)
# If this is a top level CMake project, we most lixely want the tests
set(BACKWARD_TESTS ON CACHE BOOL "Enable tests")
else()
set(BACKWARD_TESTS OFF CACHE BOOL "Enable tests")
endif()
###############################################################################
# CONFIGS
###############################################################################
include(FindPackageHandleStandardArgs)
if (STACK_WALKING_LIBUNWIND)
# libunwind works on the macOS without having to add special include
# paths or libraries
if (NOT APPLE)
find_path(LIBUNWIND_INCLUDE_DIR NAMES "libunwind.h")
find_library(LIBUNWIND_LIBRARY unwind)
if (LIBUNWIND_LIBRARY)
include(CheckSymbolExists)
check_symbol_exists(UNW_INIT_SIGNAL_FRAME libunwind.h HAVE_UNW_INIT_SIGNAL_FRAME)
if (NOT HAVE_UNW_INIT_SIGNAL_FRAME)
message(STATUS "libunwind does not support unwinding from signal handler frames")
endif()
endif()
set(LIBUNWIND_INCLUDE_DIRS ${LIBUNWIND_INCLUDE_DIR})
set(LIBDWARF_LIBRARIES ${LIBUNWIND_LIBRARY})
find_package_handle_standard_args(libunwind DEFAULT_MSG
LIBUNWIND_LIBRARY LIBUNWIND_INCLUDE_DIR)
mark_as_advanced(LIBUNWIND_INCLUDE_DIR LIBUNWIND_LIBRARY)
list(APPEND _BACKWARD_LIBRARIES ${LIBUNWIND_LIBRARY})
endif()
# Disable other unwinders if libunwind is found
set(STACK_WALKING_UNWIND FALSE)
set(STACK_WALKING_BACKTRACE FALSE)
endif()
if (${STACK_DETAILS_AUTO_DETECT})
# find libdw
find_path(LIBDW_INCLUDE_DIR NAMES "elfutils/libdw.h" "elfutils/libdwfl.h")
find_library(LIBDW_LIBRARY dw)
set(LIBDW_INCLUDE_DIRS ${LIBDW_INCLUDE_DIR} )
set(LIBDW_LIBRARIES ${LIBDW_LIBRARY} )
find_package_handle_standard_args(libdw DEFAULT_MSG
LIBDW_LIBRARY LIBDW_INCLUDE_DIR)
mark_as_advanced(LIBDW_INCLUDE_DIR LIBDW_LIBRARY)
# find libbfd
find_path(LIBBFD_INCLUDE_DIR NAMES "bfd.h")
find_path(LIBDL_INCLUDE_DIR NAMES "dlfcn.h")
find_library(LIBBFD_LIBRARY bfd)
find_library(LIBDL_LIBRARY dl)
set(LIBBFD_INCLUDE_DIRS ${LIBBFD_INCLUDE_DIR} ${LIBDL_INCLUDE_DIR})
set(LIBBFD_LIBRARIES ${LIBBFD_LIBRARY} ${LIBDL_LIBRARY})
find_package_handle_standard_args(libbfd DEFAULT_MSG
LIBBFD_LIBRARY LIBBFD_INCLUDE_DIR
LIBDL_LIBRARY LIBDL_INCLUDE_DIR)
mark_as_advanced(LIBBFD_INCLUDE_DIR LIBBFD_LIBRARY
LIBDL_INCLUDE_DIR LIBDL_LIBRARY)
# find libdwarf
find_path(LIBDWARF_INCLUDE_DIR NAMES "libdwarf.h" PATH_SUFFIXES libdwarf)
find_path(LIBELF_INCLUDE_DIR NAMES "libelf.h")
find_path(LIBDL_INCLUDE_DIR NAMES "dlfcn.h")
find_library(LIBDWARF_LIBRARY dwarf)
find_library(LIBELF_LIBRARY elf)
find_library(LIBDL_LIBRARY dl)
set(LIBDWARF_INCLUDE_DIRS ${LIBDWARF_INCLUDE_DIR} ${LIBELF_INCLUDE_DIR} ${LIBDL_INCLUDE_DIR})
set(LIBDWARF_LIBRARIES ${LIBDWARF_LIBRARY} ${LIBELF_LIBRARY} ${LIBDL_LIBRARY})
find_package_handle_standard_args(libdwarf DEFAULT_MSG
LIBDWARF_LIBRARY LIBDWARF_INCLUDE_DIR
LIBELF_LIBRARY LIBELF_INCLUDE_DIR
LIBDL_LIBRARY LIBDL_INCLUDE_DIR)
mark_as_advanced(LIBDWARF_INCLUDE_DIR LIBDWARF_LIBRARY
LIBELF_INCLUDE_DIR LIBELF_LIBRARY
LIBDL_INCLUDE_DIR LIBDL_LIBRARY)
if (LIBDW_FOUND)
LIST(APPEND _BACKWARD_INCLUDE_DIRS ${LIBDW_INCLUDE_DIRS})
LIST(APPEND _BACKWARD_LIBRARIES ${LIBDW_LIBRARIES})
set(STACK_DETAILS_DW TRUE)
set(STACK_DETAILS_BFD FALSE)
set(STACK_DETAILS_DWARF FALSE)
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE)
elseif(LIBBFD_FOUND)
LIST(APPEND _BACKWARD_INCLUDE_DIRS ${LIBBFD_INCLUDE_DIRS})
LIST(APPEND _BACKWARD_LIBRARIES ${LIBBFD_LIBRARIES})
# If we attempt to link against static bfd, make sure to link its dependencies, too
get_filename_component(bfd_lib_ext "${LIBBFD_LIBRARY}" EXT)
if (bfd_lib_ext STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}")
list(APPEND _BACKWARD_LIBRARIES iberty z)
endif()
set(STACK_DETAILS_DW FALSE)
set(STACK_DETAILS_BFD TRUE)
set(STACK_DETAILS_DWARF FALSE)
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE)
elseif(LIBDWARF_FOUND)
LIST(APPEND _BACKWARD_INCLUDE_DIRS ${LIBDWARF_INCLUDE_DIRS})
LIST(APPEND _BACKWARD_LIBRARIES ${LIBDWARF_LIBRARIES})
set(STACK_DETAILS_DW FALSE)
set(STACK_DETAILS_BFD FALSE)
set(STACK_DETAILS_DWARF TRUE)
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE)
else()
set(STACK_DETAILS_DW FALSE)
set(STACK_DETAILS_BFD FALSE)
set(STACK_DETAILS_DWARF FALSE)
set(STACK_DETAILS_BACKTRACE_SYMBOL TRUE)
endif()
else()
if (STACK_DETAILS_DW)
LIST(APPEND _BACKWARD_LIBRARIES dw)
endif()
if (STACK_DETAILS_BFD)
LIST(APPEND _BACKWARD_LIBRARIES bfd dl)
endif()
if (STACK_DETAILS_DWARF)
LIST(APPEND _BACKWARD_LIBRARIES dwarf elf)
endif()
endif()
macro(map_definitions var_prefix define_prefix)
foreach(def ${ARGN})
if (${${var_prefix}${def}})
LIST(APPEND _BACKWARD_DEFINITIONS "${define_prefix}${def}=1")
else()
LIST(APPEND _BACKWARD_DEFINITIONS "${define_prefix}${def}=0")
endif()
endforeach()
endmacro()
if (NOT _BACKWARD_DEFINITIONS)
map_definitions("STACK_WALKING_" "BACKWARD_HAS_" UNWIND LIBUNWIND BACKTRACE)
map_definitions("STACK_DETAILS_" "BACKWARD_HAS_" BACKTRACE_SYMBOL DW BFD DWARF)
endif()
set(BACKWARD_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}")
set(BACKWARD_HAS_EXTERNAL_LIBRARIES FALSE)
set(FIND_PACKAGE_REQUIRED_VARS BACKWARD_INCLUDE_DIR)
if(DEFINED _BACKWARD_LIBRARIES)
set(BACKWARD_HAS_EXTERNAL_LIBRARIES TRUE)
list(APPEND FIND_PACKAGE_REQUIRED_VARS _BACKWARD_LIBRARIES)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Backward
REQUIRED_VARS ${FIND_PACKAGE_REQUIRED_VARS}
)
list(APPEND _BACKWARD_INCLUDE_DIRS ${BACKWARD_INCLUDE_DIR})
macro(add_backward target)
target_include_directories(${target} PRIVATE ${BACKWARD_INCLUDE_DIRS})
set_property(TARGET ${target} APPEND PROPERTY COMPILE_DEFINITIONS ${BACKWARD_DEFINITIONS})
set_property(TARGET ${target} APPEND PROPERTY LINK_LIBRARIES ${BACKWARD_LIBRARIES})
endmacro()
set(BACKWARD_INCLUDE_DIRS ${_BACKWARD_INCLUDE_DIRS} CACHE INTERNAL "_BACKWARD_INCLUDE_DIRS")
set(BACKWARD_DEFINITIONS ${_BACKWARD_DEFINITIONS} CACHE INTERNAL "BACKWARD_DEFINITIONS")
set(BACKWARD_LIBRARIES ${_BACKWARD_LIBRARIES} CACHE INTERNAL "BACKWARD_LIBRARIES")
mark_as_advanced(BACKWARD_INCLUDE_DIRS BACKWARD_DEFINITIONS BACKWARD_LIBRARIES)
# Expand each definition in BACKWARD_DEFINITIONS to its own cmake var and export
# to outer scope
foreach(var ${BACKWARD_DEFINITIONS})
string(REPLACE "=" ";" var_as_list ${var})
list(GET var_as_list 0 var_name)
list(GET var_as_list 1 var_value)
set(${var_name} ${var_value})
mark_as_advanced(${var_name})
#message(STATUS "${var_name}=${var_value}")
endforeach()
# Disabled for older CMake version (CentOS)
#if (NOT TARGET Backward::Backward)
# add_library(Backward::Backward INTERFACE IMPORTED)
# set_target_properties(Backward::Backward PROPERTIES
# INTERFACE_INCLUDE_DIRECTORIES "${BACKWARD_INCLUDE_DIRS}"
# INTERFACE_COMPILE_DEFINITIONS "${BACKWARD_DEFINITIONS}"
# )
# if(BACKWARD_HAS_EXTERNAL_LIBRARIES)
# set_target_properties(Backward::Backward PROPERTIES
# INTERFACE_LINK_LIBRARIES "${BACKWARD_LIBRARIES}"
# )
# endif()
#endif()

5
debian/copyright vendored

@ -53,6 +53,11 @@ Files: lib/include/srslte/srslog/bundled/fmt/chrono.h
Copyright: 2012-2020, Victor Zverovich
License: MIT
Files: lib/include/srslte/common/backward.hpp
cmake/modules/FindBackward.cmake
Copyright: 2013, Google Inc.
License: MIT
License: AGPL-3+
This program is free software: you can redistribute it and/or modify

@ -116,7 +116,7 @@ void parse_args(int argc, char** argv)
int srslte_rf_recv_wrapper(void* h, void* data, uint32_t nsamples, srslte_timestamp_t* t)
{
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
DEBUG(" ---- Receive %d samples ---- ", nsamples);
return srslte_rf_recv_with_time((srslte_rf_t*)h, data, nsamples, 1, NULL, NULL);
}
@ -152,7 +152,7 @@ int main(int argc, char** argv)
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
exit(-1);
}
if (!cell_detect_config.init_agc) {
@ -160,7 +160,7 @@ int main(int argc, char** argv)
} else {
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
exit(-1);
}
srslte_rf_set_rx_gain(&rf, 50);
@ -171,7 +171,7 @@ int main(int argc, char** argv)
nof_freqs = srslte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN);
if (nof_freqs < 0) {
ERROR("Error getting EARFCN list\n");
ERROR("Error getting EARFCN list");
exit(-1);
}
@ -182,7 +182,7 @@ int main(int argc, char** argv)
signal(SIGINT, sig_int_handler);
if (srslte_ue_cellsearch_init(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, (void*)&rf)) {
ERROR("Error initiating UE cell detect\n");
ERROR("Error initiating UE cell detect");
exit(-1);
}
@ -199,10 +199,9 @@ int main(int argc, char** argv)
}
for (freq = 0; freq < nof_freqs && !go_exit; freq++) {
/* set rf_freq */
srslte_rf_set_rx_freq(&rf, 0, (double)channels[freq].fd * MHZ);
INFO("Set rf_freq to %.3f MHz\n", (double)channels[freq].fd * MHZ / 1000000);
INFO("Set rf_freq to %.3f MHz", (double)channels[freq].fd * MHZ / 1000000);
printf(
"[%3d/%d]: EARFCN %d Freq. %.2f MHz looking for PSS.\n", freq, nof_freqs, channels[freq].id, channels[freq].fd);
@ -214,14 +213,14 @@ int main(int argc, char** argv)
bzero(found_cells, 3 * sizeof(srslte_ue_cellsearch_result_t));
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ / 1000000);
INFO("Setting sampling frequency %.2f MHz for PSS search", SRSLTE_CS_SAMP_FREQ / 1000000);
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n");
INFO("Starting receiver...");
srslte_rf_start_rx_stream(&rf, false);
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
if (n < 0) {
ERROR("Error searching cell\n");
ERROR("Error searching cell");
exit(-1);
} else if (n > 0) {
for (int i = 0; i < 3; i++) {
@ -231,7 +230,7 @@ int main(int argc, char** argv)
cell.cp = found_cells[i].cp;
int ret = rf_mib_decoder(&rf, 1, &cell_detect_config, &cell, NULL);
if (ret < 0) {
ERROR("Error decoding MIB\n");
ERROR("Error decoding MIB");
exit(-1);
}
if (ret == SRSLTE_UE_MIB_FOUND) {

@ -121,7 +121,7 @@ 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);
DEBUG(" ---- Receive %d samples ----", nsamples);
void* ptr[SRSLTE_MAX_PORTS];
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
ptr[i] = data[i];
@ -193,7 +193,7 @@ int main(int argc, char** argv)
// set rf_freq
double rf_freq = channels[freq].fd * MHZ + raster_offset[i];
srslte_rf_set_rx_freq(&rf, 0, rf_freq);
INFO("Set rf_freq to %.3f Hz\n", rf_freq);
INFO("Set rf_freq to %.3f Hz", rf_freq);
printf("[%3d/%d]: EARFCN %d, %.2f MHz looking for NPSS.\n", freq, nof_freqs, channels[freq].id, rf_freq / 1e6);
fflush(stdout);
@ -216,9 +216,9 @@ int main(int argc, char** argv)
srslte_ue_sync_nbiot_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
}
INFO("Setting sampling frequency %.2f MHz for NPSS search\n", SRSLTE_CS_SAMP_FREQ / 1000000);
INFO("Setting sampling frequency %.2f MHz for NPSS search", SRSLTE_CS_SAMP_FREQ / 1000000);
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n");
INFO("Starting receiver...");
srslte_rf_start_rx_stream(&rf, false);
n = srslte_ue_cellsearch_nbiot_scan(&cs);

@ -498,7 +498,6 @@ int main(int argc, char** argv)
signal(SIGINT, sig_int_handler);
if (!output_file_name) {
int srate = srslte_sampling_freq_hz(cell.base.nof_prb);
if (srate != -1) {
printf("Setting sampling rate %.2f MHz\n", (float)srate / 1000000);
@ -564,7 +563,7 @@ int main(int argc, char** argv)
srslte_nsss_put_subframe(&nsss_sync, nsss_signal, sf_buffer, sfn, cell.base.nof_prb, cell.nbiot_prb);
} else {
// NRS in all other subframes (using CSR signal intentionally)
// DEBUG("%d.%d: Putting %d NRS pilots\n", sfn, sf_idx, SRSLTE_REFSIGNAL_NUM_SF(1, cell.nof_ports));
// DEBUG("%d.%d: Putting %d NRS pilots", sfn, sf_idx, SRSLTE_REFSIGNAL_NUM_SF(1, cell.nof_ports));
srslte_refsignal_nrs_put_sf(cell, 0, ch_est.nrs_signal.pilots[0][sf_idx], sf_buffer);
}
@ -600,14 +599,13 @@ int main(int argc, char** argv)
}
if (srslte_nbiot_ue_dl_is_sib1_sf(&ue_dl, sfn, sf_idx)) {
INFO("%d.%d: Transmitting SIB1-NB.\n", sfn, sf_idx);
INFO("%d.%d: Transmitting SIB1-NB.", sfn, sf_idx);
assert(send_data == false);
// configure DL grant for SIB1-NB transmission
if (sib1_npdsch_cfg.sf_idx == 0) {
srslte_ra_nbiot_dl_grant_t grant;
srslte_ra_nbiot_dl_dci_to_grant(
&ra_dl_sib1, &grant, sfn, sf_idx, DUMMY_R_MAX, true, cell.mode);
srslte_ra_nbiot_dl_dci_to_grant(&ra_dl_sib1, &grant, sfn, sf_idx, DUMMY_R_MAX, true, cell.mode);
if (srslte_npdsch_cfg(&sib1_npdsch_cfg, cell, &grant, sf_idx)) {
fprintf(stderr, "Error configuring NPDSCH\n");
exit(-1);
@ -635,7 +633,7 @@ int main(int argc, char** argv)
// always transmit NPDCCH on fixed positions if no transmission is going on
if (sf_idx == NPDCCH_SF_IDX && !npdsch_active) {
// Encode NPDCCH
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
INFO("Putting DCI to location: n=%d, L=%d", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
srslte_dci_msg_pack_npdsch(&ra_dl, SRSLTE_DCI_FORMATN1, &dci_msg, false);
if (srslte_npdcch_encode(&npdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_re_symbols, sf_idx)) {
fprintf(stderr, "Error encoding DCI message\n");
@ -654,7 +652,7 @@ int main(int argc, char** argv)
// catch start of "user" NPDSCH
if (!npdsch_active && (sf_idx == npdsch_cfg.grant.start_sfidx && sfn == npdsch_cfg.grant.start_sfn)) {
// generate data only in first sf
INFO("%d.%d: Generating %d random bits\n", sfn, sf_idx, npdsch_cfg.grant.mcs[0].tbs);
INFO("%d.%d: Generating %d random bits", sfn, sf_idx, npdsch_cfg.grant.mcs[0].tbs);
for (int i = 0; i < npdsch_cfg.grant.mcs[0].tbs / 8; i++) {
data[i] = srslte_random_uniform_int_dist(random_gen, 0, 255);
}
@ -666,7 +664,7 @@ int main(int argc, char** argv)
}
if (npdsch_active) {
DEBUG("Current sf_idx=%d, Encoding npdsch.sf_idx=%d start=%d, nof=%d\n",
DEBUG("Current sf_idx=%d, Encoding npdsch.sf_idx=%d start=%d, nof=%d",
sf_idx,
npdsch_cfg.sf_idx,
npdsch_cfg.grant.start_sfidx,
@ -677,7 +675,7 @@ int main(int argc, char** argv)
exit(-1);
}
if (npdsch_cfg.num_sf == npdsch_cfg.grant.nof_sf * npdsch_cfg.grant.nof_rep) {
INFO("Deactive current NPDSCH\n");
INFO("Deactive current NPDSCH");
npdsch_active = false;
}
}

@ -283,7 +283,7 @@ void pcap_pack_and_write(FILE* pcap_file,
#ifndef DISABLE_RF
int srslte_rf_recv_wrapper(void* h, void* data, uint32_t nsamples, srslte_timestamp_t* t)
{
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
DEBUG(" ---- Receive %d samples ----", nsamples);
return srslte_rf_recv_with_time(h, data, nsamples, true, &t->full_secs, &t->frac_secs);
}
@ -355,7 +355,6 @@ int main(int argc, char** argv)
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
printf("Opening RF device...\n");
if (srslte_rf_open_devname(&rf, prog_args.rf_dev, prog_args.rf_args, 1)) {
fprintf(stderr, "Error opening rf\n");
@ -520,9 +519,8 @@ int main(int argc, char** argv)
srslte_npbch_decode_reset(&ue_mib.npbch);
INFO("\nEntering main loop...\n\n");
INFO("\nEntering main loop...");
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
ret = srslte_ue_sync_nbiot_zerocopy_multi(&ue_sync, buff_ptrs);
if (ret < 0) {
fprintf(stderr, "Error calling srslte_nbiot_ue_sync_zerocopy_multi()\n");
@ -713,7 +711,7 @@ int main(int argc, char** argv)
srslte_ue_sync_nbiot_get_sfidx(&ue_sync),
prog_args.rnti);
if (n == SRSLTE_SUCCESS) {
INFO("NPDSCH decoded ok.\n");
INFO("NPDSCH decoded ok.");
}
} else {
// decode NPDCCH
@ -725,7 +723,7 @@ int main(int argc, char** argv)
prog_args.rnti,
&dci_msg);
if (n == SRSLTE_NBIOT_UE_DL_FOUND_DCI) {
INFO("DCI found for rnti=%d\n", prog_args.rnti);
INFO("DCI found for rnti=%d", prog_args.rnti);
// convert DCI to grant
srslte_ra_nbiot_dl_dci_t dci_unpacked;
srslte_ra_nbiot_dl_grant_t grant;

@ -151,7 +151,6 @@ static void parse_args(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "IadglfmoncpqvutxbwMsBQ")) != -1) {
switch (opt) {
case 'I':
rf_dev = argv[optind];
@ -241,7 +240,7 @@ static void base_init()
cell.nof_ports = 2;
break;
default:
ERROR("Transmission mode %d not implemented or invalid\n", transmission_mode);
ERROR("Transmission mode %d not implemented or invalid", transmission_mode);
exit(-1);
}
@ -278,7 +277,7 @@ static void base_init()
if (output_file_name) {
if (strcmp(output_file_name, "NULL")) {
if (srslte_filesink_init(&fsink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
ERROR("Error opening file %s\n", output_file_name);
ERROR("Error opening file %s", output_file_name);
exit(-1);
}
null_file_sink = false;
@ -300,12 +299,12 @@ static void base_init()
if (net_port > 0) {
if (srslte_netsource_init(&net_source, "127.0.0.1", net_port, SRSLTE_NETSOURCE_UDP)) {
ERROR("Error creating input UDP socket at port %d\n", net_port);
ERROR("Error creating input UDP socket at port %d", net_port);
exit(-1);
}
if (null_file_sink) {
if (srslte_netsink_init(&net_sink, "127.0.0.1", net_port + 1, SRSLTE_NETSINK_TCP)) {
ERROR("Error sink\n");
ERROR("Error sink");
exit(-1);
}
}
@ -318,7 +317,7 @@ static void base_init()
/* create ifft object */
for (i = 0; i < cell.nof_ports; i++) {
if (srslte_ofdm_tx_init(&ifft[i], SRSLTE_CP_NORM, sf_buffer[i], output_buffer[i], cell.nof_prb)) {
ERROR("Error creating iFFT object\n");
ERROR("Error creating iFFT object");
exit(-1);
}
@ -326,49 +325,49 @@ static void base_init()
}
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, sf_buffer[0], output_buffer[0], cell.nof_prb)) {
ERROR("Error creating iFFT object\n");
ERROR("Error creating iFFT object");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2);
srslte_ofdm_set_normalize(&ifft_mbsfn, true);
if (srslte_pbch_init(&pbch)) {
ERROR("Error creating PBCH object\n");
ERROR("Error creating PBCH object");
exit(-1);
}
if (srslte_pbch_set_cell(&pbch, cell)) {
ERROR("Error creating PBCH object\n");
ERROR("Error creating PBCH object");
exit(-1);
}
if (srslte_regs_init(&regs, cell)) {
ERROR("Error initiating regs\n");
ERROR("Error initiating regs");
exit(-1);
}
if (srslte_pcfich_init(&pcfich, 1)) {
ERROR("Error creating PBCH object\n");
ERROR("Error creating PBCH object");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
ERROR("Error creating PBCH object\n");
ERROR("Error creating PBCH object");
exit(-1);
}
if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
ERROR("Error creating PDCCH object\n");
ERROR("Error creating PDCCH object");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
ERROR("Error creating PDCCH object\n");
ERROR("Error creating PDCCH object");
exit(-1);
}
if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) {
ERROR("Error creating PDSCH object\n");
ERROR("Error creating PDSCH object");
exit(-1);
}
if (srslte_pdsch_set_cell(&pdsch, cell)) {
ERROR("Error creating PDSCH object\n");
ERROR("Error creating PDSCH object");
exit(-1);
}
@ -376,7 +375,7 @@ static void base_init()
if (mbsfn_area_id > -1) {
if (srslte_pmch_init(&pmch, cell.nof_prb, 1)) {
ERROR("Error creating PMCH object\n");
ERROR("Error creating PMCH object");
}
srslte_pmch_set_area_id(&pmch, mbsfn_area_id);
}
@ -384,12 +383,12 @@ static void base_init()
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
if (!softbuffers[i]) {
ERROR("Error allocating soft buffer\n");
ERROR("Error allocating soft buffer");
exit(-1);
}
if (srslte_softbuffer_tx_init(softbuffers[i], cell.nof_prb)) {
ERROR("Error initiating soft buffer\n");
ERROR("Error initiating soft buffer");
exit(-1);
}
}
@ -481,7 +480,6 @@ static uint32_t prbset_to_bitmask()
static int update_radl()
{
ZERO_OBJECT(dci_dl);
/* Configure cell and PDSCH in function of the transmission mode */
@ -675,7 +673,7 @@ static void* net_thread_fnc(void* arg)
1) /
8;
rpm += n;
INFO("received %d bytes. rpm=%d/%d\n", n, rpm, nbytes);
INFO("received %d bytes. rpm=%d/%d", n, rpm, nbytes);
wpm = 0;
while (rpm >= nbytes) {
// wait for packet to be transmitted
@ -686,19 +684,19 @@ static void* net_thread_fnc(void* arg)
memcpy(data[0], &data2[wpm], nbytes / (size_t)2);
memcpy(data[1], &data2[wpm], nbytes / (size_t)2);
}
INFO("Sent %d/%d bytes ready\n", nbytes, rpm);
INFO("Sent %d/%d bytes ready", nbytes, rpm);
rpm -= nbytes;
wpm += nbytes;
net_packet_ready = true;
}
if (wpm > 0) {
INFO("%d bytes left in buffer for next packet\n", rpm);
INFO("%d bytes left in buffer for next packet", rpm);
memcpy(data2, &data2[wpm], rpm * sizeof(uint8_t));
}
} else if (n == 0) {
rpm = 0;
} else {
ERROR("Error receiving from network\n");
ERROR("Error receiving from network");
exit(-1);
}
} while (true);
@ -757,22 +755,22 @@ int main(int argc, char** argv)
/* Generate reference signals */
if (srslte_refsignal_cs_init(&csr_refs, cell.nof_prb)) {
ERROR("Error initializing equalizer\n");
ERROR("Error initializing equalizer");
exit(-1);
}
if (mbsfn_area_id > -1) {
if (srslte_refsignal_mbsfn_init(&mbsfn_refs, cell.nof_prb)) {
ERROR("Error initializing equalizer\n");
ERROR("Error initializing equalizer");
exit(-1);
}
if (srslte_refsignal_mbsfn_set_cell(&mbsfn_refs, cell, mbsfn_area_id)) {
ERROR("Error initializing MBSFNR signal\n");
ERROR("Error initializing MBSFNR signal");
exit(-1);
}
}
if (srslte_refsignal_cs_set_cell(&csr_refs, cell)) {
ERROR("Error setting cell\n");
ERROR("Error setting cell");
exit(-1);
}
@ -789,17 +787,16 @@ int main(int argc, char** argv)
signal(SIGINT, sig_int_handler);
if (!output_file_name) {
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
printf("Setting sampling rate %.2f MHz\n", (float)srate / 1000000);
float srate_rf = srslte_rf_set_tx_srate(&radio, (double)srate);
if (srate_rf != srate) {
ERROR("Could not set sampling rate\n");
ERROR("Could not set sampling rate");
exit(-1);
}
} else {
ERROR("Invalid number of PRB %d\n", cell.nof_prb);
ERROR("Invalid number of PRB %d", cell.nof_prb);
exit(-1);
}
srslte_rf_set_tx_gain(&radio, rf_gain);
@ -885,17 +882,17 @@ int main(int argc, char** argv)
/* Update DL resource allocation from control port */
if (update_control()) {
ERROR("Error updating parameters from control port\n");
ERROR("Error updating parameters from control port");
}
/* Transmit PDCCH + PDSCH only when there is data to send */
if ((net_port > 0) && (mch_table[sf_idx] == 1 && mbsfn_area_id > -1)) {
send_data = net_packet_ready;
if (net_packet_ready) {
INFO("Transmitting packet from port\n");
INFO("Transmitting packet from port");
}
} else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.tb[0].tbs + pdsch_cfg.grant.tb[1].tbs);
INFO("SF: %d, Generating %d random bits", sf_idx, pdsch_cfg.grant.tb[0].tbs + pdsch_cfg.grant.tb[1].tbs);
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (pdsch_cfg.grant.tb[tb].enabled) {
for (i = 0; i < pdsch_cfg.grant.tb[tb].tbs / 8; i++) {
@ -915,24 +912,24 @@ int main(int argc, char** argv)
dl_sf.sf_type = SRSLTE_SF_NORM;
/* Encode PDCCH */
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
INFO("Putting DCI to location: n=%d, L=%d", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
srslte_dci_msg_pack_pdsch(&cell, &dl_sf, NULL, &dci_dl, &dci_msg);
dci_msg.location = locations[sf_idx][0];
if (srslte_pdcch_encode(&pdcch, &dl_sf, &dci_msg, sf_symbols)) {
ERROR("Error encoding DCI message\n");
ERROR("Error encoding DCI message");
exit(-1);
}
/* Configure pdsch_cfg parameters */
if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, transmission_mode, enable_256qam, &dci_dl, &pdsch_cfg.grant)) {
ERROR("Error configuring PDSCH\n");
ERROR("Error configuring PDSCH");
exit(-1);
}
/* Encode PDSCH */
if (srslte_pdsch_encode(&pdsch, &dl_sf, &pdsch_cfg, data, sf_symbols)) {
ERROR("Error encoding PDSCH\n");
ERROR("Error encoding PDSCH");
exit(-1);
}
if (net_port > 0 && net_packet_ready) {
@ -940,7 +937,7 @@ int main(int argc, char** argv)
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.tb[tb].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.tb[tb].tbs - 1) / 8) < 0) {
ERROR("Error sending data through UDP socket\n");
ERROR("Error sending data through UDP socket");
}
}
}
@ -961,7 +958,7 @@ int main(int argc, char** argv)
/* Configure pdsch_cfg parameters */
if (srslte_ra_dl_dci_to_grant(&cell, &dl_sf, SRSLTE_TM1, enable_256qam, &dci_dl, &pmch_cfg.pdsch_cfg.grant)) {
ERROR("Error configuring PDSCH\n");
ERROR("Error configuring PDSCH");
exit(-1);
}
@ -973,14 +970,14 @@ int main(int argc, char** argv)
/* Encode PMCH */
if (srslte_pmch_encode(&pmch, &dl_sf, &pmch_cfg, data_mbms, sf_symbols)) {
ERROR("Error encoding PDSCH\n");
ERROR("Error encoding PDSCH");
exit(-1);
}
if (net_port > 0 && net_packet_ready) {
if (null_file_sink) {
srslte_bit_pack_vector(data[0], data_tmp, pmch_cfg.pdsch_cfg.grant.tb[0].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pmch_cfg.pdsch_cfg.grant.tb[0].tbs - 1) / 8) < 0) {
ERROR("Error sending data through UDP socket\n");
ERROR("Error sending data through UDP socket");
}
}
net_packet_ready = false;

@ -346,7 +346,7 @@ cf_t* sf_buffer[SRSLTE_MAX_PORTS] = {NULL};
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);
DEBUG(" ---- Receive %d samples ----", nsamples);
void* ptr[SRSLTE_MAX_PORTS];
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
ptr[i] = data_[i];
@ -424,7 +424,6 @@ int main(int argc, char** argv)
generate_mcch_table(mch_table, prog_args.mbsfn_sf_mask);
}
if (prog_args.cpu_affinity > -1) {
cpu_set_t cpuset;
pthread_t thread;
@ -435,7 +434,7 @@ int main(int argc, char** argv)
CPU_SET((size_t)i, &cpuset);
}
if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset)) {
ERROR("Error setting main thread affinity to %d \n", prog_args.cpu_affinity);
ERROR("Error setting main thread affinity to %d", prog_args.cpu_affinity);
exit(-1);
}
}
@ -443,7 +442,7 @@ int main(int argc, char** argv)
if (prog_args.net_port > 0) {
if (srslte_netsink_init(&net_sink, prog_args.net_address, prog_args.net_port, SRSLTE_NETSINK_UDP)) {
ERROR("Error initiating UDP socket to %s:%d\n", prog_args.net_address, prog_args.net_port);
ERROR("Error initiating UDP socket to %s:%d", prog_args.net_address, prog_args.net_port);
exit(-1);
}
srslte_netsink_set_nonblocking(&net_sink);
@ -451,7 +450,7 @@ int main(int argc, char** argv)
if (prog_args.net_port_signal > 0) {
if (srslte_netsink_init(
&net_sink_signal, prog_args.net_address_signal, prog_args.net_port_signal, SRSLTE_NETSINK_UDP)) {
ERROR("Error initiating UDP socket to %s:%d\n", prog_args.net_address_signal, prog_args.net_port_signal);
ERROR("Error initiating UDP socket to %s:%d", prog_args.net_address_signal, prog_args.net_port_signal);
exit(-1);
}
srslte_netsink_set_nonblocking(&net_sink_signal);
@ -461,7 +460,6 @@ int main(int argc, char** argv)
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
printf("Opening RF device with %d RX antennas...\n", prog_args.rf_nof_rx_ant);
if (srslte_rf_open_devname(&rf, prog_args.rf_dev, prog_args.rf_args, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error opening rf\n");
@ -473,7 +471,7 @@ int main(int argc, char** argv)
} else {
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
exit(-1);
}
srslte_rf_set_rx_gain(&rf, srslte_rf_get_rx_gain(&rf));
@ -495,7 +493,7 @@ int main(int argc, char** argv)
ret = rf_search_and_decode_mib(
&rf, prog_args.rf_nof_rx_ant, &cell_detect_config, prog_args.force_N_id_2, &cell, &search_cell_cfo);
if (ret < 0) {
ERROR("Error searching for cell\n");
ERROR("Error searching for cell");
exit(-1);
} else if (ret == 0 && !go_exit) {
printf("Cell not found after %d trials. Trying again (Press Ctrl+C to exit)\n", ntrial++);
@ -513,11 +511,11 @@ int main(int argc, char** argv)
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) {
ERROR("Could not set sampling rate\n");
ERROR("Could not set sampling rate");
exit(-1);
}
} else {
ERROR("Invalid number of PRB %d\n", cell.nof_prb);
ERROR("Invalid number of PRB %d", cell.nof_prb);
exit(-1);
}
@ -541,7 +539,7 @@ int main(int argc, char** argv)
prog_args.file_offset_time,
prog_args.file_offset_freq,
prog_args.rf_nof_rx_ant)) {
ERROR("Error initiating ue_sync\n");
ERROR("Error initiating ue_sync");
exit(-1);
}
@ -562,11 +560,11 @@ int main(int argc, char** argv)
prog_args.rf_nof_rx_ant,
(void*)&rf,
decimate)) {
ERROR("Error initiating ue_sync\n");
ERROR("Error initiating ue_sync");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
ERROR("Error initiating ue_sync\n");
ERROR("Error initiating ue_sync");
exit(-1);
}
#endif
@ -578,20 +576,20 @@ int main(int argc, char** argv)
}
srslte_ue_mib_t ue_mib;
if (srslte_ue_mib_init(&ue_mib, sf_buffer[0], cell.nof_prb)) {
ERROR("Error initaiting UE MIB decoder\n");
ERROR("Error initaiting UE MIB decoder");
exit(-1);
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
ERROR("Error initaiting UE MIB decoder\n");
ERROR("Error initaiting UE MIB decoder");
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
ERROR("Error initiating UE downlink processing module\n");
ERROR("Error initiating UE downlink processing module");
exit(-1);
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
ERROR("Error initiating UE downlink processing module\n");
ERROR("Error initiating UE downlink processing module");
exit(-1);
}
@ -676,7 +674,7 @@ int main(int argc, char** argv)
srslte_pbch_decode_reset(&ue_mib.pbch);
INFO("\nEntering main loop...\n\n");
INFO("\nEntering main loop...");
// Variables for measurements
uint32_t nframes = 0;
@ -724,7 +722,7 @@ int main(int argc, char** argv)
}
ret = srslte_ue_sync_zerocopy(&ue_sync, buffers, max_num_samples);
if (ret < 0) {
ERROR("Error calling srslte_ue_sync_work()\n");
ERROR("Error calling srslte_ue_sync_work()");
}
#ifdef CORRECT_SAMPLE_OFFSET
@ -735,7 +733,6 @@ int main(int argc, char** argv)
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
struct timeval t[3];
@ -748,7 +745,7 @@ int main(int argc, char** argv)
int sfn_offset;
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) {
ERROR("Error decoding UE MIB\n");
ERROR("Error decoding UE MIB");
exit(-1);
} else if (n == SRSLTE_UE_MIB_FOUND) {
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
@ -833,7 +830,6 @@ int main(int argc, char** argv)
get_time_interval(t);
if (n > 0) {
/* Send data if socket active */
if (prog_args.net_port > 0) {
if (sf_idx == 1) {
@ -1143,7 +1139,6 @@ void* plot_thread_run(void* arg)
void init_plots()
{
if (sem_init(&plot_sem, 0, 0)) {
perror("sem_init");
exit(-1);

@ -210,7 +210,7 @@ void parse_args(prog_args_t* args, int argc, char** argv)
#ifndef DISABLE_RF
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);
DEBUG(" ---- Receive %d samples ----", nsamples);
void* ptr[SRSLTE_MAX_PORTS];
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
ptr[i] = data[i];
@ -238,7 +238,7 @@ int main(int argc, char** argv)
srslte_sl_comm_resource_pool_t sl_comm_resource_pool;
if (srslte_sl_comm_resource_pool_get_default_config(&sl_comm_resource_pool, cell_sl) != SRSLTE_SUCCESS) {
ERROR("Error initializing sl_comm_resource_pool\n");
ERROR("Error initializing sl_comm_resource_pool");
return SRSLTE_ERROR;
}
@ -254,7 +254,7 @@ int main(int argc, char** argv)
printf("Opening RF device...\n");
if (srslte_rf_open_multi(&radio, prog_args.rf_args, prog_args.nof_rx_antennas)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
exit(-1);
}
@ -269,11 +269,11 @@ int main(int argc, char** argv)
printf("Setting sampling rate %.2f MHz\n", (float)srate / 1000000);
float srate_rf = srslte_rf_set_rx_srate(&radio, (double)srate);
if (srate_rf != srate) {
ERROR("Could not set sampling rate\n");
ERROR("Could not set sampling rate");
exit(-1);
}
} else {
ERROR("Invalid number of PRB %d\n", cell_sl.nof_prb);
ERROR("Invalid number of PRB %d", cell_sl.nof_prb);
exit(-1);
}
}
@ -316,7 +316,7 @@ int main(int argc, char** argv)
ofdm_cfg.out_buffer = sf_buffer[0];
if (srslte_ofdm_rx_init_cfg(&fft[i], &ofdm_cfg)) {
ERROR("Error initiating FFT\n");
ERROR("Error initiating FFT");
goto clean_exit;
}
}
@ -329,12 +329,12 @@ int main(int argc, char** argv)
// init PSCCH object
if (srslte_pscch_init(&pscch, SRSLTE_MAX_PRB) != SRSLTE_SUCCESS) {
ERROR("Error in PSCCH init\n");
ERROR("Error in PSCCH init");
return SRSLTE_ERROR;
}
if (srslte_pscch_set_cell(&pscch, cell_sl) != SRSLTE_SUCCESS) {
ERROR("Error in PSCCH set cell\n");
ERROR("Error in PSCCH set cell");
return SRSLTE_ERROR;
}
@ -342,19 +342,19 @@ int main(int argc, char** argv)
srslte_chest_sl_cfg_t pscch_chest_sl_cfg = {};
srslte_chest_sl_t pscch_chest = {};
if (srslte_chest_sl_init(&pscch_chest, SRSLTE_SIDELINK_PSCCH, cell_sl, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error in chest PSCCH init\n");
ERROR("Error in chest PSCCH init");
return SRSLTE_ERROR;
}
if (srslte_pssch_init(&pssch, cell_sl, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error initializing PSSCH\n");
ERROR("Error initializing PSSCH");
return SRSLTE_ERROR;
}
srslte_chest_sl_cfg_t pssch_chest_sl_cfg = {};
srslte_chest_sl_t pssch_chest = {};
if (srslte_chest_sl_init(&pssch_chest, SRSLTE_SIDELINK_PSSCH, cell_sl, sl_comm_resource_pool) != SRSLTE_SUCCESS) {
ERROR("Error in chest PSSCH init\n");
ERROR("Error in chest PSSCH init");
return SRSLTE_ERROR;
}
@ -382,7 +382,7 @@ int main(int argc, char** argv)
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
ERROR("Error initiating ue_sync\n");
ERROR("Error initiating ue_sync");
exit(-1);
}
@ -423,7 +423,7 @@ int main(int argc, char** argv)
// receive subframe from radio
int ret = srslte_ue_sync_zerocopy(&ue_sync, rx_buffer, sf_len);
if (ret < 0) {
ERROR("Error calling srslte_ue_sync_work()\n");
ERROR("Error calling srslte_ue_sync_work()");
}
// update SF index
@ -438,7 +438,6 @@ int main(int argc, char** argv)
pscch_prb_start_idx = sub_channel_idx * sl_comm_resource_pool.size_sub_channel;
for (uint32_t cyclic_shift = 0; cyclic_shift <= 9; cyclic_shift += 3) {
// PSCCH Channel estimation
pscch_chest_sl_cfg.cyclic_shift = cyclic_shift;
pscch_chest_sl_cfg.prb_start_idx = pscch_prb_start_idx;

@ -127,11 +127,11 @@ int main(int argc, char** argv)
fflush(stdout);
if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
ERROR("Error opening file %s\n", input_file_name);
ERROR("Error opening file %s", input_file_name);
exit(-1);
}
if (srslte_filesink_init(&fsink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
ERROR("Error opening file %s\n", output_file_name);
ERROR("Error opening file %s", output_file_name);
exit(-1);
}
@ -152,7 +152,7 @@ int main(int argc, char** argv)
}
if (srslte_cfo_init(&cfocorr, frame_length)) {
ERROR("Error initiating CFO\n");
ERROR("Error initiating CFO");
return -1;
}
@ -163,19 +163,19 @@ int main(int argc, char** argv)
*/
for (N_id_2 = 0; N_id_2 < 3; N_id_2++) {
if (srslte_pss_init_fft(&pss[N_id_2], frame_length, symbol_sz)) {
ERROR("Error initializing PSS object\n");
ERROR("Error initializing PSS object");
exit(-1);
}
if (srslte_pss_set_N_id_2(&pss[N_id_2], N_id_2)) {
ERROR("Error initializing N_id_2\n");
ERROR("Error initializing N_id_2");
exit(-1);
}
if (srslte_sss_init(&sss[N_id_2], symbol_sz)) {
ERROR("Error initializing SSS object\n");
ERROR("Error initializing SSS object");
exit(-1);
}
if (srslte_sss_set_N_id_2(&sss[N_id_2], N_id_2)) {
ERROR("Error initializing N_id_2\n");
ERROR("Error initializing N_id_2");
exit(-1);
}
}
@ -189,7 +189,6 @@ int main(int argc, char** argv)
/* read all file or nof_frames */
frame_cnt = 0;
while (frame_length == srslte_filesource_read(&fsrc, input, frame_length) && frame_cnt < nof_frames) {
gettimeofday(&tdata[1], NULL);
if (force_cfo != CFO_AUTO) {
srslte_cfo_correct(&cfocorr, input, input, force_cfo / 128);
@ -215,7 +214,6 @@ int main(int argc, char** argv)
/* If peak detected */
if (peak_value[N_id_2] > corr_peak_threshold) {
sss_idx = peak_pos[N_id_2] - 2 * (symbol_sz + SRSLTE_CP_LEN(symbol_sz, SRSLTE_CP_NORM_LEN));
if (sss_idx >= 0) {
srslte_sss_m0m1_diff(&sss[N_id_2], &input[sss_idx], &m0, &m0_value, &m1, &m1_value);

@ -122,9 +122,9 @@ int main(int argc, char** argv)
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
printf("Opening RF device...\n");
printf("Opening RF device...");
if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
exit(-1);
}
@ -141,7 +141,7 @@ int main(int argc, char** argv)
if (srate != 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);
ERROR("Error setting samplign frequency %.2f MHz", rf_rate * 1e-6);
exit(-1);
}
}
@ -152,7 +152,7 @@ int main(int argc, char** argv)
while ((sample_count < nof_samples || nof_samples == -1) && keep_running) {
n = srslte_rf_recv_with_time_multi(&rf, (void**)buffer, buflen, true, NULL, NULL);
if (n < 0) {
ERROR("Error receiving samples\n");
ERROR("Error receiving samples");
exit(-1);
}

@ -120,7 +120,7 @@ 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);
DEBUG(" ---- Receive %d samples ----", nsamples);
void* ptr[SRSLTE_MAX_PORTS];
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
ptr[i] = data[i];
@ -147,7 +147,7 @@ int main(int argc, char** argv)
printf("Opening RF device...\n");
if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
exit(-1);
}
@ -169,11 +169,11 @@ int main(int argc, char** argv)
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) {
ERROR("Could not set sampling rate\n");
ERROR("Could not set sampling rate");
exit(-1);
}
} else {
ERROR("Invalid number of PRB %d\n", nof_prb);
ERROR("Invalid number of PRB %d", nof_prb);
exit(-1);
}
srslte_rf_start_rx_stream(&rf, false);
@ -189,7 +189,7 @@ int main(int argc, char** argv)
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
ERROR("Error initiating ue_sync\n");
ERROR("Error initiating ue_sync");
exit(-1);
}
@ -200,7 +200,7 @@ int main(int argc, char** argv)
while ((subframe_count < nof_subframes || nof_subframes == -1) && !stop_capture) {
n = srslte_ue_sync_zerocopy(&ue_sync, buffer, max_num_samples);
if (n < 0) {
ERROR("Error receiving samples\n");
ERROR("Error receiving samples");
exit(-1);
}
if (n == 1) {

@ -92,7 +92,7 @@ void parse_args(int argc, char** argv)
int srslte_rf_recv_wrapper(void* h, void* data, uint32_t nsamples, srslte_timestamp_t* t)
{
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
DEBUG(" ---- Receive %d samples ----", nsamples);
return srslte_rf_recv(h, data, nsamples, 1);
}

@ -85,7 +85,7 @@ void parse_args(int argc, char** argv)
case 'p':
nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
if (!srslte_nofprb_isvalid(nof_prb)) {
ERROR("Invalid number of UL RB %d\n", nof_prb);
ERROR("Invalid number of UL RB %d", nof_prb);
exit(-1);
}
break;
@ -137,7 +137,7 @@ int main(int argc, char** argv)
srslte_rf_t rf;
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
exit(-1);
}

@ -96,12 +96,12 @@ int main(int argc, char** argv)
// Initializes ZMQ
if (init_zmq()) {
ERROR("Initializing ZMQ\n");
ERROR("Initializing ZMQ");
exit(-1);
}
if (init_radio(&buflen)) {
ERROR("Initializing Radio\n");
ERROR("Initializing Radio");
exit(-1);
}
@ -120,7 +120,7 @@ int main(int argc, char** argv)
while (keep_running) {
n = rx_radio(buffer, buflen);
if (n < 0) {
ERROR("Error receiving samples\n");
ERROR("Error receiving samples");
exit(-1);
}
if (srslte_verbose == SRSLTE_VERBOSE_INFO) {
@ -166,7 +166,7 @@ static int init_radio(uint32_t* buffer_len)
// Uses srsLTE RF API to open a device, could use other code here
printf("Opening RF device...\n");
if (srslte_rf_open_multi(&radio, rf_args, nof_rx_antennas)) {
ERROR("Error opening rf\n");
ERROR("Error opening rf");
return -1;
}
srslte_rf_set_rx_gain(&radio, rf_gain);
@ -176,7 +176,7 @@ static int init_radio(uint32_t* buffer_len)
printf("Set RX gain: %.2f dB\n", rf_gain);
float srate = srslte_rf_set_rx_srate(&radio, rf_rate);
if (srate != rf_rate) {
ERROR("Error setting samplign frequency %.2f MHz\n", rf_rate * 1e-6);
ERROR("Error setting samplign frequency %.2f MHz", rf_rate * 1e-6);
return -1;
}

@ -44,6 +44,9 @@ class circular_array
std::array<T, N> data{};
public:
using iterator = T*;
using const_iterator = const T*;
T& operator[](std::size_t pos) { return data[pos % N]; }
const T& operator[](std::size_t pos) const { return data[pos % N]; }
@ -52,6 +55,8 @@ public:
T* end() { return data.end(); }
const T* end() const { return data.end(); }
size_t size() const { return N; }
};
} // namespace srslte

@ -241,6 +241,9 @@ inline bool operator!=(span<T> lhs, span<T> rhs)
return not lhs.equals(rhs);
}
template <typename T>
using const_span = span<const T>;
} // namespace srslte
#endif // SRSLTE_SPAN_H

@ -22,14 +22,14 @@
#ifndef SRSASN_COMMON_UTILS_H
#define SRSASN_COMMON_UTILS_H
#include "srslte/srslog/bundled/fmt/format.h"
#include "srslte/srslog/srslog.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <limits>
#include <map>
#include <stdint.h>
#include <string>
#include <vector>
@ -62,10 +62,29 @@ struct static_max<arg1, arg2, others...> {
logging
************************/
void log_error(const char* format, ...);
void log_warning(const char* format, ...);
void log_info(const char* format, ...);
void log_debug(const char* format, ...);
template <typename... Args>
void log_error(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("ASN1").error(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_warning(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("ASN1").warning(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_info(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("ASN1").info(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_debug(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("ASN1").debug(format, std::forward<Args>(args)...);
}
void warn_assert(bool cond, const char* filename, int lineno);
void log_invalid_access_choice_id(uint32_t val, uint32_t choice_id);
@ -226,7 +245,7 @@ public:
iterator erase(iterator it)
{
if (it < begin() or it >= end()) {
log_warning("Trying to access out-of-bounds iterator.\n");
log_warning("Trying to access out-of-bounds iterator.");
return end();
}
@ -281,7 +300,7 @@ public:
void push_back(const T& elem)
{
if (current_size >= MAX_N) {
log_error("Maximum size %d achieved for bounded_array.\n", MAX_N);
log_error("Maximum size %d achieved for bounded_array.", MAX_N);
return;
}
data_[current_size++] = elem;
@ -645,7 +664,7 @@ public:
fixed_octstring<N, aligned>& from_string(const std::string& hexstr)
{
if (hexstr.size() != 2 * N) {
log_error("The provided hex string size is not valid (%zd!=2*%zd).\n", hexstr.size(), (size_t)N);
log_error("The provided hex string size is not valid (%zd!=2*%zd).", hexstr.size(), (size_t)N);
} else {
string_to_octstring(&octets_[0], hexstr);
}
@ -716,7 +735,7 @@ public:
bounded_octstring<LB, UB, aligned>& from_string(const std::string& hexstr)
{
if (hexstr.size() > 2 * UB) {
log_error("The provided hex string size is not valid (%zd>2*%zd).\n", hexstr.size(), (size_t)UB);
log_error("The provided hex string size is not valid (%zd>2*%zd).", hexstr.size(), (size_t)UB);
} else {
resize(hexstr.size() / 2);
string_to_octstring(&octets_[0], hexstr);
@ -877,7 +896,8 @@ public:
this_type& from_string(const std::string& s)
{
if (s.size() < lb or s.size() > ub) {
log_error("The provided string size=%zd is not withing the bounds [%d, %d]\n", s.size(), lb, ub);
log_error(
"The provided string size=%zd is not withing the bounds [%d, %d]", s.size(), uint32_t(lb), uint32_t(ub));
} else {
resize(s.size());
for (uint32_t i = 0; i < s.size(); ++i) {
@ -893,7 +913,7 @@ public:
{
auto nof_bits_ = std::max((uint32_t)ceilf(log2(std::max(val, (uint64_t)1u))), LB);
if (nof_bits_ > UB) {
log_error("The provided bitstring value %ld does not fit the bounds [%d, %d]\n", val, lb, ub);
log_error("The provided bitstring value %ld does not fit the bounds [%d, %d]", val, uint32_t(lb), uint32_t(ub));
return *this;
}
resize(nof_bits_);
@ -1366,17 +1386,17 @@ int test_pack_unpack_consistency(const Msg& msg)
// unpack and last pack done for the same number of bits
if (bref3.distance() != bref2.distance()) {
log_error("[%s][%d] .\n", __FILE__, __LINE__);
log_error("[%s][%d] .", __FILE__, __LINE__);
return -1;
}
// ensure packed messages are the same
if (bref3.distance() != bref.distance()) {
log_error("[%s][%d] .\n", __FILE__, __LINE__);
log_error("[%s][%d] .", __FILE__, __LINE__);
return -1;
}
if (memcmp(buf, buf2, bref.distance_bytes()) != 0) {
log_error("[%s][%d] .\n", __FILE__, __LINE__);
log_error("[%s][%d] .", __FILE__, __LINE__);
return -1;
}
return SRSASN_SUCCESS;

@ -31,7 +31,7 @@
// Caution these values must match SRSLTE_ ones in common.h
#define LIBLTE_MAX_MSG_SIZE_BITS 102048
#define LIBLTE_MAX_MSG_SIZE_BYTES 12756
#define LIBLTE_MAX_MSG_SIZE_BYTES 12237
#define LIBLTE_MSG_HEADER_OFFSET 1020
// Macro to make it easier to convert defines into strings
@ -86,11 +86,12 @@ typedef struct {
uint8 msg[LIBLTE_MAX_MSG_SIZE_BITS];
} LIBLTE_BIT_MSG_STRUCT __attribute__((aligned(8)));
typedef struct {
struct alignas(8) LIBLTE_BYTE_MSG_STRUCT
{
uint32 N_bytes;
uint8 header[LIBLTE_MSG_HEADER_OFFSET];
uint8 msg[LIBLTE_MAX_MSG_SIZE_BYTES];
} LIBLTE_BYTE_MSG_STRUCT;
};
/*******************************************************************************
DECLARATIONS

@ -2467,6 +2467,15 @@ private:
elem_type_paramT_ c;
};
template <class elem_type_paramT_>
std::string setup_release_c<elem_type_paramT_>::types_opts::to_string() const
{
static const char* options[] = {"release", "setup"};
return convert_enum_idx(options, 2, value, "setup_release_c::types");
}
// UAC-BarringPerCat ::= SEQUENCE
struct uac_barr_per_cat_s {
uint8_t access_category = 1;

@ -39,6 +39,7 @@ struct sib1_s;
struct rlc_cfg_c;
struct pdcp_cfg_s;
struct lc_ch_cfg_s;
struct rach_cfg_common_s;
} // namespace rrc_nr
} // namespace asn1
@ -55,6 +56,7 @@ void to_asn1(asn1::rrc_nr::plmn_id_s* asn1_type, const plmn_id_t& cfg);
* MAC Config
**************************/
logical_channel_config_t make_mac_logical_channel_cfg_t(uint8_t lcid, const asn1::rrc_nr::lc_ch_cfg_s& asn1_type);
rach_nr_cfg_t make_mac_rach_cfg(const asn1::rrc_nr::rach_cfg_common_s& asn1_type);
/***************************
* RLC Config
**************************/

@ -84,7 +84,6 @@ struct ue_eutra_cap_s;
* Conversion Helpers
***********************/
namespace srslte {
plmn_id_t make_plmn_id_t(const asn1::rrc::plmn_id_s& asn1_type);
void to_asn1(asn1::rrc::plmn_id_s* asn1_type, const plmn_id_t& cfg);
plmn_id_t make_plmn_id_t(const asn1::fixed_octstring<3, true>& asn1_type);
@ -105,6 +104,7 @@ void to_asn1(asn1::rrc::rlc_cfg_c* asn1_type, const rlc_config_t& cfg);
**************************/
srslte::pdcp_config_t make_srb_pdcp_config_t(const uint8_t bearer_id, bool is_ue);
srslte::pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue);
uint8_t get_pdcp_drb_sn_len(const asn1::rrc::pdcp_cfg_s& pdcp_cfg);
srslte::pdcp_config_t
make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue, const asn1::rrc::pdcp_cfg_s& pdcp_cfg);

@ -45,6 +45,8 @@ struct rrc_establishment_cause_opts;
struct cause_radio_network_opts;
struct bearers_subject_to_status_transfer_item_ies_o;
struct erab_level_qos_params_s;
struct ho_cmd_s;
struct erab_admitted_item_s;
template <class ies_set_paramT_>
struct protocol_ie_single_container_s;

File diff suppressed because it is too large Load Diff

@ -0,0 +1,106 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_BAND_HELPER_H
#define SRSLTE_BAND_HELPER_H
#include <array>
#include <stdint.h>
#include <vector>
namespace srslte {
// Helper class to handle frequency bands and ARFCNs
// For NR: NR-ARFCN and channel raster as per TS 38.104
class srslte_band_helper
{
public:
srslte_band_helper() = default;
~srslte_band_helper() = default;
// Return frequency of given NR-ARFCN in Hz
double nr_arfcn_to_freq(uint32_t nr_arfcn);
// Possible values of delta f_raster in Table 5.4.2.3-1 and Table 5.4.2.3-2
enum delta_f_raster_t {
DEFAULT = 0, // for bands with 2 possible values for delta_f_raster (e.g. 15 and 30 kHz), the lower is chosen
KHZ_15,
KHZ_30,
KHZ_60,
KHZ_100,
KHZ_120
};
// Return vector of bands that ARFCN is valid for
// For bands with 2 possible raster offsets, delta_f_raster needs to be specified
std::vector<uint32_t> get_bands_nr(uint32_t nr_arfcn, delta_f_raster_t delta_f_raster = DEFAULT);
private:
// Table 5.4.2.1-1
struct nr_raster_params {
double delta_F_global_kHz;
double F_REF_Offs_MHz;
uint32_t N_REF_Offs;
uint32_t N_REF_min;
uint32_t N_REF_max;
};
// Helper to calculate F_REF according to Table 5.4.2.1-1
nr_raster_params get_raster_params(uint32_t nr_arfcn);
static const uint32_t max_nr_arfcn = 3279165;
static constexpr std::array<nr_raster_params, 3> nr_fr_params = {{
// clang-format off
// Frequency range 0 - 3000 MHz
{5, 0.0, 0, 0, 599999},
// Frequency range 3000 - 24250 MHz
{15, 3000.0, 600000, 600000, 2016666},
// Frequency range 24250 - 100000 MHz
{60, 24250.08, 2016667, 2016667, max_nr_arfcn}
// clang-format on
}};
// Elements of Table 5.4.2.3-1 in TS 38.104
struct nr_band {
uint8_t band;
delta_f_raster_t delta_f_raster;
uint32_t ul_nref_first;
uint32_t ul_nref_step;
uint32_t ul_nref_last;
uint32_t dl_nref_first;
uint32_t dl_nref_step;
uint32_t dl_nref_last;
};
// List of NR bands for FR1 (Table 5.4.2.3-1)
// bands with more than one raster offset have multiple entries
// TODO: add remaining bands
static const uint32_t nof_nr_bands_fr1 = 7;
static constexpr std::array<nr_band, nof_nr_bands_fr1> nr_band_table_fr1 = {{
// clang-format off
{74, KHZ_100, 285400, 20, 294000, 295000, 20, 303600},
// n75+n76 missing
{77, KHZ_15, 620000, 1, 680000, 620000, 1, 680000},
{77, KHZ_30, 620000, 2, 680000, 620000, 2, 680000},
{78, KHZ_15, 620000, 1, 653333, 620000, 1, 653333},
{78, KHZ_30, 620000, 2, 653332, 620000, 2, 653332},
{79, KHZ_15, 693334, 2, 733333, 693334, 2, 733333},
{79, KHZ_30, 693334, 2, 733332, 693334, 2, 733332}
// clang-format on
}};
};
} // namespace srslte
#endif // SRSLTE_BAND_HELPER_H

@ -27,7 +27,7 @@
#include "srslte/adt/choice_type.h"
#include "srslte/common/block_queue.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/logmap.h"
#include "srslte/srslog/srslog.h"
#include <arpa/inet.h>
#include <atomic>
#include <errno.h>
@ -83,7 +83,8 @@ public:
rand_gen(RAND_SEED),
rand_dist(MIN_TB_LEN, MAX_TB_LEN)
{
log_h->set_level(srslte::LOG_LEVEL_WARNING);
logger.set_level(srslog::basic_levels::warning);
logger.set_hex_dump_max_size(-1);
}
~srslte_basic_pnf() { stop(); };
@ -323,7 +324,7 @@ private:
{
basic_vnf_api::msg_header_t* header = (basic_vnf_api::msg_header_t*)buffer;
log_h->debug("Received %s (%d B) in TTI\n", basic_vnf_api::msg_type_text[header->type], len);
logger.debug("Received %s (%d B) in TTI", basic_vnf_api::msg_type_text[header->type], len);
switch (header->type) {
case basic_vnf_api::SF_IND:
@ -370,7 +371,7 @@ private:
if (rf_out_queue != nullptr) {
uint32_t len = sizeof(*msg) - sizeof(msg->pdus->data) + msg->pdus->length;
srslte::unique_byte_buffer_t tx = srslte::allocate_unique_buffer(*pool);
srslte::unique_byte_buffer_t tx = srslte::make_byte_buffer();
memcpy(tx->msg, msg, len);
rf_out_queue->push(std::move(tx));
}
@ -461,8 +462,8 @@ private:
dl_ind.pdus[i].type = tx_req->pdus[i].type;
memcpy(dl_ind.pdus[i].data, tx_req->pdus[i].data, dl_ind.pdus[i].length);
tot_bytes += dl_ind.pdus[i].length;
log_h->info_hex(
dl_ind.pdus[i].data, dl_ind.pdus[i].length, "Sending to UE a PDU (%d bytes)\n", dl_ind.pdus[i].length);
logger.info(
dl_ind.pdus[i].data, dl_ind.pdus[i].length, "Sending to UE a PDU (%d bytes)", dl_ind.pdus[i].length);
}
}
} else {
@ -479,7 +480,7 @@ private:
tot_bytes = N_bytes;
}
log_h->info_hex(dl_ind.pdus[0].data, N_bytes, "Sending to UE a TB (%d bytes)\n", N_bytes);
logger.info(dl_ind.pdus[0].data, N_bytes, "Sending to UE a TB (%d bytes)", N_bytes);
}
if (tot_bytes > 0 and tot_bytes < tb_size) {
@ -518,8 +519,7 @@ private:
std::unique_ptr<std::thread> tx_thread, rx_thread;
std::string tx_thread_name = "TX_PNF", rx_thread_name = "RX_PNF";
bool running = false;
srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance();
srslte::log_ref log_h{"PNF"};
srslog::basic_logger& logger = srslog::fetch_basic_logger("PNF", false);
std::mutex mutex;
std::atomic<std::uint32_t> tti;

@ -24,10 +24,10 @@
#include "basic_vnf_api.h"
#include "common.h"
#include "srslte/common/logmap.h"
#include "srslte/common/threads.h"
#include "srslte/interfaces/gnb_interfaces.h"
#include "srslte/interfaces/ue_nr_interfaces.h"
#include "srslte/srslog/srslog.h"
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@ -44,7 +44,7 @@ namespace srslte {
class srslte_basic_vnf : public thread
{
public:
srslte_basic_vnf(const vnf_args_t& args_, srslte::logger* logger_, stack_interface_phy_nr* stack_);
srslte_basic_vnf(const vnf_args_t& args_, stack_interface_phy_nr* stack_);
~srslte_basic_vnf();
bool stop();
@ -69,11 +69,9 @@ private:
// helpers
uint32_t calc_full_msg_len(const basic_vnf_api::tx_request_msg_t& msg);
srslte::logger* m_logger = nullptr;
srslte::log_ref log_h;
srslog::basic_logger& logger = srslog::fetch_basic_logger("VNF", false);
srsenb::stack_interface_phy_nr* m_gnb_stack = nullptr;
srsue::stack_interface_phy_nr* m_ue_stack = nullptr;
srslte::byte_buffer_pool* m_pool = nullptr;
std::unique_ptr<basic_vnf_api::tx_request_msg_t> m_tx_req_msg;

@ -22,6 +22,7 @@
#ifndef SRSLTE_BUFFER_POOL_H
#define SRSLTE_BUFFER_POOL_H
#include "byte_buffer.h"
#include <algorithm>
#include <map>
#include <pthread.h>
@ -35,6 +36,7 @@
#include "srslte/common/common.h"
#include "srslte/common/log.h"
#include "srslte/srslog/srslog.h"
namespace srslte {
@ -61,7 +63,11 @@ public:
pthread_mutex_init(&mutex, nullptr);
pthread_cond_init(&cv_not_empty, nullptr);
for (uint32_t i = 0; i < nof_buffers; i++) {
buffer_t* b = new buffer_t;
buffer_t* b = new (std::nothrow) buffer_t;
if (!b) {
perror("Error allocating memory. Exiting...\n");
exit(-1);
}
available.push(b);
}
capacity = nof_buffers;
@ -170,70 +176,74 @@ private:
class byte_buffer_pool
{
using mem_chunk = typename std::aligned_storage<sizeof(byte_buffer_t), alignof(byte_buffer_t)>::type;
public:
// Singleton static methods
static std::unique_ptr<byte_buffer_pool> instance;
static byte_buffer_pool* get_instance(int capacity = -1);
static void cleanup();
byte_buffer_pool(int capacity = -1)
static byte_buffer_pool* get_instance(int capacity = -1)
{
log = nullptr;
pool = new buffer_pool<byte_buffer_t>(capacity);
static std::unique_ptr<byte_buffer_pool> instance(new byte_buffer_pool(capacity));
return instance.get();
}
byte_buffer_pool(int capacity = -1) : pool(capacity) {}
byte_buffer_pool(const byte_buffer_pool& other) = delete;
byte_buffer_pool(byte_buffer_pool&& other) = delete;
byte_buffer_pool& operator=(const byte_buffer_pool& other) = delete;
~byte_buffer_pool() { delete pool; }
byte_buffer_t* allocate(const char* debug_name = nullptr, bool blocking = false)
byte_buffer_pool& operator=(byte_buffer_pool&& other) = delete;
void* allocate(const char* debug_name = nullptr, bool blocking = false)
{
return pool->allocate(debug_name, blocking);
return pool.allocate(debug_name, blocking);
}
void set_log(srslte::log* log) { this->log = log; }
void deallocate(byte_buffer_t* b)
void enable_logger(bool enabled) { print_to_log = enabled; }
void deallocate(void* b)
{
if (!b) {
return;
}
b->clear();
if (!pool->deallocate(b)) {
if (log) {
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
log->error("Deallocating PDU: Addr=0x%p, name=%s not found in pool\n", b, b->debug_name);
#else
log->error("Deallocating PDU: Addr=0x%p\n", b);
#endif
} else {
if (!pool.deallocate(static_cast<mem_chunk*>(b))) {
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
printf("Error deallocating PDU: Addr=0x%p, name=%s not found in pool\n", b, b->debug_name);
print_error("Error deallocating PDU: Addr=0x%p, name=%s not found in pool", (void*)b, b->debug_name);
#else
printf("Error deallocating PDU: Addr=0x%p\n", b);
print_error("Error deallocating PDU: Addr=0x%p", (void*)b);
#endif
}
}
b = nullptr;
void print_all_buffers() { pool.print_all_buffers(); }
private:
/// Formats and prints the input string and arguments into the configured output stream.
template <typename... Args>
void print_error(const char* str, Args&&... args)
{
if (print_to_log) {
srslog::fetch_basic_logger("POOL", false).error(str, std::forward<Args>(args)...);
} else {
fmt::printf(std::string(str) + "\n", std::forward<Args>(args)...);
}
}
void print_all_buffers() { pool->print_all_buffers(); }
private:
srslte::log* log;
buffer_pool<byte_buffer_t>* pool;
bool print_to_log = false;
buffer_pool<mem_chunk> pool;
};
inline void byte_buffer_deleter::operator()(byte_buffer_t* buf) const
inline unique_byte_buffer_t make_byte_buffer() noexcept
{
if (buf) {
pool->deallocate(buf);
}
return std::unique_ptr<byte_buffer_t>(new (std::nothrow) byte_buffer_t());
}
inline unique_byte_buffer_t allocate_unique_buffer(byte_buffer_pool& pool, bool blocking = false)
inline unique_byte_buffer_t make_byte_buffer(uint32_t size, uint8_t value) noexcept
{
return unique_byte_buffer_t(pool.allocate(nullptr, blocking), byte_buffer_deleter(&pool));
return std::unique_ptr<byte_buffer_t>(new (std::nothrow) byte_buffer_t(size, value));
}
inline unique_byte_buffer_t
allocate_unique_buffer(byte_buffer_pool& pool, const char* debug_name, bool blocking = false)
inline unique_byte_buffer_t make_byte_buffer(const char* debug_ctxt) noexcept
{
return unique_byte_buffer_t(pool.allocate(debug_name, blocking), byte_buffer_deleter(&pool));
std::unique_ptr<byte_buffer_t> buffer(new (std::nothrow) byte_buffer_t());
if (buffer == nullptr) {
srslog::fetch_basic_logger("POOL").error("Failed to allocate byte buffer in %s", debug_ctxt);
}
return buffer;
}
} // namespace srslte

@ -0,0 +1,231 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_BYTE_BUFFER_H
#define SRSLTE_BYTE_BUFFER_H
#include "common.h"
#include <chrono>
#include <cstdint>
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED
namespace srslte {
#define ENABLE_TIMESTAMP
struct buffer_latency_calc {
void clear()
{
#ifdef ENABLE_TIMESTAMP
timestamp_is_set = false;
#endif
}
std::chrono::microseconds get_latency_us() const
{
#ifdef ENABLE_TIMESTAMP
if (!timestamp_is_set) {
return std::chrono::microseconds{0};
}
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - tp);
#else
return std::chrono::microseconds{0};
#endif
}
std::chrono::high_resolution_clock::time_point get_timestamp() const { return tp; }
void set_timestamp()
{
#ifdef ENABLE_TIMESTAMP
tp = std::chrono::high_resolution_clock::now();
timestamp_is_set = true;
#endif
}
void set_timestamp(std::chrono::high_resolution_clock::time_point tp_)
{
#ifdef ENABLE_TIMESTAMP
tp = tp_;
timestamp_is_set = true;
#endif
}
private:
#ifdef ENABLE_TIMESTAMP
std::chrono::high_resolution_clock::time_point tp;
bool timestamp_is_set = false;
#endif
};
/******************************************************************************
* Byte buffer
*
* Generic byte buffer with headroom to accommodate packet headers and custom
* copy constructors & assignment operators for quick copying. Byte buffer
* holds a next pointer to support linked lists.
*****************************************************************************/
class byte_buffer_t
{
public:
using iterator = uint8_t*;
using const_iterator = const uint8_t*;
uint32_t N_bytes = 0;
uint8_t buffer[SRSLTE_MAX_BUFFER_SIZE_BYTES];
uint8_t* msg = nullptr;
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
char debug_name[SRSLTE_BUFFER_POOL_LOG_NAME_LEN];
#endif
struct buffer_metadata_t {
uint32_t pdcp_sn = 0;
buffer_latency_calc tp;
} md;
byte_buffer_t() : msg(&buffer[SRSLTE_BUFFER_HEADER_OFFSET])
{
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
bzero(debug_name, SRSLTE_BUFFER_POOL_LOG_NAME_LEN);
#endif
}
explicit byte_buffer_t(uint32_t size) : msg(&buffer[SRSLTE_BUFFER_HEADER_OFFSET]), N_bytes(size)
{
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
bzero(debug_name, SRSLTE_BUFFER_POOL_LOG_NAME_LEN);
#endif
}
byte_buffer_t(uint32_t size, uint8_t val) : byte_buffer_t(size) { std::fill(msg, msg + N_bytes, val); }
byte_buffer_t(const byte_buffer_t& buf) : msg(&buffer[SRSLTE_BUFFER_HEADER_OFFSET]), md(buf.md), N_bytes(buf.N_bytes)
{
// copy actual contents
memcpy(msg, buf.msg, N_bytes);
}
byte_buffer_t& operator=(const byte_buffer_t& buf)
{
// avoid self assignment
if (&buf == this)
return *this;
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bytes = buf.N_bytes;
md = buf.md;
memcpy(msg, buf.msg, N_bytes);
return *this;
}
void clear()
{
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bytes = 0;
md = {};
}
uint32_t get_headroom() { return msg - buffer; }
// Returns the remaining space from what is reported to be the length of msg
uint32_t get_tailroom() { return (sizeof(buffer) - (msg - buffer) - N_bytes); }
std::chrono::microseconds get_latency_us() const { return md.tp.get_latency_us(); }
std::chrono::high_resolution_clock::time_point get_timestamp() const { return md.tp.get_timestamp(); }
void set_timestamp() { md.tp.set_timestamp(); }
void set_timestamp(std::chrono::high_resolution_clock::time_point tp_) { md.tp.set_timestamp(tp_); }
void append_bytes(uint8_t* buf, uint32_t size)
{
memcpy(&msg[N_bytes], buf, size);
N_bytes += size;
}
uint8_t* data() { return msg; }
const uint8_t* data() const { return msg; }
uint32_t size() const { return N_bytes; }
iterator begin() { return msg; }
const iterator begin() const { return msg; }
iterator end() { return msg + N_bytes; }
const_iterator end() const { return msg + N_bytes; }
void* operator new(size_t sz);
void* operator new(size_t sz, const std::nothrow_t& nothrow_value) noexcept;
void* operator new[](size_t sz) = delete;
void operator delete(void* ptr);
void operator delete[](void* ptr) = delete;
};
struct bit_buffer_t {
uint32_t N_bits = 0;
uint8_t buffer[SRSLTE_MAX_BUFFER_SIZE_BITS];
uint8_t* msg = nullptr;
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
char debug_name[128];
#endif
bit_buffer_t() : msg(&buffer[SRSLTE_BUFFER_HEADER_OFFSET]) {}
bit_buffer_t(const bit_buffer_t& buf) : msg(&buffer[SRSLTE_BUFFER_HEADER_OFFSET]), N_bits(buf.N_bits)
{
memcpy(msg, buf.msg, N_bits);
}
bit_buffer_t& operator=(const bit_buffer_t& buf)
{
// avoid self assignment
if (&buf == this) {
return *this;
}
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bits = buf.N_bits;
memcpy(msg, buf.msg, N_bits);
return *this;
}
void clear()
{
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bits = 0;
}
uint32_t get_headroom() { return msg - buffer; }
};
// Create a Managed Life-Time Byte Buffer
class byte_buffer_pool;
using unique_byte_buffer_t = std::unique_ptr<byte_buffer_t>;
///
/// Utilities to create a span out of a byte_buffer.
///
using byte_span = span<uint8_t>;
using const_byte_span = span<const uint8_t>;
inline byte_span make_span(byte_buffer_t& b)
{
return byte_span{b.msg, b.N_bytes};
}
inline const_byte_span make_span(const byte_buffer_t& b)
{
return const_byte_span{b.msg, b.N_bytes};
}
inline byte_span make_span(unique_byte_buffer_t& b)
{
return byte_span{b->msg, b->N_bytes};
}
inline const_byte_span make_span(const unique_byte_buffer_t& b)
{
return const_byte_span{b->msg, b->N_bytes};
}
} // namespace srslte
#endif // SRSLTE_BYTE_BUFFER_H

@ -74,17 +74,6 @@
#define SRSLTE_MAX_BUFFER_SIZE_BITS (SRSLTE_MAX_TBSIZE_BITS + SRSLTE_BUFFER_HEADER_OFFSET)
#define SRSLTE_MAX_BUFFER_SIZE_BYTES (SRSLTE_MAX_TBSIZE_BITS / 8 + SRSLTE_BUFFER_HEADER_OFFSET)
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
#define pool_allocate (srslte::allocate_unique_buffer(*pool, __PRETTY_FUNCTION__))
#define pool_allocate_blocking (srslte::allocate_unique_buffer(*pool, __PRETTY_FUNCTION__, true))
#define SRSLTE_BUFFER_POOL_LOG_NAME_LEN 128
#else
#define pool_allocate (srslte::allocate_unique_buffer(*pool))
#define pool_allocate_blocking (srslte::allocate_unique_buffer(*pool, true))
#endif
/*******************************************************************************
TYPEDEFS
*******************************************************************************/
@ -93,212 +82,6 @@ namespace srslte {
#define ENABLE_TIMESTAMP
/******************************************************************************
* Byte and Bit buffers
*
* Generic buffers with headroom to accommodate packet headers and custom
* copy constructors & assignment operators for quick copying. Byte buffer
* holds a next pointer to support linked lists.
*****************************************************************************/
class byte_buffer_t
{
public:
uint32_t N_bytes;
uint8_t buffer[SRSLTE_MAX_BUFFER_SIZE_BYTES];
uint8_t* msg;
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
char debug_name[SRSLTE_BUFFER_POOL_LOG_NAME_LEN];
#endif
byte_buffer_t() : N_bytes(0)
{
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
next = NULL;
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
bzero(debug_name, SRSLTE_BUFFER_POOL_LOG_NAME_LEN);
#endif
}
byte_buffer_t(const byte_buffer_t& buf)
{
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
next = NULL;
// copy actual contents
N_bytes = buf.N_bytes;
memcpy(msg, buf.msg, N_bytes);
}
byte_buffer_t& operator=(const byte_buffer_t& buf)
{
// avoid self assignment
if (&buf == this)
return *this;
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
next = NULL;
N_bytes = buf.N_bytes;
memcpy(msg, buf.msg, N_bytes);
return *this;
}
void clear()
{
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bytes = 0;
#ifdef ENABLE_TIMESTAMP
timestamp_is_set = false;
#endif
}
uint32_t get_headroom() { return msg - buffer; }
// Returns the remaining space from what is reported to be the length of msg
uint32_t get_tailroom() { return (sizeof(buffer) - (msg - buffer) - N_bytes); }
std::chrono::microseconds get_latency_us()
{
#ifdef ENABLE_TIMESTAMP
if (!timestamp_is_set) {
return std::chrono::microseconds{0};
}
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - tp);
#else
return std::chrono::microseconds{0};
#endif
}
std::chrono::high_resolution_clock::time_point get_timestamp() { return tp; }
void set_timestamp()
{
#ifdef ENABLE_TIMESTAMP
tp = std::chrono::high_resolution_clock::now();
timestamp_is_set = true;
#endif
}
void set_timestamp(std::chrono::high_resolution_clock::time_point tp_)
{
tp = tp_;
timestamp_is_set = true;
}
void append_bytes(uint8_t* buf, uint32_t size)
{
memcpy(&msg[N_bytes], buf, size);
N_bytes += size;
}
private:
#ifdef ENABLE_TIMESTAMP
std::chrono::high_resolution_clock::time_point tp;
bool timestamp_is_set = false;
#endif
byte_buffer_t* next;
};
struct bit_buffer_t {
uint32_t N_bits;
uint8_t buffer[SRSLTE_MAX_BUFFER_SIZE_BITS];
uint8_t* msg;
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
char debug_name[128];
#endif
bit_buffer_t() : N_bits(0)
{
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
#ifdef ENABLE_TIMESTAMP
timestamp_is_set = false;
#endif
}
bit_buffer_t(const bit_buffer_t& buf)
{
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bits = buf.N_bits;
memcpy(msg, buf.msg, N_bits);
}
bit_buffer_t& operator=(const bit_buffer_t& buf)
{
// avoid self assignment
if (&buf == this) {
return *this;
}
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bits = buf.N_bits;
memcpy(msg, buf.msg, N_bits);
return *this;
}
void clear()
{
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
N_bits = 0;
#ifdef ENABLE_TIMESTAMP
timestamp_is_set = false;
#endif
}
uint32_t get_headroom() { return msg - buffer; }
long get_latency_us()
{
#ifdef ENABLE_TIMESTAMP
if (!timestamp_is_set)
return 0;
gettimeofday(&timestamp[2], NULL);
return timestamp[0].tv_usec;
#else
return 0;
#endif
}
void set_timestamp()
{
#ifdef ENABLE_TIMESTAMP
gettimeofday(&timestamp[1], NULL);
timestamp_is_set = true;
#endif
}
private:
#ifdef ENABLE_TIMESTAMP
struct timeval timestamp[3];
bool timestamp_is_set;
#endif
};
// Create a Managed Life-Time Byte Buffer
class byte_buffer_pool;
class byte_buffer_deleter
{
public:
explicit byte_buffer_deleter(byte_buffer_pool* pool_ = nullptr) : pool(pool_) {}
void operator()(byte_buffer_t* buf) const;
byte_buffer_pool* pool;
};
typedef std::unique_ptr<byte_buffer_t, byte_buffer_deleter> unique_byte_buffer_t;
///
/// Utilities to create a span out of a byte_buffer.
///
using byte_span = span<uint8_t>;
using const_byte_span = span<const uint8_t>;
inline byte_span make_span(byte_buffer_t& b)
{
return byte_span{b.msg, b.N_bytes};
}
inline const_byte_span make_span(const byte_buffer_t& b)
{
return const_byte_span{b.msg, b.N_bytes};
}
inline byte_span make_span(unique_byte_buffer_t& b)
{
return byte_span{b->msg, b->N_bytes};
}
inline const_byte_span make_span(const unique_byte_buffer_t& b)
{
return const_byte_span{b->msg, b->N_bytes};
}
// helper functions
inline const char* enum_to_text(const char* const array[], uint32_t nof_types, uint32_t enum_val)
{

@ -27,7 +27,7 @@
#ifndef SRSLTE_COMMON_HELPER_H
#define SRSLTE_COMMON_HELPER_H
#include "srslte/common/logmap.h"
#include "srslte/srslog/srslog.h"
#include <fstream>
#include <sstream>
#include <thread>
@ -41,10 +41,9 @@ inline void log_args(int argc, char* argv[], const std::string& service)
for (int32_t i = 1; i < argc; i++) {
s1 << argv[i] << " ";
}
s1 << std::endl;
srslte::logmap::get(service)->set_level(srslte::LOG_LEVEL_INFO);
srslte::logmap::get(service)->info("%s", s1.str().c_str());
srslog::fetch_basic_logger(service, false).set_level(srslog::basic_levels::info);
srslog::fetch_basic_logger(service).info("%s", s1.str().c_str());
}
inline void check_scaling_governor(const std::string& device_name)

@ -39,22 +39,28 @@ public:
virtual ~event_logger_interface() = default;
/// Logs into the underlying log channel the RRC connected event.
virtual void log_rrc_connected(unsigned cause) = 0;
virtual void log_rrc_connected(uint32_t enb_cc_idx, const std::string& asn1, unsigned error_code, uint16_t rnti) = 0;
/// Logs into the underlying log channel the RRC disconnected event.
virtual void log_rrc_disconnect(unsigned reason) = 0;
virtual void log_rrc_disconnect(uint32_t enb_cc_idx, unsigned reason, uint16_t rnti) = 0;
/// Logs into the underlying log channel the S1 context create event.
virtual void log_s1_ctx_create(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) = 0;
virtual void log_s1_ctx_create(uint32_t enb_cc_idx, uint32_t mme_id, uint32_t enb_id, uint16_t rnti) = 0;
/// Logs into the underlying log channel the S1 context delete event.
virtual void log_s1_ctx_delete(uint32_t mme_id, uint32_t enb_id, uint16_t rnti) = 0;
virtual void log_s1_ctx_delete(uint32_t enb_cc_idx, uint32_t mme_id, uint32_t enb_id, uint16_t rnti) = 0;
/// Logs into the underlying log channel the when a sector has been started.
/// Logs into the underlying log channel when a sector has been started.
virtual void log_sector_start(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) = 0;
/// Logs into the underlying log channel the when a sector has been stopped.
/// Logs into the underlying log channel when a sector has been stopped.
virtual void log_sector_stop(uint32_t cc_idx, uint32_t pci, uint32_t cell_id) = 0;
/// Logs into the underlying log channel a measurement report event..
virtual void log_measurement_report(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) = 0;
/// Logs into the underlying log channel a RLF event.
virtual void log_rlf(uint32_t enb_cc_idx, const std::string& asn1, uint16_t rnti) = 0;
};
/// Singleton class to provide global access to the event_logger_interface interface.

@ -24,18 +24,19 @@
#include "srslte/adt/detail/type_utils.h"
#include "srslte/adt/move_callback.h"
#include "srslte/common/logmap.h"
#include "srslte/srslog/srslog.h"
#include <cstdio>
#include <deque>
#include <limits>
#include <list>
#include <memory>
#include <tuple>
#define otherfsmDebug(f, fmt, ...) f->get_log()->debug("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
#define otherfsmInfo(f, fmt, ...) f->get_log()->info("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
#define otherfsmDebug(f, fmt, ...) f->get_logger().debug("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
#define otherfsmInfo(f, fmt, ...) f->get_logger().info("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
#define otherfsmWarning(f, fmt, ...) \
f->get_log()->warning("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
#define otherfsmError(f, fmt, ...) f->get_log()->error("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
f->get_logger().warning("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
#define otherfsmError(f, fmt, ...) f->get_logger().error("FSM \"%s\" - " fmt, get_type_name(*f).c_str(), ##__VA_ARGS__)
#define fsmDebug(fmt, ...) otherfsmDebug(this, fmt, ##__VA_ARGS__)
#define fsmInfo(fmt, ...) otherfsmInfo(this, fmt, ##__VA_ARGS__)
@ -168,7 +169,7 @@ static auto get_state_recursive(FSM* f) -> disable_if_fsm_state<FSM, State, Stat
//! Helper type for FSM state-related operations
template <typename FSM, typename State>
struct state_traits {
static_assert(FSM::template can_hold_state<State>(), "FSM type does not hold provided State\n");
static_assert(FSM::template can_hold_state<State>(), "FSM type does not hold provided State");
using state_t = State;
using is_subfsm = std::integral_constant<bool, ::srslte::is_composite_fsm<State>::value>;
@ -234,7 +235,7 @@ struct apply_first_guard_pass<FSM, type_list<First, Rows...> > {
// Log Transition
if (std::is_same<src_state, dest_state>::value) {
otherfsmInfo(static_cast<typename FSM::derived_t*>(f),
"Event \"%s\" triggered state \"%s\" update\n",
"Event \"%s\" triggered state \"%s\" update",
get_type_name<event_type>().c_str(),
get_type_name<src_state>().c_str());
} else {
@ -259,7 +260,7 @@ struct apply_first_guard_pass<FSM, type_list<> > {
{
if (should_log_unhandled_event(&ev)) {
otherfsmDebug(static_cast<typename FSM::derived_t*>(f),
"unhandled event caught in state \"%s\": \"%s\"\n",
"unhandled event caught in state \"%s\": \"%s\"",
get_type_name<SrcState>().c_str(),
get_type_name<Event>().c_str());
}
@ -394,7 +395,7 @@ public:
struct state_list : public std::tuple<States...> {
using tuple_base_t = std::tuple<States...>;
using init_state_t = typename std::decay<decltype(std::get<0>(std::declval<tuple_base_t>()))>::type;
static_assert(not type_list_contains<Derived, States...>(), "An FSM cannot contain itself as state\n");
static_assert(not type_list_contains<Derived, States...>(), "An FSM cannot contain itself as state");
template <typename... Args>
state_list(base_fsm_t<Derived>* f, Args&&... args) : tuple_base_t(std::forward<Args>(args)...)
@ -516,7 +517,7 @@ protected:
public:
static const bool is_nested = false;
explicit fsm_t(srslte::log_ref log_) : log_h(log_) {}
explicit fsm_t(srslog::basic_logger& logger) : logger(logger) {}
// Push Events to FSM
template <typename Ev>
@ -536,9 +537,9 @@ public:
return ret;
}
void set_fsm_event_log_level(srslte::LOG_LEVEL_ENUM e) { fsm_event_log_level = e; }
void set_fsm_event_log_level(srslog::basic_levels lvl) { log_level = lvl; }
srslte::log_ref get_log() const { return log_h; }
srslog::basic_logger& get_logger() const { return logger; }
bool is_trigger_locked() const { return trigger_locked; }
@ -546,18 +547,18 @@ public:
template <typename... Args>
void log_fsm_activity(const char* format, Args&&... args)
{
switch (fsm_event_log_level) {
case LOG_LEVEL_DEBUG:
log_h->debug(format, std::forward<Args>(args)...);
switch (log_level) {
case srslog::basic_levels::debug:
logger.debug(format, std::forward<Args>(args)...);
break;
case LOG_LEVEL_INFO:
log_h->info(format, std::forward<Args>(args)...);
case srslog::basic_levels::info:
logger.info(format, std::forward<Args>(args)...);
break;
case LOG_LEVEL_WARNING:
log_h->warning(format, std::forward<Args>(args)...);
case srslog::basic_levels::warning:
logger.warning(format, std::forward<Args>(args)...);
break;
case LOG_LEVEL_ERROR:
log_h->error(format, std::forward<Args>(args)...);
case srslog::basic_levels::error:
logger.error(format, std::forward<Args>(args)...);
break;
default:
break;
@ -579,8 +580,8 @@ protected:
pending_events.emplace_back(std::bind([this](Ev& e) { process_event(std::move(e)); }, std::move(e)));
}
srslte::log_ref log_h;
srslte::LOG_LEVEL_ENUM fsm_event_log_level = LOG_LEVEL_INFO;
srslog::basic_logger& logger;
srslog::basic_levels log_level = srslog::basic_levels::info;
bool trigger_locked = false;
std::deque<srslte::move_callback<void()> > pending_events;
};
@ -602,7 +603,7 @@ public:
parent_t* parent_fsm() { return fsm_ptr; }
srslte::log_ref get_log() const { return parent_fsm()->get_log(); }
srslog::basic_logger& get_logger() const { return parent_fsm()->get_logger(); }
// Push Events to root FSM
template <typename Ev>
@ -643,7 +644,7 @@ class proc_fsm_t : public fsm_t<Derived>
using fsm_t<Derived>::derived;
protected:
using fsm_t<Derived>::log_h;
using fsm_t<Derived>::logger;
public:
using base_t = proc_fsm_t<Derived, Result>;
@ -659,14 +660,14 @@ public:
void enter(Derived* f)
{
if (f->launch_counter > 0) {
f->log_h->warning(
"FSM \"%s\": No result was set for run no. %d\n", get_type_name<Derived>().c_str(), f->launch_counter);
f->logger.warning(
"FSM \"%s\": No result was set for run no. %d", get_type_name<Derived>().c_str(), f->launch_counter);
}
}
void enter(Derived* f, const complete_ev& ev)
{
f->log_h->info("FSM \"%s\": Finished run no. %d\n", get_type_name<Derived>().c_str(), f->launch_counter);
f->logger.info("FSM \"%s\": Finished run no. %d", get_type_name<Derived>().c_str(), f->launch_counter);
f->last_result = ev.result;
for (auto& func : f->listening_fsms) {
func(ev);
@ -677,11 +678,11 @@ public:
void exit(Derived* f)
{
f->launch_counter++;
f->log_h->info("FSM \"%s\": Starting run no. %d\n", get_type_name<Derived>().c_str(), f->launch_counter);
f->logger.info("FSM \"%s\": Starting run no. %d", get_type_name<Derived>().c_str(), f->launch_counter);
}
};
explicit proc_fsm_t(srslte::log_ref log_) : fsm_t<Derived>(log_) {}
explicit proc_fsm_t(srslog::basic_logger& logger) : fsm_t<Derived>(logger) {}
bool is_running() const { return not base_t::template is_in_state<idle_st>(); }
@ -720,7 +721,7 @@ public:
void enter(FSM* f, const Ev& ev)
{
if (proc_ptr->is_running()) {
f->get_log()->error("Unable to launch proc1\n");
f->get_logger().error("Unable to launch proc1");
f->trigger(typename ProcFSM::complete_ev{false});
}
proc_ptr->trigger(srslte::proc_launch_ev<Ev>{ev});

@ -22,6 +22,7 @@
#ifndef SRSLTE_INTERFACES_COMMON_H
#define SRSLTE_INTERFACES_COMMON_H
#include "srslte/common/byte_buffer.h"
#include "srslte/common/security.h"
#include "srslte/phy/common/phy_common.h"
#include <string>

@ -1,63 +0,0 @@
/**
* Copyright 2013-2021 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 <string>
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

@ -25,24 +25,26 @@
#include "srslte/common/block_queue.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/common.h"
#include "srslte/common/logmap.h"
#include "srslte/common/pcap.h"
#include "srslte/common/threads.h"
#include "srslte/srslog/srslog.h"
#include <mutex>
#include <stdint.h>
#include <thread>
namespace srslte {
class mac_pcap : srslte::thread
{
public:
mac_pcap();
mac_pcap(srslte_rat_t rat);
~mac_pcap();
void enable(bool en);
uint32_t open(const char* filename, uint32_t ue_id = 0);
void enable(bool enable);
uint32_t open(std::string filename, uint32_t ue_id = 0);
uint32_t close();
void set_ue_id(uint16_t ue_id);
// EUTRA
void
write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
void write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, bool crc_ok, uint32_t tti, uint8_t cc_idx);
@ -59,14 +61,24 @@ public:
// Sidelink
void write_sl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
// NR
void write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint8_t harqid, uint32_t tti);
void write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_ra_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_bch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_pch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
void write_dl_si_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
private:
srslte::byte_buffer_pool* pool = nullptr;
srslte::log_ref log;
srslog::basic_logger& logger;
bool running = false;
srslte_rat_t rat = srslte_rat_t::nulltype;
uint32_t dlt = 0; // The DLT used for the PCAP file
std::string filename;
FILE* pcap_file = nullptr;
uint32_t ue_id = 0;
void pack_and_queue(uint8_t* pdu,
uint32_t pdu_len_bytes,
void pack_and_queue(uint8_t* payload,
uint32_t payload_len,
uint32_t reTX,
bool crc_ok,
uint8_t cc_idx,
@ -74,9 +86,18 @@ private:
uint16_t crnti_,
uint8_t direction,
uint8_t rnti_type);
void pack_and_queue_nr(uint8_t* payload,
uint32_t payload_len,
uint32_t tti,
uint16_t crnti,
uint8_t harqid,
uint8_t direction,
uint8_t rnti_type);
typedef struct {
// Different PCAP context for both RATs
MAC_Context_Info_t context;
mac_nr_context_info_t context_nr;
unique_byte_buffer_t pdu;
} pcap_pdu_t;
block_queue<pcap_pdu_t> queue;

@ -23,7 +23,6 @@
#define SRSLTE_RX_SOCKET_HANDLER_H
#include "srslte/common/buffer_pool.h"
#include "srslte/common/logmap.h"
#include "srslte/common/threads.h"
#include <arpa/inet.h>
@ -134,7 +133,7 @@ public:
using sctp_recv_callback_t =
std::function<void(srslte::unique_byte_buffer_t, const sockaddr_in&, const sctp_sndrcvinfo&, int)>;
rx_multisocket_handler(std::string name_, srslte::log_ref log_, int thread_prio = 65);
rx_multisocket_handler(std::string name_, srslog::basic_logger& logger, int thread_prio = 65);
rx_multisocket_handler(rx_multisocket_handler&&) = delete;
rx_multisocket_handler(const rx_multisocket_handler&) = delete;
rx_multisocket_handler& operator=(const rx_multisocket_handler&) = delete;
@ -157,12 +156,12 @@ private:
cmd_id_t cmd = cmd_id_t::EXIT;
int new_fd = -1;
};
bool remove_socket_unprotected(int fd, fd_set* total_fd_set, int* max_fd);
std::map<int, rx_multisocket_handler::task_callback_t>::iterator
remove_socket_unprotected(int fd, fd_set* total_fd_set, int* max_fd);
// args
std::string name;
srslte::log_ref log_h;
srslte::byte_buffer_pool* pool = nullptr;
srslog::basic_logger& logger;
// state
std::mutex socket_mutex;

@ -28,6 +28,7 @@
#define SRSLTE_SIGNAL_HANDLER_H
#include "srslte/srslog/sink.h"
#include "srslte/srslog/srslog.h"
#include <signal.h>
#include <stdio.h>
@ -46,6 +47,7 @@ static void srslte_signal_handler(int signal)
switch (signal) {
case SIGALRM:
fprintf(stderr, "Couldn't stop after %ds. Forcing exit.\n", SRSLTE_TERM_TIMEOUT_S);
srslog::flush();
//:TODO: refactor the sighandler, should not depend on log utilities
if (log_sink) {
log_sink->flush();

@ -29,6 +29,8 @@
#include "srslte/common/log.h"
#include "srslte/common/log_filter.h"
#include "srslte/common/logmap.h"
#include "srslte/srslog/srslog.h"
#include <atomic>
#include <cstdio>
namespace srslte {
@ -91,6 +93,65 @@ public:
uint32_t error_counter = 0, warn_counter = 0;
};
/// This custom sink intercepts log messages to count error and warning log entries.
class log_sink_spy : public srslog::sink
{
public:
explicit log_sink_spy(std::unique_ptr<srslog::log_formatter> f) :
srslog::sink(std::move(f)), s(srslog::get_default_sink())
{
error_counter.store(0);
warning_counter.store(0);
}
/// Identifier of this custom sink.
static const char* name() { return "log_sink_spy"; }
/// Returns the number of log entries tagged as errors.
unsigned get_error_counter() const
{
// Flush to make sure all entries have been processed by the backend.
srslog::flush();
return error_counter.load();
}
/// Returns the number of log entries tagged as warnings.
unsigned get_warning_counter() const
{
// Flush to make sure all entries have been processed by the backend.
srslog::flush();
return warning_counter.load();
}
/// Resets the counters back to 0.
void reset_counters()
{
// Flush to make sure all entries have been processed by the backend.
srslog::flush();
error_counter.store(0);
warning_counter.store(0);
}
srslog::detail::error_string write(srslog::detail::memory_buffer buffer) override
{
std::string entry(buffer.data(), buffer.size());
if (entry.find("[E]") != std::string::npos) {
error_counter.fetch_add(1);
} else if (entry.find("[W]") != std::string::npos) {
warning_counter.fetch_add(1);
}
return s.write(buffer);
}
srslog::detail::error_string flush() override { return s.flush(); }
private:
srslog::sink& s;
std::atomic<unsigned> error_counter;
std::atomic<unsigned> warning_counter;
};
// specialization of test_log_filter to store last logged message
class nullsink_log : public test_log_filter
{
@ -200,7 +261,7 @@ private:
} \
} while (0)
#define TESTASSERT(cond) CONDERROR((not(cond)), "[%s][Line %d] Fail at \"%s\"\n", __FUNCTION__, __LINE__, (#cond))
#define TESTASSERT(cond) CONDERROR((not(cond)), "[%s][Line %d] Fail at \"%s\"", __FUNCTION__, __LINE__, (#cond))
#else // if C

@ -22,8 +22,9 @@
#ifndef SRSLTE_TIME_PROF_H
#define SRSLTE_TIME_PROF_H
#include "srslte/common/logmap.h"
#include "srslte/srslog/srslog.h"
#include <chrono>
#include <mutex>
#ifdef ENABLE_TIMEPROF
#define TPROF_ENABLE_DEFAULT true
@ -57,8 +58,7 @@ class tprof
public:
template <typename... Args>
explicit tprof(Args&&... args) : prof(std::forward<Args>(args)...)
{
}
{}
void start() { meas.start(); }
@ -80,8 +80,7 @@ class tprof<Prof, false>
public:
template <typename... Args>
explicit tprof(Args&&... args)
{
}
{}
void start() {}
@ -115,8 +114,7 @@ struct mutexed_tprof {
template <typename... Args>
explicit mutexed_tprof(Args&&... args) : prof(std::forward<Args>(args)...)
{
}
{}
measure start() { return measure{this}; }
Prof prof;
@ -135,8 +133,7 @@ struct mutexed_tprof<Prof, false> {
template <typename... Args>
explicit mutexed_tprof(Args&&... args)
{
}
{}
measure start() { return measure{}; }
};
@ -144,7 +141,7 @@ struct avg_time_stats {
avg_time_stats(const char* name_, const char* logname, size_t print_period_);
void operator()(std::chrono::nanoseconds duration);
srslte::log_ref log_ptr;
srslog::basic_logger& logger;
std::string name;
double avg_val = 1;
long count = 0, max_val = 0, min_val = std::numeric_limits<long>::max();
@ -158,7 +155,7 @@ public:
sliding_window_stats(const char* name_, const char* logname, size_t print_period_ = 10);
void operator()(std::chrono::nanoseconds duration);
srslte::log_ref log_ptr;
srslog::basic_logger& logger;
std::string name;
std::vector<std::chrono::nanoseconds> sliding_window;
size_t window_idx = 0;

@ -73,11 +73,11 @@ class timer_handler
bool set(uint32_t duration_)
{
if (duration_ > MAX_TIMER_DURATION) {
ERROR("Error: timer durations above %u are not supported\n", MAX_TIMER_DURATION);
ERROR("Error: timer durations above %u are not supported", MAX_TIMER_DURATION);
return false;
}
if (not active) {
ERROR("Error: setting inactive timer id=%d\n", id());
ERROR("Error: setting inactive timer id=%d", id());
return false;
}
duration = duration_;
@ -101,7 +101,7 @@ class timer_handler
{
std::unique_lock<std::mutex> lock(parent->mutex);
if (not active) {
ERROR("Error: calling run() for inactive timer id=%d\n", id());
ERROR("Error: calling run() for inactive timer id=%d", id());
return;
}
timeout = parent->cur_time + duration;

@ -22,8 +22,9 @@
#ifndef SRSLTE_TTI_POINT_H
#define SRSLTE_TTI_POINT_H
#include "logmap.h"
#include "srslte/adt/interval.h"
#include "srslte/common/common.h"
#include "srslte/srslog/srslog.h"
#include <cstdint>
#include <limits>
@ -39,7 +40,7 @@ struct tti_point {
if (diff < 10240) {
tti_val = 10240 - diff - 1;
} else {
srslte::logmap::get("COMMON")->error("Invalid TTI point assigned\n");
srslog::fetch_basic_logger("COMMON").error("Invalid TTI point assigned");
}
}
}

@ -0,0 +1,46 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_ENB_GTPU_INTERFACES_H
#define SRSLTE_ENB_GTPU_INTERFACES_H
namespace srsenb {
// GTPU interface for PDCP
class gtpu_interface_pdcp
{
public:
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
};
// GTPU interface for RRC
class gtpu_interface_rrc
{
public:
struct bearer_props {
bool forward_from_teidin_present = false;
bool flush_before_teidin_present = false;
uint32_t forward_from_teidin = 0;
uint32_t flush_before_teidin = 0;
};
virtual uint32_t
add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) = 0;
virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0;
virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
};
} // namespace srsenb
#endif // SRSLTE_ENB_GTPU_INTERFACES_H

@ -19,567 +19,16 @@
*
*/
#include "srslte/srslte.h"
#include "pdcp_interface_types.h"
#include "rlc_interface_types.h"
#include "rrc_interface_types.h"
#include "srslte/asn1/rrc_utils.h"
#include "srslte/asn1/s1ap_utils.h"
#include "srslte/common/common.h"
#include "srslte/common/interfaces_common.h"
#include "srslte/common/security.h"
#include "srslte/interfaces/sched_interface.h"
#include <vector>
#include "srslte/srslte.h"
#ifndef SRSLTE_ENB_INTERFACES_H
#define SRSLTE_ENB_INTERFACES_H
namespace srsenb {
/* Interface PHY -> MAC */
class mac_interface_phy_lte
{
public:
const static int MAX_GRANTS = 64;
/**
* DL grant structure per UE
*/
struct dl_sched_grant_t {
srslte_dci_dl_t dci = {};
uint8_t* data[SRSLTE_MAX_TB] = {};
srslte_softbuffer_tx_t* softbuffer_tx[SRSLTE_MAX_TB] = {};
};
/**
* DL Scheduling result per cell/carrier
*/
typedef struct {
dl_sched_grant_t pdsch[MAX_GRANTS]; //< DL Grants
uint32_t nof_grants; //< Number of DL grants
uint32_t cfi; //< Current CFI of the cell, it can vary across cells
} dl_sched_t;
/**
* List of DL scheduling results, one entry per cell/carrier
*/
typedef std::vector<dl_sched_t> dl_sched_list_t;
typedef struct {
uint16_t rnti;
bool ack;
} ul_sched_ack_t;
/**
* UL grant information per UE
*/
typedef struct {
srslte_dci_ul_t dci;
uint32_t current_tx_nb;
uint8_t* data;
bool needs_pdcch;
srslte_softbuffer_rx_t* softbuffer_rx;
} ul_sched_grant_t;
/**
* UL Scheduling result per cell/carrier
*/
typedef struct {
ul_sched_grant_t pusch[MAX_GRANTS];
ul_sched_ack_t phich[MAX_GRANTS];
uint32_t nof_grants;
uint32_t nof_phich;
} ul_sched_t;
/**
* List of UL scheduling results, one entry per cell/carrier
*/
typedef std::vector<ul_sched_t> ul_sched_list_t;
virtual int sr_detected(uint32_t tti, uint16_t rnti) = 0;
virtual void rach_detected(uint32_t tti, uint32_t primary_cc_idx, uint32_t preamble_idx, uint32_t time_adv) = 0;
/**
* PHY callback for giving MAC the Rank Indicator information of a given RNTI for an eNb cell/carrier.
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the measurement corresponds
* @param ri_value the actual Rank Indicator value, 0 for 1 layer, 1 for two layers and so on.
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int ri_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t ri_value) = 0;
/**
* PHY callback for giving MAC the Pre-coding Matrix Indicator information of a given RNTI for an eNb cell/carrier.
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the measurement corresponds
* @param pmi_value the actual PMI value
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int pmi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t pmi_value) = 0;
/**
* PHY callback for for giving MAC the Channel Quality information of a given RNTI, TTI and eNb cell/carrier
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the measurement corresponds
* @param cqi_value the corresponding Channel Quality Information
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) = 0;
typedef enum { PUSCH = 0, PUCCH, SRS } ul_channel_t;
/**
* PHY callback for giving MAC the SNR in dB of an UL transmission for a given RNTI at a given carrier
*
* @param tti The measurement was made
* @param rnti The UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the UL transmission was received
* @param snr_db The actual SNR of the received signal
* @param ch Indicates uplink channel (PUSCH, PUCCH or SRS)
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr_db, ul_channel_t ch) = 0;
/**
* PHY callback for giving MAC the Time Aligment information in microseconds of a given RNTI during a TTI processing
*
* @param tti The measurement was made
* @param rnti The UE identifier in the eNb
* @param ta_us The actual time alignment in microseconds
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int ta_info(uint32_t tti, uint16_t rnti, float ta_us) = 0;
/**
* PHY callback for giving MAC the HARQ DL ACK/NACK feedback information for a given RNTI, TTI, eNb cell/carrier and
* Transport block.
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx the eNb Cell/Carrier identifier
* @param tb_idx the transport block index
* @param ack true for ACK, false for NACK, do not call for DTX
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int ack_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t tb_idx, bool ack) = 0;
/**
* Informs MAC about a received PUSCH transmission for given RNTI, TTI and eNb Cell/carrier.
*
* This function does not deallocate the uplink buffer. The function push_pdu() must be called after this
* to inform the MAC that the uplink buffer can be discarded or pushed to the stack
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx the eNb Cell/Carrier identifier
* @param nof_bytes the number of grants carrierd by the PUSCH message
* @param crc_res the CRC check, set to true if the message was decoded succesfully
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int crc_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc_res) = 0;
/**
* Pushes an uplink PDU through the stack if crc_res==true or discards it if crc_res==false
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param enb_cc_idx the eNb Cell/Carrier identifier
* @param nof_bytes the number of grants carrierd by the PUSCH message
* @param crc_res the CRC check, set to true if the message was decoded succesfully
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int push_pdu(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc_res) = 0;
virtual int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) = 0;
virtual int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) = 0;
virtual int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) = 0;
virtual void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0;
};
/* Interface MAC -> PHY */
class phy_interface_mac_lte
{
public:
/**
* Removes an RNTI context from all the physical layer components, including secondary cells
* @param rnti identifier of the user
*/
virtual void rem_rnti(uint16_t rnti) = 0;
/**
* Pregenerates the scrambling sequences for a given RNTI.
* WARNING: This function make take several ms to complete.
*
* @param rnti identifier of the user
*/
virtual int pregen_sequences(uint16_t rnti) = 0;
/**
*
* @param stop
*/
virtual void set_mch_period_stop(uint32_t stop) = 0;
/**
* Activates and/or deactivates Secondary Cells in the PHY for a given RNTI. Requires the RNTI of the given UE and a
* vector with the activation/deactivation values. Use true for activation and false for deactivation. The index 0 is
* reserved for PCell and will not be used.
*
* @param rnti identifier of the user
* @param activation vector with the activate/deactivate.
*/
virtual void set_activation_deactivation_scell(uint16_t rnti,
const std::array<bool, SRSLTE_MAX_CARRIERS>& activation) = 0;
};
/* Interface RRC -> PHY */
class phy_interface_rrc_lte
{
public:
srslte::phy_cfg_mbsfn_t mbsfn_cfg;
virtual void configure_mbsfn(srslte::sib2_mbms_t* sib2, srslte::sib13_t* sib13, const srslte::mcch_msg_t& mcch) = 0;
struct phy_rrc_cfg_t {
bool configured = false; ///< Indicates whether PHY shall consider configuring this cell/carrier
uint32_t enb_cc_idx = 0; ///< eNb Cell index
srslte::phy_cfg_t phy_cfg = {}; ///< Dedicated physical layer configuration
};
typedef std::vector<phy_rrc_cfg_t> phy_rrc_cfg_list_t;
/**
* Sets the physical layer dedicated configuration for a given RNTI. The dedicated configuration list shall provide
* all the required information configuration for the following cases:
* - Add an RNTI straight from RRC
* - Moving primary to another serving cell
* - Add/Remove secondary serving cells
*
* Remind this call will partially reconfigure the primary serving cell, `complete_config``shall be called
* in order to complete the configuration.
*
* @param rnti the given RNTI
* @param phy_cfg_list Physical layer configuration for the indicated eNb cell
*/
virtual void set_config(uint16_t rnti, const phy_rrc_cfg_list_t& phy_cfg_list) = 0;
/**
* Instructs the physical layer the configuration has been complete from upper layers for a given RNTI
*
* @param rnti the given UE identifier (RNTI)
*/
virtual void complete_config(uint16_t rnti) = 0;
};
class mac_interface_rrc
{
public:
/* Provides cell configuration including SIB periodicity, etc. */
virtual int cell_cfg(const std::vector<sched_interface::cell_cfg_t>& cell_cfg) = 0;
virtual void reset() = 0;
/* Manages UE configuration context */
virtual int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) = 0;
virtual int ue_rem(uint16_t rnti) = 0;
/**
* Called after Msg3 reception to set the UE C-RNTI, resolve contention, and alter the UE's configuration in the
* scheduler and phy.
*
* @param temp_crnti temporary C-RNTI of the UE
* @param crnti chosen C-RNTI for the UE
* @param cfg new UE scheduler configuration
*/
virtual int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) = 0;
/* Manages UE bearers and associated configuration */
virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) = 0;
virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0;
virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0;
virtual void write_mcch(const srslte::sib2_mbms_t* sib2_,
const srslte::sib13_t* sib13_,
const srslte::mcch_msg_t* mcch_,
const uint8_t* mcch_payload,
const uint8_t mcch_payload_length) = 0;
/**
* Allocate a C-RNTI for a new user, without adding it to the phy layer and scheduler yet
* @return value of the allocated C-RNTI
*/
virtual uint16_t reserve_new_crnti(const sched_interface::ue_cfg_t& ue_cfg) = 0;
};
class mac_interface_rlc
{
public:
virtual int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) = 0;
};
// RLC interface for MAC
class rlc_interface_mac
{
public:
/* MAC calls RLC to get RLC segment of nof_bytes length.
* Segmentation happens in this function. RLC PDU is stored in payload. */
virtual int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
virtual void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) = 0;
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread.
* PDU gets placed into the buffer and higher layer thread gets notified. */
virtual void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
};
// RLC interface for PDCP
class rlc_interface_pdcp
{
public:
/* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls
* RLC PDUs according to TB size. */
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void discard_sdu(uint16_t rnti, uint32_t lcid, uint32_t sn) = 0;
virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0;
virtual bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid) = 0;
};
// RLC interface for RRC
class rlc_interface_rrc
{
public:
virtual void clear_buffer(uint16_t rnti) = 0;
virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
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 del_bearer(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;
virtual bool suspend_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual bool resume_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void reestablish(uint16_t rnti) = 0;
};
// PDCP interface for GTPU
class pdcp_interface_gtpu
{
public:
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
};
// PDCP interface for RRC
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 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::pdcp_config_t cnfg) = 0;
virtual void del_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0;
virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0;
virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0;
virtual bool get_bearer_state(uint16_t rnti, uint32_t lcid, srslte::pdcp_lte_state_t* state) = 0;
virtual bool set_bearer_state(uint16_t rnti, uint32_t lcid, const srslte::pdcp_lte_state_t& state) = 0;
virtual void reestablish(uint16_t rnti) = 0;
};
// PDCP interface for RLC
class pdcp_interface_rlc
{
public:
/* RLC calls PDCP to push a PDCP PDU. */
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
};
// RRC interface for RLC
class rrc_interface_rlc
{
public:
virtual void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) = 0;
virtual void max_retx_attempted(uint16_t rnti) = 0;
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
};
// RRC interface for MAC
class rrc_interface_mac
{
public:
/* Radio Link failure */
virtual int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) = 0;
virtual void upd_user(uint16_t new_rnti, uint16_t old_rnti) = 0;
virtual void set_activity_user(uint16_t rnti) = 0;
virtual bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) = 0;
///< Provide packed SIB to MAC (buffer is managed by RRC)
virtual uint8_t* read_pdu_bcch_dlsch(const uint8_t enb_cc_idx, const uint32_t sib_index) = 0;
};
// RRC interface for PDCP
class rrc_interface_pdcp
{
public:
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
};
// RRC interface for S1AP
class rrc_interface_s1ap
{
public:
virtual void write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu) = 0;
virtual void release_complete(uint16_t rnti) = 0;
virtual bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) = 0;
virtual bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) = 0;
virtual bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) = 0;
virtual void modify_erabs(uint16_t rnti,
const asn1::s1ap::erab_modify_request_s& msg,
std::vector<uint16_t>* erabs_modified,
std::vector<uint16_t>* erabs_failed_to_modify) = 0;
virtual bool release_erabs(uint32_t rnti) = 0;
virtual void release_erabs(uint32_t rnti,
const asn1::s1ap::erab_release_cmd_s& msg,
std::vector<uint16_t>* erabs_released,
std::vector<uint16_t>* erabs_failed_to_release) = 0;
virtual void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) = 0;
/**
* Reports the reception of S1 HandoverCommand / HandoverPreparationFailure or abnormal conditions during
* S1 Handover preparation back to RRC.
*
* @param rnti user
* @param is_success true if ho cmd was received
* @param container TargeteNB RRCConnectionReconfiguration message with MobilityControlInfo
*/
virtual void ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t container) = 0;
virtual uint16_t
start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container) = 0;
virtual void set_erab_status(uint16_t rnti, const asn1::s1ap::bearers_subject_to_status_transfer_list_l& erabs) = 0;
};
// GTPU interface for PDCP
class gtpu_interface_pdcp
{
public:
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
};
// GTPU interface for RRC
class gtpu_interface_rrc
{
public:
virtual uint32_t add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out) = 0;
virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
};
// S1AP interface for RRC
class s1ap_interface_rrc
{
public:
struct bearer_status_info {
uint8_t erab_id;
uint16_t pdcp_dl_sn, pdcp_ul_sn;
uint16_t dl_hfn, ul_hfn;
};
virtual void
initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) = 0;
virtual void initial_ue(uint16_t rnti,
asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu,
uint32_t m_tmsi,
uint8_t mmec) = 0;
virtual void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) = 0;
virtual bool user_exists(uint16_t rnti) = 0;
virtual void user_mod(uint16_t old_rnti, uint16_t new_rnti) = 0;
virtual bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) = 0;
virtual void ue_ctxt_setup_complete(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res) = 0;
virtual void ue_erab_setup_complete(uint16_t rnti, const asn1::s1ap::erab_setup_resp_s& res) = 0;
virtual bool is_mme_connected() = 0;
/**
* Command the s1ap to transmit a HandoverRequired message to MME.
* This message initiates the S1 handover preparation procedure at the Source eNB
*
* @param rnti user to perform S1 handover
* @param target_eci eNB Id + Cell Id of the target eNB
* @param target_plmn PLMN of the target eNB
* @param rrc_container RRC container with SourceENBToTargetENBTransparentContainer message.
* @return true if successful
*/
virtual bool send_ho_required(uint16_t rnti,
uint32_t target_eci,
srslte::plmn_id_t target_plmn,
srslte::unique_byte_buffer_t rrc_container) = 0;
/**
* Command the s1ap to transmit eNBStatusTransfer message to MME. This message passes the PDCP context of the UE
* performing S1 handover from source eNB to target eNB.
*
* @param rnti user to perform S1 handover
* @param bearer_status_list PDCP SN and HFN status of the bearers to be preserved at target eNB
* @return true if successful
*/
virtual bool send_enb_status_transfer_proc(uint16_t rnti, std::vector<bearer_status_info>& bearer_status_list) = 0;
/* Acknowledge Handover Request message back to MME.
* This message signals the completion of the HandoverPreparation from the TeNB point of view. */
virtual bool send_ho_req_ack(const asn1::s1ap::ho_request_s& msg,
uint16_t rnti,
srslte::unique_byte_buffer_t ho_cmd,
srslte::span<asn1::fixed_octstring<4, true> > admitted_bearers) = 0;
/**
* Notify MME that Handover is complete
*/
virtual void send_ho_notify(uint16_t rnti, uint64_t target_eci) = 0;
/**
* Cancel on-going S1 Handover. MME should release UE context in target eNB
* SeNB --> MME
*/
virtual void send_ho_cancel(uint16_t rnti) = 0;
};
// Combined interface for PHY to access stack (MAC and RRC)
class stack_interface_phy_lte : public mac_interface_phy_lte
{
public:
virtual void tti_clock() = 0;
};
// Combined interface for stack (MAC and RRC) to access PHY
class phy_interface_stack_lte : public phy_interface_mac_lte, public phy_interface_rrc_lte
{};
typedef struct {
uint32_t enb_id; // 20-bit id (lsb bits)
uint8_t cell_id; // 8-bit cell id
uint16_t tac; // 16-bit tac
uint16_t mcc; // BCD-coded with 0xF filler
uint16_t mnc; // BCD-coded with 0xF filler
std::string mme_addr;
std::string gtp_bind_addr;
std::string s1c_bind_addr;
std::string enb_name;
} s1ap_args_t;
struct mac_args_t {
uint32_t nof_prb; ///< Needed to dimension MAC softbuffers for all cells
sched_interface::sched_args_t sched;
int nr_tb_size = -1;
uint32_t max_nof_ues;
};
class stack_interface_phy_lte;
class stack_interface_s1ap_lte
{
public:

@ -0,0 +1,247 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/interfaces/rrc_interface_types.h"
#include "srslte/interfaces/sched_interface.h"
#ifndef SRSLTE_ENB_MAC_INTERFACES_H
#define SRSLTE_ENB_MAC_INTERFACES_H
namespace srsenb {
struct mac_args_t {
uint32_t nof_prb; ///< Needed to dimension MAC softbuffers for all cells
sched_interface::sched_args_t sched;
int nr_tb_size = -1;
uint32_t max_nof_ues;
};
/* Interface PHY -> MAC */
class mac_interface_phy_lte
{
public:
const static int MAX_GRANTS = 64;
/**
* DL grant structure per UE
*/
struct dl_sched_grant_t {
srslte_dci_dl_t dci = {};
uint8_t* data[SRSLTE_MAX_TB] = {};
srslte_softbuffer_tx_t* softbuffer_tx[SRSLTE_MAX_TB] = {};
};
/**
* DL Scheduling result per cell/carrier
*/
typedef struct {
dl_sched_grant_t pdsch[MAX_GRANTS]; //< DL Grants
uint32_t nof_grants; //< Number of DL grants
uint32_t cfi; //< Current CFI of the cell, it can vary across cells
} dl_sched_t;
/**
* List of DL scheduling results, one entry per cell/carrier
*/
typedef std::vector<dl_sched_t> dl_sched_list_t;
typedef struct {
uint16_t rnti;
bool ack;
} ul_sched_ack_t;
/**
* UL grant information per UE
*/
typedef struct {
srslte_dci_ul_t dci;
uint32_t pid;
uint32_t current_tx_nb;
uint8_t* data;
bool needs_pdcch;
srslte_softbuffer_rx_t* softbuffer_rx;
} ul_sched_grant_t;
/**
* UL Scheduling result per cell/carrier
*/
typedef struct {
ul_sched_grant_t pusch[MAX_GRANTS];
ul_sched_ack_t phich[MAX_GRANTS];
uint32_t nof_grants;
uint32_t nof_phich;
} ul_sched_t;
/**
* List of UL scheduling results, one entry per cell/carrier
*/
typedef std::vector<ul_sched_t> ul_sched_list_t;
virtual int sr_detected(uint32_t tti, uint16_t rnti) = 0;
virtual void rach_detected(uint32_t tti, uint32_t primary_cc_idx, uint32_t preamble_idx, uint32_t time_adv) = 0;
/**
* PHY callback for giving MAC the Rank Indicator information of a given RNTI for an eNb cell/carrier.
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the measurement corresponds
* @param ri_value the actual Rank Indicator value, 0 for 1 layer, 1 for two layers and so on.
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int ri_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t ri_value) = 0;
/**
* PHY callback for giving MAC the Pre-coding Matrix Indicator information of a given RNTI for an eNb cell/carrier.
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the measurement corresponds
* @param pmi_value the actual PMI value
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int pmi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t pmi_value) = 0;
/**
* PHY callback for for giving MAC the Channel Quality information of a given RNTI, TTI and eNb cell/carrier
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the measurement corresponds
* @param cqi_value the corresponding Channel Quality Information
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) = 0;
typedef enum { PUSCH = 0, PUCCH, SRS } ul_channel_t;
/**
* PHY callback for giving MAC the SNR in dB of an UL transmission for a given RNTI at a given carrier
*
* @param tti The measurement was made
* @param rnti The UE identifier in the eNb
* @param cc_idx The eNb Cell/Carrier where the UL transmission was received
* @param snr_db The actual SNR of the received signal
* @param ch Indicates uplink channel (PUSCH, PUCCH or SRS)
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr_db, ul_channel_t ch) = 0;
/**
* PHY callback for giving MAC the Time Aligment information in microseconds of a given RNTI during a TTI processing
*
* @param tti The measurement was made
* @param rnti The UE identifier in the eNb
* @param ta_us The actual time alignment in microseconds
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int ta_info(uint32_t tti, uint16_t rnti, float ta_us) = 0;
/**
* PHY callback for giving MAC the HARQ DL ACK/NACK feedback information for a given RNTI, TTI, eNb cell/carrier and
* Transport block.
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx the eNb Cell/Carrier identifier
* @param tb_idx the transport block index
* @param ack true for ACK, false for NACK, do not call for DTX
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int ack_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t tb_idx, bool ack) = 0;
/**
* Informs MAC about a received PUSCH transmission for given RNTI, TTI and eNb Cell/carrier.
*
* This function does not deallocate the uplink buffer. The function push_pdu() must be called after this
* to inform the MAC that the uplink buffer can be discarded or pushed to the stack
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param cc_idx the eNb Cell/Carrier identifier
* @param nof_bytes the number of grants carrierd by the PUSCH message
* @param crc_res the CRC check, set to true if the message was decoded succesfully
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int crc_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc_res) = 0;
/**
* Pushes an uplink PDU through the stack if crc_res==true or discards it if crc_res==false
*
* @param tti the given TTI
* @param rnti the UE identifier in the eNb
* @param enb_cc_idx the eNb Cell/Carrier identifier
* @param nof_bytes the number of grants carrierd by the PUSCH message
* @param crc_res the CRC check, set to true if the message was decoded succesfully
* @return SRSLTE_SUCCESS if no error occurs, SRSLTE_ERROR* if an error occurs
*/
virtual int push_pdu(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc_res) = 0;
virtual int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) = 0;
virtual int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) = 0;
virtual int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) = 0;
virtual void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0;
};
class mac_interface_rlc
{
public:
virtual int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) = 0;
};
class mac_interface_rrc
{
public:
/* Provides cell configuration including SIB periodicity, etc. */
virtual int cell_cfg(const std::vector<sched_interface::cell_cfg_t>& cell_cfg) = 0;
virtual void reset() = 0;
/* Manages UE configuration context */
virtual int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) = 0;
virtual int ue_rem(uint16_t rnti) = 0;
/**
* Called after Msg3 reception to set the UE C-RNTI, resolve contention, and alter the UE's configuration in the
* scheduler and phy.
*
* @param temp_crnti temporary C-RNTI of the UE
* @param crnti chosen C-RNTI for the UE
* @param cfg new UE scheduler configuration
*/
virtual int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) = 0;
/* Manages UE bearers and associated configuration */
virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) = 0;
virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0;
virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0;
virtual void write_mcch(const srslte::sib2_mbms_t* sib2_,
const srslte::sib13_t* sib13_,
const srslte::mcch_msg_t* mcch_,
const uint8_t* mcch_payload,
const uint8_t mcch_payload_length) = 0;
/**
* Allocate a C-RNTI for a new user, without adding it to the phy layer and scheduler yet
* @return value of the allocated C-RNTI
*/
virtual uint16_t reserve_new_crnti(const sched_interface::ue_cfg_t& ue_cfg) = 0;
};
// Combined interface for PHY to access stack (MAC and RRC)
class stack_interface_phy_lte : public mac_interface_phy_lte
{
public:
virtual void tti_clock() = 0;
};
} // namespace srsenb
#endif // SRSLTE_ENB_MAC_INTERFACES_H

@ -31,6 +31,7 @@
#include "srsenb/hdr/stack/upper/s1ap_metrics.h"
#include "srslte/common/metrics_hub.h"
#include "srslte/radio/radio_metrics.h"
#include "srslte/upper/pdcp_metrics.h"
#include "srslte/upper/rlc_metrics.h"
#include "srsue/hdr/stack/upper/gw_metrics.h"
@ -40,10 +41,15 @@ struct rlc_metrics_t {
std::vector<srslte::rlc_metrics_t> ues;
};
struct pdcp_metrics_t {
std::vector<srslte::pdcp_metrics_t> ues;
};
struct stack_metrics_t {
mac_metrics_t mac;
rrc_metrics_t rrc;
rlc_metrics_t rlc;
pdcp_metrics_t pdcp;
s1ap_metrics_t s1ap;
};

@ -0,0 +1,62 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/common/byte_buffer.h"
#include "srslte/interfaces/pdcp_interface_types.h"
#include <map>
#ifndef SRSLTE_ENB_PDCP_INTERFACES_H
#define SRSLTE_ENB_PDCP_INTERFACES_H
namespace srsenb {
// PDCP interface for GTPU
class pdcp_interface_gtpu
{
public:
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn = -1) = 0;
virtual std::map<uint32_t, srslte::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t lcid) = 0;
};
// PDCP interface for RRC
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 write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn = -1) = 0;
virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) = 0;
virtual void del_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0;
virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0;
virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0;
virtual void send_status_report(uint16_t rnti) = 0;
virtual void send_status_report(uint16_t rnti, uint32_t lcid) = 0;
virtual bool get_bearer_state(uint16_t rnti, uint32_t lcid, srslte::pdcp_lte_state_t* state) = 0;
virtual bool set_bearer_state(uint16_t rnti, uint32_t lcid, const srslte::pdcp_lte_state_t& state) = 0;
virtual void reestablish(uint16_t rnti) = 0;
};
// PDCP interface for RLC
class pdcp_interface_rlc
{
public:
/* RLC calls PDCP to push a PDCP PDU. */
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
virtual void notify_delivery(uint16_t rnti, uint32_t lcid, const std::vector<uint32_t>& pdcp_sns) = 0;
virtual void notify_failure(uint16_t rnti, uint32_t lcid, const std::vector<uint32_t>& pdcp_sns) = 0;
};
} // namespace srsenb
#endif // SRSLTE_ENB_PDCP_INTERFACES_H

@ -0,0 +1,102 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/interfaces/rrc_interface_types.h"
#include "srslte/phy/common/phy_common.h"
#ifndef SRSLTE_ENB_PHY_INTERFACES_H
#define SRSLTE_ENB_PHY_INTERFACES_H
namespace srsenb {
/* Interface MAC -> PHY */
class phy_interface_mac_lte
{
public:
/**
* Removes an RNTI context from all the physical layer components, including secondary cells
* @param rnti identifier of the user
*/
virtual void rem_rnti(uint16_t rnti) = 0;
/**
* Pregenerates the scrambling sequences for a given RNTI.
* WARNING: This function make take several ms to complete.
*
* @param rnti identifier of the user
*/
virtual int pregen_sequences(uint16_t rnti) = 0;
/**
*
* @param stop
*/
virtual void set_mch_period_stop(uint32_t stop) = 0;
/**
* Activates and/or deactivates Secondary Cells in the PHY for a given RNTI. Requires the RNTI of the given UE and a
* vector with the activation/deactivation values. Use true for activation and false for deactivation. The index 0 is
* reserved for PCell and will not be used.
*
* @param rnti identifier of the user
* @param activation vector with the activate/deactivate.
*/
virtual void set_activation_deactivation_scell(uint16_t rnti,
const std::array<bool, SRSLTE_MAX_CARRIERS>& activation) = 0;
};
/* Interface RRC -> PHY */
class phy_interface_rrc_lte
{
public:
srslte::phy_cfg_mbsfn_t mbsfn_cfg;
virtual void configure_mbsfn(srslte::sib2_mbms_t* sib2, srslte::sib13_t* sib13, const srslte::mcch_msg_t& mcch) = 0;
struct phy_rrc_cfg_t {
bool configured = false; ///< Indicates whether PHY shall consider configuring this cell/carrier
uint32_t enb_cc_idx = 0; ///< eNb Cell index
srslte::phy_cfg_t phy_cfg = {}; ///< Dedicated physical layer configuration
};
typedef std::vector<phy_rrc_cfg_t> phy_rrc_cfg_list_t;
/**
* Sets the physical layer dedicated configuration for a given RNTI. The dedicated configuration list shall provide
* all the required information configuration for the following cases:
* - Add an RNTI straight from RRC
* - Moving primary to another serving cell
* - Add/Remove secondary serving cells
*
* Remind this call will partially reconfigure the primary serving cell, `complete_config``shall be called
* in order to complete the configuration.
*
* @param rnti the given RNTI
* @param phy_cfg_list Physical layer configuration for the indicated eNb cell
*/
virtual void set_config(uint16_t rnti, const phy_rrc_cfg_list_t& phy_cfg_list) = 0;
/**
* Instructs the physical layer the configuration has been complete from upper layers for a given RNTI
*
* @param rnti the given UE identifier (RNTI)
*/
virtual void complete_config(uint16_t rnti) = 0;
};
// Combined interface for stack (MAC and RRC) to access PHY
class phy_interface_stack_lte : public phy_interface_mac_lte, public phy_interface_rrc_lte
{};
} // namespace srsenb
#endif // SRSLTE_ENB_PHY_INTERFACES_H

@ -0,0 +1,67 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_ENB_RLC_INTERFACES_H
#define SRSLTE_ENB_RLC_INTERFACES_H
#include "srslte/common/byte_buffer.h"
#include "srslte/interfaces/rlc_interface_types.h"
namespace srsenb {
// RLC interface for MAC
class rlc_interface_mac
{
public:
/* MAC calls RLC to get RLC segment of nof_bytes length.
* Segmentation happens in this function. RLC PDU is stored in payload. */
virtual int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
virtual void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) = 0;
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread.
* PDU gets placed into the buffer and higher layer thread gets notified. */
virtual void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
};
// RLC interface for PDCP
class rlc_interface_pdcp
{
public:
/* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls
* RLC PDUs according to TB size. */
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void discard_sdu(uint16_t rnti, uint32_t lcid, uint32_t sn) = 0;
virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0;
virtual bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid) = 0;
};
// RLC interface for RRC
class rlc_interface_rrc
{
public:
virtual void clear_buffer(uint16_t rnti) = 0;
virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
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 del_bearer(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;
virtual bool suspend_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual bool resume_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void reestablish(uint16_t rnti) = 0;
};
} // namespace srsenb
#endif // SRSLTE_ENB_RLC_INTERFACES_H

@ -0,0 +1,92 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/asn1/s1ap_utils.h"
#include "srslte/interfaces/enb_rrc_interface_types.h"
#include "srslte/interfaces/sched_interface.h"
#ifndef SRSLTE_ENB_RRC_INTERFACES_H
#define SRSLTE_ENB_RRC_INTERFACES_H
namespace srsenb {
// RRC interface for S1AP
class rrc_interface_s1ap
{
public:
virtual void write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu) = 0;
virtual void release_complete(uint16_t rnti) = 0;
virtual bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) = 0;
virtual bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) = 0;
virtual bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) = 0;
virtual void modify_erabs(uint16_t rnti,
const asn1::s1ap::erab_modify_request_s& msg,
std::vector<uint16_t>* erabs_modified,
std::vector<uint16_t>* erabs_failed_to_modify) = 0;
virtual bool release_erabs(uint32_t rnti) = 0;
virtual void release_erabs(uint32_t rnti,
const asn1::s1ap::erab_release_cmd_s& msg,
std::vector<uint16_t>* erabs_released,
std::vector<uint16_t>* erabs_failed_to_release) = 0;
virtual void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) = 0;
/**
* Reports the reception of S1 HandoverCommand / HandoverPreparationFailure or abnormal conditions during
* S1 Handover preparation back to RRC.
*
* @param rnti user
* @param is_success true if ho cmd was received
* @param container TargeteNB RRCConnectionReconfiguration message with MobilityControlInfo
*/
virtual void ho_preparation_complete(uint16_t rnti,
bool is_success,
const asn1::s1ap::ho_cmd_s& msg,
srslte::unique_byte_buffer_t container) = 0;
virtual uint16_t
start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container) = 0;
virtual void set_erab_status(uint16_t rnti, const asn1::s1ap::bearers_subject_to_status_transfer_list_l& erabs) = 0;
};
/// RRC interface for RLC
class rrc_interface_rlc
{
public:
virtual void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) = 0;
virtual void max_retx_attempted(uint16_t rnti) = 0;
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
};
/// RRC interface for MAC
class rrc_interface_mac
{
public:
/* Radio Link failure */
virtual int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) = 0;
virtual void upd_user(uint16_t new_rnti, uint16_t old_rnti) = 0;
virtual void set_activity_user(uint16_t rnti) = 0;
virtual bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) = 0;
///< Provide packed SIB to MAC (buffer is managed by RRC)
virtual uint8_t* read_pdu_bcch_dlsch(const uint8_t enb_cc_idx, const uint32_t sib_index) = 0;
};
/// RRC interface for PDCP
class rrc_interface_pdcp
{
public:
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
};
} // namespace srsenb
#endif // SRSLTE_ENB_RRC_INTERFACES_H

@ -0,0 +1,119 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srslte/asn1/s1ap_utils.h"
#include "srslte/interfaces/rrc_interface_types.h"
#ifndef SRSLTE_ENB_S1AP_INTERFACES_H
#define SRSLTE_ENB_S1AP_INTERFACES_H
namespace srsenb {
struct s1ap_args_t {
uint32_t enb_id; // 20-bit id (lsb bits)
uint8_t cell_id; // 8-bit cell id
uint16_t tac; // 16-bit tac
uint16_t mcc; // BCD-coded with 0xF filler
uint16_t mnc; // BCD-coded with 0xF filler
std::string mme_addr;
std::string gtp_bind_addr;
std::string s1c_bind_addr;
std::string enb_name;
};
// S1AP interface for RRC
class s1ap_interface_rrc
{
public:
struct bearer_status_info {
uint8_t erab_id;
uint16_t pdcp_dl_sn, pdcp_ul_sn;
uint16_t dl_hfn, ul_hfn;
};
virtual void initial_ue(uint16_t rnti,
uint32_t enb_cc_idx,
asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu) = 0;
virtual void initial_ue(uint16_t rnti,
uint32_t enb_cc_idx,
asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu,
uint32_t m_tmsi,
uint8_t mmec) = 0;
virtual void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) = 0;
virtual bool user_exists(uint16_t rnti) = 0;
virtual void user_mod(uint16_t old_rnti, uint16_t new_rnti) = 0;
virtual bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) = 0;
virtual void ue_ctxt_setup_complete(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res) = 0;
virtual void ue_erab_setup_complete(uint16_t rnti, const asn1::s1ap::erab_setup_resp_s& res) = 0;
virtual bool is_mme_connected() = 0;
/**
* Command the s1ap to transmit a HandoverRequired message to MME.
* This message initiates the S1 handover preparation procedure at the Source eNB
*
* @param rnti user to perform S1 handover
* @param target_eci eNB Id + Cell Id of the target eNB
* @param target_plmn PLMN of the target eNB
* @param fwd_erabs E-RABs that are candidates to DL forwarding
* @param rrc_container RRC container with SourceENBToTargetENBTransparentContainer message.
* @return true if successful
*/
virtual bool send_ho_required(uint16_t rnti,
uint32_t target_eci,
srslte::plmn_id_t target_plmn,
srslte::span<uint32_t> fwd_erabs,
srslte::unique_byte_buffer_t rrc_container) = 0;
/**
* Command the s1ap to transmit eNBStatusTransfer message to MME. This message passes the PDCP context of the UE
* performing S1 handover from source eNB to target eNB.
*
* @param rnti user to perform S1 handover
* @param bearer_status_list PDCP SN and HFN status of the bearers to be preserved at target eNB
* @return true if successful
*/
virtual bool send_enb_status_transfer_proc(uint16_t rnti, std::vector<bearer_status_info>& bearer_status_list) = 0;
/* Acknowledge Handover Request message back to MME.
* This message signals the completion of the HandoverPreparation from the TeNB point of view. */
virtual bool send_ho_req_ack(const asn1::s1ap::ho_request_s& msg,
uint16_t rnti,
uint32_t enb_cc_idx,
srslte::unique_byte_buffer_t ho_cmd,
srslte::span<asn1::s1ap::erab_admitted_item_s> admitted_bearers) = 0;
/**
* Notify MME that Handover is complete
*/
virtual void send_ho_notify(uint16_t rnti, uint64_t target_eci) = 0;
/**
* Cancel on-going S1 Handover. MME should release UE context in target eNB
* SeNB --> MME
*/
virtual void send_ho_cancel(uint16_t rnti) = 0;
/**
* Called during release of a subset of eNB E-RABs. Send E-RAB RELEASE INDICATION to MME.
* SeNB --> MME
*/
virtual bool release_erabs(uint16_t rnti, const std::vector<uint16_t>& erabs_successfully_released) = 0;
virtual bool send_ue_cap_info_indication(uint16_t rnti, srslte::unique_byte_buffer_t ue_radio_cap) = 0;
};
} // namespace srsenb
#endif // SRSLTE_ENB_S1AP_INTERFACES_H

@ -117,13 +117,13 @@ public:
virtual bool delete_gtpu_tunnel(in_addr_t ue_ipv4) = 0;
virtual bool delete_gtpc_tunnel(in_addr_t ue_ipv4) = 0;
virtual void send_all_queued_packets(srslte::gtp_fteid_t dw_user_fteid,
std::queue<srslte::byte_buffer_t*>& pkt_queue) = 0;
std::queue<srslte::unique_byte_buffer_t>& pkt_queue) = 0;
};
class gtpc_interface_gtpu // GTP-U -> GTP-C
{
public:
virtual bool queue_downlink_packet(uint32_t spgw_ctr_teid, srslte::byte_buffer_t* msg) = 0;
virtual bool queue_downlink_packet(uint32_t spgw_ctr_teid, srslte::unique_byte_buffer_t msg) = 0;
virtual bool send_downlink_data_notification(uint32_t spgw_ctr_teid) = 0;
};

@ -92,7 +92,10 @@ class pdcp_interface_rlc_nr
public:
/* RLC calls PDCP to push a PDCP PDU. */
virtual void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void notify_delivery(uint16_t rnti, uint32_t lcid, const std::vector<uint32_t>& tx_count) = 0;
virtual void notify_failure(uint16_t rnti, uint32_t lcid, const std::vector<uint32_t>& tx_count) = 0;
};
class pdcp_interface_rrc_nr
{
public:
@ -105,6 +108,7 @@ public:
virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0;
virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0;
};
class pdcp_interface_sdap_nr
{
public:

@ -125,6 +125,26 @@ struct rach_cfg_t {
}
};
// 38.321 5.1.1 Not complete yet
struct rach_nr_cfg_t {
uint32_t prach_ConfigurationIndex;
int PreambleReceivedTargetPower;
uint32_t preambleTransMax;
uint32_t powerRampingStep;
uint32_t ra_responseWindow;
uint32_t ra_ContentionResolutionTimer;
rach_nr_cfg_t() { reset(); }
void reset()
{
prach_ConfigurationIndex = 0;
PreambleReceivedTargetPower = 0;
powerRampingStep = 0;
preambleTransMax = 0;
ra_responseWindow = 0;
}
};
struct mac_cfg_t {
// Default constructor with default values as in 36.331 9.2.2
mac_cfg_t() { set_defaults(); }

@ -39,6 +39,7 @@ namespace srslte {
// LTE and NR common config
const uint8_t PDCP_SN_LEN_5 = 5;
const uint8_t PDCP_SN_LEN_7 = 7;
const uint8_t PDCP_SN_LEN_15 = 15;
const uint8_t PDCP_SN_LEN_12 = 12;
const uint8_t PDCP_SN_LEN_18 = 18;
@ -51,6 +52,18 @@ enum pdcp_dc_field_t {
};
static const char* pdcp_dc_field_text[PDCP_DC_FIELD_N_ITEMS] = {"Control PDU", "Data PDU"};
enum pdcp_pdu_type_t {
PDCP_PDU_TYPE_STATUS_REPORT = 0,
PDCP_PDU_TYPE_INTERSPERSED_ROHC_FEEDBACK_PACKET,
PDCP_PDU_TYPE_LWA_STATUS_REPORT,
PDCP_PDU_TYPE_LWA_END_MARKER_PACKET,
PDCP_PDU_TYPE_N_ITEMS,
};
static const char* pdcp_pdu_type_text[PDCP_PDU_TYPE_N_ITEMS] = {"PDCP Report PDU",
"Interspersed ROCH Feedback Packet",
"LWA Status Report",
"LWA End-marker Packet"};
// Taken from PDCP-Config (TS 38.331 version 15.2.1)
enum class pdcp_t_reordering_t {
ms0 = 0,
@ -120,14 +133,16 @@ public:
security_direction_t rx_direction_,
uint8_t sn_len_,
pdcp_t_reordering_t t_reordering_,
pdcp_discard_timer_t discard_timer_) :
pdcp_discard_timer_t discard_timer_,
bool status_report_required_) :
bearer_id(bearer_id_),
rb_type(rb_type_),
tx_direction(tx_direction_),
rx_direction(rx_direction_),
sn_len(sn_len_),
t_reordering(t_reordering_),
discard_timer(discard_timer_)
discard_timer(discard_timer_),
status_report_required(status_report_required_)
{
hdr_len_bytes = ceilf((float)sn_len / 8);
}
@ -142,6 +157,8 @@ public:
pdcp_t_reordering_t t_reordering = pdcp_t_reordering_t::ms500;
pdcp_discard_timer_t discard_timer = pdcp_discard_timer_t::infinity;
bool status_report_required = false;
// TODO: Support the following configurations
// bool do_rohc;
};

@ -0,0 +1,560 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_RRC_NR_INTERFACE_TYPES_H
#define SRSLTE_RRC_NR_INTERFACE_TYPES_H
#include "srslte/config.h"
#include "srslte/srslte.h"
#include <string>
namespace srslte {
/***************************
* PHY Config
**************************/
struct phy_cfg_nr_t {
srslte_sch_hl_cfg_nr_t pdsch = {};
srslte_sch_hl_cfg_nr_t pusch = {};
srslte_pucch_nr_hl_cfg_t pucch = {};
srslte_prach_cfg_t prach = {};
srslte_ue_dl_nr_pdcch_cfg_t pdcch = {};
srslte_ue_dl_nr_harq_ack_cfg_t harq_ack = {};
phy_cfg_nr_t()
{
// Default PDSCH configuration
pdsch.sch_cfg.mcs_table = srslte_mcs_table_256qam;
// Default PRACH configuration
prach.is_nr = true;
prach.config_idx = 16;
prach.root_seq_idx = 1;
prach.freq_offset = 0;
prach.zero_corr_zone = 0;
prach.num_ra_preambles = 64;
prach.hs_flag = false;
// physicalCellGroupConfig
// pdsch-HARQ-ACK-Codebook: dynamic (1)
harq_ack.pdsch_harq_ack_codebook = srslte_pdsch_harq_ack_codebook_dynamic;
// commonControlResourceSet
// controlResourceSetId: 1
// frequencyDomainResources: ff0000000000
// duration: 1
// cce-REG-MappingType: nonInterleaved (1)
// nonInterleaved: NULL
// precoderGranularity: sameAsREG-bundle (0)
pdcch.coreset[1].coreset_id = 1;
pdcch.coreset[1].precoder_granularity = srslte_coreset_precoder_granularity_reg_bundle;
pdcch.coreset[1].duration = 1;
pdcch.coreset[1].mapping_type = srslte_coreset_mapping_type_non_interleaved;
for (uint32_t i = 0; i < SRSLTE_CORESET_FREQ_DOMAIN_RES_SIZE; i++) {
pdcch.coreset[1].freq_resources[i] = (i < 8);
}
pdcch.coreset_present[1] = true;
// SearchSpace
// searchSpaceId: 1
// controlResourceSetId: 1
// monitoringSlotPeriodicityAndOffset: sl1 (0)
// sl1: NULL
// monitoringSymbolsWithinSlot: 8000 [bit length 14, 2 LSB pad bits, 1000 0000 0000 00.. decimal value 8192]
// nrofCandidates
// aggregationLevel1: n0 (0)
// aggregationLevel2: n0 (0)
// aggregationLevel4: n1 (1)
// aggregationLevel8: n0 (0)
// aggregationLevel16: n0 (0)
// searchSpaceType: common (0)
// common
// dci-Format0-0-AndFormat1-0
srslte_search_space_t search_space1 = {};
search_space1.id = 1;
search_space1.coreset_id = 1;
search_space1.nof_candidates[0] = 0;
search_space1.nof_candidates[1] = 0;
search_space1.nof_candidates[2] = 1;
search_space1.nof_candidates[3] = 0;
search_space1.nof_candidates[4] = 0;
search_space1.type = srslte_search_space_type_common_3;
pdcch.search_space[1] = search_space1;
pdcch.search_space_present[1] = true;
// ra-SearchSpace: 1
pdcch.ra_rnti = 0x16; //< Supposed to be deduced from PRACH configuration
pdcch.ra_search_space = search_space1;
pdcch.ra_search_space.type = srslte_search_space_type_common_1;
pdcch.ra_search_space_present = true;
// pdsch-ConfigCommon: setup (1)
// setup
// pdsch-TimeDomainAllocationList: 2 items
// Item 0
// PDSCH-TimeDomainResourceAllocation
// mappingType: typeA (0)
// startSymbolAndLength: 40
// Item 1
// PDSCH-TimeDomainResourceAllocation
// mappingType: typeA (0)
// startSymbolAndLength: 57
pdsch.common_time_ra[0].mapping_type = srslte_sch_mapping_type_A;
pdsch.common_time_ra[0].sliv = 40;
pdsch.common_time_ra[0].k = 0;
pdsch.common_time_ra[1].mapping_type = srslte_sch_mapping_type_A;
pdsch.common_time_ra[1].sliv = 57;
pdsch.common_time_ra[1].k = 0;
pdsch.nof_common_time_ra = 2;
// pusch-ConfigCommon: setup (1)
// setup
// pusch-TimeDomainAllocationList: 2 items
// Item 0
// PUSCH-TimeDomainResourceAllocation
// k2: 4
// mappingType: typeA (0)
// startSymbolAndLength: 27
// Item 1
// PUSCH-TimeDomainResourceAllocation
// k2: 5
// mappingType: typeA (0)
// startSymbolAndLength: 27
// p0-NominalWithGrant: -90dBm
pusch.common_time_ra[0].mapping_type = srslte_sch_mapping_type_A;
pusch.common_time_ra[0].sliv = 27;
pusch.common_time_ra[0].k = 4;
pusch.common_time_ra[1].mapping_type = srslte_sch_mapping_type_A;
pusch.common_time_ra[1].sliv = 27;
pusch.common_time_ra[1].k = 5;
pusch.nof_common_time_ra = 2;
// pusch-Config: setup (1)
// setup
// dmrs-UplinkForPUSCH-MappingTypeA: setup (1)
// setup
// dmrs-AdditionalPosition: pos1 (1)
// transformPrecodingDisabled
pusch.dmrs_typeA.additional_pos = srslte_dmrs_sch_add_pos_1;
pusch.dmrs_typeA.present = true;
// pusch-PowerControl
// msg3-Alpha: alpha1 (7)
// p0-NominalWithoutGrant: -90dBm
// p0-AlphaSets: 1 item
// Item 0
// P0-PUSCH-AlphaSet
// p0-PUSCH-AlphaSetId: 0
// p0: 0dB
// alpha: alpha1 (7)
// pathlossReferenceRSToAddModList: 1 item
// Item 0
// PUSCH-PathlossReferenceRS
// pusch-PathlossReferenceRS-Id: 0
// referenceSignal: ssb-Index (0)
// ssb-Index: 0
// sri-PUSCH-MappingToAddModList: 1 item
// Item 0
// SRI-PUSCH-PowerControl
// sri-PUSCH-PowerControlId: 0
// sri-PUSCH-PathlossReferenceRS-Id: 0
// sri-P0-PUSCH-AlphaSetId: 0
// sri-PUSCH-ClosedLoopIndex: i0 (0)
// resourceAllocation: resourceAllocationType1 (1)
// uci-OnPUSCH: setup (1)
// setup
// betaOffsets: semiStatic (1)
// semiStatic
// betaOffsetACK-Index1: 9
// betaOffsetACK-Index2: 9
// betaOffsetACK-Index3: 9
// betaOffsetCSI-Part1-Index1: 6
// betaOffsetCSI-Part1-Index2: 6
// betaOffsetCSI-Part2-Index1: 6
// betaOffsetCSI-Part2-Index2: 6
// scaling: f1 (3)
// pucch-Config: setup (1)
// setup
// resourceSetToAddModList: 2 items
pucch.enabled = true;
// Item 0
// PUCCH-ResourceSet
// pucch-ResourceSetId: 0
// resourceList: 8 items
// Item 0
// PUCCH-ResourceId: 0
// Item 1
// PUCCH-ResourceId: 1
// Item 2
// PUCCH-ResourceId: 2
// Item 3
// PUCCH-ResourceId: 3
// Item 4
// PUCCH-ResourceId: 4
// Item 5
// PUCCH-ResourceId: 5
// Item 6
// PUCCH-ResourceId: 6
// Item 7
// PUCCH-ResourceId: 7
pucch.sets[0].nof_resources = 8;
// Item 1
// PUCCH-ResourceSet
// pucch-ResourceSetId: 1
// resourceList: 8 items
// Item 0
// PUCCH-ResourceId: 8
// Item 1
// PUCCH-ResourceId: 9
// Item 2
// PUCCH-ResourceId: 10
// Item 3
// PUCCH-ResourceId: 11
// Item 4
// PUCCH-ResourceId: 12
// Item 5
// PUCCH-ResourceId: 13
// Item 6
// PUCCH-ResourceId: 14
// Item 7
// PUCCH-ResourceId: 15
pucch.sets[1].nof_resources = 8;
// resourceToAddModList: 18 items
// Item 0
// PUCCH-Resource
// pucch-ResourceId: 0
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 0
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 0
pucch.sets[0].resources[0].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[0].starting_prb = 0;
pucch.sets[0].resources[0].initial_cyclic_shift = 0;
pucch.sets[0].resources[0].nof_symbols = 14;
pucch.sets[0].resources[0].start_symbol_idx = 0;
pucch.sets[0].resources[0].time_domain_occ = 0;
// Item 1
// PUCCH-Resource
// pucch-ResourceId: 1
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 4
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 0
pucch.sets[0].resources[1].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[1].starting_prb = 0;
pucch.sets[0].resources[1].initial_cyclic_shift = 4;
pucch.sets[0].resources[1].nof_symbols = 14;
pucch.sets[0].resources[1].start_symbol_idx = 0;
pucch.sets[0].resources[1].time_domain_occ = 0;
// Item 2
// PUCCH-Resource
// pucch-ResourceId: 2
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 8
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 0
pucch.sets[0].resources[2].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[2].starting_prb = 0;
pucch.sets[0].resources[2].initial_cyclic_shift = 8;
pucch.sets[0].resources[2].nof_symbols = 14;
pucch.sets[0].resources[2].start_symbol_idx = 0;
pucch.sets[0].resources[2].time_domain_occ = 0;
// Item 3
// PUCCH-Resource
// pucch-ResourceId: 3
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 0
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 1
pucch.sets[0].resources[3].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[3].starting_prb = 0;
pucch.sets[0].resources[3].initial_cyclic_shift = 0;
pucch.sets[0].resources[3].nof_symbols = 14;
pucch.sets[0].resources[3].start_symbol_idx = 0;
pucch.sets[0].resources[3].time_domain_occ = 1;
// Item 4
// PUCCH-Resource
// pucch-ResourceId: 4
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 4
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 1
pucch.sets[0].resources[4].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[4].starting_prb = 0;
pucch.sets[0].resources[4].initial_cyclic_shift = 4;
pucch.sets[0].resources[4].nof_symbols = 14;
pucch.sets[0].resources[4].start_symbol_idx = 0;
pucch.sets[0].resources[4].time_domain_occ = 1;
// Item 5
// PUCCH-Resource
// pucch-ResourceId: 5
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 8
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 1
pucch.sets[0].resources[5].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[5].starting_prb = 0;
pucch.sets[0].resources[5].initial_cyclic_shift = 8;
pucch.sets[0].resources[5].nof_symbols = 14;
pucch.sets[0].resources[5].start_symbol_idx = 0;
pucch.sets[0].resources[5].time_domain_occ = 1;
// Item 6
// PUCCH-Resource
// pucch-ResourceId: 6
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 0
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 2
pucch.sets[0].resources[6].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[6].starting_prb = 0;
pucch.sets[0].resources[6].initial_cyclic_shift = 0;
pucch.sets[0].resources[6].nof_symbols = 14;
pucch.sets[0].resources[6].start_symbol_idx = 0;
pucch.sets[0].resources[6].time_domain_occ = 2;
// Item 7
// PUCCH-Resource
// pucch-ResourceId: 7
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 4
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 2
pucch.sets[0].resources[7].format = SRSLTE_PUCCH_NR_FORMAT_1;
pucch.sets[0].resources[7].starting_prb = 0;
pucch.sets[0].resources[7].initial_cyclic_shift = 0;
pucch.sets[0].resources[7].nof_symbols = 14;
pucch.sets[0].resources[7].start_symbol_idx = 0;
pucch.sets[0].resources[7].time_domain_occ = 2;
// Item 8
// PUCCH-Resource
// pucch-ResourceId: 8
// startingPRB: 51
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 0
pucch.sets[1].resources[0].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[0].starting_prb = 51;
pucch.sets[1].resources[0].nof_prb = 1;
pucch.sets[1].resources[0].nof_symbols = 2;
pucch.sets[1].resources[0].start_symbol_idx = 0;
// Item 9
// PUCCH-Resource
// pucch-ResourceId: 9
// startingPRB: 51
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 2
pucch.sets[1].resources[1].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[1].starting_prb = 51;
pucch.sets[1].resources[1].nof_prb = 1;
pucch.sets[1].resources[1].nof_symbols = 2;
pucch.sets[1].resources[1].start_symbol_idx = 2;
// Item 10
// PUCCH-Resource
// pucch-ResourceId: 10
// startingPRB: 51
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 4
pucch.sets[1].resources[2].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[2].starting_prb = 51;
pucch.sets[1].resources[2].nof_prb = 1;
pucch.sets[1].resources[2].nof_symbols = 2;
pucch.sets[1].resources[2].start_symbol_idx = 4;
// Item 11
// PUCCH-Resource
// pucch-ResourceId: 11
// startingPRB: 51
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 6
pucch.sets[1].resources[3].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[3].starting_prb = 51;
pucch.sets[1].resources[3].nof_prb = 1;
pucch.sets[1].resources[3].nof_symbols = 2;
pucch.sets[1].resources[3].start_symbol_idx = 6;
// Item 12
// PUCCH-Resource
// pucch-ResourceId: 12
// startingPRB: 51
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 8
pucch.sets[1].resources[4].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[4].starting_prb = 51;
pucch.sets[1].resources[4].nof_prb = 1;
pucch.sets[1].resources[4].nof_symbols = 2;
pucch.sets[1].resources[4].start_symbol_idx = 8;
// Item 13
// PUCCH-Resource
// pucch-ResourceId: 13
// startingPRB: 51
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 10
pucch.sets[1].resources[5].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[5].starting_prb = 51;
pucch.sets[1].resources[5].nof_prb = 1;
pucch.sets[1].resources[5].nof_symbols = 2;
pucch.sets[1].resources[5].start_symbol_idx = 10;
// Item 14
// PUCCH-Resource
// pucch-ResourceId: 14
// startingPRB: 51
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 12
pucch.sets[1].resources[6].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[6].starting_prb = 51;
pucch.sets[1].resources[6].nof_prb = 1;
pucch.sets[1].resources[6].nof_symbols = 2;
pucch.sets[1].resources[6].start_symbol_idx = 12;
// Item 15
// PUCCH-Resource
// pucch-ResourceId: 15
// startingPRB: 1
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 0
pucch.sets[1].resources[7].format = SRSLTE_PUCCH_NR_FORMAT_2;
pucch.sets[1].resources[7].starting_prb = 51;
pucch.sets[1].resources[7].nof_prb = 1;
pucch.sets[1].resources[7].nof_symbols = 2;
pucch.sets[1].resources[7].start_symbol_idx = 2;
// Item 16
// PUCCH-Resource
// pucch-ResourceId: 16
// startingPRB: 0
// format: format1 (1)
// format1
// initialCyclicShift: 8
// nrofSymbols: 14
// startingSymbolIndex: 0
// timeDomainOCC: 2
// Item 17
// PUCCH-Resource
// pucch-ResourceId: 17
// startingPRB: 1
// format: format2 (2)
// format2
// nrofPRBs: 1
// nrofSymbols: 2
// startingSymbolIndex: 2
// format1: setup (1)
// setup
// format2: setup (1)
// setup
// maxCodeRate: zeroDot25 (2)
for (uint32_t i = 0; i < SRSLTE_PUCCH_NR_MAX_NOF_SETS; i++) {
srslte_pucch_nr_resource_set_t* set = &pucch.sets[i];
for (uint32_t j = 0; j < set->nof_resources; j++) {
if (set->resources[j].format == SRSLTE_PUCCH_NR_FORMAT_2) {
set->resources[j].max_code_rate = 2; // 0.25
}
}
}
// schedulingRequestResourceToAddModList: 1 item
// Item 0
// SchedulingRequestResourceConfig
// schedulingRequestResourceId: 1
// schedulingRequestID: 0
// periodicityAndOffset: sl40 (10)
// sl40: 8
// resource: 16
// dl-DataToUL-ACK: 7 items
// Item 0
// dl-DataToUL-ACK item: 8
// Item 1
// dl-DataToUL-ACK item: 7
// Item 2
// dl-DataToUL-ACK item: 6
// Item 3
// dl-DataToUL-ACK item: 5
// Item 4
// dl-DataToUL-ACK item: 4
// Item 5
// dl-DataToUL-ACK item: 12
// Item 6
// dl-DataToUL-ACK item: 11
harq_ack.dl_data_to_ul_ack[0] = 8;
harq_ack.dl_data_to_ul_ack[1] = 7;
harq_ack.dl_data_to_ul_ack[2] = 6;
harq_ack.dl_data_to_ul_ack[3] = 5;
harq_ack.dl_data_to_ul_ack[4] = 4;
harq_ack.dl_data_to_ul_ack[5] = 12;
harq_ack.dl_data_to_ul_ack[6] = 11;
harq_ack.nof_dl_data_to_ul_ack = 7;
}
};
} // namespace srslte
#endif // SRSLTE_RRC_NR_INTERFACE_TYPES_H

@ -87,7 +87,12 @@ public:
class gw_interface_nas
{
public:
virtual int setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) = 0;
virtual int setup_if_addr(uint32_t eps_bearer_id,
uint32_t lcid,
uint8_t pdn_type,
uint32_t ip_addr,
uint8_t* ipv6_if_id,
char* err_str) = 0;
virtual int apply_traffic_flow_template(const uint8_t& eps_bearer_id,
const uint8_t& lcid,
const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) = 0;
@ -112,6 +117,7 @@ class gw_interface_rrc
{
public:
virtual void add_mch_port(uint32_t lcid, uint32_t port) = 0;
virtual int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) = 0;
};
// GW interface for PDCP
@ -262,7 +268,7 @@ 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) = 0;
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, int sn = -1) = 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, srslte::as_security_config_t sec_cfg) = 0;
@ -270,6 +276,8 @@ public:
virtual void enable_integrity(uint32_t lcid, srslte::srslte_direction_t direction) = 0;
virtual void enable_encryption(uint32_t lcid,
srslte::srslte_direction_t direction = srslte::srslte_direction_t::DIRECTION_TXRX) = 0;
virtual void send_status_report() = 0;
virtual void send_status_report(uint32_t lcid) = 0;
};
// RRC NR interface for RRC (LTE)
class rrc_nr_interface_rrc
@ -306,6 +314,8 @@ public:
virtual void write_pdu_bcch_dlsch(srslte::unique_byte_buffer_t sdu) = 0;
virtual void write_pdu_pcch(srslte::unique_byte_buffer_t sdu) = 0;
virtual void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void notify_delivery(uint32_t lcid, const std::vector<uint32_t>& pdcp_sn) = 0;
virtual void notify_failure(uint32_t lcid, const std::vector<uint32_t>& pdcp_sn) = 0;
};
class pdcp_interface_gw
@ -526,6 +536,10 @@ typedef struct {
std::vector<uint32_t> dl_earfcn_list = {3400}; // vectorized version of dl_earfcn that gets populated during init
std::map<uint32_t, uint32_t> ul_earfcn_map; // Map linking DL EARFCN and UL EARFCN
std::string dl_nr_arfcn = "632628"; // comma-separated list of DL NR ARFCNs
std::vector<uint32_t> dl_nr_arfcn_list = {
632628}; // vectorized version of dl_nr_arfcn that gets populated during init
float dl_freq = -1.0f;
float ul_freq = -1.0f;

@ -24,6 +24,8 @@
#include "srslte/common/interfaces_common.h"
#include "srslte/interfaces/mac_interface_types.h"
#include "srslte/interfaces/rrc_nr_interface_types.h"
#include <array>
#include <string>
namespace srsue {
@ -55,12 +57,31 @@ public:
virtual int sf_indication(const uint32_t tti) = 0; ///< FIXME: rename to slot indication
// Query the MAC for the current RNTI to look for
struct sched_rnti_t {
uint16_t id;
srslte_rnti_type_t type;
};
virtual sched_rnti_t get_dl_sched_rnti_nr(const uint32_t tti) = 0;
virtual sched_rnti_t get_ul_sched_rnti_nr(const uint32_t tti) = 0;
/// Indicate succussfully received TB to MAC. The TB buffer is allocated in the PHY and handed as unique_ptr to MAC
virtual void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) = 0;
/// Indicate reception of UL grant (only TBS is provided). Buffer for resulting MAC PDU is provided by MAC and is
/// passed as pointer to PHY during tx_reuqest
virtual void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant) = 0;
virtual void
new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, srslte::byte_buffer_t* phy_tx_pdu) = 0;
/**
* @brief Indicate the successful transmission of a PRACH.
* @param tti The TTI from the PHY viewpoint at which the PRACH was sent over-the-air (not to the radio).
* @param s_id The index of the first OFDM symbol of the specified PRACH (0 <= s_id < 14).
* @param t_id The index of the first slot of the specified PRACH (0 <= t_id < 80).
* @param f_id The index of the specified PRACH in the frequency domain (0 <= f_id < 8).
* @param ul_carrier_id The UL carrier used for Msg1 transmission (0 for NUL carrier, and 1 for SUL carrier).
*/
virtual void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) = 0;
};
class mac_interface_rrc_nr
@ -69,6 +90,38 @@ public:
virtual void setup_lcid(const srslte::logical_channel_config_t& config) = 0;
virtual void set_config(const srslte::bsr_cfg_t& bsr_cfg) = 0;
virtual void set_config(const srslte::sr_cfg_t& sr_cfg) = 0;
virtual void set_config(const srslte::rach_nr_cfg_t& rach_cfg) = 0;
// RRC triggers MAC ra procedure
virtual void start_ra_procedure() = 0;
// RRC informs MAC about the (randomly) selected ID used for contention-based RA
virtual void set_contention_id(const uint64_t ue_identity) = 0;
// RRC informs MAC about new UE identity for contention-free RA
virtual bool set_crnti(const uint16_t crnti) = 0;
};
struct phy_args_nr_t {
uint32_t nof_carriers;
uint32_t nof_prb;
uint32_t nof_phy_threads;
uint32_t worker_cpu_mask;
srslte::phy_log_args_t log;
srslte_ue_dl_nr_args_t dl;
srslte_ue_ul_nr_args_t ul;
phy_args_nr_t()
{
dl.nof_rx_antennas = 1;
dl.nof_max_prb = 100;
dl.pdsch.measure_evm = true;
dl.pdsch.measure_time = true;
dl.pdsch.sch.disable_simd = false;
ul.nof_max_prb = 100;
ul.pusch.measure_time = true;
ul.pusch.sch.disable_simd = false;
}
};
class phy_interface_mac_nr
@ -80,11 +133,26 @@ public:
uint8_t* data; // always a pointer in our case
} tx_request_t;
// MAC informs PHY about UL grant included in RAR PDU
virtual int set_ul_grant(std::array<uint8_t, SRSLTE_RAR_UL_GRANT_NBITS> packed_ul_grant,
uint16_t rnti,
srslte_rnti_type_t rnti_type) = 0;
// MAC instructs PHY to transmit MAC TB at the given TTI
virtual int tx_request(const tx_request_t& request) = 0;
/// Instruct PHY to send PRACH in the next occasion.
virtual void send_prach(const uint32_t prach_occasion,
const int preamble_index,
const float preamble_received_target_power,
const float ta_base_sec = 0.0f) = 0;
};
class phy_interface_rrc_nr
{};
{
public:
virtual bool set_config(const srslte::phy_cfg_nr_t& cfg) = 0;
};
// Combined interface for PHY to access stack (MAC and RRC)
class stack_interface_phy_nr : public mac_interface_phy_nr,

@ -0,0 +1,107 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLTE_MAC_RAR_PDU_NR_H
#define SRSLTE_MAC_RAR_PDU_NR_H
#include "srslte/common/common.h"
#include "srslte/config.h"
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/srslog/srslog.h"
#include <memory>
#include <stdint.h>
#include <vector>
namespace srslte {
class mac_rar_pdu_nr;
// 3GPP 38.321 v15.3.0 Sec 6.1.5
class mac_rar_subpdu_nr
{
public:
// Possible types of RAR subpdus (same like EUTRA)
typedef enum { BACKOFF = 0, RAPID } rar_subh_type_t;
mac_rar_subpdu_nr(mac_rar_pdu_nr* parent_);
// RAR content length in bits (38.321 Sec 6.2.3)
static const uint32_t UL_GRANT_NBITS = SRSLTE_RAR_UL_GRANT_NBITS;
static const uint32_t TA_COMMAND_NBITS = 12;
// getter
bool read_subpdu(const uint8_t* ptr);
bool has_more_subpdus();
uint32_t get_total_length();
bool has_rapid() const;
uint8_t get_rapid() const;
uint16_t get_temp_crnti() const;
uint32_t get_ta() const;
std::array<uint8_t, UL_GRANT_NBITS> get_ul_grant() const;
bool has_backoff() const;
uint8_t get_backoff() const;
// setter
uint32_t write_subpdu(const uint8_t* start_);
void set_backoff(const uint8_t backoff_indicator_);
std::string to_string();
private:
int header_length = 1; // RAR PDU subheader is always 1 B
int payload_length = 0; // only used if MAC RAR is included
std::array<uint8_t, UL_GRANT_NBITS> ul_grant = {};
uint16_t ta = 0; // 12bit TA
uint16_t temp_crnti = 0;
uint16_t rapid = 0;
uint8_t backoff_indicator = 0;
rar_subh_type_t type = BACKOFF;
bool E_bit = 0;
srslog::basic_logger& logger;
mac_rar_pdu_nr* parent = nullptr;
};
class mac_rar_pdu_nr
{
public:
mac_rar_pdu_nr();
~mac_rar_pdu_nr() = default;
bool pack();
bool unpack(const uint8_t* payload, const uint32_t& len);
uint32_t get_num_subpdus();
// Returns reference to a single subPDU
const mac_rar_subpdu_nr& get_subpdu(const uint32_t& index);
// Returns reference to all subPDUs
const std::vector<mac_rar_subpdu_nr>& get_subpdus();
uint32_t get_remaining_len();
void set_si_rapid(uint16_t si_rapid_); // configured through SIB1 for on-demand SI request (See 38.331 Sec 5.2.1)
bool has_si_rapid();
std::string to_string();
private:
std::vector<mac_rar_subpdu_nr> subpdus;
uint32_t remaining_len = 0;
uint16_t si_rapid = 0;
bool si_rapid_set = false;
srslog::basic_logger& logger;
};
} // namespace srslte
#endif // SRSLTE_MAC_RAR_PDU_NR_H

@ -19,21 +19,22 @@
*
*/
#ifndef SRSLTE_MAC_NR_PDU_H
#define SRSLTE_MAC_NR_PDU_H
#ifndef SRSLTE_MAC_SCH_PDU_NR_H
#define SRSLTE_MAC_SCH_PDU_NR_H
#include "srslte/common/common.h"
#include "srslte/common/logmap.h"
#include "srslte/config.h"
#include "srslte/srslog/srslog.h"
#include <memory>
#include <stdint.h>
#include <vector>
namespace srslte {
class mac_nr_sch_pdu;
class mac_sch_pdu_nr;
class mac_nr_sch_subpdu
class mac_sch_subpdu_nr
{
public:
// 3GPP 38.321 v15.3.0 Combined Tables 6.2.1-1, 6.2.1-2
@ -50,6 +51,7 @@ public:
LONG_TRUNC_BSR = 0b111100,
CCCH_SIZE_48 = 0b110100,
CCCH_SIZE_64 = 0b000000,
SE_PHR = 0b111001, // Single Entry PHR
SHORT_BSR = 0b111101,
LONG_BSR = 0b111110,
@ -58,7 +60,7 @@ public:
PADDING = 0b111111,
} nr_lcid_sch_t;
mac_nr_sch_subpdu(mac_nr_sch_pdu* parent_);
mac_sch_subpdu_nr(mac_sch_pdu_nr* parent_);
nr_lcid_sch_t get_type();
bool is_sdu();
@ -71,10 +73,27 @@ public:
uint32_t get_sdu_length();
uint32_t get_lcid();
uint8_t* get_sdu();
uint16_t get_c_rnti();
// both return the reported values as per TS 38.321, mapping to dB according to TS 38.133 Sec 10.1.17 not done here
uint8_t get_phr();
uint8_t get_pcmax();
// BSR
struct lcg_bsr_t {
uint8_t lcg_id;
uint8_t buffer_size;
};
lcg_bsr_t get_sbsr();
static const uint8_t max_num_lcg_lbsr = 8;
std::array<lcg_bsr_t, max_num_lcg_lbsr> get_lbsr();
// setters
void set_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_);
void set_padding(const uint32_t len_);
void set_c_rnti(const uint16_t crnti_);
void set_se_phr(const uint8_t phr_, const uint8_t pcmax_);
void set_sbsr(const lcg_bsr_t bsr_);
uint32_t write_subpdu(const uint8_t* start_);
@ -88,39 +107,49 @@ private:
bool F_bit = false;
uint8_t* sdu = nullptr;
mac_nr_sch_pdu* parent = nullptr;
srslte::log_ref log_h;
static const uint8_t mac_ce_payload_len = 8 + 1; // Long BSR has max. 9 octets (see sizeof_ce() too)
std::array<uint8_t, mac_ce_payload_len> ce_write_buffer; // Buffer for CE payload
mac_sch_pdu_nr* parent = nullptr;
};
class mac_nr_sch_pdu
class mac_sch_pdu_nr
{
public:
mac_nr_sch_pdu(bool ulsch_ = false) : ulsch(ulsch_) {}
mac_sch_pdu_nr(bool ulsch_ = false) : ulsch(ulsch_), logger(srslog::fetch_basic_logger("MAC")) {}
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);
const mac_sch_subpdu_nr& get_subpdu(const uint32_t& index);
bool is_ulsch();
void init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool is_ulsch_ = false);
void init_rx(bool ulsch_ = false);
// Add SDU or CEs to PDU
// All functions will return SRSLTE_SUCCESS on success, and SRSLE_ERROR otherwise
uint32_t add_sdu(const uint32_t lcid_, const uint8_t* payload_, const uint32_t len_);
uint32_t add_crnti_ce(const uint16_t crnti_);
uint32_t add_se_phr_ce(const uint8_t phr_, const uint8_t pcmax_);
uint32_t add_sbsr_ce(const mac_sch_subpdu_nr::lcg_bsr_t bsr_);
uint32_t get_remaing_len();
private:
uint32_t size_header_sdu(const uint32_t lcid_, const uint32_t nbytes);
/// Private helper that adds a subPDU to the MAC PDU
uint32_t add_sudpdu(mac_sch_subpdu_nr& subpdu);
bool ulsch = false;
std::vector<mac_nr_sch_subpdu> subpdus;
std::vector<mac_sch_subpdu_nr> subpdus;
byte_buffer_t* buffer = nullptr;
uint32_t pdu_len = 0;
uint32_t remaining_len = 0;
srslog::basic_logger& logger;
};
} // namespace srslte
#endif // SRSLTE_MAC_NR_PDU_H
#endif // SRSLTE_MAC_SCH_PDU_NR_H

@ -24,6 +24,7 @@
#include "srslte/common/interfaces_common.h"
#include "srslte/common/logmap.h"
#include "srslte/srslog/srslog.h"
#include <sstream>
#include <stdint.h>
#include <stdio.h>
@ -127,10 +128,10 @@ template <class SubH>
class pdu
{
public:
pdu(uint32_t max_subheaders_, log_ref log_h_) :
pdu(uint32_t max_subheaders_, srslog::basic_logger& logger) :
max_subheaders(max_subheaders_),
subheaders(max_subheaders_),
log_h(log_h_),
logger(logger),
nof_subheaders(0),
cur_idx(-1),
pdu_len(0),
@ -242,12 +243,7 @@ public:
if (ret && ((ptr - init_ptr) >= (int32_t)pdu_len)) {
// stop processing last subheader indicates another one but all bytes are consumed
nof_subheaders = 0;
if (log_h) {
log_h->warning_hex(
init_ptr, pdu_len, "Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)\n", pdu_len);
} else {
srslte::console("Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)\n", pdu_len);
}
logger.warning(init_ptr, pdu_len, "Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)", pdu_len);
return SRSLTE_ERROR;
}
} while (ret && (nof_subheaders + 1) < (int)max_subheaders && ((int32_t)pdu_len > (ptr - init_ptr)));
@ -258,13 +254,7 @@ public:
// stop processing if we read payload beyond the PDU length
if ((ptr - init_ptr) > (int32_t)pdu_len) {
nof_subheaders = 0;
if (log_h) {
log_h->warning_hex(
init_ptr, pdu_len, "Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)\n", pdu_len);
} else {
srslte::console("Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)\n", pdu_len);
}
logger.warning(init_ptr, pdu_len, "Corrupted MAC PDU - all bytes have been consumed (pdu_len=%d)", pdu_len);
return SRSLTE_ERROR;
}
}
@ -281,7 +271,7 @@ protected:
bool pdu_is_ul;
byte_buffer_t* buffer_tx = nullptr;
int last_sdu_idx;
srslte::log_ref log_h;
srslog::basic_logger& logger;
/* Prepares the PDU for parsing or writing by setting the number of subheaders to 0 and the pdu length */
virtual void init_(byte_buffer_t* buffer_tx_, uint32_t pdu_len_bytes, bool is_ulsch)
@ -401,11 +391,11 @@ private:
class sch_pdu : public pdu<sch_subh>
{
public:
sch_pdu(uint32_t max_subh, const log_ref& log_h_) : pdu(max_subh, log_h_) {}
sch_pdu(uint32_t max_subh, srslog::basic_logger& logger) : pdu(max_subh, logger) {}
void parse_packet(uint8_t* ptr);
uint8_t* write_packet();
uint8_t* write_packet(srslte::log_ref log);
uint8_t* write_packet(srslog::basic_logger& log);
bool has_space_ce(uint32_t nbytes, bool var_len = false);
bool has_space_sdu(uint32_t nbytes);
int get_pdu_len();
@ -466,7 +456,7 @@ private:
class rar_pdu : public pdu<rar_subh>
{
public:
rar_pdu(uint32_t max_rars = 16, srslte::log_ref log_ = srslte::logmap::get("MAC"));
rar_pdu(uint32_t max_rars = 16, srslog::basic_logger& logger = srslog::fetch_basic_logger("MAC"));
void set_backoff(uint8_t bi);
bool has_backoff();
@ -483,7 +473,7 @@ private:
class mch_pdu : public sch_pdu
{
public:
mch_pdu(uint32_t max_subh, const log_ref& log_h_) : sch_pdu(max_subh, log_h_) {}
mch_pdu(uint32_t max_subh, srslog::basic_logger& logger) : sch_pdu(max_subh, logger) {}
private:
/* Prepares the PDU for parsing or writing by setting the number of subheaders to 0 and the pdu length */

@ -42,8 +42,10 @@ public:
virtual void process_pdu(uint8_t* buff, uint32_t len, channel_t channel) = 0;
};
pdu_queue(uint32_t pool_size = DEFAULT_POOL_SIZE) : pool(pool_size), callback(NULL) {}
void init(process_callback* callback, log_ref log_h_);
pdu_queue(srslog::basic_logger& logger, uint32_t pool_size = DEFAULT_POOL_SIZE) :
pool(pool_size), callback(NULL), logger(logger)
{}
void init(process_callback* callback);
uint8_t* request(uint32_t len);
void deallocate(const uint8_t* pdu);
@ -71,7 +73,7 @@ private:
buffer_pool<pdu_t> pool;
process_callback* callback;
log_ref log_h;
srslog::basic_logger& logger;
};
} // namespace srslte

@ -107,7 +107,7 @@ typedef struct SRSLTE_API {
} srslte_csi_rs_nzp_resource_t;
SRSLTE_API int srslte_csi_rs_nzp_put(const srslte_carrier_nr_t* carrier,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_slot_cfg_t* slot_cfg,
const srslte_csi_rs_nzp_resource_t* resource,
cf_t* grid);
@ -123,7 +123,7 @@ typedef struct SRSLTE_API {
} srslte_csi_rs_measure_t;
SRSLTE_API int srslte_csi_rs_nzp_measure(const srslte_carrier_nr_t* carrier,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_slot_cfg_t* slot_cfg,
const srslte_csi_rs_nzp_resource_t* resource,
const cf_t* grid,
srslte_csi_rs_measure_t* measure);

@ -43,7 +43,7 @@
*/
SRSLTE_API int srslte_dmrs_pdcch_put(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_slot_cfg_t* slot_cfg,
const srslte_dci_location_t* dci_location,
cf_t* sf_symbols);
@ -119,9 +119,8 @@ SRSLTE_API void srslte_dmrs_pdcch_estimator_free(srslte_dmrs_pdcch_estimator_t*
* @param[in] sf_symbols Received resource grid.
* @return SRSLTE_SUCCESS if the configurations are valid, otherwise it returns an SRSLTE_ERROR code
*/
SRSLTE_API int srslte_dmrs_pdcch_estimate(srslte_dmrs_pdcch_estimator_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const cf_t* sf_symbols);
SRSLTE_API int
srslte_dmrs_pdcch_estimate(srslte_dmrs_pdcch_estimator_t* q, const srslte_slot_cfg_t* slot_cfg, const cf_t* sf_symbols);
/**
* @brief PDSCH DMRS measurement results

@ -51,7 +51,7 @@ SRSLTE_API int srslte_dmrs_pucch_format_3_4_get_symbol_idx(const srslte_pucch_nr
SRSLTE_API int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
cf_t* slot_symbols);
@ -69,7 +69,7 @@ SRSLTE_API int srslte_dmrs_pucch_format1_put(const srslte_pucch_nr_t*
SRSLTE_API int srslte_dmrs_pucch_format1_estimate(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
const cf_t* slot_symbols,
srslte_chest_ul_res_t* res);
@ -87,7 +87,7 @@ SRSLTE_API int srslte_dmrs_pucch_format1_estimate(const srslte_pucch_nr_t*
int srslte_dmrs_pucch_format2_put(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
cf_t* slot_symbols);
@ -105,7 +105,7 @@ int srslte_dmrs_pucch_format2_put(const srslte_pucch_nr_t* q,
int srslte_dmrs_pucch_format2_estimate(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
const cf_t* slot_symbols,
srslte_chest_ul_res_t* res);

@ -41,7 +41,7 @@
* @see srslte_dmrs_sch_estimate
*/
typedef struct {
bool is_ue;
bool is_rx;
srslte_carrier_nr_t carrier;
@ -56,12 +56,12 @@ typedef struct {
/**
* @brief Computes the symbol indexes carrying DMRS and stores them in symbols_idx
* @param pdsch_cfg PDSCH configuration provided by upper layers
* @param dmrs_cfg DMRS configuration
* @param grant PDSCH information provided by a DCI
* @param symbols_idx is the destination pointer where the symbols indexes are stored
* @return It returns the number of symbols if inputs are valid, otherwise, it returns SRSLTE_ERROR code.
*/
SRSLTE_API int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* pdsch_cfg,
SRSLTE_API int srslte_dmrs_sch_get_symbols_idx(const srslte_dmrs_sch_cfg_t* dmrs_cfg,
const srslte_sch_grant_nr_t* grant,
uint32_t symbols_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS]);
@ -78,11 +78,11 @@ SRSLTE_API int srslte_dmrs_sch_get_sc_idx(const srslte_dmrs_sch_cfg_t* cfg, uint
/**
* @brief Calculates the number of resource elements taken by a PDSCH-DMRS for a given PDSCH transmission
* @param pdsch_cfg PDSCH configuration provided by upper layers
* @param dmrs_cfg PDSCH-DMRS configuration
* @param grant PDSCH information provided by a DCI
* @return it returns the number of resource elements if the configuration is valid, otherwise it returns SRSLTE_ERROR
*/
SRSLTE_API int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant);
SRSLTE_API int srslte_dmrs_sch_get_N_prb(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslte_sch_grant_nr_t* grant);
/**
* @brief Stringifies the PDSCH DMRS configuration
@ -100,10 +100,10 @@ SRSLTE_API int srslte_dmrs_sch_cfg_to_str(const srslte_dmrs_sch_cfg_t* cfg, char
* @brief Initialises DMRS PDSCH object
*
* @param q DMRS PDSCH object
* @param is_ue indicates whethe the object is for a UE (in this case, it shall initialise as an estimator)
* @param is_rx indicates whether the object is used as receiver (in this case, it shall initialise as an estimator)
* @return it returns SRSLTE_ERROR code if an error occurs, otherwise it returns SRSLTE_SUCCESS
*/
SRSLTE_API int srslte_dmrs_sch_init(srslte_dmrs_sch_t* q, bool is_ue);
SRSLTE_API int srslte_dmrs_sch_init(srslte_dmrs_sch_t* q, bool is_rx);
/**
* @brief Frees DMRS PDSCH object
@ -135,7 +135,7 @@ SRSLTE_API int srslte_dmrs_sch_set_carrier(srslte_dmrs_sch_t* q, const srslte_ca
* @return it returns SRSLTE_ERROR code if an error occurs, otherwise it returns SRSLTE_SUCCESS
*/
SRSLTE_API int srslte_dmrs_sch_put_sf(srslte_dmrs_sch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_slot_cfg_t* slot_cfg,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
cf_t* sf_symbols);
@ -155,7 +155,7 @@ SRSLTE_API int srslte_dmrs_sch_put_sf(srslte_dmrs_sch_t* q,
* @return it returns SRSLTE_ERROR code if an error occurs, otherwise it returns SRSLTE_SUCCESS
*/
SRSLTE_API int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_slot_cfg_t* slot_cfg,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_grant_nr_t* grant,
const cf_t* sf_symbols,

@ -69,14 +69,14 @@ public:
uint32_t rlf_t_off_ms = 2000;
} args_t;
channel(const args_t& channel_args, uint32_t _nof_channels);
channel(const args_t& channel_args, uint32_t _nof_channels, srslog::basic_logger& logger);
~channel();
void set_logger(log_filter* _log_h);
void set_srate(uint32_t srate);
void set_signal_power_dBfs(float power_dBfs);
void run(cf_t* in[SRSLTE_MAX_CHANNELS], cf_t* out[SRSLTE_MAX_CHANNELS], uint32_t len, const srslte_timestamp_t& t);
private:
srslog::basic_logger& logger;
float hst_init_phase = 0.0f;
srslte_channel_fading_t* fading[SRSLTE_MAX_CHANNELS] = {};
srslte_channel_delay_t* delay[SRSLTE_MAX_CHANNELS] = {};
@ -85,7 +85,6 @@ private:
srslte_channel_rlf_t* rlf = nullptr;
cf_t* buffer_in = nullptr;
cf_t* buffer_out = nullptr;
log_filter* log_h = nullptr;
uint32_t nof_channels = 0;
uint32_t current_srate = 0;
args_t args = {};

@ -117,6 +117,11 @@ extern "C" {
*/
#define SRSLTE_MAX_NOF_DL_ALLOCATION 16
/**
* @brief Maximum dl-DataToUL-ACK value. This is defined by TS 38.331 v15.10.1 in PUCCH-Config
*/
#define SRSLTE_MAX_NOF_DL_DATA_TO_UL 8
typedef enum SRSLTE_API {
srslte_coreset_mapping_type_non_interleaved = 0,
srslte_coreset_mapping_type_interleaved,
@ -139,15 +144,33 @@ typedef enum SRSLTE_API {
*/
typedef enum SRSLTE_API { srslte_sch_mapping_type_A = 0, srslte_sch_mapping_type_B } srslte_sch_mapping_type_t;
/**
* @brief Search spaces
* @remark Described in TS 38.213 V15.10.0 Section 10.1 UE procedure for determining physical downlink control channel
* assignment
*/
typedef enum SRSLTE_API {
srslte_search_space_type_common = 0,
srslte_search_space_type_common_0,
srslte_search_space_type_common_0A,
srslte_search_space_type_common_1,
srslte_search_space_type_common_2,
srslte_search_space_type_ue,
srslte_search_space_type_common_0 = 0, ///< configured by pdcch-ConfigSIB1 in MIB or by searchSpaceSIB1 in
///< PDCCH-ConfigCommon or by searchSpaceZero in PDCCH-ConfigCommon
srslte_search_space_type_common_0A, ///< configured by searchSpaceOtherSystemInformation in PDCCH-ConfigCommon
srslte_search_space_type_common_1, ///< configured by ra-SearchSpace in PDCCH-ConfigCommon
srslte_search_space_type_common_2, ///< configured by pagingSearchSpace in PDCCH-ConfigCommon
srslte_search_space_type_common_3, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = common
srslte_search_space_type_ue, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = ue-Specific
srslte_search_space_type_rar, ///< Indicates that a grant was given by MAC RAR as described in TS 38.213 clause 8.2
srslte_search_space_type_cg ///< Indicates that a grant was given by Configured Grant from the upper layers
} srslte_search_space_type_t;
/**
* @brief Helper macro to get if a search space type is common or not
*/
#define SRSLTE_SEARCH_SPACE_IS_COMMON(SS_TYPE) ((SS_TYPE) < srslte_search_space_type_ue)
/**
* @brief RAR content length in bits (see TS 38.321 Sec 6.2.3)
*/
#define SRSLTE_RAR_UL_GRANT_NBITS (27)
/**
* @brief Indicates the MCS table the UE shall use for PDSCH and/or PUSCH without transform precoding
*/
@ -160,16 +183,17 @@ typedef enum SRSLTE_API {
/**
* @brief RNTI types
* @remark Usage described in TS 38.321 Table 7.1-2: RNTI usage.
*/
typedef enum SRSLTE_API {
srslte_rnti_type_c = 0,
srslte_rnti_type_p,
srslte_rnti_type_si,
srslte_rnti_type_ra,
srslte_rnti_type_tc,
srslte_rnti_type_cs,
srslte_rnti_type_sp_csi,
srslte_rnti_type_mcs_crnti,
srslte_rnti_type_p, ///< @brief Paging and System Information change notification (PCH)
srslte_rnti_type_si, ///< @brief Broadcast of System Information (DL-SCH)
srslte_rnti_type_ra, ///< @brief Random Access Response (DL-SCH)
srslte_rnti_type_tc, ///< @brief Contention Resolution (when no valid C-RNTI is available) (DL-SCH)
srslte_rnti_type_cs, ///< @brief Configured scheduled unicast transmission (DL-SCH, UL-SCH)
srslte_rnti_type_sp_csi, ///< @brief Activation of Semi-persistent CSI reporting on PUSCH
srslte_rnti_type_mcs_c, ///< @brief Dynamically scheduled unicast transmission (DL-SCH)
} srslte_rnti_type_t;
/**
@ -202,6 +226,15 @@ typedef enum SRSLTE_API {
srslte_xoverhead_18
} srslte_xoverhead_t;
/**
* @brief PDSCH HARQ ACK codebook configuration
* @remark Described in TS 38.331 V15.10.0 PhysicalCellGroupConfig
*/
typedef enum SRSLTE_API {
srslte_pdsch_harq_ack_codebook_none = 0,
srslte_pdsch_harq_ack_codebook_semi_static,
srslte_pdsch_harq_ack_codebook_dynamic,
} srslte_pdsch_harq_ack_codebook_t;
/**
* @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP)
*/
@ -225,7 +258,7 @@ typedef struct SRSLTE_API {
/// Left for future parameters
/// ...
} srslte_dl_slot_cfg_t;
} srslte_slot_cfg_t;
/**
* @brief Min number of OFDM symbols in a control resource set.
@ -251,8 +284,9 @@ typedef struct SRSLTE_API {
* @brief CORESET parameters as defined in TS 38.331 V15.10.0 - ControlResourceSet
*/
typedef struct SRSLTE_API {
srslte_coreset_mapping_type_t mapping_type;
uint32_t id;
uint32_t coreset_id;
srslte_coreset_mapping_type_t mapping_type;
uint32_t duration;
bool freq_resources[SRSLTE_CORESET_FREQ_DOMAIN_RES_SIZE];
srslte_coreset_bundle_size_t interleaver_size;
@ -270,11 +304,19 @@ typedef struct SRSLTE_API {
*/
typedef struct SRSLTE_API {
uint32_t id;
uint32_t coreset_id;
uint32_t duration; // in slots
srslte_search_space_type_t type;
uint32_t nof_candidates[SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR];
} srslte_search_space_t;
/**
* @brief Get the RNTI type name for NR
* @param rnti_type RNTI type name
* @return Constant string with the RNTI type name
*/
SRSLTE_API const char* srslte_rnti_type_str(srslte_rnti_type_t rnti_type);
/**
* @brief Calculates the bandwidth of a given CORESET in physical resource blocks (PRB) . This function uses the
* frequency domain resources bit-map for counting the number of PRB.
@ -320,6 +362,25 @@ SRSLTE_API const char* srslte_mcs_table_to_str(srslte_mcs_table_t mcs_table);
*/
SRSLTE_API srslte_mcs_table_t srslte_mcs_table_from_str(const char* str);
/**
* @brief Computes the minimum valid symbol size for a given amount of PRB
* @attention The valid FFT sizes are radix 2 and radix 3 between 128 to 4096 points.
* @param nof_prb Number of PRB
* @return The minimum valid FFT size if the number of PRB is in range, 0 otherwise
*/
SRSLTE_API uint32_t srslte_min_symbol_sz_rb(uint32_t nof_prb);
/**
* @brief Computes the time in seconds between two symbols in a slot
* @note l0 is expected to be smaller than l1
* @remark All symbol size reference and values are taken from TS 38.211 section 5.3 OFDM baseband signal generation
* @param l0 First symbol index within the slot
* @param l1 Second symbol index within the slot
* @param numerology NR Carrier numerology
* @return Returns the time in seconds between the two symbols if the condition above is satisfied, 0 seconds otherwise
*/
SRSLTE_API float srslte_symbol_distance_s(uint32_t l0, uint32_t l1, uint32_t numerology);
#ifdef __cplusplus
}
#endif

@ -34,7 +34,7 @@
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#define SRSLTE_SEQUENCE_MOD(X) ((X) & (uint32_t)INT32_MAX)
#define SRSLTE_SEQUENCE_MOD(X) ((uint32_t)((X) & (uint64_t)INT32_MAX))
typedef struct SRSLTE_API {
uint32_t x1;

@ -85,8 +85,28 @@ typedef struct SRSLTE_API {
cf_t* window_offset_buffer;
} srslte_ofdm_t;
/**
* @brief Initialises or reconfigures OFDM receiver
*
* @note The reconfiguration of the OFDM object considers only CP, number of PRB and optionally the FFT size
* @attention The OFDM object must be zeroed externally prior calling the initialization for first time
*
* @param q OFDM object
* @param cfg OFDM configuration
* @return SRSLTE_SUCCESS if the initialization/reconfiguration is successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ofdm_rx_init_cfg(srslte_ofdm_t* q, srslte_ofdm_cfg_t* cfg);
/**
* @brief Initialises or reconfigures OFDM transmitter
*
* @note The reconfiguration of the OFDM object considers only CP, number of PRB and optionally the FFT size
* @attention The OFDM object must be zeroed externally prior calling the initialization for first time
*
* @param q OFDM object
* @param cfg OFDM configuration
* @return SRSLTE_SUCCESS if the initialization/reconfiguration is successful, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ofdm_tx_init_cfg(srslte_ofdm_t* q, srslte_ofdm_cfg_t* cfg);
SRSLTE_API int

@ -62,17 +62,15 @@ SRSLTE_API int srslte_enb_dl_nr_base_zero(srslte_enb_dl_nr_t* q);
SRSLTE_API void srslte_enb_dl_nr_gen_signal(srslte_enb_dl_nr_t* q);
SRSLTE_API int srslte_enb_dl_nr_pdcch_put(srslte_enb_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_dci_dl_nr_t* dci_dl);
SRSLTE_API int
srslte_enb_dl_nr_pdcch_put(srslte_enb_dl_nr_t* q, const srslte_slot_cfg_t* slot_cfg, const srslte_dci_dl_nr_t* dci_dl);
SRSLTE_API int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_sch_cfg_nr_t* cfg,
uint8_t* data[SRSLTE_MAX_TB]);
SRSLTE_API int
srslte_enb_dl_nr_pdsch_info(const srslte_enb_dl_nr_t* q, const srslte_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);
#endif // SRSLTE_ENB_DL_NR_H

@ -45,6 +45,9 @@ typedef enum {
SRSLTE_LDPC_DECODER_C_AVX2, /*!< \brief %Decoder working with 8-bit integer-valued LLRs (AVX2 version). */
SRSLTE_LDPC_DECODER_C_AVX2_FLOOD, /*!< \brief %Decoder working with 8-bit integer-valued LLRs, flooded scheduling
(AVX2 version). */
SRSLTE_LDPC_DECODER_C_AVX512, /*!< \brief %Decoder working with 8-bit integer-valued LLRs (AVX512 version). */
SRSLTE_LDPC_DECODER_C_AVX512_FLOOD, /*!< \brief %Decoder working with 8-bit integer-valued LLRs, flooded scheduling
(AVX512 version). */
} srslte_ldpc_decoder_type_t;
/*!

@ -22,7 +22,7 @@
/*!
* \file ldpc_encoder.h
* \brief Declaration of the LDPC encoder.
* \author David Gregoratti
* \author David Gregoratti and Jesus Gomez
* \date 2020
*
* \copyright Software Radio Systems Limited
@ -42,6 +42,9 @@ typedef enum SRSLTE_API {
#if LV_HAVE_AVX2
SRSLTE_LDPC_ENCODER_AVX2, /*!< \brief SIMD-optimized encoder. */
#endif // LV_HAVE_AVX2
#if LV_HAVE_AVX512
SRSLTE_LDPC_ENCODER_AVX512, /*!< \brief SIMD-optimized encoder. */
#endif // LV_HAVE_AVX512
} srslte_ldpc_encoder_type_t;
/*!
@ -65,6 +68,8 @@ typedef struct SRSLTE_API {
void (*encode_high_rate)(void*, uint8_t*);
/*! \brief Pointer to the encoder for the high-rate region (SIMD-optimized version). */
void (*encode_high_rate_avx2)(void*);
/*! \brief Pointer to the encoder for the high-rate region (SIMD-AVX512-optimized version). */
void (*encode_high_rate_avx512)(void*);
} srslte_ldpc_encoder_t;

@ -360,7 +360,7 @@ static inline const uint16_t* get_mother_code(uint8_t n)
return mother_code_10;
break;
default:
ERROR("Wrong code_size_log\n");
ERROR("Wrong code_size_log");
return NULL;
}
}
@ -390,7 +390,7 @@ static inline const uint16_t* get_blk_interleaver(uint8_t n)
return blk_interleaver_10;
break;
default:
ERROR("Wrong code_size_log (%d)\n", n);
ERROR("Wrong code_size_log (%d)", n);
return NULL;
}
}

@ -139,7 +139,7 @@ void MAKE_CALL(run_tdec_iteration)(srslte_tdec_t* h, llr_t* input)
h->n_iter++;
} else {
ERROR("Error CB index not set (call srslte_tdec_new_cb() first\n");
ERROR("Error CB index not set (call srslte_tdec_new_cb() first");
}
}

@ -183,7 +183,7 @@ static inline void srslte_evm_buffer_resize(srslte_evm_buffer_t* q, uint32_t new
\
/* Return NAN if EVM buffers, modem table, LLR, symbols or bits missing*/ \
if (!q || !modem_table || !modem_table->nbits_x_symbol || !llr || !symbols || !nof_bits) { \
ERROR("Invalid inputs %p %p %p %p %d\n", q, modem_table, llr, symbols, nof_bits); \
ERROR("Invalid inputs %p %p %p %p %d", q, modem_table, llr, symbols, nof_bits); \
return evm_rms; \
} \
\

@ -29,6 +29,7 @@
typedef struct SRSLTE_API {
srslte_dci_location_t location;
srslte_search_space_type_t search_space;
uint32_t coreset_id;
uint8_t payload[50];
srslte_rnti_type_t rnti_type;
uint32_t nof_bits;
@ -41,7 +42,8 @@ typedef struct SRSLTE_API {
srslte_rnti_type_t rnti_type;
srslte_dci_format_nr_t format;
srslte_dci_location_t location;
srslte_search_space_t search_space;
srslte_search_space_type_t search_space;
uint32_t coreset_id;
// Common fields
uint32_t freq_domain_assigment; ///< Frequency domain resource assignment
@ -69,12 +71,74 @@ typedef struct SRSLTE_API {
} srslte_dci_dl_nr_t;
typedef struct SRSLTE_API {
// Context information
uint16_t rnti;
srslte_rnti_type_t rnti_type;
srslte_dci_format_nr_t format;
srslte_dci_location_t location;
srslte_search_space_type_t search_space;
uint32_t coreset_id;
// Common fields
uint32_t freq_domain_assigment; ///< Frequency domain resource assignment
uint32_t time_domain_assigment; ///< Time domain resource assignment
uint32_t freq_hopping_flag; ///< Frequency hopping flag
uint32_t mcs; ///< Modulation and coding scheme
uint32_t rv; ///< Redundancy version
uint32_t reserved; ///< Reserved bits
// C-RNTI or CS-RNTI or MCS-C-RNTI
uint32_t ndi; ///< New data indicator
uint32_t pid; ///< HARQ process number
uint32_t tpc; ///< TPC command for scheduled PUCCH
uint32_t pucch_resource; ///< PUCCH resource indicator
uint32_t harq_feedback; ///< PDSCH-to-HARQ_feedback timing indicator
// Frequency hopping
uint32_t frequency_offset; ///< frequency offset
// Random Access Response Grant
uint32_t csi_request;
} srslte_dci_ul_nr_t;
/**
* @brief Indicates whether the provided DCI message format bit indicator belongs to DCI format 1_0 according according
* to the RNTI type. If invalid, the DCI message is likely to be format 0_0
* @param dci_msg Provides DCI format 1_0 message
* @return true if the DCI message is format 1_0, false otherwise
*/
SRSLTE_API bool srslte_dci_nr_format_1_0_valid(const srslte_dci_msg_nr_t* dci_msg);
SRSLTE_API int srslte_dci_nr_pack(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
const srslte_dci_dl_nr_t* dci,
srslte_dci_msg_nr_t* msg);
SRSLTE_API SRSLTE_API int srslte_dci_nr_format_1_0_sizeof(const srslte_carrier_nr_t* carrier,
SRSLTE_API int srslte_dci_nr_format_0_0_sizeof(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_rnti_type_t rnti_type);
SRSLTE_API int srslte_dci_nr_format_0_0_pack(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset0,
const srslte_dci_ul_nr_t* dci,
srslte_dci_msg_nr_t* msg);
SRSLTE_API int srslte_dci_nr_format_0_0_unpack(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_dci_msg_nr_t* msg,
srslte_dci_ul_nr_t* dci);
/**
* @brief Unpacks DCI from Random Access Response Grant
* @remark Described in TS 38.213 Table 8.2-1: Random Access Response Grant Content field size
* @param msg
* @param dci
* @return SRSLTE_SUCCESS if unpacked correctly, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_dci_nr_rar_unpack(srslte_dci_msg_nr_t* msg, srslte_dci_ul_nr_t* dci);
SRSLTE_API int srslte_dci_nr_format_1_0_sizeof(const srslte_carrier_nr_t* carrier,
const srslte_coreset_t* coreset,
srslte_rnti_type_t rnti_type);
@ -88,4 +152,8 @@ SRSLTE_API int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrie
srslte_dci_msg_nr_t* msg,
srslte_dci_dl_nr_t* dci);
SRSLTE_API int srslte_dci_ul_nr_to_str(const srslte_dci_ul_nr_t* dci, char* str, uint32_t str_len);
SRSLTE_API int srslte_dci_dl_nr_to_str(const srslte_dci_dl_nr_t* dci, char* str, uint32_t str_len);
#endif // SRSLTE_DCI_NR_H

@ -113,6 +113,14 @@ SRSLTE_API int srslte_pdcch_nr_init_rx(srslte_pdcch_nr_t* q, const srslte_pdcch_
SRSLTE_API void srslte_pdcch_nr_free(srslte_pdcch_nr_t* q);
/**
* @brief Sets carrier and CORESET configuration for a given PDCCH object
* @note This function shall not allocate, free memory or perform any heavy computations
* @param[in,out] q PDCCH encoder/decoder object
* @param[in] carrier New carrier configuration
* @param[in] coreset New CORESET configuration
* @return SRSLTE_SUCCESS if the configurations are valid, otherwise it returns an SRSLTE_ERROR code
*/
SRSLTE_API int
srslte_pdcch_nr_set_carrier(srslte_pdcch_nr_t* q, const srslte_carrier_nr_t* carrier, const srslte_coreset_t* coreset);

@ -68,7 +68,7 @@ typedef enum {
} srslte_dmrs_sch_add_pos_t;
/**
* @brief Provides PDSCH DMRS configuration from higher layers
* @brief Provides PDSCH DMRS configuration
* @remark Parameters described in TS 38.331 V15.10.0
*/
typedef struct {
@ -91,21 +91,23 @@ typedef struct {
} srslte_dmrs_sch_cfg_t;
/**
* @brief flatten PDSCH time domain allocation parameters
* @brief Common flatten PDSCH and PUSCH time domain allocation parameters
* @remark Described in TS 38.331 V15.10.0 Section PDSCH-TimeDomainResourceAllocationList
* @remark Described in TS 38.331 V15.10.0 Section PUSCH-TimeDomainResourceAllocationList
*/
typedef struct SRSLTE_API {
/// Slot offset between DCI and its scheduled PDSCH
uint32_t k0;
/// For PDSCH Slot offset between DCI and its scheduled PDSCH
/// For PUSCH parameter K2
uint32_t k;
/// PDSCH mapping type
/// SCH mapping type
srslte_sch_mapping_type_t mapping_type;
/// An index giving valid combinations of start symbol and length (jointly encoded) as start and length indicator
/// (SLIV). The network configures the field so that the allocation does not cross the slot boundary
uint32_t sliv;
} srslte_pdsch_time_ra_t;
} srslte_sch_time_ra_t;
/**
* @brief PDSCH grant information provided by the Downlink Control Information (DCI)
@ -116,8 +118,7 @@ typedef struct SRSLTE_API {
srslte_rnti_type_t rnti_type;
/// Time domain resources
uint32_t k0; // PDSCH only
uint32_t k2; // PUSCH only
uint32_t k; // k0 for PDSCH, k2 for PUSCH
uint32_t S;
uint32_t L;
srslte_sch_mapping_type_t mapping;
@ -130,6 +131,10 @@ typedef struct SRSLTE_API {
/// Described in TS 38.214 Section 5.1.6.2
uint32_t nof_dmrs_cdm_groups_without_data;
/// Linear DMRS power offset. Zero means unset and it is equivalent to one.
/// For PUSCH, see TS 38.214 Table 6.2.2-1 for more information
float beta_dmrs;
/// Spatial resources
uint32_t nof_layers;
@ -153,21 +158,57 @@ typedef struct SRSLTE_API {
* @remark Described in TS 38.331 V15.10.0 Section PUSCH-Config
*/
typedef struct SRSLTE_API {
// Serving cell parameters
uint32_t scs_cfg; // Subcarrier spacing configuration
srslte_dmrs_sch_typeA_pos_t typeA_pos;
bool scrambling_id_present;
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)
srslte_dmrs_sch_cfg_t dmrs_typeA;
srslte_dmrs_sch_cfg_t dmrs_typeB;
srslte_sch_grant_nr_t grant;
struct {
srslte_dmrs_sch_type_t type;
srslte_dmrs_sch_add_pos_t additional_pos;
srslte_dmrs_sch_len_t length;
bool scrambling_id0_present;
uint32_t scrambling_id0;
bool scrambling_id1_present;
uint32_t scrambling_id1;
bool present;
} dmrs_typeA;
bool pdsch_time_is_default; ///< Set to true if pdsch_time_ra contains the configuration from pdsch-ConfigCommon or
///< pdsch-Config
srslte_pdsch_time_ra_t pdsch_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
struct {
srslte_dmrs_sch_type_t type;
srslte_dmrs_sch_add_pos_t additional_pos;
srslte_dmrs_sch_len_t length;
bool scrambling_id0_present;
uint32_t scrambling_id0;
bool scrambling_id1_present;
uint32_t scrambling_id1;
bool present;
} dmrs_typeB;
srslte_sch_time_ra_t common_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_common_time_ra;
srslte_sch_time_ra_t dedicated_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION];
uint32_t nof_dedicated_time_ra;
bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2)
srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters
} srslte_sch_hl_cfg_nr_t;
/**
* @brief Common NR-SCH (PDSCH and PUSCH for NR) configuration
*/
typedef struct SRSLTE_API {
bool scrambling_id_present;
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)
srslte_dmrs_sch_cfg_t dmrs;
srslte_sch_grant_nr_t grant;
srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters
/// Uplink params
bool enable_transform_precoder;

@ -40,6 +40,12 @@
#define SRSLTE_PRACH_MAX_LEN (2 * 24576 + 21024) // Maximum Tcp + Tseq
// Long PRACH ZC sequence sequence length
#define SRSLTE_PRACH_N_ZC_LONG 839
// Short PRACH ZC sequence sequence length
#define SRSLTE_PRACH_N_ZC_SHORT 139
/** Generation and detection of RACH signals for uplink.
* Currently only supports preamble formats 0-3.
* Does not currently support high speed flag.
@ -49,7 +55,7 @@
typedef struct {
int idx;
float factor;
cf_t phase_array[2 * 839];
cf_t phase_array[2 * SRSLTE_PRACH_N_ZC_LONG];
} srslte_prach_cancellation_t;
typedef struct SRSLTE_API {
@ -74,8 +80,8 @@ typedef struct SRSLTE_API {
uint32_t N_cp; // Cyclic prefix length
// Generated tables
cf_t seqs[64][839]; // Our set of 64 preamble sequences
cf_t dft_seqs[64][839]; // DFT-precoded seqs
cf_t seqs[64][SRSLTE_PRACH_N_ZC_LONG]; // Our set of 64 preamble sequences
cf_t dft_seqs[64][SRSLTE_PRACH_N_ZC_LONG]; // DFT-precoded seqs
uint64_t dft_gen_bitmap; // Bitmap where each bit Indicates if the dft has been generated for sequence i.
uint32_t root_seqs_idx[64]; // Indices of root seqs in seqs table
uint32_t N_roots; // Number of root sequences used in this configuration

@ -76,6 +76,16 @@
*/
#define SRSLTE_PUCCH_NR_MAX_CODE_RATE 7
/**
* Maximum number of NR-PUCCH resources per set (TS 38.331 maxNrofPUCCH-ResourcesPerSet)
*/
#define SRSLTE_PUCCH_NR_MAX_NOF_RESOURCES_PER_SET 32
/**
* Maximum number NR-PUCCH resource sets (TS 38.331 maxNrofPUCCH-ResourceSets)
*/
#define SRSLTE_PUCCH_NR_MAX_NOF_SETS 4
typedef enum SRSLTE_API {
SRSLTE_PUCCH_NR_FORMAT_0 = 0,
SRSLTE_PUCCH_NR_FORMAT_1,
@ -135,6 +145,18 @@ typedef struct SRSLTE_API {
bool additional_dmrs; ///< UE enables 2 DMRS symbols per hop of a PUCCH Format 3 or 4
} srslte_pucch_nr_resource_t;
typedef struct SRSLTE_API {
srslte_pucch_nr_resource_t resources[SRSLTE_PUCCH_NR_MAX_NOF_RESOURCES_PER_SET];
uint32_t nof_resources; ///< Set to 0 if it is NOT provided by higher layers
uint32_t max_payload_size; ///< Maximum payload size, set to 0 if not present
} srslte_pucch_nr_resource_set_t;
typedef struct SRSLTE_API {
srslte_pucch_nr_common_cfg_t common; ///< NR-PUCCH configuration common for all formats and resources
srslte_pucch_nr_resource_set_t sets[SRSLTE_PUCCH_NR_MAX_NOF_SETS]; ///< Resource sets, indexed by pucch-ResourceSetId
bool enabled; ///< Set to true if any set is enabled
} srslte_pucch_nr_hl_cfg_t;
/**
* @brief Validates an NR-PUCCH resource configuration provided by upper layers
* @param resource Resource configuration to validate

@ -102,7 +102,7 @@ SRSLTE_API int srslte_pucch_nr_group_sequence(const srslte_carrier_nr_t*
*/
SRSLTE_API int srslte_pucch_nr_alpha_idx(const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
uint32_t l,
uint32_t l_prime,
uint32_t m0,
@ -124,7 +124,7 @@ SRSLTE_API int srslte_pucch_nr_alpha_idx(const srslte_carrier_nr_t* car
SRSLTE_API int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
srslte_pucch_nr_resource_t* resource,
uint32_t m_cs,
cf_t* slot_symbols);
@ -144,7 +144,7 @@ SRSLTE_API int srslte_pucch_nr_format0_encode(const srslte_pucch_nr_t*
SRSLTE_API int srslte_pucch_nr_format0_measure(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
srslte_pucch_nr_resource_t* resource,
uint32_t m_cs,
const cf_t* slot_symbols,
@ -177,7 +177,7 @@ SRSLTE_API cf_t srslte_pucch_nr_format1_w(const srslte_pucch_nr_t* q, uint32_t n
SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
uint8_t* b,
uint32_t nof_bits,
@ -199,7 +199,7 @@ SRSLTE_API int srslte_pucch_nr_format1_encode(const srslte_pucch_nr_t*
SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
srslte_chest_ul_res_t* chest_res,
cf_t* slot_symbols,
@ -221,7 +221,7 @@ SRSLTE_API int srslte_pucch_nr_format1_decode(srslte_pucch_nr_t*
SRSLTE_API int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
const srslte_uci_cfg_nr_t* uci_cfg,
const srslte_uci_value_nr_t* uci_value,
@ -243,11 +243,16 @@ SRSLTE_API int srslte_pucch_nr_format_2_3_4_encode(srslte_pucch_nr_t*
SRSLTE_API int srslte_pucch_nr_format_2_3_4_decode(srslte_pucch_nr_t* q,
const srslte_carrier_nr_t* carrier,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_pucch_nr_resource_t* resource,
const srslte_uci_cfg_nr_t* uci_cfg,
srslte_chest_ul_res_t* chest_res,
cf_t* slot_symbols,
srslte_uci_value_nr_t* uci_value);
SRSLTE_API uint32_t srslte_pucch_nr_tx_info(const srslte_pucch_nr_resource_t* resource,
const srslte_uci_data_nr_t* uci_data,
char* str,
uint32_t str_len);
#endif // SRSLTE_PUCCH_NR_H

@ -67,7 +67,7 @@ typedef struct {
float evm;
} srslte_pusch_res_nr_t;
SRSLTE_API int srslte_pusch_nr_init_enb(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args);
SRSLTE_API int srslte_pusch_nr_init_gnb(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args);
SRSLTE_API int srslte_pusch_nr_init_ue(srslte_pusch_nr_t* q, const srslte_pusch_nr_args_t* args);

@ -42,16 +42,18 @@
* @remark Defined by TS 38.214 V15.10.0 section 5.1.2.1.1 Determination of the resource allocation table to be used for
* PDSCH
*
* @param pdsch_cfg Flattened PDSCH configuration provided from higher layers
* @param cfg Flattened PDSCH configuration provided from higher layers
* @param rnti_type Type of the RNTI of the corresponding DCI
* @param ss_type Type of the SS for PDCCH
* @param coreset_id CORESET identifier associated with the PDCCH transmission
* @param m Time domain resource assignment field value m provided in DCI
* @param[out] Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_dl_nr_time(const srslte_sch_cfg_nr_t* pdsch_cfg,
SRSLTE_API int srslte_ra_dl_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant);
@ -74,11 +76,11 @@ srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_type
*
* @remark Defined by TS 38.214 V15.10.0 5.1.6.1.3 CSI-RS for mobility
*
* @param pdsch_cfg PDSCH NR configuration by upper layers
* @param cfg PDSCH-DMRS NR configuration by upper layers
* @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_sch_cfg_nr_t* pdsch_cfg,
SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_dmrs_sch_cfg_t* cfg,
srslte_sch_grant_nr_t* grant);
/**
@ -89,12 +91,11 @@ SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const
* @param cfg PDSCH NR configuration by upper layers
* @param dci_dl Unpacked DCI used to schedule the PDSCH grant
* @param[out] grant Provides grant pointer to fill
* @return
* @return SRSLTE_SUCCESS if the provided data is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* cfg,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_grant_nr_t* grant);
#endif // SRSLTE_RA_DL_NR_H

@ -105,8 +105,29 @@ SRSLTE_API int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg,
* @return 0 on success, -1 on error
*/
SRSLTE_API int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_sch_cfg_nr_t* pdsch_cfg,
const srslte_sch_hl_cfg_nr_t* pdsch_cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* pdsch_grant);
/**
* @brief Converts an unpacked UL DCI message to a PUSCH grant structure.
* Implements the procedures defined in Section 6 of 38.214 to compute the resource allocation (6.1.2)
* and modulation order, target rate, redundancy version and TBS (6.1.4)
*
* Note: Only TypeA PUSCH mapping type is supported
*
* @param carrier Carrier information struct
* @param pusch_hl_cfg PUSCH configuration provided by higher layers
* @param dci_ul DCI uplink (format 0_0 or 0_1)
* @param pusch_cfg PUSCH configuration after applying the procedure
* @param pusch_grant Generated PUSCH grant
* @return 0 on success, -1 on error
*/
SRSLTE_API int srslte_ra_ul_dci_to_grant_nr(const srslte_carrier_nr_t* carrier,
const srslte_sch_hl_cfg_nr_t* pusch_hl_cfg,
const srslte_dci_ul_nr_t* dci_ul,
srslte_sch_cfg_nr_t* pusch_cfg,
srslte_sch_grant_nr_t* pusch_grant);
#endif // SRSLTE_RA_NR_H

@ -22,10 +22,69 @@
#ifndef SRSLTE_RA_UL_NR_H
#define SRSLTE_RA_UL_NR_H
#include "dci_nr.h"
#include "srslte/config.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#include "srslte/phy/phch/pucch_cfg_nr.h"
#include "uci_cfg_nr.h"
/**
* @brief Calculates the PUSCH time resource allocation and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 section 6.1.2.1.1 Determination of the resource allocation table to be used for
* PUSCH
*
* @param cfg Flattened PUSCH configuration provided from higher layers
* @param rnti_type Type of the RNTI of the corresponding DCI
* @param ss_type Type of the SS for PDCCH
* @param coreset_id CORESET identifier associated with the PDCCH transmission
* @param m Time domain resource assignment field value m provided in DCI
* @param[out] Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_ul_nr_time(const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_rnti_type_t rnti_type,
const srslte_search_space_type_t ss_type,
const uint32_t coreset_id,
const uint8_t m,
srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the PUSCH time resource default A and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 Table 6.1.2.1.1-2: Default PUSCH time domain resource allocation A for normal
* CP
*
* @param scs_cfg Sub-carrier spacing configuration for PUSCH (μ)
* @param m Time domain resource assignment field value m of the DCI
* @param[out] grant PUSCH grant
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int
srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0
*
* @remark Defined by TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure
*
* @param cfg PUSCH NR configuration by upper layers
* @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the ratio of PUSCH EPRE to DM-RS EPRE
*
* @remark Defined by TS 38.214 V15.10.0 Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE
*
* @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ra_ul_nr_dmrs_power_offset(srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the minimum number of PRB required for transmitting NR-PUCCH Format 2, 3 or 4
* @remark Based in TS 38.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR in a PUCCH
@ -34,4 +93,30 @@
SRSLTE_API int srslte_ra_ul_nr_pucch_format_2_3_min_prb(const srslte_pucch_nr_resource_t* resource,
const srslte_uci_cfg_nr_t* uci_cfg);
/**
* @brief Calculates the PUSCH frequency resource allocation and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 section 5.1.2.2
* @param carrier Carrier information
* @param cfg PDSCH NR configuration by upper layers
* @param dci_dl Unpacked DCI used to schedule the PDSCH grant
* @param[out] grant Provides grant pointer to fill
* @return SRSLTE_SUCCESS if the provided data is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ra_ul_nr_freq(const srslte_carrier_nr_t* carrier,
const srslte_sch_hl_cfg_nr_t* cfg,
const srslte_dci_ul_nr_t* dci_ul,
srslte_sch_grant_nr_t* grant);
/**
* @brief Selects a valid PUCCH resource for transmission
* @param pucch_cfg PUCCH configuration from upper layers
* @param uci_cfg Uplink Control information configuration (and PDCCH context)
* @param[out] resource Selected resource for transmitting PUCCH
* @return SRSLTE_SUCCESS if provided configuration is valid, SRSLTE_ERROR code otherwise
*/
SRSLTE_API int srslte_ra_ul_nr_pucch_resource(const srslte_pucch_nr_hl_cfg_t* pucch_cfg,
const srslte_uci_cfg_nr_t* uci_cfg,
srslte_pucch_nr_resource_t* resource);
#endif // SRSLTE_RA_UL_NR_H

@ -26,6 +26,12 @@
#include <stdbool.h>
#include <stdint.h>
/**
* @brief Maximum number of Uplink Control Bits
* @remark TS 38.212 section 5.2.1 Polar coding: The value of A is no larger than 1706.
*/
#define SRSLTE_UCI_NR_MAX_NOF_BITS 1706U
/**
* @brief Maximum number of HARQ ACK feedback bits that can be carried in Uplink Control Information (UCI) message
*/
@ -52,12 +58,20 @@
* @brief Uplink Control Information (UCI) message configuration
*/
typedef struct SRSLTE_API {
/// Common Parameters
uint32_t o_ack; ///< Number of HARQ-ACK bits
uint32_t o_sr; ///< Number of SR bits
uint32_t o_csi1; ///< Number of CSI1 report number of bits
uint32_t o_csi2; ///< Number of CSI2 report number of bits
srslte_mod_t modulation; ///< Modulation (PUSCH only)
/// PUSCH only parameters
srslte_mod_t modulation; ///< Modulation
/// PUCCH only parameters
uint16_t rnti; ///< RNTI
uint32_t pucch_resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or DCI format 1_1
} srslte_uci_cfg_nr_t;
/**
@ -71,4 +85,12 @@ typedef struct SRSLTE_API {
bool valid; ///< Indicates whether the message has been decoded successfully, ignored in the transmitter
} srslte_uci_value_nr_t;
/**
* @brief Uplink Control Information (UCI) data (configuration + values)
*/
typedef struct SRSLTE_API {
srslte_uci_cfg_nr_t cfg;
srslte_uci_value_nr_t value;
} srslte_uci_data_nr_t;
#endif // SRSLTE_UCI_CFG_NR_H

@ -123,4 +123,20 @@ SRSLTE_API int srslte_uci_nr_decode_pucch(srslte_uci_nr_t* q,
int8_t* llr,
srslte_uci_value_nr_t* value);
/**
* @brief Calculates the total number of UCI bits
* @param uci_cfg UCI configuration
* @return The number of total bits carrying HARQ ACK, CSI reports and SR bits
*/
SRSLTE_API uint32_t srslte_uci_nr_total_bits(const srslte_uci_cfg_nr_t* uci_cfg);
/**
* @brief Converts to string an UCI data structure
* @param uci_data UCO data structure
* @param str Destination string
* @param str_len String length
* @return Resultant string length
*/
SRSLTE_API uint32_t srslte_uci_nr_info(const srslte_uci_data_nr_t* uci_data, char* str, uint32_t str_len);
#endif // SRSLTE_UCI_NR_H

@ -28,6 +28,24 @@
#include "srslte/phy/phch/dci_nr.h"
#include "srslte/phy/phch/pdcch_nr.h"
#include "srslte/phy/phch/pdsch_nr.h"
#include "srslte/phy/phch/uci_cfg_nr.h"
/**
* Maximum number of CORESET
* @remark Defined in TS 38.331 by maxNrofControlResourceSets-1
*/
#define SRSLTE_UE_DL_NR_MAX_NOF_CORESET 12
/**
* Maximum number of Search spaces
* @remark Defined in TS 38.331 by maxNrofSearchSpaces-1
*/
#define SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE 40
/**
* Maximum number of DCI messages to receive
*/
#define SRSLTE_MAX_DCI_MSG_NR 4
typedef struct SRSLTE_API {
srslte_pdsch_nr_args_t pdsch;
@ -35,8 +53,64 @@ typedef struct SRSLTE_API {
uint32_t nof_rx_antennas;
uint32_t nof_max_prb;
float pdcch_dmrs_corr_thr;
float pdcch_dmrs_epre_thr;
} srslte_ue_dl_nr_args_t;
typedef struct SRSLTE_API {
srslte_coreset_t coreset[SRSLTE_UE_DL_NR_MAX_NOF_CORESET]; ///< PDCCH Control resource sets (CORESET) collection
bool coreset_present[SRSLTE_UE_DL_NR_MAX_NOF_CORESET]; ///< CORESET present flags
srslte_search_space_t search_space[SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
bool search_space_present[SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
uint16_t ra_rnti; ///< Needs to be deduced from the PRACH configuration
srslte_search_space_t ra_search_space;
bool ra_search_space_present;
} srslte_ue_dl_nr_pdcch_cfg_t;
typedef struct {
uint32_t scell_idx; ///< Serving cell index
uint32_t v_dai_dl; ///< Downlink Assigment Index
bool dci_format_1_1; ///< Set to true if the PDSCH transmission is triggered by a PDCCH DCI format 1_1 transmission
uint32_t k1; ///< HARQ feedback timing
uint16_t rnti;
uint32_t pucch_resource_id;
} srslte_pdsch_ack_resource_nr_t;
typedef struct {
srslte_pdsch_ack_resource_nr_t resource;
uint8_t value[SRSLTE_MAX_CODEWORDS]; // 0/1 or 2 for DTX
bool present; // set to true if there is a PDSCH on serving cell c associated with PDCCH in PDCCH monitoring occasion
// m, or there is a PDCCH indicating SPS PDSCH release on serving cell c
bool dl_bwp_changed; // set to true if PDCCH monitoring occasion m is before an active DL BWP change on serving cell c
bool ul_bwp_changed; // set to true if an active UL BWP change on the PCell and an active DL BWP change is not
// triggered by a DCI format 1_1 in PDCCH monitoring occasion m
bool second_tb_present; // set to true if two TB were detected in the PDCCH monitoring occasion m
} srslte_pdsch_ack_m_nr_t;
#define SRSLTE_UCI_NR_MAX_M 10
typedef struct {
uint32_t M;
srslte_pdsch_ack_m_nr_t m[SRSLTE_UCI_NR_MAX_M];
} srslte_pdsch_ack_cc_nr_t;
typedef struct {
srslte_pdsch_ack_cc_nr_t cc[SRSLTE_MAX_CARRIERS];
uint32_t nof_cc;
bool use_pusch; // Set to true, if UCI bits are carried by PUSCH
} srslte_pdsch_ack_nr_t;
typedef struct SRSLTE_API {
bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided
bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided
srslte_pdsch_harq_ack_codebook_t pdsch_harq_ack_codebook; ///< pdsch-HARQ-ACK-Codebook configuration
bool max_cw_sched_dci_is_2; ///< Param maxNrofCodeWordsScheduledByDCI, set to true if present and equal to 2
uint32_t dl_data_to_ul_ack[SRSLTE_MAX_NOF_DL_DATA_TO_UL];
uint32_t nof_dl_data_to_ul_ack;
} srslte_ue_dl_nr_harq_ack_cfg_t;
typedef struct SRSLTE_API {
uint32_t max_prb;
uint32_t nof_rx_antennas;
@ -44,7 +118,7 @@ typedef struct SRSLTE_API {
float pdcch_dmrs_epre_thr;
srslte_carrier_nr_t carrier;
srslte_coreset_t coreset;
srslte_ue_dl_nr_pdcch_cfg_t cfg;
srslte_ofdm_t fft[SRSLTE_MAX_PORTS];
@ -53,9 +127,12 @@ typedef struct SRSLTE_API {
srslte_pdsch_nr_t pdsch;
srslte_dmrs_sch_t dmrs_pdsch;
srslte_dmrs_pdcch_estimator_t dmrs_pdcch;
srslte_dmrs_pdcch_estimator_t dmrs_pdcch[SRSLTE_UE_DL_NR_MAX_NOF_CORESET];
srslte_pdcch_nr_t pdcch;
srslte_dmrs_pdcch_ce_t* pdcch_ce;
srslte_dci_msg_nr_t pending_ul_dci_msg[SRSLTE_MAX_DCI_MSG_NR];
uint32_t pending_ul_dci_count;
} srslte_ue_dl_nr_t;
SRSLTE_API int
@ -63,21 +140,28 @@ srslte_ue_dl_nr_init(srslte_ue_dl_nr_t* q, cf_t* input[SRSLTE_MAX_PORTS], const
SRSLTE_API int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t* carrier);
SRSLTE_API int srslte_ue_dl_nr_set_coreset(srslte_ue_dl_nr_t* q, const srslte_coreset_t* coreset);
SRSLTE_API int srslte_ue_dl_nr_set_pdcch_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_pdcch_cfg_t* cfg);
SRSLTE_API void srslte_ue_dl_nr_free(srslte_ue_dl_nr_t* q);
SRSLTE_API void srslte_ue_dl_nr_estimate_fft(srslte_ue_dl_nr_t* q, const srslte_dl_slot_cfg_t* slot_cfg);
SRSLTE_API void srslte_ue_dl_nr_estimate_fft(srslte_ue_dl_nr_t* q, const srslte_slot_cfg_t* slot_cfg);
SRSLTE_API int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q,
const srslte_search_space_t* search_space,
const srslte_dl_slot_cfg_t* slot_cfg,
const srslte_slot_cfg_t* slot_cfg,
uint16_t rnti,
srslte_rnti_type_t rnti_type,
srslte_dci_dl_nr_t* dci_dl_list,
uint32_t nof_dci_msg);
SRSLTE_API int srslte_ue_dl_nr_find_ul_dci(srslte_ue_dl_nr_t* q,
const srslte_slot_cfg_t* slot_cfg,
uint16_t rnti,
srslte_rnti_type_t rnti_type,
srslte_dci_ul_nr_t* dci_ul_list,
uint32_t nof_dci_msg);
SRSLTE_API int srslte_ue_dl_nr_decode_pdsch(srslte_ue_dl_nr_t* q,
const srslte_dl_slot_cfg_t* slot,
const srslte_slot_cfg_t* slot,
const srslte_sch_cfg_nr_t* cfg,
srslte_pdsch_res_nr_t* res);
@ -87,5 +171,12 @@ SRSLTE_API int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q,
char* str,
uint32_t str_len);
SRSLTE_API int srslte_ue_dl_nr_pdsch_ack_resource(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
const srslte_dci_dl_nr_t* dci_dl,
srslte_pdsch_ack_resource_nr_t* pdsch_ack_resource);
SRSLTE_API int srslte_ue_dl_nr_gen_ack(const srslte_ue_dl_nr_harq_ack_cfg_t* cfg,
const srslte_pdsch_ack_nr_t* ack_info,
srslte_uci_data_nr_t* uci_data);
#endif // SRSLTE_UE_DL_NR_H

@ -0,0 +1,78 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
/******************************************************************************
* @file ue_dl_nr.h
*
* Description: NR UE uplink physical layer procedures for data
*
* This module is a frontend to all the uplink data channel processing modules.
*
* Reference:
*****************************************************************************/
#ifndef SRSLTE_UE_UL_DATA_H
#define SRSLTE_UE_UL_DATA_H
#include "srslte/phy/ch_estimation/dmrs_sch.h"
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/dft/ofdm.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
#include "srslte/phy/phch/pucch_cfg_nr.h"
#include "srslte/phy/phch/pucch_nr.h"
#include "srslte/phy/phch/pusch_nr.h"
typedef struct SRSLTE_API {
srslte_pusch_nr_args_t pusch;
srslte_pucch_nr_args_t pucch;
uint32_t nof_max_prb;
} srslte_ue_ul_nr_args_t;
typedef struct SRSLTE_API {
uint32_t max_prb;
srslte_carrier_nr_t carrier;
srslte_ofdm_t ifft;
cf_t* sf_symbols[SRSLTE_MAX_PORTS];
srslte_pusch_nr_t pusch;
srslte_pucch_nr_t pucch;
srslte_dmrs_sch_t dmrs;
} srslte_ue_ul_nr_t;
SRSLTE_API int srslte_ue_ul_nr_init(srslte_ue_ul_nr_t* q, cf_t* output, const srslte_ue_ul_nr_args_t* args);
SRSLTE_API int srslte_ue_ul_nr_set_carrier(srslte_ue_ul_nr_t* q, const srslte_carrier_nr_t* carrier);
SRSLTE_API int srslte_ue_ul_nr_encode_pusch(srslte_ue_ul_nr_t* q,
const srslte_slot_cfg_t* slot_cfg,
const srslte_sch_cfg_nr_t* pusch_cfg,
uint8_t* data_);
SRSLTE_API int srslte_ue_ul_nr_encode_pucch(srslte_ue_ul_nr_t* q,
const srslte_slot_cfg_t* slot_cfg,
const srslte_pucch_nr_common_cfg_t* cfg,
const srslte_pucch_nr_resource_t* resource,
const srslte_uci_data_nr_t* uci_data);
SRSLTE_API void srslte_ue_ul_nr_free(srslte_ue_ul_nr_t* q);
SRSLTE_API int
srslte_ue_ul_nr_pusch_info(const srslte_ue_ul_nr_t* q, const srslte_sch_cfg_nr_t* cfg, char* str, uint32_t str_len);
SRSLTE_API int srslte_ue_ul_nr_pucch_info(const srslte_pucch_nr_resource_t* resource,
const srslte_uci_data_nr_t* uci_data,
char* str,
uint32_t str_len);
#endif // SRSLTE_UE_UL_DATA_H

@ -1,63 +0,0 @@
/**
* Copyright 2013-2021 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 ue_dl_nr.h
*
* Description: NR UE uplink physical layer procedures for data
*
* This module is a frontend to all the uplink data channel processing modules.
*
* Reference:
*****************************************************************************/
#ifndef SRSLTE_UE_UL_DATA_H
#define SRSLTE_UE_UL_DATA_H
#include "srslte/phy/common/phy_common_nr.h"
#include "srslte/phy/phch/phch_cfg_nr.h"
/**
* @brief Calculates the PUSCH time resource default A and stores it in the provided PUSCH NR grant.
*
* @remark Defined by TS 38.214 V15.10.0 Table 6.1.2.1.1-2: Default PUSCH time domain resource allocation A for normal
* CP
*
* @param m Time domain resource assignment field value m of the DCI
* @param[out] grant PUSCH grant
* @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ue_ul_nr_pdsch_time_resource_default_A(uint32_t m, srslte_sch_grant_nr_t* grant);
/**
* @brief Calculates the number of PUSCH-DMRS CDM groups without data for DCI format 0_0
*
* @remark Defined by TS 38.214 V15.10.0 6.2.2 UE DM-RS transmission procedure
*
* @param cfg PUSCH NR configuration by upper layers
* @param[out] grant Provides grant pointer to fill
* @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code
*/
SRSLTE_API int srslte_ue_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg,
srslte_sch_grant_nr_t* grant);
#endif // SRSLTE_UE_UL_DATA_H

@ -57,7 +57,7 @@ SRSLTE_API extern int handler_registered;
#define DEBUG(_fmt, ...) \
do { \
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { \
fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__); \
fprintf(stdout, "[DEBUG]: " _fmt "\n", ##__VA_ARGS__); \
} else { \
srslte_phy_log_print(LOG_LEVEL_DEBUG_S, _fmt, ##__VA_ARGS__); \
} \
@ -66,7 +66,7 @@ SRSLTE_API extern int handler_registered;
#define INFO(_fmt, ...) \
do { \
if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { \
fprintf(stdout, "[INFO]: " _fmt, ##__VA_ARGS__); \
fprintf(stdout, "[INFO]: " _fmt "\n", ##__VA_ARGS__); \
} else { \
srslte_phy_log_print(LOG_LEVEL_INFO_S, _fmt, ##__VA_ARGS__); \
} \

@ -130,6 +130,7 @@ SRSLTE_API void srslte_vec_fprint_i(FILE* stream, const int* x, const uint32_t l
SRSLTE_API void srslte_vec_fprint_s(FILE* stream, const int16_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_fprint_hex(FILE* stream, uint8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_sprint_hex(char* str, const uint32_t max_str_len, uint8_t* x, const uint32_t len);
SRSLTE_API void srslte_vec_sprint_bin(char* str, const uint32_t max_str_len, const uint8_t* x, const uint32_t len);
/* Saves/loads a vector to a file */
SRSLTE_API void srslte_vec_save_file(char* filename, const void* buffer, const uint32_t len);

@ -52,8 +52,7 @@ namespace srslte {
class radio : public radio_interface_phy, public srslte::radio_base
{
public:
radio(srslte::log_filter* log_h);
radio(srslte::logger* logger_h);
radio();
~radio();
int init(const rf_args_t& args_, phy_interface_radio* phy_) final;
@ -99,9 +98,7 @@ private:
std::vector<srslte_rf_info_t> rf_info = {};
std::vector<int32_t> rx_offset_n = {};
rf_metrics_t rf_metrics = {};
log_filter log_local = {};
log_filter* log_h = nullptr;
srslte::logger* logger = nullptr;
srslog::basic_logger& logger = srslog::fetch_basic_logger("RF", false);
phy_interface_radio* phy = nullptr;
cf_t* zeros = nullptr;
std::array<cf_t*, SRSLTE_MAX_CHANNELS> dummy_buffers;
@ -133,6 +130,8 @@ private:
std::vector<double> cur_tx_freqs = {};
std::vector<double> cur_rx_freqs = {};
constexpr static const uint32_t max_resamp_buf_sz_ms = 5; ///< Maximum buffer size in ms for intermediate resampling
///< buffers
constexpr static double tx_max_gap_zeros = 4e-3; ///< Maximum transmission gap to fill with zeros, otherwise the burst
///< shall be stopped

@ -38,7 +38,6 @@ class phy_interface_radio;
class radio_base
{
public:
radio_base(srslte::logger* logger_ = nullptr) {}
virtual ~radio_base() = default;
virtual std::string get_type() = 0;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save