diff --git a/CMakeLists.txt b/CMakeLists.txt index edd9c18657c236d03390f0ea98202e54521f8d40..e3741d1f9b06db7cad30d425de5043d2d930f4ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ include("cmake_targets/CPM.cmake") option(CCACHE_ACTIVE "CCache" ON) find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND AND CCACHE_ACTIVE) - if(${CMAKE_VERSION} VERSION_LESS "3.4.0") + if(${CMAKE_VERSION} VERSION_LESS "3.4.0") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") message(STATUS "Found ccache in ${CCACHE_FOUND}. Using ccache. CMake < 3.4") else() @@ -105,13 +105,13 @@ add_list_string_option(CMAKE_BUILD_TYPE "RelWithDebInfo" "Choose the type of bui # in case /proc/cpuinfo exists we want to inspect available Intrinsics # -so not to go always through SIMDE emulation -# -so to avoid AVX512 instructions generation by gcc +# -so to avoid AVX512 instructions generation by gcc if(EXISTS "/proc/cpuinfo" AND NOT CROSS_COMPILE) file(STRINGS "/proc/cpuinfo" CPUFLAGS REGEX flags LIMIT_COUNT 1) else() message(WARNING "did not find /proc/cpuinfo -- not setting any x86-specific compilation variables") endif() - + eval_boolean(AUTODETECT_AVX512 DEFINED CPUFLAGS AND CPUFLAGS MATCHES "avx512") add_boolean_option(AVX512 ${AUTODETECT_AVX512} "Whether AVX512 intrinsics is available on the host processor" ON) @@ -271,6 +271,11 @@ add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace" ON) add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace" ON) +add_boolean_option(TRACY_ENABLE OFF "Enable tracy instrumentation" ON) +if (TRACY_ENABLE) + CPMAddPackage("gh:wolfpld/tracy#v0.11.1") +endif() + set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) add_library(ITTI ${OCP_ITTI}/intertask_interface.cpp) target_link_libraries(ITTI PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) @@ -636,7 +641,8 @@ if (cap_FOUND) target_link_libraries(UTIL PRIVATE cap) target_compile_definitions(UTIL PRIVATE HAVE_LIB_CAP) endif() -target_link_libraries(UTIL PUBLIC ${T_LIB} pthread LOG thread-pool utils) +target_link_libraries(UTIL PUBLIC ${T_LIB} pthread LOG thread-pool utils barrier actor) +target_link_libraries(UTIL PUBLIC instrumentation) set(SECURITY_SRC ${OPENAIR3_DIR}/SECU/secu_defs.c @@ -677,7 +683,7 @@ set(SCHED_NR_SRC ${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c ) add_library(SCHED_NR_LIB ${SCHED_NR_SRC}) -target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs) +target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs UTIL) set(SCHED_SRC_RU ${OPENAIR1_DIR}/SCHED/ru_procedures.c @@ -695,7 +701,7 @@ set(SCHED_SRC_UE ${OPENAIR1_DIR}/SCHED_UE/srs_pc.c ) add_library(SCHED_UE_LIB ${SCHED_SRC_UE}) -target_link_libraries(SCHED_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_link_libraries(SCHED_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL) set(SCHED_SRC_NR_UE ${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -706,7 +712,7 @@ set(SCHED_SRC_NR_UE ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_uci_ue_nr.c ) add_library(SCHED_NR_UE_LIB ${SCHED_SRC_NR_UE}) -target_link_libraries(SCHED_NR_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_link_libraries(SCHED_NR_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL) # nFAPI ################################# @@ -717,7 +723,7 @@ set(NFAPI_SRC ) add_library(NFAPI_LIB ${NFAPI_SRC}) target_link_libraries(NFAPI_LIB PUBLIC nfapi_common) -target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5) +target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5 nr_fapi_p7) include_directories(${NFAPI_DIR}/nfapi/public_inc) include_directories(${NFAPI_DIR}/nfapi/inc) @@ -742,7 +748,7 @@ set(NFAPI_VNF_SRC ) add_library(NFAPI_VNF_LIB ${NFAPI_VNF_SRC}) target_link_libraries(NFAPI_VNF_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) -target_link_libraries(NFAPI_VNF_LIB PRIVATE nr_fapi_p5) +target_link_libraries(NFAPI_VNF_LIB PRIVATE nr_fapi_p5 nr_fapi_p7) if(OAI_AERIAL) target_compile_definitions(NFAPI_VNF_LIB PRIVATE ENABLE_AERIAL) endif() @@ -758,7 +764,8 @@ set(NFAPI_USER_SRC ${NFAPI_USER_DIR}/gnb_ind_vars.c ) add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC}) -target_link_libraries(NFAPI_USER_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_link_libraries(NFAPI_USER_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL) +target_link_libraries(NFAPI_USER_LIB PRIVATE nr_fapi_p7) include_directories(${NFAPI_USER_DIR}) # Layer 1 @@ -1118,7 +1125,7 @@ set(PHY_SRC_UE ${PHY_SRC_UE} ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_comp add_library(PHY_COMMON ${PHY_SRC_COMMON}) target_link_libraries(PHY_COMMON PRIVATE shlib_loader) add_dependencies(PHY_COMMON dfts) -target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs) +target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs PUBLIC UTIL) add_library(PHY ${PHY_SRC}) target_link_libraries(PHY PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) @@ -1127,7 +1134,7 @@ pkg_check_modules(blas REQUIRED blas) pkg_check_modules(lapacke REQUIRED lapacke) add_library(PHY_UE ${PHY_SRC_UE}) -target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL) # RHEL needs also cblas, but Ubuntu does not have it. So `cblas_LIBRARIES` will # be empty for Ubuntu, a no-op pkg_check_modules(cblas cblas) @@ -1135,6 +1142,7 @@ target_link_libraries(PHY_UE PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapa target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS}) add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON}) +target_link_libraries(PHY_NR_COMMON PUBLIC UTIL) add_library(PHY_NR ${PHY_NR_SRC}) target_link_libraries(PHY_NR nr_phy_common nr_common) @@ -1144,10 +1152,10 @@ target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common) target_compile_definitions(PHY_NR_NO_AVX_256 PUBLIC USE_128BIT) add_library(PHY_NR_UE ${PHY_NR_UE_SRC}) -target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common) +target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL) add_library(PHY_RU ${PHY_SRC_RU}) -target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs) +target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs UTIL) #Library for mex functions #########################3 @@ -1216,7 +1224,7 @@ set(NR_SDAP_SRC ${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap.c ${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_entity.c ) - + set(L2_SRC ${PDCP_DIR}/pdcp.c ${PDCP_DIR}/pdcp_fifo.c @@ -2064,7 +2072,7 @@ if(E2_AGENT) target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup) target_compile_definitions(nr-cuup PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT) endif() - + # nr-uesoftmodem is UE implementation ####################################### diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 14c4ac582a8d5beab8c040d9b3655d1bfd246d7a..229c93b0432659a60fe827d98f8011d5ed224e39 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -2,3 +2,9 @@ add_subdirectory(utils) add_subdirectory(config/yaml) configure_file(oai_version.h.in oai_version.h @ONLY) + +add_library(instrumentation INTERFACE instrumentation.h) +target_include_directories(instrumentation INTERFACE .) +if (TRACY_ENABLE) + target_link_libraries(instrumentation INTERFACE Tracy::TracyClient) +endif() diff --git a/common/instrumentation.h b/common/instrumentation.h new file mode 100644 index 0000000000000000000000000000000000000000..6810761f6981b7e1f8cd680b48399420a4362d9b --- /dev/null +++ b/common/instrumentation.h @@ -0,0 +1,42 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef INSTRUMENTATION_H +#define INSTRUMENTATION_H + +#ifdef TRACY_ENABLE +#include "tracy/TracyC.h" +#endif + +#ifndef TracyCZone +#define TracyCZone(...) +#endif +#ifndef TracyCZoneEnd +#define TracyCZoneEnd(...) +#endif +#ifndef TracyCFrameMark +#define TracyCFrameMark +#endif +#ifndef TracyCPlot +#define TracyCPlot(...) +#endif + +#endif diff --git a/common/utils/CMakeLists.txt b/common/utils/CMakeLists.txt index 7cf067dd14941fba750b65223e068d34399768be..ccb15bfd478b95ccdcf82bb739062f359a0ae544 100644 --- a/common/utils/CMakeLists.txt +++ b/common/utils/CMakeLists.txt @@ -19,3 +19,5 @@ target_link_libraries(utils PRIVATE ${T_LIB}) if (ENABLE_TESTS) add_subdirectory(hashtable/tests) endif() +add_subdirectory(barrier) +add_subdirectory(actor) diff --git a/common/utils/actor/CMakeLists.txt b/common/utils/actor/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..40057d347eb2b6d2c84781ae5f88a85ff3a0c58a --- /dev/null +++ b/common/utils/actor/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(actor actor.c) +target_include_directories(actor PUBLIC ./) +target_link_libraries(actor PUBLIC thread-pool) +if (ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/common/utils/actor/README.md b/common/utils/actor/README.md new file mode 100644 index 0000000000000000000000000000000000000000..13a577a7a1ed6ee1015d9a7d7551c349c5d81331 --- /dev/null +++ b/common/utils/actor/README.md @@ -0,0 +1,13 @@ +# Overview + +This is a simple actor implementation (see https://en.wikipedia.org/wiki/Actor_model). + +Actor is implemented as a single thread with single producer/consumer queue as input. You can think of it as a single thread threadpool + +If you need concurrency, consider allocating more than one actor. + +# Thread safety + +There is two ways to ensure thread safety between two actors + - Use core affinity to set both actor to run on the same core. + - Use data separation, like in testcase thread_safety_with_actor_specific_data diff --git a/common/utils/actor/actor.c b/common/utils/actor/actor.c new file mode 100644 index 0000000000000000000000000000000000000000..68661ddb6d7c017846b37c656bc47fa0a8b75e2c --- /dev/null +++ b/common/utils/actor/actor.c @@ -0,0 +1,87 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "thread-pool.h" +#include "actor.h" +#include "system.h" +#include "assertions.h" + +void *actor_thread(void *arg); + +void init_actor(Actor_t *actor, const char *name, int core_affinity) +{ + actor->terminate = false; + initNotifiedFIFO(&actor->fifo); + char actor_name[16]; + snprintf(actor_name, sizeof(actor_name), "%s%s", name, "_actor"); + threadCreate(&actor->thread, actor_thread, (void *)actor, actor_name, core_affinity, OAI_PRIORITY_RT_MAX); +} + +/// @brief Main actor thread +/// @param arg actor pointer +/// @return NULL +void *actor_thread(void *arg) +{ + Actor_t *actor = arg; + + // Infinite loop to process requests + do { + notifiedFIFO_elt_t *elt = pullNotifiedFIFO(&actor->fifo); + if (elt == NULL) { + AssertFatal(actor->terminate, "pullNotifiedFIFO() returned NULL\n"); + break; + } + + elt->processingFunc(NotifiedFifoData(elt)); + if (elt->reponseFifo) { + pushNotifiedFIFO(elt->reponseFifo, elt); + } else + delNotifiedFIFO_elt(elt); + } while (!actor->terminate); + + return NULL; +} + +void destroy_actor(Actor_t *actor) +{ + actor->terminate = true; + abortNotifiedFIFO(&actor->fifo); + pthread_join(actor->thread, NULL); +} + +static void self_destruct_fun(void *arg) { + Actor_t *actor = arg; + actor->terminate = true; + abortNotifiedFIFO(&actor->fifo); +} + +void shutdown_actor(Actor_t *actor) +{ + notifiedFIFO_t response_fifo; + initNotifiedFIFO(&response_fifo); + notifiedFIFO_elt_t *elt = newNotifiedFIFO_elt(0, 0, &response_fifo, self_destruct_fun); + elt->msgData = actor; + pushNotifiedFIFO(&actor->fifo, elt); + elt = pullNotifiedFIFO(&response_fifo); + delNotifiedFIFO_elt(elt); + abortNotifiedFIFO(&response_fifo); + pthread_join(actor->thread, NULL); +} diff --git a/common/utils/actor/actor.h b/common/utils/actor/actor.h new file mode 100644 index 0000000000000000000000000000000000000000..753ba8d00a5932a9d12bb66cfcdcb4610f1fc4fd --- /dev/null +++ b/common/utils/actor/actor.h @@ -0,0 +1,52 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef ACTOR_H +#define ACTOR_H +#include "thread-pool.h" + +#define INIT_ACTOR(ptr, name, core_affinity) init_actor((Actor_t *)ptr, name, core_affinity); + +#define DESTROY_ACTOR(ptr) destroy_actor((Actor_t *)ptr); + +#define SHUTDOWN_ACTOR(ptr) shutdown_actor((Actor_t *)ptr); + +typedef struct Actor_t { + notifiedFIFO_t fifo; + bool terminate; + pthread_t thread; +} Actor_t; + +/// @brief Initialize the actor. Starts actor thread +/// @param actor +/// @param name Actor name. Thread name will be derived from it +/// @param core_affinity Core affinity. Specify -1 for no affinity +void init_actor(Actor_t *actor, const char *name, int core_affinity); + +/// @brief Destroy the actor. Free the memory, stop the thread. +/// @param actor +void destroy_actor(Actor_t *actor); + +/// @brief Gracefully shutdown the actor, letting all tasks previously started finish +/// @param actor +void shutdown_actor(Actor_t *actor); + +#endif diff --git a/common/utils/actor/tests/CMakeLists.txt b/common/utils/actor/tests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..dd4a22a848a884f031ae9ffc910e3bff56c9c029 --- /dev/null +++ b/common/utils/actor/tests/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(test_actor test_actor.cpp) +target_link_libraries(test_actor PRIVATE actor GTest::gtest thread-pool LOG) +add_dependencies(tests test_actor) +add_test(NAME test_actor + COMMAND ./test_actor) diff --git a/common/utils/actor/tests/test_actor.cpp b/common/utils/actor/tests/test_actor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f613846a2c92ebb4d242c15944684d5f83e4781 --- /dev/null +++ b/common/utils/actor/tests/test_actor.cpp @@ -0,0 +1,134 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include <stdio.h> +#include <assert.h> +#include <threads.h> +#include <stdlib.h> +#include <gtest/gtest.h> +#include <unistd.h> +#include "common/config/config_userapi.h" +#include "log.h" + +extern "C" { +#include "actor.h" +configmodule_interface_t *uniqCfg; +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + if (assert) { + abort(); + } else { + exit(EXIT_SUCCESS); + } +} +} + +int num_processed = 0; + +void process(void *arg) +{ + num_processed++; +} + +TEST(actor, schedule_one) +{ + Actor_t actor; + init_actor(&actor, "TEST", -1); + notifiedFIFO_elt_t *elt = newNotifiedFIFO_elt(0, 0, NULL, process); + pushNotifiedFIFO(&actor.fifo, elt); + shutdown_actor(&actor); + EXPECT_EQ(num_processed, 1); +} + +TEST(actor, schedule_many) +{ + num_processed = 0; + Actor_t actor; + init_actor(&actor, "TEST", -1); + for (int i = 0; i < 100; i++) { + notifiedFIFO_elt_t *elt = newNotifiedFIFO_elt(0, 0, NULL, process); + pushNotifiedFIFO(&actor.fifo, elt); + } + shutdown_actor(&actor); + EXPECT_EQ(num_processed, 100); +} + +// Thread safety can be ensured through core affinity - if two actors +// are running on the same core they are thread safe +TEST(DISABLED_actor, thread_safety_with_core_affinity) +{ + num_processed = 0; + int core = 0; + Actor_t actor; + init_actor(&actor, "TEST", core); + Actor_t actor2; + init_actor(&actor2, "TEST2", core); + for (int i = 0; i < 10000; i++) { + Actor_t *actor_ptr = i % 2 == 0 ? &actor : &actor2; + notifiedFIFO_elt_t *elt = newNotifiedFIFO_elt(0, 0, NULL, process); + pushNotifiedFIFO(&actor_ptr->fifo, elt); + } + shutdown_actor(&actor); + shutdown_actor(&actor2); + EXPECT_EQ(num_processed, 10000); +} + +// Thread safety can be ensured through data separation, here using C inheritance-like +// model +typedef struct TestActor_t { + Actor_t actor; + int count; +} TestActor_t; + +void process_thread_safe(void *arg) +{ + TestActor_t *actor = static_cast<TestActor_t *>(arg); + actor->count += 1; +} + +TEST(actor, thread_safety_with_actor_specific_data) +{ + num_processed = 0; + int core = 0; + TestActor_t actor; + INIT_ACTOR(&actor, "TEST", core); + actor.count = 0; + TestActor_t actor2; + INIT_ACTOR(&actor2, "TEST2", core); + actor2.count = 0; + for (int i = 0; i < 10000; i++) { + TestActor_t *actor_ptr = i % 2 == 0 ? &actor : &actor2; + notifiedFIFO_elt_t *elt = newNotifiedFIFO_elt(0, 0, NULL, process_thread_safe); + elt->msgData = actor_ptr; + pushNotifiedFIFO(&actor_ptr->actor.fifo, elt); + } + SHUTDOWN_ACTOR(&actor); + SHUTDOWN_ACTOR(&actor2); + EXPECT_EQ(actor.count + actor2.count, 10000); +} + +int main(int argc, char **argv) +{ + logInit(); + g_log->log_component[UTIL].level = OAILOG_DEBUG; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/common/utils/barrier/CMakeLists.txt b/common/utils/barrier/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7957f3e1cfcddb7f95e088d6862af4beb3f49b1b --- /dev/null +++ b/common/utils/barrier/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(barrier barrier.c) +target_include_directories(barrier PUBLIC ./) +target_link_libraries(barrier PUBLIC pthread) + +if (ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/common/utils/barrier/barrier.c b/common/utils/barrier/barrier.c new file mode 100644 index 0000000000000000000000000000000000000000..574d6be4a387704a74127f826cbce1dce893f8a2 --- /dev/null +++ b/common/utils/barrier/barrier.c @@ -0,0 +1,75 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "barrier.h" +#include "assertions.h" + +void dynamic_barrier_init(dynamic_barrier_t* barrier) +{ + int ret = pthread_mutex_init(&barrier->barrier_lock, NULL); + AssertFatal(ret == 0, "Mutex error %d", ret); + barrier->callback = NULL; + barrier->callback_arg = NULL; + barrier->completed_jobs = 0; +} + +void dynamic_barrier_reset(dynamic_barrier_t* barrier) +{ + barrier->callback = NULL; + if (barrier->callback_arg != NULL) { + free(barrier->callback_arg); + } + barrier->callback_arg = NULL; + barrier->completed_jobs = 0; +} + +void dynamic_barrier_join(dynamic_barrier_t* barrier) +{ + int ret = pthread_mutex_lock(&barrier->barrier_lock); + AssertFatal(ret == 0, "Mutex error %d", ret); + barrier->completed_jobs++; + if (barrier->callback) { + if (barrier->completed_jobs == barrier->max_joins) { + barrier->completed_jobs = 0; + barrier->callback(barrier->callback_arg); + barrier->callback = NULL; + barrier->callback_arg = NULL; + } + } + ret = pthread_mutex_unlock(&barrier->barrier_lock); + AssertFatal(ret == 0, "Mutex error %d", ret); +} + +void dynamic_barrier_update(dynamic_barrier_t* barrier, int max_joins, callback_t callback, void* arg) +{ + int ret = pthread_mutex_lock(&barrier->barrier_lock); + AssertFatal(ret == 0, "Mutex error %d", ret); + if (barrier->completed_jobs == max_joins) { + barrier->completed_jobs = 0; + callback(arg); + } else { + barrier->max_joins = max_joins; + barrier->callback = callback; + barrier->callback_arg = arg; + } + ret = pthread_mutex_unlock(&barrier->barrier_lock); + AssertFatal(ret == 0, "Mutex error %d", ret); +} diff --git a/common/utils/barrier/barrier.h b/common/utils/barrier/barrier.h new file mode 100644 index 0000000000000000000000000000000000000000..e27b56e76616ec4f094cec6f021bbc86448b1050 --- /dev/null +++ b/common/utils/barrier/barrier.h @@ -0,0 +1,57 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _BARRIER_H_ +#define _BARRIER_H_ +#include <stdint.h> +#include <pthread.h> + +typedef void (*callback_t)(void*); + +/// @brief This thread barrier allows modifying the maximum joins after it is initialized +typedef struct dynamic_barrier_t { + pthread_mutex_t barrier_lock; + int completed_jobs; + int max_joins; + callback_t callback; + void* callback_arg; +} dynamic_barrier_t; + +/// @brief Initialize the barrier +/// @param barrier +void dynamic_barrier_init(dynamic_barrier_t* barrier); + +/// @brief Reset the barrier +/// @param barrier +void dynamic_barrier_reset(dynamic_barrier_t* barrier); + +/// @brief Perform join on the barrier. May run callback if it is already set +/// @param barrier +void dynamic_barrier_join(dynamic_barrier_t* barrier); + +/// @brief Set callback and max_joins. May run callback if the number of joins is already equal to max_joins +/// @param barrier +/// @param max_joins maximum number of joins before barrier triggers +/// @param callback callback function +/// @param arg callback function argument +void dynamic_barrier_update(dynamic_barrier_t* barrier, int max_joins, callback_t callback, void* arg); + +#endif diff --git a/common/utils/barrier/tests/CMakeLists.txt b/common/utils/barrier/tests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bbe774b5964d2dd62830375465dabc46617f6bae --- /dev/null +++ b/common/utils/barrier/tests/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(test_barrier test_barrier.cpp) +target_link_libraries(test_barrier PRIVATE barrier GTest::gtest) +add_dependencies(tests test_barrier) +add_test(NAME test_barrier + COMMAND ./test_barrier) diff --git a/common/utils/barrier/tests/test_barrier.cpp b/common/utils/barrier/tests/test_barrier.cpp new file mode 100644 index 0000000000000000000000000000000000000000..985b18c2988fd9b27b81217df42e9a59c01961c0 --- /dev/null +++ b/common/utils/barrier/tests/test_barrier.cpp @@ -0,0 +1,118 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include <stdio.h> +#include <assert.h> +#include <threads.h> +#include <stdlib.h> +#include <gtest/gtest.h> + +extern "C" { +#include "barrier.h" +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + if (assert) { + abort(); + } else { + exit(EXIT_SUCCESS); + } +} +} + +static int trigger_count = 0; +static int triggered = 0; +void f(void *arg) +{ + triggered = 1; + trigger_count++; +} + +TEST(dynamic_barrier, trigger_once) +{ + dynamic_barrier_t barrier; + triggered = 0; + dynamic_barrier_init(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_update(&barrier, 4, f, NULL); + EXPECT_EQ(triggered, 1); +} + +TEST(dynamic_barrier, trigger_twice) +{ + dynamic_barrier_t barrier; + triggered = 0; + dynamic_barrier_init(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_update(&barrier, 4, f, NULL); + EXPECT_EQ(triggered, 1); + triggered = 0; + dynamic_barrier_init(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_join(&barrier); + dynamic_barrier_update(&barrier, 4, f, NULL); + EXPECT_EQ(triggered, 1); +} + +int dynamic_barrier_thread(void *thr_data) +{ + dynamic_barrier_t *barrier = (dynamic_barrier_t *)thr_data; + dynamic_barrier_join(barrier); + return 0; +} + +int dynamic_barrier_update_thread(void *thr_data) +{ + dynamic_barrier_t *barrier = (dynamic_barrier_t *)thr_data; + dynamic_barrier_update(barrier, 3, f, NULL); + return 0; +} + +TEST(dynamic_barrier, multithreaded) +{ + thrd_t thr[3]; + dynamic_barrier_t barrier; + trigger_count = 0; + for (int i = 0; i < 300; i++) { + dynamic_barrier_init(&barrier); + thrd_t update_thread; + thrd_create(&update_thread, dynamic_barrier_update_thread, &barrier); + for (int n = 0; n < 3; ++n) + thrd_create(&thr[n], dynamic_barrier_thread, &barrier); + for (int n = 0; n < 3; ++n) + thrd_join(thr[n], NULL); + thrd_join(update_thread, NULL); + } + assert(trigger_count == 300); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/common/utils/nr/CMakeLists.txt b/common/utils/nr/CMakeLists.txt index 979958d877069e557cdb878717904b7f0b3794f5..c99b9a06a713442cf4bebf7a7204b7fd37e9fc56 100644 --- a/common/utils/nr/CMakeLists.txt +++ b/common/utils/nr/CMakeLists.txt @@ -1,6 +1,6 @@ add_library(nr_common nr_common.c) target_include_directories(nr_common PUBLIC .) -target_link_libraries(nr_common PRIVATE UTIL) +target_link_libraries(nr_common PUBLIC UTIL) if (ENABLE_TESTS) add_subdirectory(tests) endif() diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index 959812d73a9bda9b4906037935ddaa07ccce855c..a7da081f093a7c53e0db500a2e81ec8e452f12b3 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -53,7 +53,7 @@ message(STATUS "No specific telnet functions for 4Gue") message(STATUS "Add 5Gue specific telnet functions in libtelnetsrv_5Gue.so") add_library(telnetsrv_5Gue MODULE telnetsrv_5Gue_measurements.c) add_dependencies(telnetsrv telnetsrv_5Gue) -target_link_libraries(telnetsrv_5Gue PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +target_link_libraries(telnetsrv_5Gue PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) message(STATUS "Add CI specific telnet functions in libtelnetsrv_ci.so") add_library(telnetsrv_ci MODULE telnetsrv_ci.c) @@ -79,4 +79,3 @@ add_dependencies(telnetsrv telnetsrv_rrc) set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_ciUE telnetsrv_bearer telnetsrv_rrc PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../.. ) - diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index b0e1b9e4e88e68e2c46b0c9cfc3bebbf4591193b..31395d7a9b74f5c0697e08321e1d94a0a3530fff 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -30,6 +30,7 @@ #include <stdalign.h> #include <pthread.h> #include <unistd.h> +#include <string.h> #include <sys/syscall.h> #include "assertions.h" #include "common/utils/time_meas.h" diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 21e2f5ca8db8b6f4626f0c7287e97f85e555b90f..454faf1a1ec1677f515e3c961f5d14409d551520 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -136,7 +136,6 @@ These modes of operation are supported: - evalution of RSRP report - evaluation of CQI report - MAC scheduling of SR reception -- Support of up to 16 UEs (can be increased to 32) - Intra-frequency handover ## gNB RLC @@ -247,6 +246,11 @@ These modes of operation are supported: - Interfaces with PDCP and RLC for data send/receive at the CU and DU respectively (F1-U interface) - Interface with SDAP for data send/receive, capture of GTP-U Optional Header, GTP-U Extension Header and PDU Session Container. +## Number of supported UEs + +* 16 by default (as defined in `MAX_MOBILES_PER_GNB`) +* up to 64 if the configured bandwidth is sufficient (at leat 40 MHz) + # OpenAirInterface 5G-NR UE Feature Set # ## NR UE PHY Layer ## diff --git a/doc/nr-ue-design.md b/doc/nr-ue-design.md index 7ee42335d646a6c2c6476b46da316322e81fcb92..f1cef858e182159a5cb557f68cd8438ea258f8fe 100644 --- a/doc/nr-ue-design.md +++ b/doc/nr-ue-design.md @@ -13,13 +13,17 @@ The `UE_thread` function in `nr-ue.c` is the main top level thread that interact The UE exits when at any point in operation it gets out of synchronization. When the command line option `--non-stop` is used, the UE goes to 'Initial Synchronization' mode when it loses synchronization with gNB. However, this feature is not fully implemented and it is a work in progress at the time of writing this documentation. This will be the default behavior (not a command line option) when the feature is fully implemented. +UE uses actors which are threads dedicated to particular activity. Sync Actor handles initial sync. DL Actors handle DLSCH PHY procedures. UL procedures are processed directly on the threadpool + + + ## Initial Synchronization Block ```mermaid graph TD start(Start) -->|UE_thread| rxRu["RU read<br/>(Reads two frames)"] - rxRu --> |Tpool thread| sync["SSB detection<br/>(PSS & SSS detection<br/>PBCH decoding<br/>SIB decoding)"] + rxRu --> |Sync Actor| sync["SSB detection<br/>(PSS & SSS detection<br/>PBCH decoding<br/>SIB decoding)"] rxRu --> |UE_thread| rxRuDummy["RU read<br/>(Dummy read till sync detection to avoid buffer overflow at radio)"] - sync --> |Tpool thread| frameSync["Frame synchronization<br/>(Shift received samples to align with frame)"] + sync --> |UE_thread| frameSync["Frame synchronization<br/>(Shift received samples to align with frame)"] rxRuDummy --> |UE_thread| frameSync ``` ## Regular Slot Processing @@ -27,9 +31,8 @@ graph TD graph TD sync["Frame synchronization<br/>(Shift received samples to align with frame)"] -->|UE_thread| hw_read["RU read (slot n)"] hw_read --> |UE_thread| rxPreProc["PBCH & PDCCH decoding (slot n)"] - hw_read --> |Tpool thread| txProc["Tx processing (slot n+3)<br/>PUSCH encode<br/>PUCCH encode (wait for DLSCH in slot n+3-k1 to finish)<br/>RU write"] - rxPreProc --> |Tpool thread| rxProc["PDSCH decoding (slot n)"] + hw_read --> |UL Actor| txProc["Tx processing (slot n+3)<br/>PUSCH encode<br/>PUCCH encode (wait for DLSCH in slot n+3-k1 to finish)<br/>RU write"] + rxPreProc --> |DL Actor| rxProc["PDSCH decoding (slot n)"] rxPreProc --> |UE_thread| join(Merge) - txProc --> |Tpool thread| join join --> |Go to next slot<br/>UE_thread| hw_read ``` diff --git a/doc/nr-ue-threads.svg b/doc/nr-ue-threads.svg new file mode 100644 index 0000000000000000000000000000000000000000..0ae01ea8aa9dceab38af5c48a55b30dd456ce62e --- /dev/null +++ b/doc/nr-ue-threads.svg @@ -0,0 +1 @@ +<svg version="1.1" viewBox="0.0 0.0 960.0 540.0" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l960.0 0l0 540.0l-960.0 0l0 -540.0z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#ffffff" d="m0 0l960.0 0l0 540.0l-960.0 0z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m477.0533 370.51263l-34.967163 0l0 20.126007l-201.50526 0" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m477.0533 370.51263l-34.967163 0l0 20.125977l-195.50526 0" fill-rule="evenodd"/><path fill="#595959" stroke="#595959" stroke-width="1.0" stroke-linecap="butt" d="m246.58089 388.98688l-4.538086 1.6517334l4.538086 1.6517334z" fill-rule="evenodd"/><path fill="#eeeeee" d="m120.417366 74.275314l266.17325 0l0 58.740158l-266.17325 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m120.417366 74.275314l266.17325 0l0 58.740158l-266.17325 0z" fill-rule="evenodd"/><path fill="#000000" d="m169.86107 97.20602l1.765625 0l0 7.71875q0 2.015625 -0.453125 3.203125q-0.453125 1.1875 -1.640625 1.9375q-1.1875 0.734375 -3.125 0.734375q-1.875 0 -3.078125 -0.640625q-1.1875 -0.65625 -1.703125 -1.875q-0.5 -1.234375 -0.5 -3.359375l0 -7.71875l1.765625 0l0 7.71875q0 1.734375 0.3125 2.5625q0.328125 0.8125 1.109375 1.265625q0.796875 0.453125 1.9375 0.453125q1.953125 0 2.78125 -0.890625q0.828125 -0.890625 0.828125 -3.390625l0 -7.71875zm4.738571 13.359375l0 -13.359375l9.65625 0l0 1.578125l-7.875 0l0 4.09375l7.375 0l0 1.5625l-7.375 0l0 4.546875l8.1875 0l0 1.578125l-9.96875 0zm10.693573 3.703125l0 -1.1875l10.859375 0l0 1.1875l-10.859375 0zm15.469467 -5.171875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm1.6051788 1.46875l0 -13.359375l1.640625 0l0 4.796875q1.140625 -1.328125 2.890625 -1.328125q1.078125 0 1.859375 0.421875q0.796875 0.421875 1.140625 1.171875q0.34375 0.75 0.34375 2.171875l0 6.125l-1.640625 0l0 -6.125q0 -1.234375 -0.53125 -1.796875q-0.53125 -0.5625 -1.515625 -0.5625q-0.71875 0 -1.359375 0.390625q-0.640625 0.375 -0.921875 1.015625q-0.265625 0.640625 -0.265625 1.78125l0 5.296875l-1.640625 0zm10.360092 0l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm12.853302 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm15.453842 4.578125q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm10.469467 4.859375l0 -1.21875q-0.90625 1.4375 -2.703125 1.4375q-1.15625 0 -2.125 -0.640625q-0.96875 -0.640625 -1.5 -1.78125q-0.53125 -1.140625 -0.53125 -2.625q0 -1.453125 0.484375 -2.625q0.484375 -1.1875 1.4375 -1.8125q0.96875 -0.625 2.171875 -0.625q0.875 0 1.546875 0.375q0.6875 0.359375 1.109375 0.953125l0 -4.796875l1.640625 0l0 13.359375l-1.53125 0zm-5.171875 -4.828125q0 1.859375 0.78125 2.78125q0.78125 0.921875 1.84375 0.921875q1.078125 0 1.828125 -0.875q0.75 -0.890625 0.75 -2.6875q0 -1.984375 -0.765625 -2.90625q-0.765625 -0.9375 -1.890625 -0.9375q-1.078125 0 -1.8125 0.890625q-0.734375 0.890625 -0.734375 2.8125zm17.590256 8.75q-1.359375 -1.703125 -2.296875 -4.0q-0.9375 -2.296875 -0.9375 -4.765625q0 -2.15625 0.703125 -4.140625q0.828125 -2.3125 2.53125 -4.59375l1.171875 0q-1.09375 1.890625 -1.453125 2.703125q-0.546875 1.25 -0.875 2.625q-0.390625 1.703125 -0.390625 3.421875q0 4.375 2.71875 8.75l-1.171875 0zm3.087677 -3.921875l0 -9.671875l1.46875 0l0 1.359375q0.453125 -0.71875 1.203125 -1.140625q0.765625 -0.4375 1.71875 -0.4375q1.078125 0 1.765625 0.453125q0.6875 0.4375 0.96875 1.234375q1.15625 -1.6875 2.984375 -1.6875q1.453125 0 2.21875 0.796875q0.78125 0.796875 0.78125 2.453125l0 6.640625l-1.640625 0l0 -6.09375q0 -0.984375 -0.15625 -1.40625q-0.15625 -0.4375 -0.578125 -0.703125q-0.421875 -0.265625 -0.984375 -0.265625q-1.015625 0 -1.6875 0.6875q-0.671875 0.671875 -0.671875 2.15625l0 5.625l-1.640625 0l0 -6.28125q0 -1.09375 -0.40625 -1.640625q-0.40625 -0.546875 -1.3125 -0.546875q-0.6875 0 -1.28125 0.359375q-0.59375 0.359375 -0.859375 1.0625q-0.25 0.703125 -0.25 2.03125l0 5.015625l-1.640625 0zm21.853302 -1.1875q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm4.2038574 -6.609375l0 -1.890625l1.640625 0l0 1.890625l-1.640625 0zm0 11.46875l0 -9.671875l1.640625 0l0 9.671875l-1.640625 0zm4.144806 0l0 -9.671875l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953125l-1.640625 0l0 -5.890625q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.28125l-1.640625 0zm15.512146 0l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm3.5823364 -4.84375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm8.688202 0q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm9.297607 8.546875l0 -13.375l1.484375 0l0 1.25q0.53125 -0.734375 1.1875 -1.09375q0.671875 -0.375 1.625 -0.375q1.234375 0 2.171875 0.640625q0.953125 0.625 1.4375 1.796875q0.484375 1.15625 0.484375 2.546875q0 1.484375 -0.53125 2.671875q-0.53125 1.1875 -1.546875 1.828125q-1.015625 0.625 -2.140625 0.625q-0.8125 0 -1.46875 -0.34375q-0.65625 -0.34375 -1.0625 -0.875l0 4.703125l-1.640625 0zm1.484375 -8.484375q0 1.859375 0.75 2.765625q0.765625 0.890625 1.828125 0.890625q1.09375 0 1.875 -0.921875q0.78125 -0.9375 0.78125 -2.875q0 -1.84375 -0.765625 -2.765625q-0.75 -0.921875 -1.8125 -0.921875q-1.046875 0 -1.859375 0.984375q-0.796875 0.96875 -0.796875 2.84375zm9.969452 8.703125l-1.1875 0q2.734375 -4.375 2.734375 -8.75q0 -1.71875 -0.390625 -3.390625q-0.3125 -1.375 -0.875 -2.625q-0.359375 -0.828125 -1.46875 -2.734375l1.1875 0q1.703125 2.28125 2.53125 4.59375q0.6875 1.984375 0.6875 4.140625q0 2.46875 -0.9375 4.765625q-0.9375 2.296875 -2.28125 4.0z" fill-rule="nonzero"/><path fill="#eeeeee" d="m157.13637 303.85385l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m157.13637 303.85385l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path fill="#eeeeee" d="m330.57175 297.29333l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m330.57175 297.29333l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path fill="#000000" d="m347.44937 362.1448l1.65625 -0.140625q0.125 1.0 0.546875 1.640625q0.4375 0.640625 1.34375 1.046875q0.921875 0.390625 2.0625 0.390625q1.0 0 1.78125 -0.296875q0.78125 -0.296875 1.15625 -0.8125q0.375 -0.53125 0.375 -1.15625q0 -0.625 -0.375 -1.09375q-0.359375 -0.46875 -1.1875 -0.796875q-0.546875 -0.203125 -2.390625 -0.640625q-1.828125 -0.453125 -2.5625 -0.84375q-0.96875 -0.5 -1.4375 -1.234375q-0.46875 -0.75 -0.46875 -1.671875q0 -1.0 0.578125 -1.875q0.578125 -0.890625 1.671875 -1.34375q1.109375 -0.453125 2.453125 -0.453125q1.484375 0 2.609375 0.484375q1.140625 0.46875 1.75 1.40625q0.609375 0.921875 0.65625 2.09375l-1.6875 0.125q-0.140625 -1.265625 -0.9375 -1.90625q-0.78125 -0.65625 -2.3125 -0.65625q-1.609375 0 -2.34375 0.59375q-0.734375 0.59375 -0.734375 1.421875q0 0.71875 0.53125 1.171875q0.5 0.46875 2.65625 0.96875q2.15625 0.484375 2.953125 0.84375q1.171875 0.53125 1.71875 1.359375q0.5625 0.828125 0.5625 1.90625q0 1.0625 -0.609375 2.015625q-0.609375 0.9375 -1.75 1.46875q-1.140625 0.515625 -2.578125 0.515625q-1.8125 0 -3.046875 -0.53125q-1.21875 -0.53125 -1.921875 -1.59375q-0.6875 -1.0625 -0.71875 -2.40625zm12.756073 8.015625l-0.1875 -1.53125q0.546875 0.140625 0.9375 0.140625q0.546875 0 0.875 -0.1875q0.328125 -0.171875 0.546875 -0.5q0.15625 -0.25 0.5 -1.21875q0.046875 -0.140625 0.140625 -0.40625l-3.671875 -9.6875l1.765625 0l2.015625 5.59375q0.390625 1.078125 0.703125 2.25q0.28125 -1.125 0.671875 -2.203125l2.078125 -5.640625l1.640625 0l-3.6875 9.828125q-0.59375 1.609375 -0.921875 2.203125q-0.4375 0.8125 -1.0 1.1875q-0.5625 0.375 -1.34375 0.375q-0.484375 0 -1.0625 -0.203125zm9.40625 -3.71875l0 -9.671875l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953125l-1.640625 0l0 -5.890625q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.28125l-1.640625 0zm16.688232 -3.546875l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609375q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.296875q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125z" fill-rule="nonzero"/><path fill="#000000" d="m345.54044 388.44168l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm16.162323 1.9375l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609375q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.296875q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm6.59375 2.078125l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm0.9958191 -3.375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm9.281952 4.84375l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0z" fill-rule="nonzero"/><path fill="#b6d7a8" d="m588.2104 201.05766l339.77954 0l0 223.81102l-339.77954 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m588.2104 201.05766l339.77954 0l0 223.81102l-339.77954 0z" fill-rule="evenodd"/><path fill="#000000" d="m602.05414 227.97766l0 -11.78125l-4.40625 0l0 -1.578125l10.578125 0l0 1.578125l-4.40625 0l0 11.78125l-1.765625 0zm7.786621 0l0 -13.359375l1.640625 0l0 4.796875q1.140625 -1.328125 2.890625 -1.328125q1.078125 0 1.859375 0.421875q0.796875 0.421875 1.140625 1.171875q0.34375 0.75 0.34375 2.171875l0 6.125l-1.640625 0l0 -6.125q0 -1.234375 -0.53125 -1.796875q-0.53125 -0.5625 -1.515625 -0.5625q-0.71875 0 -1.359375 0.390625q-0.640625 0.375 -0.921875 1.015625q-0.265625 0.640625 -0.265625 1.78125l0 5.296875l-1.640625 0zm10.360107 0l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm12.8532715 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm15.453857 4.578125q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm10.469482 4.859375l0 -1.21875q-0.90625 1.4375 -2.703125 1.4375q-1.15625 0 -2.125 -0.640625q-0.96875 -0.640625 -1.5 -1.78125q-0.53125 -1.140625 -0.53125 -2.625q0 -1.453125 0.484375 -2.625q0.484375 -1.1875 1.4375 -1.8125q0.96875 -0.625 2.171875 -0.625q0.875 0 1.546875 0.375q0.6875 0.359375 1.109375 0.953125l0 -4.796875l1.640625 0l0 13.359375l-1.53125 0zm-5.171875 -4.828125q0 1.859375 0.78125 2.78125q0.78125 0.921875 1.84375 0.921875q1.078125 0 1.828125 -0.875q0.75 -0.890625 0.75 -2.6875q0 -1.984375 -0.765625 -2.90625q-0.765625 -0.9375 -1.890625 -0.9375q-1.078125 0 -1.8125 0.890625q-0.734375 0.890625 -0.734375 2.8125zm14.465271 8.53125l0 -13.375l1.484375 0l0 1.25q0.53125 -0.734375 1.1875 -1.09375q0.671875 -0.375 1.625 -0.375q1.234375 0 2.171875 0.640625q0.953125 0.625 1.4375 1.796875q0.484375 1.15625 0.484375 2.546875q0 1.484375 -0.53125 2.671875q-0.53125 1.1875 -1.546875 1.828125q-1.015625 0.625 -2.140625 0.625q-0.8125 0 -1.46875 -0.34375q-0.65625 -0.34375 -1.0625 -0.875l0 4.703125l-1.640625 0zm1.484375 -8.484375q0 1.859375 0.75 2.765625q0.765625 0.890625 1.828125 0.890625q1.09375 0 1.875 -0.921875q0.78125 -0.9375 0.78125 -2.875q0 -1.84375 -0.765625 -2.765625q-0.75 -0.921875 -1.8125 -0.921875q-1.046875 0 -1.859375 0.984375q-0.796875 0.96875 -0.796875 2.84375zm8.281982 -0.0625q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm8.688171 0q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm9.250732 4.84375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0z" fill-rule="nonzero"/><path fill="#eeeeee" d="m602.03986 241.22713l73.543335 0l0 146.45671l-73.543335 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m602.03986 241.22713l73.543335 0l0 146.45671l-73.543335 0z" fill-rule="evenodd"/><path fill="#eeeeee" d="m682.0398 241.22713l73.543335 0l0 146.45671l-73.543335 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m682.0398 241.22713l73.543335 0l0 146.45671l-73.543335 0z" fill-rule="evenodd"/><path fill="#eeeeee" d="m836.3791 241.22713l73.543335 0l0 146.45671l-73.543335 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m836.3791 241.22713l73.543335 0l0 146.45671l-73.543335 0z" fill-rule="evenodd"/><path fill="#ffffff" d="m418.23727 497.07367l0 0c0 -3.745758 3.0365295 -6.7822876 6.7822876 -6.7822876l151.31729 0c1.7988281 0 3.5239258 0.7145691 4.7958374 1.9864807c1.2719116 1.2719421 1.9864502 2.9970398 1.9864502 4.795807l0 27.128357c0 3.7457275 -3.036499 6.7822876 -6.7822876 6.7822876l-151.31729 0c-3.745758 0 -6.7822876 -3.03656 -6.7822876 -6.7822876z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m418.23727 497.07367l0 0c0 -3.745758 3.0365295 -6.7822876 6.7822876 -6.7822876l151.31729 0c1.7988281 0 3.5239258 0.7145691 4.7958374 1.9864807c1.2719116 1.2719421 1.9864502 2.9970398 1.9864502 4.795807l0 27.128357c0 3.7457275 -3.036499 6.7822876 -6.7822876 6.7822876l-151.31729 0c-3.745758 0 -6.7822876 -3.03656 -6.7822876 -6.7822876z" fill-rule="evenodd"/><path fill="#000000" d="m431.7782 514.66724l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.9062805q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.45315552 2.4375 0.7500305q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm13.5625 1.421875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.5781555l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.6719055q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.917694 0.28125q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25003052q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875305q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm4.188202 4.859375l0 -9.6719055l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.9219055l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.5781555l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.6719055q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm0.9489441 -1.421875l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.9062805q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.45315552 2.4375 0.7500305q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm18.745789 1.421875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.5781555l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.6719055q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm1.6051941 1.46875l0 -13.3594055l1.640625 0l0 4.796875q1.140625 -1.328125 2.890625 -1.328125q1.078125 0 1.859375 0.421875q0.796875 0.421875 1.140625 1.171875q0.34375 0.75 0.34375 2.171875l0 6.1250305l-1.640625 0l0 -6.1250305q0 -1.234375 -0.53125 -1.796875q-0.53125 -0.5625 -1.515625 -0.5625q-0.71875 0 -1.359375 0.390625q-0.640625 0.375 -0.921875 1.015625q-0.265625 0.640625 -0.265625 1.7812805l0 5.296875l-1.640625 0zm10.360077 0l0 -9.6719055l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.9219055l0 5.0625l-1.625 0zm12.853302 -3.109375l1.6875305 0.203125q-0.40625 1.484375 -1.4844055 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.4531555 1.25 -3.7969055q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.1562805 1.328125q1.234375 1.3125 1.234375 3.7031555q0 0.15625 0 0.4375l-7.2187805 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.6562805l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm15.453827 4.5781555q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25003052q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875305q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm10.469482 4.859375l0 -1.21875q-0.90625 1.4375 -2.703125 1.4375q-1.15625 0 -2.125 -0.640625q-0.96875 -0.640625 -1.5 -1.78125q-0.53125 -1.140625 -0.53125 -2.625q0 -1.4531555 0.484375 -2.6250305q0.484375 -1.1875 1.4375 -1.8125q0.96875 -0.625 2.171875 -0.625q0.875 0 1.546875 0.375q0.6875 0.359375 1.109375 0.953125l0 -4.796875l1.640625 0l0 13.3594055l-1.53125 0zm-5.171875 -4.828125q0 1.859375 0.78125 2.78125q0.78125 0.921875 1.84375 0.921875q1.078125 0 1.828125 -0.875q0.75 -0.890625 0.75 -2.6875q0 -1.9844055 -0.765625 -2.9062805q-0.765625 -0.9375 -1.890625 -0.9375q-1.078125 0 -1.8125 0.890625q-0.734375 0.890625 -0.734375 2.8125305zm8.625732 1.9375l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.9062805q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.45315552 2.4375 0.7500305q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm14.558289 -1.953125q0 -2.6875305 1.484375 -3.9687805q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.6094055q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.7969055 -0.8125 -2.7187805q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.7656555zm9.297607 4.84375l0 -9.6719055l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.9531555l-1.640625 0l0 -5.8906555q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.5156555l0 5.28125l-1.640625 0z" fill-rule="nonzero"/><path fill="#ffff00" d="m786.2974 90.60562l0 0c0 -5.9490204 4.822632 -10.77166 10.7716675 -10.77166l18.178467 0l0 0l43.42517 0l90.55383 0c2.8568115 0 5.5966187 1.1348724 7.616699 3.1549454c2.0200806 2.0200806 3.1549683 4.7598877 3.1549683 7.6167145l0 26.92913l0 0l0 16.157478l0 0c0 5.9490204 -4.822693 10.771652 -10.7716675 10.771652l-90.55383 0l-30.37445 52.5506l-13.05072 -52.5506l-18.178467 0l0 0c-5.9490356 0 -10.7716675 -4.822632 -10.7716675 -10.771652l0 0l0 -16.157478l0 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m786.2974 90.60562l0 0c0 -5.9490204 4.822632 -10.77166 10.7716675 -10.77166l18.178467 0l0 0l43.42517 0l90.55383 0c2.8568115 0 5.5966187 1.1348724 7.616699 3.1549454c2.0200806 2.0200806 3.1549683 4.7598877 3.1549683 7.6167145l0 26.92913l0 0l0 16.157478l0 0c0 5.9490204 -4.822693 10.771652 -10.7716675 10.771652l-90.55383 0l-30.37445 52.5506l-13.05072 -52.5506l-18.178467 0l0 0c-5.9490356 0 -10.7716675 -4.822632 -10.7716675 -10.771652l0 0l0 -16.157478l0 0z" fill-rule="evenodd"/><path fill="#000000" d="m799.5461 92.94892l0 -9.546875l6.4375 0l0 1.125l-5.171875 0l0 2.96875l4.46875 0l0 1.125l-4.46875 0l0 4.328125l-1.265625 0zm7.9069824 0l0 -9.546875l1.171875 0l0 9.546875l-1.171875 0zm2.5391846 -3.453125q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm11.162476 2.59375q-0.65625 0.5625 -1.265625 0.796875q-0.59375 0.21875 -1.28125 0.21875q-1.140625 0 -1.75 -0.546875q-0.609375 -0.5625 -0.609375 -1.4375q0 -0.5 0.21875 -0.921875q0.234375 -0.421875 0.609375 -0.671875q0.375 -0.25 0.84375 -0.390625q0.34375 -0.078125 1.046875 -0.171875q1.421875 -0.171875 2.09375 -0.40625q0 -0.234375 0 -0.296875q0 -0.71875 -0.328125 -1.015625q-0.453125 -0.390625 -1.34375 -0.390625q-0.8125 0 -1.21875 0.296875q-0.390625 0.28125 -0.578125 1.015625l-1.140625 -0.15625q0.15625 -0.734375 0.515625 -1.1875q0.359375 -0.453125 1.03125 -0.6875q0.671875 -0.25 1.5625 -0.25q0.890625 0 1.4375 0.203125q0.5625 0.203125 0.8125 0.53125q0.265625 0.3125 0.375 0.796875q0.046875 0.296875 0.046875 1.078125l0 1.5625q0 1.625 0.078125 2.0625q0.078125 0.4375 0.296875 0.828125l-1.21875 0q-0.1875 -0.359375 -0.234375 -0.859375zm-0.09375 -2.609375q-0.640625 0.265625 -1.921875 0.4375q-0.71875 0.109375 -1.015625 0.25q-0.296875 0.125 -0.46875 0.375q-0.15625 0.25 -0.15625 0.546875q0 0.46875 0.34375 0.78125q0.359375 0.3125 1.046875 0.3125q0.671875 0 1.203125 -0.296875q0.53125 -0.296875 0.78125 -0.8125q0.1875 -0.390625 0.1875 -1.171875l0 -0.421875zm5.5531006 2.421875l0.171875 1.03125q-0.5 0.109375 -0.890625 0.109375q-0.640625 0 -1.0 -0.203125q-0.34375 -0.203125 -0.484375 -0.53125q-0.140625 -0.328125 -0.140625 -1.390625l0 -3.96875l-0.859375 0l0 -0.90625l0.859375 0l0 -1.71875l1.171875 -0.703125l0 2.421875l1.171875 0l0 0.90625l-1.171875 0l0 4.046875q0 0.5 0.046875 0.640625q0.0625 0.140625 0.203125 0.234375q0.140625 0.078125 0.40625 0.078125q0.203125 0 0.515625 -0.046875zm1.1561279 -7.140625l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm2.9454956 0l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm7.1937256 0.578125l1.140625 0.15625q0.078125 0.53125 0.40625 0.78125q0.4375 0.3125 1.1875 0.3125q0.8125 0 1.25 -0.328125q0.453125 -0.3125 0.609375 -0.90625q0.09375 -0.359375 0.078125 -1.5q-0.765625 0.90625 -1.90625 0.90625q-1.4375 0 -2.21875 -1.03125q-0.78125 -1.03125 -0.78125 -2.46875q0 -0.984375 0.359375 -1.8125q0.359375 -0.84375 1.03125 -1.296875q0.6875 -0.453125 1.609375 -0.453125q1.21875 0 2.015625 0.984375l0 -0.828125l1.078125 0l0 5.96875q0 1.609375 -0.328125 2.28125q-0.328125 0.6875 -1.046875 1.078125q-0.703125 0.390625 -1.75 0.390625q-1.234375 0 -2.0 -0.5625q-0.75 -0.5625 -0.734375 -1.671875zm0.984375 -4.15625q0 1.359375 0.53125 1.984375q0.546875 0.625 1.359375 0.625q0.796875 0 1.34375 -0.625q0.546875 -0.625 0.546875 -1.953125q0 -1.265625 -0.5625 -1.90625q-0.5625 -0.640625 -1.359375 -0.640625q-0.765625 0 -1.3125 0.640625q-0.546875 0.625 -0.546875 1.875zm14.8654175 1.046875l1.15625 0.15625q-0.1875 1.1875 -0.96875 1.859375q-0.78125 0.671875 -1.921875 0.671875q-1.40625 0 -2.28125 -0.921875q-0.859375 -0.9375 -0.859375 -2.65625q0 -1.125 0.375 -1.96875q0.375 -0.84375 1.125 -1.25q0.765625 -0.421875 1.65625 -0.421875q1.125 0 1.84375 0.578125q0.71875 0.5625 0.921875 1.609375l-1.140625 0.171875q-0.171875 -0.703125 -0.59375 -1.046875q-0.40625 -0.359375 -0.984375 -0.359375q-0.890625 0 -1.453125 0.640625q-0.546875 0.640625 -0.546875 2.0q0 1.40625 0.53125 2.03125q0.546875 0.625 1.40625 0.625q0.6875 0 1.140625 -0.421875q0.46875 -0.421875 0.59375 -1.296875zm1.7109375 -0.921875q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm6.6312256 3.453125l0 -6.90625l1.0625 0l0 1.046875q0.40625 -0.734375 0.734375 -0.96875q0.34375 -0.234375 0.765625 -0.234375q0.59375 0 1.203125 0.375l-0.40625 1.078125q-0.4375 -0.25 -0.859375 -0.25q-0.390625 0 -0.703125 0.234375q-0.296875 0.234375 -0.421875 0.640625q-0.203125 0.625 -0.203125 1.359375l0 3.625l-1.171875 0zm9.188416 -2.21875l1.203125 0.140625q-0.28125 1.0625 -1.0625 1.65625q-0.765625 0.578125 -1.96875 0.578125q-1.515625 0 -2.40625 -0.9375q-0.890625 -0.9375 -0.890625 -2.609375q0 -1.75 0.890625 -2.703125q0.90625 -0.96875 2.34375 -0.96875q1.390625 0 2.265625 0.9375q0.875 0.9375 0.875 2.65625q0 0.109375 0 0.3125l-5.15625 0q0.0625 1.140625 0.640625 1.75q0.578125 0.59375 1.4375 0.59375q0.65625 0 1.109375 -0.328125q0.453125 -0.34375 0.71875 -1.078125zm-3.84375 -1.90625l3.859375 0q-0.078125 -0.859375 -0.4375 -1.296875q-0.5625 -0.6875 -1.453125 -0.6875q-0.8125 0 -1.359375 0.546875q-0.546875 0.53125 -0.609375 1.4375zm6.0531006 2.0625l1.15625 -0.1875q0.109375 0.703125 0.546875 1.078125q0.453125 0.359375 1.25 0.359375q0.8125 0 1.203125 -0.328125q0.390625 -0.328125 0.390625 -0.765625q0 -0.390625 -0.359375 -0.625q-0.234375 -0.15625 -1.1875 -0.390625q-1.296875 -0.328125 -1.796875 -0.5625q-0.484375 -0.25 -0.75 -0.65625q-0.25 -0.421875 -0.25 -0.9375q0 -0.453125 0.203125 -0.84375q0.21875 -0.40625 0.578125 -0.671875q0.28125 -0.1875 0.75 -0.328125q0.46875 -0.140625 1.015625 -0.140625q0.8125 0 1.421875 0.234375q0.609375 0.234375 0.90625 0.640625q0.296875 0.390625 0.40625 1.0625l-1.140625 0.15625q-0.078125 -0.53125 -0.453125 -0.828125q-0.375 -0.3125 -1.0625 -0.3125q-0.8125 0 -1.15625 0.265625q-0.34375 0.265625 -0.34375 0.625q0 0.234375 0.140625 0.421875q0.15625 0.1875 0.453125 0.3125q0.171875 0.0625 1.03125 0.296875q1.25 0.328125 1.734375 0.546875q0.5 0.203125 0.78125 0.609375q0.28125 0.40625 0.28125 1.0q0 0.59375 -0.34375 1.109375q-0.34375 0.515625 -1.0 0.796875q-0.640625 0.28125 -1.453125 0.28125q-1.34375 0 -2.046875 -0.5625q-0.703125 -0.5625 -0.90625 -1.65625zm13.085754 4.875q-0.984375 -1.234375 -1.65625 -2.875q-0.65625 -1.640625 -0.65625 -3.390625q0 -1.546875 0.5 -2.96875q0.578125 -1.640625 1.8125 -3.28125l0.828125 0q-0.78125 1.359375 -1.03125 1.9375q-0.40625 0.890625 -0.625 1.875q-0.28125 1.21875 -0.28125 2.4375q0 3.140625 1.9375 6.265625l-0.828125 0zm2.1884155 -2.8125l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm6.9749756 -3.453125q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375z" fill-rule="nonzero"/><path fill="#000000" d="m803.84296 108.08955q-0.65625 0.5625 -1.265625 0.796875q-0.59375 0.21875 -1.28125 0.21875q-1.140625 0 -1.75 -0.546875q-0.609375 -0.5625 -0.609375 -1.4375q0 -0.5 0.21875 -0.921875q0.234375 -0.421875 0.609375 -0.671875q0.375 -0.25 0.84375 -0.390625q0.34375 -0.078125 1.046875 -0.171875q1.421875 -0.171875 2.09375 -0.40625q0 -0.234375 0 -0.296875q0 -0.71875 -0.328125 -1.015625q-0.453125 -0.390625 -1.34375 -0.390625q-0.8125 0 -1.21875 0.296875q-0.390625 0.28125 -0.578125 1.015625l-1.140625 -0.15625q0.15625 -0.734375 0.515625 -1.1875q0.359375 -0.453125 1.03125 -0.6875q0.671875 -0.25 1.5625 -0.25q0.890625 0 1.4375 0.203125q0.5625 0.203125 0.8125 0.53125q0.265625 0.3125 0.375 0.796875q0.046875 0.296875 0.046875 1.078125l0 1.5625q0 1.625 0.078125 2.0625q0.078125 0.4375 0.296875 0.828125l-1.21875 0q-0.1875 -0.359375 -0.234375 -0.859375zm-0.09375 -2.609375q-0.640625 0.265625 -1.921875 0.4375q-0.71875 0.109375 -1.015625 0.25q-0.296875 0.125 -0.46875 0.375q-0.15625 0.25 -0.15625 0.546875q0 0.46875 0.34375 0.78125q0.359375 0.3125 1.046875 0.3125q0.671875 0 1.203125 -0.296875q0.53125 -0.296875 0.78125 -0.8125q0.1875 -0.390625 0.1875 -1.171875l0 -0.421875zm3.2718506 3.46875l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm3.4620972 0l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm3.437378 -8.1875l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm2.9454346 0l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm7.4281006 -8.1875l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm5.5079956 -1.046875l0.171875 1.03125q-0.5 0.109375 -0.890625 0.109375q-0.640625 0 -1.0 -0.203125q-0.34375 -0.203125 -0.484375 -0.53125q-0.140625 -0.328125 -0.140625 -1.390625l0 -3.96875l-0.859375 0l0 -0.90625l0.859375 0l0 -1.71875l1.171875 -0.703125l0 2.421875l1.171875 0l0 0.90625l-1.171875 0l0 4.046875q0 0.5 0.046875 0.640625q0.0625 0.140625 0.203125 0.234375q0.140625 0.078125 0.40625 0.078125q0.203125 0 0.515625 -0.046875zm1.0935669 3.703125l-0.125 -1.09375q0.375 0.109375 0.65625 0.109375q0.390625 0 0.625 -0.140625q0.234375 -0.125 0.390625 -0.359375q0.109375 -0.171875 0.359375 -0.875q0.03125 -0.09375 0.109375 -0.28125l-2.625 -6.921875l1.265625 0l1.4375 4.0q0.28125 0.765625 0.5 1.59375q0.203125 -0.796875 0.46875 -1.578125l1.484375 -4.015625l1.171875 0l-2.625 7.015625q-0.421875 1.140625 -0.65625 1.578125q-0.3125 0.578125 -0.71875 0.84375q-0.40625 0.28125 -0.96875 0.28125q-0.328125 0 -0.75 -0.15625zm7.4765625 0.15625l-0.828125 0q1.9375 -3.125 1.9375 -6.265625q0 -1.21875 -0.28125 -2.421875q-0.21875 -0.984375 -0.609375 -1.875q-0.265625 -0.59375 -1.046875 -1.953125l0.828125 0q1.234375 1.640625 1.8125 3.28125q0.5 1.421875 0.5 2.96875q0 1.75 -0.671875 3.390625q-0.671875 1.640625 -1.640625 2.875zm6.9382324 -6.265625q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm6.6312256 3.453125l0 -6.90625l1.0625 0l0 1.046875q0.40625 -0.734375 0.734375 -0.96875q0.34375 -0.234375 0.765625 -0.234375q0.59375 0 1.203125 0.375l-0.40625 1.078125q-0.4375 -0.25 -0.859375 -0.25q-0.390625 0 -0.703125 0.234375q-0.296875 0.234375 -0.421875 0.640625q-0.203125 0.625 -0.203125 1.359375l0 3.625l-1.171875 0zm12.672607 -0.859375q-0.65625 0.5625 -1.265625 0.796875q-0.59375 0.21875 -1.28125 0.21875q-1.140625 0 -1.75 -0.546875q-0.609375 -0.5625 -0.609375 -1.4375q0 -0.5 0.21875 -0.921875q0.234375 -0.421875 0.609375 -0.671875q0.375 -0.25 0.84375 -0.390625q0.34375 -0.078125 1.046875 -0.171875q1.421875 -0.171875 2.09375 -0.40625q0 -0.234375 0 -0.296875q0 -0.71875 -0.328125 -1.015625q-0.453125 -0.390625 -1.34375 -0.390625q-0.8125 0 -1.21875 0.296875q-0.390625 0.28125 -0.578125 1.015625l-1.140625 -0.15625q0.15625 -0.734375 0.515625 -1.1875q0.359375 -0.453125 1.03125 -0.6875q0.671875 -0.25 1.5625 -0.25q0.890625 0 1.4375 0.203125q0.5625 0.203125 0.8125 0.53125q0.265625 0.3125 0.375 0.796875q0.046875 0.296875 0.046875 1.078125l0 1.5625q0 1.625 0.078125 2.0625q0.078125 0.4375 0.296875 0.828125l-1.21875 0q-0.1875 -0.359375 -0.234375 -0.859375zm-0.09375 -2.609375q-0.640625 0.265625 -1.921875 0.4375q-0.71875 0.109375 -1.015625 0.25q-0.296875 0.125 -0.46875 0.375q-0.15625 0.25 -0.15625 0.546875q0 0.46875 0.34375 0.78125q0.359375 0.3125 1.046875 0.3125q0.671875 0 1.203125 -0.296875q0.53125 -0.296875 0.78125 -0.8125q0.1875 -0.390625 0.1875 -1.171875l0 -0.421875zm3.2718506 3.46875l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm3.4620972 0l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm3.437378 -8.1875l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm2.9454956 0l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm7.4281006 -8.1875l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm5.5079346 -1.046875l0.171875 1.03125q-0.5 0.109375 -0.890625 0.109375q-0.640625 0 -1.0 -0.203125q-0.34375 -0.203125 -0.484375 -0.53125q-0.140625 -0.328125 -0.140625 -1.390625l0 -3.96875l-0.859375 0l0 -0.90625l0.859375 0l0 -1.71875l1.171875 -0.703125l0 2.421875l1.171875 0l0 0.90625l-1.171875 0l0 4.046875q0 0.5 0.046875 0.640625q0.0625 0.140625 0.203125 0.234375q0.140625 0.078125 0.40625 0.078125q0.203125 0 0.515625 -0.046875zm1.0936279 3.703125l-0.125 -1.09375q0.375 0.109375 0.65625 0.109375q0.390625 0 0.625 -0.140625q0.234375 -0.125 0.390625 -0.359375q0.109375 -0.171875 0.359375 -0.875q0.03125 -0.09375 0.109375 -0.28125l-2.625 -6.921875l1.265625 0l1.4375 4.0q0.28125 0.765625 0.5 1.59375q0.203125 -0.796875 0.46875 -1.578125l1.484375 -4.015625l1.171875 0l-2.625 7.015625q-0.421875 1.140625 -0.65625 1.578125q-0.3125 0.578125 -0.71875 0.84375q-0.40625 0.28125 -0.96875 0.28125q-0.328125 0 -0.75 -0.15625z" fill-rule="nonzero"/><path fill="#000000" d="m803.8117 124.94893l0 -0.875q-0.65625 1.03125 -1.9375 1.03125q-0.8125 0 -1.515625 -0.453125q-0.6875 -0.453125 -1.078125 -1.265625q-0.375 -0.828125 -0.375 -1.890625q0 -1.03125 0.34375 -1.875q0.34375 -0.84375 1.03125 -1.28125q0.703125 -0.453125 1.546875 -0.453125q0.625 0 1.109375 0.265625q0.5 0.25 0.796875 0.671875l0 -3.421875l1.171875 0l0 9.546875l-1.09375 0zm-3.703125 -3.453125q0 1.328125 0.5625 1.984375q0.5625 0.65625 1.328125 0.65625q0.765625 0 1.296875 -0.625q0.53125 -0.625 0.53125 -1.90625q0 -1.421875 -0.546875 -2.078125q-0.546875 -0.671875 -1.34375 -0.671875q-0.78125 0 -1.3125 0.640625q-0.515625 0.625 -0.515625 2.0zm11.365601 1.234375l1.203125 0.140625q-0.28125 1.0625 -1.0625 1.65625q-0.765625 0.578125 -1.96875 0.578125q-1.515625 0 -2.40625 -0.9375q-0.890625 -0.9375 -0.890625 -2.609375q0 -1.75 0.890625 -2.703125q0.90625 -0.96875 2.34375 -0.96875q1.390625 0 2.265625 0.9375q0.875 0.9375 0.875 2.65625q0 0.109375 0 0.3125l-5.15625 0q0.0625 1.140625 0.640625 1.75q0.578125 0.59375 1.4375 0.59375q0.65625 0 1.109375 -0.328125q0.453125 -0.34375 0.71875 -1.078125zm-3.84375 -1.90625l3.859375 0q-0.078125 -0.859375 -0.4375 -1.296875q-0.5625 -0.6875 -1.453125 -0.6875q-0.8125 0 -1.359375 0.546875q-0.546875 0.53125 -0.609375 1.4375zm6.5218506 6.78125l0 -9.5625l1.078125 0l0 0.890625q0.375 -0.53125 0.84375 -0.78125q0.484375 -0.265625 1.15625 -0.265625q0.875 0 1.546875 0.453125q0.6875 0.453125 1.03125 1.28125q0.34375 0.828125 0.34375 1.828125q0 1.046875 -0.375 1.90625q-0.375 0.84375 -1.109375 1.296875q-0.71875 0.453125 -1.53125 0.453125q-0.578125 0 -1.046875 -0.25q-0.46875 -0.25 -0.765625 -0.625l0 3.375l-1.171875 0zm1.0625 -6.078125q0 1.34375 0.53125 1.984375q0.546875 0.625 1.3125 0.625q0.78125 0 1.34375 -0.65625q0.5625 -0.65625 0.5625 -2.046875q0 -1.3125 -0.546875 -1.96875q-0.546875 -0.671875 -1.296875 -0.671875q-0.75 0 -1.328125 0.703125q-0.578125 0.703125 -0.578125 2.03125zm11.084351 1.203125l1.203125 0.140625q-0.28125 1.0625 -1.0625 1.65625q-0.765625 0.578125 -1.96875 0.578125q-1.515625 0 -2.40625 -0.9375q-0.890625 -0.9375 -0.890625 -2.609375q0 -1.75 0.890625 -2.703125q0.90625 -0.96875 2.34375 -0.96875q1.390625 0 2.265625 0.9375q0.875 0.9375 0.875 2.65625q0 0.109375 0 0.3125l-5.15625 0q0.0625 1.140625 0.640625 1.75q0.578125 0.59375 1.4375 0.59375q0.65625 0 1.109375 -0.328125q0.453125 -0.34375 0.71875 -1.078125zm-3.84375 -1.90625l3.859375 0q-0.078125 -0.859375 -0.4375 -1.296875q-0.5625 -0.6875 -1.453125 -0.6875q-0.8125 0 -1.359375 0.546875q-0.546875 0.53125 -0.609375 1.4375zm6.5218506 4.125l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm11.896851 0l0 -0.875q-0.65625 1.03125 -1.9375 1.03125q-0.8125 0 -1.515625 -0.453125q-0.6875 -0.453125 -1.078125 -1.265625q-0.375 -0.828125 -0.375 -1.890625q0 -1.03125 0.34375 -1.875q0.34375 -0.84375 1.03125 -1.28125q0.703125 -0.453125 1.546875 -0.453125q0.625 0 1.109375 0.265625q0.5 0.25 0.796875 0.671875l0 -3.421875l1.171875 0l0 9.546875l-1.09375 0zm-3.703125 -3.453125q0 1.328125 0.5625 1.984375q0.5625 0.65625 1.328125 0.65625q0.765625 0 1.296875 -0.625q0.53125 -0.625 0.53125 -1.90625q0 -1.421875 -0.546875 -2.078125q-0.546875 -0.671875 -1.34375 -0.671875q-0.78125 0 -1.3125 0.640625q-0.515625 0.625 -0.515625 2.0zm6.6468506 -4.734375l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm2.9454346 0l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm7.1937256 0.578125l1.140625 0.15625q0.078125 0.53125 0.40625 0.78125q0.4375 0.3125 1.1875 0.3125q0.8125 0 1.25 -0.328125q0.453125 -0.3125 0.609375 -0.90625q0.09375 -0.359375 0.078125 -1.5q-0.765625 0.90625 -1.90625 0.90625q-1.4375 0 -2.21875 -1.03125q-0.78125 -1.03125 -0.78125 -2.46875q0 -0.984375 0.359375 -1.8125q0.359375 -0.84375 1.03125 -1.296875q0.6875 -0.453125 1.609375 -0.453125q1.21875 0 2.015625 0.984375l0 -0.828125l1.078125 0l0 5.96875q0 1.609375 -0.328125 2.28125q-0.328125 0.6875 -1.046875 1.078125q-0.703125 0.390625 -1.75 0.390625q-1.234375 0 -2.0 -0.5625q-0.75 -0.5625 -0.734375 -1.671875zm0.984375 -4.15625q0 1.359375 0.53125 1.984375q0.546875 0.625 1.359375 0.625q0.796875 0 1.34375 -0.625q0.546875 -0.625 0.546875 -1.953125q0 -1.265625 -0.5625 -1.90625q-0.5625 -0.640625 -1.359375 -0.640625q-0.765625 0 -1.3125 0.640625q-0.546875 0.625 -0.546875 1.875zm9.9123535 0.125q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm6.6468506 3.453125l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0z" fill-rule="nonzero"/><path fill="#000000" d="m803.84296 138.41768l1.15625 0.15625q-0.1875 1.1875 -0.96875 1.859375q-0.78125 0.671875 -1.921875 0.671875q-1.40625 0 -2.28125 -0.921875q-0.859375 -0.9375 -0.859375 -2.65625q0 -1.125 0.375 -1.96875q0.375 -0.84375 1.125 -1.25q0.765625 -0.421875 1.65625 -0.421875q1.125 0 1.84375 0.578125q0.71875 0.5625 0.921875 1.609375l-1.140625 0.171875q-0.171875 -0.703125 -0.59375 -1.046875q-0.40625 -0.359375 -0.984375 -0.359375q-0.890625 0 -1.453125 0.640625q-0.546875 0.640625 -0.546875 2.0q0 1.40625 0.53125 2.03125q0.546875 0.625 1.40625 0.625q0.6875 0 1.140625 -0.421875q0.46875 -0.421875 0.59375 -1.296875zm1.7109375 -0.921875q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm6.6468506 3.453125l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm7.6937256 0l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm3.437378 -8.1875l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm2.7266846 0.578125l1.140625 0.15625q0.078125 0.53125 0.40625 0.78125q0.4375 0.3125 1.1875 0.3125q0.8125 0 1.25 -0.328125q0.453125 -0.3125 0.609375 -0.90625q0.09375 -0.359375 0.078125 -1.5q-0.765625 0.90625 -1.90625 0.90625q-1.4375 0 -2.21875 -1.03125q-0.78125 -1.03125 -0.78125 -2.46875q0 -0.984375 0.359375 -1.8125q0.359375 -0.84375 1.03125 -1.296875q0.6875 -0.453125 1.609375 -0.453125q1.21875 0 2.015625 0.984375l0 -0.828125l1.078125 0l0 5.96875q0 1.609375 -0.328125 2.28125q-0.328125 0.6875 -1.046875 1.078125q-0.703125 0.390625 -1.75 0.390625q-1.234375 0 -2.0 -0.5625q-0.75 -0.5625 -0.734375 -1.671875zm0.984375 -4.15625q0 1.359375 0.53125 1.984375q0.546875 0.625 1.359375 0.625q0.796875 0 1.34375 -0.625q0.546875 -0.625 0.546875 -1.953125q0 -1.265625 -0.5625 -1.90625q-0.5625 -0.640625 -1.359375 -0.640625q-0.765625 0 -1.3125 0.640625q-0.546875 0.625 -0.546875 1.875zm11.178101 3.578125l0 -1.015625q-0.8125 1.171875 -2.1875 1.171875q-0.609375 0 -1.140625 -0.234375q-0.53125 -0.234375 -0.796875 -0.578125q-0.25 -0.359375 -0.359375 -0.875q-0.0625 -0.34375 -0.0625 -1.09375l0 -4.28125l1.171875 0l0 3.828125q0 0.921875 0.0625 1.234375q0.109375 0.46875 0.46875 0.734375q0.359375 0.25 0.890625 0.25q0.515625 0 0.984375 -0.265625q0.46875 -0.265625 0.65625 -0.734375q0.1875 -0.46875 0.1875 -1.34375l0 -3.703125l1.171875 0l0 6.90625l-1.046875 0zm2.8656006 0l0 -6.90625l1.0625 0l0 1.046875q0.40625 -0.734375 0.734375 -0.96875q0.34375 -0.234375 0.765625 -0.234375q0.59375 0 1.203125 0.375l-0.40625 1.078125q-0.4375 -0.25 -0.859375 -0.25q-0.390625 0 -0.703125 0.234375q-0.296875 0.234375 -0.421875 0.640625q-0.203125 0.625 -0.203125 1.359375l0 3.625l-1.171875 0zm8.9696045 -0.859375q-0.65625 0.5625 -1.265625 0.796875q-0.59375 0.21875 -1.28125 0.21875q-1.140625 0 -1.75 -0.546875q-0.609375 -0.5625 -0.609375 -1.4375q0 -0.5 0.21875 -0.921875q0.234375 -0.421875 0.609375 -0.671875q0.375 -0.25 0.84375 -0.390625q0.34375 -0.078125 1.046875 -0.171875q1.421875 -0.171875 2.09375 -0.40625q0 -0.234375 0 -0.296875q0 -0.71875 -0.328125 -1.015625q-0.453125 -0.390625 -1.34375 -0.390625q-0.8125 0 -1.21875 0.296875q-0.390625 0.28125 -0.578125 1.015625l-1.140625 -0.15625q0.15625 -0.734375 0.515625 -1.1875q0.359375 -0.453125 1.03125 -0.6875q0.671875 -0.25 1.5625 -0.25q0.890625 0 1.4375 0.203125q0.5625 0.203125 0.8125 0.53125q0.265625 0.3125 0.375 0.796875q0.046875 0.296875 0.046875 1.078125l0 1.5625q0 1.625 0.078125 2.0625q0.078125 0.4375 0.296875 0.828125l-1.21875 0q-0.1875 -0.359375 -0.234375 -0.859375zm-0.09375 -2.609375q-0.640625 0.265625 -1.921875 0.4375q-0.71875 0.109375 -1.015625 0.25q-0.296875 0.125 -0.46875 0.375q-0.15625 0.25 -0.15625 0.546875q0 0.46875 0.34375 0.78125q0.359375 0.3125 1.046875 0.3125q0.671875 0 1.203125 -0.296875q0.53125 -0.296875 0.78125 -0.8125q0.1875 -0.390625 0.1875 -1.171875l0 -0.421875zm5.5531006 2.421875l0.171875 1.03125q-0.5 0.109375 -0.890625 0.109375q-0.640625 0 -1.0 -0.203125q-0.34375 -0.203125 -0.484375 -0.53125q-0.140625 -0.328125 -0.140625 -1.390625l0 -3.96875l-0.859375 0l0 -0.90625l0.859375 0l0 -1.71875l1.171875 -0.703125l0 2.421875l1.171875 0l0 0.90625l-1.171875 0l0 4.046875q0 0.5 0.046875 0.640625q0.0625 0.140625 0.203125 0.234375q0.140625 0.078125 0.40625 0.078125q0.203125 0 0.515625 -0.046875zm0.7030029 -2.40625q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm6.6468506 3.453125l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0z" fill-rule="nonzero"/><path fill="#ffff00" d="m46.449535 255.23361l0 0c0 -6.4099884 5.196316 -11.606293 11.606297 -11.606293l38.679794 0l0 0l21.551178 0l2.7611542 0c3.078186 0 6.0302887 1.2227936 8.206894 3.3993988c2.1766052 2.1766052 3.3993988 5.128708 3.3993988 8.206894l0 29.015747l0 0l0 17.409454l0 0c0 6.409973 -5.196312 11.606293 -11.606293 11.606293l-2.7611542 0l40.169388 23.479767l-61.720566 -23.479767l-38.679794 0l0 0c-6.409981 0 -11.606297 -5.1963196 -11.606297 -11.606293l0 0l0 -17.409454l0 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m46.449535 255.23361l0 0c0 -6.4099884 5.196316 -11.606293 11.606297 -11.606293l38.679794 0l0 0l21.551178 0l2.7611542 0c3.078186 0 6.0302887 1.2227936 8.206894 3.3993988c2.1766052 2.1766052 3.3993988 5.128708 3.3993988 8.206894l0 29.015747l0 0l0 17.409454l0 0c0 6.409973 -5.196312 11.606293 -11.606293 11.606293l-2.7611542 0l40.169388 23.479767l-61.720566 -23.479767l-38.679794 0l0 0c-6.409981 0 -11.606297 -5.1963196 -11.606297 -11.606293l0 0l0 -17.409454l0 0z" fill-rule="evenodd"/><path fill="#000000" d="m59.86453 275.24622l0 -9.546875l1.296875 0l5.015621 7.5l0 -7.5l1.203125 0l0 9.546875l-1.296875 0l-5.015621 -7.5l0 7.5l-1.203125 0zm9.047024 -3.453125q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm14.865463 2.59375q-0.65625 0.5625 -1.265625 0.796875q-0.59375 0.21875 -1.28125 0.21875q-1.140625 0 -1.75 -0.546875q-0.609375 -0.5625 -0.609375 -1.4375q0 -0.5 0.21875 -0.921875q0.234375 -0.421875 0.609375 -0.671875q0.375 -0.25 0.84375 -0.390625q0.34375 -0.078125 1.046875 -0.171875q1.421875 -0.171875 2.09375 -0.40625q0 -0.234375 0 -0.296875q0 -0.71875 -0.328125 -1.015625q-0.453125 -0.390625 -1.34375 -0.390625q-0.8125 0 -1.21875 0.296875q-0.390625 0.28125 -0.578125 1.015625l-1.140625 -0.15625q0.15625 -0.734375 0.515625 -1.1875q0.359375 -0.453125 1.03125 -0.6875q0.671875 -0.25 1.5625 -0.25q0.890625 0 1.4375 0.203125q0.5625 0.203125 0.8125 0.53125q0.265625 0.3125 0.375 0.796875q0.046875 0.296875 0.046875 1.078125l0 1.5625q0 1.625 0.078125 2.0625q0.078125 0.4375 0.296875 0.828125l-1.21875 0q-0.1875 -0.359375 -0.234375 -0.859375zm-0.09375 -2.609375q-0.640625 0.265625 -1.921875 0.4375q-0.71875 0.109375 -1.015625 0.25q-0.296875 0.125 -0.46875 0.375q-0.15625 0.25 -0.15625 0.546875q0 0.46875 0.34375 0.78125q0.359375 0.3125 1.046875 0.3125q0.671875 0 1.203125 -0.296875q0.53125 -0.296875 0.78125 -0.8125q0.1875 -0.390625 0.1875 -1.171875l0 -0.421875zm3.2718506 3.46875l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm3.4620972 0l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm3.4373627 -8.1875l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm2.945465 0l0 -6.90625l1.0625 0l0 0.984375q0.75 -1.140625 2.1875 -1.140625q0.625 0 1.15625 0.21875q0.53125 0.21875 0.78125 0.59375q0.265625 0.359375 0.375 0.859375q0.0625 0.328125 0.0625 1.140625l0 4.25l-1.171875 0l0 -4.203125q0 -0.71875 -0.140625 -1.0625q-0.140625 -0.359375 -0.484375 -0.5625q-0.34375 -0.21875 -0.8125 -0.21875q-0.75 0 -1.296875 0.46875q-0.546875 0.46875 -0.546875 1.796875l0 3.78125l-1.171875 0zm7.4281006 -8.1875l0 -1.359375l1.171875 0l0 1.359375l-1.171875 0zm0 8.1875l0 -6.90625l1.171875 0l0 6.90625l-1.171875 0zm5.507965 -1.046875l0.171875 1.03125q-0.5 0.109375 -0.890625 0.109375q-0.640625 0 -1.0 -0.203125q-0.34375 -0.203125 -0.484375 -0.53125q-0.140625 -0.328125 -0.140625 -1.390625l0 -3.96875l-0.859375 0l0 -0.90625l0.859375 0l0 -1.71875l1.171875 -0.703125l0 2.421875l1.171875 0l0 0.90625l-1.171875 0l0 4.046875q0 0.5 0.046875 0.640625q0.0625 0.140625 0.203125 0.234375q0.140625 0.078125 0.40625 0.078125q0.203125 0 0.515625 -0.046875zm1.0936127 3.703125l-0.125 -1.09375q0.375 0.109375 0.65625 0.109375q0.390625 0 0.625 -0.140625q0.234375 -0.125 0.390625 -0.359375q0.109375 -0.171875 0.359375 -0.875q0.03125 -0.09375 0.109375 -0.28125l-2.625 -6.921875l1.265625 0l1.4375 4.0q0.28125 0.765625 0.5 1.59375q0.203125 -0.796875 0.46875 -1.578125l1.484375 -4.015625l1.171875 0l-2.625 7.015625q-0.421875 1.140625 -0.65625 1.578125q-0.3125 0.578125 -0.71875 0.84375q-0.40625 0.28125 -0.96875 0.28125q-0.328125 0 -0.75 -0.15625z" fill-rule="nonzero"/><path fill="#000000" d="m60.005154 291.24622l0 -6.0l-1.03125 0l0 -0.90625l1.03125 0l0 -0.734375q0 -0.703125 0.125 -1.046875q0.171875 -0.453125 0.59375 -0.734375q0.421875 -0.28125 1.203125 -0.28125q0.484375 0 1.09375 0.109375l-0.1875 1.03125q-0.359375 -0.0625 -0.6875 -0.0625q-0.53125 0 -0.75 0.234375q-0.21875 0.21875 -0.21875 0.84375l0 0.640625l1.34375 0l0 0.90625l-1.34375 0l0 6.0l-1.171875 0zm2.9842377 -3.453125q0 -1.921875 1.0781212 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.3593712 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.2031212 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm6.6312256 3.453125l0 -6.90625l1.0625 0l0 1.046875q0.40625 -0.734375 0.734375 -0.96875q0.34375 -0.234375 0.765625 -0.234375q0.59375 0 1.203125 0.375l-0.40625 1.078125q-0.4375 -0.25 -0.859375 -0.25q-0.390625 0 -0.703125 0.234375q-0.296875 0.234375 -0.421875 0.640625q-0.203125 0.625 -0.203125 1.359375l0 3.625l-1.171875 0zm12.672607 -0.859375q-0.65625 0.5625 -1.265625 0.796875q-0.59375 0.21875 -1.28125 0.21875q-1.140625 0 -1.75 -0.546875q-0.609375 -0.5625 -0.609375 -1.4375q0 -0.5 0.21875 -0.921875q0.234375 -0.421875 0.609375 -0.671875q0.375 -0.25 0.84375 -0.390625q0.34375 -0.078125 1.046875 -0.171875q1.421875 -0.171875 2.09375 -0.40625q0 -0.234375 0 -0.296875q0 -0.71875 -0.328125 -1.015625q-0.453125 -0.390625 -1.34375 -0.390625q-0.8125 0 -1.21875 0.296875q-0.390625 0.28125 -0.578125 1.015625l-1.140625 -0.15625q0.15625 -0.734375 0.515625 -1.1875q0.359375 -0.453125 1.03125 -0.6875q0.671875 -0.25 1.5625 -0.25q0.890625 0 1.4375 0.203125q0.5625 0.203125 0.8125 0.53125q0.265625 0.3125 0.375 0.796875q0.046875 0.296875 0.046875 1.078125l0 1.5625q0 1.625 0.078125 2.0625q0.078125 0.4375 0.296875 0.828125l-1.21875 0q-0.1875 -0.359375 -0.234375 -0.859375zm-0.09375 -2.609375q-0.640625 0.265625 -1.921875 0.4375q-0.71875 0.109375 -1.015625 0.25q-0.296875 0.125 -0.46875 0.375q-0.15625 0.25 -0.15625 0.546875q0 0.46875 0.34375 0.78125q0.359375 0.3125 1.046875 0.3125q0.671875 0 1.203125 -0.296875q0.53125 -0.296875 0.78125 -0.8125q0.1875 -0.390625 0.1875 -1.171875l0 -0.421875zm7.5062256 0.9375l1.15625 0.15625q-0.1875 1.1875 -0.96875 1.859375q-0.78125 0.671875 -1.921875 0.671875q-1.40625 0 -2.28125 -0.921875q-0.859375 -0.9375 -0.859375 -2.65625q0 -1.125 0.375 -1.96875q0.375 -0.84375 1.125 -1.25q0.765625 -0.421875 1.65625 -0.421875q1.125 0 1.84375 0.578125q0.71875 0.5625 0.921875 1.609375l-1.140625 0.171875q-0.171875 -0.703125 -0.59375 -1.046875q-0.40625 -0.359375 -0.984375 -0.359375q-0.890625 0 -1.453125 0.640625q-0.546875 0.640625 -0.546875 2.0q0 1.40625 0.53125 2.03125q0.546875 0.625 1.40625 0.625q0.6875 0 1.140625 -0.421875q0.46875 -0.421875 0.59375 -1.296875zm4.7109375 1.484375l0.171875 1.03125q-0.5 0.109375 -0.890625 0.109375q-0.640625 0 -1.0 -0.203125q-0.34375 -0.203125 -0.484375 -0.53125q-0.140625 -0.328125 -0.140625 -1.390625l0 -3.96875l-0.859375 0l0 -0.90625l0.859375 0l0 -1.71875l1.171875 -0.703125l0 2.421875l1.171875 0l0 0.90625l-1.171875 0l0 4.046875q0 0.5 0.046875 0.640625q0.0625 0.140625 0.203125 0.234375q0.140625 0.078125 0.40625 0.078125q0.203125 0 0.515625 -0.046875zm0.7029877 -2.40625q0 -1.921875 1.078125 -2.84375q0.890625 -0.765625 2.171875 -0.765625q1.421875 0 2.328125 0.9375q0.90625 0.921875 0.90625 2.578125q0 1.328125 -0.40625 2.09375q-0.390625 0.765625 -1.15625 1.1875q-0.765625 0.421875 -1.671875 0.421875q-1.453125 0 -2.359375 -0.921875q-0.890625 -0.9375 -0.890625 -2.6875zm1.203125 0q0 1.328125 0.578125 1.984375q0.59375 0.65625 1.46875 0.65625q0.875 0 1.453125 -0.65625q0.578125 -0.671875 0.578125 -2.03125q0 -1.28125 -0.59375 -1.9375q-0.578125 -0.65625 -1.4375 -0.65625q-0.875 0 -1.46875 0.65625q-0.578125 0.65625 -0.578125 1.984375zm6.6312256 3.453125l0 -6.90625l1.0625 0l0 1.046875q0.40625 -0.734375 0.734375 -0.96875q0.34375 -0.234375 0.765625 -0.234375q0.59375 0 1.203125 0.375l-0.40625 1.078125q-0.4375 -0.25 -0.859375 -0.25q-0.390625 0 -0.703125 0.234375q-0.296875 0.234375 -0.421875 0.640625q-0.203125 0.625 -0.203125 1.359375l0 3.625l-1.171875 0zm3.9852448 -2.0625l1.15625 -0.1875q0.109375 0.703125 0.546875 1.078125q0.453125 0.359375 1.25 0.359375q0.8125 0 1.203125 -0.328125q0.390625 -0.328125 0.390625 -0.765625q0 -0.390625 -0.359375 -0.625q-0.234375 -0.15625 -1.1875 -0.390625q-1.296875 -0.328125 -1.796875 -0.5625q-0.484375 -0.25 -0.75 -0.65625q-0.25 -0.421875 -0.25 -0.9375q0 -0.453125 0.203125 -0.84375q0.21875 -0.40625 0.578125 -0.671875q0.28125 -0.1875 0.75 -0.328125q0.46875 -0.140625 1.015625 -0.140625q0.8125 0 1.421875 0.234375q0.609375 0.234375 0.90625 0.640625q0.296875 0.390625 0.40625 1.0625l-1.140625 0.15625q-0.078125 -0.53125 -0.453125 -0.828125q-0.375 -0.3125 -1.0625 -0.3125q-0.8125 0 -1.15625 0.265625q-0.34375 0.265625 -0.34375 0.625q0 0.234375 0.140625 0.421875q0.15625 0.1875 0.453125 0.3125q0.171875 0.0625 1.03125 0.296875q1.25 0.328125 1.734375 0.546875q0.5 0.203125 0.78125 0.609375q0.28125 0.40625 0.28125 1.0q0 0.59375 -0.34375 1.109375q-0.34375 0.515625 -1.0 0.796875q-0.640625 0.28125 -1.453125 0.28125q-1.34375 0 -2.046875 -0.5625q-0.703125 -0.5625 -0.90625 -1.65625z" fill-rule="nonzero"/><path fill="#ffffff" d="m460.45285 90.08796l0 0c0 -3.7457504 3.0365295 -6.7822876 6.7822876 -6.7822876l134.21494 0c1.7988281 0 3.5239258 0.71456146 4.7958374 1.9864883c1.2719116 1.2719269 1.9864502 2.9970245 1.9864502 4.7957993l0 27.128342c0 3.7457504 -3.036499 6.7822876 -6.7822876 6.7822876l-134.21494 0c-3.745758 0 -6.7822876 -3.0365372 -6.7822876 -6.7822876z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m460.45285 90.08796l0 0c0 -3.7457504 3.0365295 -6.7822876 6.7822876 -6.7822876l134.21494 0c1.7988281 0 3.5239258 0.71456146 4.7958374 1.9864883c1.2719116 1.2719269 1.9864502 2.9970245 1.9864502 4.7957993l0 27.128342c0 3.7457504 -3.036499 6.7822876 -6.7822876 6.7822876l-134.21494 0c-3.745758 0 -6.7822876 -3.0365372 -6.7822876 -6.7822876z" fill-rule="evenodd"/><path fill="#000000" d="m512.1151 96.6815l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm13.5625 1.421875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.9176636 0.28125q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm4.1882324 4.859375l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.8064575 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm0.9489136 -1.421875l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125z" fill-rule="nonzero"/><path fill="#000000" d="m474.92142 125.27525l0 -13.375l1.484375 0l0 1.25q0.53125 -0.734375 1.1875 -1.09375q0.671875 -0.375 1.625 -0.375q1.234375 0 2.171875 0.640625q0.953125 0.625 1.4375 1.796875q0.484375 1.15625 0.484375 2.546875q0 1.484375 -0.53125 2.671875q-0.53125 1.1875 -1.546875 1.828125q-1.015625 0.625 -2.140625 0.625q-0.8125 0 -1.46875 -0.34375q-0.65625 -0.34375 -1.0625 -0.875l0 4.703125l-1.640625 0zm1.484375 -8.484375q0 1.859375 0.75 2.765625q0.765625 0.890625 1.828125 0.890625q1.09375 0 1.875 -0.921875q0.78125 -0.9375 0.78125 -2.875q0 -1.84375 -0.765625 -2.765625q-0.75 -0.921875 -1.8125 -0.921875q-1.046875 0 -1.859375 0.984375q-0.796875 0.96875 -0.796875 2.84375zm8.875702 4.78125l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm5.618927 -4.84375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm15.610107 1.296875l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609375q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.296875q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm9.6405945 0.4375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.3749695 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.2655945 -1.34375 3.2655945 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm8.485107 2.875l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm9.328125 0l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm9.59375 -1.40625l1.65625 -0.140625q0.125 1.0 0.546875 1.640625q0.4375 0.640625 1.34375 1.046875q0.921875 0.390625 2.0625 0.390625q1.0 0 1.78125 -0.296875q0.78125 -0.296875 1.15625 -0.8125q0.375 -0.53125 0.375 -1.15625q0 -0.625 -0.375 -1.09375q-0.359375 -0.46875 -1.1875 -0.796875q-0.546875 -0.203125 -2.390625 -0.640625q-1.828125 -0.453125 -2.5625 -0.84375q-0.96875 -0.5 -1.4375 -1.234375q-0.46875 -0.75 -0.46875 -1.671875q0 -1.0 0.578125 -1.875q0.578125 -0.890625 1.671875 -1.34375q1.109375 -0.453125 2.453125 -0.453125q1.484375 0 2.609375 0.484375q1.140625 0.46875 1.75 1.40625q0.609375 0.921875 0.65625 2.09375l-1.6875 0.125q-0.140625 -1.265625 -0.9375 -1.90625q-0.78125 -0.65625 -2.3125 -0.65625q-1.609375 0 -2.34375 0.59375q-0.734375 0.59375 -0.734375 1.421875q0 0.71875 0.53125 1.171875q0.5 0.46875 2.65625 0.96875q2.15625 0.484375 2.953125 0.84375q1.171875 0.53125 1.71875 1.359375q0.5625 0.828125 0.5625 1.90625q0 1.0625 -0.609375 2.015625q-0.609375 0.9375 -1.75 1.46875q-1.140625 0.515625 -2.578125 0.515625q-1.8125 0 -3.046875 -0.53125q-1.21875 -0.53125 -1.921875 -1.59375q-0.6875 -1.0625 -0.71875 -2.40625zm12.7873535 4.296875l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm3.5822754 -4.84375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm12.875732 3.375l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm5.2145386 1.46875l0 -11.78125l-4.40625 0l0 -1.578125l10.578125 0l0 1.578125l-4.40625 0l0 11.78125l-1.765625 0zm6.630371 0l5.171875 -6.953125l-4.5625 -6.40625l2.109375 0l2.421875 3.4375q0.75 1.0625 1.078125 1.625q0.4375 -0.71875 1.046875 -1.515625l2.6875 -3.546875l1.921875 0l-4.6875 6.296875l5.0625 7.0625l-2.1875 0l-3.359375 -4.765625q-0.28125 -0.40625 -0.59375 -0.890625q-0.4375 0.734375 -0.625 1.0l-3.359375 4.65625l-2.125 0z" fill-rule="nonzero"/><path fill="#eeeeee" d="m89.20461 9.160635l67.77953 0l0 12.661417l-67.77953 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m89.20461 9.160635l67.77953 0l0 12.661417l-67.77953 0z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m779.01306 278.6972l135.1496 0l0 48.472443l-135.1496 0z" fill-rule="evenodd"/><path fill="#595959" d="m790.80994 310.7372l0 -2.40625l2.40625 0l0 2.40625l-2.40625 0zm8.015625 0l0 -2.40625l2.390625 0l0 2.40625l-2.390625 0zm7.984375 0l0 -2.40625l2.421875 0l0 2.40625l-2.421875 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m492.90643 440.06082l0 0c-8.774078 0 -15.886871 -7.112793 -15.886871 -15.886902l0 -107.28131c0 -4.2134705 1.6737671 -8.254364 4.6531677 -11.233734c2.97937 -2.97937 7.0202637 -4.6531677 11.233704 -4.6531677l6.525421 0c8.774109 0 15.886932 7.1128235 15.886932 15.886902l0 107.28131c0 8.774109 -7.1128235 15.886902 -15.886932 15.886902z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m492.90643 440.06082l0 0c-8.774078 0 -15.886871 -7.112793 -15.886871 -15.886902l0 -107.28131c0 -4.2134705 1.6737671 -8.254364 4.6531677 -11.233734c2.97937 -2.97937 7.0202637 -4.6531677 11.233704 -4.6531677l6.525421 0c8.774109 0 15.886932 7.1128235 15.886932 15.886902l0 107.28131c0 8.774109 -7.1128235 15.886902 -15.886932 15.886902z" fill-rule="evenodd"/><path fill="#000000" d="m501.6204 409.78796l1.453125 -0.234375q0.140625 0.6875 0.140625 1.234375q0 0.890625 -0.28125 1.390625q-0.28125 0.484375 -0.734375 0.6875q-0.46875 0.203125 -1.9375 0.203125l-5.578125 0l0 1.203125l-1.265625 0l0 -1.203125l-2.390625 0l-0.984375 -1.625l3.375 0l0 -1.65625l1.265625 0l0 1.65625l5.671875 0q0.6875 0 0.890625 -0.078125q0.203125 -0.09375 0.328125 -0.28125q0.109375 -0.203125 0.109375 -0.578125q0 -0.265625 -0.0625 -0.71875zm0.28125 -7.917694q0.765625 0.921875 1.09375 1.765625q0.3125 0.828125 0.3125 1.796875q0 1.59375 -0.78125 2.453125q-0.78125 0.859375 -1.984375 0.859375q-0.71875 0 -1.296875 -0.328125q-0.59375 -0.328125 -0.9375 -0.84375q-0.359375 -0.53125 -0.546875 -1.1875q-0.125 -0.46875 -0.25 -1.453125q-0.234375 -1.984375 -0.5625 -2.921875q-0.34375 -0.015625 -0.421875 -0.015625q-1.0 0 -1.421875 0.46875q-0.546875 0.625 -0.546875 1.875q0 1.15625 0.40625 1.703125q0.40625 0.546875 1.421875 0.8125l-0.21875 1.609375q-1.015625 -0.21875 -1.640625 -0.71875q-0.640625 -0.5 -0.984375 -1.453125q-0.34375 -0.953125 -0.34375 -2.1875q0 -1.25 0.296875 -2.015625q0.28125 -0.78125 0.734375 -1.140625q0.4375 -0.375 1.109375 -0.515625q0.421875 -0.078125 1.515625 -0.078125l2.1875 0q2.28125 0 2.890625 -0.109375q0.59375 -0.109375 1.15625 -0.40625l0 1.703125q-0.515625 0.265625 -1.1875 0.328125zm-3.671875 0.140625q0.375 0.890625 0.625 2.671875q0.140625 1.015625 0.328125 1.4375q0.1875 0.421875 0.53125 0.65625q0.34375 0.21875 0.78125 0.21875q0.65625 0 1.09375 -0.5q0.4375 -0.5 0.4375 -1.453125q0 -0.9375 -0.40625 -1.671875q-0.421875 -0.75 -1.140625 -1.09375q-0.5625 -0.265625 -1.640625 -0.265625l-0.609375 0zm1.96875 -3.547577l-0.25 -1.625q0.96875 -0.125 1.5 -0.75q0.515625 -0.625 0.515625 -1.75q0 -1.125 -0.453125 -1.671875q-0.46875 -0.546875 -1.09375 -0.546875q-0.546875 0 -0.875 0.484375q-0.21875 0.328125 -0.546875 1.671875q-0.46875 1.8125 -0.796875 2.515625q-0.328125 0.6875 -0.90625 1.046875q-0.59375 0.359375 -1.3125 0.359375q-0.640625 0 -1.1875 -0.296875q-0.5625 -0.296875 -0.921875 -0.8125q-0.28125 -0.375 -0.46875 -1.03125q-0.203125 -0.671875 -0.203125 -1.421875q0 -1.140625 0.328125 -2.0q0.328125 -0.859375 0.890625 -1.265625q0.5625 -0.421875 1.5 -0.578125l0.21875 1.609375q-0.75 0.109375 -1.171875 0.640625q-0.421875 0.515625 -0.421875 1.46875q0 1.140625 0.375 1.625q0.375 0.46875 0.875 0.46875q0.3125 0 0.578125 -0.1875q0.265625 -0.203125 0.4375 -0.640625q0.09375 -0.234375 0.421875 -1.4375q0.453125 -1.75 0.75 -2.4375q0.296875 -0.6875 0.859375 -1.078125q0.5625 -0.390625 1.40625 -0.390625q0.828125 0 1.546875 0.484375q0.71875 0.46875 1.125 1.375q0.390625 0.90625 0.390625 2.046875q0 1.875 -0.78125 2.875q-0.78125 0.984375 -2.328125 1.25zm2.890625 -9.984375l-13.359375 0l0 -1.640625l7.625 0l-3.9375 -3.890625l0 -2.109375l3.59375 3.6875l6.078125 -4.0625l0 2.015625l-4.953125 3.203125l1.125 1.15625l3.828125 0l0 1.640625zm0 -14.495819l-9.671875 0l0 -1.46875l1.46875 0q-1.03125 -0.5625 -1.359375 -1.03125q-0.328125 -0.48434448 -0.328125 -1.0624695q0 -0.828125 0.53125 -1.6875l1.515625 0.5625q-0.359375 0.609375 -0.359375 1.203125q0 0.546875 0.328125 0.9687195q0.328125 0.421875 0.890625 0.609375q0.875 0.28125 1.921875 0.28125l5.0625 0l0 1.625zm-3.109375 -12.8532715l0.203125 -1.6875q1.484375 0.40625 2.3125 1.484375q0.8125 1.078125 0.8125 2.765625q0 2.125 -1.296875 3.375q-1.3125 1.234375 -3.671875 1.234375q-2.453125 0 -3.796875 -1.25q-1.34375 -1.265625 -1.34375 -3.265625q0 -1.9375 1.328125 -3.15625q1.3125 -1.234375 3.703125 -1.234375q0.15625 0 0.4375 0l0 7.21875q1.59375 -0.09375 2.453125 -0.90625q0.84375 -0.8125 0.84375 -2.015625q0 -0.90625 -0.46875 -1.546875q-0.484375 -0.640625 -1.515625 -1.015625zm-2.65625 5.390625l0 -5.40625q-1.21875 0.109375 -1.828125 0.625q-0.953125 0.78125 -0.953125 2.03125q0 1.125 0.765625 1.90625q0.75 0.765625 2.015625 0.84375zm4.296875 -12.719482l1.453125 -0.234375q0.140625 0.6875 0.140625 1.234375q0 0.890625 -0.28125 1.390625q-0.28125 0.484375 -0.734375 0.6875q-0.46875 0.203125 -1.9375 0.203125l-5.578125 0l0 1.203125l-1.265625 0l0 -1.203125l-2.390625 0l-0.984375 -1.625l3.375 0l0 -1.65625l1.265625 0l0 1.65625l5.671875 0q0.6875 0 0.890625 -0.078125q0.203125 -0.09375 0.328125 -0.28125q0.109375 -0.203125 0.109375 -0.578125q0 -0.265625 -0.0625 -0.71875zm1.46875 -7.9332886l-1.421875 0q1.640625 1.125 1.640625 3.0625q0 0.859375 -0.328125 1.609375q-0.328125 0.734375 -0.828125 1.09375q-0.5 0.359375 -1.21875 0.5q-0.46875 0.109375 -1.53125 0.109375l-5.984375 0l0 -1.640625l5.359375 0q1.28125 0 1.734375 -0.109375q0.640625 -0.15625 1.015625 -0.65625q0.375 -0.5 0.375 -1.234375q0 -0.734375 -0.375 -1.375q-0.390625 -0.65625 -1.03125 -0.921875q-0.65625 -0.265625 -1.890625 -0.265625l-5.1875 0l0 -1.640625l9.671875 0l0 1.46875zm0 -4.0319824l-9.671875 0l0 -1.46875l1.46875 0q-1.03125 -0.5625 -1.359375 -1.03125q-0.328125 -0.484375 -0.328125 -1.0625q0 -0.828125 0.53125 -1.6875l1.515625 0.5625q-0.359375 0.609375 -0.359375 1.203125q0 0.546875 0.328125 0.96875q0.328125 0.421875 0.890625 0.609375q0.875 0.28125 1.921875 0.28125l5.0625 0l0 1.625zm0 -6.228302l-9.671875 0l0 -1.46875l1.375 0q-1.59375 -1.0625 -1.59375 -3.078125q0 -0.875 0.3125 -1.609375q0.3125 -0.734375 0.828125 -1.09375q0.5 -0.375 1.203125 -0.515625q0.453125 -0.09375 1.59375 -0.09375l5.953125 0l0 1.640625l-5.890625 0q-1.0 0 -1.484375 0.203125q-0.5 0.1875 -0.796875 0.671875q-0.296875 0.484375 -0.296875 1.140625q0 1.046875 0.671875 1.8125q0.65625 0.75 2.515625 0.75l5.28125 0l0 1.640625z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m139.39944 0l403.43307 0l0 32.31496l-403.43307 0z" fill-rule="evenodd"/><path fill="#595959" d="m160.58578 16.943125l0 -0.9375l2.875 0l0 0.9375l-2.875 0zm8.915512 1.453125l0.125 0.828125q-0.390625 0.09375 -0.703125 0.09375q-0.5 0 -0.78125 -0.15625q-0.28125 -0.171875 -0.40625 -0.4375q-0.109375 -0.265625 -0.109375 -1.109375l0 -3.171875l-0.6875 0l0 -0.734375l0.6875 0l0 -1.359375l0.9375 -0.5625l0 1.921875l0.9375 0l0 0.734375l-0.9375 0l0 3.234375q0 0.390625 0.046875 0.515625q0.046875 0.109375 0.15625 0.1875q0.109375 0.0625 0.328125 0.0625q0.15625 0 0.40625 -0.046875zm0.9137726 0.84375l0 -7.625l0.9375 0l0 2.734375q0.65625 -0.765625 1.65625 -0.765625q0.609375 0 1.0625 0.25q0.453125 0.234375 0.640625 0.671875q0.203125 0.421875 0.203125 1.234375l0 3.5l-0.9375 0l0 -3.5q0 -0.703125 -0.3125 -1.015625q-0.296875 -0.328125 -0.859375 -0.328125q-0.40625 0 -0.78125 0.21875q-0.359375 0.21875 -0.515625 0.59375q-0.15625 0.359375 -0.15625 1.015625l0 3.015625l-0.9375 0zm5.9108734 0l0 -5.53125l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.890625l-0.9375 0zm7.3454895 -1.78125l0.96875 0.125q-0.234375 0.84375 -0.859375 1.3125q-0.609375 0.46875 -1.578125 0.46875q-1.203125 0 -1.921875 -0.75q-0.703125 -0.75 -0.703125 -2.09375q0 -1.390625 0.71875 -2.15625q0.71875 -0.78125 1.859375 -0.78125q1.109375 0 1.8125 0.765625q0.703125 0.75 0.703125 2.125q0 0.078125 0 0.234375l-4.125 0q0.046875 0.921875 0.515625 1.40625q0.46875 0.484375 1.15625 0.484375q0.515625 0 0.875 -0.265625q0.359375 -0.28125 0.578125 -0.875zm-3.078125 -1.515625l3.09375 0q-0.0625 -0.6875 -0.359375 -1.046875q-0.453125 -0.53125 -1.15625 -0.53125q-0.640625 0 -1.09375 0.4375q-0.4375 0.421875 -0.484375 1.140625zm8.832748 2.609375q-0.53125 0.453125 -1.015625 0.640625q-0.46875 0.171875 -1.015625 0.171875q-0.921875 0 -1.40625 -0.4375q-0.484375 -0.453125 -0.484375 -1.140625q0 -0.40625 0.171875 -0.734375q0.1875 -0.34375 0.484375 -0.546875q0.3125 -0.203125 0.6875 -0.3125q0.265625 -0.0625 0.828125 -0.140625q1.125 -0.125 1.671875 -0.3125q0 -0.203125 0 -0.25q0 -0.578125 -0.265625 -0.8125q-0.359375 -0.3125 -1.0625 -0.3125q-0.65625 0 -0.984375 0.234375q-0.3125 0.234375 -0.453125 0.8125l-0.921875 -0.125q0.125 -0.578125 0.40625 -0.9375q0.296875 -0.375 0.828125 -0.5625q0.546875 -0.203125 1.25 -0.203125q0.71875 0 1.15625 0.171875q0.4375 0.171875 0.640625 0.421875q0.21875 0.25 0.296875 0.640625q0.046875 0.234375 0.046875 0.859375l0 1.25q0 1.296875 0.0625 1.65625q0.0625 0.34375 0.234375 0.65625l-0.96875 0q-0.15625 -0.296875 -0.1875 -0.6875zm-0.078125 -2.078125q-0.515625 0.203125 -1.53125 0.34375q-0.578125 0.078125 -0.828125 0.1875q-0.234375 0.109375 -0.359375 0.3125q-0.125 0.1875 -0.125 0.4375q0 0.375 0.28125 0.625q0.28125 0.25 0.828125 0.25q0.53125 0 0.953125 -0.234375q0.421875 -0.234375 0.625 -0.65625q0.15625 -0.3125 0.15625 -0.9375l0 -0.328125zm5.9733734 2.765625l0 -0.703125q-0.515625 0.828125 -1.546875 0.828125q-0.65625 0 -1.21875 -0.359375q-0.546875 -0.375 -0.859375 -1.015625q-0.296875 -0.65625 -0.296875 -1.5q0 -0.828125 0.28125 -1.5q0.28125 -0.6875 0.828125 -1.046875q0.546875 -0.359375 1.234375 -0.359375q0.5 0 0.890625 0.21875q0.390625 0.203125 0.625 0.546875l0 -2.734375l0.9375 0l0 7.625l-0.875 0zm-2.953125 -2.75q0 1.046875 0.4375 1.578125q0.453125 0.53125 1.0625 0.53125q0.609375 0 1.03125 -0.5q0.4375 -0.515625 0.4375 -1.53125q0 -1.140625 -0.4375 -1.671875q-0.4375 -0.53125 -1.078125 -0.53125q-0.609375 0 -1.03125 0.515625q-0.421875 0.5 -0.421875 1.609375z" fill-rule="nonzero"/><path fill="#ffffff" d="m293.44656 207.26974l0 0c0 -4.6242065 3.7486877 -8.372864 8.372894 -8.372864l131.03378 0c2.2206116 0 4.350281 0.8821411 5.9205017 2.4523468c1.570221 1.570221 2.452362 3.6998901 2.452362 5.920517l0 33.49048c0 4.6242065 -3.7486572 8.372879 -8.372864 8.372879l-131.03378 0c-4.6242065 0 -8.372894 -3.7486725 -8.372894 -8.372879z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m293.44656 207.26974l0 0c0 -4.6242065 3.7486877 -8.372864 8.372894 -8.372864l131.03378 0c2.2206116 0 4.350281 0.8821411 5.9205017 2.4523468c1.570221 1.570221 2.452362 3.6998901 2.452362 5.920517l0 33.49048c0 4.6242065 -3.7486572 8.372879 -8.372864 8.372879l-131.03378 0c-4.6242065 0 -8.372894 -3.7486725 -8.372894 -8.372879z" fill-rule="evenodd"/><path fill="#000000" d="m345.10886 217.04436l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm13.5625 1.421875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.9176636 0.28125q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm4.188202 4.859375l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm0.9489441 -1.421875l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125z" fill-rule="nonzero"/><path fill="#000000" d="m335.02545 228.5756l1.765625 0l0 7.71875q0 2.015625 -0.453125 3.203125q-0.453125 1.1875 -1.640625 1.9375q-1.1875 0.734375 -3.125 0.734375q-1.875 0 -3.078125 -0.640625q-1.1875 -0.65625 -1.703125 -1.875q-0.5 -1.234375 -0.5 -3.359375l0 -7.71875l1.765625 0l0 7.71875q0 1.734375 0.3125 2.5625q0.328125 0.8125 1.109375 1.265625q0.796875 0.453125 1.9375 0.453125q1.953125 0 2.78125 -0.890625q0.828125 -0.890625 0.828125 -3.390625l0 -7.71875zm4.738556 13.359375l0 -13.359375l9.65625 0l0 1.578125l-7.875 0l0 4.09375l7.375 0l0 1.5625l-7.375 0l0 4.546875l8.1875 0l0 1.578125l-9.96875 0zm10.693573 3.703125l0 -1.1875l10.859375 0l0 1.1875l-10.859375 0zm11.235107 -6.59375l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm9.90625 6.609375l-0.1875 -1.53125q0.546875 0.140625 0.9375 0.140625q0.546875 0 0.875 -0.1875q0.328125 -0.171875 0.546875 -0.5q0.15625 -0.25 0.5 -1.21875q0.046875 -0.140625 0.140625 -0.40625l-3.671875 -9.6875l1.765625 0l2.015625 5.59375q0.390625 1.078125 0.703125 2.25q0.28125 -1.125 0.671875 -2.203125l2.078125 -5.640625l1.640625 0l-3.6875 9.828125q-0.59375 1.609375 -0.921875 2.203125q-0.4375 0.8125 -1.0 1.1875q-0.5625 0.375 -1.34375 0.375q-0.484375 0 -1.0625 -0.203125zm9.40625 -3.71875l0 -9.671875l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953125l-1.640625 0l0 -5.890625q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.28125l-1.640625 0zm16.688202 -3.546875l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609375q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.296875q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm3.015625 3.546875l0 -13.359375l1.640625 0l0 4.796875q1.140625 -1.328125 2.890625 -1.328125q1.078125 0 1.859375 0.421875q0.796875 0.421875 1.140625 1.171875q0.34375 0.75 0.34375 2.171875l0 6.125l-1.640625 0l0 -6.125q0 -1.234375 -0.53125 -1.796875q-0.53125 -0.5625 -1.515625 -0.5625q-0.71875 0 -1.359375 0.390625q-0.640625 0.375 -0.921875 1.015625q-0.265625 0.640625 -0.265625 1.78125l0 5.296875l-1.640625 0z" fill-rule="nonzero"/><path fill="#eeeeee" d="m159.69286 307.29163l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m159.69286 307.29163l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path fill="#eeeeee" d="m163.22864 311.44962l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m163.22864 311.44962l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path fill="#eeeeee" d="m167.03758 317.41028l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m167.03758 317.41028l73.543304 0l0 146.4567l-73.543304 0z" fill-rule="evenodd"/><path fill="#000000" d="m193.3224 386.55862l0 -13.359375l4.609375 0q1.546875 0 2.375 0.203125q1.140625 0.25 1.953125 0.953125q1.0625 0.890625 1.578125 2.28125q0.53125 1.390625 0.53125 3.171875q0 1.515625 -0.359375 2.703125q-0.359375 1.171875 -0.921875 1.9375q-0.546875 0.765625 -1.203125 1.21875q-0.65625 0.4375 -1.59375 0.671875q-0.9375 0.21875 -2.140625 0.21875l-4.828125 0zm1.765625 -1.578125l2.859375 0q1.3125 0 2.0625 -0.234375q0.75 -0.25 1.203125 -0.703125q0.625 -0.625 0.96875 -1.6875q0.359375 -1.0625 0.359375 -2.578125q0 -2.09375 -0.6875 -3.21875q-0.6875 -1.125 -1.671875 -1.5q-0.703125 -0.28125 -2.28125 -0.28125l-2.8125 0l0 10.203125zm11.629196 1.578125l0 -13.359375l1.78125 0l0 11.78125l6.5625 0l0 1.578125l-8.34375 0z" fill-rule="nonzero"/><path fill="#000000" d="m177.34222 408.55862l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm16.162323 1.9375l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609375q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.296875q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm6.59375 2.078125l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm0.99580383 -3.375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm9.281967 4.84375l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm5.572052 -2.890625l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125z" fill-rule="nonzero"/><path fill="#ffff00" d="m0 491.0498l0 0c0 -5.406891 4.383144 -9.790039 9.790027 -9.790039l94.67717 0l48.897217 -38.0542l-4.1255646 38.0542l20.05774 0c2.5964813 0 5.086609 1.0314636 6.922592 2.8674316c1.8359833 1.8359985 2.8674316 4.3261414 2.8674316 6.9226074l0 0l0 0l0 14.685028l0 24.475067c0 5.4069214 -4.383133 9.790039 -9.790024 9.790039l-20.05774 0l-44.771652 0l0 0l-94.67717 0c-5.406883 0 -9.790027 -4.3831177 -9.790027 -9.790039l0 -24.475067l0 -14.685028l0 0z" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m0 491.0498l0 0c0 -5.406891 4.383144 -9.790039 9.790027 -9.790039l94.67717 0l48.897217 -38.0542l-4.1255646 38.0542l20.05774 0c2.5964813 0 5.086609 1.0314636 6.922592 2.8674316c1.8359833 1.8359985 2.8674316 4.3261414 2.8674316 6.9226074l0 0l0 0l0 14.685028l0 24.475067c0 5.4069214 -4.383133 9.790039 -9.790024 9.790039l-20.05774 0l-44.771652 0l0 0l-94.67717 0c-5.406883 0 -9.790027 -4.3831177 -9.790027 -9.790039l0 -24.475067l0 -14.685028l0 0z" fill-rule="evenodd"/><path fill="#000000" d="m15.304901 501.36984l0 -1.828125l-3.296875 0l0 -0.859375l3.46875 -4.9375l0.765625 0l0 4.9375l1.03125 0l0 0.859375l-1.03125 0l0 1.828125l-0.9375 0zm0 -2.6875l0 -3.4375l-2.375 3.4375l2.375 0zm6.277771 2.6875l0 -7.625l2.625 0q0.890625 0 1.359375 0.109375q0.65625 0.140625 1.109375 0.546875q0.609375 0.5 0.90625 1.296875q0.296875 0.796875 0.296875 1.8125q0 0.875 -0.203125 1.546875q-0.203125 0.671875 -0.515625 1.109375q-0.3125 0.4375 -0.703125 0.6875q-0.375 0.25 -0.90625 0.390625q-0.53125 0.125 -1.21875 0.125l-2.75 0zm1.0 -0.90625l1.625 0q0.765625 0 1.1875 -0.140625q0.4375 -0.140625 0.6875 -0.390625q0.359375 -0.359375 0.5625 -0.953125q0.203125 -0.609375 0.203125 -1.484375q0 -1.1875 -0.40625 -1.828125q-0.390625 -0.65625 -0.953125 -0.875q-0.40625 -0.15625 -1.296875 -0.15625l-1.609375 0l0 5.828125zm6.6487274 0.90625l0 -7.625l1.015625 0l0 6.71875l3.75 0l0 0.90625l-4.765625 0zm12.022568 -0.6875q-0.53125 0.453125 -1.015625 0.640625q-0.46875 0.171875 -1.015625 0.171875q-0.921875 0 -1.40625 -0.4375q-0.484375 -0.453125 -0.484375 -1.140625q0 -0.40625 0.171875 -0.734375q0.1875 -0.34375 0.484375 -0.546875q0.3125 -0.203125 0.6875 -0.3125q0.265625 -0.0625 0.828125 -0.140625q1.125 -0.125 1.671875 -0.3125q0 -0.203125 0 -0.25q0 -0.578125 -0.265625 -0.8125q-0.359375 -0.3125 -1.0625 -0.3125q-0.65625 0 -0.984375 0.234375q-0.3125 0.234375 -0.453125 0.8125l-0.921875 -0.125q0.125 -0.578125 0.40625 -0.9375q0.296875 -0.375 0.828125 -0.5625q0.546875 -0.203125 1.25 -0.203125q0.71875 0 1.15625 0.171875q0.4375 0.171875 0.640625 0.421875q0.21875 0.25 0.296875 0.640625q0.046875 0.234375 0.046875 0.859375l0 1.25q0 1.296875 0.0625 1.65625q0.0625 0.34375 0.234375 0.65625l-0.96875 0q-0.15625 -0.296875 -0.1875 -0.6875zm-0.078125 -2.078125q-0.515625 0.203125 -1.53125 0.34375q-0.578125 0.078125 -0.828125 0.1875q-0.234375 0.109375 -0.359375 0.3125q-0.125 0.1875 -0.125 0.4375q0 0.375 0.28125 0.625q0.28125 0.25 0.828125 0.25q0.53125 0 0.953125 -0.234375q0.421875 -0.234375 0.625 -0.65625q0.15625 -0.3125 0.15625 -0.9375l0 -0.328125zm6.0046234 0.734375l0.921875 0.125q-0.15625 0.953125 -0.78125 1.5q-0.625 0.53125 -1.53125 0.53125q-1.125 0 -1.8125 -0.734375q-0.6875 -0.75 -0.6875 -2.125q0 -0.90625 0.296875 -1.578125q0.296875 -0.671875 0.890625 -1.0q0.609375 -0.34375 1.328125 -0.34375q0.890625 0 1.46875 0.46875q0.578125 0.453125 0.734375 1.28125l-0.90625 0.140625q-0.140625 -0.546875 -0.46875 -0.828125q-0.328125 -0.28125 -0.796875 -0.28125q-0.703125 0 -1.15625 0.515625q-0.4375 0.5 -0.4375 1.59375q0 1.109375 0.421875 1.625q0.4375 0.5 1.125 0.5q0.546875 0 0.90625 -0.34375q0.375 -0.34375 0.484375 -1.046875zm3.765625 1.1875l0.125 0.828125q-0.390625 0.09375 -0.703125 0.09375q-0.5 0 -0.78125 -0.15625q-0.28125 -0.171875 -0.40625 -0.4375q-0.109375 -0.265625 -0.109375 -1.109375l0 -3.171875l-0.6875 0l0 -0.734375l0.6875 0l0 -1.359375l0.9375 -0.5625l0 1.921875l0.9375 0l0 0.734375l-0.9375 0l0 3.234375q0 0.390625 0.046875 0.515625q0.046875 0.109375 0.15625 0.1875q0.109375 0.0625 0.328125 0.0625q0.15625 0 0.40625 -0.046875zm0.5700226 -1.921875q0 -1.53125 0.84375 -2.265625q0.71875 -0.625 1.734375 -0.625q1.140625 0 1.859375 0.75q0.734375 0.75 0.734375 2.0625q0 1.0625 -0.328125 1.6875q-0.3125 0.609375 -0.921875 0.953125q-0.609375 0.328125 -1.34375 0.328125q-1.15625 0 -1.875 -0.734375q-0.703125 -0.75 -0.703125 -2.15625zm0.953125 0q0 1.0625 0.46875 1.59375q0.46875 0.53125 1.15625 0.53125q0.703125 0 1.15625 -0.53125q0.46875 -0.53125 0.46875 -1.625q0 -1.015625 -0.46875 -1.546875q-0.453125 -0.53125 -1.15625 -0.53125q-0.6875 0 -1.15625 0.53125q-0.46875 0.515625 -0.46875 1.578125zm5.3014984 2.765625l0 -5.53125l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.890625l-0.9375 0zm3.1892395 -1.65625l0.921875 -0.140625q0.078125 0.5625 0.4375 0.859375q0.359375 0.296875 1.0 0.296875q0.640625 0 0.953125 -0.265625q0.3125 -0.265625 0.3125 -0.625q0 -0.3125 -0.28125 -0.5q-0.1875 -0.125 -0.953125 -0.3125q-1.03125 -0.265625 -1.4375 -0.453125q-0.390625 -0.1875 -0.59375 -0.515625q-0.203125 -0.34375 -0.203125 -0.75q0 -0.359375 0.171875 -0.671875q0.171875 -0.328125 0.453125 -0.53125q0.21875 -0.15625 0.59375 -0.265625q0.390625 -0.125 0.8125 -0.125q0.65625 0 1.140625 0.1875q0.5 0.1875 0.734375 0.515625q0.234375 0.3125 0.3125 0.859375l-0.90625 0.125q-0.0625 -0.4375 -0.375 -0.671875q-0.296875 -0.234375 -0.828125 -0.234375q-0.65625 0 -0.9375 0.21875q-0.265625 0.203125 -0.265625 0.484375q0 0.1875 0.109375 0.328125q0.125 0.15625 0.359375 0.25q0.140625 0.0625 0.828125 0.25q1.0 0.265625 1.390625 0.4375q0.390625 0.15625 0.609375 0.484375q0.234375 0.3125 0.234375 0.796875q0 0.46875 -0.28125 0.890625q-0.265625 0.40625 -0.78125 0.640625q-0.515625 0.21875 -1.171875 0.21875q-1.078125 0 -1.640625 -0.4375q-0.5625 -0.453125 -0.71875 -1.34375zm8.663773 1.65625l0 -5.53125l0.84375 0l0 0.78125q0.25 -0.40625 0.6875 -0.65625q0.4375 -0.25 0.984375 -0.25q0.609375 0 1.0 0.265625q0.390625 0.25 0.5625 0.703125q0.65625 -0.96875 1.703125 -0.96875q0.828125 0 1.265625 0.46875q0.4375 0.453125 0.4375 1.390625l0 3.796875l-0.921875 0l0 -3.484375q0 -0.5625 -0.09375 -0.796875q-0.09375 -0.25 -0.34375 -0.40625q-0.234375 -0.15625 -0.546875 -0.15625q-0.59375 0 -0.984375 0.390625q-0.375 0.390625 -0.375 1.25l0 3.203125l-0.9375 0l0 -3.59375q0 -0.625 -0.234375 -0.9375q-0.21875 -0.3125 -0.75 -0.3125q-0.390625 0 -0.734375 0.21875q-0.328125 0.203125 -0.484375 0.609375q-0.140625 0.390625 -0.140625 1.15625l0 2.859375l-0.9375 0zm12.6579895 -1.78125l0.96875 0.125q-0.234375 0.84375 -0.859375 1.3125q-0.609375 0.46875 -1.578125 0.46875q-1.203125 0 -1.921875 -0.75q-0.703125 -0.75 -0.703125 -2.09375q0 -1.390625 0.71875 -2.15625q0.71875 -0.78125 1.859375 -0.78125q1.109375 0 1.8125 0.765625q0.703125 0.75 0.703125 2.125q0 0.078125 0 0.234375l-4.125 0q0.046875 0.921875 0.515625 1.40625q0.46875 0.484375 1.15625 0.484375q0.515625 0 0.875 -0.265625q0.359375 -0.28125 0.578125 -0.875zm-3.078125 -1.515625l3.09375 0q-0.0625 -0.6875 -0.359375 -1.046875q-0.453125 -0.53125 -1.15625 -0.53125q-0.640625 0 -1.09375 0.4375q-0.4375 0.421875 -0.484375 1.140625zm8.832748 2.609375q-0.53125 0.453125 -1.015625 0.640625q-0.46875 0.171875 -1.015625 0.171875q-0.921875 0 -1.40625 -0.4375q-0.484375 -0.453125 -0.484375 -1.140625q0 -0.40625 0.171875 -0.734375q0.1875 -0.34375 0.484375 -0.546875q0.3125 -0.203125 0.6875 -0.3125q0.265625 -0.0625 0.828125 -0.140625q1.125 -0.125 1.671875 -0.3125q0 -0.203125 0 -0.25q0 -0.578125 -0.265625 -0.8125q-0.359375 -0.3125 -1.0625 -0.3125q-0.65625 0 -0.984375 0.234375q-0.3125 0.234375 -0.453125 0.8125l-0.921875 -0.125q0.125 -0.578125 0.40625 -0.9375q0.296875 -0.375 0.828125 -0.5625q0.546875 -0.203125 1.25 -0.203125q0.71875 0 1.15625 0.171875q0.4375 0.171875 0.640625 0.421875q0.21875 0.25 0.296875 0.640625q0.046875 0.234375 0.046875 0.859375l0 1.25q0 1.296875 0.0625 1.65625q0.0625 0.34375 0.234375 0.65625l-0.96875 0q-0.15625 -0.296875 -0.1875 -0.6875zm-0.078125 -2.078125q-0.515625 0.203125 -1.53125 0.34375q-0.578125 0.078125 -0.828125 0.1875q-0.234375 0.109375 -0.359375 0.3125q-0.125 0.1875 -0.125 0.4375q0 0.375 0.28125 0.625q0.28125 0.25 0.828125 0.25q0.53125 0 0.953125 -0.234375q0.421875 -0.234375 0.625 -0.65625q0.15625 -0.3125 0.15625 -0.9375l0 -0.328125zm2.3952484 2.765625l0 -5.53125l0.84375 0l0 0.796875q0.609375 -0.921875 1.75 -0.921875q0.5 0 0.921875 0.1875q0.421875 0.171875 0.625 0.46875q0.21875 0.296875 0.296875 0.6875q0.046875 0.265625 0.046875 0.921875l0 3.390625l-0.9375 0l0 -3.359375q0 -0.578125 -0.109375 -0.859375q-0.109375 -0.28125 -0.390625 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.59375 0 -1.03125 0.390625q-0.4375 0.375 -0.4375 1.4375l0 3.015625l-0.9375 0zm5.5514984 -1.65625l0.921875 -0.140625q0.078125 0.5625 0.4375 0.859375q0.359375 0.296875 1.0 0.296875q0.640625 0 0.953125 -0.265625q0.3125 -0.265625 0.3125 -0.625q0 -0.3125 -0.28125 -0.5q-0.1875 -0.125 -0.953125 -0.3125q-1.03125 -0.265625 -1.4375 -0.453125q-0.390625 -0.1875 -0.59375 -0.515625q-0.203125 -0.34375 -0.203125 -0.75q0 -0.359375 0.171875 -0.671875q0.171875 -0.328125 0.453125 -0.53125q0.21875 -0.15625 0.59375 -0.265625q0.390625 -0.125 0.8125 -0.125q0.65625 0 1.140625 0.1875q0.5 0.1875 0.734375 0.515625q0.234375 0.3125 0.3125 0.859375l-0.90625 0.125q-0.0625 -0.4375 -0.375 -0.671875q-0.296875 -0.234375 -0.828125 -0.234375q-0.65625 0 -0.9375 0.21875q-0.265625 0.203125 -0.265625 0.484375q0 0.1875 0.109375 0.328125q0.125 0.15625 0.359375 0.25q0.140625 0.0625 0.828125 0.25q1.0 0.265625 1.390625 0.4375q0.390625 0.15625 0.609375 0.484375q0.234375 0.3125 0.234375 0.796875q0 0.46875 -0.28125 0.890625q-0.265625 0.40625 -0.78125 0.640625q-0.515625 0.21875 -1.171875 0.21875q-1.078125 0 -1.640625 -0.4375q-0.5625 -0.453125 -0.71875 -1.34375zm8.882523 1.65625l0 -4.796875l-0.828125 0l0 -0.734375l0.828125 0l0 -0.578125q0 -0.5625 0.109375 -0.828125q0.125 -0.375 0.46875 -0.59375q0.34375 -0.234375 0.953125 -0.234375q0.390625 0 0.875 0.09375l-0.140625 0.828125q-0.296875 -0.0625 -0.546875 -0.0625q-0.421875 0 -0.609375 0.1875q-0.171875 0.1875 -0.171875 0.6875l0 0.5l1.078125 0l0 0.734375l-1.078125 0l0 4.796875l-0.9375 0zm2.3981476 -2.765625q0 -1.53125 0.84375 -2.265625q0.71875 -0.625 1.734375 -0.625q1.140625 0 1.859375 0.75q0.734375 0.75 0.734375 2.0625q0 1.0625 -0.328125 1.6875q-0.3125 0.609375 -0.921875 0.953125q-0.609375 0.328125 -1.34375 0.328125q-1.15625 0 -1.875 -0.734375q-0.703125 -0.75 -0.703125 -2.15625zm0.953125 0q0 1.0625 0.46875 1.59375q0.46875 0.53125 1.15625 0.53125q0.703125 0 1.15625 -0.53125q0.46875 -0.53125 0.46875 -1.625q0 -1.015625 -0.46875 -1.546875q-0.453125 -0.53125 -1.15625 -0.53125q-0.6875 0 -1.15625 0.53125q-0.46875 0.515625 -0.46875 1.578125zm8.942123 2.765625l0 -0.8125q-0.65625 0.9375 -1.75 0.9375q-0.5 0 -0.921875 -0.1875q-0.421875 -0.1875 -0.625 -0.46875q-0.203125 -0.28125 -0.296875 -0.703125q-0.046875 -0.265625 -0.046875 -0.875l0 -3.421875l0.9375 0l0 3.0625q0 0.734375 0.046875 1.0q0.09375 0.359375 0.375 0.578125q0.296875 0.203125 0.703125 0.203125q0.421875 0 0.796875 -0.203125q0.375 -0.21875 0.515625 -0.59375q0.15625 -0.375 0.15625 -1.078125l0 -2.96875l0.9375 0l0 5.53125l-0.828125 0zm2.2858734 0l0 -5.53125l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.890625l-0.9375 0zm8.571762 -0.84375l0.125 0.828125q-0.390625 0.09375 -0.703125 0.09375q-0.5 0 -0.78125 -0.15625q-0.28125 -0.171875 -0.40625 -0.4375q-0.109375 -0.265625 -0.109375 -1.109375l0 -3.171875l-0.6875 0l0 -0.734375l0.6875 0l0 -1.359375l0.9375 -0.5625l0 1.921875l0.9375 0l0 0.734375l-0.9375 0l0 3.234375q0 0.390625 0.046875 0.515625q0.046875 0.109375 0.15625 0.1875q0.109375 0.0625 0.328125 0.0625q0.15625 0 0.40625 -0.046875zm0.9137726 0.84375l0 -7.625l0.9375 0l0 2.734375q0.65625 -0.765625 1.65625 -0.765625q0.609375 0 1.0625 0.25q0.453125 0.234375 0.640625 0.671875q0.203125 0.421875 0.203125 1.234375l0 3.5l-0.9375 0l0 -3.5q0 -0.703125 -0.3125 -1.015625q-0.296875 -0.328125 -0.859375 -0.328125q-0.40625 0 -0.78125 0.21875q-0.359375 0.21875 -0.515625 0.59375q-0.15625 0.359375 -0.15625 1.015625l0 3.015625l-0.9375 0zm5.9108734 0l0 -5.53125l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.890625l-0.9375 0zm7.3454895 -1.78125l0.96875 0.125q-0.234375 0.84375 -0.859375 1.3125q-0.609375 0.46875 -1.578125 0.46875q-1.203125 0 -1.921875 -0.75q-0.703125 -0.75 -0.703125 -2.09375q0 -1.390625 0.71875 -2.15625q0.71875 -0.78125 1.859375 -0.78125q1.109375 0 1.8125 0.765625q0.703125 0.75 0.703125 2.125q0 0.078125 0 0.234375l-4.125 0q0.046875 0.921875 0.515625 1.40625q0.46875 0.484375 1.15625 0.484375q0.515625 0 0.875 -0.265625q0.359375 -0.28125 0.578125 -0.875zm-3.078125 -1.515625l3.09375 0q-0.0625 -0.6875 -0.359375 -1.046875q-0.453125 -0.53125 -1.15625 -0.53125q-0.640625 0 -1.09375 0.4375q-0.4375 0.421875 -0.484375 1.140625zm8.832748 2.609375q-0.53125 0.453125 -1.015625 0.640625q-0.46875 0.171875 -1.015625 0.171875q-0.921875 0 -1.40625 -0.4375q-0.484375 -0.453125 -0.484375 -1.140625q0 -0.40625 0.171875 -0.734375q0.1875 -0.34375 0.484375 -0.546875q0.3125 -0.203125 0.6875 -0.3125q0.265625 -0.0625 0.828125 -0.140625q1.125 -0.125 1.671875 -0.3125q0 -0.203125 0 -0.25q0 -0.578125 -0.265625 -0.8125q-0.359375 -0.3125 -1.0625 -0.3125q-0.65625 0 -0.984375 0.234375q-0.3125 0.234375 -0.453125 0.8125l-0.921875 -0.125q0.125 -0.578125 0.40625 -0.9375q0.296875 -0.375 0.828125 -0.5625q0.546875 -0.203125 1.25 -0.203125q0.71875 0 1.15625 0.171875q0.4375 0.171875 0.640625 0.421875q0.21875 0.25 0.296875 0.640625q0.046875 0.234375 0.046875 0.859375l0 1.25q0 1.296875 0.0625 1.65625q0.0625 0.34375 0.234375 0.65625l-0.96875 0q-0.15625 -0.296875 -0.1875 -0.6875zm-0.078125 -2.078125q-0.515625 0.203125 -1.53125 0.34375q-0.578125 0.078125 -0.828125 0.1875q-0.234375 0.109375 -0.359375 0.3125q-0.125 0.1875 -0.125 0.4375q0 0.375 0.28125 0.625q0.28125 0.25 0.828125 0.25q0.53125 0 0.953125 -0.234375q0.421875 -0.234375 0.625 -0.65625q0.15625 -0.3125 0.15625 -0.9375l0 -0.328125zm5.9733734 2.765625l0 -0.703125q-0.515625 0.828125 -1.546875 0.828125q-0.65625 0 -1.21875 -0.359375q-0.546875 -0.375 -0.859375 -1.015625q-0.296875 -0.65625 -0.296875 -1.5q0 -0.828125 0.28125 -1.5q0.28125 -0.6875 0.828125 -1.046875q0.546875 -0.359375 1.234375 -0.359375q0.5 0 0.890625 0.21875q0.390625 0.203125 0.625 0.546875l0 -2.734375l0.9375 0l0 7.625l-0.875 0zm-2.953125 -2.75q0 1.046875 0.4375 1.578125q0.453125 0.53125 1.0625 0.53125q0.609375 0 1.03125 -0.5q0.4375 -0.515625 0.4375 -1.53125q0 -1.140625 -0.4375 -1.671875q-0.4375 -0.53125 -1.078125 -0.53125q-0.609375 0 -1.03125 0.515625q-0.421875 0.5 -0.421875 1.609375zm4.9264984 1.09375l0.921875 -0.140625q0.078125 0.5625 0.4375 0.859375q0.359375 0.296875 1.0 0.296875q0.640625 0 0.953125 -0.265625q0.3125 -0.265625 0.3125 -0.625q0 -0.3125 -0.28125 -0.5q-0.1875 -0.125 -0.953125 -0.3125q-1.03125 -0.265625 -1.4375 -0.453125q-0.390625 -0.1875 -0.59375 -0.515625q-0.203125 -0.34375 -0.203125 -0.75q0 -0.359375 0.171875 -0.671875q0.171875 -0.328125 0.453125 -0.53125q0.21875 -0.15625 0.59375 -0.265625q0.390625 -0.125 0.8125 -0.125q0.65625 0 1.140625 0.1875q0.5 0.1875 0.734375 0.515625q0.234375 0.3125 0.3125 0.859375l-0.90625 0.125q-0.0625 -0.4375 -0.375 -0.671875q-0.296875 -0.234375 -0.828125 -0.234375q-0.65625 0 -0.9375 0.21875q-0.265625 0.203125 -0.265625 0.484375q0 0.1875 0.109375 0.328125q0.125 0.15625 0.359375 0.25q0.140625 0.0625 0.828125 0.25q1.0 0.265625 1.390625 0.4375q0.390625 0.15625 0.609375 0.484375q0.234375 0.3125 0.234375 0.796875q0 0.46875 -0.28125 0.890625q-0.265625 0.40625 -0.78125 0.640625q-0.515625 0.21875 -1.171875 0.21875q-1.078125 0 -1.640625 -0.4375q-0.5625 -0.453125 -0.71875 -1.34375z" fill-rule="nonzero"/><path fill="#000000" d="m16.179901 512.3386l0.921875 0.125q-0.15625 0.953125 -0.78125 1.5q-0.625 0.53125 -1.53125 0.53125q-1.125 0 -1.8125 -0.734375q-0.6875 -0.75 -0.6875 -2.1250305q0 -0.90625 0.296875 -1.578125q0.296875 -0.671875 0.890625 -1.0q0.609375 -0.34375 1.328125 -0.34375q0.890625 0 1.46875 0.46875q0.578125 0.453125 0.734375 1.28125l-0.90625 0.140625q-0.140625 -0.546875 -0.46875 -0.828125q-0.328125 -0.28125 -0.796875 -0.28125q-0.703125 0 -1.15625 0.515625q-0.4375 0.5 -0.4375 1.59375q0 1.1094055 0.421875 1.6250305q0.4375 0.5 1.125 0.5q0.546875 0 0.90625 -0.34375q0.375 -0.34375 0.484375 -1.046875zm5.328125 1.34375q-0.53125 0.453125 -1.015625 0.640625q-0.46875 0.171875 -1.015625 0.171875q-0.921875 0 -1.40625 -0.4375q-0.484375 -0.453125 -0.484375 -1.140625q0 -0.40625 0.171875 -0.734375q0.1875 -0.34378052 0.484375 -0.5469055q0.3125 -0.203125 0.6875 -0.3125q0.265625 -0.0625 0.828125 -0.140625q1.125 -0.125 1.671875 -0.3125q0 -0.203125 0 -0.25q0 -0.578125 -0.265625 -0.8125q-0.359375 -0.3125 -1.0625 -0.3125q-0.65625 0 -0.984375 0.234375q-0.3125 0.234375 -0.453125 0.8125l-0.921875 -0.125q0.125 -0.578125 0.40625 -0.9375q0.296875 -0.375 0.828125 -0.5625q0.546875 -0.203125 1.25 -0.203125q0.71875 0 1.15625 0.171875q0.4375 0.171875 0.640625 0.421875q0.21875 0.25 0.296875 0.640625q0.046875 0.234375 0.046875 0.859375l0 1.2500305q0 1.296875 0.0625 1.65625q0.0625 0.34375 0.234375 0.65625l-0.96875 0q-0.15625 -0.296875 -0.1875 -0.6875zm-0.078125 -2.0781555q-0.515625 0.203125 -1.53125 0.34375q-0.578125 0.07815552 -0.828125 0.18753052q-0.234375 0.109375 -0.359375 0.3125q-0.125 0.1875 -0.125 0.4375q0 0.375 0.28125 0.625q0.28125 0.25 0.828125 0.25q0.53125 0 0.953125 -0.234375q0.421875 -0.234375 0.625 -0.65625q0.15625 -0.3125 0.15625 -0.9375305l0 -0.328125zm2.3952484 2.7656555l0 -5.5312805l0.84375 0l0 0.796875q0.609375 -0.921875 1.75 -0.921875q0.5 0 0.921875 0.1875q0.421875 0.171875 0.625 0.46875q0.21875 0.296875 0.296875 0.6875q0.046875 0.265625 0.046875 0.921875l0 3.3906555l-0.9375 0l0 -3.3594055q0 -0.578125 -0.109375 -0.859375q-0.109375 -0.28125 -0.390625 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.59375 0 -1.03125 0.390625q-0.4375 0.375 -0.4375 1.4375l0 3.0156555l-0.9375 0zm8.871521 0l0 -5.5312805l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.8906555l-0.9375 0zm7.1892395 0l0 -0.8125q-0.65625 0.9375 -1.75 0.9375q-0.5 0 -0.921875 -0.1875q-0.421875 -0.1875 -0.625 -0.46875q-0.203125 -0.28125 -0.296875 -0.703125q-0.046875 -0.265625 -0.046875 -0.875l0 -3.4219055l0.9375 0l0 3.0625q0 0.7344055 0.046875 1.0000305q0.09375 0.359375 0.375 0.578125q0.296875 0.203125 0.703125 0.203125q0.421875 0 0.796875 -0.203125q0.375 -0.21875 0.515625 -0.59375q0.15625 -0.375 0.15625 -1.0781555l0 -2.96875l0.9375 0l0 5.5312805l-0.828125 0zm2.3014984 0l0 -5.5312805l0.84375 0l0 0.796875q0.609375 -0.921875 1.75 -0.921875q0.5 0 0.921875 0.1875q0.421875 0.171875 0.625 0.46875q0.21875 0.296875 0.296875 0.6875q0.046875 0.265625 0.046875 0.921875l0 3.3906555l-0.9375 0l0 -3.3594055q0 -0.578125 -0.109375 -0.859375q-0.109375 -0.28125 -0.390625 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.59375 0 -1.03125 0.390625q-0.4375 0.375 -0.4375 1.4375l0 3.0156555l-0.9375 0zm8.887146 -6.5469055l0 -1.078125l0.9375 0l0 1.078125l-0.9375 0zm0 6.5469055l0 -5.5312805l0.9375 0l0 5.5312805l-0.9375 0zm2.3674774 0l0 -5.5312805l0.84375 0l0 0.796875q0.609375 -0.921875 1.75 -0.921875q0.5 0 0.921875 0.1875q0.421875 0.171875 0.625 0.46875q0.21875 0.296875 0.296875 0.6875q0.046875 0.265625 0.046875 0.921875l0 3.3906555l-0.9375 0l0 -3.3594055q0 -0.578125 -0.109375 -0.859375q-0.109375 -0.28125 -0.390625 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.59375 0 -1.03125 0.390625q-0.4375 0.375 -0.4375 1.4375l0 3.0156555l-0.9375 0zm8.887146 2.125l0 -7.6562805l0.859375 0l0 0.71875q0.296875 -0.421875 0.671875 -0.625q0.390625 -0.21875 0.921875 -0.21875q0.703125 0 1.25 0.375q0.546875 0.359375 0.8125 1.03125q0.28125 0.65625 0.28125 1.453125q0 0.8437805 -0.3125 1.5312805q-0.296875 0.671875 -0.875 1.03125q-0.578125 0.359375 -1.21875 0.359375q-0.46875 0 -0.84375 -0.1875q-0.375 -0.203125 -0.609375 -0.515625l0 2.703125l-0.9375 0zm0.84375 -4.8594055q0 1.0625305 0.4375 1.5781555q0.4375 0.515625 1.046875 0.515625q0.625 0 1.0625 -0.53125q0.453125 -0.53125 0.453125 -1.6406555q0 -1.046875 -0.4375 -1.578125q-0.4375 -0.53125 -1.046875 -0.53125q-0.59375 0 -1.0625 0.5625q-0.453125 0.5625 -0.453125 1.625zm8.692123 2.0469055q-0.53125 0.453125 -1.015625 0.640625q-0.46875 0.171875 -1.015625 0.171875q-0.921875 0 -1.40625 -0.4375q-0.484375 -0.453125 -0.484375 -1.140625q0 -0.40625 0.171875 -0.734375q0.1875 -0.34378052 0.484375 -0.5469055q0.3125 -0.203125 0.6875 -0.3125q0.265625 -0.0625 0.828125 -0.140625q1.125 -0.125 1.671875 -0.3125q0 -0.203125 0 -0.25q0 -0.578125 -0.265625 -0.8125q-0.359375 -0.3125 -1.0625 -0.3125q-0.65625 0 -0.984375 0.234375q-0.3125 0.234375 -0.453125 0.8125l-0.921875 -0.125q0.125 -0.578125 0.40625 -0.9375q0.296875 -0.375 0.828125 -0.5625q0.546875 -0.203125 1.25 -0.203125q0.71875 0 1.15625 0.171875q0.4375 0.171875 0.640625 0.421875q0.21875 0.25 0.296875 0.640625q0.046875 0.234375 0.046875 0.859375l0 1.2500305q0 1.296875 0.0625 1.65625q0.0625 0.34375 0.234375 0.65625l-0.96875 0q-0.15625 -0.296875 -0.1875 -0.6875zm-0.078125 -2.0781555q-0.515625 0.203125 -1.53125 0.34375q-0.578125 0.07815552 -0.828125 0.18753052q-0.234375 0.109375 -0.359375 0.3125q-0.125 0.1875 -0.125 0.4375q0 0.375 0.28125 0.625q0.28125 0.25 0.828125 0.25q0.53125 0 0.953125 -0.234375q0.421875 -0.234375 0.625 -0.65625q0.15625 -0.3125 0.15625 -0.9375305l0 -0.328125zm2.3796234 2.7656555l0 -5.5312805l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.8906555l-0.9375 0zm7.1736145 -0.6875q-0.53125 0.453125 -1.015625 0.640625q-0.46875 0.171875 -1.015625 0.171875q-0.921875 0 -1.40625 -0.4375q-0.484375 -0.453125 -0.484375 -1.140625q0 -0.40625 0.171875 -0.734375q0.1875 -0.34378052 0.484375 -0.5469055q0.3125 -0.203125 0.6875 -0.3125q0.265625 -0.0625 0.828125 -0.140625q1.125 -0.125 1.671875 -0.3125q0 -0.203125 0 -0.25q0 -0.578125 -0.265625 -0.8125q-0.359375 -0.3125 -1.0625 -0.3125q-0.65625 0 -0.984375 0.234375q-0.3125 0.234375 -0.453125 0.8125l-0.921875 -0.125q0.125 -0.578125 0.40625 -0.9375q0.296875 -0.375 0.828125 -0.5625q0.546875 -0.203125 1.25 -0.203125q0.71875 0 1.15625 0.171875q0.4375 0.171875 0.640625 0.421875q0.21875 0.25 0.296875 0.640625q0.046875 0.234375 0.046875 0.859375l0 1.2500305q0 1.296875 0.0625 1.65625q0.0625 0.34375 0.234375 0.65625l-0.96875 0q-0.15625 -0.296875 -0.1875 -0.6875zm-0.078125 -2.0781555q-0.515625 0.203125 -1.53125 0.34375q-0.578125 0.07815552 -0.828125 0.18753052q-0.234375 0.109375 -0.359375 0.3125q-0.125 0.1875 -0.125 0.4375q0 0.375 0.28125 0.625q0.28125 0.25 0.828125 0.25q0.53125 0 0.953125 -0.234375q0.421875 -0.234375 0.625 -0.65625q0.15625 -0.3125 0.15625 -0.9375305l0 -0.328125zm2.3796234 2.7656555l0 -7.6250305l0.9375 0l0 7.6250305l-0.9375 0zm2.3674774 0l0 -7.6250305l0.9375 0l0 7.6250305l-0.9375 0zm6.1643524 -1.78125l0.96875 0.125q-0.234375 0.84375 -0.859375 1.3125q-0.609375 0.46875 -1.578125 0.46875q-1.203125 0 -1.921875 -0.75q-0.703125 -0.75 -0.703125 -2.0937805q0 -1.390625 0.71875 -2.15625q0.71875 -0.78125 1.859375 -0.78125q1.109375 0 1.8125 0.765625q0.703125 0.75 0.703125 2.125q0 0.078125 0 0.234375l-4.125 0q0.046875 0.9219055 0.515625 1.4062805q0.46875 0.484375 1.15625 0.484375q0.515625 0 0.875 -0.265625q0.359375 -0.28125 0.578125 -0.875zm-3.078125 -1.5156555l3.09375 0q-0.0625 -0.6875 -0.359375 -1.046875q-0.453125 -0.53125 -1.15625 -0.53125q-0.640625 0 -1.09375 0.4375q-0.4375 0.421875 -0.484375 1.140625zm5.2077484 3.2969055l0 -7.6250305l0.9375 0l0 7.6250305l-0.9375 0zm2.6487274 0l0 -1.0625l1.0625 0l0 1.0625l-1.0625 0zm4.3483734 0l2.921875 -7.6250305l1.09375 0l3.125 7.6250305l-1.15625 0l-0.890625 -2.3125l-3.1875 0l-0.828125 2.3125l-1.078125 0zm2.203125 -3.1250305l2.578125 0l-0.796875 -2.125q-0.359375 -0.953125 -0.53125 -1.578125q-0.15625 0.734375 -0.421875 1.453125l-0.828125 2.25zm9.2326355 1.0937805l0.921875 0.125q-0.15625 0.953125 -0.78125 1.5q-0.625 0.53125 -1.53125 0.53125q-1.125 0 -1.8125 -0.734375q-0.6875 -0.75 -0.6875 -2.1250305q0 -0.90625 0.296875 -1.578125q0.296875 -0.671875 0.890625 -1.0q0.609375 -0.34375 1.328125 -0.34375q0.890625 0 1.46875 0.46875q0.578125 0.453125 0.734375 1.28125l-0.90625 0.140625q-0.140625 -0.546875 -0.46875 -0.828125q-0.328125 -0.28125 -0.796875 -0.28125q-0.703125 0 -1.15625 0.515625q-0.4375 0.5 -0.4375 1.59375q0 1.1094055 0.421875 1.6250305q0.4375 0.5 1.125 0.5q0.546875 0 0.90625 -0.34375q0.375 -0.34375 0.484375 -1.046875zm3.765625 1.1875l0.125 0.828125q-0.390625 0.09375 -0.703125 0.09375q-0.5 0 -0.78125 -0.15625q-0.28125 -0.171875 -0.40625 -0.4375q-0.109375 -0.265625 -0.109375 -1.109375l0 -3.1719055l-0.6875 0l0 -0.734375l0.6875 0l0 -1.359375l0.9375 -0.5625l0 1.921875l0.9375 0l0 0.734375l-0.9375 0l0 3.2344055q0 0.390625 0.046875 0.515625q0.046875 0.109375 0.15625 0.1875q0.109375 0.0625 0.328125 0.0625q0.15625 0 0.40625 -0.046875zm0.5700226 -1.9219055q0 -1.53125 0.84375 -2.265625q0.71875 -0.625 1.734375 -0.625q1.140625 0 1.859375 0.75q0.734375 0.75 0.734375 2.0625q0 1.0625305 -0.328125 1.6875305q-0.3125 0.609375 -0.921875 0.953125q-0.609375 0.328125 -1.34375 0.328125q-1.15625 0 -1.875 -0.734375q-0.703125 -0.75 -0.703125 -2.1562805zm0.953125 0q0 1.0625305 0.46875 1.5937805q0.46875 0.53125 1.15625 0.53125q0.703125 0 1.15625 -0.53125q0.46875 -0.53125 0.46875 -1.6250305q0 -1.015625 -0.46875 -1.546875q-0.453125 -0.53125 -1.15625 -0.53125q-0.6875 0 -1.15625 0.53125q-0.46875 0.515625 -0.46875 1.578125zm5.3014984 2.7656555l0 -5.5312805l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.8906555l-0.9375 0zm6.524887 -6.5469055l0 -1.078125l0.9375 0l0 1.078125l-0.9375 0zm0 6.5469055l0 -5.5312805l0.9375 0l0 5.5312805l-0.9375 0zm1.9924774 -1.65625l0.921875 -0.140625q0.078125 0.5625 0.4375 0.859375q0.359375 0.296875 1.0 0.296875q0.640625 0 0.953125 -0.265625q0.3125 -0.265625 0.3125 -0.625q0 -0.3125 -0.28125 -0.5q-0.1875 -0.125 -0.953125 -0.3125q-1.03125 -0.26565552 -1.4375 -0.45315552q-0.390625 -0.1875 -0.59375 -0.515625q-0.203125 -0.34375 -0.203125 -0.75q0 -0.359375 0.171875 -0.671875q0.171875 -0.328125 0.453125 -0.53125q0.21875 -0.15625 0.59375 -0.265625q0.390625 -0.125 0.8125 -0.125q0.65625 0 1.140625 0.1875q0.5 0.1875 0.734375 0.515625q0.234375 0.3125 0.3125 0.859375l-0.90625 0.125q-0.0625 -0.4375 -0.375 -0.671875q-0.296875 -0.234375 -0.828125 -0.234375q-0.65625 0 -0.9375 0.21875q-0.265625 0.203125 -0.265625 0.484375q0 0.1875 0.109375 0.328125q0.125 0.15625 0.359375 0.25q0.140625 0.0625 0.828125 0.25q1.0 0.265625 1.390625 0.4375q0.390625 0.15625 0.609375 0.484375q0.234375 0.31253052 0.234375 0.7969055q0 0.46875 -0.28125 0.890625q-0.265625 0.40625 -0.78125 0.640625q-0.515625 0.21875 -1.171875 0.21875q-1.078125 0 -1.640625 -0.4375q-0.5625 -0.453125 -0.71875 -1.34375z" fill-rule="nonzero"/><path fill="#000000" d="m12.195526 525.7136l0.921875 -0.140625q0.078125 0.5625 0.4375 0.859375q0.359375 0.296875 1.0 0.296875q0.640625 0 0.953125 -0.265625q0.3125 -0.265625 0.3125 -0.625q0 -0.3125 -0.28125 -0.5q-0.1875 -0.125 -0.953125 -0.3125q-1.03125 -0.265625 -1.4375 -0.453125q-0.390625 -0.1875 -0.59375 -0.515625q-0.203125 -0.34375 -0.203125 -0.75q0 -0.359375 0.171875 -0.671875q0.171875 -0.328125 0.453125 -0.53125q0.21875 -0.15625 0.59375 -0.265625q0.390625 -0.125 0.8125 -0.125q0.65625 0 1.140625 0.1875q0.5 0.1875 0.734375 0.515625q0.234375 0.3125 0.3125 0.859375l-0.90625 0.125q-0.0625 -0.4375 -0.375 -0.671875q-0.296875 -0.234375 -0.828125 -0.234375q-0.65625 0 -0.9375 0.21875q-0.265625 0.203125 -0.265625 0.484375q0 0.1875 0.109375 0.328125q0.125 0.15625 0.359375 0.25q0.140625 0.0625 0.828125 0.25q1.0 0.265625 1.390625 0.4375q0.390625 0.15625 0.609375 0.484375q0.234375 0.3125 0.234375 0.796875q0 0.46875 -0.28125 0.890625q-0.265625 0.40625 -0.78125 0.640625q-0.515625 0.21875 -1.171875 0.21875q-1.078125 0 -1.640625 -0.4375q-0.5625 -0.453125 -0.71875 -1.34375zm9.484375 -0.125l0.96875 0.125q-0.234375 0.84375 -0.859375 1.3125q-0.609375 0.46875 -1.578125 0.46875q-1.203125 0 -1.921875 -0.75q-0.703125 -0.75 -0.703125 -2.09375q0 -1.390625 0.71875 -2.15625q0.71875 -0.78125 1.859375 -0.78125q1.109375 0 1.8125 0.765625q0.703125 0.75 0.703125 2.125q0 0.078125 0 0.234375l-4.125 0q0.046875 0.921875 0.515625 1.40625q0.46875 0.484375 1.15625 0.484375q0.515625 0 0.875 -0.265625q0.359375 -0.28125 0.578125 -0.875zm-3.078125 -1.515625l3.09375 0q-0.0625 -0.6875 -0.359375 -1.046875q-0.453125 -0.53125 -1.15625 -0.53125q-0.640625 0 -1.09375 0.4375q-0.4375 0.421875 -0.484375 1.140625zm5.2077484 3.296875l0 -7.625l0.9375 0l0 7.625l-0.9375 0zm6.1643524 -1.78125l0.96875 0.125q-0.234375 0.84375 -0.859375 1.3125q-0.609375 0.46875 -1.578125 0.46875q-1.203125 0 -1.921875 -0.75q-0.703125 -0.75 -0.703125 -2.09375q0 -1.390625 0.71875 -2.15625q0.71875 -0.78125 1.859375 -0.78125q1.109375 0 1.8125 0.765625q0.703125 0.75 0.703125 2.125q0 0.078125 0 0.234375l-4.125 0q0.046875 0.921875 0.515625 1.40625q0.46875 0.484375 1.15625 0.484375q0.515625 0 0.875 -0.265625q0.359375 -0.28125 0.578125 -0.875zm-3.078125 -1.515625l3.09375 0q-0.0625 -0.6875 -0.359375 -1.046875q-0.453125 -0.53125 -1.15625 -0.53125q-0.640625 0 -1.09375 0.4375q-0.4375 0.421875 -0.484375 1.140625zm8.832748 1.265625l0.921875 0.125q-0.15625 0.953125 -0.78125 1.5q-0.625 0.53125 -1.53125 0.53125q-1.125 0 -1.8125 -0.734375q-0.6875 -0.75 -0.6875 -2.125q0 -0.90625 0.296875 -1.578125q0.296875 -0.671875 0.890625 -1.0q0.609375 -0.34375 1.328125 -0.34375q0.890625 0 1.46875 0.46875q0.578125 0.453125 0.734375 1.28125l-0.90625 0.140625q-0.140625 -0.546875 -0.46875 -0.828125q-0.328125 -0.28125 -0.796875 -0.28125q-0.703125 0 -1.15625 0.515625q-0.4375 0.5 -0.4375 1.59375q0 1.109375 0.421875 1.625q0.4375 0.5 1.125 0.5q0.546875 0 0.90625 -0.34375q0.375 -0.34375 0.484375 -1.046875zm3.765625 1.1875l0.125 0.828125q-0.390625 0.09375 -0.703125 0.09375q-0.5 0 -0.78125 -0.15625q-0.28125 -0.171875 -0.40625 -0.4375q-0.109375 -0.265625 -0.109375 -1.109375l0 -3.171875l-0.6875 0l0 -0.734375l0.6875 0l0 -1.359375l0.9375 -0.5625l0 1.921875l0.9375 0l0 0.734375l-0.9375 0l0 3.234375q0 0.390625 0.046875 0.515625q0.046875 0.109375 0.15625 0.1875q0.109375 0.0625 0.328125 0.0625q0.15625 0 0.40625 -0.046875zm4.6950226 -0.9375l0.96875 0.125q-0.234375 0.84375 -0.859375 1.3125q-0.609375 0.46875 -1.578125 0.46875q-1.203125 0 -1.921875 -0.75q-0.703125 -0.75 -0.703125 -2.09375q0 -1.390625 0.71875 -2.15625q0.71875 -0.78125 1.859375 -0.78125q1.109375 0 1.8125 0.765625q0.703125 0.75 0.703125 2.125q0 0.078125 0 0.234375l-4.125 0q0.046875 0.921875 0.515625 1.40625q0.46875 0.484375 1.15625 0.484375q0.515625 0 0.875 -0.265625q0.359375 -0.28125 0.578125 -0.875zm-3.078125 -1.515625l3.09375 0q-0.0625 -0.6875 -0.359375 -1.046875q-0.453125 -0.53125 -1.15625 -0.53125q-0.640625 0 -1.09375 0.4375q-0.4375 0.421875 -0.484375 1.140625zm8.801498 3.296875l0 -0.703125q-0.515625 0.828125 -1.546875 0.828125q-0.65625 0 -1.21875 -0.359375q-0.546875 -0.375 -0.859375 -1.015625q-0.296875 -0.65625 -0.296875 -1.5q0 -0.828125 0.28125 -1.5q0.28125 -0.6875 0.828125 -1.046875q0.546875 -0.359375 1.234375 -0.359375q0.5 0 0.890625 0.21875q0.390625 0.203125 0.625 0.546875l0 -2.734375l0.9375 0l0 7.625l-0.875 0zm-2.953125 -2.75q0 1.046875 0.4375 1.578125q0.453125 0.53125 1.0625 0.53125q0.609375 0 1.03125 -0.5q0.4375 -0.515625 0.4375 -1.53125q0 -1.140625 -0.4375 -1.671875q-0.4375 -0.53125 -1.078125 -0.53125q-0.609375 0 -1.03125 0.515625q-0.421875 0.5 -0.421875 1.609375zm9.121521 2.75l-0.859375 0l0 -7.625l0.9375 0l0 2.71875q0.59375 -0.75 1.5 -0.75q0.515625 0 0.96875 0.21875q0.453125 0.203125 0.75 0.578125q0.296875 0.359375 0.453125 0.890625q0.171875 0.53125 0.171875 1.125q0 1.421875 -0.703125 2.203125q-0.703125 0.765625 -1.6875 0.765625q-0.96875 0 -1.53125 -0.8125l0 0.6875zm0 -2.796875q0 0.984375 0.265625 1.421875q0.4375 0.734375 1.1875 0.734375q0.625 0 1.0625 -0.53125q0.453125 -0.546875 0.453125 -1.59375q0 -1.078125 -0.4375 -1.59375q-0.421875 -0.515625 -1.03125 -0.515625q-0.609375 0 -1.0625 0.53125q-0.4375 0.53125 -0.4375 1.546875zm5.0202484 4.921875l-0.09375 -0.875q0.296875 0.078125 0.53125 0.078125q0.3125 0 0.5 -0.109375q0.1875 -0.09375 0.3125 -0.28125q0.078125 -0.140625 0.28125 -0.703125q0.03125 -0.078125 0.078125 -0.21875l-2.09375 -5.546875l1.015625 0l1.140625 3.203125q0.234375 0.609375 0.40625 1.28125q0.15625 -0.640625 0.375 -1.265625l1.1875 -3.21875l0.9375 0l-2.109375 5.625q-0.328125 0.90625 -0.515625 1.25q-0.25 0.46875 -0.578125 0.6875q-0.3125 0.21875 -0.765625 0.21875q-0.265625 0 -0.609375 -0.125zm8.320023 -2.125l0 -5.53125l0.84375 0l0 0.84375q0.328125 -0.59375 0.59375 -0.78125q0.28125 -0.1875 0.609375 -0.1875q0.46875 0 0.953125 0.3125l-0.3125 0.859375q-0.34375 -0.203125 -0.6875 -0.203125q-0.3125 0 -0.5625 0.1875q-0.234375 0.1875 -0.34375 0.515625q-0.15625 0.5 -0.15625 1.09375l0 2.890625l-0.9375 0zm2.9392395 0l2.015625 -2.875l-1.859375 -2.65625l1.171875 0l0.84375 1.296875q0.234375 0.375 0.390625 0.625q0.21875 -0.34375 0.40625 -0.609375l0.9375 -1.3125l1.125 0l-1.921875 2.609375l2.0625 2.921875l-1.15625 0l-1.125 -1.71875l-0.296875 -0.46875l-1.453125 2.1875l-1.140625 0zm5.09375 2.125l0 -0.6875l6.203125 0l0 0.6875l-6.203125 0zm6.4108734 -3.78125l0.921875 -0.140625q0.078125 0.5625 0.4375 0.859375q0.359375 0.296875 1.0 0.296875q0.640625 0 0.953125 -0.265625q0.3125 -0.265625 0.3125 -0.625q0 -0.3125 -0.28125 -0.5q-0.1875 -0.125 -0.953125 -0.3125q-1.03125 -0.265625 -1.4375 -0.453125q-0.390625 -0.1875 -0.59375 -0.515625q-0.203125 -0.34375 -0.203125 -0.75q0 -0.359375 0.171875 -0.671875q0.171875 -0.328125 0.453125 -0.53125q0.21875 -0.15625 0.59375 -0.265625q0.390625 -0.125 0.8125 -0.125q0.65625 0 1.140625 0.1875q0.5 0.1875 0.734375 0.515625q0.234375 0.3125 0.3125 0.859375l-0.90625 0.125q-0.0625 -0.4375 -0.375 -0.671875q-0.296875 -0.234375 -0.828125 -0.234375q-0.65625 0 -0.9375 0.21875q-0.265625 0.203125 -0.265625 0.484375q0 0.1875 0.109375 0.328125q0.125 0.15625 0.359375 0.25q0.140625 0.0625 0.828125 0.25q1.0 0.265625 1.390625 0.4375q0.390625 0.15625 0.609375 0.484375q0.234375 0.3125 0.234375 0.796875q0 0.46875 -0.28125 0.890625q-0.265625 0.40625 -0.78125 0.640625q-0.515625 0.21875 -1.171875 0.21875q-1.078125 0 -1.640625 -0.4375q-0.5625 -0.453125 -0.71875 -1.34375zm5.6875 1.65625l0 -7.625l0.9375 0l0 7.625l-0.9375 0zm2.0393524 -2.765625q0 -1.53125 0.84375 -2.265625q0.71875 -0.625 1.734375 -0.625q1.140625 0 1.859375 0.75q0.734375 0.75 0.734375 2.0625q0 1.0625 -0.328125 1.6875q-0.3125 0.609375 -0.921875 0.953125q-0.609375 0.328125 -1.34375 0.328125q-1.15625 0 -1.875 -0.734375q-0.703125 -0.75 -0.703125 -2.15625zm0.953125 0q0 1.0625 0.46875 1.59375q0.46875 0.53125 1.15625 0.53125q0.703125 0 1.15625 -0.53125q0.46875 -0.53125 0.46875 -1.625q0 -1.015625 -0.46875 -1.546875q-0.453125 -0.53125 -1.15625 -0.53125q-0.6875 0 -1.15625 0.53125q-0.46875 0.515625 -0.46875 1.578125zm7.3639984 1.921875l0.125 0.828125q-0.390625 0.09375 -0.703125 0.09375q-0.5 0 -0.78125 -0.15625q-0.28125 -0.171875 -0.40625 -0.4375q-0.109375 -0.265625 -0.109375 -1.109375l0 -3.171875l-0.6875 0l0 -0.734375l0.6875 0l0 -1.359375l0.9375 -0.5625l0 1.921875l0.9375 0l0 0.734375l-0.9375 0l0 3.234375q0 0.390625 0.046875 0.515625q0.046875 0.109375 0.15625 0.1875q0.109375 0.0625 0.328125 0.0625q0.15625 0 0.40625 -0.046875zm3.7962952 -4.953125q0 -0.8125 0.40625 -1.390625q0.40625 -0.578125 1.1875 -0.578125q0.71875 0 1.1875 0.515625q0.46875 0.515625 0.46875 1.515625q0 0.96875 -0.484375 1.5q-0.46875 0.515625 -1.15625 0.515625q-0.6875 0 -1.15625 -0.515625q-0.453125 -0.515625 -0.453125 -1.5625zm1.625 -1.3125q-0.34375 0 -0.578125 0.296875q-0.234375 0.296875 -0.234375 1.109375q0 0.734375 0.234375 1.03125q0.234375 0.296875 0.578125 0.296875q0.359375 0 0.578125 -0.296875q0.234375 -0.296875 0.234375 -1.109375q0 -0.734375 -0.234375 -1.03125q-0.234375 -0.296875 -0.578125 -0.296875zm0 7.390625l4.171875 -8.046875l0.765625 0l-4.15625 8.046875l-0.78125 0zm3.296875 -2.078125q0 -0.8125 0.40625 -1.375q0.421875 -0.578125 1.203125 -0.578125q0.71875 0 1.1875 0.515625q0.46875 0.515625 0.46875 1.5q0 0.96875 -0.46875 1.5q-0.46875 0.515625 -1.171875 0.515625q-0.703125 0 -1.171875 -0.515625q-0.453125 -0.515625 -0.453125 -1.5625zm1.640625 -1.3125q-0.359375 0 -0.59375 0.3125q-0.21875 0.296875 -0.21875 1.09375q0 0.734375 0.234375 1.046875q0.234375 0.296875 0.578125 0.296875q0.359375 0 0.578125 -0.296875q0.234375 -0.3125 0.234375 -1.109375q0 -0.75 -0.234375 -1.046875q-0.234375 -0.296875 -0.578125 -0.296875zm8.6857605 3.109375l0 -1.828125l-3.296875 0l0 -0.859375l3.46875 -4.9375l0.765625 0l0 4.9375l1.03125 0l0 0.859375l-1.03125 0l0 1.828125l-0.9375 0zm0 -2.6875l0 -3.4375l-2.375 3.4375l2.375 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m131.73615 206.8332l0 0c0 -5.4069824 4.3832245 -9.790222 9.790222 -9.790222l124.57703 0c2.596527 0 5.0867004 1.0314789 6.9227295 2.8674927c1.836029 1.836029 2.8674927 4.3262024 2.8674927 6.9227295l0 39.159714c0 5.4069977 -4.3832397 9.790222 -9.790222 9.790222l-124.57703 0l0 0c-5.4069977 0 -9.790222 -4.3832245 -9.790222 -9.790222z" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m131.73615 206.8332l0 0c0 -5.4069824 4.3832245 -9.790222 9.790222 -9.790222l124.57703 0c2.596527 0 5.0867004 1.0314789 6.9227295 2.8674927c1.836029 1.836029 2.8674927 4.3262024 2.8674927 6.9227295l0 39.159714c0 5.4069977 -4.3832397 9.790222 -9.790222 9.790222l-124.57703 0l0 0c-5.4069977 0 -9.790222 -4.3832245 -9.790222 -9.790222z" fill-rule="evenodd"/><path fill="#000000" d="m181.58737 219.44244l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm13.5625 1.421875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.917679 0.28125q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm4.188217 4.859375l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm0.94892883 -1.421875l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125z" fill-rule="nonzero"/><path fill="#000000" d="m153.75652 244.33307l0 -1.21875q-0.90625 1.4375 -2.703125 1.4375q-1.15625 0 -2.125 -0.640625q-0.96875 -0.640625 -1.5 -1.78125q-0.53125 -1.140625 -0.53125 -2.625q0 -1.453125 0.484375 -2.625q0.484375 -1.1875 1.4375 -1.8125q0.96875 -0.625 2.171875 -0.625q0.875 0 1.546875 0.375q0.6875 0.359375 1.109375 0.953125l0 -4.796875l1.640625 0l0 13.359375l-1.53125 0zm-5.171875 -4.828125q0 1.859375 0.78125 2.78125q0.78125 0.921875 1.84375 0.921875q1.078125 0 1.828125 -0.875q0.75 -0.890625 0.75 -2.6875q0 -1.984375 -0.765625 -2.90625q-0.765625 -0.9375 -1.890625 -0.9375q-1.078125 0 -1.8125 0.890625q-0.734375 0.890625 -0.734375 2.8125zm9.235092 4.828125l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm2.6760712 3.703125l0 -1.1875l10.859375 0l0 1.1875l-10.859375 0zm11.891342 0l0 -13.375l1.484375 0l0 1.25q0.53125 -0.734375 1.1875 -1.09375q0.671875 -0.375 1.625 -0.375q1.234375 0 2.171875 0.640625q0.953125 0.625 1.4375 1.796875q0.484375 1.15625 0.484375 2.546875q0 1.484375 -0.53125 2.671875q-0.53125 1.1875 -1.546875 1.828125q-1.015625 0.625 -2.140625 0.625q-0.8125 0 -1.46875 -0.34375q-0.65625 -0.34375 -1.0625 -0.875l0 4.703125l-1.640625 0zm1.484375 -8.484375q0 1.859375 0.75 2.765625q0.765625 0.890625 1.828125 0.890625q1.09375 0 1.875 -0.921875q0.78125 -0.9375 0.78125 -2.875q0 -1.84375 -0.765625 -2.765625q-0.75 -0.921875 -1.8125 -0.921875q-1.046875 0 -1.859375 0.984375q-0.796875 0.96875 -0.796875 2.84375zm8.875717 4.78125l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm5.618927 -4.84375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm15.610092 1.296875l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609375q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.296875q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm9.640625 0.4375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm8.485092 2.875l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm9.328125 0l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.71875 -1.375 1.125q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.78125 -1.25 -2.328125zm9.984375 -8.578125l0 -1.890625l1.640625 0l0 1.890625l-1.640625 0zm0 11.46875l0 -9.671875l1.640625 0l0 9.671875l-1.640625 0zm4.144821 0l0 -9.671875l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953125l-1.640625 0l0 -5.890625q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.28125l-1.640625 0zm10.063217 0.796875l1.59375 0.234375q0.109375 0.75 0.5625 1.078125q0.609375 0.453125 1.671875 0.453125q1.1406403 0 1.7500153 -0.453125q0.625 -0.453125 0.84375 -1.265625q0.125 -0.5 0.109375 -2.109375q-1.0625 1.265625 -2.6718903 1.265625q-2.0 0 -3.09375 -1.4375q-1.09375 -1.4375 -1.09375 -3.453125q0 -1.390625 0.5 -2.5625q0.515625 -1.171875 1.453125 -1.796875q0.953125 -0.640625 2.25 -0.640625q1.7031403 0 2.8125153 1.375l0 -1.15625l1.515625 0l0 8.359375q0 2.265625 -0.46875 3.203125q-0.453125 0.9375 -1.453125 1.484375q-0.984375 0.546875 -2.4531403 0.546875q-1.71875 0 -2.796875 -0.78125q-1.0625 -0.765625 -1.03125 -2.34375zm1.359375 -5.8125q0 1.90625 0.75 2.78125q0.765625 0.875 1.90625 0.875q1.1250153 0 1.8906403 -0.859375q0.765625 -0.875 0.765625 -2.734375q0 -1.78125 -0.796875 -2.671875q-0.78125 -0.90625 -1.8906403 -0.90625q-1.09375 0 -1.859375 0.890625q-0.765625 0.875 -0.765625 2.625z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m386.5906 103.64539l36.93576 0l0 0.06299591l36.922485 0" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m386.5906 103.64539l36.93576 0l0 0.06299591l36.922485 0" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m608.23236 103.65213l149.85828 0l0 97.41733" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m608.23236 103.65213l149.85828 0l0 91.41733" fill-rule="evenodd"/><path fill="#595959" stroke="#595959" stroke-width="1.0" stroke-linecap="butt" d="m756.4389 195.06946l1.6517334 4.538086l1.6517334 -4.538086z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m253.50398 133.01547l0 32.00743l-49.70079 0l0 32.024063" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m253.50398 133.01547l0 32.00743l-49.70079 0l0 32.024063" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m203.81488 255.78314l0 30.826904l0.06298828 0l0 30.810883" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m203.81488 255.78314l0 30.826904l0.06298828 0l0 24.810883" fill-rule="evenodd"/><path fill="#595959" stroke="#595959" stroke-width="1.0" stroke-linecap="butt" d="m202.22614 311.42093l1.6517334 4.538086l1.6517334 -4.538086z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m253.50398 133.01547l0 32.93631l113.82677 0l0 32.95346" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m253.50398 133.01547l0 32.93631l113.82677 0l0 32.95346" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m367.33633 249.1331l0 24.07344l0.06298828 0l0 24.084045" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m367.33633 249.1331l0 24.07344l0.06298828 0l0 18.084045" fill-rule="evenodd"/><path fill="#595959" stroke="#595959" stroke-width="1.0" stroke-linecap="butt" d="m365.7476 291.2906l1.6517334 4.538086l1.6517334 -4.538086z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m203.80923 463.86697l0 46.771667l214.4252 0" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m203.80923 463.86697l0 46.771667l214.4252 0" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m583.11914 510.63785l174.99213 0l0 -85.763794" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m583.1192 510.63785l174.99213 0l0 -79.763794" fill-rule="evenodd"/><path fill="#595959" stroke="#595959" stroke-width="1.0" stroke-linecap="butt" d="m759.76306 430.87405l-1.6517334 -4.538086l-1.6517334 4.538086z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m367.34338 443.75003l0 23.274658l133.32285 0l0 23.27652" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m367.34338 443.75003l0 23.274658l133.32285 0l0 23.27652" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m477.01956 370.53326l-36.4494 0l0 0.06298828l-36.46399 0" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m477.01956 370.53326l-36.4494 0l0 0.06298828l-30.46399 0" fill-rule="evenodd"/><path fill="#595959" stroke="#595959" stroke-width="1.0" stroke-linecap="butt" d="m410.10617 368.94452l-4.538086 1.6517334l4.538086 1.6517334z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m588.2006 312.98996l-36.440918 0l0 57.543304l-36.440918 0" fill-rule="evenodd"/><path stroke="#595959" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m588.2006 312.98996l-36.440918 0l0 57.543304l-36.440918 0" fill-rule="evenodd"/></g></svg> diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 552de278d13c56828d229fee055a8f3cecd79bfc..223d0c92f356e96c381eb6f4ca12d2bd8a2cde8e 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -193,6 +193,16 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, abort(); } +/* hack: nfapi code is common for 4G/5G, so some function calls are hardcoded. + * Provide body for 5G function not used in 4G code */ +void handle_nr_srs_measurements(const module_id_t module_id, + const frame_t frame, + const sub_frame_t slot, + nfapi_nr_srs_indication_pdu_t *srs_ind) +{ + return; +} + /* forward declarations */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 5a4002e609c30da3ccc2343bdf057465b8eba1bd..dd31088ff8724641c49704130f2da40dbf45da9c 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -621,7 +621,6 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) rxp, samples_per_slot, ru->nb_rx); - gNBscopeCopy(ru, gNbTimeDomainSamples, rxp[0], sizeof(c16_t), 1, samples_per_slot, 0); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); @@ -692,6 +691,11 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) *slot = proc->tti_rx; } + if (!emulate_rf) { + metadata mt = {.slot = *slot, .frame = *frame}; + gNBscopeCopyWithMetadata(ru, gNbTimeDomainSamples, rxp[0], sizeof(c16_t), 1, samples_per_slot, 0, &mt); + } + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, (proc->timestamp_rx+ru->ts_offset)&0xffffffff ); if (rxs != samples_per_slot) { diff --git a/executables/nr-ue.c b/executables/nr-ue.c index a7661b0c061f199951f01be93178f5108c441e9b..0aa966340be155f5cee47b1bf2ca40e618952664 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -39,6 +39,7 @@ #include "RRC/NR/MESSAGES/asn1_msg.h" #include "openair1/PHY/TOOLS/phy_scope_interface.h" #include "PHY/MODULATION/nr_modulation.h" +#include "instrumentation.h" /* * NR SLOT PROCESSING SEQUENCE @@ -99,6 +100,11 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg); +static void start_process_slot_tx(void* arg) { + notifiedFIFO_elt_t *newTx = arg; + pushTpool(&(get_nrUE_params()->Tpool), newTx); +} + static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len) { const char *begin = output; @@ -480,62 +486,17 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) void processSlotTX(void *arg) { + TracyCZone(ctx, true); nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg; const UE_nr_rxtx_proc_t *proc = &rxtxD->proc; PHY_VARS_NR_UE *UE = rxtxD->UE; nr_phy_data_tx_t phy_data = {0}; bool sl_tx_action = false; - // Force sequential execution, even if we launch in // for all slots - // at least ULstatus variable is a pure race condition that is quickly detected by assert() in the code because one thread sets it - // to active, so the other thread try to steal&run the ul work - if (rxtxD->stream_status == STREAM_STATUS_SYNCED) { - notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo + proc->nr_slot_tx); - delNotifiedFIFO_elt(res); - } - if (UE->if_inst) UE->if_inst->slot_indication(UE->Mod_id); - LOG_D(PHY, - "SlotTx %d.%d => slot type %d, wait: %d \n", - proc->frame_tx, - proc->nr_slot_tx, - proc->tx_slot_type, - rxtxD->tx_wait_for_dlsch); if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT) { - if (rxtxD->tx_wait_for_dlsch) - LOG_D(PHY, "enter wait for tx, slot %d, nb events to wait %d; ", proc->nr_slot_tx, rxtxD->tx_wait_for_dlsch); - // wait for rx slots to send indication (if any) that DLSCH decoding is finished - for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) { - notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo + proc->nr_slot_tx); - delNotifiedFIFO_elt(res); - } - LOG_D(PHY, "completed wait for tx, slot %d\n", proc->nr_slot_tx); - - /* - This herafter code is costing some perfomance for a check that should be useless - But, we face today several bugs arround the matching between events in UE->tx_resume_ind_fifo[slot] - and the corresponding tx_wait_for_dlsch[slot] - The algorithm is we accumlate the actions that should end before processing a tx slot in tx_wait_for_dlsch[slot] - later, other threads push events in UE->tx_resume_ind_fifo[slot] - so, the tx encoding starts only when related actions are done (mainly DLSCH ACK/NACK to encode PUCCH) - if there is a bug that misses to send a event in UE->tx_resume_ind_fifo[slot], the process hangs, we detect the issue - if there is a bug that makes a extra event in UE->tx_resume_ind_fifo[slot], and if we drop the hereafter check - the system runs with random race conditions, very hard to debug - - Likely we should later remove completly UE->tx_resume_ind_fifo with notifications, - instead, - we may run in place the processSlotTX() when the conditions are met (when a decreasing tx_wait_for_dlsch[slot] will become 0) - It will remove the condition signals (for a thread safe semaphore or counter) and make the system simpler - */ - notifiedFIFO_elt_t *res = pollNotifiedFIFO(UE->tx_resume_ind_fifo + proc->nr_slot_tx); - if (res) - LOG_E(NR_PHY, - "Internal error: extra event on Tx waiting queue for slot %d, event comes from rx slot %d\n", - proc->nr_slot_tx, - *(int *)NotifiedFifoData(res)); - if (UE->sl_mode == 2 && proc->tx_slot_type == NR_SIDELINK_SLOT) { // trigger L2 to run ue_sidelink_scheduler thru IF module if (UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) { @@ -584,14 +545,12 @@ void processSlotTX(void *arg) } } - notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(int), 0, NULL, NULL); - int *msgData = (int *)NotifiedFifoData(newElt); int slots_per_frame = (UE->sl_mode == 2) ? UE->SL_UE_PHY_PARAMS.sl_frame_params.slots_per_frame : UE->frame_parms.slots_per_frame; - int newslot = (proc->nr_slot_tx + 1) % slots_per_frame; - *msgData = newslot; - pushNotifiedFIFO(UE->tx_resume_ind_fifo + newslot, newElt); + int next_slot = (proc->nr_slot_tx + 1) % slots_per_frame; + dynamic_barrier_join(&UE->process_slot_tx_barriers[next_slot]); RU_write(rxtxD, sl_tx_action); + TracyCZoneEnd(ctx); } static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, @@ -600,6 +559,7 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, nr_phy_data_t *phy_data, bool *stats_printed) { + TracyCZone(ctx, true); int sampleShift = INT_MAX; NR_DL_FRAME_PARMS *fp = &UE->frame_parms; if (UE->sl_mode == 2) @@ -690,10 +650,12 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, } else ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx); + TracyCZoneEnd(ctx); return sampleShift; } void UE_dl_processing(void *arg) { + TracyCZone(ctx, true);; nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg; UE_nr_rxtx_proc_t *proc = &rxtxD->proc; PHY_VARS_NR_UE *UE = rxtxD->UE; @@ -701,6 +663,8 @@ void UE_dl_processing(void *arg) { if (!UE->sl_mode) pdsch_processing(UE, proc, phy_data); + + TracyCZoneEnd(ctx); } void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) { @@ -841,7 +805,7 @@ void *UE_thread(void *arg) int num_ind_fifo = nb_slot_frame; for(int i = 0; i < num_ind_fifo; i++) { - initNotifiedFIFO(UE->tx_resume_ind_fifo + i); + dynamic_barrier_init(&UE->process_slot_tx_barriers[i]); } int shiftForNextFrame = 0; int intialSyncOffset = 0; @@ -916,7 +880,7 @@ void *UE_thread(void *arg) } syncMsg->UE = UE; memset(&syncMsg->proc, 0, sizeof(syncMsg->proc)); - pushTpool(&(get_nrUE_params()->Tpool), Msg); + pushNotifiedFIFO(&UE->sync_actor.fifo, Msg); trashed_frames = 0; syncRunning = true; continue; @@ -956,15 +920,14 @@ void *UE_thread(void *arg) // We have resynchronized, maybe after RF loss so we need to purge any existing context memset(tx_wait_for_dlsch, 0, sizeof(tx_wait_for_dlsch)); for (int i = 0; i < num_ind_fifo; i++) { - notifiedFIFO_elt_t *res; - while ((res = pollNotifiedFIFO(UE->tx_resume_ind_fifo + i))) - delNotifiedFIFO_elt(res); + dynamic_barrier_reset(&UE->process_slot_tx_barriers[i]); } continue; } // start of normal case, the UE is in sync absolute_slot++; + TracyCFrameMark; int slot_nr = absolute_slot % nb_slot_frame; nr_rxtx_thread_data_t curMsg = {0}; @@ -1046,7 +1009,7 @@ void *UE_thread(void *arg) int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data, &stats_printed); if (ret != INT_MAX) shiftForNextFrame = ret; - pushTpool(&(get_nrUE_params()->Tpool), newRx); + pushNotifiedFIFO(&UE->dl_actors[curMsg.proc.nr_slot_rx % NUM_DL_ACTORS].fifo, newRx); // Start TX slot processing here. It runs in parallel with RX slot processing // in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot @@ -1056,11 +1019,16 @@ void *UE_thread(void *arg) curMsgTx->writeBlockSize = writeBlockSize; curMsgTx->proc.timestamp_tx = writeTimestamp; curMsgTx->UE = UE; - curMsgTx->tx_wait_for_dlsch = tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx]; curMsgTx->stream_status = stream_status; + + int sync_to_previous_thread = stream_status == STREAM_STATUS_SYNCED ? 1 : 0; + int slot = curMsgTx->proc.nr_slot_tx; + dynamic_barrier_update(&UE->process_slot_tx_barriers[slot], + tx_wait_for_dlsch[slot] + sync_to_previous_thread, + start_process_slot_tx, + newTx); stream_status = STREAM_STATUS_SYNCED; - tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx] = 0; - pushTpool(&(get_nrUE_params()->Tpool), newTx); + tx_wait_for_dlsch[slot] = 0; } return NULL; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 8a9f0c626f2ca1b464933f118092adb1bbcc6301..07d3e532f51ac427f2e2d1ff74f5859e068a4bce 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -88,6 +88,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include <openair1/PHY/MODULATION/nr_modulation.h> #include "openair2/GNB_APP/gnb_paramdef.h" #include "pdcp.h" +#include "actor.h" extern const char *duplex_mode[]; THREAD_STRUCT thread_struct; @@ -495,6 +496,10 @@ int main(int argc, char **argv) } UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode; + init_actor(&UE[CC_id]->sync_actor, "SYNC_", -1); + for (int i = 0; i < NUM_DL_ACTORS; i++) { + init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1); + } init_nr_ue_vars(UE[CC_id], inst); if (UE[CC_id]->sl_mode) { diff --git a/nfapi/oai_integration/aerial/CMakeLists.txt b/nfapi/oai_integration/aerial/CMakeLists.txt index 80d4cd77c601ea7a2331d68bdabd4b2380967a6c..74b1ad9fbf20241ea99c0621ac4c903f84589279 100644 --- a/nfapi/oai_integration/aerial/CMakeLists.txt +++ b/nfapi/oai_integration/aerial/CMakeLists.txt @@ -21,7 +21,7 @@ if (OAI_AERIAL) endif () target_compile_definitions(aerial_lib PUBLIC ENABLE_L2_SLT_RSP) target_link_libraries(aerial_lib PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) - target_link_libraries(aerial_lib PRIVATE nr_fapi_p5) + target_link_libraries(aerial_lib PRIVATE nr_fapi_p5 nr_fapi_p7) target_link_libraries(aerial_lib PRIVATE "${NVLOG_LIB}" "${NVIPC_LIB}") else () message(STATUS "No Support for Aerial") diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index ca8cd163815a62fa9bcd6e52301576803f071661..ed087204b09c81e8a59c5a57b9965c0406ef81eb 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -250,9 +250,14 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) } case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: { + uint8_t *pReadData = msg->data_buf; + int dataBufLen = msg->data_len; + uint8_t *data_end = msg->data_buf + dataBufLen; nfapi_nr_srs_indication_t ind; aerial_unpack_nr_srs_indication(&pReadPackedMessage, end, + &pReadData, + data_end, &ind, &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_srs_indication) { @@ -288,7 +293,7 @@ int8_t buf[1024]; nv_ipc_config_t nv_ipc_config; -int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p4_p5_message_header_t *header) +int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header) { if (ipc == NULL) { return -1; @@ -334,12 +339,12 @@ int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p4_p5_me memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); LOG_D(NFAPI_VNF, - "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", - send_msg.cell_id, - send_msg.msg_id, - send_msg.msg_len, - send_msg.data_len, - send_msg.data_pool); + "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", + send_msg.cell_id, + send_msg.msg_id, + send_msg.msg_len, + send_msg.data_len, + send_msg.data_pool); // Send the message int send_retval = ipc->tx_send_msg(ipc, &send_msg); if (send_retval < 0) { @@ -352,7 +357,7 @@ int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p4_p5_me return 0; } -int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p7_message_header_t *header) +int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header) { if (ipc == NULL) { return -1; @@ -421,12 +426,12 @@ int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p7_messa memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); LOG_D(NFAPI_VNF, - "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", - send_msg.cell_id, - send_msg.msg_id, - send_msg.msg_len, - send_msg.data_len, - send_msg.data_pool); + "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", + send_msg.cell_id, + send_msg.msg_id, + send_msg.msg_len, + send_msg.data_len, + send_msg.data_pool); // Send the message int send_retval = ipc->tx_send_msg(ipc, &send_msg); if (send_retval < 0) { @@ -440,10 +445,10 @@ int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p7_messa } int aerial_send_P7_msg_with_data(void *packedBuf, - uint32_t packedMsgLength, - void *dataBuf, - uint32_t dataLength, - nfapi_p7_message_header_t *header) + uint32_t packedMsgLength, + void *dataBuf, + uint32_t dataLength, + nfapi_nr_p7_message_header_t *header) { if (ipc == NULL) { return -1; @@ -511,12 +516,12 @@ int aerial_send_P7_msg_with_data(void *packedBuf, memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); memcpy(send_msg.data_buf, dataBuf, send_msg.data_len); LOG_D(NFAPI_VNF, - "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", - send_msg.cell_id, - send_msg.msg_id, - send_msg.msg_len, - send_msg.data_len, - send_msg.data_pool); + "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", + send_msg.cell_id, + send_msg.msg_id, + send_msg.msg_len, + send_msg.data_len, + send_msg.data_pool); // Send the message int send_retval = ipc->tx_send_msg(ipc, &send_msg); if (send_retval != 0) { diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 3d88937f606797f453f80b71d599a666dbbaf453..5b8b9959642d2145a661f5f8c005d57e4f024929 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -47,13 +47,13 @@ typedef struct { uint32_t message_length; } fapi_phy_api_msg; -int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p4_p5_message_header_t *header); -int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_p7_message_header_t *header); +int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header); +int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header); int aerial_send_P7_msg_with_data(void *packedBuf, - uint32_t packedMsgLength, - void *dataBuf, - uint32_t dataLength, - nfapi_p7_message_header_t *header); + uint32_t packedMsgLength, + void *dataBuf, + uint32_t dataLength, + nfapi_nr_p7_message_header_t *header); void set_config(nfapi_vnf_config_t *conf); int nvIPC_Init(nvipc_params_t nvipc_params_s); diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p5.c b/nfapi/oai_integration/aerial/fapi_vnf_p5.c index 951a734ddd241e0e27f5dc67bea7deb75576521c..1128559b1df2997122654d753796db46e702cb8c 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p5.c +++ b/nfapi/oai_integration/aerial/fapi_vnf_p5.c @@ -299,7 +299,6 @@ int aerial_nr_send_config_request(nfapi_vnf_config_t *config, int p5_idx) req->header.phy_id = phy->id; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Send NFAPI_CONFIG_REQUEST\n"); - vnf_t *_this = (vnf_t *)(config); nfapi_vnf_phy_info_t *vnf_phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); @@ -309,7 +308,7 @@ int aerial_nr_send_config_request(nfapi_vnf_config_t *config, int p5_idx) return -1; } - nfapi_p4_p5_message_header_t *msg = &req->header; + nfapi_nr_p4_p5_message_header_t *msg = &req->header; uint16_t msg_len = sizeof(nfapi_nr_config_request_scf_t); uint8_t tx_messagebufferFAPI[sizeof(_this->tx_message_buffer)]; int packedMessageLengthFAPI = -1; @@ -346,19 +345,19 @@ int aerial_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_sta return 0; } -int aerial_vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_p4_p5_message_header_t *msg) +int aerial_vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, void *msg) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s\n", __FUNCTION__); - switch (msg->message_id) { + switch (((nfapi_nr_p4_p5_message_header_t *)msg)->message_id) { case P5_VENDOR_EXT_RSP: { vendor_ext_p5_rsp *rsp = (vendor_ext_p5_rsp *)msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] P5_VENDOR_EXT_RSP error_code:%d\n", rsp->error_code); // send the start request - nfapi_pnf_start_request_t req; + nfapi_nr_pnf_start_request_t req; memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_PNF_START_REQUEST; - nfapi_vnf_pnf_start_req(config, p5_idx, &req); + nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); } break; } @@ -392,12 +391,12 @@ int aerial_vnf_pack_vendor_extension_tlv(void *vext, uint8_t **ppWritePackedMsg, return -1; } -int aerial_vnf_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, +int aerial_vnf_unpack_p4_p5_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { - if (header->message_id == P5_VENDOR_EXT_RSP) { + if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_RSP) { vendor_ext_p5_rsp *req = (vendor_ext_p5_rsp *)(header); return (!pull16(ppReadPackedMessage, &req->error_code, end)); } @@ -405,12 +404,12 @@ int aerial_vnf_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *heade return 0; } -int aerial_vnf_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, +int aerial_vnf_pack_p4_p5_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { - if (header->message_id == P5_VENDOR_EXT_REQ) { + if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_REQ) { vendor_ext_p5_req *req = (vendor_ext_p5_req *)(header); return (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))); } @@ -418,17 +417,17 @@ int aerial_vnf_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, return 0; } -nfapi_p4_p5_message_header_t *aerial_vnf_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) +void *aerial_vnf_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) { if (message_id == P5_VENDOR_EXT_RSP) { *msg_size = sizeof(vendor_ext_p5_rsp); - return (nfapi_p4_p5_message_header_t *)malloc(sizeof(vendor_ext_p5_rsp)); + return malloc(sizeof(vendor_ext_p5_rsp)); } return 0; } -void aerial_vnf_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t *header) +void aerial_vnf_deallocate_p4_p5_vendor_ext(void *header) { free(header); } diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c index 2f8d001d5072945a05c4353dd788b681b80a4544..25508f833bc79369f042745eab4bb6c2f30b6ad3 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c @@ -32,6 +32,8 @@ #include "fapi_vnf_p7.h" #include "nr_nfapi_p7.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" // for handle_nr_srs_measurements() @@ -42,38 +44,10 @@ extern int nfapi_sync_var; int aerial_phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind)); - crc_ind->header.message_id = ind->header.message_id; - crc_ind->number_crcs = ind->number_crcs; - crc_ind->sfn = ind->sfn; - crc_ind->slot = ind->slot; - if (ind->number_crcs > 0) { - crc_ind->crc_list = CALLOC(NFAPI_NR_CRC_IND_MAX_PDU, sizeof(nfapi_nr_crc_t)); - AssertFatal(crc_ind->crc_list != NULL, "Memory not allocated for crc_ind->crc_list in phy_nr_crc_indication."); - } - for (int j = 0; j < ind->number_crcs; j++) { - crc_ind->crc_list[j].handle = ind->crc_list[j].handle; - crc_ind->crc_list[j].rnti = ind->crc_list[j].rnti; - crc_ind->crc_list[j].harq_id = ind->crc_list[j].harq_id; - crc_ind->crc_list[j].tb_crc_status = ind->crc_list[j].tb_crc_status; - crc_ind->crc_list[j].num_cb = ind->crc_list[j].num_cb; - crc_ind->crc_list[j].cb_crc_status = ind->crc_list[j].cb_crc_status; - crc_ind->crc_list[j].ul_cqi = ind->crc_list[j].ul_cqi; - crc_ind->crc_list[j].timing_advance = ind->crc_list[j].timing_advance; - crc_ind->crc_list[j].rssi = ind->crc_list[j].rssi; - if (crc_ind->crc_list[j].tb_crc_status != 0) { - LOG_D(NR_MAC, - "Received crc_ind.harq_id %d status %d for index %d SFN SLot %u %u with rnti %04x\n", - crc_ind->crc_list[j].harq_id, - crc_ind->crc_list[j].tb_crc_status, - j, - crc_ind->sfn, - crc_ind->slot, - crc_ind->crc_list[j].rnti); - } - } + copy_crc_indication(ind, crc_ind); if (!put_queue(&gnb_crc_ind_queue, crc_ind)) { LOG_E(NR_MAC, "Put_queue failed for crc_ind\n"); - free(crc_ind->crc_list); + free_crc_indication(crc_ind); free(crc_ind); } return 1; @@ -82,40 +56,10 @@ int aerial_phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) int aerial_phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind)); - rx_ind->header.message_id = ind->header.message_id; - rx_ind->sfn = ind->sfn; - rx_ind->slot = ind->slot; - rx_ind->number_of_pdus = ind->number_of_pdus; - - if (ind->number_of_pdus > 0) { - rx_ind->pdu_list = CALLOC(NFAPI_NR_RX_DATA_IND_MAX_PDU, sizeof(nfapi_nr_rx_data_pdu_t)); - AssertFatal(rx_ind->pdu_list != NULL, "Memory not allocated for rx_ind->pdu_list in phy_nr_rx_data_indication."); - } - for (int j = 0; j < ind->number_of_pdus; j++) { - rx_ind->pdu_list[j].handle = ind->pdu_list[j].handle; - rx_ind->pdu_list[j].rnti = ind->pdu_list[j].rnti; - rx_ind->pdu_list[j].harq_id = ind->pdu_list[j].harq_id; - rx_ind->pdu_list[j].pdu_length = ind->pdu_list[j].pdu_length; - rx_ind->pdu_list[j].ul_cqi = ind->pdu_list[j].ul_cqi; - rx_ind->pdu_list[j].timing_advance = ind->pdu_list[j].timing_advance; - rx_ind->pdu_list[j].rssi = ind->pdu_list[j].rssi; - // Only copy PDU data if there's any to copy - if (rx_ind->pdu_list[j].pdu_length > 0) { - rx_ind->pdu_list[j].pdu = calloc(rx_ind->pdu_list[j].pdu_length, sizeof(uint8_t)); - memcpy(rx_ind->pdu_list[j].pdu, ind->pdu_list[j].pdu, ind->pdu_list[j].pdu_length); - } - LOG_D(NR_MAC, - "(%d.%d) Handle %d for index %d, RNTI, %04x, HARQID %d\n", - ind->sfn, - ind->slot, - ind->pdu_list[j].handle, - j, - ind->pdu_list[j].rnti, - ind->pdu_list[j].harq_id); - } + copy_rx_data_indication(ind, rx_ind); if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { LOG_E(NR_MAC, "Put_queue failed for rx_ind\n"); - free(rx_ind->pdu_list); + free_rx_data_indication(rx_ind); free(rx_ind); } return 1; @@ -124,29 +68,10 @@ int aerial_phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) int aerial_phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { nfapi_nr_rach_indication_t *rach_ind = CALLOC(1, sizeof(*rach_ind)); - rach_ind->header.message_id = ind->header.message_id; - rach_ind->sfn = ind->sfn; - rach_ind->slot = ind->slot; - rach_ind->number_of_pdus = ind->number_of_pdus; - rach_ind->pdu_list = CALLOC(rach_ind->number_of_pdus, sizeof(*rach_ind->pdu_list)); - AssertFatal(rach_ind->pdu_list != NULL, "Memory not allocated for rach_ind->pdu_list in phy_nr_rach_indication."); - for (int i = 0; i < ind->number_of_pdus; i++) { - rach_ind->pdu_list[i].phy_cell_id = ind->pdu_list[i].phy_cell_id; - rach_ind->pdu_list[i].symbol_index = ind->pdu_list[i].symbol_index; - rach_ind->pdu_list[i].slot_index = ind->pdu_list[i].slot_index; - rach_ind->pdu_list[i].freq_index = ind->pdu_list[i].freq_index; - rach_ind->pdu_list[i].avg_rssi = ind->pdu_list[i].avg_rssi; - rach_ind->pdu_list[i].avg_snr = ind->pdu_list[i].avg_snr; - rach_ind->pdu_list[i].num_preamble = ind->pdu_list[i].num_preamble; - for (int j = 0; j < ind->pdu_list[i].num_preamble; j++) { - rach_ind->pdu_list[i].preamble_list[j].preamble_index = ind->pdu_list[i].preamble_list[j].preamble_index; - rach_ind->pdu_list[i].preamble_list[j].timing_advance = ind->pdu_list[i].preamble_list[j].timing_advance; - rach_ind->pdu_list[i].preamble_list[j].preamble_pwr = ind->pdu_list[i].preamble_list[j].preamble_pwr; - } - } + copy_rach_indication(ind, rach_ind); if (!put_queue(&gnb_rach_ind_queue, rach_ind)) { LOG_E(NR_MAC, "Put_queue failed for rach_ind\n"); - free(rach_ind->pdu_list); + free_rach_indication(rach_ind); free(rach_ind); } else { LOG_I(NR_MAC, "RACH.indication put_queue successfull\n"); @@ -158,99 +83,10 @@ int aerial_phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind)); AssertFatal(uci_ind, "Memory not allocated for uci_ind in phy_nr_uci_indication."); - *uci_ind = *ind; - - uci_ind->uci_list = CALLOC(NFAPI_NR_UCI_IND_MAX_PDU, sizeof(nfapi_nr_uci_t)); - AssertFatal(uci_ind->uci_list != NULL, "Memory not allocated for uci_ind->uci_list in phy_nr_uci_indication."); - for (int i = 0; i < ind->num_ucis; i++) { - uci_ind->uci_list[i] = ind->uci_list[i]; - - switch (uci_ind->uci_list[i].pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); - break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { -// nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_ind_pdu = &uci_ind->uci_list[i].pucch_pdu_format_0_1; -// nfapi_nr_uci_pucch_pdu_format_0_1_t *ind_pdu = &ind->uci_list[i].pucch_pdu_format_0_1; -// if (ind_pdu->sr) { -// uci_ind_pdu->sr = CALLOC(1, sizeof(*uci_ind_pdu->sr)); -// AssertFatal(uci_ind_pdu->sr != NULL, "Memory not allocated for uci_ind_pdu->harq in phy_nr_uci_indication."); -// *uci_ind_pdu->sr = *ind_pdu->sr; -// } -// if (ind_pdu->harq) { -// uci_ind_pdu->harq = CALLOC(1, sizeof(*uci_ind_pdu->harq)); -// AssertFatal(uci_ind_pdu->harq != NULL, "Memory not allocated for uci_ind_pdu->harq in phy_nr_uci_indication."); -// -// *uci_ind_pdu->harq = *ind_pdu->harq; -// uci_ind_pdu->harq->harq_list = CALLOC(uci_ind_pdu->harq->num_harq, sizeof(*uci_ind_pdu->harq->harq_list)); -// AssertFatal(uci_ind_pdu->harq->harq_list != NULL, -// "Memory not allocated for uci_ind_pdu->harq->harq_list in phy_nr_uci_indication."); -// for (int j = 0; j < uci_ind_pdu->harq->num_harq; j++) -// uci_ind_pdu->harq->harq_list[j].harq_value = ind_pdu->harq->harq_list[j].harq_value; -// } - break; - } - - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_ind_pdu = &uci_ind->uci_list[i].pucch_pdu_format_2_3_4; - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *ind_pdu = &ind->uci_list[i].pucch_pdu_format_2_3_4; - *uci_ind_pdu = *ind_pdu; - if (ind_pdu->harq.harq_payload) { - uci_ind_pdu->harq.harq_payload = CALLOC(1, sizeof(*uci_ind_pdu->harq.harq_payload)); - AssertFatal(uci_ind_pdu->harq.harq_payload != NULL, - "Memory not allocated for uci_ind_pdu->harq.harq_payload in phy_nr_uci_indication."); - *uci_ind_pdu->harq.harq_payload = *ind_pdu->harq.harq_payload; - } - if (ind_pdu->sr.sr_payload) { - uci_ind_pdu->sr.sr_payload = CALLOC(1, sizeof(*uci_ind_pdu->sr.sr_payload)); - AssertFatal(uci_ind_pdu->sr.sr_payload != NULL, - "Memory not allocated for uci_ind_pdu->sr.sr_payload in phy_nr_uci_indication."); - //SCF222.10.02 sr_bit_len values from 1 to 8, payload always just one byte - uci_ind_pdu->sr.sr_payload[0] = ind_pdu->sr.sr_payload[0]; - } - if (ind_pdu->csi_part1.csi_part1_payload) { - uint8_t byte_len = (ind_pdu->csi_part1.csi_part1_bit_len / 8) + 1; - uci_ind_pdu->csi_part1.csi_part1_payload = calloc(byte_len, sizeof(uint8_t)); - AssertFatal(uci_ind_pdu->csi_part1.csi_part1_payload != NULL, - "Memory not allocated for uci_ind_pdu->csi_part1.csi_part1_payload in phy_nr_uci_indication."); - memcpy(uci_ind_pdu->csi_part1.csi_part1_payload,ind_pdu->csi_part1.csi_part1_payload,byte_len); - } - if (ind_pdu->csi_part2.csi_part2_payload) { - uint8_t byte_len = (ind_pdu->csi_part2.csi_part2_bit_len / 8) + 1; - uci_ind_pdu->csi_part2.csi_part2_payload = calloc(byte_len, sizeof(uint8_t)); - AssertFatal(uci_ind_pdu->csi_part2.csi_part2_payload != NULL, - "Memory not allocated for uci_ind_pdu->csi_part2.csi_part2_payload in phy_nr_uci_indication."); - memcpy(uci_ind_pdu->csi_part2.csi_part2_payload,ind_pdu->csi_part2.csi_part2_payload,byte_len); - } - break; - } - } - } - + copy_uci_indication(ind, uci_ind); if (!put_queue(&gnb_uci_ind_queue, uci_ind)) { LOG_E(NR_MAC, "Put_queue failed for uci_ind\n"); - for (int i = 0; i < ind->num_ucis; i++) { - if (uci_ind->uci_list[i].pdu_type == NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE) { -// if (uci_ind->uci_list[i].pucch_pdu_format_0_1.harq) { -// free(uci_ind->uci_list[i].pucch_pdu_format_0_1.harq->harq_list); -// uci_ind->uci_list[i].pucch_pdu_format_0_1.harq->harq_list = NULL; -// free(uci_ind->uci_list[i].pucch_pdu_format_0_1.harq); -// uci_ind->uci_list[i].pucch_pdu_format_0_1.harq = NULL; -// } -// if (uci_ind->uci_list[i].pucch_pdu_format_0_1.sr) { -// free(uci_ind->uci_list[i].pucch_pdu_format_0_1.sr); -// uci_ind->uci_list[i].pucch_pdu_format_0_1.sr = NULL; -// } - } - if (uci_ind->uci_list[i].pdu_type == NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE) { - free(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload); - free(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload); - free(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload); - } - } - free(uci_ind->uci_list); - uci_ind->uci_list = NULL; + free_uci_indication(uci_ind); free(uci_ind); uci_ind = NULL; } @@ -333,25 +169,25 @@ void aerial_vnf_deallocate(void *ptr) free(ptr); } -int aerial_phy_vendor_ext(struct nfapi_vnf_p7_config *config, nfapi_p7_message_header_t *msg) +int aerial_phy_vendor_ext(struct nfapi_vnf_p7_config *config, void *msg) { - if (msg->message_id == P7_VENDOR_EXT_IND) { + if (((nfapi_nr_p7_message_header_t *)msg)->message_id == P7_VENDOR_EXT_IND) { // vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)msg; // NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] vendor_ext (error_code:%d)\n", ind->error_code); } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] unknown %02x\n", msg->message_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] unknown %02x\n", ((nfapi_nr_p7_message_header_t *)msg)->message_id); } return 0; } -int aerial_phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, +int aerial_phy_unpack_p7_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *config) { // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if (header->message_id == P7_VENDOR_EXT_IND) { + if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_IND) { vendor_ext_p7_ind *req = (vendor_ext_p7_ind *)(header); if (!pull16(ppReadPackedMessage, &req->error_code, end)) @@ -361,13 +197,10 @@ int aerial_phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, return 1; } -int aerial_phy_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, - uint8_t **ppWritePackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config) +int aerial_phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if (header->message_id == P7_VENDOR_EXT_REQ) { + if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_REQ) { // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); vendor_ext_p7_req *req = (vendor_ext_p7_req *)(header); @@ -412,17 +245,17 @@ int aerial_phy_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, u } } -nfapi_p7_message_header_t *aerial_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) +void *aerial_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) { if (message_id == P7_VENDOR_EXT_IND) { *msg_size = sizeof(vendor_ext_p7_ind); - return (nfapi_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_ind)); + return (nfapi_nr_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_ind)); } return 0; } -void aerial_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) +void aerial_phy_deallocate_p7_vendor_ext(void *header) { free(header); } @@ -504,9 +337,25 @@ uint8_t aerial_unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, return unpack_nr_uci_indication(ppReadPackedMsg, end, msg, config); } -uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, + uint8_t *end, + uint8_t **pDataMsg, + uint8_t *data_end, + void *msg, + nfapi_p7_codec_config_t *config) { - return unpack_nr_srs_indication(ppReadPackedMsg, end, msg, config); + uint8_t retval = unpack_nr_srs_indication(ppReadPackedMsg, end, msg, config); + nfapi_nr_srs_indication_t *srs_ind = (nfapi_nr_srs_indication_t *)msg; + for (uint8_t pdu_idx = 0; pdu_idx < srs_ind->number_of_pdus; pdu_idx++) { + nfapi_nr_srs_indication_pdu_t *pdu = &srs_ind->pdu_list[pdu_idx]; + nfapi_srs_report_tlv_t *report_tlv = &pdu->report_tlv; + for (int i = 0; i < (report_tlv->length + 3) / 4; i++) { + if (!pull32(pDataMsg, &report_tlv->value[i], data_end)) { + return 0; + } + } + } + return retval; } uint8_t aerial_unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, @@ -530,7 +379,7 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, return -1; } - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + nfapi_nr_p7_message_header_t *pMessageHeader = pMessageBuf; uint8_t *end = pPackedBuf + packedBufLen; uint8_t *data_end = pDataBuf + dataBufLen; uint8_t *pWritePackedMessage = pPackedBuf; @@ -569,8 +418,7 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, // recalculate PDU_Length for Aerial (leave only the size occupied in the payload buffer afterward) // assuming there is only 1 TLV present value->PDU_length = value->TLVs[0].length; - if (!(push32(value->PDU_length, ppWriteBody, end) - && // cuBB expects TX_DATA.request PDUSize to be 32 bit + if (!(push32(value->PDU_length, ppWriteBody, end) && // cuBB expects TX_DATA.request PDUSize to be 32 bit push16(value->PDU_index, ppWriteBody, end) && push32(value->num_TLV, ppWriteBody, end))) { return 0; } @@ -589,7 +437,7 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, } } - //Actual payloads are packed in a separate buffer + // Actual payloads are packed in a separate buffer for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)&pNfapiMsg->pdu_list[i]; @@ -626,12 +474,11 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, } } } else { - LOG_E(NR_MAC,"value->TLVs[i].length was 0! (%d.%d) \n", pNfapiMsg->SFN, pNfapiMsg->Slot); + LOG_E(NR_MAC, "value->TLVs[i].length was 0! (%d.%d) \n", pNfapiMsg->SFN, pNfapiMsg->Slot); } } } - // calculate data_len uintptr_t dataHead = (uintptr_t)pPackedDataFieldStart; uintptr_t dataEnd = (uintptr_t)pPackedDataField; @@ -659,155 +506,8 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, return (packedMsgLen16); } -int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) -{ - if (pMessageBuf == NULL || pPackedBuf == NULL) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *end = pPackedBuf + packedBufLen; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *pPacketBodyField = &pWritePackedMessage[8]; - uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8]; - - // PHY API message header - // Number of messages [0] - // Opaque handle [1] - // PHY API Message structure - // Message type ID [2,3] - // Message Length [4,5,6,7] - // Message Body [8,...] - if (!(push8(1, &pWritePackedMessage, pPackMessageEnd) && push8(0, &pWritePackedMessage, pPackMessageEnd) - && push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd))) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - result = pack_dl_tti_request(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - result = pack_ul_tti_request(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - // TX_DATA.request already handled by aerial_pack_tx_data_request - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - result = pack_ul_dci_request(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_UE_RELEASE_REQUEST: - result = pack_ue_release_request(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - result = pack_ue_release_response(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: - result = pack_nr_slot_indication(pMessageHeader, &pPacketBodyField, end, config); - - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - result = pack_nr_rx_data_indication(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - result = pack_nr_crc_indication(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - result = pack_nr_uci_indication(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - result = pack_nr_dl_node_sync(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - result = pack_nr_ul_node_sync(pMessageHeader, &pPacketBodyField, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_nr_timing_info(pMessageHeader, &pPacketBodyField, end, config); - break; - - case 0x8f: - result = pack_nr_slot_indication(pMessageHeader, &pPacketBodyField, end, config); - break; - - default: { - if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { - if (config && config->pack_p7_vendor_extension) { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pPacketBodyField, end, config); - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, - "%s VE NFAPI message ID %d. No ve ecoder provided\n", - __FUNCTION__, - pMessageHeader->message_id); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } break; - } - - if (result == 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPacketBodyFieldStart; - uintptr_t msgEnd = (uintptr_t)pPacketBodyField; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } else { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - // Update the message length in the header - if (!push32(packedMsgLen, &pPackedLengthField, pPackMessageEnd)) - return -1; - - if (1) { - // quick test - if (pMessageHeader->message_length != packedMsgLen) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, - "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", - packedMsgLen, - pMessageHeader->message_length, - pMessageHeader->message_id); - } - } - - return (packedMsgLen16); -} -int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_p7_message_header_t *header) +int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) { uint8_t FAPI_buffer[1024 * 64]; // Check if TX_DATA request, if true, need to pack to data_buf @@ -817,7 +517,7 @@ int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_p7_message_header_t for (int i = 0; i < pNfapiMsg->Number_of_PDUs; ++i) { size += pNfapiMsg->pdu_list[i].PDU_length; } - AssertFatal(size <= 1024 * 1024 * 2, "Message data larger than available buffer, tried to pack %"PRId64 ,size); + AssertFatal(size <= 1024 * 1024 * 2, "Message data larger than available buffer, tried to pack %" PRId64, size); uint8_t FAPI_data_buffer[1024 * 1024 * 2]; // 2MB uint32_t data_len = 0; int32_t len_FAPI = aerial_pack_tx_data_request(header, diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.h b/nfapi/oai_integration/aerial/fapi_vnf_p7.h index 404df347cc9b485cb18cfac01800f75aa45a91b7..ca75b022760cc110767deb4b31a035dc486d06b5 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.h +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.h @@ -187,23 +187,20 @@ int aerial_phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); int aerial_phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind); void *aerial_vnf_allocate(size_t size); void aerial_vnf_deallocate(void *ptr); -int aerial_phy_vendor_ext(struct nfapi_vnf_p7_config *config, nfapi_p7_message_header_t *msg); -int aerial_phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, +int aerial_phy_vendor_ext(struct nfapi_vnf_p7_config *config, void *msg); +int aerial_phy_unpack_p7_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *config); -int aerial_phy_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, - uint8_t **ppWritePackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config); +int aerial_phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); int aerial_phy_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMessage, uint8_t *end, void **ve, nfapi_p7_codec_config_t *codec); int aerial_phy_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codec); -nfapi_p7_message_header_t *aerial_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size); -void aerial_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header); +void *aerial_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size); +void aerial_phy_deallocate_p7_vendor_ext(void *header); uint8_t aerial_unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, @@ -220,12 +217,17 @@ uint8_t aerial_unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, nfapi_nr_crc_indication_t *msg, nfapi_p7_codec_config_t *config); uint8_t aerial_unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); -uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, + uint8_t *end, + uint8_t **pDataMsg, + uint8_t *data_end, + void *msg, + nfapi_p7_codec_config_t *config); uint8_t aerial_unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rach_indication_t *msg, nfapi_p7_codec_config_t *config); // int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); -int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_p7_message_header_t *header); +int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header); #endif // OPENAIRINTERFACE_FAPI_VNF_P7_H diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index a933aba614815deac44748548ab3a36bc17d9f6a..c96acd9fba4c51fe11062d151e60a05d9c8e714d 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1076,8 +1076,9 @@ int nr_config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n return 0; } -nfapi_p7_message_header_t *pnf_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) { - if(message_id == P7_VENDOR_EXT_REQ) { +void *pnf_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) +{ + if (message_id == P7_VENDOR_EXT_REQ) { (*msg_size) = sizeof(vendor_ext_p7_req); return (nfapi_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_req)); } @@ -1085,7 +1086,23 @@ nfapi_p7_message_header_t *pnf_phy_allocate_p7_vendor_ext(uint16_t message_id, u return 0; } -void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) { +void *pnf_nr_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) +{ + if (message_id == P7_VENDOR_EXT_REQ) { + (*msg_size) = sizeof(vendor_ext_p7_req); + return (nfapi_nr_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_req)); + } + + return 0; +} + +void pnf_phy_deallocate_p7_vendor_ext(void *header) +{ + free(header); +} + +void pnf_nr_phy_deallocate_p7_vendor_ext(void *header) +{ free(header); } @@ -1522,10 +1539,23 @@ int pnf_phy_ue_release_req(nfapi_pnf_p7_config_t* config, nfapi_ue_release_reque return 0; } -int pnf_phy_vendor_ext(nfapi_pnf_p7_config_t *config, nfapi_p7_message_header_t *msg) { - if(msg->message_id == P7_VENDOR_EXT_REQ) { - //vendor_ext_p7_req* req = (vendor_ext_p7_req*)msg; - //printf("[PNF] vendor request (1:%d 2:%d)\n", req->dummy1, req->dummy2); +int pnf_phy_vendor_ext(nfapi_pnf_p7_config_t *config, void *msg) +{ + if (((nfapi_p7_message_header_t *)msg)->message_id == P7_VENDOR_EXT_REQ) { + // vendor_ext_p7_req* req = (vendor_ext_p7_req*)msg; + // printf("[PNF] vendor request (1:%d 2:%d)\n", req->dummy1, req->dummy2); + } else { + printf("[PNF] unknown vendor ext\n"); + } + + return 0; +} + +int pnf_nr_phy_vendor_ext(nfapi_pnf_p7_config_t *config, void *msg) +{ + if (((nfapi_nr_p7_message_header_t *)msg)->message_id == P7_VENDOR_EXT_REQ) { + // vendor_ext_p7_req* req = (vendor_ext_p7_req*)msg; + // printf("[PNF] vendor request (1:%d 2:%d)\n", req->dummy1, req->dummy2); } else { printf("[PNF] unknown vendor ext\n"); } @@ -1533,9 +1563,9 @@ int pnf_phy_vendor_ext(nfapi_pnf_p7_config_t *config, nfapi_p7_message_header_t return 0; } -int pnf_phy_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codex) { +int pnf_phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codex) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if(header->message_id == P7_VENDOR_EXT_IND) { + if(((nfapi_p7_message_header_t*)header)->message_id == P7_VENDOR_EXT_IND) { vendor_ext_p7_ind *ind = (vendor_ext_p7_ind *)(header); if(!push16(ind->error_code, ppWritePackedMsg, end)) @@ -1547,13 +1577,43 @@ int pnf_phy_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t return -1; } -int pnf_phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *codec) { - if(header->message_id == P7_VENDOR_EXT_REQ) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); +int pnf_phy_unpack_p7_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *codec) +{ + if (((nfapi_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_REQ) { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + vendor_ext_p7_req *req = (vendor_ext_p7_req *)(header); + + if (!(pull16(ppReadPackedMessage, &req->dummy1, end) && pull16(ppReadPackedMessage, &req->dummy2, end))) + return 0; + + return 1; + } + + return -1; +} + +int pnf_nr_phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codex) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_IND) { + vendor_ext_p7_ind *ind = (vendor_ext_p7_ind *)(header); + + if (!push16(ind->error_code, ppWritePackedMsg, end)) + return 0; + + return 1; + } + + return -1; +} + +int pnf_nr_phy_unpack_p7_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *codec) +{ + if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_REQ) { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); vendor_ext_p7_req *req = (vendor_ext_p7_req *)(header); - if(!(pull16(ppReadPackedMessage, &req->dummy1, end) && - pull16(ppReadPackedMessage, &req->dummy2, end))) + if (!(pull16(ppReadPackedMessage, &req->dummy1, end) && pull16(ppReadPackedMessage, &req->dummy2, end))) return 0; return 1; @@ -1585,6 +1645,34 @@ int pnf_phy_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, uint return -1; } +int pnf_nr_phy_unpack_vendor_extension_tlv(nfapi_tl_t *tl, + uint8_t **ppReadPackedMessage, + uint8_t *end, + void **ve, + nfapi_p7_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "pnf_phy_unpack_vendor_extension_tlv\n"); + switch (tl->tag) { + case VENDOR_EXT_TLV_1_TAG: + *ve = malloc(sizeof(vendor_ext_tlv_1)); + + if (!pull32(ppReadPackedMessage, &((vendor_ext_tlv_1 *)(*ve))->dummy, end)) + return 0; + + return 1; + break; + } + + return -1; +} + +int pnf_nr_phy_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + // printf("%s\n", __FUNCTION__); + (void)ve; + (void)ppWritePackedMsg; + return -1; +} int pnf_sim_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMessage, uint8_t *end, void **ve, nfapi_p4_p5_codec_config_t *config) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "pnf_sim_unpack_vendor_extension_tlv\n"); switch(tl->tag) { @@ -1601,6 +1689,27 @@ int pnf_sim_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMe return -1; } +int pnf_nr_sim_unpack_vendor_extension_tlv(nfapi_tl_t *tl, + uint8_t **ppReadPackedMessage, + uint8_t *end, + void **ve, + nfapi_p4_p5_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "pnf_sim_unpack_vendor_extension_tlv\n"); + switch (tl->tag) { + case VENDOR_EXT_TLV_2_TAG: + *ve = malloc(sizeof(vendor_ext_tlv_2)); + + if (!pull32(ppReadPackedMessage, &((vendor_ext_tlv_2 *)(*ve))->dummy, end)) + return 0; + + return 1; + break; + } + + return -1; +} + int pnf_sim_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { //printf("%s\n", __FUNCTION__); (void)ve; @@ -1609,11 +1718,18 @@ int pnf_sim_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, uint return -1; } +int pnf_nr_sim_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) +{ + // printf("%s\n", __FUNCTION__); + (void)ve; + (void)ppWritePackedMsg; + + return -1; +} + nfapi_dl_config_request_t dummy_dl_config_req; nfapi_tx_request_t dummy_tx_req; -nfapi_pnf_p7_subframe_buffer_t dummy_subframe; - int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_start_request_t *req) { printf("[PNF] Received NFAPI_START_REQ phy_id:%d\n", req->header.phy_id); pnf_info *pnf = (pnf_info *)(config->user_data); @@ -1674,12 +1790,8 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi memset(&dummy_tx_req, 0, sizeof(dummy_tx_req)); dummy_tx_req.tx_request_body.number_of_pdus=0; dummy_tx_req.tx_request_body.tl.tag=NFAPI_TX_REQUEST_BODY_TAG; - dummy_subframe.dl_config_req = &dummy_dl_config_req; - dummy_subframe.tx_req = 0;//&dummy_tx_req; - dummy_subframe.ul_config_req=0; - dummy_subframe.hi_dci0_req=0; - dummy_subframe.lbt_dl_config_req=0; - p7_config->dummy_subframe = dummy_subframe; + memset(&p7_config->dummy_subframe, 0, sizeof(p7_config->dummy_subframe)); + p7_config->dummy_subframe.dl_config_req = &dummy_dl_config_req; p7_config->vendor_ext = &pnf_phy_vendor_ext; p7_config->allocate_p7_vendor_ext = &pnf_phy_allocate_p7_vendor_ext; p7_config->deallocate_p7_vendor_ext = &pnf_phy_deallocate_p7_vendor_ext; @@ -1732,7 +1844,8 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi return 0; } -int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_start_request_scf_t *req) { +int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_start_request_scf_t *req) +{ printf("[PNF] Received NFAPI_START_REQ phy_id:%d\n", req->header.phy_id); pnf_info *pnf = (pnf_info *)(config->user_data); phy_info *phy_info = pnf->phys; @@ -1743,7 +1856,11 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n p7_config->local_p7_port = phy_info->udp.rx_port; p7_config->local_p7_addr = phy_info->local_addr; - printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port); + printf("[PNF] P7 remote:%s:%d local:%s:%d\n", + p7_config->remote_p7_addr, + p7_config->remote_p7_port, + p7_config->local_p7_addr, + p7_config->local_p7_port); p7_config->user_data = phy_info; p7_config->malloc = &pnf_allocate; p7_config->free = &pnf_deallocate; @@ -1755,19 +1872,19 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n p7_config->slot_buffer_size = phy_info->timing_window; // TODO: check if correct for NR printf("subframe_buffer_size configured using phy_info->timing_window:%d\n", phy_info->timing_window); - if(phy_info->timing_info_mode & 0x1) { + if (phy_info->timing_info_mode & 0x1) { p7_config->timing_info_mode_periodic = 1; p7_config->timing_info_period = phy_info->timing_info_period; } - if(phy_info->timing_info_mode & 0x2) { + if (phy_info->timing_info_mode & 0x2) { p7_config->timing_info_mode_aperiodic = 1; } // NR - p7_config->dl_tti_req_fn = &pnf_phy_dl_tti_req; - p7_config->ul_tti_req_fn = &pnf_phy_ul_tti_req; - p7_config->ul_dci_req_fn = &pnf_phy_ul_dci_req; + p7_config->dl_tti_req_fn = &pnf_phy_dl_tti_req; + p7_config->ul_tti_req_fn = &pnf_phy_ul_tti_req; + p7_config->ul_dci_req_fn = &pnf_phy_ul_dci_req; p7_config->tx_data_req_fn = &pnf_phy_tx_data_req; // LTE @@ -1777,7 +1894,7 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n p7_config->tx_req = &pnf_phy_tx_req; p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req; p7_config->ue_release_req = &pnf_phy_ue_release_req; - if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { + if (NFAPI_MODE == NFAPI_UE_STUB_PNF) { p7_config->dl_config_req = NULL; p7_config->ul_config_req = NULL; p7_config->hi_dci0_req = NULL; @@ -1791,29 +1908,25 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req; memset(&dummy_dl_config_req, 0, sizeof(dummy_dl_config_req)); - dummy_dl_config_req.dl_config_request_body.tl.tag=NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - dummy_dl_config_req.dl_config_request_body.number_pdcch_ofdm_symbols=1; - dummy_dl_config_req.dl_config_request_body.number_dci=0; - dummy_dl_config_req.dl_config_request_body.number_pdu=0; - dummy_dl_config_req.dl_config_request_body.number_pdsch_rnti=0; - dummy_dl_config_req.dl_config_request_body.transmission_power_pcfich=6000; - dummy_dl_config_req.dl_config_request_body.dl_config_pdu_list=0; + dummy_dl_config_req.dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + dummy_dl_config_req.dl_config_request_body.number_pdcch_ofdm_symbols = 1; + dummy_dl_config_req.dl_config_request_body.number_dci = 0; + dummy_dl_config_req.dl_config_request_body.number_pdu = 0; + dummy_dl_config_req.dl_config_request_body.number_pdsch_rnti = 0; + dummy_dl_config_req.dl_config_request_body.transmission_power_pcfich = 6000; + dummy_dl_config_req.dl_config_request_body.dl_config_pdu_list = 0; memset(&dummy_tx_req, 0, sizeof(dummy_tx_req)); - dummy_tx_req.tx_request_body.number_of_pdus=0; - dummy_tx_req.tx_request_body.tl.tag=NFAPI_TX_REQUEST_BODY_TAG; - dummy_subframe.dl_config_req = &dummy_dl_config_req; - dummy_subframe.tx_req = 0;//&dummy_tx_req; - dummy_subframe.ul_config_req=0; - dummy_subframe.hi_dci0_req=0; - dummy_subframe.lbt_dl_config_req=0; - p7_config->dummy_subframe = dummy_subframe; - p7_config->vendor_ext = &pnf_phy_vendor_ext; - p7_config->allocate_p7_vendor_ext = &pnf_phy_allocate_p7_vendor_ext; - p7_config->deallocate_p7_vendor_ext = &pnf_phy_deallocate_p7_vendor_ext; - p7_config->codec_config.unpack_p7_vendor_extension = &pnf_phy_unpack_p7_vendor_extension; - p7_config->codec_config.pack_p7_vendor_extension = &pnf_phy_pack_p7_vendor_extension; - p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_phy_unpack_vendor_extension_tlv; - p7_config->codec_config.pack_vendor_extension_tlv = &pnf_phy_pack_vendor_extention_tlv; + dummy_tx_req.tx_request_body.number_of_pdus = 0; + dummy_tx_req.tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG; + memset(&p7_config->dummy_subframe, 0, sizeof(p7_config->dummy_subframe)); + p7_config->dummy_subframe.dl_config_req = &dummy_dl_config_req; + p7_config->vendor_ext = &pnf_nr_phy_vendor_ext; + p7_config->allocate_p7_vendor_ext = &pnf_nr_phy_allocate_p7_vendor_ext; + p7_config->deallocate_p7_vendor_ext = &pnf_nr_phy_deallocate_p7_vendor_ext; + p7_config->codec_config.unpack_p7_vendor_extension = &pnf_nr_phy_unpack_p7_vendor_extension; + p7_config->codec_config.pack_p7_vendor_extension = &pnf_nr_phy_pack_p7_vendor_extension; + p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_nr_phy_unpack_vendor_extension_tlv; + p7_config->codec_config.pack_vendor_extension_tlv = &pnf_nr_phy_pack_vendor_extention_tlv; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__); pthread_t p7_thread; threadCreate(&p7_thread, &pnf_nr_p7_thread_start, p7_config, "pnf_p7_thread", -1, OAI_PRIORITY_RT); @@ -1823,24 +1936,24 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n p7_config_g = p7_config; // Need to wait for main thread to create RU structures - while(config_sync_var<0) { + while (config_sync_var < 0) { usleep(5000000); printf("[PNF] waiting for OAI to be configured (eNB/RU)\n"); } printf("[PNF] OAI eNB/RU configured\n"); - //printf("[PNF] About to call phy_init_RU() for RC.ru[0]:%p\n", RC.ru[0]); - //phy_init_RU(RC.ru[0]); + // printf("[PNF] About to call phy_init_RU() for RC.ru[0]:%p\n", RC.ru[0]); + // phy_init_RU(RC.ru[0]); printf("[PNF] About to call init_eNB_afterRU()\n"); - if (NFAPI_MODE!=NFAPI_UE_STUB_PNF) { + if (NFAPI_MODE != NFAPI_UE_STUB_PNF) { init_eNB_afterRU(); } // Signal to main thread that it can carry on - otherwise RU will startup too quickly and it is not initialised { pthread_mutex_lock(&nfapi_sync_mutex); - nfapi_sync_var=0; + nfapi_sync_var = 0; pthread_cond_broadcast(&nfapi_sync_cond); pthread_mutex_unlock(&nfapi_sync_mutex); } @@ -1860,8 +1973,7 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // SFN_SF set to zero - correct??? printf("[PNF] Sent first P7 subframe ind\n"); #endif - - + return 0; } @@ -2052,10 +2164,11 @@ int nmm_stop_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf return 0; } -int vendor_ext(nfapi_pnf_config_t *config, nfapi_p4_p5_message_header_t *msg) { +int vendor_ext(nfapi_pnf_config_t *config, void *msg) +{ NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P5 %s %p\n", __FUNCTION__, msg); - switch(msg->message_id) { + switch (((nfapi_p4_p5_message_header_t *)msg)->message_id) { case P5_VENDOR_EXT_REQ: { vendor_ext_p5_req *req = (vendor_ext_p5_req *)msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P5 Vendor Ext Req (%d %d)\n", req->dummy1, req->dummy2); @@ -2065,15 +2178,35 @@ int vendor_ext(nfapi_pnf_config_t *config, nfapi_p4_p5_message_header_t *msg) { rsp.header.message_id = P5_VENDOR_EXT_RSP; rsp.error_code = NFAPI_MSG_OK; nfapi_pnf_vendor_extension(config, &rsp.header, sizeof(vendor_ext_p5_rsp)); - } - break; + } break; + } + + return 0; +} + +int nr_vendor_ext(nfapi_pnf_config_t *config, void *msg) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P5 %s %p\n", __FUNCTION__, msg); + + switch (((nfapi_nr_p4_p5_message_header_t *)msg)->message_id) { + case P5_VENDOR_EXT_REQ: { + vendor_ext_p5_req *req = (vendor_ext_p5_req *)msg; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P5 Vendor Ext Req (%d %d)\n", req->dummy1, req->dummy2); + // send back the P5_VENDOR_EXT_RSP + vendor_ext_p5_rsp rsp; + memset(&rsp, 0, sizeof(rsp)); + rsp.header.message_id = P5_VENDOR_EXT_RSP; + rsp.error_code = NFAPI_MSG_OK; + nfapi_pnf_vendor_extension(config, &rsp.header, sizeof(vendor_ext_p5_rsp)); + } break; } return 0; } -nfapi_p4_p5_message_header_t *pnf_sim_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) { - if(message_id == P5_VENDOR_EXT_REQ) { +void *pnf_sim_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) +{ + if (message_id == P5_VENDOR_EXT_REQ) { (*msg_size) = sizeof(vendor_ext_p5_req); return (nfapi_p4_p5_message_header_t *)malloc(sizeof(vendor_ext_p5_req)); } @@ -2081,13 +2214,30 @@ nfapi_p4_p5_message_header_t *pnf_sim_allocate_p4_p5_vendor_ext(uint16_t message return 0; } -void pnf_sim_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t *header) { +void *pnf_nr_sim_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) +{ + if (message_id == P5_VENDOR_EXT_REQ) { + (*msg_size) = sizeof(vendor_ext_p5_req); + return (nfapi_p4_p5_message_header_t *)malloc(sizeof(vendor_ext_p5_req)); + } + + return 0; +} + +void pnf_sim_deallocate_p4_p5_vendor_ext(void *header) +{ free(header); } -int pnf_sim_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if(header->message_id == P5_VENDOR_EXT_RSP) { +void pnf_nr_sim_deallocate_p4_p5_vendor_ext(void *header) +{ + free(header); +} + +int pnf_sim_pack_p4_p5_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_RSP) { vendor_ext_p5_rsp *rsp = (vendor_ext_p5_rsp *)(header); return (!push16(rsp->error_code, ppWritePackedMsg, end)); } @@ -2095,13 +2245,45 @@ int pnf_sim_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, ui return 0; } -int pnf_sim_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if(header->message_id == P5_VENDOR_EXT_REQ) { +int pnf_nr_sim_pack_p4_p5_vendor_extension(void *header, + uint8_t **ppWritePackedMsg, + uint8_t *end, + nfapi_p4_p5_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_RSP) { + vendor_ext_p5_rsp *rsp = (vendor_ext_p5_rsp *)(header); + return (!push16(rsp->error_code, ppWritePackedMsg, end)); + } + + return 0; +} + +int pnf_sim_unpack_p4_p5_vendor_extension(void *header, + uint8_t **ppReadPackedMessage, + uint8_t *end, + nfapi_p4_p5_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_REQ) { + vendor_ext_p5_req *req = (vendor_ext_p5_req *)(header); + return (!(pull16(ppReadPackedMessage, &req->dummy1, end) && pull16(ppReadPackedMessage, &req->dummy2, end))); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s (%d %d)\n", __FUNCTION__, req->dummy1, req->dummy2); + } + + return 0; +} + +int pnf_nr_sim_unpack_p4_p5_vendor_extension(void *header, + uint8_t **ppReadPackedMessage, + uint8_t *end, + nfapi_p4_p5_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_REQ) { vendor_ext_p5_req *req = (vendor_ext_p5_req *)(header); - return (!(pull16(ppReadPackedMessage, &req->dummy1, end) && - pull16(ppReadPackedMessage, &req->dummy2, end))); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s (%d %d)\n", __FUNCTION__, req->dummy1, req->dummy2); + return (!(pull16(ppReadPackedMessage, &req->dummy1, end) && pull16(ppReadPackedMessage, &req->dummy2, end))); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s (%d %d)\n", __FUNCTION__, req->dummy1, req->dummy2); } return 0; @@ -2128,9 +2310,10 @@ void *pnf_nr_start_thread(void *ptr) { return (void *)0; } -void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { +void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) +{ printf("%s() PNF\n\n\n\n\n\n", __FUNCTION__); - nfapi_setmode(NFAPI_MODE_PNF); // PNF! + nfapi_setmode(NFAPI_MODE_PNF); // PNF! nfapi_pnf_config_t *config = nfapi_pnf_config_create(); config->vnf_ip_addr = vnf_ip_addr; @@ -2149,9 +2332,8 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add pnf.phys[0].udp.tx_port, pnf.phys[0].udp.rx_port); config->cell_search_req = &cell_search_request; - - - //config->pnf_nr_param_req = &pnf_nr_param_request; + + // config->pnf_nr_param_req = &pnf_nr_param_request; config->pnf_nr_param_req = &pnf_nr_param_request; config->pnf_nr_config_req = &pnf_nr_config_request; config->pnf_nr_start_req = &pnf_nr_start_request; @@ -2159,22 +2341,21 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->nr_param_req = &nr_param_request; config->nr_config_req = &nr_config_request; config->nr_start_req = &nr_start_request; - config->measurement_req = &measurement_request; config->rssi_req = &rssi_request; config->broadcast_detect_req = &broadcast_detect_request; config->system_information_schedule_req = &system_information_schedule_request; config->system_information_req = &system_information_request; config->nmm_stop_req = &nmm_stop_request; - config->vendor_ext = &vendor_ext; + config->vendor_ext = &nr_vendor_ext; config->trace = &pnf_nfapi_trace; config->user_data = &pnf; // To allow custom vendor extentions to be added to nfapi - config->codec_config.unpack_vendor_extension_tlv = &pnf_sim_unpack_vendor_extension_tlv; - config->codec_config.pack_vendor_extension_tlv = &pnf_sim_pack_vendor_extention_tlv; - config->allocate_p4_p5_vendor_ext = &pnf_sim_allocate_p4_p5_vendor_ext; - config->deallocate_p4_p5_vendor_ext = &pnf_sim_deallocate_p4_p5_vendor_ext; - config->codec_config.unpack_p4_p5_vendor_extension = &pnf_sim_unpack_p4_p5_vendor_extension; - config->codec_config.pack_p4_p5_vendor_extension = &pnf_sim_pack_p4_p5_vendor_extension; + config->codec_config.unpack_vendor_extension_tlv = &pnf_nr_sim_unpack_vendor_extension_tlv; + config->codec_config.pack_vendor_extension_tlv = &pnf_nr_sim_pack_vendor_extention_tlv; + config->allocate_p4_p5_vendor_ext = &pnf_nr_sim_allocate_p4_p5_vendor_ext; + config->deallocate_p4_p5_vendor_ext = &pnf_nr_sim_deallocate_p4_p5_vendor_ext; + config->codec_config.unpack_p4_p5_vendor_extension = &pnf_nr_sim_unpack_p4_p5_vendor_extension; + config->codec_config.pack_p4_p5_vendor_extension = &pnf_nr_sim_pack_p4_p5_vendor_extension; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); pthread_create(&pnf_start_pthread, NULL, &pnf_nr_start_thread, config); pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index c742a7088a609b23de6fb74318249d9f41cdbd95..76542d3587e3efeb9abd9998fceb9f0f10460076 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -47,6 +47,9 @@ #include "common/ran_context.h" #include "openair2/PHY_INTERFACE/queue_t.h" #include "gnb_ind_vars.h" +#include "nr_fapi_p7_utils.h" +#include <NR_MAC_gNB/mac_proto.h> + #define TEST @@ -195,9 +198,36 @@ int vnf_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t return -1; } +int vnf_nr_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "vnf_pack_vendor_extension_tlv\n"); + nfapi_tl_t *tlv = (nfapi_tl_t *)ve; + + switch (tlv->tag) { + case VENDOR_EXT_TLV_2_TAG: { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "Packing VENDOR_EXT_TLV_2\n"); + vendor_ext_tlv_2 *ve = (vendor_ext_tlv_2 *)tlv; + + if (!push32(ve->dummy, ppWritePackedMsg, end)) + return 0; + + return 1; + } break; + } + + return -1; +} int vnf_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMessage, uint8_t *end, void **ve, nfapi_p4_p5_codec_config_t *codec) { return -1; } +int vnf_nr_unpack_vendor_extension_tlv(nfapi_tl_t *tl, + uint8_t **ppReadPackedMessage, + uint8_t *end, + void **ve, + nfapi_p4_p5_codec_config_t *codec) +{ + return -1; +} void install_nr_schedule_handlers(NR_IF_Module_t *if_inst); void install_schedule_handlers(IF_Module_t *if_inst); extern uint16_t sf_ahead; @@ -718,35 +748,15 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { - if(NFAPI_MODE == NFAPI_MODE_VNF) - { + if (NFAPI_MODE == NFAPI_MODE_VNF) { nfapi_nr_rach_indication_t *rach_ind = CALLOC(1, sizeof(*rach_ind)); - rach_ind->header.message_id = ind->header.message_id; - rach_ind->number_of_pdus = ind->number_of_pdus; - rach_ind->sfn = ind->sfn; - rach_ind->slot = ind->slot; - rach_ind->pdu_list = CALLOC(rach_ind->number_of_pdus, sizeof(*rach_ind->pdu_list)); - AssertFatal(rach_ind->pdu_list != NULL, "Memory not allocated for rach_ind->pdu_list in phy_nr_rach_indication."); - for (int i = 0; i < ind->number_of_pdus; i++) - { - rach_ind->pdu_list[i].num_preamble = ind->pdu_list[i].num_preamble; - rach_ind->pdu_list[i].freq_index = ind->pdu_list[i].freq_index; - rach_ind->pdu_list[i].symbol_index = ind->pdu_list[i].symbol_index; - AssertFatal(rach_ind->pdu_list[i].preamble_list != NULL, "Memory not allocated for rach_ind->pdu_list[i].preamble_list in phy_nr_rach_indication."); - for (int j = 0; j < ind->number_of_pdus; j++) - { - rach_ind->pdu_list[i].preamble_list[j].preamble_index = ind->pdu_list[i].preamble_list[j].preamble_index; - rach_ind->pdu_list[i].preamble_list[j].timing_advance = ind->pdu_list[i].preamble_list[j].timing_advance; - } - } - if (!put_queue(&gnb_rach_ind_queue, rach_ind)) - { + copy_rach_indication(ind, rach_ind); + if (!put_queue(&gnb_rach_ind_queue, rach_ind)) { LOG_E(NR_MAC, "Put_queue failed for rach_ind\n"); - free(rach_ind->pdu_list); + free_rach_indication(rach_ind); free(rach_ind); } - } - else { + } else { LOG_E(NR_MAC, "NFAPI_MODE = %d not NFAPI_MODE_VNF(2)\n", nfapi_getmode()); } return 1; @@ -754,84 +764,18 @@ int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { - - LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", - __FUNCTION__,ind->sfn, ind->slot, ind->num_ucis); - if(NFAPI_MODE == NFAPI_MODE_VNF) - { + LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", __FUNCTION__, ind->sfn, ind->slot, ind->num_ucis); + if (NFAPI_MODE == NFAPI_MODE_VNF) { nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind)); AssertFatal(uci_ind, "Memory not allocated for uci_ind in phy_nr_uci_indication."); - *uci_ind = *ind; - - uci_ind->uci_list = CALLOC(NFAPI_NR_UCI_IND_MAX_PDU, sizeof(nfapi_nr_uci_t)); - AssertFatal(uci_ind->uci_list != NULL, "Memory not allocated for uci_ind->uci_list in phy_nr_uci_indication."); - for (int i = 0; i < ind->num_ucis; i++) - { - uci_ind->uci_list[i] = ind->uci_list[i]; - - switch (uci_ind->uci_list[i].pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); - break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - //nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_ind_pdu = &uci_ind->uci_list[i].pucch_pdu_format_0_1; - //nfapi_nr_uci_pucch_pdu_format_0_1_t *ind_pdu = &ind->uci_list[i].pucch_pdu_format_0_1; - //Unused - break; - } - - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_ind_pdu = &uci_ind->uci_list[i].pucch_pdu_format_2_3_4; - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *ind_pdu = &ind->uci_list[i].pucch_pdu_format_2_3_4; - *uci_ind_pdu = *ind_pdu; - if (ind_pdu->harq.harq_payload) { - uci_ind_pdu->harq.harq_payload = CALLOC(1, sizeof(*uci_ind_pdu->harq.harq_payload)); - AssertFatal(uci_ind_pdu->harq.harq_payload != NULL, "Memory not allocated for uci_ind_pdu->harq.harq_payload in phy_nr_uci_indication."); - *uci_ind_pdu->harq.harq_payload = *ind_pdu->harq.harq_payload; - } - if (ind_pdu->sr.sr_payload) { - uci_ind_pdu->sr.sr_payload = CALLOC(1, sizeof(*uci_ind_pdu->sr.sr_payload)); - AssertFatal(uci_ind_pdu->sr.sr_payload != NULL, "Memory not allocated for uci_ind_pdu->sr.sr_payload in phy_nr_uci_indication."); - *uci_ind_pdu->sr.sr_payload = *ind_pdu->sr.sr_payload; - } - if (ind_pdu->csi_part1.csi_part1_payload) { - uci_ind_pdu->csi_part1.csi_part1_payload = CALLOC(1, sizeof(*uci_ind_pdu->csi_part1.csi_part1_payload)); - AssertFatal(uci_ind_pdu->csi_part1.csi_part1_payload != NULL, "Memory not allocated for uci_ind_pdu->csi_part1.csi_part1_payload in phy_nr_uci_indication."); - *uci_ind_pdu->csi_part1.csi_part1_payload = *ind_pdu->csi_part1.csi_part1_payload; - } - if (ind_pdu->csi_part2.csi_part2_payload) { - uci_ind_pdu->csi_part2.csi_part2_payload = CALLOC(1, sizeof(*uci_ind_pdu->csi_part2.csi_part2_payload)); - AssertFatal(uci_ind_pdu->csi_part2.csi_part2_payload != NULL, "Memory not allocated for uci_ind_pdu->csi_part2.csi_part2_payload in phy_nr_uci_indication."); - *uci_ind_pdu->csi_part2.csi_part2_payload = *ind_pdu->csi_part2.csi_part2_payload; - } - break; - } - } - } - - if (!put_queue(&gnb_uci_ind_queue, uci_ind)) - { + copy_uci_indication(ind, uci_ind); + if (!put_queue(&gnb_uci_ind_queue, uci_ind)) { LOG_E(NR_MAC, "Put_queue failed for uci_ind\n"); - for (int i = 0; i < ind->num_ucis; i++) - { - if (uci_ind->uci_list[i].pdu_type == NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE) - { - } - if (uci_ind->uci_list[i].pdu_type == NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE) - { - free(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload); - free(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload); - free(uci_ind->uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload); - } - } - free(uci_ind->uci_list); - uci_ind->uci_list = NULL; + free_uci_indication(uci_ind); free(uci_ind); uci_ind = NULL; } - } - else { + } else { LOG_E(NR_MAC, "NFAPI_MODE = %d not NFAPI_MODE_VNF(2)\n", nfapi_getmode()); } return 1; @@ -922,43 +866,19 @@ int phy_crc_indication(struct nfapi_vnf_p7_config *config, nfapi_crc_indication_ return 1; } -int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { - - LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", - __FUNCTION__,ind->sfn, ind->slot, ind->number_crcs); +int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) +{ + LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", __FUNCTION__, ind->sfn, ind->slot, ind->number_crcs); - if(NFAPI_MODE == NFAPI_MODE_VNF) - { + if (NFAPI_MODE == NFAPI_MODE_VNF) { nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind)); - crc_ind->header.message_id = ind->header.message_id; - crc_ind->number_crcs = ind->number_crcs; - crc_ind->sfn = ind->sfn; - crc_ind->slot = ind->slot; - if (ind->number_crcs > 0) { - crc_ind->crc_list = CALLOC(NFAPI_NR_CRC_IND_MAX_PDU, sizeof(nfapi_nr_crc_t)); - AssertFatal(crc_ind->crc_list != NULL, "Memory not allocated for crc_ind->crc_list in phy_nr_crc_indication."); - } - for (int j = 0; j < ind->number_crcs; j++) - { - crc_ind->crc_list[j].handle = ind->crc_list[j].handle; - crc_ind->crc_list[j].harq_id = ind->crc_list[j].harq_id; - crc_ind->crc_list[j].num_cb = ind->crc_list[j].num_cb; - crc_ind->crc_list[j].rnti = ind->crc_list[j].rnti; - crc_ind->crc_list[j].tb_crc_status = ind->crc_list[j].tb_crc_status; - crc_ind->crc_list[j].timing_advance = ind->crc_list[j].timing_advance; - crc_ind->crc_list[j].ul_cqi = ind->crc_list[j].ul_cqi; - LOG_D(NR_MAC, "Received crc_ind.harq_id = %d for %d index SFN SLot %u %u with rnti %x\n", - ind->crc_list[j].harq_id, j, ind->sfn, ind->slot, ind->crc_list[j].rnti); - } - if (!put_queue(&gnb_crc_ind_queue, crc_ind)) - { + copy_crc_indication(ind, crc_ind); + if (!put_queue(&gnb_crc_ind_queue, crc_ind)) { LOG_E(NR_MAC, "Put_queue failed for crc_ind\n"); - free(crc_ind->crc_list); + free_crc_indication(crc_ind); free(crc_ind); } - } - else - { + } else { LOG_E(NR_MAC, "NFAPI_MODE = %d not NFAPI_MODE_VNF(2)\n", nfapi_getmode()); } return 1; @@ -1041,43 +961,25 @@ int phy_rx_indication(struct nfapi_vnf_p7_config *config, nfapi_rx_indication_t return 1; } -int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { - - LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u, and pdu %p\n", - __FUNCTION__,ind->sfn, ind->slot, ind->number_of_pdus, ind->pdu_list[0].pdu); +int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) +{ + LOG_D(NR_MAC, + "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u, and pdu %p\n", + __FUNCTION__, + ind->sfn, + ind->slot, + ind->number_of_pdus, + ind->pdu_list[0].pdu); - if(NFAPI_MODE == NFAPI_MODE_VNF) - { + if (NFAPI_MODE == NFAPI_MODE_VNF) { nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind)); - rx_ind->header.message_id = ind->header.message_id; - rx_ind->sfn = ind->sfn; - rx_ind->slot = ind->slot; - rx_ind->number_of_pdus = ind->number_of_pdus; - - if (ind->number_of_pdus > 0) { - rx_ind->pdu_list = CALLOC(NFAPI_NR_RX_DATA_IND_MAX_PDU, sizeof(nfapi_nr_rx_data_pdu_t)); - AssertFatal(rx_ind->pdu_list != NULL, "Memory not allocated for rx_ind->pdu_list in phy_nr_rx_data_indication."); - } - for (int j = 0; j < ind->number_of_pdus; j++) - { - rx_ind->pdu_list[j].handle = ind->pdu_list[j].handle; - rx_ind->pdu_list[j].harq_id = ind->pdu_list[j].harq_id; - rx_ind->pdu_list[j].pdu = ind->pdu_list[j].pdu; - rx_ind->pdu_list[j].pdu_length = ind->pdu_list[j].pdu_length; - rx_ind->pdu_list[j].rnti = ind->pdu_list[j].rnti; - rx_ind->pdu_list[j].timing_advance = ind->pdu_list[j].timing_advance; - rx_ind->pdu_list[j].ul_cqi = ind->pdu_list[j].ul_cqi; - rx_ind->pdu_list[j].rssi = ind->pdu_list[j].rssi; - } - if (!put_queue(&gnb_rx_ind_queue, rx_ind)) - { + copy_rx_data_indication(ind, rx_ind); + if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { LOG_E(NR_MAC, "Put_queue failed for rx_ind\n"); - free(rx_ind->pdu_list); + free_rx_data_indication(rx_ind); free(rx_ind); } - } - else - { + } else { LOG_E(NR_MAC, "NFAPI_MODE = %d not NFAPI_MODE_VNF(2)\n", nfapi_getmode()); } return 1; @@ -1238,24 +1140,10 @@ int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { return 1; } - -int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - - gNB->UL_INFO.srs_ind = *ind; - - if (ind->number_of_pdus > 0) - gNB->UL_INFO.srs_ind.pdu_list = malloc(sizeof(nfapi_nr_srs_indication_pdu_t)*ind->number_of_pdus); - - for (int i=0; i<ind->number_of_pdus; i++) { - memcpy(&gNB->UL_INFO.srs_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); - - LOG_D(MAC, "%s() NFAPI SFN/Slot:%d.%d SRS_IND:number_of_pdus:%d UL_INFO:pdus:%d\n", - __FUNCTION__, - ind->sfn,ind->slot, ind->number_of_pdus, gNB->UL_INFO.srs_ind.number_of_pdus - ); - } - +int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) +{ + for (int i = 0; i < ind->number_of_pdus; ++i) + handle_nr_srs_measurements(0, ind->sfn, ind->slot, &ind->pdu_list[i]); return 1; } //end NR phy indication @@ -1288,6 +1176,17 @@ void vnf_deallocate(void *ptr) { free(ptr); } +void *vnf_nr_allocate(size_t size) +{ + // return (void*)memory_pool::allocate(size); + return (void *)malloc(size); +} + +void vnf_nr_deallocate(void *ptr) +{ + // memory_pool::deallocate((uint8_t*)ptr); + free(ptr); +} void vnf_trace(nfapi_trace_level_t nfapi_level, const char *message, ...) { va_list args; @@ -1296,18 +1195,31 @@ void vnf_trace(nfapi_trace_level_t nfapi_level, const char *message, ...) { va_end(args); } -int phy_vendor_ext(struct nfapi_vnf_p7_config *config, nfapi_p7_message_header_t *msg) { - if(msg->message_id == P7_VENDOR_EXT_IND) { - //vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)msg; - //NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] vendor_ext (error_code:%d)\n", ind->error_code); +int phy_vendor_ext(struct nfapi_vnf_p7_config *config, void *msg) +{ + if (((nfapi_p7_message_header_t *)msg)->message_id == P7_VENDOR_EXT_IND) { + // vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)msg; + // NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] vendor_ext (error_code:%d)\n", ind->error_code); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] unknown %02x\n", ((nfapi_p7_message_header_t *)msg)->message_id); + } + + return 0; +} + +int phy_nr_vendor_ext(struct nfapi_vnf_p7_config *config, void *msg) +{ + if (((nfapi_nr_p7_message_header_t *)msg)->message_id == P7_VENDOR_EXT_IND) { + // vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)msg; + // NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] vendor_ext (error_code:%d)\n", ind->error_code); } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] unknown %02x\n", msg->message_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] unknown %02x\n", ((nfapi_nr_p7_message_header_t *)msg)->message_id); } return 0; } -nfapi_p7_message_header_t *phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) { +void *phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) { if(message_id == P7_VENDOR_EXT_IND) { *msg_size = sizeof(vendor_ext_p7_ind); return (nfapi_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_ind)); @@ -1316,7 +1228,23 @@ nfapi_p7_message_header_t *phy_allocate_p7_vendor_ext(uint16_t message_id, uint1 return 0; } -void phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) { +void phy_deallocate_p7_vendor_ext(void *header) +{ + free(header); +} + +void *phy_nr_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) +{ + if (message_id == P7_VENDOR_EXT_IND) { + *msg_size = sizeof(vendor_ext_p7_ind); + return (nfapi_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_ind)); + } + + return 0; +} + +void phy_nr_deallocate_p7_vendor_ext(void *header) +{ free(header); } @@ -1327,6 +1255,18 @@ int phy_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMessag return -1; } +int phy_nr_unpack_vendor_extension_tlv(nfapi_tl_t *tl, + uint8_t **ppReadPackedMessage, + uint8_t *end, + void **ve, + nfapi_p7_codec_config_t *codec) +{ + (void)tl; + (void)ppReadPackedMessage; + (void)ve; + return -1; +} + int phy_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codec) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "phy_pack_vendor_extension_tlv\n"); nfapi_tl_t *tlv = (nfapi_tl_t *)ve; @@ -1349,39 +1289,100 @@ int phy_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t } } -int phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *config) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if(header->message_id == P7_VENDOR_EXT_IND) { +int phy_nr_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "phy_pack_vendor_extension_tlv\n"); + nfapi_tl_t *tlv = (nfapi_tl_t *)ve; + + switch (tlv->tag) { + case VENDOR_EXT_TLV_1_TAG: { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "Packing VENDOR_EXT_TLV_1\n"); + vendor_ext_tlv_1 *ve = (vendor_ext_tlv_1 *)tlv; + + if (!push32(ve->dummy, ppWritePackedMsg, end)) + return 0; + + return 1; + } break; + + default: + return -1; + break; + } +} +int phy_unpack_p7_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_IND) { + vendor_ext_p7_ind *req = (vendor_ext_p7_ind *)(header); + + if (!pull16(ppReadPackedMessage, &req->error_code, end)) + return 0; + } + + return 1; +} + +int phy_nr_unpack_p7_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_IND) { vendor_ext_p7_ind *req = (vendor_ext_p7_ind *)(header); - if(!pull16(ppReadPackedMessage, &req->error_code, end)) + if (!pull16(ppReadPackedMessage, &req->error_code, end)) return 0; } return 1; } -int phy_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if(header->message_id == P7_VENDOR_EXT_REQ) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); +int phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_REQ) { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); vendor_ext_p7_req *req = (vendor_ext_p7_req *)(header); - if(!(push16(req->dummy1, ppWritePackedMsg, end) && - push16(req->dummy2, ppWritePackedMsg, end))) + if (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))) return 0; } return 1; } -int vnf_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if(header->message_id == P5_VENDOR_EXT_REQ) { +int phy_nr_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_REQ) { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + vendor_ext_p7_req *req = (vendor_ext_p7_req *)(header); + + if (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} + +int vnf_pack_p4_p5_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_REQ) { + vendor_ext_p5_req *req = (vendor_ext_p5_req *)(header); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s %d %d\n", __FUNCTION__, req->dummy1, req->dummy2); + return (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))); + } + + return 0; +} + +int vnf_nr_pack_p4_p5_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_REQ) { vendor_ext_p5_req *req = (vendor_ext_p5_req *)(header); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s %d %d\n", __FUNCTION__, req->dummy1, req->dummy2); - return (!(push16(req->dummy1, ppWritePackedMsg, end) && - push16(req->dummy2, ppWritePackedMsg, end))); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s %d %d\n", __FUNCTION__, req->dummy1, req->dummy2); + return (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))); } return 0; @@ -1406,7 +1407,8 @@ void *vnf_p7_start_thread(void *ptr) { return config; } -void *vnf_nr_p7_thread_start(void *ptr) { +void *vnf_nr_p7_thread_start(void *ptr) +{ init_queue(&gnb_rach_ind_queue); init_queue(&gnb_rx_ind_queue); init_queue(&gnb_crc_ind_queue); @@ -1432,17 +1434,17 @@ void *vnf_nr_p7_thread_start(void *ptr) { p7_vnf->config->nr_srs_indication = &phy_nr_srs_indication; p7_vnf->config->malloc = &vnf_allocate; p7_vnf->config->free = &vnf_deallocate; - p7_vnf->config->vendor_ext = &phy_vendor_ext; + p7_vnf->config->vendor_ext = &phy_nr_vendor_ext; p7_vnf->config->user_data = p7_vnf; p7_vnf->mac->user_data = p7_vnf; - p7_vnf->config->codec_config.unpack_p7_vendor_extension = &phy_unpack_p7_vendor_extension; - p7_vnf->config->codec_config.pack_p7_vendor_extension = &phy_pack_p7_vendor_extension; - p7_vnf->config->codec_config.unpack_vendor_extension_tlv = &phy_unpack_vendor_extension_tlv; - p7_vnf->config->codec_config.pack_vendor_extension_tlv = &phy_pack_vendor_extension_tlv; + p7_vnf->config->codec_config.unpack_p7_vendor_extension = &phy_nr_unpack_p7_vendor_extension; + p7_vnf->config->codec_config.pack_p7_vendor_extension = &phy_nr_pack_p7_vendor_extension; + p7_vnf->config->codec_config.unpack_vendor_extension_tlv = &phy_nr_unpack_vendor_extension_tlv; + p7_vnf->config->codec_config.pack_vendor_extension_tlv = &phy_nr_pack_vendor_extension_tlv; p7_vnf->config->codec_config.allocate = &vnf_allocate; p7_vnf->config->codec_config.deallocate = &vnf_deallocate; - p7_vnf->config->allocate_p7_vendor_ext = &phy_allocate_p7_vendor_ext; - p7_vnf->config->deallocate_p7_vendor_ext = &phy_deallocate_p7_vendor_ext; + p7_vnf->config->allocate_p7_vendor_ext = &phy_nr_allocate_p7_vendor_ext; + p7_vnf->config->deallocate_p7_vendor_ext = &phy_nr_deallocate_p7_vendor_ext; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); pthread_create(&vnf_p7_start_pthread, NULL, &vnf_nr_p7_start_thread, p7_vnf->config); return 0; @@ -1696,10 +1698,11 @@ int nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_resp return 0; } -int vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_p4_p5_message_header_t *msg) { +int vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, void *msg) +{ NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s\n", __FUNCTION__); - switch(msg->message_id) { + switch (((nfapi_p4_p5_message_header_t *)msg)->message_id) { case P5_VENDOR_EXT_RSP: { vendor_ext_p5_rsp *rsp = (vendor_ext_p5_rsp *)msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] P5_VENDOR_EXT_RSP error_code:%d\n", rsp->error_code); @@ -1708,25 +1711,58 @@ int vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_p4_p5_message_he memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_PNF_START_REQUEST; nfapi_vnf_pnf_start_req(config, p5_idx, &req); - } - break; + } break; + } + + return 0; +} + +int vendor_nr_ext_cb(nfapi_vnf_config_t *config, int p5_idx, void *msg) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s\n", __FUNCTION__); + + switch (((nfapi_nr_p4_p5_message_header_t *)msg)->message_id) { + case P5_VENDOR_EXT_RSP: { + vendor_ext_p5_rsp *rsp = (vendor_ext_p5_rsp *)msg; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] P5_VENDOR_EXT_RSP error_code:%d\n", rsp->error_code); + // send the start request + nfapi_nr_pnf_start_request_t req = {0}; + req.header.message_id = NFAPI_PNF_START_REQUEST; + nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); + } break; } return 0; } -int vnf_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if(header->message_id == P5_VENDOR_EXT_RSP) { +int vnf_unpack_p4_p5_vendor_extension(void *header, uint8_t **ppReadPackedMessage, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_RSP) { vendor_ext_p5_rsp *req = (vendor_ext_p5_rsp *)(header); - return(!pull16(ppReadPackedMessage, &req->error_code, end)); + return (!pull16(ppReadPackedMessage, &req->error_code, end)); } return 0; } -nfapi_p4_p5_message_header_t *vnf_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) { - if(message_id == P5_VENDOR_EXT_RSP) { +int vnf_nr_unpack_p4_p5_vendor_extension(void *header, + uint8_t **ppReadPackedMessage, + uint8_t *end, + nfapi_p4_p5_codec_config_t *codec) +{ + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_RSP) { + vendor_ext_p5_rsp *req = (vendor_ext_p5_rsp *)(header); + return (!pull16(ppReadPackedMessage, &req->error_code, end)); + } + + return 0; +} + +void *vnf_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) +{ + if (message_id == P5_VENDOR_EXT_RSP) { *msg_size = sizeof(vendor_ext_p5_rsp); return (nfapi_p4_p5_message_header_t *)malloc(sizeof(vendor_ext_p5_rsp)); } @@ -1734,10 +1770,26 @@ nfapi_p4_p5_message_header_t *vnf_allocate_p4_p5_vendor_ext(uint16_t message_id, return 0; } -void vnf_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t *header) { +void vnf_deallocate_p4_p5_vendor_ext(void *header) +{ free(header); } +void *vnf_nr_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t *msg_size) +{ + if (message_id == P5_VENDOR_EXT_RSP) { + *msg_size = sizeof(vendor_ext_p5_rsp); + return (nfapi_p4_p5_message_header_t *)malloc(sizeof(vendor_ext_p5_rsp)); + } + + return 0; +} + +void vnf_nr_deallocate_p4_p5_vendor_ext(void *header) { + free(header); +} + + nfapi_vnf_config_t *config = 0; void vnf_nr_start_thread(void *ptr) { @@ -1756,7 +1808,8 @@ void vnf_start_thread(void *ptr) { static vnf_info vnf; -void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { +void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) +{ nfapi_setmode(NFAPI_MODE_VNF); memset(&vnf, 0, sizeof(vnf)); memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); @@ -1765,7 +1818,12 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; vnf.p7_vnfs[0].periodic_timing_period = 10; vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port); + NFAPI_TRACE(NFAPI_TRACE_INFO, + "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", + __FUNCTION__, + vnf.p7_vnfs[0].config, + vnf_addr, + vnf_p5_port); strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); vnf.p7_vnfs[0].local_port = vnf_p7_port; vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); @@ -1787,18 +1845,18 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, config->nr_param_resp = &nr_param_resp_cb; config->nr_config_resp = &nr_config_resp_cb; config->nr_start_resp = &nr_start_resp_cb; - config->vendor_ext = &vendor_ext_cb; + config->vendor_ext = &vendor_nr_ext_cb; config->user_data = &vnf; // To allow custom vendor extentions to be added to nfapi - config->codec_config.unpack_vendor_extension_tlv = &vnf_unpack_vendor_extension_tlv; - config->codec_config.pack_vendor_extension_tlv = &vnf_pack_vendor_extension_tlv; - config->codec_config.unpack_p4_p5_vendor_extension = &vnf_unpack_p4_p5_vendor_extension; - config->codec_config.pack_p4_p5_vendor_extension = &vnf_pack_p4_p5_vendor_extension; - config->allocate_p4_p5_vendor_ext = &vnf_allocate_p4_p5_vendor_ext; - config->deallocate_p4_p5_vendor_ext = &vnf_deallocate_p4_p5_vendor_ext; - config->codec_config.allocate = &vnf_allocate; - config->codec_config.deallocate = &vnf_deallocate; - memset(&UL_RCC_INFO,0,sizeof(UL_RCC_IND_t)); + config->codec_config.unpack_vendor_extension_tlv = &vnf_nr_unpack_vendor_extension_tlv; + config->codec_config.pack_vendor_extension_tlv = &vnf_nr_pack_vendor_extension_tlv; + config->codec_config.unpack_p4_p5_vendor_extension = &vnf_nr_unpack_p4_p5_vendor_extension; + config->codec_config.pack_p4_p5_vendor_extension = &vnf_nr_pack_p4_p5_vendor_extension; + config->allocate_p4_p5_vendor_ext = &vnf_nr_allocate_p4_p5_vendor_ext; + config->deallocate_p4_p5_vendor_ext = &vnf_nr_deallocate_p4_p5_vendor_ext; + config->codec_config.allocate = &vnf_nr_allocate; + config->codec_config.deallocate = &vnf_nr_deallocate; + memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_IND_t)); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_nr_start_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); diff --git a/nfapi/open-nFAPI/fapi/CMakeLists.txt b/nfapi/open-nFAPI/fapi/CMakeLists.txt index 1e2208172f284526cf1cf97a1bab3bed81e4e6f9..b332ef6a8e1f87c923038cdeecf2e8575b3bc914 100644 --- a/nfapi/open-nFAPI/fapi/CMakeLists.txt +++ b/nfapi/open-nFAPI/fapi/CMakeLists.txt @@ -1,9 +1,24 @@ +add_library(nr_fapi_common + src/nr_fapi.c +) +target_include_directories(nr_fapi_common PUBLIC inc) +target_link_libraries(nr_fapi_common PUBLIC nfapi_common) + add_library(nr_fapi_p5 src/nr_fapi_p5.c src/nr_fapi_p5_utils.c ) target_include_directories(nr_fapi_p5 PUBLIC inc) -target_link_libraries(nr_fapi_p5 PUBLIC nfapi_common) -if(OAI_AERIAL) +target_link_libraries(nr_fapi_p5 PUBLIC nr_fapi_common) + +add_library(nr_fapi_p7 + src/nr_fapi_p7.c + src/nr_fapi_p7_utils.c +) +target_include_directories(nr_fapi_p7 PUBLIC inc) +target_link_libraries(nr_fapi_p7 PUBLIC nr_fapi_common) + +if (OAI_AERIAL) target_compile_definitions(nr_fapi_p5 PRIVATE ENABLE_AERIAL) -endif() + target_compile_definitions(nr_fapi_p7 PRIVATE ENABLE_AERIAL) +endif () diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h index 322c09b59c5d5175a673cd22d4aa9715454e06d3..f90fafebebc393f8c8ae620ee85eaae52cdfd1a4 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h @@ -18,16 +18,6 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/open-nFAPI/fapi/inc/nr_fapi.h - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #ifndef OPENAIRINTERFACE_NR_FAPI_H #define OPENAIRINTERFACE_NR_FAPI_H @@ -42,6 +32,32 @@ #include <arpa/inet.h> #include <netinet/in.h> #include "assertions.h" +#include "debug.h" + +#define EQ_TLV(_tlv_a, _tlv_b) \ + do { \ + EQ(_tlv_a.tl.tag, _tlv_b.tl.tag); \ + EQ(_tlv_a.value, _tlv_b.value); \ + } while (0) + +#define EQ(_a, _b) \ + do { \ + if ((_a) != (_b)) { \ + return false; \ + } \ + } while (0) + +#define COPY_TL(_dst_tl, _src_tl) \ + do { \ + _dst_tl.tag = _src_tl.tag; \ + _dst_tl.length = _src_tl.length; \ + } while (0) + +#define COPY_TLV(_dst, _src) \ + do { \ + COPY_TL(_dst.tl, _src.tl); \ + _dst.value = _src.value; \ + } while (0) typedef struct { uint8_t num_msg; @@ -50,23 +66,16 @@ typedef struct { uint32_t message_length; } fapi_message_header_t; -int fapi_nr_p5_message_header_unpack(uint8_t **pMessageBuf, - uint32_t messageBufLen, - void *pUnpackedBuf, - uint32_t unpackedBufLen, - nfapi_p4_p5_codec_config_t *config); - -int fapi_nr_p5_message_pack(void *pMessageBuf, - uint32_t messageBufLen, - void *pPackedBuf, - uint32_t packedBufLen, - nfapi_p4_p5_codec_config_t *config); +void copy_vendor_extension_value(nfapi_vendor_extension_tlv_t *dst, const nfapi_vendor_extension_tlv_t *src); -int fapi_nr_p5_message_unpack(void *pMessageBuf, - uint32_t messageBufLen, - void *pUnpackedBuf, - uint32_t unpackedBufLen, - nfapi_p4_p5_codec_config_t *config); +bool isFAPIMessageIDValid(uint16_t id); int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen); + +int fapi_nr_message_header_unpack(uint8_t **pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config); + #endif // OPENAIRINTERFACE_NR_FAPI_H diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h index feade4015b125e9ff16890a726a95fa3e846f02e..307b5bad27afc61248adc03a087958f090040d24 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h @@ -18,22 +18,24 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #ifndef OPENAIRINTERFACE_NR_FAPI_P5_H #define OPENAIRINTERFACE_NR_FAPI_P5_H #include "stdint.h" #include "nfapi_interface.h" +int fapi_nr_p5_message_pack(void *pMessageBuf, + uint32_t messageBufLen, + void *pPackedBuf, + uint32_t packedBufLen, + nfapi_p4_p5_codec_config_t *config); + +int fapi_nr_p5_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config); + uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config); uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config); uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config); diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h index 36d327a850a8cc65d292780f9067e3e8958e7007..edd75df6775a63fbe927f9d813ed3dd4a1e239c0 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h @@ -18,16 +18,6 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #ifndef OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H #define OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H @@ -36,33 +26,6 @@ #include "nr_fapi.h" #include "nfapi/oai_integration/vendor_ext.h" -#define EQ_TLV(_tlv_a, _tlv_b) \ - do { \ - EQ(_tlv_a.tl.tag, _tlv_b.tl.tag); \ - EQ(_tlv_a.value, _tlv_b.value); \ - } while (0) - -#define EQ(_a, _b) \ - do { \ - if ((_a) != (_b)) { \ - return false; \ - } \ - } while (0) - -#define COPY_TL(_dst_tl, _src_tl) \ - do { \ - _dst_tl.tag = _src_tl.tag; \ - _dst_tl.length = _src_tl.length; \ - } while (0) - -#define COPY_TLV(_dst, _src) \ - do { \ - COPY_TL(_dst.tl, _src.tl); \ - _dst.value = _src.value; \ - } while (0) - -void copy_vendor_extension_value(nfapi_vendor_extension_tlv_t *dst, const nfapi_vendor_extension_tlv_t *src); - bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req); bool eq_param_response(const nfapi_nr_param_response_scf_t *unpacked_req, const nfapi_nr_param_response_scf_t *req); bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const nfapi_nr_config_request_scf_t *req); diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h new file mode 100644 index 0000000000000000000000000000000000000000..76e2043f2d69aa38d5487ead15c2095d520bf39c --- /dev/null +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h @@ -0,0 +1,55 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#ifndef OPENAIRINTERFACE_NR_FAPI_P7_H +#define OPENAIRINTERFACE_NR_FAPI_P7_H + +int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config); + +int fapi_nr_p7_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config); + +uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_nr_slot_indication_scf_t *msg, + nfapi_p7_codec_config_t *config); +uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); +uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); +#endif // OPENAIRINTERFACE_NR_FAPI_P7_H diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..e0682dbb44e88eda2d27ff926eac4d3645393f2e --- /dev/null +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h @@ -0,0 +1,78 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +/*! \file nfapi/open-nFAPI/fapi/inc/p5/nr_fapi_p5_utils.h + * \brief + * \author Ruben S. Silva + * \date 2024 + * \version 0.1 + * \company OpenAirInterface Software Alliance + * \email: contact@openairinterface.org, rsilva@allbesmart.pt + * \note + * \warning + */ + +#ifndef OPENAIRINTERFACE_NR_FAPI_P7_UTILS_H +#define OPENAIRINTERFACE_NR_FAPI_P7_UTILS_H +#include "stdio.h" +#include "stdint.h" +#include "nr_fapi.h" + +bool eq_dl_tti_request(const nfapi_nr_dl_tti_request_t *a, const nfapi_nr_dl_tti_request_t *b); +bool eq_ul_tti_request(const nfapi_nr_ul_tti_request_t *a, const nfapi_nr_ul_tti_request_t *b); +bool eq_slot_indication(const nfapi_nr_slot_indication_scf_t *a, const nfapi_nr_slot_indication_scf_t *b); +bool eq_ul_dci_request(const nfapi_nr_ul_dci_request_t *a, const nfapi_nr_ul_dci_request_t *b); +bool eq_tx_data_request(const nfapi_nr_tx_data_request_t *a, const nfapi_nr_tx_data_request_t *b); +bool eq_rx_data_indication(const nfapi_nr_rx_data_indication_t *a, const nfapi_nr_rx_data_indication_t *b); +bool eq_crc_indication(const nfapi_nr_crc_indication_t *a, const nfapi_nr_crc_indication_t *b); +bool eq_uci_indication(const nfapi_nr_uci_indication_t *a, const nfapi_nr_uci_indication_t *b); +bool eq_srs_indication(const nfapi_nr_srs_indication_t *a, const nfapi_nr_srs_indication_t *b); +bool eq_rach_indication(const nfapi_nr_rach_indication_t *a, const nfapi_nr_rach_indication_t *b); + +void free_dl_tti_request(nfapi_nr_dl_tti_request_t *msg); +void free_ul_tti_request(nfapi_nr_ul_tti_request_t *msg); +void free_slot_indication(nfapi_nr_slot_indication_scf_t *msg); +void free_ul_dci_request(nfapi_nr_ul_dci_request_t *msg); +void free_tx_data_request(nfapi_nr_tx_data_request_t *msg); +void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg); +void free_crc_indication(nfapi_nr_crc_indication_t *msg); +void free_uci_indication(nfapi_nr_uci_indication_t *msg); +void free_srs_indication(nfapi_nr_srs_indication_t *msg); +void free_rach_indication(nfapi_nr_rach_indication_t *msg); + +void copy_dl_tti_request(const nfapi_nr_dl_tti_request_t *src, nfapi_nr_dl_tti_request_t *dst); +void copy_ul_tti_request(const nfapi_nr_ul_tti_request_t *src, nfapi_nr_ul_tti_request_t *dst); +void copy_slot_indication(const nfapi_nr_slot_indication_scf_t *src, nfapi_nr_slot_indication_scf_t *dst); +void copy_ul_dci_request(const nfapi_nr_ul_dci_request_t *src, nfapi_nr_ul_dci_request_t *dst); +void copy_tx_data_request(const nfapi_nr_tx_data_request_t *src, nfapi_nr_tx_data_request_t *dst); +void copy_rx_data_indication(const nfapi_nr_rx_data_indication_t *src, nfapi_nr_rx_data_indication_t *dst); +void copy_crc_indication(const nfapi_nr_crc_indication_t *src, nfapi_nr_crc_indication_t *dst); +void copy_uci_indication(const nfapi_nr_uci_indication_t *src, nfapi_nr_uci_indication_t *dst); +void copy_srs_indication(const nfapi_nr_srs_indication_t *src, nfapi_nr_srs_indication_t *dst); +void copy_rach_indication(const nfapi_nr_rach_indication_t *src, nfapi_nr_rach_indication_t *dst); + + +size_t get_tx_data_request_size(const nfapi_nr_tx_data_request_t *msg); +size_t get_rx_data_indication_size(const nfapi_nr_rx_data_indication_t *msg); +size_t get_crc_indication_size(const nfapi_nr_crc_indication_t *msg); +size_t get_uci_indication_size(const nfapi_nr_uci_indication_t *msg); +size_t get_srs_indication_size(const nfapi_nr_srs_indication_t *msg); +size_t get_rach_indication_size(nfapi_nr_rach_indication_t *msg); +#endif // OPENAIRINTERFACE_NR_FAPI_P7_UTILS_H diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi.c b/nfapi/open-nFAPI/fapi/src/nr_fapi.c new file mode 100644 index 0000000000000000000000000000000000000000..c36fff4b349c927d9a5a69b822681b7046bbfff5 --- /dev/null +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi.c @@ -0,0 +1,188 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "nr_fapi.h" + +void copy_vendor_extension_value(nfapi_vendor_extension_tlv_t *dst, const nfapi_vendor_extension_tlv_t *src) +{ + nfapi_tl_t *dst_tlv = (nfapi_tl_t *)dst; + nfapi_tl_t *src_tlv = (nfapi_tl_t *)src; + + switch (dst_tlv->tag) { + case VENDOR_EXT_TLV_2_TAG: { + vendor_ext_tlv_2 *dst_ve = (vendor_ext_tlv_2 *)dst_tlv; + vendor_ext_tlv_2 *src_ve = (vendor_ext_tlv_2 *)src_tlv; + + dst_ve->dummy = src_ve->dummy; + } break; + case VENDOR_EXT_TLV_1_TAG: { + vendor_ext_tlv_1 *dst_ve = (vendor_ext_tlv_1 *)dst_tlv; + vendor_ext_tlv_1 *src_ve = (vendor_ext_tlv_1 *)src_tlv; + + dst_ve->dummy = src_ve->dummy; + } break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown Vendor Extension tag %d\n", dst_tlv->tag); + } +} + +bool isFAPIMessageIDValid(const uint16_t id) +{ + // SCF 222.10.04 Table 3-5 PHY API message types + return (id >= NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST && id <= 0xFF) || id == NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE + || id == NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC || id == NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC + || id == NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO; +} + +int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + // check for size of nFAPI struct without the nFAPI specific parameters + switch (msgId) { + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) + retLen = sizeof(fapi_message_header_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t) - sizeof(nfapi_nr_nfapi_t)) + retLen = sizeof(nfapi_nr_param_request_scf_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t) - sizeof(nfapi_nr_nfapi_t)) + retLen = sizeof(nfapi_nr_config_request_scf_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) + retLen = sizeof(nfapi_nr_config_response_scf_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_start_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) + retLen = sizeof(fapi_message_header_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) + retLen = sizeof(fapi_message_header_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_stop_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) + retLen = sizeof(fapi_message_header_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_stop_indication_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) + retLen = sizeof(fapi_message_header_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_error_indication_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) + retLen = sizeof(fapi_message_header_t); + + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) + retLen = sizeof(nfapi_nr_dl_tti_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) + retLen = sizeof(nfapi_nr_ul_tti_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + case NFAPI_NR_PHY_MSG_TYPE_VENDOR_EXT_SLOT_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_slot_indication_scf_t)) + retLen = sizeof(nfapi_nr_slot_indication_scf_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) + retLen = sizeof(nfapi_nr_ul_dci_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) + retLen = sizeof(nfapi_nr_tx_data_request_t); + break; + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) + retLen = sizeof(nfapi_nr_rx_data_indication_t); + break; + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) + retLen = sizeof(nfapi_nr_crc_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) + retLen = sizeof(nfapi_nr_rach_indication_t); + break; + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) + retLen = sizeof(nfapi_nr_uci_indication_t); + break; + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) + retLen = sizeof(nfapi_nr_srs_indication_t); + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) + retLen = sizeof(nfapi_nr_dl_node_sync_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) + retLen = sizeof(nfapi_nr_ul_node_sync_t); + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); + break; + } + + return retLen; +} + +int fapi_nr_message_header_unpack(uint8_t **pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config) +{ + uint8_t **pReadPackedMessage = pMessageBuf; + nfapi_nr_p4_p5_message_header_t *header = pUnpackedBuf; + fapi_message_header_t fapi_msg = {0}; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL || messageBufLen < NFAPI_HEADER_LENGTH + || unpackedBufLen < sizeof(fapi_message_header_t)) { + return -1; + } + uint8_t *end = *pMessageBuf + messageBufLen; + // process the header + int result = + (pull8(pReadPackedMessage, &fapi_msg.num_msg, end) && pull8(pReadPackedMessage, &fapi_msg.opaque_handle, end) + && pull16(pReadPackedMessage, &header->message_id, end) && pull32(pReadPackedMessage, &header->message_length, end)); + return (result); +} diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 295cca7a4876dd3ce2069dc5fcdd3ddd890c5e5c..b5ff0a24900d4c4e711be375dadb587b124dd6f1 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -18,53 +18,11 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nr_fapi.h" #include "nr_fapi_p5.h" -#include "nr_fapi_p5_utils.h" #include "debug.h" -bool isFAPIMessageIDValid(uint16_t id) -{ - // SCF 222.10.04 Table 3-5 PHY API message types - return (id >= NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST && id <= 0xFF) || id == NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE - || id == NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC || id == NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC - || id == NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO; -} - -int fapi_nr_p5_message_header_unpack(uint8_t **pMessageBuf, - uint32_t messageBufLen, - void *pUnpackedBuf, - uint32_t unpackedBufLen, - nfapi_p4_p5_codec_config_t *config) -{ - uint8_t **pReadPackedMessage = pMessageBuf; - nfapi_p4_p5_message_header_t *header = pUnpackedBuf; - fapi_message_header_t fapi_msg; - - if(pMessageBuf == NULL || pUnpackedBuf == NULL || messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)){ - return -1; - } - uint8_t *end = *pMessageBuf + messageBufLen; - // process the header - int result = - (pull8(pReadPackedMessage, &fapi_msg.num_msg, end) && pull8(pReadPackedMessage, &fapi_msg.opaque_handle, end) - && pull16(pReadPackedMessage, &header->message_id, end) && pull32(pReadPackedMessage, &fapi_msg.message_length, end)); - DevAssert(fapi_msg.message_length <= 0xFFFF); - header->message_length = fapi_msg.message_length; - return (result); -} - -uint8_t fapi_nr_p5_message_body_pack(nfapi_p4_p5_message_header_t *header, +uint8_t fapi_nr_p5_message_body_pack(nfapi_nr_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) @@ -74,7 +32,7 @@ uint8_t fapi_nr_p5_message_body_pack(nfapi_p4_p5_message_header_t *header, // look for the specific message switch (header->message_id) { case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: - result = 0; + result = 1; break; case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: @@ -110,7 +68,7 @@ uint8_t fapi_nr_p5_message_body_pack(nfapi_p4_p5_message_header_t *header, break; default: { - AssertFatal(header->message_id >= 0x00 && header->message_id <= 0xFF, + AssertFatal(header->message_id <= 0xFF, "FAPI message IDs are defined between 0x00 and 0xFF the message provided 0x%02x, which is not a FAPI message", header->message_id); break; @@ -122,17 +80,14 @@ uint8_t fapi_nr_p5_message_body_pack(nfapi_p4_p5_message_header_t *header, int fapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, - uint32_t packedBufLen, + const uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { - nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + nfapi_nr_p4_p5_message_header_t *pMessageHeader = pMessageBuf; uint8_t *pWritePackedMessage = pPackedBuf; AssertFatal(isFAPIMessageIDValid(pMessageHeader->message_id), "FAPI message IDs are defined between 0x00 and 0xFF the message provided 0x%02x, which is not a FAPI message", pMessageHeader->message_id); - uint32_t packedMsgLen; - uint32_t packedBodyLen; - uint16_t packedMsgLen16; AssertFatal(pMessageBuf != NULL && pPackedBuf != NULL, "P5 Pack supplied pointers are null"); uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; @@ -140,8 +95,8 @@ int fapi_nr_p5_message_pack(void *pMessageBuf, uint8_t *pPacketBodyField = &pWritePackedMessage[8]; uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8]; - uint8_t res = fapi_nr_p5_message_body_pack(pMessageHeader, &pPacketBodyField, pPackMessageEnd, config); - AssertFatal(res >= 0, "fapi_nr_p5_message_body_pack error packing message body %d\n", res); + const uint8_t res = fapi_nr_p5_message_body_pack(pMessageHeader, &pPacketBodyField, pPackMessageEnd, config); + AssertFatal(res > 0, "fapi_nr_p5_message_body_pack error packing message body %d\n", res); // PHY API message header push8(1, &pWritePackedMessage, pPackMessageEnd); // Number of messages @@ -151,9 +106,8 @@ int fapi_nr_p5_message_pack(void *pMessageBuf, push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd); // Message type ID // check for a valid message length - packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pPacketBodyField); - packedBodyLen = get_packed_msg_len((uintptr_t)pPacketBodyFieldStart, (uintptr_t)pPacketBodyField); - packedMsgLen16 = (uint16_t)packedBodyLen; + const uint32_t packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pPacketBodyField); + uint16_t packedMsgLen16 = get_packed_msg_len((uintptr_t)pPacketBodyFieldStart, (uintptr_t)pPacketBodyField); if (pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST || pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_START_REQUEST || pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST @@ -171,13 +125,13 @@ int fapi_nr_p5_message_pack(void *pMessageBuf, return -1; // return the packed length - return (int)(packedMsgLen); + return packedMsgLen; } int fapi_nr_p5_message_unpack(void *pMessageBuf, - uint32_t messageBufLen, + const uint32_t messageBufLen, void *pUnpackedBuf, - uint32_t unpackedBufLen, + const uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { fapi_message_header_t *pMessageHeader = pUnpackedBuf; @@ -191,7 +145,7 @@ int fapi_nr_p5_message_unpack(void *pMessageBuf, unpackedBufLen); // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); - if (fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0) + if (fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0) < 0) { // failed to read the header return -1; @@ -259,73 +213,6 @@ int fapi_nr_p5_message_unpack(void *pMessageBuf, return result; } -int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - /** NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST= 0x00, - NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE= 0x01, - NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST= 0x02, - NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE=0X03, - NFAPI_NR_PHY_MSG_TYPE_START_REQUEST= 0X04, - NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST= 0X05, - NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION=0X06, - NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION=0X07 - */ - // check for size of nFAPI struct without the nFAPI specific parameters - switch (msgId) { - case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) - retLen = sizeof(fapi_message_header_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t) - sizeof(nfapi_nr_nfapi_t)) - retLen = sizeof(nfapi_nr_param_request_scf_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t) - sizeof(nfapi_nr_nfapi_t)) - retLen = sizeof(nfapi_nr_config_request_scf_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) - retLen = sizeof(nfapi_nr_config_response_scf_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_start_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) - retLen = sizeof(fapi_message_header_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) - retLen = sizeof(fapi_message_header_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_stop_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) - retLen = sizeof(fapi_message_header_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_stop_indication_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) - retLen = sizeof(fapi_message_header_t); - - break; - case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_error_indication_scf_t) - sizeof(nfapi_vendor_extension_tlv_t)) - retLen = sizeof(fapi_message_header_t); - - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); - break; - } - - return retLen; -} - uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg; @@ -370,12 +257,7 @@ uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e &pack_uint16_tlv_value); for (int i = 0; i < pNfapiMsg->cell_param.num_config_tlvs_to_report.value; ++i) { - /*retval &= pack_nr_tlv(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag, - &(pNfapiMsg->cell_param.config_tlvs_to_report_list[i]), - ppWritePackedMsg, - end, - &pack_uint8_tlv_value);*/ - retval &= push16(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag, ppWritePackedMsg, end); + retval &= push16(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag, ppWritePackedMsg, end) != 0; retval &= push8(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.length, ppWritePackedMsg, end); retval &= push8(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].value, ppWritePackedMsg, end); // Add padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1) @@ -1141,9 +1023,8 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 uint8_t cyclicprefix = 1; - bool normal_CP = cyclicprefix ? false : true; // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 - uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12; + uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; for (int i = 0; i < slotsperframe[pNfapiMsg->ssb_config.scs_common.value]; i++) { // TODO check right number of slots for (int k = 0; k < number_of_symbols_per_slot; k++) { // TODO can change? retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, @@ -1362,9 +1243,8 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 uint8_t cyclicprefix = 1; - bool normal_CP = cyclicprefix ? false : true; // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 - uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12; + uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *)malloc( slotsperframe[pNfapiMsg->ssb_config.scs_common.value] * sizeof(nfapi_nr_max_tdd_periodicity_t)); @@ -1709,8 +1589,8 @@ uint8_t unpack_nr_stop_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void uint8_t pack_nr_error_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { nfapi_nr_error_indication_scf_t *pNfapiMsg = (nfapi_nr_error_indication_scf_t *)msg; - uint8_t retval = push16(pNfapiMsg->sfn, ppWritePackedMsg, end); - retval &= push16(pNfapiMsg->slot, ppWritePackedMsg, end); + uint8_t retval = push16(pNfapiMsg->sfn, ppWritePackedMsg, end) != 0; + retval &= push16(pNfapiMsg->slot, ppWritePackedMsg, end) != 0; retval &= push8(pNfapiMsg->message_id, ppWritePackedMsg, end); retval &= push8(pNfapiMsg->error_code, ppWritePackedMsg, end); diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index abcbc3e9717a6578810fb8175f2085961076b137..6450fadb44dc903fb8c4ee0ff6068236ad4a3b46 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -18,39 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nr_fapi_p5_utils.h" -void copy_vendor_extension_value(nfapi_vendor_extension_tlv_t *dst, const nfapi_vendor_extension_tlv_t *src) -{ - nfapi_tl_t *dst_tlv = (nfapi_tl_t *)dst; - nfapi_tl_t *src_tlv = (nfapi_tl_t *)src; - - switch (dst_tlv->tag) { - case VENDOR_EXT_TLV_2_TAG: { - vendor_ext_tlv_2 *dst_ve = (vendor_ext_tlv_2 *)dst_tlv; - vendor_ext_tlv_2 *src_ve = (vendor_ext_tlv_2 *)src_tlv; - - dst_ve->dummy = src_ve->dummy; - } break; - case VENDOR_EXT_TLV_1_TAG: { - vendor_ext_tlv_1 *dst_ve = (vendor_ext_tlv_1 *)dst_tlv; - vendor_ext_tlv_1 *src_ve = (vendor_ext_tlv_1 *)src_tlv; - - dst_ve->dummy = src_ve->dummy; - } break; - } -} - bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); @@ -276,9 +245,8 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 uint8_t cyclicprefix = 1; - bool normal_CP = cyclicprefix ? false : true; // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 - uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12; + uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; for (int i = 0; i < slotsperframe[unpacked_req->ssb_config.scs_common.value]; i++) { for (int k = 0; k < number_of_symbols_per_slot; k++) { @@ -805,9 +773,8 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 uint8_t cyclicprefix = 1; - bool normal_CP = cyclicprefix ? false : true; // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 - uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12; + uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; dst->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *)malloc(slotsperframe[dst->ssb_config.scs_common.value] * sizeof(nfapi_nr_max_tdd_periodicity_t)); diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c new file mode 100644 index 0000000000000000000000000000000000000000..8e58e5117876d25de2c88088d3f1d136a9dc2f20 --- /dev/null +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -0,0 +1,2413 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "nr_fapi.h" +#include "nr_fapi_p7.h" +#include "nr_nfapi_p7.h" +#include "debug.h" + +uint8_t fapi_nr_p7_message_body_pack(nfapi_nr_p7_message_header_t *header, + uint8_t **ppWritePackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + // look for the specific message + uint8_t result = 0; + switch (header->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + result = pack_dl_tti_request(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + result = pack_ul_tti_request(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + result = pack_nr_slot_indication(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + result = pack_ul_dci_request(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + result = pack_tx_data_request(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + result = pack_nr_rx_data_indication(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + result = pack_nr_crc_indication(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + result = pack_nr_uci_indication(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + result = pack_nr_srs_indication(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + result = pack_nr_rach_indication(header, ppWritePackedMsg, end, config); + break; +#ifdef ENABLE_AERIAL + case NFAPI_NR_PHY_MSG_TYPE_VENDOR_EXT_SLOT_RESPONSE: + result = pack_nr_slot_indication(header, ppWritePackedMsg, end, config); + break; +#endif + default: { + if (header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (config && config->pack_p7_vendor_extension) { + result = (config->pack_p7_vendor_extension)(header, ppWritePackedMsg, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, header->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); + } + } break; + } + + if (result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + } + return result; +} + +int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) +{ + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + + nfapi_nr_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *pPacketBodyField = &pWritePackedMessage[8]; + uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8]; + + const uint8_t result = fapi_nr_p7_message_body_pack(pMessageHeader, &pPacketBodyField, pPackMessageEnd, config); + AssertFatal(result > 0, "fapi_nr_p7_message_body_pack error packing message body %d\n", result); + + // PHY API message header + // Number of messages [0] + // Opaque handle [1] + // PHY API Message structure + // Message type ID [2,3] + // Message Length [4,5,6,7] + // Message Body [8,...] + if (!(push8(1, &pWritePackedMessage, pPackMessageEnd) && push8(0, &pWritePackedMessage, pPackMessageEnd) + && push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPacketBodyFieldStart; + uintptr_t msgEnd = (uintptr_t)pPacketBodyField; + uint32_t packedMsgLen = msgEnd - msgHead; + if (packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen; + + // Update the message length in the header + if (!push32(packedMsgLen, &pPackedLengthField, pPackMessageEnd)) + return -1; + + return packedMsgLen; +} + +int fapi_nr_p7_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config) +{ + int result = 0; + nfapi_nr_p7_message_header_t *pMessageHeader = (nfapi_nr_p7_message_header_t *)pUnpackedBuf; + fapi_message_header_t fapi_hdr; + uint8_t *pReadPackedMessage = pMessageBuf; + + AssertFatal(pMessageBuf != NULL && pUnpackedBuf != NULL, "P7 unpack supplied pointers are null"); + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; + AssertFatal(messageBufLen >= NFAPI_HEADER_LENGTH && unpackedBufLen >= sizeof(fapi_message_header_t), + "P5 unpack supplied message buffer is too small %d, %d\n", + messageBufLen, + unpackedBufLen); + + + if (fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &fapi_hdr, sizeof(fapi_message_header_t), 0) < 0) { + // failed to read the header + return -1; + } + pMessageHeader->message_length = fapi_hdr.message_length; + pMessageHeader->message_id = fapi_hdr.message_id; + if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); + return -1; + } + + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) + result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) + result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)) { + nfapi_nr_slot_indication_scf_t *msg = (nfapi_nr_slot_indication_scf_t *)pMessageHeader; + result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); + } + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) + result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) + result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) { + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + } + break; + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) { + result = unpack_nr_crc_indication(&pReadPackedMessage, end, pMessageHeader, config); + } + break; + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) { + result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); + } + break; + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) { + result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + } + break; + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) { + result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + } + break; + default: + + if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (config && config->unpack_p7_vendor_extension) { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s VE NFAPI message ID %d. No ve decoder provided\n", + __FUNCTION__, + pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + if (result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Unpack failed to unpack message\n"); + return -1; + } + return 0; +} + +static uint8_t pack_nr_tx_beamforming_pdu(const nfapi_nr_tx_precoding_and_beamforming_t *beamforming_pdu, + uint8_t **ppWritePackedMsg, + uint8_t *end) +{ // Pack RX Beamforming PDU + if (!(push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end) && push16(beamforming_pdu->prg_size, ppWritePackedMsg, end) + && push8(beamforming_pdu->dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < beamforming_pdu->num_prgs; prg++) { + if (!push16(beamforming_pdu->prgs_list[prg].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interfaces; digBFInterface++) { + if (!push16(beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } + return 1; +} + +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; + if (!(push16(value->bwp_size, ppWritePackedMsg, end) && push16(value->bwp_start, ppWritePackedMsg, end) + && push8(value->subcarrier_spacing, ppWritePackedMsg, end) && push8(value->cyclic_prefix, ppWritePackedMsg, end) + && push16(value->start_rb, ppWritePackedMsg, end) && push16(value->nr_of_rbs, ppWritePackedMsg, end) + && push8(value->csi_type, ppWritePackedMsg, end) && push8(value->row, ppWritePackedMsg, end) + && push16(value->freq_domain, ppWritePackedMsg, end) && push8(value->symb_l0, ppWritePackedMsg, end) + && push8(value->symb_l1, ppWritePackedMsg, end) && push8(value->cdm_type, ppWritePackedMsg, end) + && push8(value->freq_density, ppWritePackedMsg, end) && push16(value->scramb_id, ppWritePackedMsg, end) + && push8(value->power_control_offset, ppWritePackedMsg, end) + && push8(value->power_control_offset_ss, ppWritePackedMsg, end))) { + return 0; + } + + // Precoding and beamforming + if(!pack_nr_tx_beamforming_pdu(&value->precodingAndBeamforming,ppWritePackedMsg, end)) { + return 0; + } + return 1; +} + +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; + + if (!(push16(value->BWPSize, ppWritePackedMsg, end) && push16(value->BWPStart, ppWritePackedMsg, end) + && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && push8(value->CyclicPrefix, ppWritePackedMsg, end) + && push8(value->StartSymbolIndex, ppWritePackedMsg, end) && push8(value->DurationSymbols, ppWritePackedMsg, end) + && pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) + && push8(value->CceRegMappingType, ppWritePackedMsg, end) && push8(value->RegBundleSize, ppWritePackedMsg, end) + && push8(value->InterleaverSize, ppWritePackedMsg, end) && push8(value->CoreSetType, ppWritePackedMsg, end) + && push16(value->ShiftIndex, ppWritePackedMsg, end) && push8(value->precoderGranularity, ppWritePackedMsg, end) + && push16(value->numDlDci, ppWritePackedMsg, end))) { + return 0; + } + + for (uint16_t i = 0; i < value->numDlDci; ++i) { + if (!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) + && push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end))) { + return 0; + } + // Precoding and beamforming + if(!pack_nr_tx_beamforming_pdu(&value->dci_pdu[i].precodingAndBeamforming,ppWritePackedMsg, end)) { + return 0; + } + // TX Power info + if (!(push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) + && push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + // DCI Payload fields + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + // Pack DCI Payload + pack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) { + return 0; + } + } + return 1; +} + +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; + + if (!(push16(value->pduBitmap, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) + && push16(value->pduIndex, ppWritePackedMsg, end) && push16(value->BWPSize, ppWritePackedMsg, end) + && push16(value->BWPStart, ppWritePackedMsg, end) && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) + && push8(value->CyclicPrefix, ppWritePackedMsg, end) && push8(value->NrOfCodewords, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->NrOfCodewords; ++i) { + if (!(push16(value->targetCodeRate[i], ppWritePackedMsg, end) && push8(value->qamModOrder[i], ppWritePackedMsg, end) + && push8(value->mcsIndex[i], ppWritePackedMsg, end) && push8(value->mcsTable[i], ppWritePackedMsg, end) + && push8(value->rvIndex[i], ppWritePackedMsg, end) && push32(value->TBSize[i], ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push16(value->dataScramblingId, ppWritePackedMsg, end) && push8(value->nrOfLayers, ppWritePackedMsg, end) + && push8(value->transmissionScheme, ppWritePackedMsg, end) && push8(value->refPoint, ppWritePackedMsg, end) + && push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && push8(value->dmrsConfigType, ppWritePackedMsg, end) + && push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && push8(value->SCID, ppWritePackedMsg, end) + && push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && push16(value->dmrsPorts, ppWritePackedMsg, end) + && push8(value->resourceAlloc, ppWritePackedMsg, end) && (int)pusharray8(value->rbBitmap, 36, 36, ppWritePackedMsg, end) + && push16(value->rbStart, ppWritePackedMsg, end) && push16(value->rbSize, ppWritePackedMsg, end) + && push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && push8(value->StartSymbolIndex, ppWritePackedMsg, end) + && push8(value->NrOfSymbols, ppWritePackedMsg, end))) { + return 0; + } + + // Check pduBitMap bit 0 to add or not PTRS parameters + if (value->pduBitmap & 0b1) { + if (!(push8(value->PTRSPortIndex, ppWritePackedMsg, end) && push8(value->PTRSTimeDensity, ppWritePackedMsg, end) + && push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && push8(value->PTRSReOffset, ppWritePackedMsg, end) + && push8(value->nEpreRatioOfPDSCHToPTRS, ppWritePackedMsg, end))) { + return 0; + } + } + + // Precoding and beamforming + if(!pack_nr_tx_beamforming_pdu(&value->precodingAndBeamforming,ppWritePackedMsg, end)) { + return 0; + } + + if (!(push8(value->powerControlOffset, ppWritePackedMsg, end) && push8(value->powerControlOffsetSS, ppWritePackedMsg, end))) { + return 0; + } + + // Check pduBitMap bit 1 to add or not CBG parameters + if (value->pduBitmap & 0b10) { + if (!(push8(value->isLastCbPresent, ppWritePackedMsg, end) && push8(value->isInlineTbCrc, ppWritePackedMsg, end) + && push32(value->dlTbCrc, ppWritePackedMsg, end))) { + return 0; + } + } +#ifndef ENABLE_AERIAL + if (!push8(value->maintenance_parms_v3.ldpcBaseGraph, ppWritePackedMsg, end) + || !push32(value->maintenance_parms_v3.tbSizeLbrmBytes, ppWritePackedMsg, end)) + return 0; +#endif + return 1; +} + +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing ssb. \n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; + + if (!(push16(value->PhysCellId, ppWritePackedMsg, end) && push8(value->BetaPss, ppWritePackedMsg, end) + && push8(value->SsbBlockIndex, ppWritePackedMsg, end) && push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) + && push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && push8(value->bchPayloadFlag, ppWritePackedMsg, end) + && push8((value->bchPayload >> 16) & 0xff, ppWritePackedMsg, end) + && push8((value->bchPayload >> 8) & 0xff, ppWritePackedMsg, end) && push8(value->bchPayload & 0xff, ppWritePackedMsg, end) + && push8(0, ppWritePackedMsg, end))) { + return 0; + } + // Precoding and beamforming + if(!pack_nr_tx_beamforming_pdu(&value->precoding_and_beamforming,ppWritePackedMsg, end)) { + return 0; + } + return 1; +} + +static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)tlv; + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->PDUType, ppWritePackedMsg, end)) + return 0; + uint8_t *pPackedLengthField = *ppWritePackedMsg; + if (!push16(value->PDUSize, ppWritePackedMsg, end)) + return 0; + + // first match the pdu type, then call the respective function + switch (value->PDUType) { + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { + if (!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15, ppWritePackedMsg, end))) + return 0; + } break; + + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + if (!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15, ppWritePackedMsg, end))) + return 0; + } break; + + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { + if (!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15, ppWritePackedMsg, end))) + return 0; + } break; + + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { + if (!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15, ppWritePackedMsg, end))) + return 0; + } break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType); + } break; + } + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->PDUSize = packedMsgLen; + return push16(value->PDUSize, &pPackedLengthField, end); +} + +uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) + && push8(pNfapiMsg->dl_tti_request_body.nPDUs, ppWritePackedMsg, end) + && push8(pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { + if (!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i], ppWritePackedMsg, end)) { + return 0; + } + } + + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { + if (!push8(pNfapiMsg->dl_tti_request_body.nUe[i], ppWritePackedMsg, end)) + return 0; + for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { + if (!(push32(pNfapiMsg->dl_tti_request_body.PduIdx[i][j], ppWritePackedMsg, end))) { + return 0; + } + } + } + return 1; +} + +static uint8_t unpack_nr_tx_beamforming_pdu(nfapi_nr_tx_precoding_and_beamforming_t *beamforming_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) +{ // Unpack RX Beamforming PDU + if (!(pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end) && pull16(ppReadPackedMsg, &beamforming_pdu->prg_size, end) + && pull8(ppReadPackedMsg, &beamforming_pdu->dig_bf_interfaces, end))) { + return 0; + } + for (int prg = 0; prg < beamforming_pdu->num_prgs; prg++) { + if (!(pull16(ppReadPackedMsg, &beamforming_pdu->prgs_list[prg].pm_idx, end))) { + return 0; + } + for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interfaces; digBFInterface++) { + if (!pull16(ppReadPackedMsg, &beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, end)) { + return 0; + } + } + } + return 1; +} + +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; + + if (!(pull16(ppReadPackedMsg, &value->BWPSize, end) && pull16(ppReadPackedMsg, &value->BWPStart, end) + && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) + && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && pull8(ppReadPackedMsg, &value->DurationSymbols, end) + && pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) + && pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && pull8(ppReadPackedMsg, &value->RegBundleSize, end) + && pull8(ppReadPackedMsg, &value->InterleaverSize, end) && pull8(ppReadPackedMsg, &value->CoreSetType, end) + && pull16(ppReadPackedMsg, &value->ShiftIndex, end) && pull8(ppReadPackedMsg, &value->precoderGranularity, end) + && pull16(ppReadPackedMsg, &value->numDlDci, end))) { + return 0; + } + + for (uint16_t i = 0; i < value->numDlDci; ++i) { + if (!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end))) { + return 0; + } + + // Preocding and Beamforming + if(!unpack_nr_tx_beamforming_pdu(&value->dci_pdu[i].precodingAndBeamforming, ppReadPackedMsg, end)) { + return 0; + } + + if (!(pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) + && pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) + && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) + && unpack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppReadPackedMsg, end))) { + return 0; + } + } + return 1; +} + +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; + + if (!(pull16(ppReadPackedMsg, &value->pduBitmap, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull16(ppReadPackedMsg, &value->pduIndex, end) && pull16(ppReadPackedMsg, &value->BWPSize, end) + && pull16(ppReadPackedMsg, &value->BWPStart, end) && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) + && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && pull8(ppReadPackedMsg, &value->NrOfCodewords, end))) { + return 0; + } + for (int i = 0; i < value->NrOfCodewords; ++i) { + if (!(pull16(ppReadPackedMsg, &value->targetCodeRate[i], end) && pull8(ppReadPackedMsg, &value->qamModOrder[i], end) + && pull8(ppReadPackedMsg, &value->mcsIndex[i], end) && pull8(ppReadPackedMsg, &value->mcsTable[i], end) + && pull8(ppReadPackedMsg, &value->rvIndex[i], end) && pull32(ppReadPackedMsg, &value->TBSize[i], end))) { + return 0; + } + } + + if (!(pull16(ppReadPackedMsg, &value->dataScramblingId, end) && pull8(ppReadPackedMsg, &value->nrOfLayers, end) + && pull8(ppReadPackedMsg, &value->transmissionScheme, end) && pull8(ppReadPackedMsg, &value->refPoint, end) + && pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && pull8(ppReadPackedMsg, &value->dmrsConfigType, end) + && pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && pull8(ppReadPackedMsg, &value->SCID, end) + && pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && pull16(ppReadPackedMsg, &value->dmrsPorts, end) + && pull8(ppReadPackedMsg, &value->resourceAlloc, end) && pullarray8(ppReadPackedMsg, &value->rbBitmap[0], 36, 36, end) + && pull16(ppReadPackedMsg, &value->rbStart, end) && pull16(ppReadPackedMsg, &value->rbSize, end) + && pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) + && pull8(ppReadPackedMsg, &value->NrOfSymbols, end))) { + return 0; + } + // Check pduBitMap bit 0 to pull PTRS parameters or not + if (value->pduBitmap & 0b1) { + if (!(pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) + && pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + && pull8(ppReadPackedMsg, &value->nEpreRatioOfPDSCHToPTRS, end))) { + return 0; + } + } + + // Preocding and Beamforming + if(!unpack_nr_tx_beamforming_pdu(&value->precodingAndBeamforming, ppReadPackedMsg, end)) { + return 0; + } + + // Tx power info + if (!(pull8(ppReadPackedMsg, &value->powerControlOffset, end) && pull8(ppReadPackedMsg, &value->powerControlOffsetSS, end))) { + return 0; + } + + // Check pduBitMap bit 1 to pull CBG parameters or not + if (value->pduBitmap & 0b10) { + if (!(pull8(ppReadPackedMsg, &value->isLastCbPresent, end) && pull8(ppReadPackedMsg, &value->isInlineTbCrc, end) + && pull32(ppReadPackedMsg, &value->dlTbCrc, end))) { + return 0; + } + } +#ifndef ENABLE_AERIAL + if (!pull8(ppReadPackedMsg, &value->maintenance_parms_v3.ldpcBaseGraph, end) + || !pull32(ppReadPackedMsg, &value->maintenance_parms_v3.tbSizeLbrmBytes, end)) + return 0; +#endif + return 1; +} + +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; + if (!(pull16(ppReadPackedMsg, &value->bwp_size, end) && pull16(ppReadPackedMsg, &value->bwp_start, end) + && pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &value->cyclic_prefix, end) + && pull16(ppReadPackedMsg, &value->start_rb, end) && pull16(ppReadPackedMsg, &value->nr_of_rbs, end) + && pull8(ppReadPackedMsg, &value->csi_type, end) && pull8(ppReadPackedMsg, &value->row, end) + && pull16(ppReadPackedMsg, &value->freq_domain, end) && pull8(ppReadPackedMsg, &value->symb_l0, end) + && pull8(ppReadPackedMsg, &value->symb_l1, end) && pull8(ppReadPackedMsg, &value->cdm_type, end) + && pull8(ppReadPackedMsg, &value->freq_density, end) && pull16(ppReadPackedMsg, &value->scramb_id, end) + && pull8(ppReadPackedMsg, &value->power_control_offset, end) + && pull8(ppReadPackedMsg, &value->power_control_offset_ss, end))) { + return 0; + } + + // Preocding and Beamforming + if(!unpack_nr_tx_beamforming_pdu(&value->precodingAndBeamforming, ppReadPackedMsg, end)) { + return 0; + } + + return 1; +} + +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Unpacking ssb. \n"); + uint8_t byte3, byte2, byte1, byte0; + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; + + if (!(pull16(ppReadPackedMsg, &value->PhysCellId, end) && pull8(ppReadPackedMsg, &value->BetaPss, end) + && pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) + && pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) + && pull8(ppReadPackedMsg, &byte3, end) && pull8(ppReadPackedMsg, &byte2, end) && pull8(ppReadPackedMsg, &byte1, end) + && pull8(ppReadPackedMsg, &byte0, end))) { // this should be always 0, bchpayload is 24 bits + return 0; + } + // rebuild the bchPayload + value->bchPayload = byte3 << 16 | byte2 << 8 | byte1; + + // Preocding and Beamforming + if(!unpack_nr_tx_beamforming_pdu(&value->precoding_and_beamforming, ppReadPackedMsg, end)) { + return 0; + } + return 1; +} + +static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)msg; + + if (!(pull16(ppReadPackedMsg, &value->PDUType, end) && pull16(ppReadPackedMsg, (uint16_t *)&value->PDUSize, end))) + return 0; + + // first match the pdu type, then call the respective function + switch (value->PDUType) { + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { + if (!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15, ppReadPackedMsg, end))) + return 0; + } break; + + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + if (!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15, ppReadPackedMsg, end))) + return 0; + } break; + + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { + if (!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15, ppReadPackedMsg, end))) + return 0; + } break; + + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { + if (!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15, ppReadPackedMsg, end))) + return 0; + } break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType); + } break; + } + + return 1; +} + +uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; + pNfapiMsg->vendor_extension = NULL; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end))) { + return 0; + } + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { + if (!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } + + for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { + if (!pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nUe[i], end)) { + return 0; + } + for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { + if (!pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.PduIdx[i][j], end)) { + return 0; + } + } + } + + return 1; +} + +// Pack fns for ul_tti PDUS + +static uint8_t pack_nr_rx_beamforming_pdu(const nfapi_nr_ul_beamforming_t *beamforming_pdu, + uint8_t **ppWritePackedMsg, + uint8_t *end) +{ // Pack RX Beamforming PDU + if (!(push8(beamforming_pdu->trp_scheme, ppWritePackedMsg, end) && push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end) + && push16(beamforming_pdu->prg_size, ppWritePackedMsg, end) + && push8(beamforming_pdu->dig_bf_interface, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < beamforming_pdu->num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interface; digBFInterface++) { + if (!push16(beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } + return 1; +} + +static uint8_t pack_ul_tti_request_prach_pdu(const nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) + && push8(prach_pdu->prach_format, ppWritePackedMsg, end) && push8(prach_pdu->num_ra, ppWritePackedMsg, end) + && push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && push16(prach_pdu->num_cs, ppWritePackedMsg, end))) { + return 0; + } + + return pack_nr_rx_beamforming_pdu(&prach_pdu->beamforming, ppWritePackedMsg, end); +} + +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && push16(pusch_pdu->rnti, ppWritePackedMsg, end) + && push32(pusch_pdu->handle, ppWritePackedMsg, end) && push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) + && push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) + && push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) + && push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) + && push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) + && push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) + && push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) + && push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_identity, ppWritePackedMsg, end) && push8(pusch_pdu->scid, ppWritePackedMsg, end) + && push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) + && push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) + && pusharray8(pusch_pdu->rb_bitmap, 36, 36, ppWritePackedMsg, end) && push16(pusch_pdu->rb_start, ppWritePackedMsg, end) + && push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) + && push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) + && push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) + && push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) + && push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end))) { + return 0; + } + + // Pack Optional Data only included if indicated in pduBitmap + // Check if PUSCH_PDU_BITMAP_PUSCH_DATA bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_DATA) { + // pack optional TLVs + if (!(push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_data.new_data_indicator, ppWritePackedMsg, end) + && push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end))) { + return 0; + } + const uint16_t cb_len = (pusch_pdu->pusch_data.num_cb + 7) / 8; + if (!pusharray8(pusch_pdu->pusch_data.cb_present_and_position, cb_len, cb_len, ppWritePackedMsg, end)) { + return 0; + } + } + + // Check if PUSCH_PDU_BITMAP_PUSCH_UCI bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_UCI) { + if (!(push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) + && push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end))) { + return 0; + } + } + + // Check if PUSCH_PDU_BITMAP_PUSCH_PTRS bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + if (!push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end)) { + return 0; + } + for (int i = 0; i < pusch_pdu->pusch_ptrs.num_ptrs_ports; ++i) { + if (!(push16(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_port_index, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_dmrs_port, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_re_offset, ppWritePackedMsg, end))) { + return 0; + } + } + + if (!(push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) + && push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end))) { + return 0; + } + } + + // Check if PUSCH_PDU_BITMAP_DFTS_OFDM bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_DFTS_OFDM) { + if (!(push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) + && push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) + && push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) + && push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end))) { + return 0; + } + } + + // Pack RX Beamforming PDU + if (!(pack_nr_rx_beamforming_pdu(&pusch_pdu->beamforming, ppWritePackedMsg, end))) { + return 0; + } +#ifndef ENABLE_AERIAL + if (!(push8(pusch_pdu->maintenance_parms_v3.ldpcBaseGraph, ppWritePackedMsg, end) + && push32(pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes, ppWritePackedMsg, end))) + return 0; +#endif + return 1; +} + +static uint8_t pack_ul_tti_request_pucch_pdu(const nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(pucch_pdu->rnti, ppWritePackedMsg, end) && push32(pucch_pdu->handle, ppWritePackedMsg, end) + && push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) + && push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) + && push8(pucch_pdu->format_type, ppWritePackedMsg, end) && push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) + && push8(pucch_pdu->pi_2bpsk, ppWritePackedMsg, end) && push16(pucch_pdu->prb_start, ppWritePackedMsg, end) + && push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) + && push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) + && push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) + && push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) + && push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) + && push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) + && push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) + && push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) + && push16(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) + && push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end))) { + return 0; + } + + return pack_nr_rx_beamforming_pdu(&pucch_pdu->beamforming, ppWritePackedMsg, end); +} + +static uint8_t pack_ul_tti_request_srs_parameters_v4(nfapi_v4_srs_parameters_t *srsParameters, + const uint8_t num_symbols, + uint8_t **ppWritePackedMsg, + uint8_t *end) +{ + if (!(push16(srsParameters->srs_bandwidth_size, ppWritePackedMsg, end))) { + return 0; + } + for (int symbol_idx = 0; symbol_idx < num_symbols; ++symbol_idx) { + const nfapi_v4_srs_parameters_symbols_t *symbol = &srsParameters->symbol_list[symbol_idx]; + if (!(push16(symbol->srs_bandwidth_start, ppWritePackedMsg, end) && push8(symbol->sequence_group, ppWritePackedMsg, end) + && push8(symbol->sequence_number, ppWritePackedMsg, end))) { + return 0; + } + } +#ifdef ENABLE_AERIAL + // For Aerial, we always pack/unpack the 4 reported symbols, not only the ones indicated by num_symbols + for (int symbol_idx = num_symbols; symbol_idx < 4; ++symbol_idx) { + if (!(push16(0, ppWritePackedMsg, end) && push8(0, ppWritePackedMsg, end) && push8(0, ppWritePackedMsg, end))) { + return 0; + } + } +#endif // ENABLE_AERIAL + const uint8_t nUsage = __builtin_popcount(srsParameters->usage); + if (!(push32(srsParameters->usage, ppWritePackedMsg, end) + && pusharray8(srsParameters->report_type, 4, nUsage, ppWritePackedMsg, end) + && push8(srsParameters->singular_Value_representation, ppWritePackedMsg, end) + && push8(srsParameters->iq_representation, ppWritePackedMsg, end) && push16(srsParameters->prg_size, ppWritePackedMsg, end) + && push8(srsParameters->num_total_ue_antennas, ppWritePackedMsg, end) + && push32(srsParameters->ue_antennas_in_this_srs_resource_set, ppWritePackedMsg, end) + && push32(srsParameters->sampled_ue_antennas, ppWritePackedMsg, end) + && push8(srsParameters->report_scope, ppWritePackedMsg, end) + && push8(srsParameters->num_ul_spatial_streams_ports, ppWritePackedMsg, end) + && pusharray8(srsParameters->Ul_spatial_stream_ports, + 256, + srsParameters->num_ul_spatial_streams_ports, + ppWritePackedMsg, + end))) { + return 0; + } + return 1; +} + +static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t *srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push16(srs_pdu->rnti, ppWritePackedMsg, end) && push32(srs_pdu->handle, ppWritePackedMsg, end) + && push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && push16(srs_pdu->bwp_start, ppWritePackedMsg, end) + && push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) + && push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && push8(srs_pdu->num_symbols, ppWritePackedMsg, end) + && push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && push8(srs_pdu->time_start_position, ppWritePackedMsg, end) + && push8(srs_pdu->config_index, ppWritePackedMsg, end) && push16(srs_pdu->sequence_id, ppWritePackedMsg, end) + && push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && push8(srs_pdu->comb_size, ppWritePackedMsg, end) + && push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) + && push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && push16(srs_pdu->frequency_shift, ppWritePackedMsg, end) + && push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) + && push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && push8(srs_pdu->resource_type, ppWritePackedMsg, end) + && push16(srs_pdu->t_srs, ppWritePackedMsg, end) && push16(srs_pdu->t_offset, ppWritePackedMsg, end))) { + return 0; + } + + if(!(pack_nr_rx_beamforming_pdu(&srs_pdu->beamforming, ppWritePackedMsg, end))){ + return 0; + } + + if(!(pack_ul_tti_request_srs_parameters_v4(&srs_pdu->srs_parameters_v4, 1 << srs_pdu->num_symbols, ppWritePackedMsg, end))){ + return 0; + } + + return 1; +} + +static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t *value = (nfapi_nr_ul_tti_request_number_of_pdus_t *)tlv; + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->pdu_type, ppWritePackedMsg, end)) { + return 0; + } + uint8_t *pPackedLengthField = *ppWritePackedMsg; + + if (!push16(value->pdu_size, ppWritePackedMsg, end)) + return 0; + // pack PDUs + // first match the pdu type, then call the respective function + switch (value->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + if (!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + return 0; + } break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + if (!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + return 0; + } break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + if (!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + return 0; + } break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { + if (!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + return 0; + } break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type); + } break; + } + + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->pdu_size = packedMsgLen; + return push16(value->pdu_size, &pPackedLengthField, end); +} + +static uint8_t pack_ul_tti_groups_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_groups_t *value = (nfapi_nr_ul_tti_request_number_of_groups_t *)tlv; + + if (!push8(value->n_ue, ppWritePackedMsg, end)) + return 0; + + for (int i = 0; i < value->n_ue; i++) { + if (!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; + pNfapiMsg->n_ulcch = 0; + pNfapiMsg->n_ulsch = 0; + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { + switch (pNfapiMsg->pdus_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + pNfapiMsg->n_ulcch++; + } break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + pNfapiMsg->n_ulsch++; + } break; + default: + break; + } + } + if (!push16(pNfapiMsg->SFN, ppWritePackedMsg, end)) + return 0; + if (!push16(pNfapiMsg->Slot, ppWritePackedMsg, end)) + return 0; + if (!push8(pNfapiMsg->n_pdus, ppWritePackedMsg, end)) + return 0; + if (!push8(pNfapiMsg->rach_present, ppWritePackedMsg, end)) + return 0; + if (!push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end)) + return 0; + if (!push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end)) + return 0; + if (!push8(pNfapiMsg->n_group, ppWritePackedMsg, end)) + return 0; + + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { + if (!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + return 0; + } + + for (int i = 0; i < pNfapiMsg->n_group; i++) { + if (!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_rx_beamforming_pdu(nfapi_nr_ul_beamforming_t *beamforming_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) +{ // Unpack RX Beamforming PDU + if (!(pull8(ppReadPackedMsg, &beamforming_pdu->trp_scheme, end) && pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end) + && pull16(ppReadPackedMsg, &beamforming_pdu->prg_size, end) + && pull8(ppReadPackedMsg, &beamforming_pdu->dig_bf_interface, end))) { + return 0; + } + for (int prg = 0; prg < beamforming_pdu->num_prgs; prg++) { + for (int digBFInterface = 0; digBFInterface < beamforming_pdu->dig_bf_interface; digBFInterface++) { + if (!pull16(ppReadPackedMsg, &beamforming_pdu->prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, end)) { + return 0; + } + } + } + return 1; +} + +static uint8_t unpack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + if (!(pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) + && pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) + && pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && pull16(ppReadPackedMsg, &prach_pdu->num_cs, end))) { + return 0; + } + + return unpack_nr_rx_beamforming_pdu(&prach_pdu->beamforming, ppReadPackedMsg, end); +} + +static uint8_t unpack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + if (!(pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) + && pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) + && pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) + && pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) + && pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) + && pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) + && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) + && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_identity, end) && pull8(ppReadPackedMsg, &pusch_pdu->scid, end) + && pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) + && pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) + && pullarray8(ppReadPackedMsg, pusch_pdu->rb_bitmap, 36, 36, end) && pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) + && pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) + && pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) + && pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) + && pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) + && pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end))) + return 0; + + // Unpack Optional Data only included if indicated in pduBitmap + // Check if PUSCH_PDU_BITMAP_PUSCH_DATA bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_DATA) { + // pack optional TLVs + if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.new_data_indicator, end) + && pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end))) { + return 0; + } + const uint8_t cb_len = (pusch_pdu->pusch_data.num_cb + 7) / 8; + if (!pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position, cb_len, cb_len, end)) { + return 0; + } + } + // Check if PUSCH_PDU_BITMAP_PUSCH_UCI bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_UCI) { + if (!(pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) + && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end))) { + return 0; + } + } + + // Check if PUSCH_PDU_BITMAP_PUSCH_PTRS bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end))) { + return 0; + } + pusch_pdu->pusch_ptrs.ptrs_ports_list = calloc(pusch_pdu->pusch_ptrs.num_ptrs_ports, sizeof(nfapi_nr_ptrs_ports_t)); + for (int ptrs_port = 0; ptrs_port < pusch_pdu->pusch_ptrs.num_ptrs_ports; ++ptrs_port) { + if (!(pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list[ptrs_port].ptrs_port_index, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list[ptrs_port].ptrs_dmrs_port, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list[ptrs_port].ptrs_re_offset, end))) { + return 0; + } + } + if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end))) { + return 0; + } + } + + // Check if PUSCH_PDU_BITMAP_DFTS_OFDM bit is set + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_DFTS_OFDM) { + if (!(pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) + && pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) + && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) + && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end))) { + return 0; + } + } + + if (!(unpack_nr_rx_beamforming_pdu(&pusch_pdu->beamforming, ppReadPackedMsg, end))) { + return 0; + } +#ifndef ENABLE_AERIAL + if (!(pull8(ppReadPackedMsg, &pusch_pdu->maintenance_parms_v3.ldpcBaseGraph, end) + && pull32(ppReadPackedMsg, &pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes, end))) + return 0; +#endif + return 1; +} + +static uint8_t unpack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + if (!(pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && pull32(ppReadPackedMsg, &pucch_pdu->handle, end) + && pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) + && pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) + && pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) + && pull8(ppReadPackedMsg, &pucch_pdu->pi_2bpsk, end) && pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) + && pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) + && pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) + && pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) + && pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) + && pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) + && pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) + && pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) + && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) + && pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) + && pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) + && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) + && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end))) { + return 0; + } + return unpack_nr_rx_beamforming_pdu(&pucch_pdu->beamforming, ppReadPackedMsg, end); +} + +static uint8_t unpack_ul_tti_request_srs_parameters_v4(nfapi_v4_srs_parameters_t *srsParameters, + const uint8_t num_symbols, + uint8_t **ppReadPackedMsg, + uint8_t *end) +{ + if (!(pull16(ppReadPackedMsg, &srsParameters->srs_bandwidth_size, end))) { + return 0; + } + + for (int symbol_idx = 0; symbol_idx < num_symbols; ++symbol_idx) { + nfapi_v4_srs_parameters_symbols_t *symbol = &srsParameters->symbol_list[symbol_idx]; + if (!(pull16(ppReadPackedMsg, &symbol->srs_bandwidth_start, end) && pull8(ppReadPackedMsg, &symbol->sequence_group, end) + && pull8(ppReadPackedMsg, &symbol->sequence_number, end))) { + return 0; + } + } +#ifdef ENABLE_AERIAL + // For Aerial, we always pack/unpack the 4 reported symbols, not only the ones indicated by num_symbols + for (int symbol_idx = num_symbols; symbol_idx < 4; ++symbol_idx) { + nfapi_v4_srs_parameters_symbols_t *symbol = &srsParameters->symbol_list[symbol_idx]; + if (!(pull16(ppReadPackedMsg, &symbol->srs_bandwidth_start, end) && pull8(ppReadPackedMsg, &symbol->sequence_group, end) + && pull8(ppReadPackedMsg, &symbol->sequence_number, end))) { + return 0; + } + } +#endif // ENABLE_AERIAL + + if (!(pull32(ppReadPackedMsg, &srsParameters->usage, end))) { + return 0; + } + const uint8_t nUsage = __builtin_popcount(srsParameters->usage); + if (!(pullarray8(ppReadPackedMsg, &srsParameters->report_type[0], 4, nUsage, end) + && pull8(ppReadPackedMsg, &srsParameters->singular_Value_representation, end) + && pull8(ppReadPackedMsg, &srsParameters->iq_representation, end) && pull16(ppReadPackedMsg, &srsParameters->prg_size, end) + && pull8(ppReadPackedMsg, &srsParameters->num_total_ue_antennas, end) + && pull32(ppReadPackedMsg, &srsParameters->ue_antennas_in_this_srs_resource_set, end) + && pull32(ppReadPackedMsg, &srsParameters->sampled_ue_antennas, end) + && pull8(ppReadPackedMsg, &srsParameters->report_scope, end) + && pull8(ppReadPackedMsg, &srsParameters->num_ul_spatial_streams_ports, end) + && pullarray8(ppReadPackedMsg, + &srsParameters->Ul_spatial_stream_ports[0], + 256, + srsParameters->num_ul_spatial_streams_ports, + end))) { + return 0; + } + return 1; +} + +static uint8_t unpack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t *srs_pdu, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + if (!(pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && pull32(ppReadPackedMsg, &srs_pdu->handle, end) + && pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) + && pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) + && pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) + && pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) + && pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) + && pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) + && pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) + && pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && pull16(ppReadPackedMsg, &srs_pdu->frequency_shift, end) + && pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) + && pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) + && pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && pull16(ppReadPackedMsg, &srs_pdu->t_offset, end))) { + return 0; + } + + if (!(unpack_nr_rx_beamforming_pdu(&srs_pdu->beamforming, ppReadPackedMsg, end))) { + return 0; + } + + if (!(unpack_ul_tti_request_srs_parameters_v4(&srs_pdu->srs_parameters_v4, 1 << srs_pdu->num_symbols, ppReadPackedMsg, end))) { + return 0; + } + + return 1; +} + +static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) && pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end))) + return 0; + + // first natch the pdu type, then call the respective function + switch (pNfapiMsg->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + if (!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) + return 0; + } break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + if (!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) + return 0; + } break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + if (!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) + return 0; + } break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { + if (!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) + return 0; + } break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type); + } break; + } + + return 1; +} + +static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_groups_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t *)msg; + + if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) + return 0; + + for (int i = 0; i < pNfapiMsg->n_ue; i++) { + if (!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx, end)) + return 0; + } + + return 1; +} + +uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; + + if (!pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end)) + return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end)) + return 0; + if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end)) + return 0; + if (!pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end)) + return 0; + if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end)) + return 0; + if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end)) + return 0; + if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end)) + return 0; + for (int i = 0; i < pNfapiMsg->n_pdus; i++) { + if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) + return 0; + } + + for (int i = 0; i < pNfapiMsg->n_group; i++) { + if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) + return 0; + } + + return 1; +} + +uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t *)msg; + + if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end))) + return 0; + + return 1; +} + +uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_nr_slot_indication_scf_t *msg, + nfapi_p7_codec_config_t *config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end))) + return 0; + + return 1; +} + +static uint8_t pack_ul_dci_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)tlv; + uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; + if (!push16(value->PDUType, ppWritePackedMsg, end)) { + return 0; + } + uint8_t *pPackedLengthField = *ppWritePackedMsg; + if (!(push16(value->PDUSize, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) + && pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) + && push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) + && push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end))) { + return 0; + } + for (int i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { + nfapi_nr_dl_dci_pdu_t *dci_pdu = &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i]; + if (!(push16(dci_pdu->RNTI, ppWritePackedMsg, end) && push16(dci_pdu->ScramblingId, ppWritePackedMsg, end) + && push16(dci_pdu->ScramblingRNTI, ppWritePackedMsg, end) && push8(dci_pdu->CceIndex, ppWritePackedMsg, end) + && push8(dci_pdu->AggregationLevel, ppWritePackedMsg, end))) { + return 0; + } + // Precoding and Beamforming + nfapi_nr_tx_precoding_and_beamforming_t *beamforming = &dci_pdu->precodingAndBeamforming; + if (!(push16(beamforming->num_prgs, ppWritePackedMsg, end) && push16(beamforming->prg_size, ppWritePackedMsg, end) + && push8(beamforming->dig_bf_interfaces, ppWritePackedMsg, end))) { + return 0; + } + for (int prg = 0; prg < beamforming->num_prgs; prg++) { + if (!push16(beamforming->prgs_list[prg].pm_idx, ppWritePackedMsg, end)) { + return 0; + } + for (int digInt = 0; digInt < beamforming->dig_bf_interfaces; digInt++) { + if (!push16(beamforming->prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, ppWritePackedMsg, end)) { + return 0; + } + } + } + if (!(push8(dci_pdu->beta_PDCCH_1_0, ppWritePackedMsg, end) && push8(dci_pdu->powerControlOffsetSS, ppWritePackedMsg, end) && + // DCI Payload fields + push16(dci_pdu->PayloadSizeBits, ppWritePackedMsg, end) && + // Pack DCI Payload + pack_dci_payload(dci_pdu->Payload, dci_pdu->PayloadSizeBits, ppWritePackedMsg, end))) { + return 0; + } + } + + // pack proper size + uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; + uint16_t packedMsgLen = msgEnd - msgHead; + value->PDUSize = packedMsgLen; + return push16(value->PDUSize, &pPackedLengthField, end); +} + +uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) + && push8(pNfapiMsg->numPdus, ppWritePackedMsg, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->numPdus; i++) { + if (!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)msg; + + if (!(pull16(ppReadPackedMsg, &value->PDUType, end) && pull16(ppReadPackedMsg, &value->PDUSize, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) + && pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) + && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) + && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end))) { + return 0; + } + + for (uint16_t i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { + nfapi_nr_dl_dci_pdu_t *dci_pdu = &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i]; + if (!(pull16(ppReadPackedMsg, &dci_pdu->RNTI, end) && pull16(ppReadPackedMsg, &dci_pdu->ScramblingId, end) + && pull16(ppReadPackedMsg, &dci_pdu->ScramblingRNTI, end) && pull8(ppReadPackedMsg, &dci_pdu->CceIndex, end) + && pull8(ppReadPackedMsg, &dci_pdu->AggregationLevel, end))) { + return 0; + } + // Precoding and Beamforming + nfapi_nr_tx_precoding_and_beamforming_t *beamforming = &dci_pdu->precodingAndBeamforming; + if (!(pull16(ppReadPackedMsg, &beamforming->num_prgs, end) && pull16(ppReadPackedMsg, &beamforming->prg_size, end) + && pull8(ppReadPackedMsg, &beamforming->dig_bf_interfaces, end))) { + return 0; + } + + for (int prg = 0; prg < beamforming->num_prgs; prg++) { + if (!pull16(ppReadPackedMsg, &beamforming->prgs_list[prg].pm_idx, end)) { + return 0; + } + for (int digInt = 0; digInt < beamforming->dig_bf_interfaces; digInt++) { + if (!pull16(ppReadPackedMsg, &beamforming->prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, end)) { + return 0; + } + } + } + if (!(pull8(ppReadPackedMsg, &dci_pdu->beta_PDCCH_1_0, end) && pull8(ppReadPackedMsg, &dci_pdu->powerControlOffsetSS, end) + && pull16(ppReadPackedMsg, &dci_pdu->PayloadSizeBits, end) + && unpack_dci_payload(dci_pdu->Payload, dci_pdu->PayloadSizeBits, ppReadPackedMsg, end))) { + return 0; + } + } + return 1; +} + +uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->numPdus; i++) { + if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) + return 0; + } + + return 1; +} + +static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv; + if (!(push32(value->PDU_length, ppWritePackedMsg, end) && push16(value->PDU_index, ppWritePackedMsg, end) + && push32(value->num_TLV, ppWritePackedMsg, end))) + return 0; + + for (int i = 0; i < value->num_TLV; ++i) { + if (!(push16(value->TLVs[i].tag, ppWritePackedMsg, end) && push32(value->TLVs[i].length, ppWritePackedMsg, end))) + return 0; + const uint32_t byte_len = (value->TLVs[i].length + 3) / 4; + switch (value->TLVs[i].tag) { + case 0: { + if (!pusharray32(value->TLVs[i].value.direct, byte_len, byte_len, ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); + return 0; + } + break; + } + + case 1: { + if (!pusharray32(value->TLVs[i].value.ptr, byte_len, byte_len, ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); + return 0; + } + + break; + } + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag); + break; + } + } + } + + return 1; +} + +uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) + && push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { + if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n", + __FUNCTION__, + __LINE__, + i, + pNfapiMsg->pdu_list[i].PDU_length, + pNfapiMsg->pdu_list[i].PDU_index); + return 0; + } + } + + return 1; +} + +static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_pdu_t *pNfapiMsg = (nfapi_nr_pdu_t *)msg; + + if (!(pull32(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) && pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) + && pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->num_TLV; ++i) { + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end) && pull32(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end))) + return 0; + const uint32_t byte_len = (pNfapiMsg->TLVs[i].length + 3) / 4; + if (pNfapiMsg->TLVs[i].tag == 1) { + pNfapiMsg->TLVs[i].value.ptr = calloc(byte_len, sizeof(uint32_t)); + } + switch (pNfapiMsg->TLVs[i].tag) { + case 0: { + if (!pullarray32(ppReadPackedMsg, + pNfapiMsg->TLVs[i].value.direct, + sizeof(pNfapiMsg->TLVs[i].value.direct) / sizeof(uint32_t), + byte_len, + end)) + return 0; + + break; + } + + case 1: { + if (!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, byte_len, byte_len, end)) + return 0; + + break; + } + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag); + return 0; + } + } + } + + return 1; +} + +uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) + && pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) { + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_rx_data_indication_body(const nfapi_nr_rx_data_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push32(value->handle, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) + && push8(value->harq_id, ppWritePackedMsg, end) && push32(value->pdu_length, ppWritePackedMsg, end) + && push8(value->ul_cqi, ppWritePackedMsg, end) && push16(value->timing_advance, ppWritePackedMsg, end) + && push16(value->rssi, ppWritePackedMsg, end))) + return 0; + + if (pusharray8(value->pdu, value->pdu_length, value->pdu_length, ppWritePackedMsg, end) == 0) + return 0; + + return 1; +} + +uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t *)msg; + + if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) + && push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull8(ppReadPackedMsg, &value->harq_id, end) && pull32(ppReadPackedMsg, &value->pdu_length, end) + && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) + return 0; + + const uint32_t length = value->pdu_length; + value->pdu = calloc(length, sizeof(*value->pdu)); + if (pullarray8(ppReadPackedMsg, value->pdu, length, length, end) == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pullarray8 failure\n", __FUNCTION__); + return 0; + } + return 1; +} + +uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) + && pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) + return 0; + + if (pNfapiMsg->number_of_pdus > 0) { + pNfapiMsg->pdu_list = calloc(pNfapiMsg->number_of_pdus, sizeof(*pNfapiMsg->pdu_list)); + } + + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_crc_indication_body(const nfapi_nr_crc_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!(push32(value->handle, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) + && push8(value->harq_id, ppWritePackedMsg, end) && push8(value->tb_crc_status, ppWritePackedMsg, end) + && push16(value->num_cb, ppWritePackedMsg, end))) { + return 0; + } + if (value->num_cb != 0) { + const uint16_t cb_len = (value->num_cb / 8) + 1; // length is ceil(NumCb/8) + if (!pusharray8(value->cb_crc_status, cb_len, cb_len, ppWritePackedMsg, + end)) { + return 0; + } + } + if (!(push8(value->ul_cqi, ppWritePackedMsg, end) && push16(value->timing_advance, ppWritePackedMsg, end) + && push16(value->rssi, ppWritePackedMsg, end))) { + return 0; + } + return 1; +} + +uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *)msg; + + if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) + && push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->number_crcs; i++) { + if (!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) + && pull8(ppReadPackedMsg, &value->harq_id, end) && pull8(ppReadPackedMsg, &value->tb_crc_status, end) + && pull16(ppReadPackedMsg, &value->num_cb, end))) { + return 0; + } + if (value->num_cb != 0) { + const uint16_t cb_len = (value->num_cb / 8) + 1; // length is ceil(NumCb/8) + value->cb_crc_status = calloc(cb_len, sizeof(uint8_t)); + if (!pullarray8(ppReadPackedMsg, value->cb_crc_status, cb_len, cb_len, end)) { + return 0; + } + } + if (!(pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) { + return 0; + } + + return 1; +} + +uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) + && pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end))) + return 0; + + if (pNfapiMsg->number_crcs > 0) { + pNfapiMsg->crc_list = calloc(pNfapiMsg->number_crcs, sizeof(*pNfapiMsg->crc_list)); + } + + for (int i = 0; i < pNfapiMsg->number_crcs; i++) { + if (!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_pusch(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_pusch_pdu_t *value = (nfapi_nr_uci_pusch_pdu_t *)tlv; + + if (!push8(value->pduBitmap, ppWritePackedMsg, end)) + return 0; + if (!push32(value->handle, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rnti, ppWritePackedMsg, end)) + return 0; + if (!push8(value->ul_cqi, ppWritePackedMsg, end)) + return 0; + if (!push16(value->timing_advance, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rssi, ppWritePackedMsg, end)) + return 0; + + // Bit 0 not used in PUSCH PDU + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) + return 0; + const uint16_t harq_len = (value->harq.harq_bit_len / 8) + 1; + if (!pusharray8(value->harq.harq_payload, harq_len, harq_len, ppWritePackedMsg, end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) + return 0; + const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1; + if (!pusharray8(value->csi_part1.csi_part1_payload, csi_len, csi_len, ppWritePackedMsg, end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) + return 0; + const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1; + if (!pusharray8(value->csi_part2.csi_part2_payload, csi_len, csi_len, ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_pucch_0_1(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_pucch_pdu_format_0_1_t *value = (nfapi_nr_uci_pucch_pdu_format_0_1_t *)tlv; + + if (!push8(value->pduBitmap, ppWritePackedMsg, end)) + return 0; + if (!push32(value->handle, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rnti, ppWritePackedMsg, end)) + return 0; + if (!push8(value->pucch_format, ppWritePackedMsg, end)) + return 0; + if (!push8(value->ul_cqi, ppWritePackedMsg, end)) + return 0; + if (!push16(value->timing_advance, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rssi, ppWritePackedMsg, end)) + return 0; + if (value->pduBitmap & 0x01) { // SR + if (!push8(value->sr.sr_indication, ppWritePackedMsg, end)) + return 0; + if (!push8(value->sr.sr_confidence_level, ppWritePackedMsg, end)) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { // HARQ + if (!push8(value->harq.num_harq, ppWritePackedMsg, end)) + return 0; + if (!push8(value->harq.harq_confidence_level, ppWritePackedMsg, end)) + return 0; + for (int i = 0; i < value->harq.num_harq; i++) { + if (!push8(value->harq.harq_list[i].harq_value, ppWritePackedMsg, end)) + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_pucch_2_3_4(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t *)tlv; + + if (!push8(value->pduBitmap, ppWritePackedMsg, end)) + return 0; + if (!push32(value->handle, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rnti, ppWritePackedMsg, end)) + return 0; + if (!push8(value->pucch_format, ppWritePackedMsg, end)) + return 0; + if (!push8(value->ul_cqi, ppWritePackedMsg, end)) + return 0; + if (!push16(value->timing_advance, ppWritePackedMsg, end)) + return 0; + if (!push16(value->rssi, ppWritePackedMsg, end)) + return 0; + + if (value->pduBitmap & 0x01) { // SR + if (!push16(value->sr.sr_bit_len, ppWritePackedMsg, end)) + return 0; + const uint16_t sr_len = value->sr.sr_bit_len / 8 + 1; + if (!pusharray8(value->sr.sr_payload, sr_len, sr_len, ppWritePackedMsg, end)) + return 0; + } + + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) + return 0; + const uint16_t harq_len = value->harq.harq_bit_len / 8 + 1; + if (!pusharray8(value->harq.harq_payload, harq_len, harq_len, ppWritePackedMsg, end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) + return 0; + const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1; + if (!pusharray8(value->csi_part1.csi_part1_payload, csi_len, csi_len, ppWritePackedMsg, end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) + return 0; + if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) + return 0; + const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1; + if (!pusharray8(value->csi_part2.csi_part2_payload, csi_len, csi_len, ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_indication_body(nfapi_nr_uci_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!push16(value->pdu_type, ppWritePackedMsg, end)) + return 0; + if (!push16(value->pdu_size, ppWritePackedMsg, end)) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + if (!pack_nr_uci_pusch(&value->pusch_pdu, ppWritePackedMsg, end)) { + return 0; + } + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + if (!pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end)) { + return 0; + } + break; + + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + if (!pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end)) { + return 0; + } + break; + default: + NFAPI_TRACE(NFAPI_TRACE_WARN, "Unexpected UCI.indication PDU type %d\n", value->pdu_type); + return 0; + } + + return 1; +} + +uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg; + + if (!push16(pNfapiMsg->sfn, ppWritePackedMsg, end)) + return 0; + if (!push16(pNfapiMsg->slot, ppWritePackedMsg, end)) + return 0; + if (!push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end)) + return 0; + + for (int i = 0; i < pNfapiMsg->num_ucis; i++) { + if (!pack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_pusch(nfapi_nr_uci_pusch_pdu_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!pull8(ppReadPackedMsg, &value->pduBitmap, end)) + return 0; + if (!pull32(ppReadPackedMsg, &value->handle, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rnti, end)) + return 0; + if (!pull8(ppReadPackedMsg, &value->ul_cqi, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->timing_advance, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rssi, end)) + return 0; + + // Bit 0 not used in PUSCH PDU + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end)) + return 0; + const uint16_t harq_len = value->harq.harq_bit_len / 8 + 1; + value->harq.harq_payload = calloc(harq_len, sizeof(*value->harq.harq_payload)); + + if (value->harq.harq_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->harq.harq_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, value->harq.harq_payload, harq_len, harq_len, end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end)) + return 0; + const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1; + value->csi_part1.csi_part1_payload = calloc(csi_len, sizeof(*value->csi_part1.csi_part1_payload)); + + if (value->csi_part1.csi_part1_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part1.csi_part1_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, csi_len, csi_len, end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end)) + return 0; + const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1; + value->csi_part2.csi_part2_payload = calloc(csi_len, sizeof(*value->csi_part2.csi_part2_payload)); + + if (value->csi_part2.csi_part2_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part2.csi_part2_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, csi_len, csi_len, end)) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && pull32(ppReadPackedMsg, &value->handle, end) + && pull16(ppReadPackedMsg, &value->rnti, end) && pull8(ppReadPackedMsg, &value->pucch_format, end) + && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) + && pull16(ppReadPackedMsg, &value->rssi, end))) + return 0; + if (value->pduBitmap & 0x01) { // SR + if (!(pull8(ppReadPackedMsg, &value->sr.sr_indication, end) && pull8(ppReadPackedMsg, &value->sr.sr_confidence_level, end))) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { // HARQ + + if (!(pull8(ppReadPackedMsg, &value->harq.num_harq, end) && pull8(ppReadPackedMsg, &value->harq.harq_confidence_level, end))) + return 0; + if (value->harq.num_harq > 0) { + for (int i = 0; i < value->harq.num_harq; i++) { + if (!pull8(ppReadPackedMsg, &value->harq.harq_list[i].harq_value, end)) { + return 0; + } + } + } + } + + return 1; +} + +static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!pull8(ppReadPackedMsg, &value->pduBitmap, end)) + return 0; + if (!pull32(ppReadPackedMsg, &value->handle, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rnti, end)) + return 0; + if (!pull8(ppReadPackedMsg, &value->pucch_format, end)) + return 0; + if (!pull8(ppReadPackedMsg, &value->ul_cqi, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->timing_advance, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->rssi, end)) + return 0; + + if (value->pduBitmap & 0x01) { // SR + if (!pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end)) + return 0; + const uint16_t sr_len = value->sr.sr_bit_len / 8 + 1; + value->sr.sr_payload = calloc(sr_len, sizeof(*value->sr.sr_payload)); + + if (value->sr.sr_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->sr.sr_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, value->sr.sr_payload, sr_len, sr_len, end)) + return 0; + } + + if ((value->pduBitmap >> 1) & 0x01) { // HARQ + if (!pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end)) + return 0; + const uint16_t harq_len = value->harq.harq_bit_len / 8 + 1; + value->harq.harq_payload = calloc(harq_len, sizeof(*value->harq.harq_payload)); + + if (value->harq.harq_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->harq.harq_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, value->harq.harq_payload, harq_len, harq_len, end)) + return 0; + } + + if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 + if (!pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end)) + return 0; + const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1; + value->csi_part1.csi_part1_payload = calloc(csi_len, sizeof(*value->csi_part1.csi_part1_payload)); + + if (value->csi_part1.csi_part1_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part1.csi_part1_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, csi_len, csi_len, end)) + return 0; + } + + if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 + if (!pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end)) + return 0; + const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1; + value->csi_part2.csi_part2_payload = calloc(csi_len, sizeof(*value->csi_part2.csi_part2_payload)); + + if (value->csi_part2.csi_part2_payload == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part2.csi_part2_payload\n", __FUNCTION__); + return 0; + } + + if (!pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, csi_len, csi_len, end)) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!pull16(ppReadPackedMsg, &value->pdu_type, end)) + return 0; + if (!pull16(ppReadPackedMsg, &value->pdu_size, end)) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { + nfapi_nr_uci_pusch_pdu_t *uci_pdu = &value->pusch_pdu; + if (!unpack_nr_uci_pusch(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + if (!unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + if (!unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end, config)) + return 0; + break; + } + default: + NFAPI_TRACE(NFAPI_TRACE_WARN, "Unexpected UCI.indication PDU type %d\n", value->pdu_type); + break; + } + + return 1; +} + +uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg; + + if (!pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end)) + return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)) + return 0; + if (!pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end)) + return 0; + + pNfapiMsg->uci_list = calloc(pNfapiMsg->num_ucis, sizeof(*pNfapiMsg->uci_list)); + for (int i = 0; i < pNfapiMsg->num_ucis; i++) { + if (!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppReadPackedMsg, end, config)) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_srs_report_tlv(const nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + + if(!(push16(report_tlv->tag, ppWritePackedMsg, end) && + push32(report_tlv->length, ppWritePackedMsg, end))) { + return 0; + } + + for (int i = 0; i < (report_tlv->length + 3) / 4; i++) { + if (!push32(report_tlv->value[i], ppWritePackedMsg, end)) { + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_srs_indication_body(const nfapi_nr_srs_indication_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->timing_advance_offset, ppWritePackedMsg, end) && + pushs16(value->timing_advance_offset_nsec, ppWritePackedMsg, end) && + push8(value->srs_usage, ppWritePackedMsg, end) && + push8(value->report_type, ppWritePackedMsg, end))) { + return 0; + } + + if (!pack_nr_srs_report_tlv(&value->report_tlv, ppWritePackedMsg, end)) { + return 0; + } + + return 1; +} + +uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t *)msg; + + if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) + && push16(pNfapiMsg->control_length, ppWritePackedMsg, end) && push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) { + return 0; + } + + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) { + return 0; + } + } + + return 1; +} + +static uint8_t unpack_nr_srs_report_tlv(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + + if(!(pull16(ppReadPackedMsg, &report_tlv->tag, end) && + pull32(ppReadPackedMsg, &report_tlv->length, end))) { + return 0; + } +#ifndef ENABLE_AERIAL + for (int i = 0; i < (report_tlv->length + 3) / 4; i++) { + if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) { + return 0; + } + } +#endif + return 1; +} + +static uint8_t unpack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end) { + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->timing_advance_offset, end) && + pulls16(ppReadPackedMsg, &value->timing_advance_offset_nsec, end) && + pull8(ppReadPackedMsg, &value->srs_usage, end) && + pull8(ppReadPackedMsg, &value->report_type, end))) { + return 0; + } + + if (!unpack_nr_srs_report_tlv(&value->report_tlv, ppReadPackedMsg, end)) { + return 0; + } + + return 1; +} + +uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t *)msg; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) + && pull16(ppReadPackedMsg, &pNfapiMsg->control_length, end) && pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) { + return 0; + } + pNfapiMsg->pdu_list = calloc(pNfapiMsg->number_of_pdus, sizeof(*pNfapiMsg->pdu_list)); + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end)) { + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_rach_indication_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t *value = (nfapi_nr_prach_indication_pdu_t *)tlv; + + if (!(push16(value->phy_cell_id, ppWritePackedMsg, end) && push8(value->symbol_index, ppWritePackedMsg, end) + && push8(value->slot_index, ppWritePackedMsg, end) && push8(value->freq_index, ppWritePackedMsg, end) + && push8(value->avg_rssi, ppWritePackedMsg, end) && push8(value->avg_snr, ppWritePackedMsg, end) + && push8(value->num_preamble, ppWritePackedMsg, end))) + return 0; + for (int i = 0; i < value->num_preamble; i++) { + if (!(push8(value->preamble_list[i].preamble_index, ppWritePackedMsg, end) + && push16(value->preamble_list[i].timing_advance, ppWritePackedMsg, end) + && push32(value->preamble_list[i].preamble_pwr, ppWritePackedMsg, end))) + return 0; + } + return 1; +} + +uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg; + + if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) + && push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) + return 0; + + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t *value, + uint8_t **ppReadPackedMsg, + uint8_t *end, + nfapi_p7_codec_config_t *config) +{ + if (!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && pull8(ppReadPackedMsg, &value->symbol_index, end) + && pull8(ppReadPackedMsg, &value->slot_index, end) && pull8(ppReadPackedMsg, &value->freq_index, end) + && pull8(ppReadPackedMsg, &value->avg_rssi, end) && pull8(ppReadPackedMsg, &value->avg_snr, end) + && pull8(ppReadPackedMsg, &value->num_preamble, end))) { + return 0; + } + + for (int i = 0; i < value->num_preamble; i++) { + nfapi_nr_prach_indication_preamble_t *preamble = &(value->preamble_list[i]); + if (!(pull8(ppReadPackedMsg, &preamble->preamble_index, end) && pull16(ppReadPackedMsg, &preamble->timing_advance, end) + && pull32(ppReadPackedMsg, &preamble->preamble_pwr, end))) { + return 0; + } + } + return 1; +} + +uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) + && pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) { + return 0; + } + + if (pNfapiMsg->number_of_pdus > 0) { + pNfapiMsg->pdu_list = calloc(pNfapiMsg->number_of_pdus, sizeof(*pNfapiMsg->pdu_list)); + for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { + if (!unpack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]), ppReadPackedMsg, end, config)) + return 0; + } + } + return 1; +} diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..395cb29fe1d741efe67c07284e3b75f124022927 --- /dev/null +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -0,0 +1,2003 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "nr_fapi_p7_utils.h" + +#include <malloc.h> + +static bool eq_dl_tti_beamforming(const nfapi_nr_tx_precoding_and_beamforming_t *a, + const nfapi_nr_tx_precoding_and_beamforming_t *b) +{ + EQ(a->num_prgs, b->num_prgs); + EQ(a->prg_size, b->prg_size); + EQ(a->dig_bf_interfaces, b->dig_bf_interfaces); + for (int prg = 0; prg < a->num_prgs; ++prg) { + EQ(a->prgs_list[prg].pm_idx, b->prgs_list[prg].pm_idx); + for (int dbf_if = 0; dbf_if < a->dig_bf_interfaces; ++dbf_if) { + EQ(a->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx, b->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx); + } + } + + return true; +} + +static bool eq_dl_tti_request_pdcch_pdu(const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *a, const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *b) +{ + EQ(a->BWPSize, b->BWPSize); + EQ(a->BWPStart, b->BWPStart); + EQ(a->SubcarrierSpacing, b->SubcarrierSpacing); + EQ(a->CyclicPrefix, b->CyclicPrefix); + EQ(a->StartSymbolIndex, b->StartSymbolIndex); + EQ(a->DurationSymbols, b->DurationSymbols); + for (int fdr_idx = 0; fdr_idx < 6; ++fdr_idx) { + EQ(a->FreqDomainResource[fdr_idx], b->FreqDomainResource[fdr_idx]); + } + EQ(a->CceRegMappingType, b->CceRegMappingType); + EQ(a->RegBundleSize, b->RegBundleSize); + EQ(a->InterleaverSize, b->InterleaverSize); + EQ(a->CoreSetType, b->CoreSetType); + EQ(a->ShiftIndex, b->ShiftIndex); + EQ(a->precoderGranularity, b->precoderGranularity); + EQ(a->numDlDci, b->numDlDci); + for (int dl_dci = 0; dl_dci < a->numDlDci; ++dl_dci) { + const nfapi_nr_dl_dci_pdu_t *a_dci_pdu = &a->dci_pdu[dl_dci]; + const nfapi_nr_dl_dci_pdu_t *b_dci_pdu = &b->dci_pdu[dl_dci]; + EQ(a_dci_pdu->RNTI, b_dci_pdu->RNTI); + EQ(a_dci_pdu->ScramblingId, b_dci_pdu->ScramblingId); + EQ(a_dci_pdu->ScramblingRNTI, b_dci_pdu->ScramblingRNTI); + EQ(a_dci_pdu->CceIndex, b_dci_pdu->CceIndex); + EQ(a_dci_pdu->AggregationLevel, b_dci_pdu->AggregationLevel); + EQ(eq_dl_tti_beamforming(&a_dci_pdu->precodingAndBeamforming, &b_dci_pdu->precodingAndBeamforming), true); + EQ(a_dci_pdu->beta_PDCCH_1_0, b_dci_pdu->beta_PDCCH_1_0); + EQ(a_dci_pdu->powerControlOffsetSS, b_dci_pdu->powerControlOffsetSS); + EQ(a_dci_pdu->PayloadSizeBits, b_dci_pdu->PayloadSizeBits); + for (int i = 0; i < 8; ++i) { + // The parameter itself always has 8 positions, no need to calculate how many bytes the payload actually occupies + EQ(a_dci_pdu->Payload[i], b_dci_pdu->Payload[i]); + } + } + return true; +} + +static bool eq_dl_tti_request_pdsch_pdu(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *a, const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *b) +{ + EQ(a->pduBitmap, b->pduBitmap); + EQ(a->rnti, b->rnti); + EQ(a->pduIndex, b->pduIndex); + EQ(a->BWPSize, b->BWPSize); + EQ(a->BWPStart, b->BWPStart); + EQ(a->SubcarrierSpacing, b->SubcarrierSpacing); + EQ(a->CyclicPrefix, b->CyclicPrefix); + EQ(a->NrOfCodewords, b->NrOfCodewords); + for (int cw = 0; cw < a->NrOfCodewords; ++cw) { + EQ(a->targetCodeRate[cw], b->targetCodeRate[cw]); + EQ(a->qamModOrder[cw], b->qamModOrder[cw]); + EQ(a->mcsIndex[cw], b->mcsIndex[cw]); + EQ(a->mcsTable[cw], b->mcsTable[cw]); + EQ(a->rvIndex[cw], b->rvIndex[cw]); + EQ(a->TBSize[cw], b->TBSize[cw]); + } + EQ(a->dataScramblingId, b->dataScramblingId); + EQ(a->nrOfLayers, b->nrOfLayers); + EQ(a->transmissionScheme, b->transmissionScheme); + EQ(a->refPoint, b->refPoint); + EQ(a->dlDmrsSymbPos, b->dlDmrsSymbPos); + EQ(a->dmrsConfigType, b->dmrsConfigType); + EQ(a->dlDmrsScramblingId, b->dlDmrsScramblingId); + EQ(a->SCID, b->SCID); + EQ(a->numDmrsCdmGrpsNoData, b->numDmrsCdmGrpsNoData); + EQ(a->dmrsPorts, b->dmrsPorts); + EQ(a->resourceAlloc, b->resourceAlloc); + for (int i = 0; i < 36; ++i) { + EQ(a->rbBitmap[i], b->rbBitmap[i]); + } + EQ(a->rbStart, b->rbStart); + EQ(a->rbSize, b->rbSize); + EQ(a->VRBtoPRBMapping, b->VRBtoPRBMapping); + EQ(a->StartSymbolIndex, b->StartSymbolIndex); + EQ(a->NrOfSymbols, b->NrOfSymbols); + EQ(a->PTRSPortIndex, b->PTRSPortIndex); + EQ(a->PTRSTimeDensity, b->PTRSTimeDensity); + EQ(a->PTRSFreqDensity, b->PTRSFreqDensity); + EQ(a->PTRSReOffset, b->PTRSReOffset); + EQ(a->nEpreRatioOfPDSCHToPTRS, b->nEpreRatioOfPDSCHToPTRS); + EQ(eq_dl_tti_beamforming(&a->precodingAndBeamforming, &b->precodingAndBeamforming), true); + EQ(a->powerControlOffset, b->powerControlOffset); + EQ(a->powerControlOffsetSS, b->powerControlOffsetSS); + EQ(a->isLastCbPresent, b->isLastCbPresent); + EQ(a->isInlineTbCrc, b->isInlineTbCrc); + EQ(a->dlTbCrc, b->dlTbCrc); + EQ(a->maintenance_parms_v3.ldpcBaseGraph, b->maintenance_parms_v3.ldpcBaseGraph); + EQ(a->maintenance_parms_v3.tbSizeLbrmBytes, b->maintenance_parms_v3.tbSizeLbrmBytes); + return true; +} + +static bool eq_dl_tti_request_csi_rs_pdu(const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *a, const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *b) +{ + EQ(a->bwp_size, b->bwp_size); + EQ(a->bwp_start, b->bwp_start); + EQ(a->subcarrier_spacing, b->subcarrier_spacing); + EQ(a->cyclic_prefix, b->cyclic_prefix); + EQ(a->start_rb, b->start_rb); + EQ(a->nr_of_rbs, b->nr_of_rbs); + EQ(a->csi_type, b->csi_type); + EQ(a->row, b->row); + EQ(a->freq_domain, b->freq_domain); + EQ(a->symb_l0, b->symb_l0); + EQ(a->symb_l1, b->symb_l1); + EQ(a->cdm_type, b->cdm_type); + EQ(a->freq_density, b->freq_density); + EQ(a->scramb_id, b->scramb_id); + EQ(a->power_control_offset, b->power_control_offset); + EQ(a->power_control_offset_ss, b->power_control_offset_ss); + EQ(eq_dl_tti_beamforming(&a->precodingAndBeamforming, &b->precodingAndBeamforming), true); + return true; +} + +static bool eq_dl_tti_request_ssb_pdu(const nfapi_nr_dl_tti_ssb_pdu_rel15_t *a, const nfapi_nr_dl_tti_ssb_pdu_rel15_t *b) +{ + EQ(a->PhysCellId, b->PhysCellId); + EQ(a->BetaPss, b->BetaPss); + EQ(a->SsbBlockIndex, b->SsbBlockIndex); + EQ(a->SsbSubcarrierOffset, b->SsbSubcarrierOffset); + EQ(a->ssbOffsetPointA, b->ssbOffsetPointA); + EQ(a->bchPayloadFlag, b->bchPayloadFlag); + EQ(a->bchPayload, b->bchPayload); + EQ(a->ssbRsrp, b->ssbRsrp); + EQ(eq_dl_tti_beamforming(&a->precoding_and_beamforming, &b->precoding_and_beamforming), true); + return true; +} + +bool eq_dl_tti_request(const nfapi_nr_dl_tti_request_t *a, const nfapi_nr_dl_tti_request_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + + EQ(a->SFN, b->SFN); + EQ(a->Slot, b->Slot); + EQ(a->dl_tti_request_body.nPDUs, b->dl_tti_request_body.nPDUs); + EQ(a->dl_tti_request_body.nGroup, b->dl_tti_request_body.nGroup); + + for (int PDU = 0; PDU < a->dl_tti_request_body.nPDUs; ++PDU) { + // take the PDU at the start of loops + const nfapi_nr_dl_tti_request_pdu_t *a_dl_pdu = &a->dl_tti_request_body.dl_tti_pdu_list[PDU]; + const nfapi_nr_dl_tti_request_pdu_t *b_dl_pdu = &b->dl_tti_request_body.dl_tti_pdu_list[PDU]; + + EQ(a_dl_pdu->PDUType, b_dl_pdu->PDUType); + EQ(a_dl_pdu->PDUSize, b_dl_pdu->PDUSize); + + switch (a_dl_pdu->PDUType) { + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + EQ(eq_dl_tti_request_pdcch_pdu(&a_dl_pdu->pdcch_pdu.pdcch_pdu_rel15, &b_dl_pdu->pdcch_pdu.pdcch_pdu_rel15), true); + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + EQ(eq_dl_tti_request_pdsch_pdu(&a_dl_pdu->pdsch_pdu.pdsch_pdu_rel15, &b_dl_pdu->pdsch_pdu.pdsch_pdu_rel15), true); + break; + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + EQ(eq_dl_tti_request_csi_rs_pdu(&a_dl_pdu->csi_rs_pdu.csi_rs_pdu_rel15, &b_dl_pdu->csi_rs_pdu.csi_rs_pdu_rel15), true); + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + EQ(eq_dl_tti_request_ssb_pdu(&a_dl_pdu->ssb_pdu.ssb_pdu_rel15, &b_dl_pdu->ssb_pdu.ssb_pdu_rel15), true); + break; + default: + // PDU Type is not any known value + return false; + } + } + + for (int nGroup = 0; nGroup < a->dl_tti_request_body.nGroup; ++nGroup) { + EQ(a->dl_tti_request_body.nUe[nGroup], b->dl_tti_request_body.nUe[nGroup]); + for (int UE = 0; UE < a->dl_tti_request_body.nUe[nGroup]; ++UE) { + EQ(a->dl_tti_request_body.PduIdx[nGroup][UE], b->dl_tti_request_body.PduIdx[nGroup][UE]); + } + } + + return true; +} + +static bool eq_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *a, const nfapi_nr_ul_beamforming_t *b) +{ + EQ(a->trp_scheme, b->trp_scheme); + EQ(a->num_prgs, b->num_prgs); + EQ(a->prg_size, b->prg_size); + EQ(a->dig_bf_interface, b->dig_bf_interface); + for (int prg = 0; prg < a->num_prgs; ++prg) { + for (int dbf_if = 0; dbf_if < a->dig_bf_interface; ++dbf_if) { + EQ(a->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx, b->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx); + } + } + + return true; +} + +static bool eq_ul_tti_request_prach_pdu(const nfapi_nr_prach_pdu_t *a, const nfapi_nr_prach_pdu_t *b) +{ + EQ(a->phys_cell_id, b->phys_cell_id); + EQ(a->num_prach_ocas, b->num_prach_ocas); + EQ(a->prach_format, b->prach_format); + EQ(a->num_ra, b->num_ra); + EQ(a->prach_start_symbol, b->prach_start_symbol); + EQ(a->num_cs, b->num_cs); + EQ(eq_ul_tti_beamforming(&a->beamforming, &b->beamforming), true); + return true; +} + +static bool eq_ul_tti_request_pusch_pdu(const nfapi_nr_pusch_pdu_t *a, const nfapi_nr_pusch_pdu_t *b) +{ + EQ(a->pdu_bit_map, b->pdu_bit_map); + EQ(a->rnti, b->rnti); + EQ(a->handle, b->handle); + EQ(a->bwp_size, b->bwp_size); + EQ(a->bwp_start, b->bwp_start); + EQ(a->subcarrier_spacing, b->subcarrier_spacing); + EQ(a->cyclic_prefix, b->cyclic_prefix); + EQ(a->target_code_rate, b->target_code_rate); + EQ(a->qam_mod_order, b->qam_mod_order); + EQ(a->mcs_index, b->mcs_index); + EQ(a->mcs_table, b->mcs_table); + EQ(a->transform_precoding, b->transform_precoding); + EQ(a->data_scrambling_id, b->data_scrambling_id); + EQ(a->nrOfLayers, b->nrOfLayers); + EQ(a->ul_dmrs_symb_pos, b->ul_dmrs_symb_pos); + EQ(a->dmrs_config_type, b->dmrs_config_type); + EQ(a->ul_dmrs_scrambling_id, b->ul_dmrs_scrambling_id); + EQ(a->pusch_identity, b->pusch_identity); + EQ(a->scid, b->scid); + EQ(a->num_dmrs_cdm_grps_no_data, b->num_dmrs_cdm_grps_no_data); + EQ(a->dmrs_ports, b->dmrs_ports); + EQ(a->resource_alloc, b->resource_alloc); + for (int i = 0; i < 36; ++i) { + EQ(a->rb_bitmap[i], b->rb_bitmap[i]); + } + EQ(a->rb_start, b->rb_start); + EQ(a->rb_size, b->rb_size); + EQ(a->vrb_to_prb_mapping, b->vrb_to_prb_mapping); + EQ(a->frequency_hopping, b->frequency_hopping); + EQ(a->tx_direct_current_location, b->tx_direct_current_location); + EQ(a->uplink_frequency_shift_7p5khz, b->uplink_frequency_shift_7p5khz); + EQ(a->start_symbol_index, b->start_symbol_index); + EQ(a->nr_of_symbols, b->nr_of_symbols); + + if (a->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_DATA) { + const nfapi_nr_pusch_data_t *a_pusch_data = &a->pusch_data; + const nfapi_nr_pusch_data_t *b_pusch_data = &b->pusch_data; + EQ(a_pusch_data->rv_index, b_pusch_data->rv_index); + EQ(a_pusch_data->harq_process_id, b_pusch_data->harq_process_id); + EQ(a_pusch_data->new_data_indicator, b_pusch_data->new_data_indicator); + EQ(a_pusch_data->tb_size, b_pusch_data->tb_size); + EQ(a_pusch_data->num_cb, b_pusch_data->num_cb); + for (int i = 0; i < (a_pusch_data->num_cb + 7) / 8; ++i) { + EQ(a_pusch_data->cb_present_and_position[i], b_pusch_data->cb_present_and_position[i]); + } + } + if (a->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_UCI) { + const nfapi_nr_pusch_uci_t *a_pusch_uci = &a->pusch_uci; + const nfapi_nr_pusch_uci_t *b_pusch_uci = &b->pusch_uci; + EQ(a_pusch_uci->harq_ack_bit_length, b_pusch_uci->harq_ack_bit_length); + EQ(a_pusch_uci->csi_part1_bit_length, b_pusch_uci->csi_part1_bit_length); + EQ(a_pusch_uci->csi_part2_bit_length, b_pusch_uci->csi_part2_bit_length); + EQ(a_pusch_uci->alpha_scaling, b_pusch_uci->alpha_scaling); + EQ(a_pusch_uci->beta_offset_harq_ack, b_pusch_uci->beta_offset_harq_ack); + EQ(a_pusch_uci->beta_offset_csi1, b_pusch_uci->beta_offset_csi1); + EQ(a_pusch_uci->beta_offset_csi2, b_pusch_uci->beta_offset_csi2); + } + if (a->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + const nfapi_nr_pusch_ptrs_t *a_pusch_ptrs = &a->pusch_ptrs; + const nfapi_nr_pusch_ptrs_t *b_pusch_ptrs = &b->pusch_ptrs; + + EQ(a_pusch_ptrs->num_ptrs_ports, b_pusch_ptrs->num_ptrs_ports); + for (int i = 0; i < a_pusch_ptrs->num_ptrs_ports; ++i) { + const nfapi_nr_ptrs_ports_t *a_ptrs_port = &a_pusch_ptrs->ptrs_ports_list[i]; + const nfapi_nr_ptrs_ports_t *b_ptrs_port = &b_pusch_ptrs->ptrs_ports_list[i]; + + EQ(a_ptrs_port->ptrs_port_index, b_ptrs_port->ptrs_port_index); + EQ(a_ptrs_port->ptrs_dmrs_port, b_ptrs_port->ptrs_dmrs_port); + EQ(a_ptrs_port->ptrs_re_offset, b_ptrs_port->ptrs_re_offset); + } + + EQ(a_pusch_ptrs->ptrs_time_density, b_pusch_ptrs->ptrs_time_density); + EQ(a_pusch_ptrs->ptrs_freq_density, b_pusch_ptrs->ptrs_freq_density); + EQ(a_pusch_ptrs->ul_ptrs_power, b_pusch_ptrs->ul_ptrs_power); + } + if (a->pdu_bit_map & PUSCH_PDU_BITMAP_DFTS_OFDM) { + const nfapi_nr_dfts_ofdm_t *a_dfts_ofdm = &a->dfts_ofdm; + const nfapi_nr_dfts_ofdm_t *b_dfts_ofdm = &b->dfts_ofdm; + + EQ(a_dfts_ofdm->low_papr_group_number, b_dfts_ofdm->low_papr_group_number); + EQ(a_dfts_ofdm->low_papr_sequence_number, b_dfts_ofdm->low_papr_sequence_number); + EQ(a_dfts_ofdm->ul_ptrs_sample_density, b_dfts_ofdm->ul_ptrs_sample_density); + EQ(a_dfts_ofdm->ul_ptrs_time_density_transform_precoding, b_dfts_ofdm->ul_ptrs_time_density_transform_precoding); + } + EQ(eq_ul_tti_beamforming(&a->beamforming, &b->beamforming), true); + EQ(a->maintenance_parms_v3.ldpcBaseGraph, b->maintenance_parms_v3.ldpcBaseGraph); + EQ(a->maintenance_parms_v3.tbSizeLbrmBytes, b->maintenance_parms_v3.tbSizeLbrmBytes); + return true; +} + +static bool eq_ul_tti_request_pucch_pdu(const nfapi_nr_pucch_pdu_t *a, const nfapi_nr_pucch_pdu_t *b) +{ + EQ(a->rnti, b->rnti); + EQ(a->handle, b->handle); + EQ(a->bwp_size, b->bwp_size); + EQ(a->bwp_start, b->bwp_start); + EQ(a->subcarrier_spacing, b->subcarrier_spacing); + EQ(a->cyclic_prefix, b->cyclic_prefix); + EQ(a->format_type, b->format_type); + EQ(a->multi_slot_tx_indicator, b->multi_slot_tx_indicator); + EQ(a->pi_2bpsk, b->pi_2bpsk); + EQ(a->prb_start, b->prb_start); + EQ(a->prb_size, b->prb_size); + EQ(a->start_symbol_index, b->start_symbol_index); + EQ(a->nr_of_symbols, b->nr_of_symbols); + EQ(a->freq_hop_flag, b->freq_hop_flag); + EQ(a->second_hop_prb, b->second_hop_prb); + EQ(a->group_hop_flag, b->group_hop_flag); + EQ(a->sequence_hop_flag, b->sequence_hop_flag); + EQ(a->hopping_id, b->hopping_id); + EQ(a->initial_cyclic_shift, b->initial_cyclic_shift); + EQ(a->data_scrambling_id, b->data_scrambling_id); + EQ(a->time_domain_occ_idx, b->time_domain_occ_idx); + EQ(a->pre_dft_occ_idx, b->pre_dft_occ_idx); + EQ(a->pre_dft_occ_len, b->pre_dft_occ_len); + EQ(a->add_dmrs_flag, b->add_dmrs_flag); + EQ(a->dmrs_scrambling_id, b->dmrs_scrambling_id); + EQ(a->dmrs_cyclic_shift, b->dmrs_cyclic_shift); + EQ(a->sr_flag, b->sr_flag); + EQ(a->bit_len_harq, b->bit_len_harq); + EQ(a->bit_len_csi_part1, b->bit_len_csi_part1); + EQ(a->bit_len_csi_part2, b->bit_len_csi_part2); + EQ(eq_ul_tti_beamforming(&a->beamforming, &b->beamforming), true); + return true; +} + +static bool eq_ul_tti_request_srs_parameters(const nfapi_v4_srs_parameters_t *a, + const uint8_t num_symbols, + const nfapi_v4_srs_parameters_t *b) +{ + EQ(a->srs_bandwidth_size, b->srs_bandwidth_size); + for (int symbol_idx = 0; symbol_idx < num_symbols; ++symbol_idx) { + const nfapi_v4_srs_parameters_symbols_t *a_symbol = &a->symbol_list[symbol_idx]; + const nfapi_v4_srs_parameters_symbols_t *b_symbol = &b->symbol_list[symbol_idx]; + EQ(a_symbol->srs_bandwidth_start, b_symbol->srs_bandwidth_start); + EQ(a_symbol->sequence_group, b_symbol->sequence_group); + EQ(a_symbol->sequence_number, b_symbol->sequence_number); + } + +#ifdef ENABLE_AERIAL + // For Aerial, we always process the 4 reported symbols, not only the ones indicated by num_symbols + for (int symbol_idx = num_symbols; symbol_idx < 4; ++symbol_idx) { + const nfapi_v4_srs_parameters_symbols_t *a_symbol = &a->symbol_list[symbol_idx]; + const nfapi_v4_srs_parameters_symbols_t *b_symbol = &b->symbol_list[symbol_idx]; + EQ(a_symbol->srs_bandwidth_start, b_symbol->srs_bandwidth_start); + EQ(a_symbol->sequence_group, b_symbol->sequence_group); + EQ(a_symbol->sequence_number, b_symbol->sequence_number); + } +#endif // ENABLE_AERIAL + + EQ(a->usage, b->usage); + const uint8_t nUsage = __builtin_popcount(a->usage); + for (int idx = 0; idx < nUsage; ++idx) { + EQ(a->report_type[idx], b->report_type[idx]); + } + EQ(a->singular_Value_representation, b->singular_Value_representation); + EQ(a->iq_representation, b->iq_representation); + EQ(a->prg_size, b->prg_size); + EQ(a->num_total_ue_antennas, b->num_total_ue_antennas); + EQ(a->ue_antennas_in_this_srs_resource_set, b->ue_antennas_in_this_srs_resource_set); + EQ(a->sampled_ue_antennas, b->sampled_ue_antennas); + EQ(a->report_scope, b->report_scope); + EQ(a->num_ul_spatial_streams_ports, b->num_ul_spatial_streams_ports); + for (int idx = 0; idx < a->num_ul_spatial_streams_ports; ++idx) { + EQ(a->Ul_spatial_stream_ports[idx], b->Ul_spatial_stream_ports[idx]); + } + return true; +} + +static bool eq_ul_tti_request_srs_pdu(const nfapi_nr_srs_pdu_t *a, const nfapi_nr_srs_pdu_t *b) +{ + EQ(a->rnti, b->rnti); + EQ(a->handle, b->handle); + EQ(a->bwp_size, b->bwp_size); + EQ(a->bwp_start, b->bwp_start); + EQ(a->subcarrier_spacing, b->subcarrier_spacing); + EQ(a->cyclic_prefix, b->cyclic_prefix); + EQ(a->num_ant_ports, b->num_ant_ports); + EQ(a->num_symbols, b->num_symbols); + EQ(a->num_repetitions, b->num_repetitions); + EQ(a->time_start_position, b->time_start_position); + EQ(a->config_index, b->config_index); + EQ(a->sequence_id, b->sequence_id); + EQ(a->bandwidth_index, b->bandwidth_index); + EQ(a->comb_size, b->comb_size); + EQ(a->comb_offset, b->comb_offset); + EQ(a->cyclic_shift, b->cyclic_shift); + EQ(a->frequency_position, b->frequency_position); + EQ(a->frequency_shift, b->frequency_shift); + EQ(a->frequency_hopping, b->frequency_hopping); + EQ(a->group_or_sequence_hopping, b->group_or_sequence_hopping); + EQ(a->resource_type, b->resource_type); + EQ(a->t_srs, b->t_srs); + EQ(a->t_offset, b->t_offset); + EQ(eq_ul_tti_beamforming(&a->beamforming, &b->beamforming), true); + EQ(eq_ul_tti_request_srs_parameters(&a->srs_parameters_v4, 1 << a->num_symbols, &b->srs_parameters_v4), true); + return true; +} + +bool eq_ul_tti_request(const nfapi_nr_ul_tti_request_t *a, const nfapi_nr_ul_tti_request_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + + EQ(a->SFN, b->SFN); + EQ(a->Slot, b->Slot); + EQ(a->n_pdus, b->n_pdus); + EQ(a->rach_present, b->rach_present); + EQ(a->n_ulsch, b->n_ulsch); + EQ(a->n_ulcch, b->n_ulcch); + EQ(a->n_group, b->n_group); + + for (int PDU = 0; PDU < a->n_pdus; ++PDU) { + // take the PDU at the start of loops + const nfapi_nr_ul_tti_request_number_of_pdus_t *a_pdu = &a->pdus_list[PDU]; + const nfapi_nr_ul_tti_request_number_of_pdus_t *b_pdu = &b->pdus_list[PDU]; + + EQ(a_pdu->pdu_type, b_pdu->pdu_type); + EQ(a_pdu->pdu_size, b_pdu->pdu_size); + + switch (a_pdu->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + EQ(eq_ul_tti_request_prach_pdu(&a_pdu->prach_pdu, &b_pdu->prach_pdu), true); + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + EQ(eq_ul_tti_request_pusch_pdu(&a_pdu->pusch_pdu, &b_pdu->pusch_pdu), true); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + EQ(eq_ul_tti_request_pucch_pdu(&a_pdu->pucch_pdu, &b_pdu->pucch_pdu), true); + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + EQ(eq_ul_tti_request_srs_pdu(&a_pdu->srs_pdu, &b_pdu->srs_pdu), true); + break; + default: + // PDU Type is not any known value + return false; + } + } + + for (int nGroup = 0; nGroup < a->n_group; ++nGroup) { + EQ(a->groups_list[nGroup].n_ue, b->groups_list[nGroup].n_ue); + for (int UE = 0; UE < a->groups_list[nGroup].n_ue; ++UE) { + EQ(a->groups_list[nGroup].ue_list[UE].pdu_idx, b->groups_list[nGroup].ue_list[UE].pdu_idx); + } + } + return true; +} + +bool eq_slot_indication(const nfapi_nr_slot_indication_scf_t *a, const nfapi_nr_slot_indication_scf_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + + EQ(a->sfn, b->sfn); + EQ(a->slot, b->slot); + return true; +} + +bool eq_ul_dci_request_PDU(const nfapi_nr_ul_dci_request_pdus_t *a, const nfapi_nr_ul_dci_request_pdus_t *b) +{ + EQ(a->PDUType, b->PDUType); + EQ(a->PDUSize, b->PDUSize); + // Is the same PDU as the DL_TTI.request PDCCH PDU, reuse comparison function + EQ(eq_dl_tti_request_pdcch_pdu(&a->pdcch_pdu.pdcch_pdu_rel15, &b->pdcch_pdu.pdcch_pdu_rel15), true); + return true; +} + +bool eq_ul_dci_request(const nfapi_nr_ul_dci_request_t *a, const nfapi_nr_ul_dci_request_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + + EQ(a->SFN, b->SFN); + EQ(a->Slot, b->Slot); + EQ(a->numPdus, b->numPdus); + for (int pdu_idx = 0; pdu_idx < a->numPdus; ++pdu_idx) { + EQ(eq_ul_dci_request_PDU(&a->ul_dci_pdu_list[pdu_idx], &b->ul_dci_pdu_list[pdu_idx]), true); + } + return true; +} + +bool eq_tx_data_request_PDU(const nfapi_nr_pdu_t *a, const nfapi_nr_pdu_t *b) +{ + EQ(a->PDU_length, b->PDU_length); + EQ(a->PDU_index, b->PDU_index); + EQ(a->num_TLV, b->num_TLV); + for (int tlv_idx = 0; tlv_idx < a->num_TLV; ++tlv_idx) { + const nfapi_nr_tx_data_request_tlv_t *a_tlv = &a->TLVs[tlv_idx]; + const nfapi_nr_tx_data_request_tlv_t *b_tlv = &b->TLVs[tlv_idx]; + EQ(a_tlv->tag, b_tlv->tag); + EQ(a_tlv->length, b_tlv->length); + switch (a_tlv->tag) { + case 0: + for (int payload_idx = 0; payload_idx < (a_tlv->length + 3) / 4; ++payload_idx) { + // value.direct + EQ(a_tlv->value.direct[payload_idx], b_tlv->value.direct[payload_idx]); + } + break; + case 1: + for (int payload_idx = 0; payload_idx < (a_tlv->length + 3) / 4; ++payload_idx) { + // value.ptr + EQ(a_tlv->value.ptr[payload_idx], b_tlv->value.ptr[payload_idx]); + } + break; + default: + break; + } + } + return true; +} + +bool eq_tx_data_request(const nfapi_nr_tx_data_request_t *a, const nfapi_nr_tx_data_request_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + + EQ(a->SFN, b->SFN); + EQ(a->Slot, b->Slot); + EQ(a->Number_of_PDUs, b->Number_of_PDUs); + for (int pdu_idx = 0; pdu_idx < a->Number_of_PDUs; ++pdu_idx) { + EQ(eq_tx_data_request_PDU(&a->pdu_list[pdu_idx], &b->pdu_list[pdu_idx]), true); + } + return true; +} + +bool eq_rx_data_indication_PDU(const nfapi_nr_rx_data_pdu_t *a, const nfapi_nr_rx_data_pdu_t *b) +{ + EQ(a->handle, b->handle); + EQ(a->rnti, b->rnti); + EQ(a->harq_id, b->harq_id); + EQ(a->pdu_length, b->pdu_length); + EQ(a->ul_cqi, b->ul_cqi); + EQ(a->timing_advance, b->timing_advance); + EQ(a->rssi, b->rssi); + for (int i = 0; i < a->pdu_length; ++i) { + EQ(a->pdu[i], b->pdu[i]); + } + return true; +} + +bool eq_rx_data_indication(const nfapi_nr_rx_data_indication_t *a, const nfapi_nr_rx_data_indication_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + EQ(a->sfn, b->sfn); + EQ(a->slot, b->slot); + EQ(a->number_of_pdus, b->number_of_pdus); + for (int pdu_idx = 0; pdu_idx < a->number_of_pdus; ++pdu_idx) { + EQ(eq_rx_data_indication_PDU(&a->pdu_list[pdu_idx], &b->pdu_list[pdu_idx]), true); + } + return true; +} + +bool eq_crc_indication_CRC(const nfapi_nr_crc_t *a, const nfapi_nr_crc_t *b) +{ + EQ(a->handle, b->handle); + EQ(a->rnti, b->rnti); + EQ(a->harq_id, b->harq_id); + EQ(a->tb_crc_status, b->tb_crc_status); + EQ(a->num_cb, b->num_cb); + if (a->num_cb > 0) { + for (int cb = 0; cb < (a->num_cb / 8) + 1; ++cb) { + EQ(a->cb_crc_status[cb], b->cb_crc_status[cb]); + } + } + EQ(a->ul_cqi, b->ul_cqi); + EQ(a->timing_advance, b->timing_advance); + EQ(a->rssi, b->rssi); + return true; +} + +bool eq_crc_indication(const nfapi_nr_crc_indication_t *a, const nfapi_nr_crc_indication_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + EQ(a->sfn, b->sfn); + EQ(a->slot, b->slot); + EQ(a->number_crcs, b->number_crcs); + for (int crc_idx = 0; crc_idx < a->number_crcs; ++crc_idx) { + EQ(eq_crc_indication_CRC(&a->crc_list[crc_idx], &b->crc_list[crc_idx]), true); + } + return true; +} + +bool eq_uci_indication_sr_pdu_0_1(const nfapi_nr_sr_pdu_0_1_t *a, const nfapi_nr_sr_pdu_0_1_t *b) +{ + EQ(a->sr_indication, b->sr_indication); + EQ(a->sr_confidence_level, b->sr_confidence_level); + return true; +} + +bool eq_uci_indication_sr_pdu_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *a, const nfapi_nr_sr_pdu_2_3_4_t *b) +{ + EQ(a->sr_bit_len, b->sr_bit_len); + for (int i = 0; i < (a->sr_bit_len / 8) + 1; ++i) { + EQ(a->sr_payload[i], b->sr_payload[i]); + } + return true; +} + +bool eq_uci_indication_harq_pdu_0_1(const nfapi_nr_harq_pdu_0_1_t *a, const nfapi_nr_harq_pdu_0_1_t *b) +{ + EQ(a->num_harq, b->num_harq); + EQ(a->harq_confidence_level, b->harq_confidence_level); + for (int i = 0; i < a->num_harq; ++i) { + EQ(a->harq_list[i].harq_value, b->harq_list[i].harq_value); + } + return true; +} + +bool eq_uci_indication_harq_pdu_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *a, const nfapi_nr_harq_pdu_2_3_4_t *b) +{ + EQ(a->harq_crc, b->harq_crc); + EQ(a->harq_bit_len, b->harq_bit_len); + for (int i = 0; i < (a->harq_bit_len / 8) + 1; ++i) { + EQ(a->harq_payload[i], b->harq_payload[i]); + } + return true; +} + +bool eq_uci_indication_csi_part1(const nfapi_nr_csi_part1_pdu_t *a, const nfapi_nr_csi_part1_pdu_t *b) +{ + EQ(a->csi_part1_crc, b->csi_part1_crc); + EQ(a->csi_part1_bit_len, b->csi_part1_bit_len); + for (int i = 0; i < (a->csi_part1_bit_len / 8) + 1; ++i) { + EQ(a->csi_part1_payload[i], b->csi_part1_payload[i]); + } + return true; +} + +bool eq_uci_indication_csi_part2(const nfapi_nr_csi_part2_pdu_t *a, const nfapi_nr_csi_part2_pdu_t *b) +{ + EQ(a->csi_part2_crc, b->csi_part2_crc); + EQ(a->csi_part2_bit_len, b->csi_part2_bit_len); + for (int i = 0; i < (a->csi_part2_bit_len / 8) + 1; ++i) { + EQ(a->csi_part2_payload[i], b->csi_part2_payload[i]); + } + return true; +} + +bool eq_uci_indication_PUSCH(const nfapi_nr_uci_pusch_pdu_t *a, const nfapi_nr_uci_pusch_pdu_t *b) +{ + EQ(a->pduBitmap, b->pduBitmap); + EQ(a->handle, b->handle); + EQ(a->rnti, b->rnti); + EQ(a->ul_cqi, b->ul_cqi); + EQ(a->timing_advance, b->timing_advance); + EQ(a->rssi, b->rssi); + + // Bit 0 not used in PUSCH PDU + // HARQ + if ((a->pduBitmap >> 1) & 0x01) { + EQ(eq_uci_indication_harq_pdu_2_3_4(&a->harq, &b->harq), true); + } + // CSI Part 1 + if ((a->pduBitmap >> 2) & 0x01) { + EQ(eq_uci_indication_csi_part1(&a->csi_part1, &b->csi_part1), true); + } + // CSI Part 2 + if ((a->pduBitmap >> 3) & 0x01) { + EQ(eq_uci_indication_csi_part2(&a->csi_part2, &b->csi_part2), true); + } + return true; +} + +bool eq_uci_indication_PUCCH_0_1(const nfapi_nr_uci_pucch_pdu_format_0_1_t *a, const nfapi_nr_uci_pucch_pdu_format_0_1_t *b) +{ + EQ(a->pduBitmap, b->pduBitmap); + EQ(a->handle, b->handle); + EQ(a->rnti, b->rnti); + EQ(a->pucch_format, b->pucch_format); + EQ(a->ul_cqi, b->ul_cqi); + EQ(a->timing_advance, b->timing_advance); + EQ(a->rssi, b->rssi); + + // SR + if (a->pduBitmap & 0x01) { + EQ(eq_uci_indication_sr_pdu_0_1(&a->sr, &b->sr), true); + } + // HARQ + if ((a->pduBitmap >> 1) & 0x01) { + EQ(eq_uci_indication_harq_pdu_0_1(&a->harq, &b->harq), true); + } + return true; +} + +bool eq_uci_indication_PUCCH_2_3_4(const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *a, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *b) +{ + EQ(a->pduBitmap, b->pduBitmap); + EQ(a->handle, b->handle); + EQ(a->rnti, b->rnti); + EQ(a->pucch_format, b->pucch_format); + EQ(a->ul_cqi, b->ul_cqi); + EQ(a->timing_advance, b->timing_advance); + EQ(a->rssi, b->rssi); + // SR + if (a->pduBitmap & 0x01) { + EQ(eq_uci_indication_sr_pdu_2_3_4(&a->sr, &b->sr), true); + } + // HARQ + if ((a->pduBitmap >> 1) & 0x01) { + EQ(eq_uci_indication_harq_pdu_2_3_4(&a->harq, &b->harq), true); + } + // CSI Part 1 + if ((a->pduBitmap >> 2) & 0x01) { + EQ(eq_uci_indication_csi_part1(&a->csi_part1, &b->csi_part1), true); + } + // CSI Part 2 + if ((a->pduBitmap >> 3) & 0x01) { + EQ(eq_uci_indication_csi_part2(&a->csi_part2, &b->csi_part2), true); + } + return true; +} + +bool eq_uci_indication_UCI(const nfapi_nr_uci_t *a, const nfapi_nr_uci_t *b) +{ + EQ(a->pdu_type, b->pdu_type); + EQ(a->pdu_size, b->pdu_size); + switch (a->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + EQ(eq_uci_indication_PUSCH(&a->pusch_pdu, &b->pusch_pdu), true); + break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + EQ(eq_uci_indication_PUCCH_0_1(&a->pucch_pdu_format_0_1, &b->pucch_pdu_format_0_1), true); + break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + EQ(eq_uci_indication_PUCCH_2_3_4(&a->pucch_pdu_format_2_3_4, &b->pucch_pdu_format_2_3_4), true); + break; + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", a->pdu_type); + break; + } + return true; +} + +bool eq_uci_indication(const nfapi_nr_uci_indication_t *a, const nfapi_nr_uci_indication_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + EQ(a->sfn, b->sfn); + EQ(a->slot, b->slot); + EQ(a->num_ucis, b->num_ucis); + for (int crc_idx = 0; crc_idx < a->num_ucis; ++crc_idx) { + EQ(eq_uci_indication_UCI(&a->uci_list[crc_idx], &b->uci_list[crc_idx]), true); + } + return true; +} + +static bool eq_srs_indication_report_tlv(const nfapi_srs_report_tlv_t *a, const nfapi_srs_report_tlv_t *b) +{ + EQ(a->tag, b->tag); + EQ(a->length, b->length); + for (int i = 0; i < (a->length + 3) / 4; ++i) { + EQ(a->value[i], b->value[i]); + } + return true; +} + +static bool eq_srs_indication_PDU(const nfapi_nr_srs_indication_pdu_t *a, const nfapi_nr_srs_indication_pdu_t *b) +{ + EQ(a->handle, b->handle); + EQ(a->rnti, b->rnti); + EQ(a->timing_advance_offset, b->timing_advance_offset); + EQ(a->timing_advance_offset_nsec, b->timing_advance_offset_nsec); + EQ(a->srs_usage, b->srs_usage); + EQ(a->report_type, b->report_type); + EQ(eq_srs_indication_report_tlv(&a->report_tlv, &b->report_tlv), true); + return true; +} + +bool eq_srs_indication(const nfapi_nr_srs_indication_t *a, const nfapi_nr_srs_indication_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + EQ(a->sfn, b->sfn); + EQ(a->slot, b->slot); + EQ(a->control_length, b->control_length); + EQ(a->number_of_pdus, b->number_of_pdus); + for (int pdu_idx = 0; pdu_idx < a->number_of_pdus; ++pdu_idx) { + EQ(eq_srs_indication_PDU(&a->pdu_list[pdu_idx], &b->pdu_list[pdu_idx]), true); + } + return true; +} + +static bool eq_rach_indication_PDU(const nfapi_nr_prach_indication_pdu_t *a, const nfapi_nr_prach_indication_pdu_t *b) +{ + EQ(a->phy_cell_id, b->phy_cell_id); + EQ(a->symbol_index, b->symbol_index); + EQ(a->slot_index, b->slot_index); + EQ(a->freq_index, b->freq_index); + EQ(a->avg_rssi, b->avg_rssi); + EQ(a->avg_snr, b->avg_snr); + EQ(a->num_preamble, b->num_preamble); + for (int preamble_idx = 0; preamble_idx < a->num_preamble; ++preamble_idx) { + const nfapi_nr_prach_indication_preamble_t *a_pr = &a->preamble_list[preamble_idx]; + const nfapi_nr_prach_indication_preamble_t *b_pr = &b->preamble_list[preamble_idx]; + EQ(a_pr->preamble_index, b_pr->preamble_index); + EQ(a_pr->timing_advance, b_pr->timing_advance); + EQ(a_pr->preamble_pwr, b_pr->preamble_pwr); + } + return true; +} + +bool eq_rach_indication(const nfapi_nr_rach_indication_t *a, const nfapi_nr_rach_indication_t *b) +{ + EQ(a->header.message_id, b->header.message_id); + EQ(a->header.message_length, b->header.message_length); + EQ(a->sfn, b->sfn); + EQ(a->slot, b->slot); + EQ(a->number_of_pdus, b->number_of_pdus); + for (int pdu_idx = 0; pdu_idx < a->number_of_pdus; ++pdu_idx) { + EQ(eq_rach_indication_PDU(&a->pdu_list[pdu_idx], &b->pdu_list[pdu_idx]), true); + } + return true; +} + +void free_dl_tti_request(nfapi_nr_dl_tti_request_t *msg) +{ + if (msg->vendor_extension) { + free(msg->vendor_extension); + } +} + +void free_ul_tti_request(nfapi_nr_ul_tti_request_t *msg) +{ + for (int idx_pdu = 0; idx_pdu < msg->n_pdus; ++idx_pdu) { + nfapi_nr_ul_tti_request_number_of_pdus_t *pdu = &msg->pdus_list[idx_pdu]; + switch (pdu->pdu_type) { + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + free(pdu->pusch_pdu.pusch_ptrs.ptrs_ports_list); + break; + default: + break; + } + } +} + +void free_slot_indication(nfapi_nr_slot_indication_scf_t *msg) +{ + // Nothing to free +} + +void free_ul_dci_request(nfapi_nr_ul_dci_request_t *msg) +{ + // Nothing to free +} + +void free_tx_data_request(nfapi_nr_tx_data_request_t *msg) +{ + for (int pdu_idx = 0; pdu_idx < msg->Number_of_PDUs; ++pdu_idx) { + nfapi_nr_pdu_t *pdu = &msg->pdu_list[pdu_idx]; + for (int tlv_idx = 0; tlv_idx < pdu->num_TLV; ++tlv_idx) { + nfapi_nr_tx_data_request_tlv_t *tlv = &pdu->TLVs[tlv_idx]; + if (tlv->tag == 1) { + // value.ptr + free(tlv->value.ptr); + } + } + } +} + +void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) +{ + if (msg->number_of_pdus > 0) { + for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { + nfapi_nr_rx_data_pdu_t *rx_pdu = &msg->pdu_list[pdu_idx]; + if (rx_pdu->pdu) { + free(rx_pdu->pdu); + } + } + free(msg->pdu_list); + } +} + +void free_crc_indication(nfapi_nr_crc_indication_t *msg) +{ + if (msg->crc_list) { + for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { + nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; + if (crc->cb_crc_status) { + free(crc->cb_crc_status); + } + } + free(msg->crc_list); + } +} + +void free_uci_indication(nfapi_nr_uci_indication_t *msg) +{ + if (msg->uci_list) { + for (int pdu_idx = 0; pdu_idx < msg->num_ucis; ++pdu_idx) { + nfapi_nr_uci_t *uci_pdu = &msg->uci_list[pdu_idx]; + switch (uci_pdu->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { + nfapi_nr_uci_pusch_pdu_t *pdu = &uci_pdu->pusch_pdu; + // Bit 0 not used in PUSCH PDU + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + if (pdu->harq.harq_payload) { + free(pdu->harq.harq_payload); + } + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + if (pdu->csi_part1.csi_part1_payload) { + free(pdu->csi_part1.csi_part1_payload); + } + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + if (pdu->csi_part2.csi_part2_payload) { + free(pdu->csi_part2.csi_part2_payload); + } + } + break; + } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + // Nothing to free + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu = &uci_pdu->pucch_pdu_format_2_3_4; + // SR + if (pdu->pduBitmap & 0x01) { + if (pdu->sr.sr_payload) { + free(pdu->sr.sr_payload); + } + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + if (pdu->harq.harq_payload) { + free(pdu->harq.harq_payload); + } + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + if (pdu->csi_part1.csi_part1_payload) { + free(pdu->csi_part1.csi_part1_payload); + } + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + if (pdu->csi_part2.csi_part2_payload) { + free(pdu->csi_part2.csi_part2_payload); + } + } + break; + } + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); + break; + } + } + free(msg->uci_list); + } +} + +void free_srs_indication(nfapi_nr_srs_indication_t *msg) +{ + if (msg->pdu_list) { + free(msg->pdu_list); + } +} + +void free_rach_indication(nfapi_nr_rach_indication_t *msg) +{ + if (msg->pdu_list) { + free(msg->pdu_list); + } +} + +static void copy_dl_tti_beamforming(const nfapi_nr_tx_precoding_and_beamforming_t *src, + nfapi_nr_tx_precoding_and_beamforming_t *dst) +{ + dst->num_prgs = src->num_prgs; + dst->prg_size = src->prg_size; + dst->dig_bf_interfaces = src->dig_bf_interfaces; + for (int prg = 0; prg < dst->num_prgs; ++prg) { + dst->prgs_list[prg].pm_idx = src->prgs_list[prg].pm_idx; + for (int dbf_if = 0; dbf_if < dst->dig_bf_interfaces; ++dbf_if) { + dst->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx = src->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx; + } + } +} + +static void copy_dl_tti_request_pdcch_pdu(const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *src, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *dst) +{ + dst->BWPSize = src->BWPSize; + dst->BWPStart = src->BWPStart; + dst->SubcarrierSpacing = src->SubcarrierSpacing; + dst->CyclicPrefix = src->CyclicPrefix; + dst->StartSymbolIndex = src->StartSymbolIndex; + dst->DurationSymbols = src->DurationSymbols; + for (int fdr_idx = 0; fdr_idx < 6; ++fdr_idx) { + dst->FreqDomainResource[fdr_idx] = src->FreqDomainResource[fdr_idx]; + } + dst->CceRegMappingType = src->CceRegMappingType; + dst->RegBundleSize = src->RegBundleSize; + dst->InterleaverSize = src->InterleaverSize; + dst->CoreSetType = src->CoreSetType; + dst->ShiftIndex = src->ShiftIndex; + dst->precoderGranularity = src->precoderGranularity; + dst->numDlDci = src->numDlDci; + for (int dl_dci = 0; dl_dci < dst->numDlDci; ++dl_dci) { + nfapi_nr_dl_dci_pdu_t *dst_dci_pdu = &dst->dci_pdu[dl_dci]; + const nfapi_nr_dl_dci_pdu_t *src_dci_pdu = &src->dci_pdu[dl_dci]; + dst_dci_pdu->RNTI = src_dci_pdu->RNTI; + dst_dci_pdu->ScramblingId = src_dci_pdu->ScramblingId; + dst_dci_pdu->ScramblingRNTI = src_dci_pdu->ScramblingRNTI; + dst_dci_pdu->CceIndex = src_dci_pdu->CceIndex; + dst_dci_pdu->AggregationLevel = src_dci_pdu->AggregationLevel; + copy_dl_tti_beamforming(&src_dci_pdu->precodingAndBeamforming, &dst_dci_pdu->precodingAndBeamforming); + dst_dci_pdu->beta_PDCCH_1_0 = src_dci_pdu->beta_PDCCH_1_0; + dst_dci_pdu->powerControlOffsetSS = src_dci_pdu->powerControlOffsetSS; + dst_dci_pdu->PayloadSizeBits = src_dci_pdu->PayloadSizeBits; + for (int i = 0; i < 8; ++i) { + dst_dci_pdu->Payload[i] = src_dci_pdu->Payload[i]; + } + } +} + +static void copy_dl_tti_request_pdsch_pdu(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *src, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *dst) +{ + dst->pduBitmap = src->pduBitmap; + dst->rnti = src->rnti; + dst->pduIndex = src->pduIndex; + dst->BWPSize = src->BWPSize; + dst->BWPStart = src->BWPStart; + dst->SubcarrierSpacing = src->SubcarrierSpacing; + dst->CyclicPrefix = src->CyclicPrefix; + dst->NrOfCodewords = src->NrOfCodewords; + for (int cw = 0; cw < dst->NrOfCodewords; ++cw) { + dst->targetCodeRate[cw] = src->targetCodeRate[cw]; + dst->qamModOrder[cw] = src->qamModOrder[cw]; + dst->mcsIndex[cw] = src->mcsIndex[cw]; + dst->mcsTable[cw] = src->mcsTable[cw]; + dst->rvIndex[cw] = src->rvIndex[cw]; + dst->TBSize[cw] = src->TBSize[cw]; + } + dst->dataScramblingId = src->dataScramblingId; + dst->nrOfLayers = src->nrOfLayers; + dst->transmissionScheme = src->transmissionScheme; + dst->refPoint = src->refPoint; + dst->dlDmrsSymbPos = src->dlDmrsSymbPos; + dst->dmrsConfigType = src->dmrsConfigType; + dst->dlDmrsScramblingId = src->dlDmrsScramblingId; + dst->SCID = src->SCID; + dst->numDmrsCdmGrpsNoData = src->numDmrsCdmGrpsNoData; + dst->dmrsPorts = src->dmrsPorts; + dst->resourceAlloc = src->resourceAlloc; + for (int i = 0; i < 36; ++i) { + dst->rbBitmap[i] = src->rbBitmap[i]; + } + dst->rbStart = src->rbStart; + dst->rbSize = src->rbSize; + dst->VRBtoPRBMapping = src->VRBtoPRBMapping; + dst->StartSymbolIndex = src->StartSymbolIndex; + dst->NrOfSymbols = src->NrOfSymbols; + dst->PTRSPortIndex = src->PTRSPortIndex; + dst->PTRSTimeDensity = src->PTRSTimeDensity; + dst->PTRSFreqDensity = src->PTRSFreqDensity; + dst->PTRSReOffset = src->PTRSReOffset; + dst->nEpreRatioOfPDSCHToPTRS = src->nEpreRatioOfPDSCHToPTRS; + copy_dl_tti_beamforming(&src->precodingAndBeamforming, &dst->precodingAndBeamforming); + dst->powerControlOffset = src->powerControlOffset; + dst->powerControlOffsetSS = src->powerControlOffsetSS; + dst->isLastCbPresent = src->isLastCbPresent; + dst->isInlineTbCrc = src->isInlineTbCrc; + dst->dlTbCrc = src->dlTbCrc; + dst->maintenance_parms_v3.ldpcBaseGraph = src->maintenance_parms_v3.ldpcBaseGraph; + dst->maintenance_parms_v3.tbSizeLbrmBytes = src->maintenance_parms_v3.tbSizeLbrmBytes; +} + +static void copy_dl_tti_request_csi_rs_pdu(const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *src, nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *dst) +{ + dst->bwp_size = src->bwp_size; + dst->bwp_start = src->bwp_start; + dst->subcarrier_spacing = src->subcarrier_spacing; + dst->cyclic_prefix = src->cyclic_prefix; + dst->start_rb = src->start_rb; + dst->nr_of_rbs = src->nr_of_rbs; + dst->csi_type = src->csi_type; + dst->row = src->row; + dst->freq_domain = src->freq_domain; + dst->symb_l0 = src->symb_l0; + dst->symb_l1 = src->symb_l1; + dst->cdm_type = src->cdm_type; + dst->freq_density = src->freq_density; + dst->scramb_id = src->scramb_id; + dst->power_control_offset = src->power_control_offset; + dst->power_control_offset_ss = src->power_control_offset_ss; + copy_dl_tti_beamforming(&src->precodingAndBeamforming, &dst->precodingAndBeamforming); +} + +static void copy_dl_tti_request_ssb_pdu(const nfapi_nr_dl_tti_ssb_pdu_rel15_t *src, nfapi_nr_dl_tti_ssb_pdu_rel15_t *dst) +{ + dst->PhysCellId = src->PhysCellId; + dst->BetaPss = src->BetaPss; + dst->SsbBlockIndex = src->SsbBlockIndex; + dst->SsbSubcarrierOffset = src->SsbSubcarrierOffset; + dst->ssbOffsetPointA = src->ssbOffsetPointA; + dst->bchPayloadFlag = src->bchPayloadFlag; + dst->bchPayload = src->bchPayload; + dst->ssbRsrp = src->ssbRsrp; + copy_dl_tti_beamforming(&src->precoding_and_beamforming, &dst->precoding_and_beamforming); +} + +static void copy_dl_tti_request_pdu(const nfapi_nr_dl_tti_request_pdu_t *src, nfapi_nr_dl_tti_request_pdu_t *dst) +{ + dst->PDUType = src->PDUType; + dst->PDUSize = src->PDUSize; + + switch (dst->PDUType) { + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + copy_dl_tti_request_pdcch_pdu(&src->pdcch_pdu.pdcch_pdu_rel15, &dst->pdcch_pdu.pdcch_pdu_rel15); + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + copy_dl_tti_request_pdsch_pdu(&src->pdsch_pdu.pdsch_pdu_rel15, &dst->pdsch_pdu.pdsch_pdu_rel15); + break; + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + copy_dl_tti_request_csi_rs_pdu(&src->csi_rs_pdu.csi_rs_pdu_rel15, &dst->csi_rs_pdu.csi_rs_pdu_rel15); + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + copy_dl_tti_request_ssb_pdu(&src->ssb_pdu.ssb_pdu_rel15, &dst->ssb_pdu.ssb_pdu_rel15); + break; + default: + // PDU Type is not any known value + AssertFatal(1 == 0, "PDU Type value unknown, allowed values range from 0 to 3\n"); + } +} + +void copy_dl_tti_request(const nfapi_nr_dl_tti_request_t *src, nfapi_nr_dl_tti_request_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + if (src->vendor_extension) { + dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); + dst->vendor_extension->tag = src->vendor_extension->tag; + dst->vendor_extension->length = src->vendor_extension->length; + copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); + } + + dst->SFN = src->SFN; + dst->Slot = src->Slot; + dst->dl_tti_request_body.nPDUs = src->dl_tti_request_body.nPDUs; + dst->dl_tti_request_body.nGroup = src->dl_tti_request_body.nGroup; + for (int pdu = 0; pdu < dst->dl_tti_request_body.nPDUs; ++pdu) { + copy_dl_tti_request_pdu(&src->dl_tti_request_body.dl_tti_pdu_list[pdu], &dst->dl_tti_request_body.dl_tti_pdu_list[pdu]); + } + if (dst->dl_tti_request_body.nGroup > 0) { + for (int nGroup = 0; nGroup < dst->dl_tti_request_body.nGroup; ++nGroup) { + dst->dl_tti_request_body.nUe[nGroup] = src->dl_tti_request_body.nUe[nGroup]; + for (int UE = 0; UE < dst->dl_tti_request_body.nUe[nGroup]; ++UE) { + dst->dl_tti_request_body.PduIdx[nGroup][UE] = src->dl_tti_request_body.PduIdx[nGroup][UE]; + } + } + } +} + +static void copy_ul_tti_beamforming(const nfapi_nr_ul_beamforming_t *src, nfapi_nr_ul_beamforming_t *dst) +{ + dst->trp_scheme = src->trp_scheme; + dst->num_prgs = src->num_prgs; + dst->prg_size = src->prg_size; + dst->dig_bf_interface = src->dig_bf_interface; + + for (int prg = 0; prg < dst->num_prgs; ++prg) { + if (dst->dig_bf_interface > 0) { + for (int dbf_if = 0; dbf_if < dst->dig_bf_interface; ++dbf_if) { + dst->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx = src->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx; + } + } + } +} + +static void copy_ul_tti_request_prach_pdu(const nfapi_nr_prach_pdu_t *src, nfapi_nr_prach_pdu_t *dst) +{ + dst->phys_cell_id = src->phys_cell_id; + dst->num_prach_ocas = src->num_prach_ocas; + dst->prach_format = src->prach_format; + dst->num_ra = src->num_ra; + dst->prach_start_symbol = src->prach_start_symbol; + dst->num_cs = src->num_cs; + copy_ul_tti_beamforming(&src->beamforming, &dst->beamforming); +} + +static void copy_ul_tti_request_pusch_pdu(const nfapi_nr_pusch_pdu_t *src, nfapi_nr_pusch_pdu_t *dst) +{ + dst->pdu_bit_map = src->pdu_bit_map; + dst->rnti = src->rnti; + dst->handle = src->handle; + dst->bwp_size = src->bwp_size; + dst->bwp_start = src->bwp_start; + dst->subcarrier_spacing = src->subcarrier_spacing; + dst->cyclic_prefix = src->cyclic_prefix; + dst->target_code_rate = src->target_code_rate; + dst->qam_mod_order = src->qam_mod_order; + dst->mcs_index = src->mcs_index; + dst->mcs_table = src->mcs_table; + dst->transform_precoding = src->transform_precoding; + dst->data_scrambling_id = src->data_scrambling_id; + dst->nrOfLayers = src->nrOfLayers; + dst->ul_dmrs_symb_pos = src->ul_dmrs_symb_pos; + dst->dmrs_config_type = src->dmrs_config_type; + dst->ul_dmrs_scrambling_id = src->ul_dmrs_scrambling_id; + dst->pusch_identity = src->pusch_identity; + dst->scid = src->scid; + dst->num_dmrs_cdm_grps_no_data = src->num_dmrs_cdm_grps_no_data; + dst->dmrs_ports = src->dmrs_ports; + dst->resource_alloc = src->resource_alloc; + for (int i = 0; i < 36; ++i) { + dst->rb_bitmap[i] = src->rb_bitmap[i]; + } + dst->rb_start = src->rb_start; + dst->rb_size = src->rb_size; + dst->vrb_to_prb_mapping = src->vrb_to_prb_mapping; + dst->frequency_hopping = src->frequency_hopping; + dst->tx_direct_current_location = src->tx_direct_current_location; + dst->uplink_frequency_shift_7p5khz = src->uplink_frequency_shift_7p5khz; + dst->start_symbol_index = src->start_symbol_index; + dst->nr_of_symbols = src->nr_of_symbols; + + if (dst->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_DATA) { + const nfapi_nr_pusch_data_t *src_pusch_data = &src->pusch_data; + nfapi_nr_pusch_data_t *dst_pusch_data = &dst->pusch_data; + dst_pusch_data->rv_index = src_pusch_data->rv_index; + dst_pusch_data->harq_process_id = src_pusch_data->harq_process_id; + dst_pusch_data->new_data_indicator = src_pusch_data->new_data_indicator; + dst_pusch_data->tb_size = src_pusch_data->tb_size; + dst_pusch_data->num_cb = src_pusch_data->num_cb; + for (int i = 0; i < (src_pusch_data->num_cb + 7) / 8; ++i) { + dst_pusch_data->cb_present_and_position[i] = src_pusch_data->cb_present_and_position[i]; + } + } + if (src->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_UCI) { + const nfapi_nr_pusch_uci_t *src_pusch_uci = &src->pusch_uci; + nfapi_nr_pusch_uci_t *dst_pusch_uci = &dst->pusch_uci; + dst_pusch_uci->harq_ack_bit_length = src_pusch_uci->harq_ack_bit_length; + dst_pusch_uci->csi_part1_bit_length = src_pusch_uci->csi_part1_bit_length; + dst_pusch_uci->csi_part2_bit_length = src_pusch_uci->csi_part2_bit_length; + dst_pusch_uci->alpha_scaling = src_pusch_uci->alpha_scaling; + dst_pusch_uci->beta_offset_harq_ack = src_pusch_uci->beta_offset_harq_ack; + dst_pusch_uci->beta_offset_csi1 = src_pusch_uci->beta_offset_csi1; + dst_pusch_uci->beta_offset_csi2 = src_pusch_uci->beta_offset_csi2; + } + if (src->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + const nfapi_nr_pusch_ptrs_t *src_pusch_ptrs = &src->pusch_ptrs; + nfapi_nr_pusch_ptrs_t *dst_pusch_ptrs = &dst->pusch_ptrs; + + dst_pusch_ptrs->num_ptrs_ports = src_pusch_ptrs->num_ptrs_ports; + dst_pusch_ptrs->ptrs_ports_list = calloc(dst_pusch_ptrs->num_ptrs_ports, sizeof(nfapi_nr_ptrs_ports_t)); + for (int i = 0; i < src_pusch_ptrs->num_ptrs_ports; ++i) { + const nfapi_nr_ptrs_ports_t *src_ptrs_port = &src_pusch_ptrs->ptrs_ports_list[i]; + nfapi_nr_ptrs_ports_t *dst_ptrs_port = &dst_pusch_ptrs->ptrs_ports_list[i]; + + dst_ptrs_port->ptrs_port_index = src_ptrs_port->ptrs_port_index; + dst_ptrs_port->ptrs_dmrs_port = src_ptrs_port->ptrs_dmrs_port; + dst_ptrs_port->ptrs_re_offset = src_ptrs_port->ptrs_re_offset; + } + + dst_pusch_ptrs->ptrs_time_density = src_pusch_ptrs->ptrs_time_density; + dst_pusch_ptrs->ptrs_freq_density = src_pusch_ptrs->ptrs_freq_density; + dst_pusch_ptrs->ul_ptrs_power = src_pusch_ptrs->ul_ptrs_power; + } + if (src->pdu_bit_map & PUSCH_PDU_BITMAP_DFTS_OFDM) { + const nfapi_nr_dfts_ofdm_t *src_dfts_ofdm = &src->dfts_ofdm; + nfapi_nr_dfts_ofdm_t *dst_dfts_ofdm = &dst->dfts_ofdm; + + dst_dfts_ofdm->low_papr_group_number = src_dfts_ofdm->low_papr_group_number; + dst_dfts_ofdm->low_papr_sequence_number = src_dfts_ofdm->low_papr_sequence_number; + dst_dfts_ofdm->ul_ptrs_sample_density = src_dfts_ofdm->ul_ptrs_sample_density; + dst_dfts_ofdm->ul_ptrs_time_density_transform_precoding = src_dfts_ofdm->ul_ptrs_time_density_transform_precoding; + } + copy_ul_tti_beamforming(&src->beamforming, &dst->beamforming); + dst->maintenance_parms_v3.ldpcBaseGraph = src->maintenance_parms_v3.ldpcBaseGraph; + dst->maintenance_parms_v3.tbSizeLbrmBytes = src->maintenance_parms_v3.tbSizeLbrmBytes; +} + +static void copy_ul_tti_request_pucch_pdu(const nfapi_nr_pucch_pdu_t *src, nfapi_nr_pucch_pdu_t *dst) +{ + dst->rnti = src->rnti; + dst->handle = src->handle; + dst->bwp_size = src->bwp_size; + dst->bwp_start = src->bwp_start; + dst->subcarrier_spacing = src->subcarrier_spacing; + dst->cyclic_prefix = src->cyclic_prefix; + dst->format_type = src->format_type; + dst->multi_slot_tx_indicator = src->multi_slot_tx_indicator; + dst->pi_2bpsk = src->pi_2bpsk; + dst->prb_start = src->prb_start; + dst->prb_size = src->prb_size; + dst->start_symbol_index = src->start_symbol_index; + dst->nr_of_symbols = src->nr_of_symbols; + dst->freq_hop_flag = src->freq_hop_flag; + dst->second_hop_prb = src->second_hop_prb; + dst->group_hop_flag = src->group_hop_flag; + dst->sequence_hop_flag = src->sequence_hop_flag; + dst->hopping_id = src->hopping_id; + dst->initial_cyclic_shift = src->initial_cyclic_shift; + dst->data_scrambling_id = src->data_scrambling_id; + dst->time_domain_occ_idx = src->time_domain_occ_idx; + dst->pre_dft_occ_idx = src->pre_dft_occ_idx; + dst->pre_dft_occ_len = src->pre_dft_occ_len; + dst->add_dmrs_flag = src->add_dmrs_flag; + dst->dmrs_scrambling_id = src->dmrs_scrambling_id; + dst->dmrs_cyclic_shift = src->dmrs_cyclic_shift; + dst->sr_flag = src->sr_flag; + dst->bit_len_harq = src->bit_len_harq; + dst->bit_len_csi_part1 = src->bit_len_csi_part1; + dst->bit_len_csi_part2 = src->bit_len_csi_part2; + copy_ul_tti_beamforming(&src->beamforming, &dst->beamforming); +} + +static void copy_ul_tti_request_srs_parameters(const nfapi_v4_srs_parameters_t *src, + const uint8_t num_symbols, + nfapi_v4_srs_parameters_t *dst) +{ + dst->srs_bandwidth_size = src->srs_bandwidth_size; + for (int symbol_idx = 0; symbol_idx < num_symbols; ++symbol_idx) { + nfapi_v4_srs_parameters_symbols_t *dst_symbol = &dst->symbol_list[symbol_idx]; + const nfapi_v4_srs_parameters_symbols_t *src_symbol = &src->symbol_list[symbol_idx]; + dst_symbol->srs_bandwidth_start = src_symbol->srs_bandwidth_start; + dst_symbol->sequence_group = src_symbol->sequence_group; + dst_symbol->sequence_number = src_symbol->sequence_number; + } + +#ifdef ENABLE_AERIAL + // For Aerial, we always process the 4 reported symbols, not only the ones indicated by num_symbols + for (int symbol_idx = num_symbols; symbol_idx < 4; ++symbol_idx) { + nfapi_v4_srs_parameters_symbols_t *dst_symbol = &dst->symbol_list[symbol_idx]; + const nfapi_v4_srs_parameters_symbols_t *src_symbol = &src->symbol_list[symbol_idx]; + dst_symbol->srs_bandwidth_start = src_symbol->srs_bandwidth_start; + dst_symbol->sequence_group = src_symbol->sequence_group; + dst_symbol->sequence_number = src_symbol->sequence_number; + } +#endif // ENABLE_AERIAL + dst->usage = src->usage; + const uint8_t nUsage = __builtin_popcount(dst->usage); + for (int idx = 0; idx < nUsage; ++idx) { + dst->report_type[idx] = src->report_type[idx]; + } + dst->singular_Value_representation = src->singular_Value_representation; + dst->iq_representation = src->iq_representation; + dst->prg_size = src->prg_size; + dst->num_total_ue_antennas = src->num_total_ue_antennas; + dst->ue_antennas_in_this_srs_resource_set = src->ue_antennas_in_this_srs_resource_set; + dst->sampled_ue_antennas = src->sampled_ue_antennas; + dst->report_scope = src->report_scope; + dst->num_ul_spatial_streams_ports = src->num_ul_spatial_streams_ports; + for (int idx = 0; idx < dst->num_ul_spatial_streams_ports; ++idx) { + dst->Ul_spatial_stream_ports[idx] = src->Ul_spatial_stream_ports[idx]; + } +} + +static void copy_ul_tti_request_srs_pdu(const nfapi_nr_srs_pdu_t *src, nfapi_nr_srs_pdu_t *dst) +{ + dst->rnti = src->rnti; + dst->handle = src->handle; + dst->bwp_size = src->bwp_size; + dst->bwp_start = src->bwp_start; + dst->subcarrier_spacing = src->subcarrier_spacing; + dst->cyclic_prefix = src->cyclic_prefix; + dst->num_ant_ports = src->num_ant_ports; + dst->num_symbols = src->num_symbols; + dst->num_repetitions = src->num_repetitions; + dst->time_start_position = src->time_start_position; + dst->config_index = src->config_index; + dst->sequence_id = src->sequence_id; + dst->bandwidth_index = src->bandwidth_index; + dst->comb_size = src->comb_size; + dst->comb_offset = src->comb_offset; + dst->cyclic_shift = src->cyclic_shift; + dst->frequency_position = src->frequency_position; + dst->frequency_shift = src->frequency_shift; + dst->frequency_hopping = src->frequency_hopping; + dst->group_or_sequence_hopping = src->group_or_sequence_hopping; + dst->resource_type = src->resource_type; + dst->t_srs = src->t_srs; + dst->t_offset = src->t_offset; + copy_ul_tti_beamforming(&src->beamforming, &dst->beamforming); + copy_ul_tti_request_srs_parameters(&src->srs_parameters_v4, 1 << src->num_symbols, &dst->srs_parameters_v4); +} + +void copy_ul_tti_request(const nfapi_nr_ul_tti_request_t *src, nfapi_nr_ul_tti_request_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + + dst->SFN = src->SFN; + dst->Slot = src->Slot; + dst->n_pdus = src->n_pdus; + dst->rach_present = src->rach_present; + dst->n_ulsch = src->n_ulsch; + dst->n_ulcch = src->n_ulcch; + dst->n_group = src->n_group; + + for (int PDU = 0; PDU < src->n_pdus; ++PDU) { + // take the PDU at the start of loops + const nfapi_nr_ul_tti_request_number_of_pdus_t *src_pdu = &src->pdus_list[PDU]; + nfapi_nr_ul_tti_request_number_of_pdus_t *dst_pdu = &dst->pdus_list[PDU]; + + dst_pdu->pdu_type = src_pdu->pdu_type; + dst_pdu->pdu_size = src_pdu->pdu_size; + + switch (src_pdu->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + copy_ul_tti_request_prach_pdu(&src_pdu->prach_pdu, &dst_pdu->prach_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + copy_ul_tti_request_pusch_pdu(&src_pdu->pusch_pdu, &dst_pdu->pusch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + copy_ul_tti_request_pucch_pdu(&src_pdu->pucch_pdu, &dst_pdu->pucch_pdu); + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + copy_ul_tti_request_srs_pdu(&src_pdu->srs_pdu, &dst_pdu->srs_pdu); + break; + default: + // PDU Type is not any known value + AssertFatal(1 == 0, "PDU Type value unknown, allowed values range from 0 to 3\n"); + } + } + + for (int nGroup = 0; nGroup < src->n_group; ++nGroup) { + dst->groups_list[nGroup].n_ue = src->groups_list[nGroup].n_ue; + for (int UE = 0; UE < src->groups_list[nGroup].n_ue; ++UE) { + dst->groups_list[nGroup].ue_list[UE].pdu_idx = src->groups_list[nGroup].ue_list[UE].pdu_idx; + } + } +} + +void copy_slot_indication(const nfapi_nr_slot_indication_scf_t *src, nfapi_nr_slot_indication_scf_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + + dst->sfn = src->sfn; + dst->slot = src->slot; +} + +void copy_ul_dci_request_pdu(const nfapi_nr_ul_dci_request_pdus_t *src, nfapi_nr_ul_dci_request_pdus_t *dst) +{ + dst->PDUType = src->PDUType; + dst->PDUSize = src->PDUSize; + + // Is the same PDU as the DL_TTI.request PDCCH PDU, reuse copy function + copy_dl_tti_request_pdcch_pdu(&src->pdcch_pdu.pdcch_pdu_rel15, &dst->pdcch_pdu.pdcch_pdu_rel15); +} + +void copy_ul_dci_request(const nfapi_nr_ul_dci_request_t *src, nfapi_nr_ul_dci_request_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + + dst->SFN = src->SFN; + dst->Slot = src->Slot; + dst->numPdus = src->numPdus; + + for (int pdu_idx = 0; pdu_idx < src->numPdus; ++pdu_idx) { + copy_ul_dci_request_pdu(&src->ul_dci_pdu_list[pdu_idx], &dst->ul_dci_pdu_list[pdu_idx]); + } +} + +void copy_tx_data_request_PDU(const nfapi_nr_pdu_t *src, nfapi_nr_pdu_t *dst) +{ + dst->PDU_length = src->PDU_length; + dst->PDU_index = src->PDU_index; + dst->num_TLV = src->num_TLV; + for (int tlv_idx = 0; tlv_idx < src->num_TLV; ++tlv_idx) { + const nfapi_nr_tx_data_request_tlv_t *src_tlv = &src->TLVs[tlv_idx]; + nfapi_nr_tx_data_request_tlv_t *dst_tlv = &dst->TLVs[tlv_idx]; + dst_tlv->tag = src_tlv->tag; + dst_tlv->length = src_tlv->length; + switch (src_tlv->tag) { + case 0: + // value.direct + memcpy(dst_tlv->value.direct, src_tlv->value.direct, sizeof(src_tlv->value.direct)); + break; + case 1: + // value.ptr + dst_tlv->value.ptr = calloc((src_tlv->length + 3) / 4, sizeof(uint32_t)); + memcpy(dst_tlv->value.ptr, src_tlv->value.ptr, src_tlv->length); + break; + default: + AssertFatal(1 == 0, "TX_DATA request TLV tag value unsupported"); + break; + } + } +} + +void copy_tx_data_request(const nfapi_nr_tx_data_request_t *src, nfapi_nr_tx_data_request_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + + dst->SFN = src->SFN; + dst->Slot = src->Slot; + dst->Number_of_PDUs = src->Number_of_PDUs; + for (int pdu_idx = 0; pdu_idx < src->Number_of_PDUs; ++pdu_idx) { + copy_tx_data_request_PDU(&src->pdu_list[pdu_idx], &dst->pdu_list[pdu_idx]); + } +} + +size_t get_tx_data_request_size(const nfapi_nr_tx_data_request_t *msg) +{ + // Get size of the whole message ( allocated pointer included ) + size_t total_size = sizeof(msg->header); + total_size += sizeof(msg->SFN); + total_size += sizeof(msg->Slot); + total_size += sizeof(msg->Number_of_PDUs); + for (int pdu_idx = 0; pdu_idx < msg->Number_of_PDUs; ++pdu_idx) { + const nfapi_nr_pdu_t *pdu = &msg->pdu_list[pdu_idx]; + total_size += sizeof(pdu->PDU_length); + total_size += sizeof(pdu->PDU_index); + total_size += sizeof(pdu->num_TLV); + for (int tlv_idx = 0; tlv_idx < pdu->num_TLV; ++tlv_idx) { + const nfapi_nr_tx_data_request_tlv_t *tlv = &pdu->TLVs[tlv_idx]; + total_size += sizeof(tlv->tag); + total_size += sizeof(tlv->length); + if (tlv->tag == 0) { + total_size += sizeof(tlv->value.direct); + } else { + total_size += (tlv->length + 3) / 4 * sizeof(uint32_t); + } + } + } + return total_size; +} + +void copy_rx_data_indication_PDU(const nfapi_nr_rx_data_pdu_t *src, nfapi_nr_rx_data_pdu_t *dst) +{ + dst->handle = src->handle; + dst->rnti = src->rnti; + dst->harq_id = src->harq_id; + dst->pdu_length = src->pdu_length; + dst->ul_cqi = src->ul_cqi; + dst->timing_advance = src->timing_advance; + dst->rssi = src->rssi; + dst->pdu = calloc(dst->pdu_length, sizeof(uint8_t)); + memcpy(dst->pdu, src->pdu, src->pdu_length); +} + +void copy_rx_data_indication(const nfapi_nr_rx_data_indication_t *src, nfapi_nr_rx_data_indication_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + + dst->sfn = src->sfn; + dst->slot = src->slot; + dst->number_of_pdus = src->number_of_pdus; + dst->pdu_list = calloc(dst->number_of_pdus, sizeof(*dst->pdu_list)); + for (int pdu_idx = 0; pdu_idx < src->number_of_pdus; ++pdu_idx) { + copy_rx_data_indication_PDU(&src->pdu_list[pdu_idx], &dst->pdu_list[pdu_idx]); + } +} + +size_t get_rx_data_indication_size(const nfapi_nr_rx_data_indication_t *msg) +{ + // Get size of the whole message ( allocated pointer included ) + size_t total_size = sizeof(msg->header); + total_size += sizeof(msg->sfn); + total_size += sizeof(msg->slot); + total_size += sizeof(msg->number_of_pdus); + for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { + const nfapi_nr_rx_data_pdu_t *pdu = &msg->pdu_list[pdu_idx]; + total_size += sizeof(pdu->handle); + total_size += sizeof(pdu->rnti); + total_size += sizeof(pdu->harq_id); + total_size += sizeof(pdu->pdu_length); + total_size += sizeof(pdu->ul_cqi); + total_size += sizeof(pdu->timing_advance); + total_size += sizeof(pdu->rssi); + total_size += pdu->pdu_length; + } + return total_size; +} + +void copy_crc_indication_CRC(const nfapi_nr_crc_t *src, nfapi_nr_crc_t *dst) +{ + dst->handle = src->handle; + dst->rnti = src->rnti; + dst->harq_id = src->harq_id; + dst->tb_crc_status = src->tb_crc_status; + dst->num_cb = src->num_cb; + if (dst->num_cb > 0) { + const uint16_t cb_len = (dst->num_cb / 8) + 1; + dst->cb_crc_status = calloc(cb_len, sizeof(uint8_t)); + for (int cb = 0; cb < cb_len; ++cb) { + dst->cb_crc_status[cb] = src->cb_crc_status[cb]; + } + } + dst->ul_cqi = src->ul_cqi; + dst->timing_advance = src->timing_advance; + dst->rssi = src->rssi; +} + +void copy_crc_indication(const nfapi_nr_crc_indication_t *src, nfapi_nr_crc_indication_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + + dst->sfn = src->sfn; + dst->slot = src->slot; + dst->number_crcs = src->number_crcs; + dst->crc_list = calloc(dst->number_crcs, sizeof(*dst->crc_list)); + for (int crc_idx = 0; crc_idx < src->number_crcs; ++crc_idx) { + copy_crc_indication_CRC(&src->crc_list[crc_idx], &dst->crc_list[crc_idx]); + } +} + +size_t get_crc_indication_size(const nfapi_nr_crc_indication_t *msg) +{ + // Get size of the whole message ( allocated pointer included ) + size_t total_size = sizeof(msg->header); + total_size += sizeof(msg->sfn); + total_size += sizeof(msg->slot); + total_size += sizeof(msg->number_crcs); + for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { + const nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; + total_size += sizeof(crc->handle); + total_size += sizeof(crc->rnti); + total_size += sizeof(crc->harq_id); + total_size += sizeof(crc->tb_crc_status); + total_size += sizeof(crc->num_cb); + if (crc->num_cb > 0) { + total_size += crc->num_cb / 8 + 1; + } + total_size += sizeof(crc->ul_cqi); + total_size += sizeof(crc->timing_advance); + total_size += sizeof(crc->rssi); + } + return total_size; +} + +void copy_uci_indication_sr_pdu_0_1(const nfapi_nr_sr_pdu_0_1_t *src, nfapi_nr_sr_pdu_0_1_t *dst) +{ + dst->sr_indication = src->sr_indication; + dst->sr_confidence_level = src->sr_confidence_level; +} + +void copy_uci_indication_sr_pdu_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *src, nfapi_nr_sr_pdu_2_3_4_t *dst) +{ + dst->sr_bit_len = src->sr_bit_len; + const uint16_t sr_len = (dst->sr_bit_len / 8) + 1; + dst->sr_payload = calloc(sr_len, sizeof(*dst->sr_payload)); + for (int i = 0; i < sr_len; ++i) { + dst->sr_payload[i] = src->sr_payload[i]; + } +} + +void copy_uci_indication_harq_pdu_0_1(const nfapi_nr_harq_pdu_0_1_t *src, nfapi_nr_harq_pdu_0_1_t *dst) +{ + dst->num_harq = src->num_harq; + dst->harq_confidence_level = src->harq_confidence_level; + for (int i = 0; i < dst->num_harq; ++i) { + dst->harq_list[i].harq_value = src->harq_list[i].harq_value; + } +} + +void copy_uci_indication_harq_pdu_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *src, nfapi_nr_harq_pdu_2_3_4_t *dst) +{ + dst->harq_crc = src->harq_crc; + dst->harq_bit_len = src->harq_bit_len; + const uint16_t harq_length = (dst->harq_bit_len / 8) + 1; + dst->harq_payload = calloc(harq_length, sizeof(*dst->harq_payload)); + for (int i = 0; i < harq_length; ++i) { + dst->harq_payload[i] = src->harq_payload[i]; + } +} + +void copy_uci_indication_csi_part1(const nfapi_nr_csi_part1_pdu_t *src, nfapi_nr_csi_part1_pdu_t *dst) +{ + dst->csi_part1_crc = src->csi_part1_crc; + dst->csi_part1_bit_len = src->csi_part1_bit_len; + const uint16_t payload_length = (dst->csi_part1_bit_len / 8) + 1; + dst->csi_part1_payload = calloc(payload_length, sizeof(*dst->csi_part1_payload)); + for (int i = 0; i < payload_length; ++i) { + dst->csi_part1_payload[i] = src->csi_part1_payload[i]; + } +} + +void copy_uci_indication_csi_part2(const nfapi_nr_csi_part2_pdu_t *src, nfapi_nr_csi_part2_pdu_t *dst) +{ + dst->csi_part2_crc = src->csi_part2_crc; + dst->csi_part2_bit_len = src->csi_part2_bit_len; + const uint16_t payload_length = (dst->csi_part2_bit_len / 8) + 1; + dst->csi_part2_payload = calloc(payload_length, sizeof(*dst->csi_part2_payload)); + for (int i = 0; i < payload_length; ++i) { + dst->csi_part2_payload[i] = src->csi_part2_payload[i]; + } +} + +void copy_uci_indication_PUSCH(const nfapi_nr_uci_pusch_pdu_t *src, nfapi_nr_uci_pusch_pdu_t *dst) +{ + dst->pduBitmap = src->pduBitmap; + dst->handle = src->handle; + dst->rnti = src->rnti; + dst->ul_cqi = src->ul_cqi; + dst->timing_advance = src->timing_advance; + dst->rssi = src->rssi; + + // Bit 0 not used in PUSCH PDU + // HARQ + if ((dst->pduBitmap >> 1) & 0x01) { + copy_uci_indication_harq_pdu_2_3_4(&src->harq, &dst->harq); + } + // CSI Part 1 + if ((dst->pduBitmap >> 2) & 0x01) { + copy_uci_indication_csi_part1(&src->csi_part1, &dst->csi_part1); + } + // CSI Part 2 + if ((dst->pduBitmap >> 3) & 0x01) { + copy_uci_indication_csi_part2(&src->csi_part2, &dst->csi_part2); + } +} + +void copy_uci_indication_PUCCH_0_1(const nfapi_nr_uci_pucch_pdu_format_0_1_t *src, nfapi_nr_uci_pucch_pdu_format_0_1_t *dst) +{ + dst->pduBitmap = src->pduBitmap; + dst->handle = src->handle; + dst->rnti = src->rnti; + dst->pucch_format = src->pucch_format; + dst->ul_cqi = src->ul_cqi; + dst->timing_advance = src->timing_advance; + dst->rssi = src->rssi; + + // SR + if (dst->pduBitmap & 0x01) { + copy_uci_indication_sr_pdu_0_1(&src->sr, &dst->sr); + } + // HARQ + if ((dst->pduBitmap >> 1) & 0x01) { + copy_uci_indication_harq_pdu_0_1(&src->harq, &dst->harq); + } +} + +void copy_uci_indication_PUCCH_2_3_4(const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *src, nfapi_nr_uci_pucch_pdu_format_2_3_4_t *dst) +{ + dst->pduBitmap = src->pduBitmap; + dst->handle = src->handle; + dst->rnti = src->rnti; + dst->pucch_format = src->pucch_format; + dst->ul_cqi = src->ul_cqi; + dst->timing_advance = src->timing_advance; + dst->rssi = src->rssi; + // SR + if (dst->pduBitmap & 0x01) { + copy_uci_indication_sr_pdu_2_3_4(&src->sr, &dst->sr); + } + // HARQ + if ((dst->pduBitmap >> 1) & 0x01) { + copy_uci_indication_harq_pdu_2_3_4(&src->harq, &dst->harq); + } + // CSI Part 1 + if ((dst->pduBitmap >> 2) & 0x01) { + copy_uci_indication_csi_part1(&src->csi_part1, &dst->csi_part1); + } + // CSI Part 2 + if ((dst->pduBitmap >> 3) & 0x01) { + copy_uci_indication_csi_part2(&src->csi_part2, &dst->csi_part2); + } +} + +void copy_uci_indication_UCI(const nfapi_nr_uci_t *src, nfapi_nr_uci_t *dst) +{ + dst->pdu_type = src->pdu_type; + dst->pdu_size = src->pdu_size; + switch (dst->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + copy_uci_indication_PUSCH(&src->pusch_pdu, &dst->pusch_pdu); + break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + copy_uci_indication_PUCCH_0_1(&src->pucch_pdu_format_0_1, &dst->pucch_pdu_format_0_1); + break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + copy_uci_indication_PUCCH_2_3_4(&src->pucch_pdu_format_2_3_4, &dst->pucch_pdu_format_2_3_4); + break; + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", src->pdu_type); + break; + } +} + +void copy_uci_indication(const nfapi_nr_uci_indication_t *src, nfapi_nr_uci_indication_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + dst->sfn = src->sfn; + dst->slot = src->slot; + dst->num_ucis = src->num_ucis; + dst->uci_list = calloc(dst->num_ucis, sizeof(*dst->uci_list)); + for (int crc_idx = 0; crc_idx < src->num_ucis; ++crc_idx) { + copy_uci_indication_UCI(&src->uci_list[crc_idx], &dst->uci_list[crc_idx]); + } +} + +size_t get_uci_indication_size(const nfapi_nr_uci_indication_t *msg) +{ + // Get size of the message (allocated pointer included) + size_t total_size = 0; + + // Header and fixed-size fields + total_size += sizeof(msg->header); + total_size += sizeof(msg->sfn); + total_size += sizeof(msg->slot); + total_size += sizeof(msg->num_ucis); + + // Loop through each UCI in the uci_list + for (int uci_idx = 0; uci_idx < msg->num_ucis; ++uci_idx) { + const nfapi_nr_uci_t *uci_pdu = &msg->uci_list[uci_idx]; + + total_size += sizeof(uci_pdu->pdu_type); + total_size += sizeof(uci_pdu->pdu_size); + + switch (uci_pdu->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + total_size += sizeof(uci_pdu->pusch_pdu); + + // HARQ payload, CSI Part 1 and 2 are conditionally allocated + if ((uci_pdu->pusch_pdu.pduBitmap >> 1) & 0x01) { + total_size += uci_pdu->pusch_pdu.harq.harq_bit_len / 8 + 1; + } + if ((uci_pdu->pusch_pdu.pduBitmap >> 2) & 0x01) { + total_size += uci_pdu->pusch_pdu.csi_part1.csi_part1_bit_len / 8 + 1; + } + if ((uci_pdu->pusch_pdu.pduBitmap >> 3) & 0x01) { + total_size += uci_pdu->pusch_pdu.csi_part2.csi_part2_bit_len / 8 + 1; + } + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + total_size += sizeof(uci_pdu->pucch_pdu_format_0_1); + // SR and HARQ are conditionally filled, but neither require calloc inside + break; + + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + total_size += sizeof(uci_pdu->pucch_pdu_format_2_3_4); + + // SR, HARQ, CSI Part 1, and CSI Part 2 are conditionally allocated + if (uci_pdu->pucch_pdu_format_2_3_4.pduBitmap & 0x01) { + total_size += uci_pdu->pucch_pdu_format_2_3_4.sr.sr_bit_len / 8 + 1; + } + if ((uci_pdu->pucch_pdu_format_2_3_4.pduBitmap >> 1) & 0x01) { + total_size += uci_pdu->pucch_pdu_format_2_3_4.harq.harq_bit_len / 8 + 1; + } + if ((uci_pdu->pucch_pdu_format_2_3_4.pduBitmap >> 2) & 0x01) { + total_size += uci_pdu->pucch_pdu_format_2_3_4.csi_part1.csi_part1_bit_len / 8 + 1; + } + if ((uci_pdu->pucch_pdu_format_2_3_4.pduBitmap >> 3) & 0x01) { + total_size += uci_pdu->pucch_pdu_format_2_3_4.csi_part2.csi_part2_bit_len / 8 + 1; + } + break; + + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); + break; + } + } + + // Finally, add the size of the uci_list pointer itself + total_size += msg->num_ucis * sizeof(*msg->uci_list); + + return total_size; +} + +void copy_srs_indication_report_tlv(const nfapi_srs_report_tlv_t *src, nfapi_srs_report_tlv_t *dst) +{ + dst->tag = src->tag; + dst->length = src->length; + for (int i = 0; i < (dst->length + 3) / 4; ++i) { + dst->value[i] = src->value[i]; + } +} + +void copy_srs_indication_PDU(const nfapi_nr_srs_indication_pdu_t *src, nfapi_nr_srs_indication_pdu_t *dst) +{ + dst->handle = src->handle; + dst->rnti = src->rnti; + dst->timing_advance_offset = src->timing_advance_offset; + dst->timing_advance_offset_nsec = src->timing_advance_offset_nsec; + dst->srs_usage = src->srs_usage; + dst->report_type = src->report_type; + copy_srs_indication_report_tlv(&src->report_tlv, &dst->report_tlv); +} + +void copy_srs_indication(const nfapi_nr_srs_indication_t *src, nfapi_nr_srs_indication_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + dst->sfn = src->sfn; + dst->slot = src->slot; + dst->control_length = src->control_length; + dst->number_of_pdus = src->number_of_pdus; + dst->pdu_list = calloc(dst->number_of_pdus, sizeof(*dst->pdu_list)); + for (int pdu_idx = 0; pdu_idx < src->number_of_pdus; ++pdu_idx) { + copy_srs_indication_PDU(&src->pdu_list[pdu_idx], &dst->pdu_list[pdu_idx]); + } +} + +size_t get_srs_indication_size(const nfapi_nr_srs_indication_t *msg) +{ + // Get size of the message (allocated pointer included) + size_t total_size = 0; + + // Header and fixed-size fields + total_size += sizeof(msg->header); + total_size += sizeof(msg->sfn); + total_size += sizeof(msg->slot); + total_size += sizeof(msg->control_length); + total_size += sizeof(msg->number_of_pdus); + total_size += msg->number_of_pdus * sizeof(*msg->pdu_list); + + return total_size; +} + +static void copy_rach_indication_PDU(const nfapi_nr_prach_indication_pdu_t *src, nfapi_nr_prach_indication_pdu_t *dst) +{ + dst->phy_cell_id = src->phy_cell_id; + dst->symbol_index = src->symbol_index; + dst->slot_index = src->slot_index; + dst->freq_index = src->freq_index; + dst->avg_rssi = src->avg_rssi; + dst->avg_snr = src->avg_snr; + dst->num_preamble = src->num_preamble; + for (int preamble_idx = 0; preamble_idx < dst->num_preamble; ++preamble_idx) { + nfapi_nr_prach_indication_preamble_t *dst_pr = &dst->preamble_list[preamble_idx]; + const nfapi_nr_prach_indication_preamble_t *src_pr = &src->preamble_list[preamble_idx]; + dst_pr->preamble_index = src_pr->preamble_index; + dst_pr->timing_advance = src_pr->timing_advance; + dst_pr->preamble_pwr = src_pr->preamble_pwr; + } +} + +void copy_rach_indication(const nfapi_nr_rach_indication_t *src, nfapi_nr_rach_indication_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + dst->sfn = src->sfn; + dst->slot = src->slot; + dst->number_of_pdus = src->number_of_pdus; + dst->pdu_list = calloc(dst->number_of_pdus, sizeof(*dst->pdu_list)); + for (int pdu_idx = 0; pdu_idx < dst->number_of_pdus; ++pdu_idx) { + copy_rach_indication_PDU(&src->pdu_list[pdu_idx], &dst->pdu_list[pdu_idx]); + } +} + +size_t get_rach_indication_size(nfapi_nr_rach_indication_t *msg) +{ + // Get size of the message (allocated pointer included) + size_t total_size = 0; + + // Header and fixed-size fields + total_size += sizeof(msg->header); + total_size += sizeof(msg->sfn); + total_size += sizeof(msg->slot); + total_size += sizeof(msg->number_of_pdus); + total_size += msg->number_of_pdus * sizeof(*msg->pdu_list); + + return total_size; +} diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_common_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_common_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..fa3b9316a62dafb1a82bb1e2847793665a56e2eb --- /dev/null +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_common_interface.h @@ -0,0 +1,197 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef NFAPI_COMMON_INTERFACE_H +#define NFAPI_COMMON_INTERFACE_H + +typedef struct { + uint16_t tag; + uint16_t length; +} nfapi_tl_t; + +/*! Configuration options for the p7 pack unpack functions + * + */ + +typedef struct nfapi_p7_codec_config { + /*! Optional call back to allow the user to define the memory allocator. + * \param size The size of the memory to allocate + * \return a pointer to a valid memory block or 0 if it has failed. + * + * If not set the nfapi unpack functions will use malloc + */ + void* (*allocate)(size_t size); + + /*! Optional call back to allow the user to define the memory deallocator. + * \param ptr A poiner to a memory block allocated by the allocate callback + * + * If not set the client should use free + */ + void (*deallocate)(void* ptr); + + /*! Optional call back function to handle unpacking vendor extension tlv. + * \param tl A pointer to a decoded tag length structure + * \param ppReadPackedMsg A handle to the read buffer. + * \param end The end of the read buffer + * \param ve A handle to a vendor extention structure that the call back should allocate if the structure can be decoded + * \param config A pointer to the p7 codec configuration + * \return return 0 if packed successfully, -1 if failed. + * + * If not set the tlv will be skipped + * + * Client should use the help methods in nfapi.h to decode the vendor extention. + * + * \todo Add code example + */ + int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, + uint8_t** ppReadPackedMsg, + uint8_t* end, + void** ve, + struct nfapi_p7_codec_config* config); + + /*! Optional call back function to handle packing vendor extension tlv. + * \param ve A pointer to a vendor extention structure. + * \param ppWritePackedMsg A handle to the write buffer + * \param end The end of the write buffer. The callee should make sure not to write beyond the end + * \param config A pointer to the p7 codec configuration + * \return return 0 if packed successfully, -1 if failed. + * + * If not set the the tlv will be skipped + * + * Client should use the help methods in nfapi.h to encode the vendor extention + * + * \todo Add code example + */ + int (*pack_vendor_extension_tlv)(void* ve, uint8_t** ppWritePackedMsg, uint8_t* end, struct nfapi_p7_codec_config* config); + + /*! Optional call back function to handle unpacking vendor extension messages. + * \param header A pointer to a decode P7 message header for the vendor extention message + * \param ppReadPackedMsg A handle to the encoded data buffer + * \param end A pointer to the end of the encoded data buffer + * \param config A pointer to the p7 codec configuration + * \return 0 if unpacked successfully, -1 if failed + * + * If not set the message will be ignored + * + * If the message if is unknown the function should return -1 + */ + int (*unpack_p7_vendor_extension)(void* header, uint8_t** ppReadPackedMsg, uint8_t* end, struct nfapi_p7_codec_config* config); + + /*! Optional call back function to handle packing vendor extension messages. + * \param header A poiner to a P7 message structure for the venfor extention message + * \param ppWritePackedmsg A handle to the buffer to write the encoded message into + * \param end A pointer to the end of the buffer + * \param cofig A pointer to the p7 codec configuration + * \return 0 if packed successfully, -1 if failed + * + * If not set the the message will be ingored + * + * If the message if is unknown the function should return -1 + */ + int (*pack_p7_vendor_extension)(void* header, uint8_t** ppWritePackedmsg, uint8_t* end, struct nfapi_p7_codec_config* config); + + /*! Optional user data that will be passed back with callbacks + */ + void* user_data; + +} nfapi_p7_codec_config_t; + +/*! Configuration options for the p4 & p5 pack unpack functions + * + */ +typedef struct nfapi_p4_p5_codec_config { + /*! Optional call back to allow the user to define the memory allocator. + * \param size The size of the memory to allocate + * \return a pointer to a valid memory block or 0 if it has failed. + * + * If not set the nfapi unpack functions will use malloc + */ + void* (*allocate)(size_t size); + + /*! Optional call back to allow the user to define the memory deallocator. + * \param ptr A poiner to a memory block allocated by the allocate callback + * + * If not set free will be used + */ + void (*deallocate)(void* ptr); + + /*! Optional call back function to handle unpacking vendor extension tlv. + * \param tl A pointer to a decoded tag length structure + * \param ppReadPackedMsg A handle to the data buffer to decode + * \param end A pointer to the end of the buffer + * \param ve A handle to a vendor extention structure that will be allocated by this callback + * \param config A pointer to the P4/P5 codec configuration + * \return 0 if unpacked successfully, -1 if failed + * + * If not set the tlv will be skipped + */ + int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, + uint8_t** ppReadPackedMsg, + uint8_t* end, + void** ve, + struct nfapi_p4_p5_codec_config* config); + + /*! Optional call back function to handle packing vendor extension tlv. + * \param ve + * \param ppWritePackedMsg A handle to the data buffer pack the tlv into + * \param end A pointer to the end of the buffer + * \param config A pointer to the P4/P5 codec configuration + * \return 0 if packed successfully, -1 if failed + * + * If not set the the tlv will be skipped + */ + int (*pack_vendor_extension_tlv)(void* ve, uint8_t** ppWritePackedMsg, uint8_t* end, struct nfapi_p4_p5_codec_config* config); + + /*! Optional call back function to handle unpacking vendor extension messages. + * \param header A pointer to a decode P4/P5 message header + * \param ppReadPackgedMsg A handle to the data buffer to decode + * \param end A pointer to the end of the buffer + * \param config A pointer to the P4/P5 codec configuration + * \return 0 if packed successfully, -1 if failed + * + * If not set the message will be ignored + */ + int (*unpack_p4_p5_vendor_extension)(void* header, + uint8_t** ppReadPackedMsg, + uint8_t* end, + struct nfapi_p4_p5_codec_config* config); + + /*! Optional call back function to handle packing vendor extension messages. + * \param header A pointer to the P4/P5 message header to be encoded + * \param ppWritePackedMsg A handle to the data buffer pack the message into + * \param end A pointer to the end of the buffer + * \param config A pointer to the P4/P5 codec configuration + * \return 0 if packed successfully, -1 if failed + * + * If not set the the message will be ingored + */ + int (*pack_p4_p5_vendor_extension)(void* header, + uint8_t** ppwritepackedmsg, + uint8_t* end, + struct nfapi_p4_p5_codec_config* config); + + /*! Optional user data that will be passed back with callbacks + */ + void* user_data; + +} nfapi_p4_p5_codec_config_t; + +#endif // NFAPI_COMMON_INTERFACE_H diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h index 3312fa832eb3d4b56a132b0d14c7f1f28f479920..2d761bab8865827a196c3736df8ed8c337f52f53 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h @@ -20,6 +20,7 @@ #include "stddef.h" #include <stdint.h> +#include "nfapi_common_interface.h" // Constants - update based on implementation #define NFAPI_MAX_PHY_RF_INSTANCES 2 @@ -27,7 +28,7 @@ #define NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH 3 #define NFAPI_MAX_NUM_RF_BANDS 16 -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192 +#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 // The following definition control the size of arrays used in the interface. // These may be changed if desired. They are used in the encoder to make sure @@ -92,19 +93,19 @@ typedef signed short int16_t; typedef signed char int8_t; typedef struct { - uint16_t phy_id; - uint16_t message_id; - uint16_t message_length; - uint16_t spare; + uint16_t phy_id; + uint16_t message_id; + uint16_t message_length; + uint16_t spare; } nfapi_p4_p5_message_header_t; typedef struct { - uint16_t phy_id; - uint16_t message_id; - uint16_t message_length; - uint16_t m_segment_sequence; /* This consists of 3 fields - namely, M, Segement & Sequence number*/ - uint32_t checksum; - uint32_t transmit_timestamp; + uint16_t phy_id; + uint16_t message_id; + uint16_t message_length; + uint16_t m_segment_sequence; /* This consists of 3 fields - namely, M, Segement & Sequence number*/ + uint32_t checksum; + uint32_t transmit_timestamp; } nfapi_p7_message_header_t; #define NFAPI_PHY_ID_NA 0 @@ -116,10 +117,6 @@ typedef struct { #define NFAPI_P7_GET_SEQUENCE(_mss) ( (_mss) & 0x00FF ) #define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7) << 4) | ((_sequ) & 0xF) ) -typedef struct { - uint16_t tag; - uint16_t length; -} nfapi_tl_t; #define NFAPI_TAG_LENGTH_PACKED_LEN 4 // Convenience methods to convert between SFN/SLOT formats @@ -2537,29 +2534,6 @@ typedef struct { nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_timing_info_t; -typedef struct { - nfapi_p7_message_header_t header; - - uint32_t last_sfn; - uint32_t last_slot; - uint32_t time_since_last_timing_info; - - uint32_t dl_tti_jitter; - uint32_t tx_data_request_jitter; - uint32_t ul_tti_jitter; - uint32_t ul_dci_jitter; - - int32_t dl_tti_latest_delay; - int32_t tx_data_request_latest_delay; - int32_t ul_tti_latest_delay; - int32_t ul_dci_latest_delay; - - int32_t dl_tti_earliest_arrival; - int32_t tx_data_request_earliest_arrival; - int32_t ul_tti_earliest_arrival; - int32_t ul_dci_earliest_arrival; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nr_timing_info_t; typedef struct { nfapi_tl_t tl; @@ -3772,160 +3746,6 @@ typedef struct // Configuration options for the encode decode functions // -/*! Configuration options for the p7 pack unpack functions - * - */ -typedef struct nfapi_p7_codec_config { - - /*! Optional call back to allow the user to define the memory allocator. - * \param size The size of the memory to allocate - * \return a pointer to a valid memory block or 0 if it has failed. - * - * If not set the nfapi unpack functions will use malloc - */ - void* (*allocate)(size_t size); - - /*! Optional call back to allow the user to define the memory deallocator. - * \param ptr A poiner to a memory block allocated by the allocate callback - * - * If not set the client should use free - */ - void (*deallocate)(void* ptr); - - /*! Optional call back function to handle unpacking vendor extension tlv. - * \param tl A pointer to a decoded tag length structure - * \param ppReadPackedMsg A handle to the read buffer. - * \param end The end of the read buffer - * \param ve A handle to a vendor extention structure that the call back should allocate if the structure can be decoded - * \param config A pointer to the p7 codec configuration - * \return return 0 if packed successfully, -1 if failed. - * - * If not set the tlv will be skipped - * - * Client should use the help methods in nfapi.h to decode the vendor extention. - * - * \todo Add code example - */ - int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p7_codec_config* config); - - /*! Optional call back function to handle packing vendor extension tlv. - * \param ve A pointer to a vendor extention structure. - * \param ppWritePackedMsg A handle to the write buffer - * \param end The end of the write buffer. The callee should make sure not to write beyond the end - * \param config A pointer to the p7 codec configuration - * \return return 0 if packed successfully, -1 if failed. - * - * If not set the the tlv will be skipped - * - * Client should use the help methods in nfapi.h to encode the vendor extention - * - * \todo Add code example - */ - int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config); - - /*! Optional call back function to handle unpacking vendor extension messages. - * \param header A pointer to a decode P7 message header for the vendor extention message - * \param ppReadPackedMsg A handle to the encoded data buffer - * \param end A pointer to the end of the encoded data buffer - * \param config A pointer to the p7 codec configuration - * \return 0 if unpacked successfully, -1 if failed - * - * If not set the message will be ignored - * - * If the message if is unknown the function should return -1 - */ - int (*unpack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config); - - /*! Optional call back function to handle packing vendor extension messages. - * \param header A poiner to a P7 message structure for the venfor extention message - * \param ppWritePackedmsg A handle to the buffer to write the encoded message into - * \param end A pointer to the end of the buffer - * \param cofig A pointer to the p7 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the the message will be ingored - * - * If the message if is unknown the function should return -1 - */ - int (*pack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedmsg, uint8_t *end, struct nfapi_p7_codec_config* config); - - /*! Optional user data that will be passed back with callbacks - */ - void* user_data; - -} nfapi_p7_codec_config_t; - -/*! Configuration options for the p4 & p5 pack unpack functions - * - */ -typedef struct nfapi_p4_p5_codec_config { - - /*! Optional call back to allow the user to define the memory allocator. - * \param size The size of the memory to allocate - * \return a pointer to a valid memory block or 0 if it has failed. - * - * If not set the nfapi unpack functions will use malloc - */ - void* (*allocate)(size_t size); - - /*! Optional call back to allow the user to define the memory deallocator. - * \param ptr A poiner to a memory block allocated by the allocate callback - * - * If not set free will be used - */ - void (*deallocate)(void* ptr); - - /*! Optional call back function to handle unpacking vendor extension tlv. - * \param tl A pointer to a decoded tag length structure - * \param ppReadPackedMsg A handle to the data buffer to decode - * \param end A pointer to the end of the buffer - * \param ve A handle to a vendor extention structure that will be allocated by this callback - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if unpacked successfully, -1 if failed - * - * If not set the tlv will be skipped - */ - int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p4_p5_codec_config* config); - - /*! Optional call back function to handle packing vendor extension tlv. - * \param ve - * \param ppWritePackedMsg A handle to the data buffer pack the tlv into - * \param end A pointer to the end of the buffer - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the the tlv will be skipped - */ - int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config); - - /*! Optional call back function to handle unpacking vendor extension messages. - * \param header A pointer to a decode P4/P5 message header - * \param ppReadPackgedMsg A handle to the data buffer to decode - * \param end A pointer to the end of the buffer - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the message will be ignored - */ - int (*unpack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config); - - /*! Optional call back function to handle packing vendor extension messages. - * \param header A pointer to the P4/P5 message header to be encoded - * \param ppWritePackedMsg A handle to the data buffer pack the message into - * \param end A pointer to the end of the buffer - * \param config A pointer to the P4/P5 codec configuration - * \return 0 if packed successfully, -1 if failed - * - * If not set the the message will be ingored - */ - int (*pack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppwritepackedmsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config); - - /*! Optional user data that will be passed back with callbacks - */ - void* user_data; - -} nfapi_p4_p5_codec_config_t; - // // Functions // @@ -3979,21 +3799,7 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn * */ int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); -int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); -/*! \brief Packs a NFAPI P5 message body - * \param header A pointer to the header of the P5 message - * \param ppWritePackedMsg A pointer to the buffer where to pack the P5 message - * \param end Pointer to the end of the packing buffer - * \param config A pointer to the nfapi configuration structure - * \return 0 means success, -1 means failure. - * - * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf - */ -uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t* header, - uint8_t** ppWritePackedMsg, - uint8_t* end, - nfapi_p4_p5_codec_config_t* config); /*! \brief Decodes an NFAPI P5 message header * \param pMessageBuf A pointer to an encoded P5 message header @@ -4017,7 +3823,6 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo * * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf */ -int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); /*! \brief Encodes an NFAPI P7 message to a buffer @@ -4031,7 +3836,6 @@ int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn * */ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); -int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); /*! \brief Decodes an NFAPI P7 message header * \param pMessageBuf A pointer to an encoded P7 message header @@ -4057,7 +3861,6 @@ int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf */ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); -int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); /*! \brief Calculates the checksum of a message * @@ -4083,42 +3886,4 @@ int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len); */ int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp); -/*! \brief Encodes a nfapi_nr_srs_normalized_channel_iq_matrix_t to a buffer - * - * \param pMessageBuf A pointer to a nfapi_nr_srs_normalized_channel_iq_matrix_t structure - * \param pPackedBuf A pointer to the buffer that the nfapi_nr_srs_normalized_channel_iq_matrix_t will be packed into - * \param packedBufLen The size of the buffer - * \return number of bytes written to the buffer - */ -int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen); - -/*! \brief Decodes a nfapi_nr_srs_normalized_channel_iq_matrix_t from a buffer - * - * \param pMessageBuf A pointer to an encoded nfapi_nr_srs_normalized_channel_iq_matrix_t - * \param messageBufLen The size of the encoded nfapi_nr_srs_normalized_channel_iq_matrix_t - * \param pUnpackedBuf A pointer to the nfapi_nr_srs_normalized_channel_iq_matrix_t - * \param unpackedBufLen The size of nfapi_nr_srs_normalized_channel_iq_matrix_t structure. - * \return 0 means success, -1 means failure. - */ -int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen); - -/*! \brief Encodes a nfapi_nr_srs_beamforming_report_t to a buffer - * - * \param pMessageBuf A pointer to a nfapi_nr_srs_beamforming_report_t structure - * \param pPackedBuf A pointer to the buffer that the nfapi_nr_srs_beamforming_report_t will be packed into - * \param packedBufLen The size of the buffer - * \return number of bytes written to the buffer - */ -int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen); - -/*! \brief Decodes a nfapi_nr_srs_beamforming_report_t from a buffer - * - * \param pMessageBuf A pointer to an encoded nfapi_nr_srs_beamforming_report_t - * \param messageBufLen The size of the encoded nfapi_nr_srs_beamforming_report_t - * \param pUnpackedBuf A pointer to the nfapi_nr_srs_beamforming_report_t - * \param unpackedBufLen The size of nfapi_nr_srs_beamforming_report_t structure. - * \return 0 means success, -1 means failure. - */ -int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen); - #endif /* _NFAPI_INTERFACE_H_ */ diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index 4e9987b0cb6fc5b521ab4836d85fd4885e09fd2f..c68566634dcf1bd550e53df80bb743c9df98f81c 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -8,6 +8,10 @@ #ifndef _NFAPI_NR_INTERFACE_H_ #define _NFAPI_NR_INTERFACE_H_ +#include "nfapi_common_interface.h" + +#define NFAPI_NR_P5_HEADER_LENGTH 10 +#define NFAPI_NR_P7_HEADER_LENGTH 18 //These TLVs are used exclusively by nFAPI #define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x0100 @@ -26,6 +30,22 @@ #define NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG 0xA000 #define NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG 0xA001 +typedef struct { + uint16_t phy_id; + uint16_t message_id; + uint32_t message_length; + uint16_t spare; +} nfapi_nr_p4_p5_message_header_t; + +typedef struct { + uint16_t phy_id; + uint16_t message_id; + uint32_t message_length; + uint16_t m_segment_sequence; /* This consists of 3 fields - namely, M, Segement & Sequence number*/ + uint32_t checksum; + uint32_t transmit_timestamp; +} nfapi_nr_p7_message_header_t; + typedef enum { NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED=1, NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED=0 @@ -48,4 +68,178 @@ typedef enum { NFAPI_NR_SRS_ANTENNASWITCH = 3 } nfapi_nr_srs_usage_e; +/*! \brief Encodes an NFAPI P5 message to a buffer + * \param pMessageBuf A pointer to a nfapi p5 message structure + * \param messageBufLen The size of the p5 message structure + * \param pPackedBuf A pointer to the buffer that the p5 message will be packed into + * \param packedBufLen The size of the buffer + * \param config A pointer to the nfapi configuration structure + * \return != 0 means success, -1 means failure. + * + * The function will encode a nFAPI P5 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf. + * The function returns the message length that was packed + */ +int nfapi_nr_p5_message_pack(void *pMessageBuf, + uint32_t messageBufLen, + void *pPackedBuf, + uint32_t packedBufLen, + nfapi_p4_p5_codec_config_t *config); + +/*! \brief Packs a NFAPI P5 message body + * \param header A pointer to the header of the P5 message + * \param ppWritePackedMsg A pointer to the buffer where to pack the P5 message + * \param end Pointer to the end of the packing buffer + * \param config A pointer to the nfapi configuration structure + * \return 1 means success, 0 means failure. + * + * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf + */ +uint8_t pack_nr_p5_message_body(nfapi_nr_p4_p5_message_header_t *header, + uint8_t **ppWritePackedMsg, + uint8_t *end, + nfapi_p4_p5_codec_config_t *config); + +/*! \brief Decodes an NFAPI P5 message header + * \param pMessageBuf A pointer to an encoded P5 message header + * \param messageBufLen The size of the encoded P5 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return 10 ( size of the unpacked header ) on success, -1 on failure. + * + * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 header structure pointed to by pUnpackedBuf + */ +int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config); + +/*! \brief Decodes a NFAPI P5 message + * \param pMessageBuf A pointer to an encoded P5 message + * \param messageBufLen The size of the encoded P5 message + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return != -1 means success, -1 means failure. + * + * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf + */ +int nfapi_nr_p5_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config); + +/*! \brief Encodes an NFAPI P7 message to a buffer + * \param pMessageBuf A pointer to a nfapi p7 message structure + * \param pPackedBuf A pointer to the buffer that the p7 message will be packed into + * \param packedBufLen The size of the buffer + * \param config A pointer to the nfapi configuration structure + * \return != -1 means success, -1 means failure. + * + * The function will encode a nFAPI P7 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf. + * The function returns the message length packed + */ +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config); + +/*! \brief Decodes an NFAPI P7 message header + * \param pMessageBuf A pointer to an encoded P7 message header + * \param messageBufLen The size of the encoded P7 message header + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return 0 means success, -1 means failure. + * + * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p7_message_header structure pointer to by + pUnpackedBuf + + */ +int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config); + +/*! \brief Decodes a NFAPI P7 message + * \param pMessageBuf A pointer to an encoded P7 message + * \param messageBufLen The size of the encoded P7 message + * \param pUnpackedBuf A pointer to the nfapi_message_header + * \param unpackedBufLen The size of nfapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return 0 means success, -1 means failure. + * + * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf + */ +int nfapi_nr_p7_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config); + +/*! \brief Calculates the checksum of a message + * + * \param buffer Pointer to the packed message + * \param len The length of the message + * \return The checksum. If there is an error the function with return -1 + */ +uint32_t nfapi_nr_p7_calculate_checksum(uint8_t *buffer, uint32_t len); + +/*! \brief Calculates & updates the checksum in the message + * + * \param buffer Pointer to the packed message + * \param len The length of the message + * \return 0 means success, -1 means failure. + */ +int nfapi_nr_p7_update_checksum(uint8_t *buffer, uint32_t len); + +/*! \brief Updates the transmition time stamp in the p7 message header + * + * \param buffer Pointer to the packed message + * \param timestamp The time stamp value + * \return 0 means success, -1 means failure. + */ +int nfapi_nr_p7_update_transmit_timestamp(uint8_t *buffer, uint32_t timestamp); + +/*! \brief Encodes a nfapi_nr_srs_normalized_channel_iq_matrix_t to a buffer + * + * \param pMessageBuf A pointer to a nfapi_nr_srs_normalized_channel_iq_matrix_t structure + * \param pPackedBuf A pointer to the buffer that the nfapi_nr_srs_normalized_channel_iq_matrix_t will be packed into + * \param packedBufLen The size of the buffer + * \return number of bytes written to the buffer + */ +int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen); + +/*! \brief Decodes a nfapi_nr_srs_normalized_channel_iq_matrix_t from a buffer + * + * \param pMessageBuf A pointer to an encoded nfapi_nr_srs_normalized_channel_iq_matrix_t + * \param messageBufLen The size of the encoded nfapi_nr_srs_normalized_channel_iq_matrix_t + * \param pUnpackedBuf A pointer to the nfapi_nr_srs_normalized_channel_iq_matrix_t + * \param unpackedBufLen The size of nfapi_nr_srs_normalized_channel_iq_matrix_t structure. + * \return 0 means success, -1 means failure. + */ +int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen); + +/*! \brief Encodes a nfapi_nr_srs_beamforming_report_t to a buffer + * + * \param pMessageBuf A pointer to a nfapi_nr_srs_beamforming_report_t structure + * \param pPackedBuf A pointer to the buffer that the nfapi_nr_srs_beamforming_report_t will be packed into + * \param packedBufLen The size of the buffer + * \return number of bytes written to the buffer + */ +int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen); + +/*! \brief Decodes a nfapi_nr_srs_beamforming_report_t from a buffer + * + * \param pMessageBuf A pointer to an encoded nfapi_nr_srs_beamforming_report_t + * \param messageBufLen The size of the encoded nfapi_nr_srs_beamforming_report_t + * \param pUnpackedBuf A pointer to the nfapi_nr_srs_beamforming_report_t + * \param unpackedBufLen The size of nfapi_nr_srs_beamforming_report_t structure. + * \return 0 means success, -1 means failure. + */ +int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen); + #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 2476833d7c815cb1c26eb8431bb0579f51143a8e..f82c6c414a587b5fe47b19cf60cf4174989431b7 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -11,6 +11,7 @@ #include "stddef.h" #include "nfapi_interface.h" +#include "nfapi_nr_interface.h" #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 @@ -68,6 +69,8 @@ typedef enum { NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION = 0X88, NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION = 0X89, // RESERVED 0X8a ~ 0xff + NFAPI_NR_PHY_MSG_TYPE_VENDOR_EXT_SLOT_RESPONSE = 0x8F, // Aerial-specfiic + NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST = 0x0100, NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE = 0x0101, NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST = 0x0102, @@ -510,12 +513,12 @@ typedef enum { // Table 2-27 //PNF P5 NR typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_pnf_param_request_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint8_t error_code; uint8_t num_tlvs; nfapi_pnf_param_general_t pnf_param_general; @@ -524,36 +527,36 @@ typedef struct { } nfapi_nr_pnf_param_response_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint8_t num_tlvs; nfapi_pnf_phy_rf_config_t pnf_phy_rf_config; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_pnf_config_request_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint8_t error_code; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_pnf_config_response_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_pnf_start_request_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint32_t error_code; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_pnf_start_response_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_pnf_stop_request_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint32_t error_code; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_pnf_stop_response_t; @@ -561,13 +564,13 @@ typedef struct { /* PARAM.REQUEST */ typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_param_request_scf_t; /* PARAM.RESPONSE */ typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint8_t error_code; uint8_t num_tlv; @@ -589,7 +592,7 @@ typedef struct { /* CONFIG.REQUEST */ typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint8_t num_tlv; nfapi_vendor_extension_tlv_t vendor_extension; @@ -627,7 +630,7 @@ typedef struct { /* CONFIG.RESPONSE */ typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint8_t error_code; uint8_t num_invalid_tlvs; uint8_t num_invalid_tlvs_configured_in_idle; @@ -644,12 +647,12 @@ typedef struct { //3.3.3 START typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_start_request_scf_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_nr_start_errors_e error_code; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_start_response_scf_t; @@ -657,17 +660,17 @@ typedef struct { //3.3.4 STOP typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_stop_request_scf_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_stop_indication_scf_t; typedef struct { - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t message_id; // Which message received on the PNF has an error @@ -708,7 +711,7 @@ typedef struct { #define NFAPI_NR_SLOT_INDICATION_PERIOD_NUMEROLOGY_3 125 //us typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t sfn; //0->1023 uint16_t slot;//0->319 @@ -894,6 +897,19 @@ typedef struct { uint8_t nEpreRatioOfPDSCHToPTRS; // Beamforming nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming; + // TX Power info + /// Ratio of PDSCH EPRE to NZP CSI-RSEPRE [TS38.214,sec 5.2.2.3.1] + uint8_t powerControlOffset; + /// Ratio of SSB/PBCH block EPRE to NZP CSI-RS EPRES [TS38.214, sec 5.2.2.3.1] + uint8_t powerControlOffsetSS; + // CBG fields + /// Indicates whether last CB is present in the CBG retransmission ( 0 -> not included; 1 -> included ) + uint8_t isLastCbPresent; + /// Indicates whether TB CRC is part of data payload or control message ( 0 -> payload; 1 -> control message ) + uint8_t isInlineTbCrc; + /// TB CRC: to be used in the last CB, applicable only if last CB is present + uint32_t dlTbCrc; + nfapi_v3_pdsch_maintenance_parameters_t maintenance_parms_v3; }nfapi_nr_dl_tti_pdsch_pdu_rel15_t; @@ -1070,23 +1086,46 @@ typedef struct { typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint32_t t1; int32_t delta_sfn_slot; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_dl_node_sync_t; typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint32_t t1; uint32_t t2; uint32_t t3; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_ul_node_sync_t; +typedef struct { + nfapi_nr_p7_message_header_t header; + + uint32_t last_sfn; + uint32_t last_slot; + uint32_t time_since_last_timing_info; + + uint32_t dl_tti_jitter; + uint32_t tx_data_request_jitter; + uint32_t ul_tti_jitter; + uint32_t ul_dci_jitter; + + int32_t dl_tti_latest_delay; + int32_t tx_data_request_latest_delay; + int32_t ul_tti_latest_delay; + int32_t ul_dci_latest_delay; + + int32_t dl_tti_earliest_arrival; + int32_t tx_data_request_earliest_arrival; + int32_t ul_tti_earliest_arrival; + int32_t ul_dci_earliest_arrival; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_timing_info_t; typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; /// System Frame Number (0-1023) uint16_t SFN; /// Slot number (0-19) @@ -1320,7 +1359,7 @@ typedef struct uint8_t dmrs_cyclic_shift; uint8_t sr_flag; - uint8_t bit_len_harq; + uint16_t bit_len_harq; uint16_t bit_len_csi_part1; uint16_t bit_len_csi_part2; @@ -1336,7 +1375,7 @@ typedef struct { typedef struct { uint16_t srs_bandwidth_size; // mSRS,b: Number of PRB’s that are sounded for each SRS symbol, per 3GPP TS 38.211, section 6.4.1.4.3. Value: 4->272 - nfapi_v4_srs_parameters_symbols_t *symbol_list; + nfapi_v4_srs_parameters_symbols_t symbol_list[4]; uint32_t usage; // Bitmap indicating the type of report(s) expected at L2 from the SRS signaled by this PDU. Bit positions: 0 – beamManagement; 1 – codebook; 2 – nonCodebook; 3 – antennaSwitching; 4 – 255: reserved. For each of this bit positions: 1 = requested; 0 = not requested. nUsage = sum(all bits in usage) uint8_t report_type[4]; // Interpretation of each Report Type depends on usage: beamManagement (1 = PRG SNR, 2-255 reserved); codebook (1 = PRG I and Q channel estimate, per srs Tx port and gNB antenna element, 2-255 reserved); nonCodebook (1 = PRG I and Q channel estimate, per SRI and gNB antenna element, 2-255 reserved); antennaSwitching (1 = SVD representation UE Rx and gNB sets of antenna element, 2-255 reserved); all (0 – no report required). uint8_t singular_Value_representation; // 0 – 8-bit dB; 1 – 16-bit linear; 255 – not applicable @@ -1420,7 +1459,7 @@ typedef struct } nfapi_nr_ul_tti_request_number_of_groups_t; typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t SFN; //0->1023 uint16_t Slot;//0->319 uint8_t n_pdus;//Number of PDUs that are included in this message. All PDUs in the message are numbered in order. Value 0 -> 255 @@ -1464,7 +1503,7 @@ typedef struct { } nfapi_nr_ul_dci_request_pdus_t; typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t SFN; uint16_t Slot; uint8_t numPdus; @@ -1510,7 +1549,7 @@ typedef struct #define NFAPI_NR_MAX_TX_REQUEST_PDUS 16 typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t SFN; uint16_t Slot; uint16_t Number_of_PDUs; @@ -1545,7 +1584,7 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; @@ -1573,7 +1612,7 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1710,7 +1749,7 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1721,6 +1760,44 @@ typedef struct /// 5G PHY FAPI Specification: SRS indication - Section 3.4.10 +// Table 3–133 Channel SVD Representation + +typedef struct { + // Array of (Nu*Nu) entries of the type denoted by ‘iq Representation’ + // U[ueAntenna uI, left eigenvector leI] = array[uI*Nu + leI] + uint8_t* left_eigenvectors_matrix_u; + + // Array of (Nu) entries of the type denoted by ‘singular + // Values Representation’ + // Σ[left eigenvector leI, right eigenvector reI] = + // • 0 if leI ≠reI + // • 0 if min(leI, reI) ≥ Nu + // • array[leI] if leI = reI + uint8_t* diagonal_entries_of_singular_matrix_sum_f; + + // Array of (Nu*Ng) entries of the type denoted by ‘iq + // Representation’ + // H + // VF[right eigenvector reI, gNB antenna gI] = + // array[reI*Ng + gI], + //- reI: 0…Nu-1 + //- gI: 0…Ng-1 + uint8_t* complex_conjugate_of_matrix_of_right_eigenvectors_v_hf; +} nfapi_nr_srs_channel_svd_representation_prg_t; + +typedef struct { + uint8_t normalized_iq_representation; // 0: 16-bit normalized complex number (iqSize = 2); 1: 32-bit normalized complex number + // (iqSize = 4) + uint8_t normalized_singular_value_representation; // 0: 8-bit linear representation (sSize = 1); 1:16-bit linear representation + // (sSize = 2) + int8_t singular_value_scaling; // dB-domain representation of singular value scaling + uint16_t num_gnb_antenna_elements; // Ng: Number of gNB antenna elements + uint8_t num_ue_srs_ports; // Nu: Number of sampled UE SRS ports + uint16_t prg_size; // Size in RBs of a precoding resource block group (PRG) + uint16_t num_prgs; // Number of PRGs to be reported for this SRS PDU + nfapi_nr_srs_channel_svd_representation_prg_t* prg_list; +} nfapi_nr_srs_channel_svd_representation_t; + // Normalized channel I/Q matrix typedef struct { @@ -1748,11 +1825,11 @@ typedef struct { uint8_t num_symbols; // Number of symbols for SRS. Value: 1 -> 4. If a PHY does not report for individual symbols then this parameter should be set to 1. uint8_t wide_band_snr; // SNR value in dB measured within configured SRS bandwidth on each symbol. Value: 0 -> 255 representing -64 dB to 63 dB with a step size 0.5 dB. 0xff will be set if this field is invalid. uint8_t num_reported_symbols; // Number of symbols reported in this message. This allows PHY to report individual symbols or aggregated symbols where this field will be set to 1. Value: 1 -> 4. - nfapi_nr_srs_reported_symbol_t prgs; + nfapi_nr_srs_reported_symbol_t* reported_symbol_list; } nfapi_nr_srs_beamforming_report_t; // SRS indication - +#define NFAPI_NR_SRS_IND_MAX_PDU 100 typedef struct { uint16_t tag; // 0: Report is carried directly in the value field; 3: The offset from the end of the control portion of the message to the beginning of the report. Other values are reserved. uint32_t length; // Length of the actual report in bytes, without the padding bytes. @@ -1770,7 +1847,7 @@ typedef struct { } nfapi_nr_srs_indication_pdu_t; typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t sfn; // SFN. Value: 0 -> 1023 uint16_t slot; // Slot. Value: 0 -> 159 uint16_t control_length; // Size of control portion of SRS indication. 0 if reports are included inline; >0 if reports are concatenated to the end of the message. @@ -1780,6 +1857,7 @@ typedef struct { //3.4.11 rach_indication +#define NFAPI_NR_RACH_IND_MAX_PDU 100 //table 3-74 typedef struct { @@ -1803,7 +1881,7 @@ typedef struct{ typedef struct { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h b/nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h index 5a6fe08701a539890ed9c885e8eab83c77bf1825..4116422268b7ae93cda4d342fba357c655f5b24d 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h @@ -34,56 +34,16 @@ #include "nfapi_interface.h" #include "nfapi_nr_interface_scf.h" -uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_slot_indication_scf_t *msg, - nfapi_p7_codec_config_t *config); - void *nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t *config); -uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_srs_indication_t *pNfapiMsg, - nfapi_p7_codec_config_t *config); - -uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - -uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - -uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); -uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - -uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - -uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - -uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - -uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - -uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); - uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config); -uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_crc_indication_t *msg, - nfapi_p7_codec_config_t *config); - -uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config); - -uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_rach_indication_t *msg, - nfapi_p7_codec_config_t *config); - #endif // OPENAIRINTERFACE_NR_NFAPI_P7_H diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c index 9615d3b934dfa891bb11cef94893a421f7a6b84e..64ec807d51b62025881edfdacad2aa26c33b6638 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c @@ -1616,7 +1616,12 @@ int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPack // Main unpack functions - public -int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { +int nfapi_p4_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config) +{ nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; uint8_t *pReadPackedMessage = pMessageBuf; @@ -1632,17 +1637,21 @@ int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo return -1; } - // process the headei - if (pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end)) + // process the header + if (pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->spare, end)) return -1; return 0; } -int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { +int nfapi_p4_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config) +{ int result = 0; nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; uint8_t *pReadPackedMessage = pMessageBuf; @@ -1661,12 +1670,10 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) + if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) return -1; // look for the specific message @@ -1779,7 +1786,7 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_RESPONSE, unpackedBufLen)) result = unpack_system_information_response(&pReadPackedMessage, end, pMessageHeader, config); else - result = -1; + result = -1; break; @@ -1787,7 +1794,7 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_INDICATION, unpackedBufLen)) result = unpack_system_information_indication(&pReadPackedMessage, end, pMessageHeader, config); else - result = -1; + result = -1; break; @@ -1808,12 +1815,14 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn break; default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { - if(config && config->unpack_p4_p5_vendor_extension) { + if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (config && config->unpack_p4_p5_vendor_extension) { result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s VE NFAPI message ID %d. No ve decoder provided\n", + __FUNCTION__, + pMessageHeader->message_id); } } else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P4 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); @@ -1822,7 +1831,7 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn break; } - if(result == 0) + if (result == 0) return -1; return result; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index a5a7810f405421d140c435cf3198ea171c31b69a..1aeef4b766ac12248da73d856dc2cdb180d87dfc 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -1185,7 +1185,7 @@ static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg, pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t *header, +uint8_t pack_nr_p5_message_body(nfapi_nr_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) @@ -1377,11 +1377,8 @@ int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { - nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + nfapi_nr_p4_p5_message_header_t *pMessageHeader = pMessageBuf; uint8_t *pWritePackedMessage = pPackedBuf; - uint32_t packedMsgLen; - uint32_t packedBodyLen; - uint16_t packedMsgLen16; if (pMessageBuf == NULL || pPackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); @@ -1390,28 +1387,26 @@ int nfapi_nr_p5_message_pack(void *pMessageBuf, uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8]; - uint8_t *pPacketBodyField = &pWritePackedMessage[8]; + uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[10]; + uint8_t *pPacketBodyField = &pWritePackedMessage[10]; // pack the message if (push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) - && push16(0, &pWritePackedMessage, pPackMessageEnd) && push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) + && push32(0, &pWritePackedMessage, pPackMessageEnd) && push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && pack_nr_p5_message_body(pMessageHeader, &pPacketBodyField, pPackMessageEnd, config)) { // to check if whole message is bigger than the buffer provided - packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pPacketBodyField); + uint32_t packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pPacketBodyField); // obtain the length of the message body to pack - packedBodyLen = get_packed_msg_len((uintptr_t)pPacketBodyFieldStart, (uintptr_t)pPacketBodyField); + uint32_t packedBodyLen = get_packed_msg_len((uintptr_t)pPacketBodyFieldStart, (uintptr_t)pPacketBodyField); - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + if (packedMsgLen > packedBufLen) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); return -1; - } else { - packedMsgLen16 = (uint16_t)packedBodyLen; } // Update the message length in the header - if (!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) + if (!push32(packedBodyLen, &pPackedLengthField, pPackMessageEnd)) return -1; // return the packed length @@ -2299,7 +2294,12 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen // Main unpack functions - public -int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { +int nfapi_p5_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config) +{ nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; uint8_t *pReadPackedMessage = pMessageBuf; @@ -2316,10 +2316,42 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo } // process the header - return ( pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end) ); + if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { + return -1; + } + + return 8; +} + +int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t *config) +{ + nfapi_nr_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n"); + return -1; + } + + uint8_t *end = pMessageBuf + messageBufLen; + + if (messageBufLen < NFAPI_NR_P5_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p4_p5_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + // process the header + if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull32(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { + return -1; + } + return NFAPI_NR_P5_HEADER_LENGTH; } int nfapi_nr_p5_message_unpack(void *pMessageBuf, @@ -2328,41 +2360,24 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); return -1; } - - uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; - - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) { + if (messageBufLen < NFAPI_NR_P5_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p4_p5_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); return -1; } - uint8_t *ptr = pReadPackedMessage; - printf("\n Read NR message unpack: "); - - while (ptr < end) { - printf(" %02x ", *ptr); - ptr++; - } - - printf("\n"); + nfapi_nr_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); - // process the header - if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) - && pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) - && pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { - // failed to read the header + if (!nfapi_nr_p5_message_header_unpack(pMessageBuf, messageBufLen, pMessageHeader, unpackedBufLen, config)) { return -1; } - + uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_NR_P5_HEADER_LENGTH; + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; int result = -1; if (check_nr_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index bcaf7a524ddff848dfbb89829802d31ddec3f4b6..df554ab599834c74d0e9e708c36e3eb7ad30ecfc 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -39,6 +39,8 @@ #include <debug.h> #include "nfapi_nr_interface_scf.h" #include "nr_nfapi_p7.h" +#include "nr_fapi.h" +#include "nr_fapi_p7.h" extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppReadPackedMsg, void *user_data); extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppWritePackedMsg, void *user_data); @@ -62,15 +64,50 @@ int nfapi_p7_update_checksum(uint8_t *buffer, uint32_t len) { return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); } -int nfapi_p7_update_transmit_timestamp(uint8_t *buffer, uint32_t timestamp) { +int nfapi_p7_update_transmit_timestamp(uint8_t *buffer, uint32_t timestamp) +{ uint8_t *p_write = &buffer[12]; - return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); + return (push32(timestamp, &p_write, buffer + NFAPI_P7_HEADER_LENGTH) > 0 ? 0 : -1); } uint32_t nfapi_p7_calculate_checksum(uint8_t *buffer, uint32_t len) { return nfapi_calculate_checksum(buffer, len); } +uint32_t nfapi_nr_calculate_checksum(uint8_t *buffer, uint16_t len) +{ + uint32_t chksum = 0; + // calcaulte upto the checksum + chksum = crc32(chksum, buffer, 10); + // skip the checksum + uint8_t zeros[4] = {0, 0, 0, 0}; + chksum = crc32(chksum, zeros, 4); + // continu with the rest of the mesage + chksum = crc32(chksum, &buffer[NFAPI_NR_P7_HEADER_LENGTH], len - NFAPI_NR_P7_HEADER_LENGTH); + // return the inverse + return ~(chksum); +} + +int nfapi_nr_p7_update_checksum(uint8_t *buffer, uint32_t len) +{ + uint32_t checksum = nfapi_nr_calculate_checksum(buffer, len); + // 10 is the beginning position of checksum + uint8_t *p_write = &buffer[10]; + return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); +} + +int nfapi_nr_p7_update_transmit_timestamp(uint8_t *buffer, uint32_t timestamp) +{ + // 14 is the beginning position of transmit_timestamp + uint8_t *p_write = &buffer[14]; + return (push32(timestamp, &p_write, buffer + NFAPI_NR_P7_HEADER_LENGTH) > 0 ? 0 : -1); +} + +uint32_t nfapi_nr_p7_calculate_checksum(uint8_t *buffer, uint32_t len) +{ + return nfapi_nr_calculate_checksum(buffer, len); +} + void *nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t *config) { if(size == 0) return 0; @@ -198,174 +235,6 @@ static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t *value, uint8_t **ppW return 1; } -static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; - return (push16(value->bwp_size, ppWritePackedMsg, end) && push16(value->bwp_start, ppWritePackedMsg, end) - && push8(value->subcarrier_spacing, ppWritePackedMsg, end) && push8(value->cyclic_prefix, ppWritePackedMsg, end) - && push16(value->start_rb, ppWritePackedMsg, end) && push16(value->nr_of_rbs, ppWritePackedMsg, end) - && push8(value->csi_type, ppWritePackedMsg, end) && push8(value->row, ppWritePackedMsg, end) - && push16(value->freq_domain, ppWritePackedMsg, end) && push8(value->symb_l0, ppWritePackedMsg, end) - && push8(value->symb_l1, ppWritePackedMsg, end) && push8(value->cdm_type, ppWritePackedMsg, end) - && push8(value->freq_density, ppWritePackedMsg, end) && push16(value->scramb_id, ppWritePackedMsg, end) - && push8(value->power_control_offset, ppWritePackedMsg, end) - && push8(value->power_control_offset_ss, ppWritePackedMsg, end) && - // TODO Add Precoding and Beamforming, hardcoded for now - push16(0, ppWritePackedMsg, end) && push16(0, ppWritePackedMsg, end) && push8(0, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; - - if (!(push16(value->BWPSize, ppWritePackedMsg, end) && push16(value->BWPStart, ppWritePackedMsg, end) - && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && push8(value->CyclicPrefix, ppWritePackedMsg, end) - && push8(value->StartSymbolIndex, ppWritePackedMsg, end) && push8(value->DurationSymbols, ppWritePackedMsg, end) - && pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) - && push8(value->CceRegMappingType, ppWritePackedMsg, end) && push8(value->RegBundleSize, ppWritePackedMsg, end) - && push8(value->InterleaverSize, ppWritePackedMsg, end) && push8(value->CoreSetType, ppWritePackedMsg, end) - && push16(value->ShiftIndex, ppWritePackedMsg, end) && push8(value->precoderGranularity, ppWritePackedMsg, end) - && push16(value->numDlDci, ppWritePackedMsg, end))) { - return 0; - } - - for (uint16_t i = 0; i < value->numDlDci; ++i) { - if (!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) - && push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) - && push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) - && push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end))) { - return 0; - } - // Precoding and beamforming - // TODO get these values from elsewhere and delete the hardcoded ones - value->dci_pdu[i].precodingAndBeamforming.num_prgs = 0; - value->dci_pdu[i].precodingAndBeamforming.prg_size = 0; // 1 PRG of max size for analogue beamforming - value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces = 0; - value->dci_pdu[i].precodingAndBeamforming.prgs_list[0].pm_idx = 0; - value->dci_pdu[i].precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; - if (!(push16(value->dci_pdu[i].precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) - && push16(value->dci_pdu[i].precodingAndBeamforming.prg_size, ppWritePackedMsg, end) - && push8(value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { - return 0; - } - for (int prg = 0; prg < value->dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { - if (!push16(value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, ppWritePackedMsg, end)) { - return 0; - } - for (int digInt = 0; digInt < value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; digInt++) { - if (!push16(value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, - ppWritePackedMsg, - end)) { - return 0; - } - } - } - // TX Power info - if (!(push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) - && push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - // DCI Payload fields - push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - // Pack DCI Payload - pack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) { - return 0; - } - } - return 1; -} - -static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; - - if (!(push16(value->pduBitmap, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) - && push16(value->pduIndex, ppWritePackedMsg, end) && push16(value->BWPSize, ppWritePackedMsg, end) - && push16(value->BWPStart, ppWritePackedMsg, end) && push8(value->SubcarrierSpacing, ppWritePackedMsg, end) - && push8(value->CyclicPrefix, ppWritePackedMsg, end) && push8(value->NrOfCodewords, ppWritePackedMsg, end))) { - return 0; - } - for (int i = 0; i < value->NrOfCodewords; ++i) { - if (!(push16(value->targetCodeRate[i], ppWritePackedMsg, end) && push8(value->qamModOrder[i], ppWritePackedMsg, end) - && push8(value->mcsIndex[i], ppWritePackedMsg, end) && push8(value->mcsTable[i], ppWritePackedMsg, end) - && push8(value->rvIndex[i], ppWritePackedMsg, end) && push32(value->TBSize[i], ppWritePackedMsg, end))) { - return 0; - } - } - - if (!(push16(value->dataScramblingId, ppWritePackedMsg, end) && push8(value->nrOfLayers, ppWritePackedMsg, end) - && push8(value->transmissionScheme, ppWritePackedMsg, end) && push8(value->refPoint, ppWritePackedMsg, end) - && push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && push8(value->dmrsConfigType, ppWritePackedMsg, end) - && push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && push8(value->SCID, ppWritePackedMsg, end) - && push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && push16(value->dmrsPorts, ppWritePackedMsg, end) - && push8(value->resourceAlloc, ppWritePackedMsg, end) && (int)pusharray8(value->rbBitmap, 36, 36, ppWritePackedMsg, end) - && push16(value->rbStart, ppWritePackedMsg, end) && push16(value->rbSize, ppWritePackedMsg, end) - && push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && push8(value->StartSymbolIndex, ppWritePackedMsg, end) - && push8(value->NrOfSymbols, ppWritePackedMsg, end))) { - return 0; - } - - // Check pduBitMap bit 1 to add or not PTRS parameters - if (value->pduBitmap & 0b1) { - if (!(push8(value->PTRSPortIndex, ppWritePackedMsg, end) && push8(value->PTRSTimeDensity, ppWritePackedMsg, end) - && push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && push8(value->PTRSReOffset, ppWritePackedMsg, end) - && push8(value->nEpreRatioOfPDSCHToPTRS, ppWritePackedMsg, end))) { - return 0; - } - } - - if (!(push16(value->precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) - && push16(value->precodingAndBeamforming.prg_size, ppWritePackedMsg, end) - && push8(value->precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { - return 0; - } - for (int i = 0; i < value->precodingAndBeamforming.num_prgs; ++i) { - if (!push16(value->precodingAndBeamforming.prgs_list[i].pm_idx, ppWritePackedMsg, end)) { - return 0; - } - for (int k = 0; k < value->precodingAndBeamforming.dig_bf_interfaces; ++k) { - if (!push16(value->precodingAndBeamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, ppWritePackedMsg, end)) { - return 0; - } - } - } - // TODO Add TX power info - // Hardcoded values that represent 0db - if (!(push8(0, ppWritePackedMsg, end) && // powerControlOffset - push8(0, ppWritePackedMsg, end))) { // powerControlOffsetSS - return 0; - } - // TODO Add CBG Fields - return 1; -} - -static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing ssb. \n"); - nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; - - if (!(push16(value->PhysCellId, ppWritePackedMsg, end) && push8(value->BetaPss, ppWritePackedMsg, end) - && push8(value->SsbBlockIndex, ppWritePackedMsg, end) && push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) - && push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && push8(value->bchPayloadFlag, ppWritePackedMsg, end) - && push8((value->bchPayload >> 16) & 0xff, ppWritePackedMsg, end) - && push8((value->bchPayload >> 8) & 0xff, ppWritePackedMsg, end) && push8(value->bchPayload & 0xff, ppWritePackedMsg, end) - && push8(0, ppWritePackedMsg, end) - // TODO add Tx Power Info - && push16(value->precoding_and_beamforming.num_prgs, ppWritePackedMsg, end) - && push16(value->precoding_and_beamforming.prg_size, ppWritePackedMsg, end) - && push8(value->precoding_and_beamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { - return 0; - } - for (int i = 0; i < value->precoding_and_beamforming.num_prgs; ++i) { - if (!push16(value->precoding_and_beamforming.prgs_list[i].pm_idx, ppWritePackedMsg, end)) { - return 0; - } - for (int k = 0; k < value->precoding_and_beamforming.dig_bf_interfaces; ++k) { - if (!push16(value->precoding_and_beamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, ppWritePackedMsg, end)) { - return 0; - } - } - } - return 1; -} static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_dl_config_dci_dl_pdu_rel13_t *value = (nfapi_dl_config_dci_dl_pdu_rel13_t *)tlv; @@ -647,49 +516,6 @@ static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppWrit push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); } -static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)tlv; - uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; - if (!push16(value->PDUType, ppWritePackedMsg, end)) - return 0; - uint8_t *pPackedLengthField = *ppWritePackedMsg; - if (!push16(value->PDUSize, ppWritePackedMsg, end)) - return 0; - - // first match the pdu type, then call the respective function - switch (value->PDUType) { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { - if (!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15, ppWritePackedMsg, end))) - return 0; - } break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { - if (!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15, ppWritePackedMsg, end))) - return 0; - } break; - - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - if (!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15, ppWritePackedMsg, end))) - return 0; - } break; - - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { - if (!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15, ppWritePackedMsg, end))) - return 0; - } break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType); - } break; - } - // pack proper size - uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; - uint16_t packedMsgLen = msgEnd - msgHead; - value->PDUSize = packedMsgLen; - return push16(value->PDUSize, &pPackedLengthField, end); -} - static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_dl_config_request_body_t *value = (nfapi_dl_config_request_body_t *)tlv; @@ -830,34 +656,6 @@ static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePac return 1; } -uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; - - if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) - && push8(pNfapiMsg->dl_tti_request_body.nPDUs, ppWritePackedMsg, end) - && push8(pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end))) { - return 0; - } - for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { - if (!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i], ppWritePackedMsg, end)) - return 0; - } - - for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { - if (!push8(pNfapiMsg->dl_tti_request_body.nUe[i], ppWritePackedMsg, end)) - return 0; - for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { - if (!(push32(pNfapiMsg->dl_tti_request_body.PduIdx[i][j], ppWritePackedMsg, end))) { - return 0; - } - } - return 0; - } - - return 1; -} - static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && @@ -925,213 +723,6 @@ static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppW push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); } -//Pack fns for ul_tti PDUS - -static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!(push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) - && push8(prach_pdu->prach_format, ppWritePackedMsg, end) && push8(prach_pdu->num_ra, ppWritePackedMsg, end) - && push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && push16(prach_pdu->num_cs, ppWritePackedMsg, end))) { - return 0; - } - - // Pack RX Beamforming PDU - if (!(push16(prach_pdu->beamforming.num_prgs, ppWritePackedMsg, end) - && push16(prach_pdu->beamforming.prg_size, ppWritePackedMsg, end) - && push8(prach_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) - return 0; - - for (int prg = 0; prg < prach_pdu->beamforming.num_prgs; prg++) { - for (int digBFInterface = 0; digBFInterface < prach_pdu->beamforming.dig_bf_interface; digBFInterface++) { - if (!push16(prach_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) - return 0; - } - } - return 1; -} - -static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!(push16(pucch_pdu->rnti, ppWritePackedMsg, end) && push32(pucch_pdu->handle, ppWritePackedMsg, end) - && push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) - && push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) - && push8(pucch_pdu->format_type, ppWritePackedMsg, end) && push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) - && push8(pucch_pdu->pi_2bpsk, ppWritePackedMsg, end) && push16(pucch_pdu->prb_start, ppWritePackedMsg, end) - && push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) - && push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) - && push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) - && push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) - && push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) - && push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) - && push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) - && push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) - && push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) - && push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) - && push16(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) - && push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) - // Pack RX Beamforming PDU - && push16(pucch_pdu->beamforming.num_prgs, ppWritePackedMsg, end) - && push16(pucch_pdu->beamforming.prg_size, ppWritePackedMsg, end) - && push8(pucch_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) { - return 0; - } - - for (int prg = 0; prg < pucch_pdu->beamforming.num_prgs; prg++) { - for (int digBFInterface = 0; digBFInterface < pucch_pdu->beamforming.dig_bf_interface; digBFInterface++) { - if (!push16(pucch_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) - return 0; - } - } - return 1; -} - -static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!(push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && push16(pusch_pdu->rnti, ppWritePackedMsg, end) - && push32(pusch_pdu->handle, ppWritePackedMsg, end) && push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) - && push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) - && push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) - && push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) - && push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) - && push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) - && push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) - && push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) - && push16(pusch_pdu->pusch_identity, ppWritePackedMsg, end) && push8(pusch_pdu->scid, ppWritePackedMsg, end) - && push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) - && push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) - && pusharray8(pusch_pdu->rb_bitmap, 36, 36, ppWritePackedMsg, end) && push16(pusch_pdu->rb_start, ppWritePackedMsg, end) - && push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) - && push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) - && push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) - && push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) - && push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - )) { - return 0; - } - // Pack Optional Data only included if indicated in pduBitmap - switch (pusch_pdu->pdu_bit_map) { - case PUSCH_PDU_BITMAP_PUSCH_DATA: { - // pack optional TLVs - if (!(push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_data.new_data_indicator, ppWritePackedMsg, end) - && push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) - && push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) - && pusharray8(pusch_pdu->pusch_data.cb_present_and_position, - (pusch_pdu->pusch_data.num_cb + 7) / 8, - (pusch_pdu->pusch_data.num_cb + 7) / 8, - ppWritePackedMsg, - end))) { - return 0; - } - } break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: { - if (!(push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) - && push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) - && push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end))) { - return 0; - } - } break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: { - if (!push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end)) { - return 0; - } - for (int i = 0; i < pusch_pdu->pusch_ptrs.num_ptrs_ports; ++i) { - if (!(push16(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_port_index, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_dmrs_port, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_ptrs.ptrs_ports_list[i].ptrs_re_offset, ppWritePackedMsg, end))) { - return 0; - } - } - - if (!(push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) - && push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end))) { - return 0; - } - } break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: { - if (!(push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) - && push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) - && push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) - && push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end))) { - return 0; - } - } break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map); - } - } - // Pack RX Beamforming PDU - if (!(push16(pusch_pdu->beamforming.num_prgs, ppWritePackedMsg, end) - && push16(pusch_pdu->beamforming.prg_size, ppWritePackedMsg, end) - && push8(pusch_pdu->beamforming.dig_bf_interface, ppWritePackedMsg, end))) { - return 0; - } - for (int prg = 0; prg < pusch_pdu->beamforming.num_prgs; prg++) { - for (int digBFInterface = 0; digBFInterface < pusch_pdu->beamforming.dig_bf_interface; digBFInterface++) { - if (!push16(pusch_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, ppWritePackedMsg, end)) { - return 0; - } - } - } - return 1; -} - -static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t *srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { - if(!( - push16(srs_pdu->rnti, ppWritePackedMsg, end) && - push32(srs_pdu->handle, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && - push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && - push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && - push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && - push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && - push8(srs_pdu->config_index, ppWritePackedMsg, end) && - push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && - push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && - push8(srs_pdu->comb_size, ppWritePackedMsg, end) && - push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && - push16(srs_pdu->frequency_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->resource_type, ppWritePackedMsg, end) && - push16(srs_pdu->t_srs, ppWritePackedMsg, end) && - push16(srs_pdu->t_offset, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - )){ - return 0; - } - // Rx Beamforming PDU - if(!(push16(srs_pdu->beamforming.num_prgs,ppWritePackedMsg,end) && - push16(srs_pdu->beamforming.prg_size,ppWritePackedMsg,end) && - push8(srs_pdu->beamforming.dig_bf_interface,ppWritePackedMsg,end))){ - return 0; - } - for(int prg = 0; prg < srs_pdu->beamforming.num_prgs; prg ++){ - for(int digInt = 0; digInt < srs_pdu->beamforming.dig_bf_interface; digInt++){ - if(!push16(srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx,ppWritePackedMsg,end)){ - return 0; - } - } - } - return 1; -} - static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu *ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && @@ -1422,66 +1013,6 @@ static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t * push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); } -static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_tti_request_number_of_pdus_t *value = (nfapi_nr_ul_tti_request_number_of_pdus_t *)tlv; - uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; - if (!push16(value->pdu_type, ppWritePackedMsg, end)) { - return 0; - } - uint8_t *pPackedLengthField = *ppWritePackedMsg; - - if (!push16(value->pdu_size, ppWritePackedMsg, end)) - return 0; - // pack PDUs - // first match the pdu type, then call the respective function - switch (value->pdu_type) { - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { - if (!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) - return 0; - } break; - - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { - if (!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) - return 0; - } break; - - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { - if (!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) - return 0; - } break; - - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { - if (!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) - return 0; - } break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type); - } break; - } - - // pack proper size - uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; - uint16_t packedMsgLen = msgEnd - msgHead; - value->pdu_size = packedMsgLen; - return push16(value->pdu_size, &pPackedLengthField, end); -} - -static uint8_t pack_ul_tti_groups_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_ul_tti_request_number_of_groups_t *value = (nfapi_nr_ul_tti_request_number_of_groups_t *)tlv; - - if(!push8(value->n_ue, ppWritePackedMsg, end)) - return 0; - - for(int i=0; i<value->n_ue; i++) { - if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) - return 0; - } - - return 1; -} - static uint8_t pack_ul_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_ul_config_request_body_t *value = (nfapi_ul_config_request_body_t *)tlv; @@ -1655,52 +1186,6 @@ static uint8_t pack_ul_config_request_body_value(void *tlv, uint8_t **ppWritePac return 1; } -uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; - pNfapiMsg->n_ulcch = 0; - pNfapiMsg->n_ulsch = 0; - for (int i = 0; i < pNfapiMsg->n_pdus; i++) { - switch ((&pNfapiMsg->pdus_list[i])->pdu_type) { - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { - pNfapiMsg->n_ulcch++; - } break; - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { - pNfapiMsg->n_ulsch++; - } break; - default: - break; - } - } - - if (!push16(pNfapiMsg->SFN, ppWritePackedMsg, end)) - return 0; - if (!push16(pNfapiMsg->Slot, ppWritePackedMsg, end)) - return 0; - if (!push8(pNfapiMsg->n_pdus, ppWritePackedMsg, end)) - return 0; - if (!push8(pNfapiMsg->rach_present, ppWritePackedMsg, end)) - return 0; - if (!push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end)) - return 0; - if (!push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end)) - return 0; - if (!push8(pNfapiMsg->n_group, ppWritePackedMsg, end)) - return 0; - - for (int i = 0; i < pNfapiMsg->n_pdus; i++) { - if (!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) - return 0; - } - - for (int i = 0; i < pNfapiMsg->n_group; i++) { - if (!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) - return 0; - } - - return 1; -} - static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t *)msg; return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && @@ -1901,105 +1386,6 @@ static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePacke return 1; } -static uint8_t pack_ul_dci_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)tlv; - uintptr_t msgHead = (uintptr_t)*ppWritePackedMsg; - if (!push16(value->PDUType, ppWritePackedMsg, end)) { - return 0; - } - uint8_t *pPackedLengthField = *ppWritePackedMsg; - if (!(push16(value->PDUSize, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) - && push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) - && pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) - && push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) - && push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end))) { - return 0; - } - for (int i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { - if (!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) - && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) - && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end))) { - return 0; - } - // Precoding and Beamforming - // TODO get these values from elsewhere and delete the hardcoded ones - value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs = 0; - value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size = 0; - value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces = 0; - value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[0].pm_idx = 0; - value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0; - - if (!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs, ppWritePackedMsg, end) - && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, ppWritePackedMsg, end))) { - return 0; - } - for (int prg = 0; prg < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { - if (!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, - ppWritePackedMsg, - end)) { - return 0; - } - for (int digInt = 0; digInt < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; - digInt++) { - if (!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i] - .precodingAndBeamforming.prgs_list[prg] - .dig_bf_interface_list[digInt] - .beam_idx, - ppWritePackedMsg, - end)) { - return 0; - } - } - } - if (!(push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) - && push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - // DCI Payload fields - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - // Pack DCI Payload - pack_dci_payload(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, - value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, - ppWritePackedMsg, - end))) { - return 0; - } - } - - // pack proper size - uintptr_t msgEnd = (uintptr_t)*ppWritePackedMsg; - uint16_t packedMsgLen = msgEnd - msgHead; - value->PDUSize = packedMsgLen; - return push16(value->PDUSize, &pPackedLengthField, end); -} - -uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; - - if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) - && push8(pNfapiMsg->numPdus, ppWritePackedMsg, end))) - return 0; - - for (int i = 0; i < pNfapiMsg->numPdus; i++) { - if (!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) - return 0; - } - - return 1; -} - static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t *)msg; return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && @@ -2008,55 +1394,6 @@ static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8 } //pack_tx_data_pdu_list_value -static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv; - if (!(push32(value->PDU_length, ppWritePackedMsg, end) && push16(value->PDU_index, ppWritePackedMsg, end) - && push32(value->num_TLV, ppWritePackedMsg, end))) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_tlvs = value->num_TLV; - - for (; i < total_number_of_tlvs; ++i) { - if (!(push16(value->TLVs[i].tag, ppWritePackedMsg, end) && push32(value->TLVs[i].length, ppWritePackedMsg, end))) - return 0; - - switch (value->TLVs[i].tag) { - case 0: { - if (!pusharray32(value->TLVs[i].value.direct, - (value->TLVs[i].length + 3) / 4, - (value->TLVs[i].length + 3) / 4, - ppWritePackedMsg, - end)) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); - return 0; - } - break; - } - - case 1: { - if (!pusharray32(value->TLVs[i].value.ptr, - (value->TLVs[i].length + 3) / 4, - (value->TLVs[i].length + 3) / 4, - ppWritePackedMsg, - end)) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s():%d. value->TLVs[i].length %d \n", __FUNCTION__, __LINE__, value->TLVs[i].length); - return 0; - } - - break; - } - - default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag); - break; - } - } - } - - return 1; -} static uint8_t pack_tx_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_tx_request_body_t *value = (nfapi_tx_request_body_t *)tlv; @@ -2101,30 +1438,6 @@ static uint8_t pack_tx_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, return 1; } -static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - - if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end) - && push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end))) - return 0; - - for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { - if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, - "%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n", - __FUNCTION__, - __LINE__, - i, - pNfapiMsg->pdu_list[i].PDU_length, - pNfapiMsg->pdu_list[i].PDU_index); - return 0; - } - } - - return 1; -} - static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t *)msg; int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); @@ -3157,119 +2470,79 @@ uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, //NR UPLINK indication function packing -//SLOT INDICATION - -uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t *)msg; - - if (!(push16((uint16_t)pNfapiMsg->sfn, ppWritePackedMsg, end) && push16((uint16_t)pNfapiMsg->slot, ppWritePackedMsg, end))) - return 0; - - return 1; -} - -//RX DATA INDICATION +//SRS INDICATION -static uint8_t pack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) +int pack_nr_srs_channel_svd_representation(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen) { - if (!(push32(value->handle, ppWritePackedMsg, end) - && push16(value->rnti, ppWritePackedMsg, end) - && push8(value->harq_id, ppWritePackedMsg, end) - && push32(value->pdu_length, ppWritePackedMsg, end) - && push8(value->ul_cqi, ppWritePackedMsg, end) - && push16(value->timing_advance, ppWritePackedMsg, end) - && push16(value->rssi, ppWritePackedMsg, end))) - return 0; - - if (pusharray8(value->pdu, value->pdu_length, value->pdu_length, ppWritePackedMsg, end) == 0) - return 0; + nfapi_nr_srs_channel_svd_representation_t *value = (nfapi_nr_srs_channel_svd_representation_t *)pMessageBuf; - return 1; -} + const uint16_t iq_size = value->normalized_iq_representation == 0 ? 2 : 4; + const uint16_t ng = value->num_gnb_antenna_elements; + const uint8_t nu = value->num_ue_srs_ports; -uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t *)msg; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *end = pPackedBuf + packedBufLen; - if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) - && push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) + if (!(push8(value->normalized_iq_representation, &pWritePackedMessage, end) + && push8(value->normalized_singular_value_representation, &pWritePackedMessage, end) + && pushs8(value->singular_value_scaling, &pWritePackedMessage, end) + && push16(value->num_gnb_antenna_elements, &pWritePackedMessage, end) + && push8(value->num_ue_srs_ports, &pWritePackedMessage, end) && push16(value->prg_size, &pWritePackedMessage, end) + && push16(value->num_prgs, &pWritePackedMessage, end))) { return 0; - - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { - if (!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) - return 0; } - return 1; -} - -//NR CRC INDICATION - -static uint8_t pack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!(push32(value->handle, ppWritePackedMsg, end) && push16(value->rnti, ppWritePackedMsg, end) - && push8(value->harq_id, ppWritePackedMsg, end) && push8(value->tb_crc_status, ppWritePackedMsg, end) - && push16(value->num_cb, ppWritePackedMsg, end))) { - return 0; - } - if (value->num_cb != 0) { - if (!pusharray8(value->cb_crc_status, - (int)(value->num_cb / 8) + 1, - (int)(value->num_cb / 8) + 1, - ppWritePackedMsg, - end)) { // length is ceil(NumCb/8) + for (int prg_idx = 0; prg_idx < value->num_prgs; ++prg_idx) { + const nfapi_nr_srs_channel_svd_representation_prg_t *prg = &value->prg_list[prg_idx]; + if (!(pusharray8(prg->left_eigenvectors_matrix_u, nu * nu * iq_size, nu * nu * iq_size, &pWritePackedMessage, end))) { return 0; } - } - if (!(push8(value->ul_cqi, ppWritePackedMsg, end) && push16(value->timing_advance, ppWritePackedMsg, end) - && push16(value->rssi, ppWritePackedMsg, end))) { - return 0; - } - return 1; -} - -uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *)msg; - - if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) - && push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end))) - return 0; - - for (int i = 0; i < pNfapiMsg->number_crcs; i++) { - if (!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end)) + if (!(pusharray8(prg->diagonal_entries_of_singular_matrix_sum_f, nu * iq_size, nu * iq_size, &pWritePackedMessage, end))) { + return 0; + } + if (!(pusharray8(prg->complex_conjugate_of_matrix_of_right_eigenvectors_v_hf, + nu * ng * iq_size, + nu * ng * iq_size, + &pWritePackedMessage, + end))) { return 0; + } } - return 1; + // Message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + return (msgEnd - msgHead); } -//SRS INDICATION - -int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen) { - - nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix = (nfapi_nr_srs_normalized_channel_iq_matrix_t*)pMessageBuf; +int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen) +{ + nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix = + (nfapi_nr_srs_normalized_channel_iq_matrix_t *)pMessageBuf; uint8_t *pWritePackedMessage = pPackedBuf; uint8_t *end = pPackedBuf + packedBufLen; - if(!(push8(nr_srs_normalized_channel_iq_matrix->normalized_iq_representation, &pWritePackedMessage, end) && - push16(nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements, &pWritePackedMessage, end) && - push16(nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports, &pWritePackedMessage, end) && - push16(nr_srs_normalized_channel_iq_matrix->prg_size, &pWritePackedMessage, end) && - push16(nr_srs_normalized_channel_iq_matrix->num_prgs, &pWritePackedMessage, end))) { + if (!(push8(nr_srs_normalized_channel_iq_matrix->normalized_iq_representation, &pWritePackedMessage, end) + && push16(nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements, &pWritePackedMessage, end) + && push16(nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports, &pWritePackedMessage, end) + && push16(nr_srs_normalized_channel_iq_matrix->prg_size, &pWritePackedMessage, end) + && push16(nr_srs_normalized_channel_iq_matrix->num_prgs, &pWritePackedMessage, end))) { return 0; } - uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs*nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports*nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements; + uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs + * nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports + * nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements; if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) { + // 0: 16-bit normalized complex number (iqSize = 2) channel_matrix_size <<= 1; } else { + // 1: 32-bit normalized complex number (iqSize = 4) channel_matrix_size <<= 2; } - for(int i = 0; i < channel_matrix_size; i++) { + for (int i = 0; i < channel_matrix_size; i++) { if (!push8(nr_srs_normalized_channel_iq_matrix->channel_matrix[i], &pWritePackedMessage, end)) { return 0; } @@ -3278,7 +2551,7 @@ int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf // Message length uintptr_t msgHead = (uintptr_t)pPackedBuf; uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - return (msgEnd-msgHead); + return (msgEnd - msgHead); } static uint8_t pack_nr_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *prgs, uint8_t **ppWritePackedMsg, uint8_t *end) { @@ -3296,476 +2569,159 @@ static uint8_t pack_nr_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *prgs, return 1; } -int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen) { - - nfapi_nr_srs_beamforming_report_t *nr_srs_beamforming_report = (nfapi_nr_srs_beamforming_report_t*)pMessageBuf; +int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen) +{ + nfapi_nr_srs_beamforming_report_t *nr_srs_beamforming_report = (nfapi_nr_srs_beamforming_report_t *)pMessageBuf; uint8_t *pWritePackedMessage = pPackedBuf; uint8_t *end = pPackedBuf + packedBufLen; - if(!(push16(nr_srs_beamforming_report->prg_size, &pWritePackedMessage, end) && - push8(nr_srs_beamforming_report->num_symbols, &pWritePackedMessage, end) && - push8(nr_srs_beamforming_report->wide_band_snr, &pWritePackedMessage, end) && - push8(nr_srs_beamforming_report->num_reported_symbols, &pWritePackedMessage, end))) { + if (!(push16(nr_srs_beamforming_report->prg_size, &pWritePackedMessage, end) + && push8(nr_srs_beamforming_report->num_symbols, &pWritePackedMessage, end) + && push8(nr_srs_beamforming_report->wide_band_snr, &pWritePackedMessage, end) + && push8(nr_srs_beamforming_report->num_reported_symbols, &pWritePackedMessage, end))) { return 0; } - if (!pack_nr_srs_reported_symbol(&nr_srs_beamforming_report->prgs, &pWritePackedMessage, end)) { - return 0; + for (int reported_symbol = 0; reported_symbol < nr_srs_beamforming_report->num_reported_symbols; ++reported_symbol) { + if (!pack_nr_srs_reported_symbol(&nr_srs_beamforming_report->reported_symbol_list[reported_symbol], + &pWritePackedMessage, + end)) { + return 0; + } } // Message length uintptr_t msgHead = (uintptr_t)pPackedBuf; uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - return (msgEnd-msgHead); + return (msgEnd - msgHead); } -static uint8_t pack_nr_srs_report_tlv(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { +// Main pack function - public - if(!(push16(report_tlv->tag, ppWritePackedMsg, end) && - push32(report_tlv->length, ppWritePackedMsg, end))) { - return 0; - } +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) +{ + nfapi_nr_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - for(int i = 0; i < report_tlv->length; i++) { - if (!push32(report_tlv->value[i], ppWritePackedMsg, end)) { - return 0; - } + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; } - return 1; -} - -static uint8_t pack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { + uint8_t *end = (uint8_t *)pPackedBuf + packedBufLen; - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->timing_advance_offset, ppWritePackedMsg, end) && - pushs16(value->timing_advance_offset_nsec, ppWritePackedMsg, end) && - push8(value->srs_usage, ppWritePackedMsg, end) && - push8(value->report_type, ppWritePackedMsg, end))) { - return 0; + // process the header + if (!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && push16(pMessageHeader->message_id, &pWritePackedMessage, end) + && push32(0 /*pMessageHeader->message_length*/, &pWritePackedMessage, end) + && push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) + && push32(0 /*pMessageHeader->checksum*/, &pWritePackedMessage, end) + && push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; } - if (!pack_nr_srs_report_tlv(&value->report_tlv, ppWritePackedMsg, end)) { - return 0; + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, + // pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; - return 1; -} + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; -uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t *)msg; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; - if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) - && push16(pNfapiMsg->control_length, ppWritePackedMsg, end) && push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) { - return 0; - } + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_UE_RELEASE_REQUEST: + result = pack_nr_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { - if (!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) { - return 0; - } - } + case NFAPI_UE_RELEASE_RESPONSE: + result = pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; - return 1; -} + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; -//RACH INDICATION + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; -static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; - - if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && - push8(value->symbol_index, ppWritePackedMsg, end) && - push8(value->slot_index, ppWritePackedMsg, end) && - push8(value->freq_index, ppWritePackedMsg, end) && - push8(value->avg_rssi, ppWritePackedMsg, end) && - push8(value->avg_snr, ppWritePackedMsg, end) && - push8(value->num_preamble, ppWritePackedMsg, end) - )) - return 0; - for(int i = 0; i < value->num_preamble; i++) - { - if(!(push8(value->preamble_list[i].preamble_index, ppWritePackedMsg, end) && - push16(value->preamble_list[i].timing_advance, ppWritePackedMsg, end) && - push32(value->preamble_list[i].preamble_pwr, ppWritePackedMsg, end) - )) - return 0; - } - return 1; -} + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; -uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg; + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end) - && push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) - return 0; + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { - if (!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) - return 0; - } + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - return 1; -} + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; -//UCI INDICATION + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; -static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + case NFAPI_TIMING_INFO: + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; - if (!push8(value->pduBitmap, ppWritePackedMsg, end)) - return 0; - if (!push32(value->handle, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rnti, ppWritePackedMsg, end)) - return 0; - if (!push8(value->pucch_format, ppWritePackedMsg, end)) - return 0; - if (!push8(value->ul_cqi, ppWritePackedMsg, end)) - return 0; - if (!push16(value->timing_advance, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rssi, ppWritePackedMsg, end)) - return 0; - if (value->pduBitmap & 0x01) { //SR - if (!push8(value->sr.sr_indication, ppWritePackedMsg, end)) - return 0; - if (!push8(value->sr.sr_confidence_level, ppWritePackedMsg, end)) - return 0; - } + default: { + if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (config && config->pack_p7_vendor_extension) { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s VE NFAPI message ID %d. No ve ecoder provided\n", + __FUNCTION__, + pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } break; + } - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if (!push8(value->harq.num_harq, ppWritePackedMsg, end)) - return 0; - if (!push8(value->harq.harq_confidence_level, ppWritePackedMsg, end)) - return 0; - for (int i = 0; i < value->harq.num_harq; i++) - { - if (!push8(value->harq.harq_list[i].harq_value, ppWritePackedMsg, end)) - return 0; - } - } + if (result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } - return 1; -} + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + if (packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } -static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen; - if (!push8(value->pduBitmap, ppWritePackedMsg, end)) - return 0; - if (!push32(value->handle, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rnti, ppWritePackedMsg, end)) - return 0; - if (!push8(value->pucch_format-2, ppWritePackedMsg, end)) - return 0; - if (!push8(value->ul_cqi, ppWritePackedMsg, end)) - return 0; - if (!push16(value->timing_advance, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rssi, ppWritePackedMsg, end)) - return 0; - - if (value->pduBitmap & 0x01) { //SR - if (!push16(value->sr.sr_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->sr.sr_payload, - (int)((value->sr.sr_bit_len / 8) + 1), - (int)((value->sr.sr_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } - - if ((value->pduBitmap >> 1) & 0x01) { //HARQ - if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->harq.harq_payload, - (int)((value->harq.harq_bit_len / 8) + 1), - (int)((value->harq.harq_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } - - if ((value->pduBitmap >> 2) & 0x01) { //CSI-1 - if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->csi_part1.csi_part1_payload, - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } - - if ((value->pduBitmap >> 3) & 0x01) { //CSI-2 - if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) - return 0; - if (!pusharray8(value->csi_part2.csi_part2_payload, - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } - - return 1; -} - -static uint8_t pack_nr_uci_pusch(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_uci_pusch_pdu_t *value = (nfapi_nr_uci_pusch_pdu_t *)tlv; - - if (!push8(value->pduBitmap, ppWritePackedMsg, end)) - return 0; - if (!push32(value->handle, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rnti, ppWritePackedMsg, end)) - return 0; - if (!push8(value->ul_cqi, ppWritePackedMsg, end)) - return 0; - if (!push16(value->timing_advance, ppWritePackedMsg, end)) - return 0; - if (!push16(value->rssi, ppWritePackedMsg, end)) - return 0; - - // Bit 0 not used in PUSCH PDU - if ((value->pduBitmap >> 1) & 0x01) { // HARQ - if (!push8(value->harq.harq_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end)) - return 0; - - if (!pusharray8(value->harq.harq_payload, - (int)((value->harq.harq_bit_len / 8) + 1), - (int)((value->harq.harq_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } - - if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 - if (!push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end)) - return 0; - - if (!pusharray8(value->csi_part1.csi_part1_payload, - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } - - if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 - if (!push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end)) - return 0; - if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end)) - return 0; - - if (!pusharray8(value->csi_part2.csi_part2_payload, - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - ppWritePackedMsg, - end)) - return 0; - } - - return 1; -} - -static uint8_t pack_nr_uci_indication_body(nfapi_nr_uci_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!push16(value->pdu_type, ppWritePackedMsg, end)) - return 0; - if (!push16(value->pdu_size, ppWritePackedMsg, end)) - return 0; - - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - if(!pack_nr_uci_pusch(&value->pusch_pdu, ppWritePackedMsg, end)){ - return 0; - } - break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: - if(!pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end)){ - return 0; - } - break; - - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: - if(!pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end)){ - return 0; - } - break; - } - - return 1; -} - -uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg; - - if (!push16(pNfapiMsg->sfn, ppWritePackedMsg, end)) - return 0; - if (!push16(pNfapiMsg->slot, ppWritePackedMsg, end)) - return 0; - if (!push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end)) - return 0; - - for (int i = 0; i < pNfapiMsg->num_ucis; i++) { - if (!pack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppWritePackedMsg, end)) - return 0; - } - - return 1; -} - -// Main pack function - public - -int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - - if (pMessageBuf == NULL || pPackedBuf == NULL) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - - uint8_t *end = (uint8_t *)pPackedBuf + packedBufLen; - - // process the header - if (!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && push16(pMessageHeader->message_id, &pWritePackedMessage, end) - && push16(0 /*pMessageHeader->message_length*/, &pWritePackedMessage, end) - && push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) - && push32(0 /*pMessageHeader->checksum*/, &pWritePackedMessage, end) - && push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, - // pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); - } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_UE_RELEASE_REQUEST: - result = pack_nr_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - result = pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: - result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: { - if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { - if (config && config->pack_p7_vendor_extension) { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, - "%s VE NFAPI message ID %d. No ve ecoder provided\n", - __FUNCTION__, - pMessageHeader->message_id); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } break; - } - - if (result == 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } else { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if (!push16(packedMsgLen16, &pPackedLengthField, end)) + if (!push32(pMessageHeader->message_length, &pPackedLengthField, end)) return -1; if (1) { @@ -3947,179 +2903,6 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu // Unpack routines // NR: -static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; - uint16_t num_prgs = 0, prg_size = 0; - uint8_t dig_bf_interfaces = 0; - return (pull16(ppReadPackedMsg, &value->bwp_size, end) && pull16(ppReadPackedMsg, &value->bwp_start, end) - && pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &value->cyclic_prefix, end) - && pull16(ppReadPackedMsg, &value->start_rb, end) && pull16(ppReadPackedMsg, &value->nr_of_rbs, end) - && pull8(ppReadPackedMsg, &value->csi_type, end) && pull8(ppReadPackedMsg, &value->row, end) - && pull16(ppReadPackedMsg, &value->freq_domain, end) && pull8(ppReadPackedMsg, &value->symb_l0, end) - && pull8(ppReadPackedMsg, &value->symb_l1, end) && pull8(ppReadPackedMsg, &value->cdm_type, end) - && pull8(ppReadPackedMsg, &value->freq_density, end) && pull16(ppReadPackedMsg, &value->scramb_id, end) - && pull8(ppReadPackedMsg, &value->power_control_offset, end) - && pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) && - // Precoding and Beamforming hardcoded to 0 - pull16(ppReadPackedMsg, &num_prgs, end) && pull16(ppReadPackedMsg, &prg_size, end) - && pull8(ppReadPackedMsg, &dig_bf_interfaces, end)); -} - -static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t *)tlv; - - if (!(pull16(ppReadPackedMsg, &value->BWPSize, end) && pull16(ppReadPackedMsg, &value->BWPStart, end) - && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) - && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && pull8(ppReadPackedMsg, &value->DurationSymbols, end) - && pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) - && pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && pull8(ppReadPackedMsg, &value->RegBundleSize, end) - && pull8(ppReadPackedMsg, &value->InterleaverSize, end) && pull8(ppReadPackedMsg, &value->CoreSetType, end) - && pull16(ppReadPackedMsg, &value->ShiftIndex, end) && pull8(ppReadPackedMsg, &value->precoderGranularity, end) - && pull16(ppReadPackedMsg, &value->numDlDci, end))) { - return 0; - } - - for (uint16_t i = 0; i < value->numDlDci; ++i) { - if (!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) - && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) - && pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) - && pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) - && pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.num_prgs, end) - && pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.prg_size, end) - && pull8(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, end))) { - return 0; - } - for (int prg = 0; prg < value->dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { - if (!pull16(ppReadPackedMsg, &value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, end)) { - return 0; - } - for (int digInt = 0; digInt < value->dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; digInt++) { - if (!pull16(ppReadPackedMsg, - &value->dci_pdu[i].precodingAndBeamforming.prgs_list[prg].dig_bf_interface_list[digInt].beam_idx, - end)) { - return 0; - } - } - } - if (!(pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) - && pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) - && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) - && unpack_dci_payload(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, ppReadPackedMsg, end))) { - return 0; - } - } - // TODO: resolve the packaging of array (currently sending a single element) - return 1; -} - -static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; - // TODO: resolve the packaging of array (currently sending a single element) - uint8_t powerControlOffset = 0, powerControlOffsetSS = 0; - - if (!(pull16(ppReadPackedMsg, &value->pduBitmap, end) && pull16(ppReadPackedMsg, &value->rnti, end) - && pull16(ppReadPackedMsg, &value->pduIndex, end) && pull16(ppReadPackedMsg, &value->BWPSize, end) - && pull16(ppReadPackedMsg, &value->BWPStart, end) && pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) - && pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && pull8(ppReadPackedMsg, &value->NrOfCodewords, end))) { - return 0; - } - for (int i = 0; i < value->NrOfCodewords; ++i) { - if (!(pull16(ppReadPackedMsg, &value->targetCodeRate[i], end) && pull8(ppReadPackedMsg, &value->qamModOrder[i], end) - && pull8(ppReadPackedMsg, &value->mcsIndex[i], end) && pull8(ppReadPackedMsg, &value->mcsTable[i], end) - && pull8(ppReadPackedMsg, &value->rvIndex[i], end) && pull32(ppReadPackedMsg, &value->TBSize[i], end))) { - return 0; - } - } - - if (!(pull16(ppReadPackedMsg, &value->dataScramblingId, end) && pull8(ppReadPackedMsg, &value->nrOfLayers, end) - && pull8(ppReadPackedMsg, &value->transmissionScheme, end) && pull8(ppReadPackedMsg, &value->refPoint, end) - && pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && pull8(ppReadPackedMsg, &value->dmrsConfigType, end) - && pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && pull8(ppReadPackedMsg, &value->SCID, end) - && pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && pull16(ppReadPackedMsg, &value->dmrsPorts, end) - && pull8(ppReadPackedMsg, &value->resourceAlloc, end) && pullarray8(ppReadPackedMsg, &value->rbBitmap[0], 36, 36, end) - && pull16(ppReadPackedMsg, &value->rbStart, end) && pull16(ppReadPackedMsg, &value->rbSize, end) - && pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) - && pull8(ppReadPackedMsg, &value->NrOfSymbols, end))) { - return 0; - } - // Check pduBitMap bit 1 to pull PTRS parameters or not - if (value->pduBitmap & 0b1) { - if (!(pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) - && pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && pull8(ppReadPackedMsg, &value->PTRSReOffset, end) - && pull8(ppReadPackedMsg, &value->nEpreRatioOfPDSCHToPTRS, end))) { - return 0; - } - } - - if (!(pull16(ppReadPackedMsg, &value->precodingAndBeamforming.num_prgs, end) - && pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prg_size, end) - && pull8(ppReadPackedMsg, &value->precodingAndBeamforming.dig_bf_interfaces, end))) { - return 0; - } - - for (int i = 0; i < value->precodingAndBeamforming.num_prgs; ++i) { - if (!pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prgs_list[i].pm_idx, end)) { - return 0; - } - for (int k = 0; k < value->precodingAndBeamforming.dig_bf_interfaces; ++k) { - if (!pull16(ppReadPackedMsg, &value->precodingAndBeamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, end)) { - return 0; - } - } - } - // TODO Add TX power info - // Hardcoded values that represent 0db - - if (!(pull8(ppReadPackedMsg, &powerControlOffset, end) && // powerControlOffset - pull8(ppReadPackedMsg, &powerControlOffsetSS, end))) { // powerControlOffsetSS - return 0; - } - // TODO Add CBG Fields - return 1; -} - -static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Unpacking ssb. \n"); - uint8_t byte3, byte2, byte1, byte0; - nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; - - if (!(pull16(ppReadPackedMsg, &value->PhysCellId, end) && pull8(ppReadPackedMsg, &value->BetaPss, end) - && pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) - && pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) - && pull8(ppReadPackedMsg, &byte3, end) && pull8(ppReadPackedMsg, &byte2, end) && pull8(ppReadPackedMsg, &byte1, end) - && pull8(ppReadPackedMsg, &byte0, end))) { // this should be always 0, bchpayload is 24 bits - return 0; - } - // rebuild the bchpayload - value->bchPayload = byte3; - value->bchPayload = value->bchPayload << 8; - value->bchPayload |= byte2; - value->bchPayload = value->bchPayload << 8; - value->bchPayload |= byte1; - // TODO add Tx Power Info - if (!(pull8(ppReadPackedMsg, &byte1, end) && pull8(ppReadPackedMsg, &byte0, end) - && pull16(ppReadPackedMsg, &value->precoding_and_beamforming.num_prgs, end) - && pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prg_size, end) - && pull8(ppReadPackedMsg, &value->precoding_and_beamforming.dig_bf_interfaces, end))) { - return 0; - } - - for (int i = 0; i < value->precoding_and_beamforming.num_prgs; ++i) { - if (!pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prgs_list[i].pm_idx, end)) { - return 0; - } - for (int k = 0; k < value->precoding_and_beamforming.dig_bf_interfaces; ++k) { - if (!pull16(ppReadPackedMsg, &value->precoding_and_beamforming.prgs_list[i].dig_bf_interface_list[k].beam_idx, end)) { - return 0; - } - } - } - return 1; -} // LTE: static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { @@ -4510,51 +3293,6 @@ static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppRe } -static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { - nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)msg; - - if(!(pull16(ppReadPackedMsg, &value->PDUType, end) && - pull16(ppReadPackedMsg, (uint16_t *) &value->PDUSize, end))) - return 0; - - // first match the pdu type, then call the respective function - switch(value->PDUType) { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { - if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { - if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { - if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; - } - - return 1; -} - - - - static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { nfapi_dl_config_request_body_t *value = (nfapi_dl_config_request_body_t *)tlv; @@ -4723,291 +3461,6 @@ static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPa return 1; } -static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) - && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) - && pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end))) { - return 0; - } - for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nPDUs; i++) { - if (!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) - return 0; - } - - int arr[12]; - if (!pullarray8(ppReadPackedMsg, pNfapiMsg->dl_tti_request_body.nUe, 256, pNfapiMsg->dl_tti_request_body.nGroup, end)) { - return 0; - } - for (int i = 0; i < pNfapiMsg->dl_tti_request_body.nGroup; i++) { - for (int j = 0; j < pNfapiMsg->dl_tti_request_body.nUe[i]; j++) { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - - if (!(pullarrays32(ppReadPackedMsg, arr, 12, pNfapiMsg->dl_tti_request_body.nUe[i], end))) - return 0; - } - - return 1; -} - -static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_prach_pdu_t *prach_pdu = (nfapi_nr_prach_pdu_t *)tlv; - - if (!(pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) - && pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) - && pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && pull16(ppReadPackedMsg, &prach_pdu->num_cs, end))) { - return 0; - } - // Unpack RX Beamforming PDU - if (!(pull16(ppReadPackedMsg, &prach_pdu->beamforming.num_prgs, end) - && pull16(ppReadPackedMsg, &prach_pdu->beamforming.prg_size, end) - && pull8(ppReadPackedMsg, &prach_pdu->beamforming.dig_bf_interface, end))) { - return 0; - } - for (int prg = 0; prg < prach_pdu->beamforming.num_prgs; prg++) { - for (int digBFInterface = 0; digBFInterface < prach_pdu->beamforming.dig_bf_interface; digBFInterface++) { - if (!pull16(ppReadPackedMsg, &prach_pdu->beamforming.prgs_list[prg].dig_bf_interface_list[digBFInterface].beam_idx, end)) { - return 0; - } - } - } - - return 1; -} - -static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pucch_pdu_t *pucch_pdu = (nfapi_nr_pucch_pdu_t *)tlv; - uint16_t dummy16 = 0; - uint8_t dummy8 = 0; - return (pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && pull32(ppReadPackedMsg, &pucch_pdu->handle, end) - && pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) - && pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) - && pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) - && pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && pull8(ppReadPackedMsg, &pucch_pdu->pi_2bpsk, end) - && pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) - && pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) - && pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) - && pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) - && pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) - && pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) - && pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) - && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) - && pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) - && pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) - && pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) - && pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) && - // TODO: ignoring beamforming tlv for now - pull16(ppReadPackedMsg, &dummy16, end) && pull16(ppReadPackedMsg, &dummy16, end) && pull8(ppReadPackedMsg, &dummy8, end)); -} - -static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pusch_pdu_t *pusch_pdu = (nfapi_nr_pusch_pdu_t *)tlv; - - if (!(pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) - && pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) - && pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) - && pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) - && pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) - && pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) - && pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) - && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) - && pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && pull8(ppReadPackedMsg, &pusch_pdu->scid, end) - && pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) - && pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) - && pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) - && pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) - && pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) - && pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) - && pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) - && pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) - // TODO: ignoring beamforming tlv for now - )) - return 0; - - // Pack Optional Data only included if indicated in pduBitmap - switch (pusch_pdu->pdu_bit_map) { - case PUSCH_PDU_BITMAP_PUSCH_DATA: { - // pack optional TLVs - if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) - && pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) - && pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) - && pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position, 1, 1, end))) { - return 0; - } - } break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: { - if (!(pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) - && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) - && pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end))) { - return 0; - } - } break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: { - if (!(pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) - && pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) - && pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end))) { - return 0; - } - } break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: { - if (!(pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) - && pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) - && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) - && pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end))) { - return 0; - } - } break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map); - } - } - uint16_t dummy16 = 0; - uint8_t dummy8 = 0; - if (!(pull16(ppReadPackedMsg, &dummy16, end) && pull16(ppReadPackedMsg, &dummy16, end) && pull8(ppReadPackedMsg, &dummy8, end))) { - return 0; - } - - return 1; -} - -static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_srs_pdu_t *srs_pdu = (nfapi_nr_srs_pdu_t *)tlv; - return( - pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && - pull32(ppReadPackedMsg, &srs_pdu->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && - pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && - pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && - pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && - pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && - pull16(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { - nfapi_nr_ul_tti_request_number_of_pdus_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t *)msg; - - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) )) - return 0; - - // first natch the pdu type, then call the respective function - switch(pNfapiMsg->pdu_type) { - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { - if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { - if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { - if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { - if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); - } - break; - } - - return 1; -} - - -static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { - nfapi_nr_ul_tti_request_number_of_groups_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t *)msg; - - if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) - return 0; - - for (int i = 0; i < pNfapiMsg->n_ue; i++) { - if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx,end) ) - return 0; - } - - return 1; -} - -static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; - - if (!pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end)) - return 0; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end)) - return 0; - if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end)) - return 0; - if (!pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end)) - return 0; - if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end)) - return 0; - if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end)) - return 0; - if (!pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end)) - return 0; - for (int i = 0; i < pNfapiMsg->n_pdus; i++) { - if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) - return 0; - } - - for (int i = 0; i < pNfapiMsg->n_group; i++) { - if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) - return 0; - } - - return 1; -} - static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; unpack_p7_tlv_t unpack_fns[] = { @@ -5786,88 +4239,6 @@ static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPack return 1; } -//unpack_ul_dci_pdu_list_value - -static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_dci_request_pdus_t *value = (nfapi_nr_ul_dci_request_pdus_t *)msg; - - if (!(pull16(ppReadPackedMsg, &value->PDUType, end) && pull16(ppReadPackedMsg, &value->PDUSize, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) - && pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end))) { - return 0; - } - - for (uint16_t i = 0; i < value->pdcch_pdu.pdcch_pdu_rel15.numDlDci; ++i) { - if (!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prg_size, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces, end))) { - return 0; - } - for (int prg = 0; prg < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.num_prgs; prg++) { - if (!pull16(ppReadPackedMsg, - &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.prgs_list[prg].pm_idx, - end)) { - return 0; - } - for (int digInt = 0; digInt < value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].precodingAndBeamforming.dig_bf_interfaces; - digInt++) { - if (!pull16(ppReadPackedMsg, - &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i] - .precodingAndBeamforming.prgs_list[prg] - .dig_bf_interface_list[digInt] - .beam_idx, - end)) { - return 0; - } - } - } - if (!(pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) - && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) - && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) - && unpack_dci_payload(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, - value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, - ppReadPackedMsg, - end))) { - return 0; - } - } - return 1; -} - -static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { - nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) - )) - return 0; - - for(int i=0; i< pNfapiMsg->numPdus; i++) { - if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) - return 0; - } - - return 1; -} static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t *)msg; @@ -5877,67 +4248,6 @@ static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, v return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { - nfapi_nr_pdu_t *pNfapiMsg = (nfapi_nr_pdu_t *)msg; - - if (!(pull32(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) && pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) - && pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end))) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; - - for(; i < total_number_of_tlvs; ++i) { - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end) && pull32(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end))) - return 0; - - switch(pNfapiMsg->TLVs[i].tag) { - case 0: { - if (!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, - sizeof(pNfapiMsg->TLVs[i].value.direct) / sizeof(uint32_t), - (pNfapiMsg->TLVs[i].length+3)/4, end)) - return 0; - - break; - } - - case 1: { - if (!pullarray32(ppReadPackedMsg, - pNfapiMsg->TLVs[i].value.ptr, - (pNfapiMsg->TLVs[i].length + 3) / 4, - (pNfapiMsg->TLVs[i].length + 3) / 4, - end)) - return 0; - - break; - } - - default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); - break; - } - } - } - - return 1; -} - -static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) - && pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) - return 0; - - for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { - if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) { - return 0; - } - } - - return 1; -} static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { uint8_t proceed = 1; @@ -6014,589 +4324,148 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); } } - } - break; - - default: { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} - -//UNPACK NR UPLINK INDICATION FUNCTIONS - -//SLOT INDICATION - -uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_slot_indication_scf_t *msg, - nfapi_p7_codec_config_t *config) -{ - nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t *)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end))) - return 0; - - return 1; -} - -//RX DATA INDICATION - -static uint8_t unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, - uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config) -{ - if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) - && pull8(ppReadPackedMsg, &value->harq_id, end) && pull32(ppReadPackedMsg, &value->pdu_length, end) - && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) - && pull16(ppReadPackedMsg, &value->rssi, end))) - return 0; - - value->pdu = nfapi_p7_allocate(sizeof(*value->pdu) * value->pdu_length, config); - if (pullarray8(ppReadPackedMsg, value->pdu, value->pdu_length, value->pdu_length, end) == 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pullarray8 failure\n", __FUNCTION__); - return 0; - } - return 1; -} - -static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; - - if (pNfapiMsg->number_of_pdus > 0) - { - pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); - } - - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) - { - if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end, config)) - return 0; - } - - return 1; -} - -//NR CRC INDICATION - -uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) - && pull8(ppReadPackedMsg, &value->harq_id, end) && pull8(ppReadPackedMsg, &value->tb_crc_status, end) - && pull16(ppReadPackedMsg, &value->num_cb, end))) { - return 0; - } - if (value->num_cb != 0) { - if (!pullarray8(ppReadPackedMsg, - value->cb_crc_status, - (int)(value->num_cb / 8) + 1, - (int)(value->num_cb / 8) + 1, - end)) { // length is ceil(NumCb/8) - return 0; - } - } - if (!(pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) - && pull16(ppReadPackedMsg, &value->rssi, end))) { - return 0; - } - - // memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); - - return 1; -} - -uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_crc_indication_t *msg, - nfapi_p7_codec_config_t *config) -{ - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) - && pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end))) - return 0; - - if (pNfapiMsg->number_crcs > 0) { - pNfapiMsg->crc_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->crc_list) * pNfapiMsg->number_crcs, config); - } - - for (int i = 0; i < pNfapiMsg->number_crcs; i++) { - if (!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end)) - return 0; - } - - return 1; -} - -//SRS INDICATION - -int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen) { - - nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix = (nfapi_nr_srs_normalized_channel_iq_matrix_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - memset(pUnpackedBuf, 0, unpackedBufLen); - - if(!(pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->normalized_iq_representation, end) && - pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements, end) && - pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports, end) && - pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->prg_size, end) && - pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_prgs, end))) { - return -1; - } - - uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs*nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports*nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements; - if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) { - channel_matrix_size <<= 1; - } else { - channel_matrix_size <<= 2; - } - - for(int i = 0; i < channel_matrix_size; i++) { - if (!pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->channel_matrix[i], end)) { - return 0; - } - } - - return 0; -} - -static uint8_t unpack_nr_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *prgs, uint8_t **ppReadPackedMsg, uint8_t *end) { - - if(!pull16(ppReadPackedMsg, &prgs->num_prgs, end)) { - return 0; - } - - for(int i = 0; i < prgs->num_prgs; i++) { - if (!pull8(ppReadPackedMsg, &prgs->prg_list[i].rb_snr, end)) { - return 0; - } - } - - return 1; -} - -int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen) { - - nfapi_nr_srs_beamforming_report_t *nr_srs_beamforming_report = (nfapi_nr_srs_beamforming_report_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - memset(pUnpackedBuf, 0, unpackedBufLen); - - if(!(pull16(&pReadPackedMessage, &nr_srs_beamforming_report->prg_size, end) && - pull8(&pReadPackedMessage, &nr_srs_beamforming_report->num_symbols, end) && - pull8(&pReadPackedMessage, &nr_srs_beamforming_report->wide_band_snr, end) && - pull8(&pReadPackedMessage, &nr_srs_beamforming_report->num_reported_symbols, end))) { - return -1; - } - - if (!unpack_nr_srs_reported_symbol(&nr_srs_beamforming_report->prgs, &pReadPackedMessage, end)) { - return -1; - } - - return 0; -} - -static uint8_t unpack_nr_srs_report_tlv(nfapi_srs_report_tlv_t *report_tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - - if(!(pull16(ppReadPackedMsg, &report_tlv->tag, end) && - pull32(ppReadPackedMsg, &report_tlv->length, end))) { - return 0; - } - - for(int i = 0; i < report_tlv->length; i++) { - if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) { - return 0; - } - } - - return 1; -} - -static uint8_t unpack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end) { - - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->timing_advance_offset, end) && - pulls16(ppReadPackedMsg, &value->timing_advance_offset_nsec, end) && - pull8(ppReadPackedMsg, &value->srs_usage, end) && - pull8(ppReadPackedMsg, &value->report_type, end))) { - return 0; - } - - if (!unpack_nr_srs_report_tlv(&value->report_tlv, ppReadPackedMsg, end)) { - return 0; - } - - return 1; -} - -uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_srs_indication_t *pNfapiMsg, - nfapi_p7_codec_config_t *config) -{ - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) - && pull16(ppReadPackedMsg, &pNfapiMsg->control_length, end) && pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) { - return 0; - } - - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { - if (!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end)) { - return 0; - } - } - - return 1; -} - -//NR RACH - -static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t *value, - uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config) -{ - if (!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && pull8(ppReadPackedMsg, &value->symbol_index, end) - && pull8(ppReadPackedMsg, &value->slot_index, end) && pull8(ppReadPackedMsg, &value->freq_index, end) - && pull8(ppReadPackedMsg, &value->avg_rssi, end) && pull8(ppReadPackedMsg, &value->avg_snr, end) - && pull8(ppReadPackedMsg, &value->num_preamble, end))) { - return 0; - } - - for (int i = 0; i < value->num_preamble; i++) { - nfapi_nr_prach_indication_preamble_t *preamble = &(value->preamble_list[i]); - if (!(pull8(ppReadPackedMsg, &preamble->preamble_index, end) && pull16(ppReadPackedMsg, &preamble->timing_advance, end) - && pull32(ppReadPackedMsg, &preamble->preamble_pwr, end))) { - return 0; - } - } - return 1; -} - -uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_rach_indication_t *msg, - nfapi_p7_codec_config_t *config) -{ - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) - && pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) { - return 0; - } - - if (pNfapiMsg->number_of_pdus > 0) { - pNfapiMsg->pdu_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->pdu_list) * pNfapiMsg->number_of_pdus, config); - for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { - if (!unpack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]), ppReadPackedMsg, end, config)) - return 0; - } - } - return 1; -} - -//NR UCI - -static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t *value, - uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config) -{ - if (!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && pull32(ppReadPackedMsg, &value->handle, end) - && pull16(ppReadPackedMsg, &value->rnti, end) && pull8(ppReadPackedMsg, &value->pucch_format, end) - && pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end) - && pull16(ppReadPackedMsg, &value->rssi, end))) - return 0; - if (value->pduBitmap & 0x01) { // SR - if (!(pull8(ppReadPackedMsg, &value->sr.sr_indication, end) && pull8(ppReadPackedMsg, &value->sr.sr_confidence_level, end))) - return 0; - } - - if (((value->pduBitmap >> 1) & 0x01)) { // HARQ - - if (!(pull8(ppReadPackedMsg, &value->harq.num_harq, end) && pull8(ppReadPackedMsg, &value->harq.harq_confidence_level, end))) - return 0; - if (value->harq.num_harq > 0) { - for (int i = 0; i < value->harq.num_harq; i++) { - if (!pull8(ppReadPackedMsg, &value->harq.harq_list[i].harq_value, end)) { - return 0; - } - } - } - } - - return 1; -} - -static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value, - uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config) { - - if (!pull8(ppReadPackedMsg, &value->pduBitmap, end)) - return 0; - if (!pull32(ppReadPackedMsg, &value->handle, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->rnti, end)) - return 0; - if (!pull8(ppReadPackedMsg, &value->pucch_format, end)) - return 0; - if (!pull8(ppReadPackedMsg, &value->ul_cqi, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->timing_advance, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->rssi, end)) - return 0; - - value->pucch_format += 2; - if (value->pduBitmap & 0x01) { //SR - if (!pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end)) - return 0; - - value->sr.sr_payload = nfapi_p7_allocate(sizeof(*value->sr.sr_payload) * - (int)((value->sr.sr_bit_len / 8) + 1), - config); - if (value->sr.sr_payload == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->sr.sr_payload\n", __FUNCTION__); - return 0; - } - - if (!pullarray8(ppReadPackedMsg, value->sr.sr_payload, - (int)((value->sr.sr_bit_len / 8) + 1), - (int)((value->sr.sr_bit_len / 8) + 1), - end)) - return 0; - } - - if ((value->pduBitmap >> 1) & 0x01) { //HARQ - if (!pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end)) - return 0; - - value->harq.harq_payload = nfapi_p7_allocate(sizeof(*value->harq.harq_payload) * - (int)((value->harq.harq_bit_len / 8) + 1), - config); - if (value->harq.harq_payload == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->harq.harq_payload\n", __FUNCTION__); - return 0; - } - - if (!pullarray8(ppReadPackedMsg, value->harq.harq_payload, - (int)((value->harq.harq_bit_len / 8) + 1), - (int)((value->harq.harq_bit_len / 8) + 1), - end)) - return 0; - } + } + break; - if ((value->pduBitmap >> 2) & 0x01) { //CSI-1 - if (!pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end)) - return 0; + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); + } + break; + }; + } - value->csi_part1.csi_part1_payload = nfapi_p7_allocate(sizeof(*value->csi_part1.csi_part1_payload) * - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - config); - if (value->csi_part1.csi_part1_payload == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part1.csi_part1_payload\n", - __FUNCTION__); - return 0; - } + return 1; +} - if (!pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - end)) - return 0; - } +//UNPACK NR UPLINK INDICATION FUNCTIONS - if ((value->pduBitmap >> 3) & 0x01) { //CSI-2 - if (!pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end)) - return 0; - value->csi_part2.csi_part2_payload = nfapi_p7_allocate(sizeof(*value->csi_part2.csi_part2_payload) * - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - config); - if (value->csi_part2.csi_part2_payload == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part2.csi_part2_payload\n", - __FUNCTION__); - return 0; - } +//SRS INDICATION - if (!pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - end)) - return 0; - } +int unpack_nr_srs_channel_svd_representation(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen) +{ + nfapi_nr_srs_channel_svd_representation_t *value = (nfapi_nr_srs_channel_svd_representation_t *)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - return 1; -} + memset(pUnpackedBuf, 0, unpackedBufLen); + if (!(pull8(&pReadPackedMessage, &value->normalized_iq_representation, end) + && pull8(&pReadPackedMessage, &value->normalized_singular_value_representation, end) + && pulls8(&pReadPackedMessage, &value->singular_value_scaling, end) + && pull16(&pReadPackedMessage, &value->num_gnb_antenna_elements, end) + && pull8(&pReadPackedMessage, &value->num_ue_srs_ports, end) && pull16(&pReadPackedMessage, &value->prg_size, end) + && pull16(&pReadPackedMessage, &value->num_prgs, end))) { + return -1; + } + const uint16_t iq_size = value->normalized_iq_representation == 0 ? 2 : 4; + const uint16_t ng = value->num_gnb_antenna_elements; + const uint8_t nu = value->num_ue_srs_ports; -static uint8_t unpack_nr_uci_pusch(nfapi_nr_uci_pusch_pdu_t *value, - uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config) -{ - if (!pull8(ppReadPackedMsg, &value->pduBitmap, end)) - return 0; - if (!pull32(ppReadPackedMsg, &value->handle, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->rnti, end)) - return 0; - if (!pull8(ppReadPackedMsg, &value->ul_cqi, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->timing_advance, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->rssi, end)) - return 0; + value->prg_list = calloc(value->num_prgs, sizeof(*value->prg_list)); - // Bit 0 not used in PUSCH PDU - if ((value->pduBitmap >> 1) & 0x01) { // HARQ - if (!pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) + for (int prg_idx = 0; prg_idx < value->num_prgs; ++prg_idx) { + nfapi_nr_srs_channel_svd_representation_prg_t *prg = &value->prg_list[prg_idx]; + prg->left_eigenvectors_matrix_u = calloc(nu * nu * iq_size, sizeof(*prg->left_eigenvectors_matrix_u)); + if (!(pullarray8(&pReadPackedMessage, prg->left_eigenvectors_matrix_u, nu * nu * iq_size, nu * nu * iq_size, end))) { return 0; - if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end)) - return 0; - - value->harq.harq_payload = - nfapi_p7_allocate(sizeof(*value->harq.harq_payload) * (int)((value->harq.harq_bit_len / 8) + 1), config); - if (value->harq.harq_payload == NULL) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->harq.harq_payload\n", __FUNCTION__); + } + prg->diagonal_entries_of_singular_matrix_sum_f = calloc(nu * iq_size, sizeof(*prg->diagonal_entries_of_singular_matrix_sum_f)); + if (!(pullarray8(&pReadPackedMessage, prg->diagonal_entries_of_singular_matrix_sum_f, nu * iq_size, nu * iq_size, end))) { return 0; } - - if (!pullarray8(ppReadPackedMsg, - value->harq.harq_payload, - (int)((value->harq.harq_bit_len / 8) + 1), - (int)((value->harq.harq_bit_len / 8) + 1), - end)) + prg->complex_conjugate_of_matrix_of_right_eigenvectors_v_hf = + calloc(nu * ng * iq_size, sizeof(*prg->complex_conjugate_of_matrix_of_right_eigenvectors_v_hf)); + if (!(pullarray8(&pReadPackedMessage, + prg->complex_conjugate_of_matrix_of_right_eigenvectors_v_hf, + nu * ng * iq_size, + nu * ng * iq_size, + end))) { return 0; + } } + return 1; +} - if ((value->pduBitmap >> 2) & 0x01) { // CSI-1 - if (!pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end)) - return 0; +int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen) +{ + nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_normalized_channel_iq_matrix = + (nfapi_nr_srs_normalized_channel_iq_matrix_t *)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - value->csi_part1.csi_part1_payload = - nfapi_p7_allocate(sizeof(*value->csi_part1.csi_part1_payload) * (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - config); - if (value->csi_part1.csi_part1_payload == NULL) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part1.csi_part1_payload\n", __FUNCTION__); - return 0; - } + memset(pUnpackedBuf, 0, unpackedBufLen); - if (!pullarray8(ppReadPackedMsg, - value->csi_part1.csi_part1_payload, - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - (int)((value->csi_part1.csi_part1_bit_len / 8) + 1), - end)) - return 0; + if (!(pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->normalized_iq_representation, end) + && pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements, end) + && pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports, end) + && pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->prg_size, end) + && pull16(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->num_prgs, end))) { + return -1; } - if ((value->pduBitmap >> 3) & 0x01) { // CSI-2 - if (!pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end)) - return 0; + uint16_t channel_matrix_size = nr_srs_normalized_channel_iq_matrix->num_prgs + * nr_srs_normalized_channel_iq_matrix->num_ue_srs_ports + * nr_srs_normalized_channel_iq_matrix->num_gnb_antenna_elements; + if (nr_srs_normalized_channel_iq_matrix->normalized_iq_representation == 0) { + // 0: 16-bit normalized complex number (iqSize = 2) + channel_matrix_size <<= 1; + } else { + // 1: 32-bit normalized complex number (iqSize = 4) + channel_matrix_size <<= 2; + } - value->csi_part2.csi_part2_payload = - nfapi_p7_allocate(sizeof(*value->csi_part2.csi_part2_payload) * (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - config); - if (value->csi_part2.csi_part2_payload == NULL) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate value->csi_part2.csi_part2_payload\n", __FUNCTION__); + for (int i = 0; i < channel_matrix_size; i++) { + if (!pull8(&pReadPackedMessage, &nr_srs_normalized_channel_iq_matrix->channel_matrix[i], end)) { return 0; } - - if (!pullarray8(ppReadPackedMsg, - value->csi_part2.csi_part2_payload, - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - (int)((value->csi_part2.csi_part2_bit_len / 8) + 1), - end)) - return 0; } return 1; } -static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t *value, - uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_p7_codec_config_t *config) -{ - if (!pull16(ppReadPackedMsg, &value->pdu_type, end)) - return 0; - if (!pull16(ppReadPackedMsg, &value->pdu_size, end)) +static uint8_t unpack_nr_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *prgs, uint8_t **ppReadPackedMsg, uint8_t *end) { + + if(!pull16(ppReadPackedMsg, &prgs->num_prgs, end)) { return 0; + } - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { - nfapi_nr_uci_pusch_pdu_t *uci_pdu = &value->pusch_pdu; - if (!unpack_nr_uci_pusch(uci_pdu, ppReadPackedMsg, end, config)) - return 0; - break; - } - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; - if (!unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end, config)) - return 0; - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - if (!unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end, config)) - return 0; - break; + for(int i = 0; i < prgs->num_prgs; i++) { + if (!pull8(ppReadPackedMsg, &prgs->prg_list[i].rb_snr, end)) { + return 0; } - default: - NFAPI_TRACE(NFAPI_TRACE_WARN, "Unexpected pdu type %d\n", value->pdu_type); - break; } return 1; } -uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) +int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen) { - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg; + nfapi_nr_srs_beamforming_report_t *nr_srs_beamforming_report = (nfapi_nr_srs_beamforming_report_t *)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end)) - return 0; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)) - return 0; - if (!pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end)) - return 0; + memset(pUnpackedBuf, 0, unpackedBufLen); - pNfapiMsg->uci_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->uci_list) * pNfapiMsg->num_ucis, config); - for (int i = 0; i < pNfapiMsg->num_ucis; i++) { - if (!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppReadPackedMsg, end, config)) - return 0; + if (!(pull16(&pReadPackedMessage, &nr_srs_beamforming_report->prg_size, end) + && pull8(&pReadPackedMessage, &nr_srs_beamforming_report->num_symbols, end) + && pull8(&pReadPackedMessage, &nr_srs_beamforming_report->wide_band_snr, end) + && pull8(&pReadPackedMessage, &nr_srs_beamforming_report->num_reported_symbols, end))) { + return -1; + } + nr_srs_beamforming_report->reported_symbol_list = + calloc(nr_srs_beamforming_report->num_reported_symbols, sizeof(*nr_srs_beamforming_report->reported_symbol_list)); + for (int reported_symbol = 0; reported_symbol < nr_srs_beamforming_report->num_reported_symbols; ++reported_symbol) { + if (!unpack_nr_srs_reported_symbol(&nr_srs_beamforming_report->reported_symbol_list[reported_symbol], + &pReadPackedMessage, + end)) { + return -1; + } } - return 1; + return 0; } static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { @@ -8030,81 +5899,45 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen return retLen; } -static int check_nr_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) - retLen = sizeof(nfapi_nr_dl_tti_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) - retLen = sizeof(nfapi_nr_ul_tti_request_t); - break; - - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) - retLen = sizeof(nfapi_nr_ul_dci_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) - retLen = sizeof(nfapi_nr_tx_data_request_t); - break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) - retLen = sizeof(nfapi_nr_rx_data_indication_t); - break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) - retLen = sizeof(nfapi_nr_crc_indication_t); - break; +// Main unpack functions - public - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) - retLen = sizeof(nfapi_nr_rach_indication_t); - break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) - retLen = sizeof(nfapi_nr_uci_indication_t); - break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) - retLen = sizeof(nfapi_nr_srs_indication_t); - break; - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) - retLen = sizeof(nfapi_nr_dl_node_sync_t); - break; +int nfapi_p7_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config) +{ + nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) - retLen = sizeof(nfapi_nr_ul_node_sync_t); - break; + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); + return -1; + } - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; - return retLen; + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + // process the header + if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) + && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) + && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + return -1; + return 0; } - - -// Main unpack functions - public - -int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { - nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; +int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config) +{ + nfapi_nr_p7_message_header_t *pMessageHeader = pUnpackedBuf; uint8_t *pReadPackedMessage = pMessageBuf; if (pMessageBuf == NULL || pUnpackedBuf == NULL) { @@ -8114,24 +5947,27 @@ int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) { + if (messageBufLen < NFAPI_NR_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p7_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); return -1; } - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull32(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) + && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) + && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) return -1; return 0; } -int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { +int nfapi_p7_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config) +{ int result = 0; nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t *)pUnpackedBuf; uint8_t *pReadPackedMessage = pMessageBuf; @@ -8159,19 +5995,16 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn */ // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { + if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) + && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) + && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); return -1; } - - if((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { + if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); return -1; } @@ -8188,7 +6021,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn switch (pMessageHeader->message_id) { case NFAPI_DL_CONFIG_REQUEST: if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8204,7 +6037,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_TX_REQUEST: if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) - result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8212,7 +6045,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_HI_DCI0_REQUEST: if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) - result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8220,7 +6053,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_UE_RELEASE_REQUEST: if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8228,7 +6061,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_HARQ_INDICATION: if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8236,7 +6069,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_CRC_INDICATION: if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end, pMessageHeader, config); + result = unpack_crc_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8244,7 +6077,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_RX_ULSCH_INDICATION: if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8252,7 +6085,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_RACH_INDICATION: if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8260,7 +6093,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_SRS_INDICATION: if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8268,7 +6101,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_RX_SR_INDICATION: if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8276,7 +6109,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_RX_CQI_INDICATION: if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8284,7 +6117,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_LBT_DL_CONFIG_REQUEST: if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8292,7 +6125,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_LBT_DL_INDICATION: if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8300,7 +6133,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_NB_HARQ_INDICATION: if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8308,7 +6141,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_NRACH_INDICATION: if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8316,7 +6149,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_DL_NODE_SYNC: if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); else return -1; @@ -8340,19 +6173,21 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn case NFAPI_UE_RELEASE_RESPONSE: if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { - if(config && config->unpack_p7_vendor_extension) { + if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (config && config->unpack_p7_vendor_extension) { result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s VE NFAPI message ID %d. No ve decoder provided\n", + __FUNCTION__, + pMessageHeader->message_id); } } else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); @@ -8361,173 +6196,152 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn break; } - if(result == 0) + if (result == 0) return -1; else return 0; } -int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +int nfapi_nr_p7_message_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config) { - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } - - uint8_t *end = (uint8_t*)pMessageBuf + messageBufLen; + int result = 0; + nfapi_nr_p7_message_header_t *pMessageHeader = (nfapi_nr_p7_message_header_t *)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } + if (messageBufLen < NFAPI_NR_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p7_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } - if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; - } + // process the header + if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) + && pull32(&pReadPackedMessage, &pMessageHeader->message_length, end) + && pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) + && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) + && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); + return -1; + } - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) - result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - break; + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) + result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + break; - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) - result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) - result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) - result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - case NFAPI_UE_RELEASE_REQUEST: - if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)){ - nfapi_nr_slot_indication_scf_t* msg = (nfapi_nr_slot_indication_scf_t*) pMessageHeader; - result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); - } - break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) + result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) + result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) + result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_UE_RELEASE_REQUEST: + if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)) { + nfapi_nr_slot_indication_scf_t *msg = (nfapi_nr_slot_indication_scf_t *)pMessageHeader; + result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); + } + break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)){ - nfapi_nr_rx_data_indication_t* msg = (nfapi_nr_rx_data_indication_t*) pMessageHeader; - msg->pdu_list = (nfapi_nr_rx_data_pdu_t*) malloc(sizeof(nfapi_nr_rx_data_pdu_t)); - msg->pdu_list->pdu = (uint8_t *) malloc(sizeof(uint8_t)); - result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, msg, config); - } + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) { + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + } break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)){ - - nfapi_nr_crc_indication_t* msg = (nfapi_nr_crc_indication_t*) pMessageHeader; - msg->crc_list = (nfapi_nr_crc_t*) malloc(sizeof(nfapi_nr_crc_t)); - result = unpack_nr_crc_indication(&pReadPackedMessage,end , msg, config); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) { + result = unpack_nr_crc_indication(&pReadPackedMessage, end, pMessageHeader, config); } break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)){ - nfapi_nr_uci_indication_t* msg = (nfapi_nr_uci_indication_t*) pMessageHeader; - msg->uci_list = (nfapi_nr_uci_t*) malloc(sizeof(nfapi_nr_uci_t)); - result = unpack_nr_uci_indication(&pReadPackedMessage, end, msg, config); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) { + result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); } break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)){ - nfapi_nr_srs_indication_t* msg = (nfapi_nr_srs_indication_t*) pMessageHeader; - msg->pdu_list = (nfapi_nr_srs_indication_pdu_t*) malloc(sizeof(nfapi_nr_srs_indication_pdu_t)); - result = unpack_nr_srs_indication(&pReadPackedMessage, end, msg, config); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) { + result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); } break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)){ - nfapi_nr_rach_indication_t* msg = (nfapi_nr_rach_indication_t*) pMessageHeader; - result = unpack_nr_rach_indication(&pReadPackedMessage, end, msg, config); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) { + result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); } break; - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - break; + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + break; - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - break; + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (check_nr_fapi_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_ul_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + break; - case NFAPI_TIMING_INFO: - if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - break; + case NFAPI_TIMING_INFO: + if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + break; - case NFAPI_UE_RELEASE_RESPONSE: - if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - break; + case NFAPI_UE_RELEASE_RESPONSE: + if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + break; - default: + default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } + if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if (config && config->unpack_p7_vendor_extension) { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s VE NFAPI message ID %d. No ve decoder provided\n", + __FUNCTION__, + pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } if (result == 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h index 8c4e5cf9ab083c03c034f7dad57d8703328bd6d1..7275db76e172fd0f3bd0700a1cb8c6934ebc4f94 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf.h @@ -20,7 +20,7 @@ #include "nfapi_pnf_interface.h" -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192 +#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 typedef struct { @@ -40,7 +40,7 @@ int pnf_connect(pnf_t *pnf); int pnf_message_pump(pnf_t *pnf); int pnf_nr_message_pump(pnf_t *pnf); -int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); +int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream_id); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index cab245569165bd51a93c40ae6ca53b96ae4ba760..737e76e04fc863b1f340d31a26fee586e97ed038 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -25,7 +25,7 @@ #include "nfapi_pnf_interface.h" -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192 +#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 typedef struct { uint16_t dl_conf_ontime; @@ -148,7 +148,7 @@ typedef struct { int pnf_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len); +int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); @@ -164,7 +164,7 @@ pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pn void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg); void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta); -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len); +int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); #endif /* _PNF_P7_H_ */ diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 14782bdcf4ae856abf49ad1b0fa335f00c0fe71a..cb8dd6f6d71694b9d0885a3970d5ad2664f2620a 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -305,19 +305,19 @@ typedef struct nfapi_pnf_config * \param msg A pointer to the decode P4/P5 message * \return not current used */ - int (*vendor_ext)(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg); + int (*vendor_ext)(nfapi_pnf_config_t* config, void* msg); /*! A callback to allocate vendor extension message * \param message_id The message id from the decode P4/P5 message header * \param msg_size A pointer a the size of the allocated message structure. The callee should set this * \return A pointer to a allocated P4/P5 message structure */ - nfapi_p4_p5_message_header_t* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size); + void* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size); /*! A callback to deallocate vendor extension message * \param header A pointer to an P4/P5 message structure */ - void (*deallocate_p4_p5_vendor_ext)(nfapi_p4_p5_message_header_t* header); + void (*deallocate_p4_p5_vendor_ext)(void* header); @@ -571,8 +571,8 @@ typedef struct typedef struct { //uint16_t sfn_slot - int16_t sfn; - int16_t slot; + uint16_t sfn; + uint16_t slot; //TODO: Change P7 structs to NR nfapi_nr_dl_tti_request_t* dl_tti_req;//nfapi_dl_config_request_t* dl_config_req; nfapi_nr_ul_tti_request_t* ul_tti_req;//nfapi_ul_config_request_t* ul_config_req; @@ -711,7 +711,7 @@ typedef struct nfapi_pnf_p7_config * \param msg A pointer to a decode vendor extention message * \return not currently used */ - int (*vendor_ext)(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg); + int (*vendor_ext)(nfapi_pnf_p7_config_t* config, void* msg); /*! A callback to allocate vendor extension message * \param message_id The vendor extention message id from the decode message header @@ -720,12 +720,12 @@ typedef struct nfapi_pnf_p7_config * * */ - nfapi_p7_message_header_t* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size); + void* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size); /*! A callback to deallocate vendor extension message * \param header A pointer to a p7 vendor extention message */ - void (*deallocate_p7_vendor_ext)(nfapi_p7_message_header_t* header); + void (*deallocate_p7_vendor_ext)(void* header); diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index 9ee06b1ca8190717be596a9817ec33eece93635a..f3e44663f89a5a13847bd9eb99a939a2d3a21cca 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -1519,100 +1519,96 @@ void pnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, pnf_t* pnf, uin } } -void pnf_nr_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +void pnf_nr_handle_p5_message(pnf_t* pnf, void* pRecvMsg, int recvMsgLen) { - nfapi_p4_p5_message_header_t messageHeader; + nfapi_nr_p4_p5_message_header_t messageHeader; - // validate the input params - if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return; - } + // validate the input params + if (pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } - // unpack the message header - if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &pnf->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return; - } + // unpack the message header + if (nfapi_nr_p5_message_header_unpack(pRecvMsg, + recvMsgLen, + &messageHeader, + sizeof(nfapi_nr_p4_p5_message_header_t), + &pnf->_public.codec_config) + < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } - switch (messageHeader.message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: - pnf_nr_handle_pnf_param_request(pnf, pRecvMsg, recvMsgLen); - break; + switch (messageHeader.message_id) { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + pnf_nr_handle_pnf_param_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: - pnf_nr_handle_pnf_config_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + pnf_nr_handle_pnf_config_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: - pnf_nr_handle_pnf_start_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + pnf_nr_handle_pnf_start_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_PNF_STOP_REQUEST: - pnf_handle_pnf_stop_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_PNF_STOP_REQUEST: + pnf_handle_pnf_stop_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: - pnf_nr_handle_param_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + pnf_nr_handle_param_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: - pnf_nr_handle_config_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + pnf_nr_handle_config_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: - pnf_nr_handle_start_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + pnf_nr_handle_start_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: - pnf_nr_handle_stop_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + pnf_nr_handle_stop_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_MEASUREMENT_REQUEST: - pnf_handle_measurement_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_MEASUREMENT_REQUEST: + pnf_handle_measurement_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_RSSI_REQUEST: - pnf_handle_rssi_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_RSSI_REQUEST: + pnf_handle_rssi_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_CELL_SEARCH_REQUEST: - pnf_handle_cell_search_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_CELL_SEARCH_REQUEST: + pnf_handle_cell_search_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_BROADCAST_DETECT_REQUEST: - pnf_handle_broadcast_detect_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_BROADCAST_DETECT_REQUEST: + pnf_handle_broadcast_detect_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: - pnf_handle_system_information_schedule_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + pnf_handle_system_information_schedule_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_SYSTEM_INFORMATION_REQUEST: - pnf_handle_system_information_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_SYSTEM_INFORMATION_REQUEST: + pnf_handle_system_information_request(pnf, pRecvMsg, recvMsgLen); + break; - case NFAPI_NMM_STOP_REQUEST: - pnf_handle_nmm_stop_request(pnf, pRecvMsg, recvMsgLen); - break; + case NFAPI_NMM_STOP_REQUEST: + pnf_handle_nmm_stop_request(pnf, pRecvMsg, recvMsgLen); + break; - default: - { - if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - pnf_handle_vendor_extension(pRecvMsg, recvMsgLen, pnf, messageHeader.message_id); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id); - } - } - break; - } + default: { + if (messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + pnf_handle_vendor_extension(pRecvMsg, recvMsgLen, pnf, messageHeader.message_id); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id); + } + } break; + } } void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) @@ -1711,21 +1707,17 @@ void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } - -int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) +int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) { - int packed_len = nfapi_nr_p5_message_pack(msg, msg_len, - pnf->tx_message_buffer, - sizeof(pnf->tx_message_buffer), - &pnf->_public.codec_config); + int packed_len = + nfapi_nr_p5_message_pack(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); - if (packed_len < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len); - return -1; - } + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed (%d)\n", packed_len); + return -1; + } - return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/); + return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0 /*msg->stream_id*/); } @@ -2123,7 +2115,7 @@ int pnf_nr_read_dispatch_message(pnf_t* pnf) // 3. Read the buffer // 4. Handle the p5 message - uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; uint8_t header_buffer[header_buffer_size]; uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure @@ -2155,8 +2147,8 @@ int pnf_nr_read_dispatch_message(pnf_t* pnf) return 0; } - nfapi_p4_p5_message_header_t header; - int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); + nfapi_nr_p4_p5_message_header_t header; + int unpack_result = nfapi_nr_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); if (unpack_result < 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); return 0; diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index a7e7e0cb6e3dc78d98cabb5177a1cdf84a9fd593..a7f0385d9e82990d54474d6b2031b16e6635646b 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -666,95 +666,83 @@ int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* return 0; } - -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len) +int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len) { - header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number); + header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number); - // Need to guard against different threads calling the encode function at the same time - if(pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); - return -1; - } + // Need to guard against different threads calling the encode function at the same time + if (pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return -1; + } - int len = nfapi_nr_p7_message_pack(header, pnf_p7->tx_message_buffer, sizeof(pnf_p7->tx_message_buffer), &pnf_p7->_public.codec_config); + int len = + nfapi_nr_p7_message_pack(header, pnf_p7->tx_message_buffer, sizeof(pnf_p7->tx_message_buffer), &pnf_p7->_public.codec_config); - if (len < 0) - { - if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len ); - return -1; - } + if (len < 0) { + if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } - if(len > pnf_p7->_public.segment_size) - { - int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; - int seg_body_len = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; - int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len); + return -1; + } - int segment = 0; - int offset = NFAPI_P7_HEADER_LENGTH; - uint8_t buffer[pnf_p7->_public.segment_size]; - for(segment = 0; segment < segment_count; ++segment) - { - uint8_t last = 0; - uint16_t size = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH; - if(segment + 1 == segment_count) - { - last = 1; - size = (msg_body_len) - (seg_body_len * segment); - } + if (len > pnf_p7->_public.segment_size) { + int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH; + int seg_body_len = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); - uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH; + int segment = 0; + int offset = NFAPI_NR_P7_HEADER_LENGTH; + uint8_t buffer[pnf_p7->_public.segment_size]; + for (segment = 0; segment < segment_count; ++segment) { + uint8_t last = 0; + uint16_t size = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + if (segment + 1 == segment_count) { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } - // Update the header with the m and segement - memcpy(&buffer[0], pnf_p7->tx_message_buffer, NFAPI_P7_HEADER_LENGTH); + uint16_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; - // set the segment length - buffer[4] = (segment_size & 0xFF00) >> 8; - buffer[5] = (segment_size & 0xFF); + // Update the header with the m and segement + memcpy(&buffer[0], pnf_p7->tx_message_buffer, NFAPI_NR_P7_HEADER_LENGTH); - // set the m & segment number - buffer[6] = ((!last) << 7) + segment; + // set the segment length + buffer[6] = (segment_size & 0xFF00) >> 8; + buffer[7] = (segment_size & 0xFF); - memcpy(&buffer[NFAPI_P7_HEADER_LENGTH], pnf_p7->tx_message_buffer + offset, size); - offset += size; + // set the m & segment number + buffer[8] = ((!last) << 7) + segment; - if(pnf_p7->_public.checksum_enabled) - { - nfapi_p7_update_checksum(buffer, segment_size); - } + memcpy(&buffer[NFAPI_NR_P7_HEADER_LENGTH], pnf_p7->tx_message_buffer + offset, size); + offset += size; + if (pnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(buffer, segment_size); + } - pnf_p7_send_message(pnf_p7, &buffer[0], segment_size); - } - } - else - { - if(pnf_p7->_public.checksum_enabled) - { - nfapi_p7_update_checksum(pnf_p7->tx_message_buffer, len); - } + pnf_p7_send_message(pnf_p7, &buffer[0], segment_size); + } + } else { + if (pnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(pnf_p7->tx_message_buffer, len); + } - // simple case that the message fits in a single segment - pnf_p7_send_message(pnf_p7, pnf_p7->tx_message_buffer, len); - } + // simple case that the message fits in a single segment + pnf_p7_send_message(pnf_p7, pnf_p7->tx_message_buffer, len); + } - pnf_p7->sequence_number++; - - if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; - } + pnf_p7->sequence_number++; - return 0; + if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } + + return 0; } void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) @@ -2607,62 +2595,52 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, } } -void pnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +void pnf_nr_dispatch_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; - // validate the input params - if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return; - } + // validate the input params + if (pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } - // unpack the message header - if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return; - } + // unpack the message header + if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } - // ensure the message is sensible - if (recvMsgLen < 8 || pRecvMsg == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); - return; - } + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } - switch (header.message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - pnf_nr_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); - break; - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - pnf_handle_ul_tti_request(pRecvMsg, recvMsgLen, pnf_p7); - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - pnf_handle_ul_dci_request(pRecvMsg, recvMsgLen, pnf_p7); - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - pnf_handle_tx_data_request(pRecvMsg, recvMsgLen, pnf_p7); - break; - default: - { - if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - pnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, pnf_p7, header.message_id); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P7 Unknown message ID %d\n", __FUNCTION__, header.message_id); - } - } - break; - } + switch (header.message_id) { + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + pnf_nr_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + pnf_handle_ul_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + pnf_handle_ul_dci_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + pnf_handle_tx_data_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + default: { + if (header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + pnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, pnf_p7, header.message_id); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P7 Unknown message ID %d\n", __FUNCTION__, header.message_id); + } + } break; + } } void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) @@ -2771,110 +2749,104 @@ void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, ui } -void pnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +void pnf_nr_handle_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { - nfapi_p7_message_header_t messageHeader; - - // validate the input params - if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, pnf_p7); - return; - } - - // unpack the message header - if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &pnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return; - } - - uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); - uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); - uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + nfapi_nr_p7_message_header_t messageHeader; - if(pnf_p7->_public.checksum_enabled) - { - uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen); - if(checksum != messageHeader.checksum) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); - return; - } - } + // validate the input params + if (pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, pnf_p7); + return; + } - if(m == 0 && segment_num == 0) - { - // we have a complete message - // ensure the message is sensible - if (recvMsgLen < 8 || pRecvMsg == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); - return; - } + // unpack the message header + if (nfapi_nr_p7_message_header_unpack(pRecvMsg, + recvMsgLen, + &messageHeader, + sizeof(nfapi_nr_p7_message_header_t), + &pnf_p7->_public.codec_config) + < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } - pnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); - } - else - { - pnf_p7_rx_message_t* rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, sequence_num, segment_num, m, pRecvMsg, recvMsgLen); + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); - if(rx_msg->num_segments_received == rx_msg->num_segments_expected) - { - // send the buffer on - uint16_t i = 0; - uint16_t length = 0; - for(i = 0; i < rx_msg->num_segments_expected; ++i) - { - length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0); - } - - if(pnf_p7->reassemby_buffer_size < length) - { - pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); - pnf_p7->reassemby_buffer = 0; - } - - if(pnf_p7->reassemby_buffer == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); - pnf_p7->reassemby_buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, length); + if (pnf_p7->_public.checksum_enabled) { + uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if (checksum != messageHeader.checksum) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); + return; + } + } - if(pnf_p7->reassemby_buffer == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); - return; - } - memset(pnf_p7->reassemby_buffer, 0, length); - pnf_p7->reassemby_buffer_size = length; - } - - uint16_t offset = 0; - for(i = 0; i < rx_msg->num_segments_expected; ++i) - { - if(i == 0) - { - memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); - offset += rx_msg->segments[i].length; - } - else - { - memcpy(pnf_p7->reassemby_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH); - offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH; - } - } + if (m == 0 && segment_num == 0) { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } - - pnf_nr_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); + pnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + } else { + pnf_p7_rx_message_t* rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, + &(pnf_p7->reassembly_queue), + rx_hr_time, + sequence_num, + segment_num, + m, + pRecvMsg, + recvMsgLen); + + if (rx_msg->num_segments_received == rx_msg->num_segments_expected) { + // send the buffer on + uint16_t i = 0; + uint16_t length = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); + } + + if (pnf_p7->reassemby_buffer_size < length) { + pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); + pnf_p7->reassemby_buffer = 0; + } + + if (pnf_p7->reassemby_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); + pnf_p7->reassemby_buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, length); + + if (pnf_p7->reassemby_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(pnf_p7->reassemby_buffer, 0, length); + pnf_p7->reassemby_buffer_size = length; + } + + uint16_t offset = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + if (i == 0) { + memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } else { + memcpy(pnf_p7->reassemby_buffer + offset, + rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, + rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; + } + } + pnf_nr_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); - // delete the structure - pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); - } - } + // delete the structure + pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); + } + } - pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 1000); - + pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 1000); } @@ -2949,63 +2921,63 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) { - int recvfrom_result = 0; - struct sockaddr_in remote_addr; - socklen_t remote_addr_size = sizeof(remote_addr); - remote_addr.sin_family = 2; //hardcoded - do - { - // peek the header - uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH]; - recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); - if(recvfrom_result > 0) - { - // get the segment size - nfapi_p7_message_header_t header; - nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, 34, 0); - - // resize the buffer if we have a large segment - if(header.message_length > pnf_p7->rx_message_buffer_size) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); - pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); - pnf_p7->rx_message_buffer_size = header.message_length; - } - - // read the segment - recvfrom_result = recvfrom(pnf_p7->p7_sock, pnf_p7->rx_message_buffer, header.message_length, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); - - now_hr_time = pnf_get_current_time_hr(); //moved to here - get closer timestamp??? - - if(recvfrom_result > 0) - { - pnf_nr_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); - //printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); - } - } - else if(recvfrom_result == 0) - { - // recv zero length message - recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); - } + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + remote_addr.sin_family = 2; // hardcoded + do { + // peek the header + uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(pnf_p7->p7_sock, + header_buffer, + NFAPI_NR_P7_HEADER_LENGTH, + MSG_DONTWAIT | MSG_PEEK, + (struct sockaddr*)&remote_addr, + &remote_addr_size); + if (recvfrom_result > 0) { + // get the segment size + nfapi_nr_p7_message_header_t header; + nfapi_nr_p7_message_header_unpack(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, 34, 0); + + // resize the buffer if we have a large segment + if (header.message_length > pnf_p7->rx_message_buffer_size) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); + pnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(pnf_p7->p7_sock, + pnf_p7->rx_message_buffer, + header.message_length, + MSG_DONTWAIT, + (struct sockaddr*)&remote_addr, + &remote_addr_size); + + now_hr_time = pnf_get_current_time_hr(); // moved to here - get closer timestamp??? + + if (recvfrom_result > 0) { + pnf_nr_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); + // printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); + } + } else if (recvfrom_result == 0) { + // recv zero length message + recvfrom_result = + recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); + } - if(recvfrom_result == -1) - { - if(errno == EAGAIN || errno == EWOULDBLOCK) - { - // return to the select - //NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); - } - } + if (recvfrom_result == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // return to the select + // NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } - // need to update the time as we would only use the value from the - // select - } - while(recvfrom_result > 0); + // need to update the time as we would only use the value from the + // select + } while (recvfrom_result > 0); } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index dd91d2fc71f00b940d0c11b75813b7c6b7bf88c8..9b78d80fd39072fee03d7292d81f07569077bfaa 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -259,7 +259,7 @@ int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indica } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); } int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) @@ -271,7 +271,7 @@ int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_ } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); } int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) @@ -283,7 +283,7 @@ int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); } int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind) @@ -295,7 +295,7 @@ int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); } int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind) @@ -307,7 +307,7 @@ int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); } int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) @@ -319,5 +319,5 @@ int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indica } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); } diff --git a/nfapi/open-nFAPI/vnf/inc/vnf.h b/nfapi/open-nFAPI/vnf/inc/vnf.h index b16b842606dab220fc4c63e8c1f1786b2a4b491b..26870f5523928e269ade84fcbc1497f731d0bfaf 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf.h @@ -35,7 +35,7 @@ typedef struct int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); -int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); +int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint16_t msg_len); int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index 4fcc99f79b7bf27f6f817557932ee0834d0bb38b..31512124acd9a86fa939feb7f87a05e49919d070 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -137,7 +137,7 @@ nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id); int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); -int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); +int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header); void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index decb48e5c8334482029cc3c05a57f34d8c1ca4f2..30d1edfe320919ab1b50a144f35f2c0cd926f696 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -30,7 +30,7 @@ extern "C" { #endif -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192 +#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 /*! The nfapi VNF phy configuration information */ @@ -434,7 +434,7 @@ typedef struct nfapi_vnf_config * \param resp A data structure for the decoded vendor extention message * \return not currently used. */ - int (*vendor_ext)(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg); + int (*vendor_ext)(nfapi_vnf_config_t* config, int p5_idx, void* msg); /*! A callback to allocate vendor extension messages * \param message_id The message is taken from the message header @@ -442,12 +442,12 @@ typedef struct nfapi_vnf_config * The callee must set this value * \return A pointer to an allocated vendor extention message */ - nfapi_p4_p5_message_header_t* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size); + void* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size); /*! A callback to deallocate vendor extension messages * \param header A pointer to an allocated vendor extention message */ - void (*deallocate_p4_p5_vendor_ext)(nfapi_p4_p5_message_header_t* header); + void (*deallocate_p4_p5_vendor_ext)(void* header); @@ -860,7 +860,7 @@ typedef struct nfapi_vnf_p7_config * using the allocate_p7_vendor_ext callback * \return not currently used. */ - int (*vendor_ext)(struct nfapi_vnf_p7_config* config, nfapi_p7_message_header_t* msg); + int (*vendor_ext)(struct nfapi_vnf_p7_config* config, void* msg); /*! Optional userdata that will be passed back in the callbacks*/ void* user_data; @@ -871,12 +871,12 @@ typedef struct nfapi_vnf_p7_config * The callee must set this value * \return A pointer to an allocated vendor extention message */ - nfapi_p7_message_header_t* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size); + void* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size); /*! A callback to deallocate a vendor extension message * \param header A pointer to an allocated vendor extention message */ - void (*deallocate_p7_vendor_ext)(nfapi_p7_message_header_t* header); + void (*deallocate_p7_vendor_ext)(void* header); } nfapi_vnf_p7_config_t; diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 631ce2b7e9fb36542418d40ea8f1de675696ac94..cf8a945264c9ed89a75a2d9ef4c6f4323d45fc0f 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -30,7 +30,7 @@ #ifdef ENABLE_AERIAL #include "nfapi/oai_integration/aerial/fapi_nvIPC.h" #include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" -#include "nr_fapi.h" +#include "nr_fapi_p5.h" #endif #include "nfapi/oai_integration/vendor_ext.h" @@ -1063,7 +1063,7 @@ void vnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, nfapi_vnf_confi void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config) { - nfapi_p4_p5_message_header_t messageHeader; + nfapi_nr_p4_p5_message_header_t messageHeader; // validate the input params if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH || config == NULL) @@ -1073,7 +1073,7 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa } // unpack the message header - if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &config->codec_config) < 0) + if (nfapi_nr_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p4_p5_message_header_t), &config->codec_config) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -1255,7 +1255,7 @@ int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_ // 3. Read the buffer // 4. Handle the p5 message - uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; uint8_t header_buffer[header_buffer_size]; uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure @@ -1282,8 +1282,8 @@ int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_ return 0; } - nfapi_p4_p5_message_header_t header; - int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); + nfapi_nr_p4_p5_message_header_t header; + int unpack_result = nfapi_nr_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); if (unpack_result < 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header %d\n", unpack_result); return 0; @@ -1518,7 +1518,7 @@ static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, return 0; } -int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len) +int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint16_t msg_len) { nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); @@ -1547,7 +1547,7 @@ int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_mes &vnf->_public.codec_config); if (packedMessageLength < 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed with return %d\n", packedMessageLength); + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed with return %d\n", packedMessageLength); return -1; } // printf("msg id = 0x%02x, entire message length: %d\n", msg->message_id, packedMessageLength); diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 28c7b71656f1f444a4ff4669a4ca74d7f34055fd..a30efaf47f75af05113dc713a60de7aeafc468c8 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -29,6 +29,7 @@ #include "nfapi/oai_integration/aerial/fapi_nvIPC.h" #endif #include "vnf_p7.h" +#include "nr_fapi_p7_utils.h" #ifdef NDEBUG # warning assert is disabled @@ -474,14 +475,14 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u return 0; } -int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header) +int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header) { nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); if(p7_connection) { int send_result = 0; - uint8_t buffer[1024 * 32]; + uint8_t buffer[1024*1024*3]; header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, p7_connection->sequence_number); @@ -501,45 +502,45 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* // todo : worry about blocking writes? // segmenting the transmit - int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; - int seg_body_len = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; + int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH ; + int seg_body_len = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH ; int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); int segment = 0; - int offset = NFAPI_P7_HEADER_LENGTH; + int offset = NFAPI_NR_P7_HEADER_LENGTH; uint8_t tx_buffer[vnf_p7->_public.segment_size]; NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); for(segment = 0; segment < segment_count; ++segment) { uint8_t last = 0; - uint16_t size = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH; + uint16_t size = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; if(segment + 1 == segment_count) { last = 1; size = (msg_body_len) - (seg_body_len * segment); } - uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH; + uint16_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; // Update the header with the m and segement - memcpy(&tx_buffer[0], buffer, NFAPI_P7_HEADER_LENGTH); + memcpy(&tx_buffer[0], buffer, NFAPI_NR_P7_HEADER_LENGTH); // set the segment length - tx_buffer[4] = (segment_size & 0xFF00) >> 8; - tx_buffer[5] = (segment_size & 0xFF); + tx_buffer[6] = (segment_size & 0xFF00) >> 8; + tx_buffer[7] = (segment_size & 0xFF); // set the m & segment number - tx_buffer[6] = ((!last) << 7) + segment; + tx_buffer[8] = ((!last) << 7) + segment; - memcpy(&tx_buffer[NFAPI_P7_HEADER_LENGTH], &buffer[0] + offset, size); + memcpy(&tx_buffer[NFAPI_NR_P7_HEADER_LENGTH], &buffer[0] + offset, size); offset += size; if(vnf_p7->_public.checksum_enabled) { - nfapi_p7_update_checksum(tx_buffer, segment_size); + nfapi_nr_p7_update_checksum(tx_buffer, segment_size); } - nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); + nfapi_nr_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); @@ -549,10 +550,10 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* { if(vnf_p7->_public.checksum_enabled) { - nfapi_p7_update_checksum(buffer, len); + nfapi_nr_p7_update_checksum(buffer, len); } - nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); + nfapi_nr_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); // simple case that the message fits in a single segement send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len); @@ -1084,6 +1085,37 @@ void vnf_handle_p7_vendor_extension(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vn } +void vnf_nr_handle_p7_vendor_extension(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7, uint16_t message_id) +{ + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else if(vnf_p7->_public.allocate_p7_vendor_ext) + { + uint16_t msg_size; + nfapi_nr_p7_message_header_t* msg = vnf_p7->_public.allocate_p7_vendor_ext(message_id, &msg_size); + + if(msg == 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n", __FUNCTION__); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &vnf_p7->_public.codec_config); + + if(unpack_result == 0) + { + if(vnf_p7->_public.vendor_ext) + vnf_p7->_public.vendor_ext(&(vnf_p7->_public), msg); + } + + if(vnf_p7->_public.deallocate_p7_vendor_ext) + vnf_p7->_public.deallocate_p7_vendor_ext(msg); + + } +} + void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { uint32_t now_time_hr = vnf_get_current_time_hr(); @@ -1480,6 +1512,7 @@ void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf { (vnf_p7->_public.nr_slot_indication)(&ind); } + free_slot_indication(&ind); } } @@ -1506,6 +1539,7 @@ void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* { (vnf_p7->_public.nr_rx_data_indication)(&ind); } + free_rx_data_indication(&ind); } } } @@ -1532,6 +1566,7 @@ void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { (vnf_p7->_public.nr_crc_indication)(&ind); } + free_crc_indication(&ind); } } } @@ -1557,6 +1592,7 @@ void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { (vnf_p7->_public.nr_srs_indication)(&ind); } + free_srs_indication(&ind); } } } @@ -1583,6 +1619,7 @@ void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { (vnf_p7->_public.nr_uci_indication)(&ind); } + free_uci_indication(&ind); } } } @@ -1609,6 +1646,7 @@ void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf { (vnf_p7->_public.nr_rach_indication)(&ind); } + free_rach_indication(&ind); } } } @@ -2166,7 +2204,7 @@ void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { - nfapi_p7_message_header_t header; + nfapi_nr_p7_message_header_t header; // validate the input params if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) @@ -2176,7 +2214,7 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 } // unpack the message header - if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0) + if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -2363,7 +2401,7 @@ void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { - nfapi_p7_message_header_t messageHeader; + nfapi_nr_p7_message_header_t messageHeader; // validate the input params if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) @@ -2373,7 +2411,7 @@ void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } // unpack the message header - if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &vnf_p7->_public.codec_config) < 0) + if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p7_message_header_t), &vnf_p7->_public.codec_config) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -2381,7 +2419,7 @@ void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) if(vnf_p7->_public.checksum_enabled) { - uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen); + uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); if(checksum != messageHeader.checksum) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d msg:%d len:%d\n", checksum, messageHeader.checksum, messageHeader.message_id, recvMsgLen); @@ -2422,7 +2460,7 @@ void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) uint16_t length = 0; for(i = 0; i < rx_msg->num_segments_expected; ++i) { - length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0); + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); } if(phy->reassembly_buffer_size < length) @@ -2455,8 +2493,8 @@ void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } else { - memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH); - offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH; + memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; } } @@ -2488,14 +2526,14 @@ int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7) do { // peek the header - uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH]; - recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); + uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_NR_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); if(recvfrom_result > 0) { // get the segment size - nfapi_p7_message_header_t header; - if(nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0) + nfapi_nr_p7_message_header_t header; + if(nfapi_nr_p7_message_header_unpack(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return -1; diff --git a/nfapi/tests/nr_fapi_test.h b/nfapi/tests/nr_fapi_test.h index 3c4c67a542b7b613cb96320188dfcd8b45600c10..647cdf94f2963a9a91df429e19e11187c9abf33e 100644 --- a/nfapi/tests/nr_fapi_test.h +++ b/nfapi/tests/nr_fapi_test.h @@ -81,6 +81,16 @@ uint16_t rand16_range(uint16_t lower, uint16_t upper) return (rand() % (upper - lower + 1)) + lower; } +int16_t rands16_range(int16_t lower, int16_t upper) +{ + return (rand() % (upper - lower + 1)) + lower; +} + +uint32_t rand32_range(uint32_t lower, uint32_t upper) +{ + return (rand() % (upper - lower + 1)) + lower; +} + int main(int n, char *v[]); static inline void fapi_test_init_seeded(time_t seed) diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 3e098722b235ee879a5b5278999045c187749cd9..f980b3e61ec4081ebebfc8a8dfebb935c6d7c383 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_config_request_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void fill_config_request_tlv(nfapi_nr_config_request_scf_t *nfapi_resp) @@ -88,8 +79,7 @@ void fill_config_request_tlv(nfapi_nr_config_request_scf_t *nfapi_resp) FILL_TLV(nfapi_resp->ssb_config.bch_payload, NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG, rand8()); nfapi_resp->num_tlv++; - // NOTE: MUST be between 0 & 4 ( inclusive ) , since this value is used as index to obtain slots per frame - FILL_TLV(nfapi_resp->ssb_config.scs_common, NFAPI_NR_CONFIG_SCS_COMMON_TAG, rand8_range(0, 4)); + FILL_TLV(nfapi_resp->ssb_config.scs_common, NFAPI_NR_CONFIG_SCS_COMMON_TAG, 1 /* 30 kHz */); nfapi_resp->num_tlv++; FILL_TLV(nfapi_resp->prach_config.prach_sequence_length, NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, rand8()); @@ -185,30 +175,31 @@ void fill_config_request_tlv(nfapi_nr_config_request_scf_t *nfapi_resp) nfapi_resp->num_tlv++; } - FILL_TLV(nfapi_resp->tdd_table.tdd_period, NFAPI_NR_CONFIG_TDD_PERIOD_TAG, rand8()); + FILL_TLV(nfapi_resp->tdd_table.tdd_period, NFAPI_NR_CONFIG_TDD_PERIOD_TAG, 6 /* ms5 */); nfapi_resp->num_tlv++; - const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; - // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 - uint8_t cyclicprefix = 1; - bool normal_CP = cyclicprefix ? false : true; - // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 - uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12; - - nfapi_resp->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *)malloc( - slotsperframe[nfapi_resp->ssb_config.scs_common.value] * sizeof(nfapi_nr_max_tdd_periodicity_t)); - for (int i = 0; i < slotsperframe[nfapi_resp->ssb_config.scs_common.value]; i++) { - nfapi_resp->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = - (nfapi_nr_max_num_of_symbol_per_slot_t *)malloc(number_of_symbols_per_slot * sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); +#define SET_SYMBOL_TYPE(TDD_PERIOD_LIST, START, END, TYPE) \ + for (int SyM = (START); SyM < (END); SyM++) { \ + FILL_TLV((TDD_PERIOD_LIST)[SyM].slot_config, NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, (TYPE)); \ } - for (int i = 0; i < slotsperframe[nfapi_resp->ssb_config.scs_common.value]; i++) { // TODO check right number of slots - for (int k = 0; k < number_of_symbols_per_slot; k++) { // TODO can change? - FILL_TLV(nfapi_resp->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config, - NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, - rand8()); - nfapi_resp->num_tlv++; + int slots = 20; + int sym = 14; + nfapi_resp->tdd_table.max_tdd_periodicity_list = calloc(slots, sizeof(*nfapi_resp->tdd_table.max_tdd_periodicity_list)); + for (int i = 0; i < slots; i++) { + nfapi_nr_max_tdd_periodicity_t* list = &nfapi_resp->tdd_table.max_tdd_periodicity_list[i]; + list->max_num_of_symbol_per_slot_list = calloc(sym, sizeof(*list->max_num_of_symbol_per_slot_list)); + // DDDDDDMUUU + if ((i >= 0 && i <= 5) || (i >= 10 && i <= 15)) { + SET_SYMBOL_TYPE(list->max_num_of_symbol_per_slot_list, 0, sym, 0 /* DL */); + } else if (i == 6 || i == 16) { + SET_SYMBOL_TYPE(list->max_num_of_symbol_per_slot_list, 0, 4, 0 /* DL */); + SET_SYMBOL_TYPE(list->max_num_of_symbol_per_slot_list, 4, 10, 2 /* guard */); + SET_SYMBOL_TYPE(list->max_num_of_symbol_per_slot_list, 10, sym, 1 /* UL */); + } else { + SET_SYMBOL_TYPE(list->max_num_of_symbol_per_slot_list, 0, sym, 1 /* UL */); } + nfapi_resp->num_tlv += sym; } FILL_TLV(nfapi_resp->measurement_config.rssi_measurement, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, rand8()); @@ -259,7 +250,7 @@ void test_pack_unpack(nfapi_nr_config_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_config_response_test.c b/nfapi/tests/p5/nr_fapi_config_response_test.c index ae97b93c2ce9cada3be15e3c73ca76f2b848c3c7..bc44b4b6fdeffbc3961b8b4a7c926b4f6c591dfa 100644 --- a/nfapi/tests/p5/nr_fapi_config_response_test.c +++ b/nfapi/tests/p5/nr_fapi_config_response_test.c @@ -18,22 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_config_response_test.c - * \brief Defines a unitary test for the FAPI CONFIG.response message ( 0x03 ) - * The test consists of filling a message with randomized data, filling each lists as well with random TLVs - * After the message is created, is is packed into a byte buffer - * After packing, the header is unpacked to mimic SCTP PEEK and the values unpacked checked against the original message - * After the header is checked, the whole message is unpacked. - * The test ends by checking all of the unpacked message contents against the original message - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void fill_config_response_tlv_list(nfapi_nr_generic_tlv_scf_t *list, uint8_t size) @@ -106,7 +92,7 @@ void test_pack_unpack(nfapi_nr_config_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_error_indication_test.c b/nfapi/tests/p5/nr_fapi_error_indication_test.c index 97431ca9c3f4289307eeab484bce270c38baa5b8..85ef17b536ad67d17c613a2c346224da597a1027 100644 --- a/nfapi/tests/p5/nr_fapi_error_indication_test.c +++ b/nfapi/tests/p5/nr_fapi_error_indication_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_error_indication_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void test_pack_unpack(nfapi_nr_error_indication_scf_t *req) @@ -49,7 +40,7 @@ void test_pack_unpack(nfapi_nr_error_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_param_request_test.c b/nfapi/tests/p5/nr_fapi_param_request_test.c index 5356160ca4128371bf517c92efedb5f7dcf09d73..d42717eaeb9be5139a5faec29dcd096c1a64ffeb 100644 --- a/nfapi/tests/p5/nr_fapi_param_request_test.c +++ b/nfapi/tests/p5/nr_fapi_param_request_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_param_request_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void test_pack_unpack(nfapi_nr_param_request_scf_t *req) @@ -50,7 +41,7 @@ void test_pack_unpack(nfapi_nr_param_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_param_response_test.c b/nfapi/tests/p5/nr_fapi_param_response_test.c index 75ca6d5e31ef0878f009038511da7caaed27062c..1ba14c1655e2fb22814ee594c1f1fec53cad1f9b 100644 --- a/nfapi/tests/p5/nr_fapi_param_response_test.c +++ b/nfapi/tests/p5/nr_fapi_param_response_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_param_response_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void fill_param_response_tlv(nfapi_nr_param_response_scf_t *nfapi_resp) @@ -235,14 +226,14 @@ void test_pack_unpack(nfapi_nr_param_response_scf_t *req) req->header.message_length = pack_result - NFAPI_HEADER_LENGTH; // test the unpacking of the header // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK - nfapi_p4_p5_message_header_t header; + nfapi_nr_p4_p5_message_header_t header; uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; uint8_t header_buffer[header_buffer_size]; for (int idx = 0; idx < header_buffer_size; idx++) { header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_start_request_test.c b/nfapi/tests/p5/nr_fapi_start_request_test.c index 9384488c46c40ccb188994079c58a2cf4b855e77..9a36528db657407feed62e0b84cb7d70bc3f8793 100644 --- a/nfapi/tests/p5/nr_fapi_start_request_test.c +++ b/nfapi/tests/p5/nr_fapi_start_request_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_start_request_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void test_pack_unpack(nfapi_nr_start_request_scf_t *req) @@ -50,7 +41,7 @@ void test_pack_unpack(nfapi_nr_start_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_start_response_test.c b/nfapi/tests/p5/nr_fapi_start_response_test.c index 32ef894981d9fc6ff477413cbec8dd5f8e64e43b..bb3a0967342858386caafac4ff8f853c4ba30e65 100644 --- a/nfapi/tests/p5/nr_fapi_start_response_test.c +++ b/nfapi/tests/p5/nr_fapi_start_response_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_start_response_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void test_pack_unpack(nfapi_nr_start_response_scf_t *req) @@ -50,7 +41,7 @@ void test_pack_unpack(nfapi_nr_start_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_stop_indication_test.c b/nfapi/tests/p5/nr_fapi_stop_indication_test.c index ee3946c8e40c6ffb0f14a6d4a48eecdf81d69269..4b5d9d431938f4c15c8181aac2a3f293ce27db39 100644 --- a/nfapi/tests/p5/nr_fapi_stop_indication_test.c +++ b/nfapi/tests/p5/nr_fapi_stop_indication_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_stop_indication_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void test_pack_unpack(nfapi_nr_stop_indication_scf_t *req) @@ -50,7 +41,7 @@ void test_pack_unpack(nfapi_nr_stop_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_stop_request_test.c b/nfapi/tests/p5/nr_fapi_stop_request_test.c index 74311cf94e33efc84473d01838709e2ce549282c..74e5ea31ffbd04bb84cf6231f13dfeaaf4be4a45 100644 --- a/nfapi/tests/p5/nr_fapi_stop_request_test.c +++ b/nfapi/tests/p5/nr_fapi_stop_request_test.c @@ -18,17 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_stop_request_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ #include "nfapi/tests/nr_fapi_test.h" +#include "nr_fapi_p5.h" #include "nr_fapi_p5_utils.h" void test_pack_unpack(nfapi_nr_stop_request_scf_t *req) @@ -50,7 +41,7 @@ void test_pack_unpack(nfapi_nr_stop_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/CMakeLists.txt b/nfapi/tests/p7/CMakeLists.txt index 7cf1958693a8ad0b9faa480e34eb22a46f653e24..74e90a855705db4d4cceb39588b03800212824ca 100644 --- a/nfapi/tests/p7/CMakeLists.txt +++ b/nfapi/tests/p7/CMakeLists.txt @@ -1,8 +1,8 @@ set(Test_Labels fapi p7) -set(_fapi_p7_messages "dci_inversion") +set(_fapi_p7_messages "dci_inversion;dl_tti_request;ul_tti_request;slot_indication;ul_dci_request;tx_data_request;rx_data_indication;crc_indication;uci_indication;srs_indication;rach_indication") foreach (fapi_p7_message IN LISTS _fapi_p7_messages) add_executable(nr_fapi_${fapi_p7_message}_test nr_fapi_${fapi_p7_message}_test.c) - target_link_libraries(nr_fapi_${fapi_p7_message}_test PUBLIC nr_fapi_p5) + target_link_libraries(nr_fapi_${fapi_p7_message}_test PUBLIC nr_fapi_p7) target_link_libraries(nr_fapi_${fapi_p7_message}_test PRIVATE pthread UTIL ${T_LIB} minimal_lib) add_dependencies(tests nr_fapi_${fapi_p7_message}_test) diff --git a/nfapi/tests/p7/dci_payload_utils.h b/nfapi/tests/p7/dci_payload_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..5788a133bcb4766e4ff66305b383ae064d5f9c4c --- /dev/null +++ b/nfapi/tests/p7/dci_payload_utils.h @@ -0,0 +1,94 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef OPENAIRINTERFACE_DCI_PAYLOAD_UTILS_H +#define OPENAIRINTERFACE_DCI_PAYLOAD_UTILS_H +#include "nfapi/tests/nr_fapi_test.h" + +void printbits(const uint64_t n, const uint8_t numBytesToPrint) +{ + uint64_t i; + uint8_t counter = 0; + if (numBytesToPrint == 0) { + i = 1UL << (sizeof(n) * 8 - 1); + } else { + i = 1UL << (numBytesToPrint * 8 - 1); + } + while (i > 0) { + if (n & i) + printf("1"); + else + printf("0"); + i >>= 1; + counter++; + if (counter % 8 == 0) { + printf(" "); + } + } +} + +/*! \brief Drops unwanted bits from a byte array, leaving only a specified number of payload bits + * + * \param payloadSizeBits How many bits the payload is to have, from 1 to 64 (8 * DCI_PAYLOAD_BYTE_LEN) + * \param payload[] A uint8_t array containing the payload bytes with random data + * \details This function creates a bitmask of payloadSizeBits width to truncate the data in payload[] to only have the specified + * number of payload bits\n + * For example, a payload of 39 bits needs 5 bytes, but on the last byte, the last bit is unused, this function makes sure that + * last bit is set to 0, allowing the payload to be then packed and unpacked and successfully compared with the original payload + */ +void truncate_unwanted_bits(uint8_t payloadSizeBits, uint8_t payload[]) +{ + uint8_t payloadSizeBytes = (payloadSizeBits + 7) / 8; + printf("Original Value:\t"); + uint64_t t = 0; + memcpy(&t, payload, payloadSizeBytes); + printbits(t, payloadSizeBytes); + printf("\n"); + uint64_t bitmask = 1; + for (int i = 0; i < payloadSizeBits - 1; i++) { + bitmask = bitmask << 1 | 1; + } + printf("Calculated Bitmask:\t"); + printbits(bitmask, payloadSizeBytes); + printf("\n"); + t = t & bitmask; + printf("Truncated Value:\t"); + printbits(t, payloadSizeBytes); + printf("\n"); + memcpy(payload, &t, payloadSizeBytes); +} + +/*! \brief Generates a random payload payloadSizeBits long into payload[] + * + * \param payloadSizeBits How many bits the payload is to have, from 1 to 64 (8 * DCI_PAYLOAD_BYTE_LEN) + * \param payload[] A uint8_t array to contain the generated payload + * \details This function fills a uint8_t array with payloadSizeBits of random data, by first filling however many bytes are needed + * to contain payloadSizeBits with random data, and then truncating the excess bits + */ +void generate_payload(uint8_t payloadSizeBits, uint8_t payload[]) +{ + for (int i = 0; i < (payloadSizeBits + 7) / 8; ++i) { + payload[i] = rand8(); + } + truncate_unwanted_bits(payloadSizeBits, payload); +} + +#endif // OPENAIRINTERFACE_DCI_PAYLOAD_UTILS_H diff --git a/nfapi/tests/p7/nr_fapi_crc_indication_test.c b/nfapi/tests/p7/nr_fapi_crc_indication_test.c new file mode 100644 index 0000000000000000000000000000000000000000..472959b0d6aebe63794d774a242f548c976529b4 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_crc_indication_test.c @@ -0,0 +1,116 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_crc_indication_CRC(nfapi_nr_crc_t *crc) +{ + crc->handle = rand32(); + crc->rnti = rand16_range(1, 65535); + crc->harq_id = rand8_range(0, 15); + crc->tb_crc_status = rand8_range(0, 1); + crc->num_cb = rand16(); + if (crc->num_cb > 0) { + crc->cb_crc_status = calloc((crc->num_cb / 8) + 1, sizeof(uint8_t)); + for (int cb = 0; cb < (crc->num_cb / 8) + 1; ++cb) { + crc->cb_crc_status[cb] = rand8(); + } + } + crc->ul_cqi = rand8(); + crc->timing_advance = rand16_range(0, 63); + crc->rssi = rand16_range(0, 1280); +} + +static void fill_crc_indication(nfapi_nr_crc_indication_t *msg) +{ + msg->sfn = rand16_range(0, 1023); + msg->slot = rand16_range(0, 159); + msg->number_crcs = rand8_range(1, NFAPI_NR_CRC_IND_MAX_PDU); // Minimum 1 PDUs in order to test at least one + msg->crc_list = calloc_or_fail(msg->number_crcs, sizeof(*msg->crc_list)); + for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { + fill_crc_indication_CRC(&msg->crc_list[crc_idx]); + } +} + +static void test_pack_unpack(nfapi_nr_crc_indication_t *req) +{ + size_t message_size = get_crc_indication_size(req); + uint8_t *msg_buf = calloc_or_fail(message_size, sizeof(uint8_t)); + /*uint8_t msg_buf[1024*1024*3]; + size_t message_size = sizeof(msg_buf);*/ + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, message_size, NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_crc_indication_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_crc_indication(&unpacked_req, req)); + free_crc_indication(&unpacked_req); + free(msg_buf); +} + +static void test_copy(const nfapi_nr_crc_indication_t *msg) +{ + // Test copy function + nfapi_nr_crc_indication_t copy = {0}; + copy_crc_indication(msg, ©); + DevAssert(eq_crc_indication(msg, ©)); + free_crc_indication(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_crc_indication_t *req = calloc_or_fail(1, sizeof(nfapi_nr_crc_indication_t)); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; + // Get the actual allocated size + printf("Allocated size before filling: %zu bytes\n", get_crc_indication_size(req)); + // Fill TX_DATA request + fill_crc_indication(req); + printf("Allocated size after filling: %zu bytes\n", get_crc_indication_size(req)); + // Perform tests + test_pack_unpack(req); + test_copy(req); + // All tests successful! + free_crc_indication(req); + free(req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_dci_inversion_test.c b/nfapi/tests/p7/nr_fapi_dci_inversion_test.c index 22e883b0cd91b5246c169b4e35cd6be1bc046acb..29c534baa5053da2f885e7319f48ee7b65fec153 100644 --- a/nfapi/tests/p7/nr_fapi_dci_inversion_test.c +++ b/nfapi/tests/p7/nr_fapi_dci_inversion_test.c @@ -18,86 +18,8 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -/*! \file nfapi/tests/p5/nr_fapi_param_request_test.c - * \brief - * \author Ruben S. Silva - * \date 2024 - * \version 0.1 - * \company OpenAirInterface Software Alliance - * \email: contact@openairinterface.org, rsilva@allbesmart.pt - * \note - * \warning - */ -#include "nfapi/tests/nr_fapi_test.h" -#include "nr_fapi_p5.h" +#include "dci_payload_utils.h" #include "nr_fapi.h" -void printbits(uint64_t n, uint8_t numBytesToPrint) -{ - uint64_t i; - uint8_t counter = 0; - if (numBytesToPrint == 0) { - i = 1UL << (sizeof(n) * 8 - 1); - } else { - i = 1UL << (numBytesToPrint * 8 - 1); - } - while (i > 0) { - if (n & i) - printf("1"); - else - printf("0"); - i >>= 1; - counter++; - if (counter % 8 == 0) { - printf(" "); - } - } -} - -/*! \brief Drops unwanted bits from a byte array, leaving only a specified number of payload bits - * - * \param payloadSizeBits How many bits the payload is to have, from 1 to 64 (8 * DCI_PAYLOAD_BYTE_LEN) - * \param payload[] A uint8_t array containing the payload bytes with random data - * \details This function creates a bitmask of payloadSizeBits width to truncate the data in payload[] to only have the specified - * number of payload bits\n - * For example, a payload of 39 bits needs 5 bytes, but on the last byte, the last bit is unused, this function makes sure that - * last bit is set to 0, allowing the payload to be then packed and unpacked and successfully compared with the original payload - */ -void truncate_unwanted_bits(uint8_t payloadSizeBits, uint8_t payload[]) -{ - uint8_t payloadSizeBytes = (payloadSizeBits + 7) / 8; - printf("Original Value:\t"); - uint64_t t = 0; - memcpy(&t, payload, payloadSizeBytes); - printbits(t, payloadSizeBytes); - printf("\n"); - uint64_t bitmask = 1; - for (int i = 0; i < payloadSizeBits - 1; i++) { - bitmask = bitmask << 1 | 1; - } - printf("Calculated Bitmask:\t"); - printbits(bitmask, payloadSizeBytes); - printf("\n"); - t = t & bitmask; - printf("Truncated Value:\t"); - printbits(t, payloadSizeBytes); - printf("\n"); - memcpy(payload, &t, payloadSizeBytes); -} - -/*! \brief Generates a random payload payloadSizeBits long into payload[] - * - * \param payloadSizeBits How many bits the payload is to have, from 1 to 64 (8 * DCI_PAYLOAD_BYTE_LEN) - * \param payload[] A uint8_t array to contain the generated payload - * \details This function fills a uint8_t array with payloadSizeBits of random data, by first filling however many bytes are needed - * to contain payloadSizeBits with random data, and then truncating the excess bits - */ -void generate_payload(uint8_t payloadSizeBits, uint8_t payload[]) -{ - for (int i = 0; i < (payloadSizeBits + 7) / 8; ++i) { - payload[i] = rand8(); - } - truncate_unwanted_bits(payloadSizeBits, payload); -} void test_pack_payload(uint8_t payloadSizeBits, uint8_t payload[]) { diff --git a/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c b/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c new file mode 100644 index 0000000000000000000000000000000000000000..2cc95260f0a4f0107592b013983e4684ba8f13e2 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c @@ -0,0 +1,279 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_dl_tti_request_beamforming(nfapi_nr_tx_precoding_and_beamforming_t *precodingAndBeamforming) +{ + precodingAndBeamforming->num_prgs = rand16_range(1, NFAPI_MAX_NUM_PRGS); + precodingAndBeamforming->prg_size = rand16_range(1, 275); + precodingAndBeamforming->dig_bf_interfaces = rand8_range(0,NFAPI_MAX_NUM_BG_IF); + for (int prg = 0; prg < precodingAndBeamforming->num_prgs; ++prg) { + precodingAndBeamforming->prgs_list[prg].pm_idx = rand16(); + for (int dbf_if = 0; dbf_if < precodingAndBeamforming->dig_bf_interfaces; ++dbf_if) { + precodingAndBeamforming->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx = rand16(); + } + } +} + +static void fill_dl_tti_request_pdcch_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdu) +{ + pdu->BWPSize = rand16(); + pdu->BWPStart = rand16(); + pdu->SubcarrierSpacing = rand8(); + pdu->CyclicPrefix = rand8(); + pdu->StartSymbolIndex = rand8(); + pdu->DurationSymbols = rand8(); + for (int fdr_idx = 0; fdr_idx < 6; ++fdr_idx) { + pdu->FreqDomainResource[fdr_idx] = rand8(); + } + pdu->CceRegMappingType = rand8(); + pdu->RegBundleSize = rand8(); + pdu->InterleaverSize = rand8(); + pdu->CoreSetType = rand8(); + pdu->ShiftIndex = rand8(); + pdu->precoderGranularity = rand8(); + pdu->numDlDci = rand8_range(1, MAX_DCI_CORESET); + for (int dl_dci = 0; dl_dci < pdu->numDlDci; ++dl_dci) { + pdu->dci_pdu[dl_dci].RNTI = rand16(); + pdu->dci_pdu[dl_dci].ScramblingId = rand16(); + pdu->dci_pdu[dl_dci].ScramblingRNTI = rand16(); + pdu->dci_pdu[dl_dci].CceIndex = rand8(); + pdu->dci_pdu[dl_dci].AggregationLevel = rand8(); + fill_dl_tti_request_beamforming(&pdu->dci_pdu[dl_dci].precodingAndBeamforming); + pdu->dci_pdu[dl_dci].beta_PDCCH_1_0 = rand8(); + pdu->dci_pdu[dl_dci].powerControlOffsetSS = rand8(); + pdu->dci_pdu[dl_dci].PayloadSizeBits = rand16_range(0, DCI_PAYLOAD_BYTE_LEN * 8); + generate_payload(pdu->dci_pdu[dl_dci].PayloadSizeBits, pdu->dci_pdu[dl_dci].Payload); + } +} + +static void fill_dl_tti_request_pdsch_pdu(nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdu) +{ + pdu->pduBitmap = rand16_range(0, 2); + pdu->rnti = rand16(); + pdu->pduIndex = rand16(); + pdu->BWPSize = rand16_range(1, 275); + pdu->BWPStart = rand16_range(0, 274); + pdu->SubcarrierSpacing = rand8_range(0, 4); + pdu->CyclicPrefix = rand8_range(0, 1); + pdu->NrOfCodewords = rand8_range(1, 2); + for (int cw = 0; cw < pdu->NrOfCodewords; ++cw) { + pdu->targetCodeRate[cw] = rand16(); + pdu->qamModOrder[cw] = rand8(); + pdu->mcsIndex[cw] = rand8(); + pdu->mcsTable[cw] = rand8_range(0, 2); + pdu->rvIndex[cw] = rand8_range(0, 3); + pdu->TBSize[cw] = rand16(); + } + pdu->dataScramblingId = rand16(); + pdu->nrOfLayers = rand8_range(1, 8); + pdu->transmissionScheme = rand8_range(0, 8); + pdu->refPoint = rand8_range(0, 1); + // dlDmrsSymbPos is a bitmap occupying the 14 LSB + pdu->dlDmrsSymbPos = rand16_range(0, 0x3FFF); + pdu->dmrsConfigType = rand8_range(0, 1); + pdu->dlDmrsScramblingId = rand16(); + pdu->SCID = rand8_range(0, 1); + pdu->numDmrsCdmGrpsNoData = rand8_range(1, 3); + // dmrsPorts is a bitmap occupying the 11 LSB + pdu->dmrsPorts = rand16_range(0, 0x7FF); + pdu->resourceAlloc = rand8_range(0, 1); + for (int i = 0; i < 36; ++i) { + pdu->rbBitmap[i] = rand8(); + } + pdu->rbStart = rand16_range(0, 274); + pdu->rbSize = rand16_range(1, 275); + pdu->VRBtoPRBMapping = rand8_range(0, 2); + pdu->StartSymbolIndex = rand8_range(0, 13); + pdu->NrOfSymbols = rand8_range(1, 14); + + if (pdu->pduBitmap & 0b1) { + // PTRSPortIndex is a bitmap occupying the 6 LSB + pdu->PTRSPortIndex = rand8_range(0, 0x3F); + pdu->PTRSTimeDensity = rand8_range(0, 2); + pdu->PTRSFreqDensity = rand8_range(0, 1); + pdu->PTRSReOffset = rand8_range(0, 3); + pdu->nEpreRatioOfPDSCHToPTRS = rand8_range(0, 3); + } + fill_dl_tti_request_beamforming(&pdu->precodingAndBeamforming); + pdu->powerControlOffset = rand8_range(0, 23); + pdu->powerControlOffsetSS = rand8_range(0, 3); + // Check pduBitMap bit 1 to add or not CBG parameters + if (pdu->pduBitmap & 0b10) { + pdu->isLastCbPresent = rand8_range(0, 1); + pdu->isInlineTbCrc = rand8_range(0, 1); + pdu->dlTbCrc = rand32(); + } + pdu->maintenance_parms_v3.ldpcBaseGraph = rand8(); + pdu->maintenance_parms_v3.tbSizeLbrmBytes = rand32(); +} + +static void fill_dl_tti_request_csi_rs_pdu(nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *pdu) +{ + pdu->bwp_size = rand16_range(1, 275); + pdu->bwp_start = rand16_range(0, 274); + pdu->subcarrier_spacing = rand8_range(0, 4); + pdu->cyclic_prefix = rand8_range(0, 1); + pdu->start_rb = rand16_range(0, 274); + pdu->nr_of_rbs = rand16_range(0, pdu->bwp_size); + pdu->csi_type = rand8_range(0, 2); + pdu->row = rand8_range(1, 18); + // freq_domain is a bitmap up to 12 LSB, depending on row value [TS38.211, sec 7.4.1.5.3] + // row = 1 -> b0 to b3 + // row = 2 -> b0 to b11 + // row = 4 -> b0 to b2 + // other rows -> b0 to b5 + switch (pdu->row) { + case 1: // 4 bits + pdu->freq_domain = rand16_range(0, 0xF); + break; + case 2: // 12 bits + pdu->freq_domain = rand16_range(0, 0xFFF); + break; + case 4: // 3 bits + pdu->freq_domain = rand16_range(0, 7); + break; + default: // 6 bits + pdu->freq_domain = rand16_range(0, 0x3F); + break; + } + pdu->symb_l0 = rand8_range(0, 13); + pdu->symb_l1 = rand8_range(2, 12); + pdu->cdm_type = rand8_range(0, 3); + pdu->scramb_id = rand16_range(0, 1023); + pdu->power_control_offset = rand8_range(0, 23); + pdu->power_control_offset_ss = rand8_range(0, 3); + fill_dl_tti_request_beamforming(&pdu->precodingAndBeamforming); +} + +static void fill_dl_tti_request_ssb_pdu(nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu) +{ + pdu->PhysCellId = rand16_range(0, 1007); + pdu->BetaPss = rand8_range(0, 1); + pdu->SsbBlockIndex = rand8_range(0, 63); + pdu->SsbSubcarrierOffset = rand8_range(0, 31); + pdu->ssbOffsetPointA = rand16_range(0, 2199); + pdu->bchPayloadFlag = rand8_range(0, 2); + pdu->bchPayload = rand24(); + fill_dl_tti_request_beamforming(&pdu->precoding_and_beamforming); +} + +static void fill_dl_tti_request(nfapi_nr_dl_tti_request_t *msg) +{ + msg->SFN = rand16_range(0, 1023); + msg->Slot = rand16_range(0, 159); + int available_PDUs = rand8_range(4, 16); // Minimum 4 PDUs in order to test at least one of each + msg->dl_tti_request_body.nPDUs = available_PDUs; + msg->dl_tti_request_body.nGroup = rand8(); + + int pdu = 0; + int num_PDCCH = rand8_range(1, available_PDUs - 3); + + available_PDUs -= num_PDCCH; + int num_PDSCH = rand8_range(1, available_PDUs - 2); + + available_PDUs -= num_PDSCH; + int num_CSI_RS = rand8_range(1, available_PDUs - 1); + + available_PDUs -= num_CSI_RS; + int num_SSB = available_PDUs; + + for (int i = 0; i < num_PDCCH; ++pdu, ++i) { + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUSize = rand16(); + fill_dl_tti_request_pdcch_pdu(&msg->dl_tti_request_body.dl_tti_pdu_list[pdu].pdcch_pdu.pdcch_pdu_rel15); + } + + for (int i = 0; i < num_PDSCH; ++pdu, ++i) { + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUSize = rand16(); + fill_dl_tti_request_pdsch_pdu(&msg->dl_tti_request_body.dl_tti_pdu_list[pdu].pdsch_pdu.pdsch_pdu_rel15); + } + + for (int i = 0; i < num_CSI_RS; ++pdu, ++i) { + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUType = NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE; + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUSize = rand16(); + fill_dl_tti_request_csi_rs_pdu(&msg->dl_tti_request_body.dl_tti_pdu_list[pdu].csi_rs_pdu.csi_rs_pdu_rel15); + } + + for (int i = 0; i < num_SSB; ++pdu, ++i) { + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUType = NFAPI_NR_DL_TTI_SSB_PDU_TYPE; + msg->dl_tti_request_body.dl_tti_pdu_list[pdu].PDUSize = rand16(); + fill_dl_tti_request_ssb_pdu(&msg->dl_tti_request_body.dl_tti_pdu_list[pdu].ssb_pdu.ssb_pdu_rel15); + } +} + +static void test_pack_unpack(nfapi_nr_dl_tti_request_t *req) +{ + uint8_t msg_buf[1024 * 1024 * 6]; + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, sizeof(msg_buf), NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_dl_tti_request_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_dl_tti_request(&unpacked_req, req)); + free_dl_tti_request(&unpacked_req); +} + +static void test_copy(const nfapi_nr_dl_tti_request_t *msg) +{ + // Test copy function + nfapi_nr_dl_tti_request_t copy = {0}; + copy_dl_tti_request(msg, ©); + DevAssert(eq_dl_tti_request(msg, ©)); + free_dl_tti_request(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_dl_tti_request_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST}; + // Fill DL_TTI request + fill_dl_tti_request(&req); + // Perform tests + test_pack_unpack(&req); + test_copy(&req); + // All tests successful! + free_dl_tti_request(&req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_rach_indication_test.c b/nfapi/tests/p7/nr_fapi_rach_indication_test.c new file mode 100644 index 0000000000000000000000000000000000000000..fd4a0fac32c571e58122274ae0288f4aa3806a41 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_rach_indication_test.c @@ -0,0 +1,115 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_rach_indication_PDU(nfapi_nr_prach_indication_pdu_t *pdu) +{ + pdu->phy_cell_id = rand32(); + pdu->symbol_index = rand8_range(0,13); + pdu->slot_index = rand8_range(0,79); + pdu->freq_index = rand8_range(0,7); + pdu->avg_rssi = rand8(); + pdu->avg_snr = rand8(); + pdu->num_preamble = rand8_range(0,63); + for (int preamble_idx = 0; preamble_idx < pdu->num_preamble; ++preamble_idx) { + nfapi_nr_prach_indication_preamble_t *preamble = &pdu->preamble_list[preamble_idx]; + preamble->preamble_index = rand8_range(0,63); + preamble->timing_advance = rand16_range(0,3846); + preamble->preamble_pwr = rand32_range(0, 170000); + } +} + +static void fill_rach_indication(nfapi_nr_rach_indication_t *msg) +{ + msg->sfn = rand16_range(0, 1023); + msg->slot = rand16_range(0, 159); + msg->number_of_pdus = rand8_range(1, NFAPI_NR_RACH_IND_MAX_PDU); // Minimum 1 PDUs in order to test at least one + msg->pdu_list = calloc_or_fail(msg->number_of_pdus, sizeof(*msg->pdu_list)); + for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { + fill_rach_indication_PDU(&msg->pdu_list[pdu_idx]); + } +} + +static void test_pack_unpack(nfapi_nr_rach_indication_t *req) +{ + size_t message_size = get_rach_indication_size(req); + uint8_t *msg_buf = calloc_or_fail(message_size, sizeof(uint8_t)); + /*uint8_t msg_buf[1024*1024*3]; + size_t message_size = sizeof(msg_buf);*/ + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, message_size, NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_rach_indication_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_rach_indication(&unpacked_req, req)); + free_rach_indication(&unpacked_req); + free(msg_buf); +} + +static void test_copy(const nfapi_nr_rach_indication_t *msg) +{ + // Test copy function + nfapi_nr_rach_indication_t copy = {0}; + copy_rach_indication(msg, ©); + DevAssert(eq_rach_indication(msg, ©)); + free_rach_indication(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_rach_indication_t *req = calloc_or_fail(1, sizeof(nfapi_nr_rach_indication_t)); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; + // Get the actual allocated size + printf("Allocated size before filling: %zu bytes\n", get_rach_indication_size(req)); + // Fill TX_DATA request + fill_rach_indication(req); + printf("Allocated size after filling: %zu bytes\n", get_rach_indication_size(req)); + // Perform tests + test_pack_unpack(req); + test_copy(req); + // All tests successful! + free_rach_indication(req); + free(req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c b/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c new file mode 100644 index 0000000000000000000000000000000000000000..2f382cf7971f8714a39dd252a2f75ae082f7b0a1 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c @@ -0,0 +1,113 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_rx_data_indication_PDU(nfapi_nr_rx_data_pdu_t *pdu) +{ + pdu->handle = rand32(); + pdu->rnti = rand16_range(1, 65535); + pdu->harq_id = rand8_range(0, 15); + pdu->pdu_length = rand32_range(0, 65535 * 100); // Testing to a maximum of 100 times 2^16, to test 32 bit would take too long + pdu->ul_cqi = rand8(); + pdu->timing_advance = rand16_range(0, 63); + pdu->rssi = rand16_range(0, 1280); + pdu->pdu = calloc_or_fail(pdu->pdu_length, sizeof(uint8_t)); + for (int i = 0; i < pdu->pdu_length; ++i) { + pdu->pdu[i] = rand8(); + } +} + +static void fill_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) +{ + msg->sfn = rand16_range(0, 1023); + msg->slot = rand16_range(0, 159); + msg->number_of_pdus = rand8_range(1, NFAPI_NR_RX_DATA_IND_MAX_PDU); // Minimum 1 PDUs in order to test at least one + msg->pdu_list = calloc_or_fail(msg->number_of_pdus, sizeof(*msg->pdu_list)); + for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { + fill_rx_data_indication_PDU(&msg->pdu_list[pdu_idx]); + } +} + +static void test_pack_unpack(nfapi_nr_rx_data_indication_t *req) +{ + const size_t message_size = get_rx_data_indication_size(req); + uint8_t *msg_buf = calloc_or_fail(message_size, sizeof(uint8_t)); + /*uint8_t msg_buf[1024*1024*3]; + size_t message_size = sizeof(msg_buf);*/ + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, message_size, NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_rx_data_indication_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_rx_data_indication(&unpacked_req, req)); + free_rx_data_indication(&unpacked_req); + free(msg_buf); +} + +static void test_copy(const nfapi_nr_rx_data_indication_t *msg) +{ + // Test copy function + nfapi_nr_rx_data_indication_t copy = {0}; + copy_rx_data_indication(msg, ©); + DevAssert(eq_rx_data_indication(msg, ©)); + free_rx_data_indication(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_rx_data_indication_t *req = calloc_or_fail(1, sizeof(nfapi_nr_rx_data_indication_t)); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; + // Get the actual allocated size + printf("Allocated size before filling: %zu bytes\n", get_rx_data_indication_size(req)); + // Fill TX_DATA request + fill_rx_data_indication(req); + printf("Allocated size after filling: %zu bytes\n", get_rx_data_indication_size(req)); + // Perform tests + test_pack_unpack(req); + test_copy(req); + // All tests successful! + free_rx_data_indication(req); + free(req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_slot_indication_test.c b/nfapi/tests/p7/nr_fapi_slot_indication_test.c new file mode 100644 index 0000000000000000000000000000000000000000..96c030479c86c74709e4f5832e0e4e9e0dd64438 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_slot_indication_test.c @@ -0,0 +1,86 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_slot_indication(nfapi_nr_slot_indication_scf_t *msg) +{ + msg->sfn = rand16_range(0, 1023); + msg->slot = rand16_range(0, 159); +} + +static void test_pack_unpack(nfapi_nr_slot_indication_scf_t *req) +{ + uint8_t msg_buf[1024 * 1024 * 2]; + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, sizeof(msg_buf), NULL); + + // Should always return 4 (2 bytes sfn + 2 bytes slot ) + DevAssert(pack_result == 4); + // update req message_length value with value calculated in message_pack procedure + // req->header.message_length = pack_result; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_slot_indication_scf_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_slot_indication(&unpacked_req, req)); + free_slot_indication(&unpacked_req); +} + +static void test_copy(const nfapi_nr_slot_indication_scf_t *msg) +{ + // Test copy function + nfapi_nr_slot_indication_scf_t copy = {0}; + copy_slot_indication(msg, ©); + DevAssert(eq_slot_indication(msg, ©)); + free_slot_indication(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_slot_indication_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION}; + + // Fill DL_TTI request + fill_slot_indication(&req); + // Perform tests + test_pack_unpack(&req); + test_copy(&req); + // All tests successful! + free_slot_indication(&req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_srs_indication_test.c b/nfapi/tests/p7/nr_fapi_srs_indication_test.c new file mode 100644 index 0000000000000000000000000000000000000000..49b73fd8f5c443803587775c4f66ceac268aa2a0 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_srs_indication_test.c @@ -0,0 +1,119 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fil_srs_indication_report_tlv(nfapi_srs_report_tlv_t *tlv) +{ + tlv->tag = rand16_range(0,3); + tlv->length = rand32_range(0,sizeof(tlv->value)); + for (int i = 0; i < (tlv->length + 3) / 4; ++i) { + tlv->value[i] = rand32(); + } +} + +static void fill_srs_indication_PDU(nfapi_nr_srs_indication_pdu_t *pdu) +{ + pdu->handle = rand32(); + pdu->rnti = rand16_range(1, 65535); + pdu->timing_advance_offset = rand16_range(0, 63); + pdu->timing_advance_offset_nsec = rands16_range(-16800, 16800); + pdu->srs_usage = rand8_range(0,3); + pdu->report_type = rand8_range(0,1); + fil_srs_indication_report_tlv(&pdu->report_tlv); +} + +static void fill_srs_indication(nfapi_nr_srs_indication_t *msg) +{ + msg->sfn = rand16_range(0, 1023); + msg->slot = rand16_range(0, 159); + msg->control_length = rand16(); // being ignored number_of_pdusat the moment, report is always sent inline + msg->number_of_pdus = rand8_range(1, NFAPI_NR_SRS_IND_MAX_PDU); // Minimum 1 PDUs in order to test at least one + msg->pdu_list = calloc_or_fail(msg->number_of_pdus, sizeof(*msg->pdu_list)); + for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { + fill_srs_indication_PDU(&msg->pdu_list[pdu_idx]); + } +} + +static void test_pack_unpack(nfapi_nr_srs_indication_t *req) +{ + size_t message_size = get_srs_indication_size(req); + uint8_t *msg_buf = calloc_or_fail(message_size, sizeof(uint8_t)); + /*uint8_t msg_buf[1024*1024*3]; + size_t message_size = sizeof(msg_buf);*/ + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, message_size, NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_srs_indication_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_srs_indication(&unpacked_req, req)); + free_srs_indication(&unpacked_req); + free(msg_buf); +} + +static void test_copy(const nfapi_nr_srs_indication_t *msg) +{ + // Test copy function + nfapi_nr_srs_indication_t copy = {0}; + copy_srs_indication(msg, ©); + DevAssert(eq_srs_indication(msg, ©)); + free_srs_indication(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_srs_indication_t *req = calloc_or_fail(1, sizeof(nfapi_nr_srs_indication_t)); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; + // Get the actual allocated size + printf("Allocated size before filling: %zu bytes\n", get_srs_indication_size(req)); + // Fill TX_DATA request + fill_srs_indication(req); + printf("Allocated size after filling: %zu bytes\n", get_srs_indication_size(req)); + // Perform tests + test_pack_unpack(req); + test_copy(req); + // All tests successful! + free_srs_indication(req); + free(req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_tx_data_request_test.c b/nfapi/tests/p7/nr_fapi_tx_data_request_test.c new file mode 100644 index 0000000000000000000000000000000000000000..e67b5bf3ca5cbf635e0a33da179db1c903e5e07a --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_tx_data_request_test.c @@ -0,0 +1,176 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_tx_data_request_PDU(nfapi_nr_pdu_t *pdu) +{ + // PDU_Length The total length (in bytes) of the PDU description and PDU data, without the padding bytes. + // Minimum length = 4 PDULength + 2 PDUIndex + 4 numTLV + 2 tag + 4 length + 4 value = 20 + // ( assuming 1 TLV and "empty payload" sends 4 bytes of zeroes - For testing purposes only ) + // Max Length => 10 bytes PDU Header + 2 * (2 bytes tag, 4 bytes length, 38016*4 bytes value (on value.direct)) + // = 304150 + pdu->PDU_index = rand16(); + pdu->num_TLV = rand8_range(1, NFAPI_NR_MAX_TX_REQUEST_TLV); + pdu->PDU_length = rand32_range(20, 10 + pdu->num_TLV * (4 + (38016 * 4))); + uint32_t remaining_size = pdu->PDU_length - 10 - (pdu->num_TLV * 4); + for (int tlv_idx = 0; tlv_idx < pdu->num_TLV; ++tlv_idx) { + nfapi_nr_tx_data_request_tlv_t *tlv = &pdu->TLVs[tlv_idx]; + tlv->tag = rand16_range(0, 1); + uint32_t maxSize = 0; + if (tlv->tag == 0) { + maxSize = sizeof(tlv->value.direct); + } else { + maxSize = (remaining_size / pdu->num_TLV); + } + if (pdu->num_TLV == 1) { + tlv->length = remaining_size; + } else { + if (tlv_idx == pdu->num_TLV - 1) { + tlv->length = min(maxSize, sizeof(tlv->value.direct)); + } else { + tlv->length = min(rand32_range(0, maxSize), sizeof(tlv->value.direct)); + remaining_size -= tlv->length - 4; + } + } + switch (tlv->tag) { + case 0: + // value.direct + if (tlv->length % 4 != 0) { + for (int idx = 0; idx < ((tlv->length + 3) / 4) - 1; ++idx) { + tlv->value.direct[idx] = rand32(); + } + uint32_t bytesToAdd = 4 - (4 - (tlv->length % 4)) % 4; + if (bytesToAdd != 4) { + for (int j = 0; j < bytesToAdd; j++) { + tlv->value.direct[((tlv->length + 3) / 4) - 1] |= rand8(); + tlv->value.direct[((tlv->length + 3) / 4) - 1] = tlv->value.direct[((tlv->length + 3) / 4) - 1] << (j * 8); + } + } + } else { + // no padding needed + for (int idx = 0; idx < (tlv->length + 3) / 4; ++idx) { + tlv->value.direct[idx] = rand32(); + } + } + break; + case 1: + // value.ptr + tlv->value.ptr = calloc((tlv->length + 3) / 4, sizeof(uint32_t)); + if (tlv->length % 4 != 0) { + for (int idx = 0; idx < ((tlv->length + 3) / 4) - 1; ++idx) { + tlv->value.ptr[idx] = rand32(); + } + uint32_t bytesToAdd = 4 - (4 - (tlv->length % 4)) % 4; + if (bytesToAdd != 4) { + uint32_t value = 0; + for (int j = 0; j < bytesToAdd; j++) { + value |= rand8() << (j * 8); + } + tlv->value.ptr[((tlv->length + 3) / 4) - 1] = value; + } + } else { + // no padding needed + for (int idx = 0; idx < (tlv->length + 3) / 4; ++idx) { + tlv->value.ptr[idx] = rand32(); + } + } + break; + default: + AssertFatal(1 == 0, "Unsupported tag value %d\n", tlv->tag); + } + } +} + +static void fill_tx_data_request(nfapi_nr_tx_data_request_t *msg) +{ + msg->SFN = rand16_range(0, 1023); + msg->Slot = rand16_range(0, 159); + msg->Number_of_PDUs = rand8_range(1, NFAPI_NR_MAX_TX_REQUEST_PDUS); // Minimum 1 PDUs in order to test at least one + for (int pdu_idx = 0; pdu_idx < msg->Number_of_PDUs; ++pdu_idx) { + fill_tx_data_request_PDU(&msg->pdu_list[pdu_idx]); + } +} + +static void test_pack_unpack(nfapi_nr_tx_data_request_t *req) +{ + size_t message_size = get_tx_data_request_size(req); + uint8_t *msg_buf = calloc_or_fail(message_size, sizeof(uint8_t)); + /*uint8_t msg_buf[1024*1024*3]; + size_t message_size = sizeof(msg_buf);*/ + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, message_size, NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_tx_data_request_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_tx_data_request(&unpacked_req, req)); + free_tx_data_request(&unpacked_req); + free(msg_buf); +} + +static void test_copy(const nfapi_nr_tx_data_request_t *msg) +{ + // Test copy function + nfapi_nr_tx_data_request_t copy = {0}; + copy_tx_data_request(msg, ©); + DevAssert(eq_tx_data_request(msg, ©)); + free_tx_data_request(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_tx_data_request_t *req = calloc_or_fail(1, sizeof(nfapi_nr_tx_data_request_t)); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; + // Get the actual allocated size + printf("Allocated size before filling: %zu bytes\n", get_tx_data_request_size(req)); + // Fill TX_DATA request + fill_tx_data_request(req); + printf("Allocated size after filling: %zu bytes\n", get_tx_data_request_size(req)); + // Perform tests + test_pack_unpack(req); + test_copy(req); + // All tests successful! + free_tx_data_request(req); + free(req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_uci_indication_test.c b/nfapi/tests/p7/nr_fapi_uci_indication_test.c new file mode 100644 index 0000000000000000000000000000000000000000..9e2dcda6beb3d7a16f4a1c2bcb04b0139b4a1122 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_uci_indication_test.c @@ -0,0 +1,243 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_uci_indication_sr_pdu_0_1(nfapi_nr_sr_pdu_0_1_t *pdu) +{ + pdu->sr_indication = rand8_range(0, 1); + pdu->sr_confidence_level = rand8_range(0, 1); +} + +static void fill_uci_indication_sr_pdu_2_3_4(nfapi_nr_sr_pdu_2_3_4_t *pdu) +{ + pdu->sr_bit_len = rand16_range(1, 8); + pdu->sr_payload = calloc(((pdu->sr_bit_len / 8) + 1), sizeof(*pdu->sr_payload)); + for (int i = 0; i < (pdu->sr_bit_len / 8) + 1; ++i) { + pdu->sr_payload[i] = rand8(); + } +} + +static void fill_uci_indication_harq_pdu_0_1(nfapi_nr_harq_pdu_0_1_t *pdu) +{ + pdu->num_harq = rand8_range(1, 2); + pdu->harq_confidence_level = rand8_range(0, 1); + for (int i = 0; i < pdu->num_harq; ++i) { + pdu->harq_list[i].harq_value = rand8_range(0, 2); + } +} + +static void fill_uci_indication_harq_pdu_2_3_4(nfapi_nr_harq_pdu_2_3_4_t *pdu) +{ + pdu->harq_crc = rand8_range(0, 2); + pdu->harq_bit_len = rand16_range(1, 1706); + pdu->harq_payload = calloc(((pdu->harq_bit_len / 8) + 1), sizeof(*pdu->harq_payload)); + for (int i = 0; i < (pdu->harq_bit_len / 8) + 1; ++i) { + pdu->harq_payload[i] = rand8(); + } +} + +static void fill_uci_indication_csi_part1(nfapi_nr_csi_part1_pdu_t *pdu) +{ + pdu->csi_part1_crc = rand8_range(0, 2); + pdu->csi_part1_bit_len = rand16_range(1, 1706); + pdu->csi_part1_payload = calloc(((pdu->csi_part1_bit_len / 8) + 1), sizeof(*pdu->csi_part1_payload)); + for (int i = 0; i < (pdu->csi_part1_bit_len / 8) + 1; ++i) { + pdu->csi_part1_payload[i] = rand8(); + } +} + +static void fill_uci_indication_csi_part2(nfapi_nr_csi_part2_pdu_t *pdu) +{ + pdu->csi_part2_crc = rand8_range(0, 2); + pdu->csi_part2_bit_len = rand16_range(1, 1706); + pdu->csi_part2_payload = calloc(((pdu->csi_part2_bit_len / 8) + 1), sizeof(*pdu->csi_part2_payload)); + for (int i = 0; i < (pdu->csi_part2_bit_len / 8) + 1; ++i) { + pdu->csi_part2_payload[i] = rand8(); + } +} + +static void fill_uci_indication_PUSCH(nfapi_nr_uci_pusch_pdu_t *pdu) +{ + pdu->pduBitmap = rand8_range(0, 0b1110) & 0b1110; // Bit 0 is always unused + pdu->handle = rand32(); + pdu->rnti = rand16_range(1, 65535); + pdu->ul_cqi = rand8(); + pdu->timing_advance = rand16_range(0, 63); + pdu->rssi = rand16_range(0, 1280); + + // Bit 0 not used in PUSCH PDU + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + fill_uci_indication_harq_pdu_2_3_4(&pdu->harq); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + fill_uci_indication_csi_part1(&pdu->csi_part1); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + fill_uci_indication_csi_part2(&pdu->csi_part2); + } +} + +static void fill_uci_indication_PUCCH_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu) +{ + pdu->pduBitmap = rand8_range(0, 0b11); + pdu->handle = rand32(); + pdu->rnti = rand16_range(1, 65535); + pdu->pucch_format = rand8_range(0, 1); + pdu->ul_cqi = rand8(); + pdu->timing_advance = rand16_range(0, 63); + pdu->rssi = rand16_range(0, 1280); + + // SR + if (pdu->pduBitmap & 0x01) { + fill_uci_indication_sr_pdu_0_1(&pdu->sr); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + fill_uci_indication_harq_pdu_0_1(&pdu->harq); + } +} + +static void fill_uci_indication_PUCCH_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu) +{ + pdu->pduBitmap = rand8_range(0, 0b1111); + pdu->handle = rand32(); + pdu->rnti = rand16_range(1, 65535); + pdu->pucch_format = rand8_range(0, 2); + pdu->ul_cqi = rand8(); + pdu->timing_advance = rand16_range(0, 63); + pdu->rssi = rand16_range(0, 1280); + // SR + if (pdu->pduBitmap & 0x01) { + fill_uci_indication_sr_pdu_2_3_4(&pdu->sr); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + fill_uci_indication_harq_pdu_2_3_4(&pdu->harq); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + fill_uci_indication_csi_part1(&pdu->csi_part1); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + fill_uci_indication_csi_part2(&pdu->csi_part2); + } +} + +static void fill_uci_indication_UCI(nfapi_nr_uci_t *uci) +{ + uci->pdu_type = rand16_range(NFAPI_NR_UCI_PUSCH_PDU_TYPE, NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE); + uci->pdu_size = rand16(); + switch (uci->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + fill_uci_indication_PUSCH(&uci->pusch_pdu); + break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + fill_uci_indication_PUCCH_0_1(&uci->pucch_pdu_format_0_1); + break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + fill_uci_indication_PUCCH_2_3_4(&uci->pucch_pdu_format_2_3_4); + break; + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci->pdu_type); + break; + } +} + +static void fill_uci_indication(nfapi_nr_uci_indication_t *msg) +{ + msg->sfn = rand16_range(0, 1023); + msg->slot = rand16_range(0, 159); + msg->num_ucis = rand8_range(1, NFAPI_NR_UCI_IND_MAX_PDU); // Minimum 1 PDUs in order to test at least one + msg->uci_list = calloc_or_fail(msg->num_ucis, sizeof(*msg->uci_list)); + for (int crc_idx = 0; crc_idx < msg->num_ucis; ++crc_idx) { + fill_uci_indication_UCI(&msg->uci_list[crc_idx]); + } +} + +static void test_pack_unpack(nfapi_nr_uci_indication_t *req) +{ + size_t message_size = get_uci_indication_size(req); + uint8_t *msg_buf = calloc_or_fail(message_size, sizeof(uint8_t)); + /*uint8_t msg_buf[1024*1024*3]; + size_t message_size = sizeof(msg_buf);*/ + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, message_size, NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_uci_indication_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_uci_indication(&unpacked_req, req)); + free_uci_indication(&unpacked_req); + free(msg_buf); +} + +static void test_copy(const nfapi_nr_uci_indication_t *msg) +{ + // Test copy function + nfapi_nr_uci_indication_t copy = {0}; + copy_uci_indication(msg, ©); + DevAssert(eq_uci_indication(msg, ©)); + free_uci_indication(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_uci_indication_t *req = calloc_or_fail(1, sizeof(nfapi_nr_uci_indication_t)); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; + // Get the actual allocated size + printf("Allocated size before filling: %zu bytes\n", get_uci_indication_size(req)); + // Fill TX_DATA request + fill_uci_indication(req); + printf("Allocated size after filling: %zu bytes\n", get_uci_indication_size(req)); + // Perform tests + test_pack_unpack(req); + test_copy(req); + // All tests successful! + free_uci_indication(req); + free(req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c b/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c new file mode 100644 index 0000000000000000000000000000000000000000..b1bc910da8d25b306cc3953d4ed3f2e214f687e6 --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c @@ -0,0 +1,142 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_beamforming(nfapi_nr_tx_precoding_and_beamforming_t *precodingAndBeamforming) +{ + precodingAndBeamforming->num_prgs = rand16_range(1, NFAPI_MAX_NUM_PRGS); + precodingAndBeamforming->prg_size = rand16_range(1, 275); + precodingAndBeamforming->dig_bf_interfaces = rand8_range(0,NFAPI_MAX_NUM_BG_IF); + for (int prg = 0; prg < precodingAndBeamforming->num_prgs; ++prg) { + precodingAndBeamforming->prgs_list[prg].pm_idx = rand16(); + for (int dbf_if = 0; dbf_if < precodingAndBeamforming->dig_bf_interfaces; ++dbf_if) { + precodingAndBeamforming->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx = rand16(); + } + } +} + +static void fill_ul_dci_request_pdcch_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdu) +{ + pdu->BWPSize = rand16(); + pdu->BWPStart = rand16(); + pdu->SubcarrierSpacing = rand8(); + pdu->CyclicPrefix = rand8(); + pdu->StartSymbolIndex = rand8(); + pdu->DurationSymbols = rand8(); + for (int fdr_idx = 0; fdr_idx < 6; ++fdr_idx) { + pdu->FreqDomainResource[fdr_idx] = rand8(); + } + pdu->CceRegMappingType = rand8(); + pdu->RegBundleSize = rand8(); + pdu->InterleaverSize = rand8(); + pdu->CoreSetType = rand8(); + pdu->ShiftIndex = rand8(); + pdu->precoderGranularity = rand8(); + pdu->numDlDci = rand8_range(1, MAX_DCI_CORESET); + for (int dl_dci = 0; dl_dci < pdu->numDlDci; ++dl_dci) { + pdu->dci_pdu[dl_dci].RNTI = rand16(); + pdu->dci_pdu[dl_dci].ScramblingId = rand16(); + pdu->dci_pdu[dl_dci].ScramblingRNTI = rand16(); + pdu->dci_pdu[dl_dci].CceIndex = rand8(); + pdu->dci_pdu[dl_dci].AggregationLevel = rand8(); + fill_beamforming(&pdu->dci_pdu[dl_dci].precodingAndBeamforming); + pdu->dci_pdu[dl_dci].beta_PDCCH_1_0 = rand8(); + pdu->dci_pdu[dl_dci].powerControlOffsetSS = rand8(); + pdu->dci_pdu[dl_dci].PayloadSizeBits = rand16_range(0, DCI_PAYLOAD_BYTE_LEN * 8); + generate_payload(pdu->dci_pdu[dl_dci].PayloadSizeBits, pdu->dci_pdu[dl_dci].Payload); + } +} + +static void fill_ul_dci_request_pdu(nfapi_nr_ul_dci_request_pdus_t *pdu) +{ + pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + pdu->PDUSize = rand16(); + fill_ul_dci_request_pdcch_pdu(&pdu->pdcch_pdu.pdcch_pdu_rel15); +} + +static void fill_ul_dci_request(nfapi_nr_ul_dci_request_t *msg) +{ + msg->SFN = rand16_range(0, 1023); + msg->Slot = rand16_range(0, 159); + msg->numPdus = rand8_range(1, 10); // Minimum 1 PDUs in order to test at least one + printf(" NUM PDUS %d\n", msg->numPdus); + for (int pdu_idx = 0; pdu_idx < msg->numPdus; ++pdu_idx) { + fill_ul_dci_request_pdu(&msg->ul_dci_pdu_list[pdu_idx]); + } +} + +static void test_pack_unpack(nfapi_nr_ul_dci_request_t *req) +{ + uint8_t msg_buf[1024 * 1024 * 2]; + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, sizeof(msg_buf), NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_ul_dci_request_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_ul_dci_request(&unpacked_req, req)); + free_ul_dci_request(&unpacked_req); +} + +static void test_copy(const nfapi_nr_ul_dci_request_t *msg) +{ + // Test copy function + nfapi_nr_ul_dci_request_t copy = {0}; + copy_ul_dci_request(msg, ©); + DevAssert(eq_ul_dci_request(msg, ©)); + free_ul_dci_request(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_ul_dci_request_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST}; + + // Fill UL_DCI request + fill_ul_dci_request(&req); + // Perform tests + test_pack_unpack(&req); + test_copy(&req); + // All tests successful! + free_ul_dci_request(&req); + return 0; +} diff --git a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c new file mode 100644 index 0000000000000000000000000000000000000000..4f65cbfc9ea39357eb846e9904d6536290da690b --- /dev/null +++ b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c @@ -0,0 +1,461 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include "dci_payload_utils.h" +#include "nr_fapi_p7.h" +#include "nr_fapi_p7_utils.h" + +static void fill_ul_tti_request_beamforming(nfapi_nr_ul_beamforming_t *beamforming_pdu) +{ + beamforming_pdu->trp_scheme = rand8(); + beamforming_pdu->num_prgs = rand16_range(1, NFAPI_MAX_NUM_PRGS); + beamforming_pdu->prg_size = rand16_range(1, 275); + beamforming_pdu->dig_bf_interface = rand8_range(1,NFAPI_MAX_NUM_BG_IF); + + for (int prg = 0; prg < beamforming_pdu->num_prgs; ++prg) { + for (int dbf_if = 0; dbf_if < beamforming_pdu->dig_bf_interface; ++dbf_if) { + beamforming_pdu->prgs_list[prg].dig_bf_interface_list[dbf_if].beam_idx = rand16(); + } + } +} + +static void fill_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *pdu) +{ + pdu->phys_cell_id = rand16_range(0, 1007); + pdu->num_prach_ocas = rand8_range(1, 7); + pdu->prach_format = rand8_range(0, 13); + pdu->num_ra = rand8_range(0, 7); + pdu->prach_start_symbol = rand8_range(0, 13); + pdu->num_cs = rand16_range(0, 419); + fill_ul_tti_request_beamforming(&pdu->beamforming); +} + +static void fill_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pdu) +{ + pdu->pdu_bit_map = rand16_range(0b0000, 0b1111); + pdu->rnti = rand16_range(1, 65535); + pdu->handle = rand32(); + pdu->bwp_size = rand16_range(1, 275); + pdu->bwp_start = rand16_range(0, 274); + pdu->subcarrier_spacing = rand8_range(0, 4); + pdu->cyclic_prefix = rand8_range(0, 1); + pdu->target_code_rate = rand16_range(300, 9480); + uint8_t transform_precoding = rand8_range(0, 1); + uint8_t qam_mod_order_values[] = {1, 2, 4, 6, 8}; + // Value: 2,4,6,8 if transform precoding is disabled + // Value: 1,2,4,6,8 if transform precoding is enabled + pdu->qam_mod_order = qam_mod_order_values[rand8_range(1 - pdu->transform_precoding, 4)]; + pdu->mcs_index = rand8_range(0, 31); + pdu->mcs_table = rand8_range(0, 4); + pdu->transform_precoding = transform_precoding; + pdu->data_scrambling_id = rand16(); + pdu->nrOfLayers = rand8_range(1, 4); + // Bitmap occupying the 14 LSBs + pdu->ul_dmrs_symb_pos = rand16_range(0b00000000000000, 0b11111111111111); + pdu->dmrs_config_type = rand8_range(0, 1); + pdu->ul_dmrs_scrambling_id = rand16(); + pdu->pusch_identity = rand16_range(0, 1007); + pdu->scid = rand8_range(0, 1); + pdu->num_dmrs_cdm_grps_no_data = rand8_range(1, 3); + // Bitmap occupying the 11 LSBs + pdu->dmrs_ports = rand16_range(0b00000000000, 0b11111111111); + pdu->resource_alloc = rand8_range(0, 1); + for (int i = 0; i < 36; ++i) { + pdu->rb_bitmap[i] = rand8(); + } + pdu->rb_start = rand16_range(0, 274); + pdu->rb_size = rand16_range(1, 275); + pdu->vrb_to_prb_mapping = 0; + pdu->frequency_hopping = rand8_range(0, 1); + pdu->tx_direct_current_location = rand16_range(0, 4095); + pdu->uplink_frequency_shift_7p5khz = rand8_range(0, 1); + pdu->start_symbol_index = rand8_range(0, 13); + pdu->nr_of_symbols = rand8_range(1, 14); + + // Check if PUSCH_PDU_BITMAP_PUSCH_DATA bit is set + if (pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_DATA) { + nfapi_nr_pusch_data_t *pusch_data = &pdu->pusch_data; + pusch_data->rv_index = rand8_range(0, 3); + pusch_data->harq_process_id = rand8_range(0, 15); + pusch_data->new_data_indicator = rand8_range(0, 1); + // TBSize is 32 bits in width, but the value is from 0 to 65535 ( max for 16 bits ) + pusch_data->tb_size = rand16(); + // num_cb set always to 0, due to OAI not supporting CBG + pusch_data->num_cb = 0; + for (int i = 0; i < (pusch_data->num_cb + 7) / 8; ++i) { + pusch_data->cb_present_and_position[i] = 0; + } + } + + // Check if PUSCH_PDU_BITMAP_PUSCH_UCI bit is set + if (pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_UCI) { + nfapi_nr_pusch_uci_t *pusch_uci = &pdu->pusch_uci; + // For testing purposes "decide" here if it uses small block length or polar + pusch_uci->harq_ack_bit_length = rand16_range(0, 1706); + if (pusch_uci->harq_ack_bit_length <= 11) { + pusch_uci->csi_part1_bit_length = rand16_range(0, 11); + pusch_uci->csi_part2_bit_length = rand16_range(0, 11); + } else { + pusch_uci->csi_part1_bit_length = rand16_range(12, 1706); + pusch_uci->csi_part2_bit_length = rand16_range(12, 1706); + } + pusch_uci->alpha_scaling = rand8_range(0, 3); + pusch_uci->beta_offset_harq_ack = rand8_range(0, 15); + pusch_uci->beta_offset_csi1 = rand8_range(0, 18); + pusch_uci->beta_offset_csi2 = rand8_range(0, 18); + } + + // Check if PUSCH_PDU_BITMAP_PUSCH_PTRS bit is set + if (pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + nfapi_nr_pusch_ptrs_t *pusch_ptrs = &pdu->pusch_ptrs; + pusch_ptrs->num_ptrs_ports = rand8_range(1, 2); + pusch_ptrs->ptrs_ports_list = calloc(pusch_ptrs->num_ptrs_ports, sizeof(nfapi_nr_ptrs_ports_t)); + for (int ptrs_port = 0; ptrs_port < pusch_ptrs->num_ptrs_ports; ++ptrs_port) { + // Bitmap occupying the 12 LSBs + pusch_ptrs->ptrs_ports_list[ptrs_port].ptrs_port_index = rand16_range(0b000000000000, 0b111111111111); + pusch_ptrs->ptrs_ports_list[ptrs_port].ptrs_dmrs_port = rand8_range(0, 11); + pusch_ptrs->ptrs_ports_list[ptrs_port].ptrs_re_offset = rand8_range(0, 11); + } + pusch_ptrs->ptrs_time_density = rand8_range(0, 2); + pusch_ptrs->ptrs_freq_density = rand8_range(0, 1); + pusch_ptrs->ul_ptrs_power = rand8_range(0, 3); + } + + // Check if PUSCH_PDU_BITMAP_DFTS_OFDM bit is set + if (pdu->pdu_bit_map & PUSCH_PDU_BITMAP_DFTS_OFDM) { + nfapi_nr_dfts_ofdm_t *dfts_ofdm = &pdu->dfts_ofdm; + dfts_ofdm->low_papr_group_number = rand8_range(0, 29); + dfts_ofdm->low_papr_sequence_number = rand16(); + dfts_ofdm->ul_ptrs_sample_density = rand8_range(1, 8); + dfts_ofdm->ul_ptrs_time_density_transform_precoding = rand8_range(1, 4); + } + + fill_ul_tti_request_beamforming(&pdu->beamforming); + pdu->maintenance_parms_v3.ldpcBaseGraph = rand8(); + pdu->maintenance_parms_v3.tbSizeLbrmBytes = rand32(); +} + +static void fill_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pdu) +{ + pdu->rnti = rand16_range(1, 65535); + pdu->handle = rand32(); + pdu->bwp_size = rand16_range(1, 275); + pdu->bwp_start = rand16_range(0, 274); + pdu->subcarrier_spacing = rand8_range(0, 4); + pdu->cyclic_prefix = rand8_range(0, 1); + pdu->format_type = rand8_range(0, 4); + pdu->multi_slot_tx_indicator = rand8_range(0, 3); + pdu->pi_2bpsk = rand8_range(0, 1); + pdu->prb_start = rand16_range(0, 274); + pdu->prb_size = rand16_range(1, 16); + pdu->start_symbol_index = rand8_range(0, 13); + if (pdu->format_type == 0 || pdu->format_type == 2) { + pdu->nr_of_symbols = rand8_range(1, 2); + } else { + pdu->nr_of_symbols = rand8_range(4, 14); + } + pdu->freq_hop_flag = rand8_range(0, 1); + pdu->second_hop_prb = rand16_range(0, 274); + // Following 4 parameters are Valid for formats 0, 1, 3 and 4, assuming that otherwise, set to 0 + if (pdu->format_type == 0 || pdu->format_type == 1 || pdu->format_type == 3 || pdu->format_type == 4) { + pdu->group_hop_flag = rand8_range(0, 1); + pdu->sequence_hop_flag = rand8_range(0, 1); + pdu->hopping_id = rand16_range(0, 1023); + pdu->initial_cyclic_shift = rand16_range(0, 11); + } else { + pdu->group_hop_flag = 0; + pdu->sequence_hop_flag = 0; + pdu->hopping_id = 0; + pdu->initial_cyclic_shift = 0; + } + // Valid for format 2, 3 and 4. + if (pdu->format_type == 2 || pdu->format_type == 3 || pdu->format_type == 4) { + pdu->data_scrambling_id = rand16_range(0, 1023); + } else { + pdu->data_scrambling_id = 0; + } + + // Valid for format 1. + if (pdu->format_type == 1) { + pdu->time_domain_occ_idx = rand8_range(0, 6); + } else { + pdu->time_domain_occ_idx = 0; + } + + // the following 2 parameters are Valid for format 4. + if (pdu->format_type == 4) { + pdu->pre_dft_occ_idx = rand8_range(0, 3); + // Value: 2 or 4 + pdu->pre_dft_occ_len = 2 + (2 * rand8_range(0, 1)); + } else { + pdu->pre_dft_occ_idx = 0; + pdu->pre_dft_occ_len = 0; + } + + // Valid for formats 3 and 4. + if (pdu->format_type == 3 || pdu->format_type == 4) { + pdu->add_dmrs_flag = rand8_range(0, 1); + } else { + pdu->add_dmrs_flag = 0; + } + + // Valid for format 2. + if (pdu->format_type == 2) { + pdu->dmrs_scrambling_id = rand16(); + } else { + pdu->dmrs_scrambling_id = 0; + } + + // Valid for format 4. + if (pdu->format_type == 4) { + pdu->dmrs_cyclic_shift = rand8_range(0, 9); + } else { + pdu->dmrs_cyclic_shift = 0; + } + + // Valid for format 0 and 1 + if (pdu->format_type == 0 || pdu->format_type == 1) { + pdu->sr_flag = rand8_range(0, 1); + } else { + pdu->sr_flag = 0; + } + // Value: + // 0 = no HARQ bits + // 1->2 = Valid for Formats 0 and 1 + // 2 -> 1706 = Valid for Formats 2, 3 and 4 + if (pdu->format_type == 0 || pdu->format_type == 1) { + //{0,1,2} + pdu->bit_len_harq = rand16_range(0, 2); + } else { + // {0}∪{2,…,1706} + uint16_t bit_len_harq = rand16_range(0, 1705); + if (bit_len_harq == 0) { + pdu->bit_len_harq = 0; + } else { + // Shift range {1,…,1705} -> {2,…,1706} + pdu->bit_len_harq = bit_len_harq + 1; + } + } + + // Following 2 parameters are Valid for format 2, 3 and 4. + if (pdu->format_type == 2 || pdu->format_type == 3 || pdu->format_type == 4) { + pdu->bit_len_csi_part1 = rand16_range(0, 1706); + pdu->bit_len_csi_part2 = rand16_range(0, 1706); + } else { + pdu->bit_len_csi_part1 = 0; + pdu->bit_len_csi_part2 = 0; + } + + fill_ul_tti_request_beamforming(&pdu->beamforming); +} + +static void fill_ul_tti_request_srs_parameters(nfapi_v4_srs_parameters_t *params, const uint8_t num_symbols){ + params->srs_bandwidth_size = rand16_range(4, 272); + for (int idx = 0; idx < num_symbols; ++idx) { + nfapi_v4_srs_parameters_symbols_t *symbol = ¶ms->symbol_list[idx]; + symbol->srs_bandwidth_start = rand16_range(0,268); + symbol->sequence_group = rand8_range(0,29); + symbol->sequence_number = rand8_range(0,1); + } + +#ifdef ENABLE_AERIAL + // For Aerial, we always process the 4 reported symbols, not only the ones indicated by num_symbols + for (int symbol_idx = num_symbols; symbol_idx < 4; ++symbol_idx) { + nfapi_v4_srs_parameters_symbols_t *symbol = ¶ms->symbol_list[idx]; + symbol->srs_bandwidth_start = rand16_range(0,268); + symbol->sequence_group = rand8_range(0,29); + symbol->sequence_number = rand8_range(0,1); + } +#endif // ENABLE_AERIAL + + params->usage = rand32_range(0, 0b1111); + const uint8_t nUsage = __builtin_popcount(params->usage); + for (int idx = 0; idx < nUsage; ++idx) { + params->report_type[idx] = rand8_range(0,1); + } + params->singular_Value_representation = rand8_range(0,1); + params->iq_representation = rand8_range(0,1); + params->prg_size = rand16_range(1,272); + params->num_total_ue_antennas = rand8_range(1, 16); + params->ue_antennas_in_this_srs_resource_set = rand32(); + params->sampled_ue_antennas = rand32(); + params->report_scope = rand8_range(0,1); + params->num_ul_spatial_streams_ports = rand8_range(0, 255); + for (int idx = 0; idx < params->num_ul_spatial_streams_ports; ++idx) { + params->Ul_spatial_stream_ports[idx] = rand8(); + } +} + +static void fill_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t *pdu) +{ + pdu->rnti = rand16_range(1, 65535); + pdu->handle = rand32(); + pdu->bwp_size = rand16_range(1, 275); + pdu->bwp_start = rand16_range(0, 274); + pdu->subcarrier_spacing = rand8_range(0, 4); + pdu->cyclic_prefix = rand8_range(0, 1); + pdu->num_ant_ports = rand8_range(0, 2); + pdu->num_symbols = rand8_range(0, 2); + pdu->num_repetitions = rand8_range(0, 2); + pdu->time_start_position = rand8_range(0, 13); + pdu->config_index = rand8_range(0, 63); + pdu->sequence_id = rand16_range(0, 1023); + pdu->bandwidth_index = rand8_range(0, 3); + pdu->comb_size = rand8_range(0, 1); + // Following 2 parameters value range differs according to comb_size + if (pdu->comb_size == 0) { + pdu->comb_offset = rand8_range(0, 1); + pdu->cyclic_shift = rand8_range(0, 7); + } else { + pdu->comb_offset = rand8_range(0, 3); + pdu->cyclic_shift = rand8_range(0, 11); + } + pdu->frequency_position = rand8_range(0, 67); + pdu->frequency_shift = rand16_range(0, 268); + pdu->frequency_hopping = rand8_range(0, 3); + pdu->group_or_sequence_hopping = rand8_range(0, 2); + pdu->resource_type = rand8_range(0, 2); + // Value: 1,2,3,4,5,8,10,16,20,32,40,64,80,160,320,640,1280,2560 + const uint16_t t_srs_values[] = {1, 2, 3, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}; + pdu->t_srs = t_srs_values[rand16_range(0, 17)]; + pdu->t_offset = rand16_range(0, 2559); + fill_ul_tti_request_beamforming(&pdu->beamforming); + fill_ul_tti_request_srs_parameters(&pdu->srs_parameters_v4, 1 << pdu->num_symbols); +} + +static void fill_ul_tti_request(nfapi_nr_ul_tti_request_t *msg) +{ + msg->SFN = rand16_range(0, 1023); + msg->Slot = rand16_range(0, 159); + msg->n_pdus = rand8_range(4, 16); // Minimum 4 PDUs in order to test at least one of each + + printf(" NUM PDUS %d\n", msg->n_pdus); + msg->rach_present = 1; // rand8_range(0, 1); Always set to 1, since there can only be 1 PRACH PDU + printf(" NUM RACH PDUS %d\n", msg->rach_present); + uint8_t available_PDUs = msg->n_pdus - msg->rach_present; + msg->n_ulsch = rand8_range(1, available_PDUs - 2); + printf(" NUM PUSCH PDUS %d\n", msg->n_ulsch); + available_PDUs -= msg->n_ulsch; + msg->n_ulcch = rand8_range(1, available_PDUs - 1); + printf(" NUM PUCCH PDUS %d\n", msg->n_ulcch); + // The variable available_PDUs now contains the number of SRS PDUs needed to add to reach n_pdus + available_PDUs -= msg->n_ulcch; + printf(" NUM SRS PDUS %d\n", available_PDUs); + msg->n_group = rand8_range(0, NFAPI_MAX_NUM_GROUPS); + printf(" NUM Groups %d\n", msg->n_group); + + // Add PRACH PDU, if applicable + + if (msg->rach_present == 1) { + nfapi_nr_ul_tti_request_number_of_pdus_t *prach_pdu = &msg->pdus_list[0]; + prach_pdu->pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE; + prach_pdu->pdu_size = rand16(); + fill_ul_tti_request_prach_pdu(&prach_pdu->prach_pdu); + } + + // start either at 0 or 1, same value as rach_present + int pdu_idx = msg->rach_present; + // Assign all PUSCH PDUs + for (int i = 0; i < msg->n_ulsch; ++i, ++pdu_idx) { + nfapi_nr_ul_tti_request_number_of_pdus_t *pdu = &msg->pdus_list[pdu_idx]; + pdu->pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + pdu->pdu_size = rand16(); + fill_ul_tti_request_pusch_pdu(&pdu->pusch_pdu); + } + // Assign all PUCCH PDUs + for (int i = 0; i < msg->n_ulcch; ++i, ++pdu_idx) { + nfapi_nr_ul_tti_request_number_of_pdus_t *pdu = &msg->pdus_list[pdu_idx]; + pdu->pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; + pdu->pdu_size = rand16(); + fill_ul_tti_request_pucch_pdu(&pdu->pucch_pdu); + } + + // Assing all SRS PDUs + for (int i = 0; i < available_PDUs; ++i, ++pdu_idx) { + nfapi_nr_ul_tti_request_number_of_pdus_t *pdu = &msg->pdus_list[pdu_idx]; + pdu->pdu_type = NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE; + pdu->pdu_size = rand16(); + fill_ul_tti_request_srs_pdu(&pdu->srs_pdu); + } + + for (int group_idx = 0; group_idx < msg->n_group; ++group_idx) { + nfapi_nr_ul_tti_request_number_of_groups_t *group = &msg->groups_list[group_idx]; + group->n_ue = rand8_range(1, 6); + for (int ue = 0; ue < group->n_ue; ++ue) { + group->ue_list[ue].pdu_idx = rand8(); + } + } +} + +static void test_pack_unpack(nfapi_nr_ul_tti_request_t *req) +{ + uint8_t msg_buf[1024 * 1024 * 2]; + // first test the packing procedure + int pack_result = fapi_nr_p7_message_pack(req, msg_buf, sizeof(msg_buf), NULL); + + DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH); + // update req message_length value with value calculated in message_pack procedure + req->header.message_length = pack_result; //- NFAPI_HEADER_LENGTH; + // test the unpacking of the header + // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK + fapi_message_header_t header; + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + for (int idx = 0; idx < header_buffer_size; idx++) { + header_buffer[idx] = msg_buf[idx]; + } + uint8_t *pReadPackedMessage = header_buffer; + int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + DevAssert(unpack_header_result >= 0); + DevAssert(header.message_id == req->header.message_id); + DevAssert(header.message_length == req->header.message_length); + // test the unpacking and compare with initial message + nfapi_nr_ul_tti_request_t unpacked_req = {0}; + int unpack_result = + fapi_nr_p7_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0); + DevAssert(unpack_result >= 0); + DevAssert(eq_ul_tti_request(&unpacked_req, req)); + free_ul_tti_request(&unpacked_req); +} + +static void test_copy(const nfapi_nr_ul_tti_request_t *msg) +{ + // Test copy function + nfapi_nr_ul_tti_request_t copy = {0}; + copy_ul_tti_request(msg, ©); + DevAssert(eq_ul_tti_request(msg, ©)); + free_ul_tti_request(©); +} + +int main(int n, char *v[]) +{ + fapi_test_init(); + + nfapi_nr_ul_tti_request_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST}; + + // Fill DL_TTI request + fill_ul_tti_request(&req); + // Perform tests + test_pack_unpack(&req); + test_copy(&req); + // All tests successful! + free_ul_tti_request(&req); + return 0; +} diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c index 77a120970994958f41e887dfa6c072ae5c72fe9d..fd222f40b4c402807d4f2462225055b9c7f194ee 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c @@ -595,23 +595,22 @@ static int retrieve_ldpc_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n, static int retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n, uint8_t *p_out, nrLDPC_params_per_cb_t *perCB) { - struct rte_bbdev_op_data *output; - struct rte_mbuf *m; - unsigned int i; - char *data; - uint8_t *out; int offset = 0; - for (i = 0; i < n; ++i) { - output = &ops[i]->ldpc_enc.output; - m = output->data; + for (int i = 0; i < n; ++i) { + struct rte_bbdev_op_data *output = &ops[i]->ldpc_enc.output; + struct rte_mbuf *m = output->data; uint16_t data_len = rte_pktmbuf_data_len(m) - output->offset; - out = &p_out[offset]; - data = m->buf_addr; - for (int byte = 0; byte < data_len; byte++) - for (int bit = 0; bit < 8; bit++) - out[byte * 8 + bit] = (data[m->data_off + byte] >> (7 - bit)) & 1; + uint8_t *out = &p_out[offset]; + const char *data = m->buf_addr + m->data_off; + const char *end = data + data_len; + while (data < end) { + uint8_t byte = *data++; // get the current byte + for (int bit = 7; bit >= 0; --bit) { + *out++ = (byte >> bit) & 1; // extract each bit + } + } offset += perCB[i].E_cb; - rte_pktmbuf_free(ops[i]->ldpc_enc.output.data); + rte_pktmbuf_free(m); rte_pktmbuf_free(ops[i]->ldpc_enc.input.data); } return 0; diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h index d713340a19a3b6441a1d8700fd27217984f666cd..43bf68f48d38a47bdf8bd174d07c9517631700b8 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h @@ -99,7 +99,8 @@ /** Maximum number of possible input LLR = NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX */ #define NR_LDPC_MAX_NUM_LLR 27000 -#define NR_LDPC_MAX_NUM_CB 72 +/** Maximum number of segments per TB = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS */ +#define NR_LDPC_MAX_NUM_CB 144 // ============================================================================== // GLOBAL CONSTANT VARIABLES diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c index 3d26a190639f4ddac14cc70895f6b00fbb3558dd..81d4462d2a93f762dee07db415ee02b1d21cc4cb 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c @@ -386,7 +386,7 @@ static inline int encode_parity_check_part_orig(unsigned char *c,unsigned char * rate=5; } else { - printf("problem with BG\n"); + printf("problem with BG: is %d\n", BG); return(-1); } diff --git a/openair1/PHY/INIT/phy_init.h b/openair1/PHY/INIT/phy_init.h index daf6eafa42e8098eb994f01b090724116d1cf996..6b278f899f88f27b3525f2122c258ca3e8c8c62a 100644 --- a/openair1/PHY/INIT/phy_init.h +++ b/openair1/PHY/INIT/phy_init.h @@ -25,7 +25,6 @@ #include "PHY/defs_eNB.h" #include "PHY/defs_UE.h" #include "PHY/defs_gNB.h" -#include "PHY/defs_nr_UE.h" #include "LTE_SystemInformationBlockType2.h" //#include "RadioResourceConfigCommonSIB.h" diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index acdd291343d5eb5d4b70415d06df63fbb59e5e23..e8570a3bbcd3b0c7e74c399b264ca61f00f666d6 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -480,7 +480,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #endif - int nbAarx = 0; int nest_count = 0; uint64_t noise_amp2 = 0; delay_t *delay = &gNB->ulsch[ul_id].delay; @@ -503,9 +502,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, initNotifiedFIFO(&respPuschAarx); start_meas(&gNB->pusch_channel_estimation_antenna_processing_stats); int numAntennas = gNB->dmrs_num_antennas_per_thread; - for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx += numAntennas) { + int num_jobs = CEILIDIV(gNB->frame_parms.nb_antennas_rx, numAntennas); + for (int job_id = 0; job_id < num_jobs; job_id++) { union puschAntennaReqUnion id = {.s = {ul_id, 0}}; - id.p = 1 + aarx; + id.p = 1 + job_id * numAntennas; notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschAntennaProc_t), id.p, &respPuschAarx, @@ -517,7 +517,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, rdata->nl = nl; rdata->p = p; rdata->symbol = symbol; - rdata->aarx = aarx; + rdata->aarx = job_id * numAntennas; rdata->numAntennas = numAntennas; rdata->bwp_start_subcarrier = bwp_start_subcarrier; rdata->pusch_pdu = pusch_pdu; @@ -532,15 +532,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, rdata->chest_freq = gNB->chest_freq; rdata->rxdataF = gNB->common_vars.rxdataF; // Call the nr_pusch_antenna_processing function - pushTpool(&gNB->threadPool, req); - nbAarx++; - - LOG_D(PHY, "Added Antenna (count %d) to process, in pipe\n", nbAarx); + if (job_id == num_jobs - 1) { + // Run the last job inline + nr_pusch_antenna_processing(rdata); + delNotifiedFIFO_elt(req); + } else { + pushTpool(&gNB->threadPool, req); + } + LOG_D(PHY, "Added Antenna (count %d/%d) to process, in pipe\n", job_id, num_jobs); } // Antenna Loop - while (nbAarx > 0) { + while (num_jobs - 1 > 0) { notifiedFIFO_elt_t *req = pullTpool(&respPuschAarx, &gNB->threadPool); - nbAarx--; + num_jobs--; delNotifiedFIFO_elt(req); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 32ce0acba2527a7ac08bcc07d8f8a7d9a5fd5815..44bb20115db5fadc59423f6f129eb2d6c50526e0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -232,7 +232,7 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB, { NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; - int16_t z_ol[NR_LDPC_MAX_NUM_CB * LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); + int16_t z_ol[LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); int8_t l_ol[NR_LDPC_MAX_NUM_CB * LDPC_MAX_CB_SIZE] __attribute__((aligned(16))); const int kc = decParams->BG == 2 ? 52 : 68; uint32_t A = (harq_process->TBS) << 3; @@ -247,8 +247,8 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB, for (int r = 0; r < harq_process->C; r++) { decParams->perCB[r].E_cb = nr_get_E(G, harq_process->C, decParams->Qm, pusch_pdu->nrOfLayers, r); - memcpy(&z_ol[offset], ulsch_llr + r_offset, decParams->perCB[r].E_cb * sizeof(*z_ol)); - simde__m128i *pv_ol128 = (simde__m128i *)&z_ol[offset]; + memcpy(z_ol, ulsch_llr + r_offset, decParams->perCB[r].E_cb * sizeof(int16_t)); + simde__m128i *pv_ol128 = (simde__m128i *)z_ol; simde__m128i *pl_ol128 = (simde__m128i *)&l_ol[offset]; for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 53c302e789d8ba4901a2be8c9bbaf396eacaa02f..23560568cfd515053efa7855773c6954c1cad3b5 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -33,6 +33,7 @@ #include "T.h" #include <openair1/PHY/TOOLS/phy_scope_interface.h> #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h" +#include "instrumentation.h" extern openair0_config_t openair0_cfg[]; @@ -658,6 +659,7 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, bool sidelink, uint Nid) { + TracyCZone(ctx, true); int Ns = proc->nr_slot_rx; c16_t pilot[200] __attribute__((aligned(16))); //int slot_pbch; @@ -830,6 +832,7 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, } } + TracyCZoneEnd(ctx); return(0); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 82819551e4b56ad627627df0b571f2b7badb906b..5dbab85f124a9ed6e952d360f00a7626d9d655e0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -38,6 +38,7 @@ #include <openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h> #include <openair1/PHY/TOOLS/phy_scope_interface.h> #include "openair1/PHY/NR_REFSIG/nr_refsig_common.h" +#include "instrumentation.h" //#define DEBUG_PBCH //#define DEBUG_PBCH_ENCODING @@ -365,6 +366,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, int rxdataFSize, const struct complex16 rxdataF[][rxdataFSize]) { + TracyCZone(ctx, true); int max_h=0; int symbol; uint8_t Lmax=frame_parms->Lmax; @@ -539,5 +541,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, ue->if_inst->dl_indication(&dl_indication); } + TracyCZoneEnd(ctx); return 0; } diff --git a/openair1/PHY/TOOLS/CMakeLists.txt b/openair1/PHY/TOOLS/CMakeLists.txt index ada3d8c86336f2cce55ac6a576029c154b3be904..574899f3e70c43e6e901aaa637c49c74324bb2bb 100644 --- a/openair1/PHY/TOOLS/CMakeLists.txt +++ b/openair1/PHY/TOOLS/CMakeLists.txt @@ -53,7 +53,7 @@ if(ENABLE_UESCOPE OR ENABLE_ENBSCOPE OR ENABLE_NRSCOPE) target_link_libraries(uescope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_library(nrscope MODULE nr_phy_scope.c) - target_link_libraries(nrscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) + target_link_libraries(nrscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) # all libraries should be written to root build dir (default creates the same hierarchie under build as existing for sources) set_target_properties(enbscope uescope nrscope diff --git a/openair1/PHY/TOOLS/imscope/CMakeLists.txt b/openair1/PHY/TOOLS/imscope/CMakeLists.txt index 60b2dc69cebe4817e10a895df89ae70bb9090906..26eb85510088c889be6d319f7f764e7f49da25c0 100644 --- a/openair1/PHY/TOOLS/imscope/CMakeLists.txt +++ b/openair1/PHY/TOOLS/imscope/CMakeLists.txt @@ -1,5 +1,5 @@ -CPMAddPackage("gh:ocornut/imgui#v1.90.9") +CPMAddPackage("gh:ocornut/imgui#v1.91.3-docking") add_library(imgui ${imgui_SOURCE_DIR}/imgui_draw.cpp ${imgui_SOURCE_DIR}/imgui.cpp @@ -32,3 +32,4 @@ target_include_directories(implot PUBLIC ${implot_SOURCE_DIR}) add_library(imscope MODULE imscope.cpp ../phy_scope_interface.c) target_link_libraries(imscope PUBLIC imgui_glfw_backend glfw imgui_opengl_renderer OpenGL::OpenGL implot UTIL) set_target_properties(imscope PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +configure_file(imgui.ini ${CMAKE_BINARY_DIR}/imscope-init.ini COPYONLY) diff --git a/openair1/PHY/TOOLS/imscope/imgui.ini b/openair1/PHY/TOOLS/imscope/imgui.ini new file mode 100644 index 0000000000000000000000000000000000000000..3fc08b6f7c1dc838290c7abc5853c40ce6725fb0 --- /dev/null +++ b/openair1/PHY/TOOLS/imscope/imgui.ini @@ -0,0 +1,99 @@ +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][NR KPI] +Pos=0,19 +Size=1133,667 +Collapsed=0 +DockId=0x00000005,0 + +[Window][Dear ImGui Demo] +Pos=531,19 +Size=529,667 +Collapsed=0 +DockId=0x00000002,0 + +[Window][ImPlot Demo] +Pos=531,19 +Size=529,667 +Collapsed=0 +DockId=0x00000002,0 + +[Window][WindowOverViewport_11111111] +Pos=0,19 +Size=1280,701 +Collapsed=0 + +[Window][Status bar] +Pos=0,688 +Size=1280,32 +Collapsed=0 +DockId=0x00000004,0 + +[Window][Global scope settings] +Pos=1038,19 +Size=242,667 +Collapsed=0 +DockId=0x00000006,0 + +[Window][UE KPI] +Pos=532,19 +Size=528,667 +Collapsed=0 +DockId=0x00000008,0 + +[Window][UE PDSCH IQ] +Pos=0,19 +Size=530,667 +Collapsed=0 +DockId=0x00000005,1 + +[Window][Time domain samples] +Pos=0,19 +Size=1036,667 +Collapsed=0 +DockId=0x00000005,0 + +[Window][Time domain samples - before sync] +Pos=0,19 +Size=530,667 +Collapsed=0 +DockId=0x00000005,2 + +[Window][Broadcast channel] +Pos=0,19 +Size=530,667 +Collapsed=0 +DockId=0x00000005,3 + +[Window][RX IQ] +Pos=532,19 +Size=528,667 +Collapsed=0 +DockId=0x00000008,0 + +[Window][PUSCH SLOT IQ] +Pos=0,19 +Size=1036,667 +Collapsed=0 +DockId=0x00000005,1 + +[Window][PUSCH LLRs] +Pos=0,19 +Size=1036,667 +Collapsed=0 +DockId=0x00000005,2 + +[Docking][Data] +DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=1280,701 Split=Y Selected=0x71C89FCB + DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=1280,667 Split=X + DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1319,720 Split=X Selected=0x6627CA6C + DockNode ID=0x00000007 Parent=0x00000001 SizeRef=530,667 Split=X Selected=0x93FDECFF + DockNode ID=0x00000005 Parent=0x00000007 SizeRef=1036,334 CentralNode=1 Selected=0x93FDECFF + DockNode ID=0x00000006 Parent=0x00000007 SizeRef=242,334 Selected=0xFAA8D9D5 + DockNode ID=0x00000008 Parent=0x00000001 SizeRef=528,667 Selected=0x6627CA6C + DockNode ID=0x00000002 Parent=0x00000003 SizeRef=529,720 Selected=0xB903C8C9 + DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=1280,32 HiddenTabBar=1 Selected=0xD9B9B9C7 + diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index 054fcdad79b9651ed979ffbc43f9304ca51ed12f..84ae7d85f4113466bba9afe836587031d83fca52 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -107,7 +107,7 @@ typedef struct IQData { float max_power; float timestamp; int nonzero_count; - int len; + int len = 0; metadata meta; bool TryCollect(ImScopeData *imscope_data, float time, float epsilon) @@ -213,11 +213,13 @@ class IQHist { float epsilon = 0.0; bool auto_adjust_range = true; int plot_type = 0; + bool disable_scatterplot; public: - IQHist(const char *label_) + IQHist(const char *label_, bool _disable_scatterplot = false) { label = label_; + disable_scatterplot = _disable_scatterplot; }; bool ShouldReadData(void) { @@ -264,10 +266,11 @@ class IQHist { ImGui::DragFloat("%% nonzero elements", &min_nonzero_percentage, 1, 0.0, 100); ImGui::DragFloat("epsilon", &epsilon, 1, 0.0, 3000); } - const char *items[] = {"Histogram", "Scatter", "RMS"}; - ImGui::Combo("Select plot type", &plot_type, items, sizeof(items) / sizeof(items[0])); + const char *items[] = {"Histogram", "RMS", "Scatter"}; + ImGui::Combo("Select plot type", &plot_type, items, disable_scatterplot ? 2 : 3); if (plot_type == 0) { - if (ImPlot::BeginPlot(label.c_str(), {(float)ImGui::GetWindowWidth() * 0.3f, (float)ImGui::GetWindowWidth() * 0.3f})) { + float x = ImGui::CalcItemWidth(); + if (ImPlot::BeginPlot(label.c_str(), {x, x})) { ImPlot::PlotHistogram2D(label.c_str(), iq_data->real.data(), iq_data->imag.data(), @@ -277,8 +280,9 @@ class IQHist { ImPlotRect(-range, range, -range, range)); ImPlot::EndPlot(); } - } else if (plot_type == 1) { - if (ImPlot::BeginPlot(label.c_str(), {(float)ImGui::GetWindowWidth() * 0.3f, (float)ImGui::GetWindowWidth() * 0.3f})) { + } else if (plot_type == 2) { + float x = ImGui::CalcItemWidth(); + if (ImPlot::BeginPlot(label.c_str(), {x, x})) { int points_drawn = 0; while (points_drawn < iq_data->len) { // Limit the amount of data plotted with PlotScatter call (issue with vertices/draw call) @@ -292,7 +296,7 @@ class IQHist { } ImPlot::EndPlot(); } - } else if (plot_type == 2) { + } else if (plot_type == 1) { if (ImPlot::BeginPlot(label.c_str())) { ImPlot::PlotLine(label.c_str(), iq_data->power.data(), iq_data->len); ImPlot::EndPlot(); @@ -457,6 +461,7 @@ struct ScrollingBuffer { void ShowUeScope(PHY_VARS_NR_UE *ue, float t) { + ImGui::Begin("UE KPI"); if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1, 150))) { static float history = 10.0f; ImGui::SliderFloat("History", &history, 1, 30, "%.1f s"); @@ -479,7 +484,9 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) ImPlot::PlotLine("mcs", &mcs.Data[0].x, &mcs.Data[0].y, mcs.Data.size(), 0, 0, 2 * sizeof(float)); ImPlot::EndPlot(); } - if (ImGui::TreeNode("PDSCH IQ")) { + ImGui::End(); + + if (ImGui::Begin("UE PDSCH IQ")) { static auto iq_data = new IQData(); static auto pdsch_iq_hist = new IQHist("PDSCH IQ"); bool new_data = false; @@ -487,29 +494,36 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) new_data = iq_data->TryCollect(&scope_array[pdschRxdataF_comp], t, pdsch_iq_hist->GetEpsilon()); } pdsch_iq_hist->Draw(iq_data, t, new_data); - ImGui::TreePop(); } - if (ImGui::TreeNode("Time domain samples")) { + ImGui::End(); + + if (ImGui::Begin("Time domain samples")) { static auto iq_data = new IQData(); - static auto time_domain_iq = new IQHist("Time domain samples"); + // Issue with imgui deferring draw calls until the end of the frame - cases segfault if scatterplot has too many points + bool disable_scatterplot = true; + static auto time_domain_iq = new IQHist("Time domain samples", disable_scatterplot); bool new_data = false; if (time_domain_iq->ShouldReadData()) { new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamples], t, time_domain_iq->GetEpsilon()); } time_domain_iq->Draw(iq_data, t, new_data); - ImGui::TreePop(); } - if (ImGui::TreeNode("Time domain samples - before sync")) { + ImGui::End(); + + if (ImGui::Begin("Time domain samples - before sync")) { static auto iq_data = new IQData(); - static auto time_domain_iq = new IQHist("Time domain samples - before sync"); + // Issue with imgui deferring draw calls until the end of the frame - cases segfault if scatterplot has too many points + bool disable_scatterplot = true; + static auto time_domain_iq = new IQHist("Time domain samples - before sync", disable_scatterplot); bool new_data = false; if (time_domain_iq->ShouldReadData()) { new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamplesBeforeSync], t, time_domain_iq->GetEpsilon()); } time_domain_iq->Draw(iq_data, t, new_data); - ImGui::TreePop(); } - if (ImGui::TreeNode("Broadcast channel")) { + ImGui::End(); + + if (ImGui::Begin("Broadcast channel")) { ImGui::Text("RSRP %d", ue->measurements.ssb_rsrp_dBm[ue->frame_parms.ssb_index]); if (ImGui::TreeNode("IQ")) { static auto iq_data = new IQData(); @@ -541,32 +555,33 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) llr_plot->Draw(t, ue->sl_mode ? psbchLlr : pbchLlr, "Broadcast LLR"); ImGui::TreePop(); } - ImGui::TreePop(); - } - if (ImGui::TreeNode("RX IQ")) { - static auto common_rx_iq_heatmap = new IQSlotHeatmap(&scope_array[commonRxdataF], "common RX IQ"); - common_rx_iq_heatmap->Draw(t, - ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.symbols_per_slot, - ue->frame_parms.first_carrier_offset, - ue->frame_parms.N_RB_DL); - ImGui::TreePop(); } + ImGui::End(); + + // if (ImGui::Begin("RX IQ")) { + // static auto common_rx_iq_heatmap = new IQSlotHeatmap(&scope_array[commonRxdataF], "common RX IQ"); + // common_rx_iq_heatmap->Draw(t, + // ue->frame_parms.ofdm_symbol_size, + // ue->frame_parms.symbols_per_slot, + // ue->frame_parms.first_carrier_offset, + // ue->frame_parms.N_RB_DL); + // } + // ImGui::End(); } void ShowGnbScope(PHY_VARS_gNB *gNB, float t) { - if (ImGui::TreeNode("RX IQ")) { - static auto gnb_heatmap = new IQSlotHeatmap(&scope_array[gNBRxdataF], "common RX IQ"); - - gnb_heatmap->Draw(t, - gNB->frame_parms.ofdm_symbol_size, - gNB->frame_parms.symbols_per_slot, - gNB->frame_parms.first_carrier_offset, - gNB->frame_parms.N_RB_UL); - ImGui::TreePop(); - } - if (ImGui::TreeNode("PUSCH SLOT IQ")) { + // if (ImGui::TreeNode("RX IQ")) { + // static auto gnb_heatmap = new IQSlotHeatmap(&scope_array[gNBRxdataF], "common RX IQ"); + + // gnb_heatmap->Draw(t, + // gNB->frame_parms.ofdm_symbol_size, + // gNB->frame_parms.symbols_per_slot, + // gNB->frame_parms.first_carrier_offset, + // gNB->frame_parms.N_RB_UL); + // ImGui::TreePop(); + // } + if (ImGui::Begin("PUSCH SLOT IQ")) { static auto pusch_iq = new IQData(); static auto pusch_iq_display = new IQHist("PUSCH compensated IQ"); bool new_data = false; @@ -574,23 +589,27 @@ void ShowGnbScope(PHY_VARS_gNB *gNB, float t) new_data = pusch_iq->TryCollect(&scope_array[gNBPuschRxIq], t, pusch_iq_display->GetEpsilon()); } pusch_iq_display->Draw(pusch_iq, t, new_data); - ImGui::TreePop(); } - if (ImGui::TreeNode("PUSCH LLRs")) { + ImGui::End(); + + if (ImGui::Begin("PUSCH LLRs")) { static auto pusch_llr_plot = new LLRPlot(); pusch_llr_plot->Draw(t, gNBPuschLlr, "PUSCH LLR"); - ImGui::TreePop(); } - if (ImGui::TreeNode("Time domain samples")) { + ImGui::End(); + + if (ImGui::Begin("Time domain samples")) { static auto iq_data = new IQData(); - static auto time_domain_iq = new IQHist("Time domain samples"); + // Issue with imgui deferring draw calls until the end of the frame - cases segfault if scatterplot has too many points + bool disable_scatterplot = true; + static auto time_domain_iq = new IQHist("Time domain samples", disable_scatterplot); bool new_data = false; if (time_domain_iq->ShouldReadData()) { new_data = iq_data->TryCollect(&scope_array[gNbTimeDomainSamples], t, time_domain_iq->GetEpsilon()); } time_domain_iq->Draw(iq_data, t, new_data); - ImGui::TreePop(); } + ImGui::End(); } void *imscope_thread(void *data_void_ptr) @@ -636,6 +655,7 @@ void *imscope_thread(void *data_void_ptr) ImGuiIO &io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Setup Dear ImGui style ImGui::StyleColorsDark(); @@ -659,7 +679,8 @@ void *imscope_thread(void *data_void_ptr) static int target_fps = 24; bool is_ue = (get_softmodem_optmask() & SOFTMODEM_5GUE_BIT) > 0; - while (!glfwWindowShouldClose(window)) { + bool close_window = false; + while (!glfwWindowShouldClose(window) && close_window == false) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy @@ -672,33 +693,62 @@ void *imscope_thread(void *data_void_ptr) // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); + + static bool reset_ini_settings = false; + if (reset_ini_settings) + { + ImGui::LoadIniSettingsFromDisk("imscope-init.ini"); + reset_ini_settings = false; + } ImGui::NewFrame(); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); static float t = 0; - - t += ImGui::GetIO().DeltaTime; - ImGui::SetNextWindowPos({0, 0}); - ImGui::SetNextWindowSize({(float)display_w, (float)display_h}); - ImGui::Begin("NR KPI", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove); - if (ImGui::TreeNode("Global settings")) { - ImGui::ShowFontSelector("Font"); - ImGui::ShowStyleSelector("ImGui Style"); - ImPlot::ShowStyleSelector("ImPlot Style"); - ImPlot::ShowColormapSelector("ImPlot Colormap"); - ImGui::SliderInt("FPS target", &target_fps, 12, 60); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Reduces scope flickering in unfrozen mode. Can reduce impact on perfromance of the modem"); + static bool show_imgui_demo_window = false; + static bool show_implot_demo_window = false; + ImGui::DockSpaceOverViewport(); + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Close scope")) { + close_window = true; + } + ImGui::EndMenu(); } - ImGui::TreePop(); + if (ImGui::BeginMenu("Options")) { + ImGui::Checkbox("Show imgui demo window", &show_imgui_demo_window); + ImGui::Checkbox("Show implot demo window", &show_implot_demo_window); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Layout")) { + if (ImGui::MenuItem("Reset")) { + reset_ini_settings = true; + } + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); } - iq_procedure_timer.UpdateAverage(t); + + ImGui::Begin("Status bar"); ImGui::Text("Total time used by IQ capture procedures per milisecond: %.2f [us]/[ms]", iq_procedure_timer.average / 1000); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Total time used in PHY threads for copying out IQ data for the scope, in uS, averaged over 1 ms"); } + ImGui::End(); + + ImGui::Begin("Global scope settings"); + ImGui::ShowStyleSelector("ImGui Style"); + ImPlot::ShowStyleSelector("ImPlot Style"); + ImPlot::ShowColormapSelector("ImPlot Colormap"); + ImGui::SliderInt("FPS target", &target_fps, 12, 60); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Reduces scope flickering in unfrozen mode. Can reduce impact on perfromance of the modem"); + } + ImGui::End(); + + t += ImGui::GetIO().DeltaTime; + iq_procedure_timer.UpdateAverage(t); if (is_ue) { PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)data_void_ptr; @@ -708,11 +758,12 @@ void *imscope_thread(void *data_void_ptr) PHY_VARS_gNB *gNB = scope_params->gNB; ShowGnbScope(gNB, t); } - ImGui::End(); // For reference - ImPlot::ShowDemoWindow(); - ImGui::ShowDemoWindow(); + if (show_implot_demo_window) + ImPlot::ShowDemoWindow(); + if (show_imgui_demo_window) + ImGui::ShowDemoWindow(); // Rendering ImGui::Render(); @@ -880,7 +931,8 @@ void unlockScopeData(enum scopeDataType type) total_size += scope_data.data_copied_per_offset[i]; } if (total_size != (uint64_t)scope_data.scope_graph_data->dataSize) { - LOG_E(PHY, "Scope is missing data - not all data that was expected was copied - possibly missed copyDataUnsafeWithOffset call\n"); + LOG_E(PHY, + "Scope is missing data - not all data that was expected was copied - possibly missed copyDataUnsafeWithOffset call\n"); } scope_data.is_data_ready = true; scope_data.write_mutex.unlock(); diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 7178faefd12f1e9266a1463ca8b92373225fa1e0..182450f0e77348436c729e88f9dc6679f7e87de3 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -50,6 +50,8 @@ #include "common_lib.h" #include "fapi_nr_ue_interface.h" #include "assertions.h" +#include "barrier.h" +#include "actor.h" //#include "openair1/SCHED_NR_UE/defs.h" #ifdef MEX @@ -74,16 +76,6 @@ #define openair_free(y,x) free((y)) #define PAGE_SIZE 4096 -#ifdef NR_UNIT_TEST - #define FILE_NAME " " - #define LINE_FILE (0) - #define NR_TST_PHY_PRINTF(...) printf(__VA_ARGS__) -#else - #define FILE_NAME (__FILE__) - #define LINE_FILE (__LINE__) - #define NR_TST_PHY_PRINTF(...) -#endif - #define PAGE_MASK 0xfffff000 #define virt_to_phys(x) (x) #define openair_sched_exit() exit(-1) @@ -91,6 +83,7 @@ #define bzero(s,n) (memset((s),0,(n))) /// suppress compiler warning for unused arguments #define UNUSED(x) (void)x; +#define NUM_DL_ACTORS 4 #include "impl_defs_top.h" #include "impl_defs_nr.h" @@ -530,7 +523,7 @@ typedef struct PHY_VARS_NR_UE_s { void *phy_sim_pdsch_dl_ch_estimates_ext; uint8_t *phy_sim_dlsch_b; - notifiedFIFO_t tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME]; + dynamic_barrier_t process_slot_tx_barriers[NR_MAX_SLOTS_PER_FRAME]; // Gain change required for automation RX gain change int adjust_rxgain; @@ -538,6 +531,8 @@ typedef struct PHY_VARS_NR_UE_s { // Sidelink parameters sl_nr_sidelink_mode_t sl_mode; sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS; + Actor_t sync_actor; + Actor_t dl_actors[NUM_DL_ACTORS]; } PHY_VARS_NR_UE; typedef struct { diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 250dcc2f953ab0d9392373e75dde4186ccc69c5b..da7cc26e1adc5f5afc37836e8a163044396f0995 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -31,10 +31,19 @@ #include "PHY/defs_nr_common.h" #include "PHY/defs_gNB.h" -#include "PHY/defs_nr_UE.h" #include "SCHED_NR/phy_frame_config_nr.h" #include "common/utils/nr/nr_common.h" +#ifdef NR_UNIT_TEST + #define FILE_NAME " " + #define LINE_FILE (0) + #define NR_TST_PHY_PRINTF(...) printf(__VA_ARGS__) +#else + #define FILE_NAME (__FILE__) + #define LINE_FILE (__LINE__) + #define NR_TST_PHY_PRINTF(...) +#endif + /******************************************************************* * * NAME : set_tdd_configuration diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 73eda60dcd3042a10445be5362066ace46dbc71f..221e4634085f6fe00527fa4370321eb9700bd0d0 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -660,22 +660,21 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 } } -int fill_srs_reported_symbol_list(nfapi_nr_srs_reported_symbol_t *prgs, - const nfapi_nr_srs_pdu_t *srs_pdu, +int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_symbol, + const nfapi_nr_srs_pdu_t *srs_pdu, const int N_RB_UL, const int8_t *snr_per_rb, const int srs_est) { - - prgs->num_prgs = srs_pdu->beamforming.num_prgs; - for(int prg_idx = 0; prg_idx < prgs->num_prgs; prg_idx++) { + reported_symbol->num_prgs = srs_pdu->beamforming.num_prgs; + for (int prg_idx = 0; prg_idx < reported_symbol->num_prgs; prg_idx++) { if (srs_est<0) { - prgs->prg_list[prg_idx].rb_snr = 0xFF; + reported_symbol->prg_list[prg_idx].rb_snr = 0xFF; } else if (snr_per_rb[prg_idx] < -64) { - prgs->prg_list[prg_idx].rb_snr = 0; + reported_symbol->prg_list[prg_idx].rb_snr = 0; } else if (snr_per_rb[prg_idx] > 63) { - prgs->prg_list[prg_idx].rb_snr = 0xFE; + reported_symbol->prg_list[prg_idx].rb_snr = 0xFE; } else { - prgs->prg_list[prg_idx].rb_snr = (snr_per_rb[prg_idx] + 64) << 1; + reported_symbol->prg_list[prg_idx].rb_snr = (snr_per_rb[prg_idx] + 64) << 1; } } @@ -1065,7 +1064,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) nr_srs_bf_report.num_symbols = 1 << srs_pdu->num_symbols; nr_srs_bf_report.wide_band_snr = srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid nr_srs_bf_report.num_reported_symbols = 1 << srs_pdu->num_symbols; - fill_srs_reported_symbol_list(&nr_srs_bf_report.prgs, srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est); + fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est); #ifdef SRS_IND_DEBUG LOG_I(NR_PHY, "nr_srs_bf_report.prg_size = %i\n", nr_srs_bf_report.prg_size); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index a737b5246eacfa1229858f475a96cf57ed275190..aab41da209c0da3301254732fd006928c24e6e1d 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -75,6 +75,7 @@ fifo_dump_emos_UE emos_dump_UE; #include "UTIL/OPT/opt.h" #include "intertask_interface.h" #include "T.h" +#include "instrumentation.h" static const unsigned int gain_table[31] = {100, 112, 126, 141, 158, 178, 200, 224, 251, 282, 316, 359, 398, 447, 501, 562, 631, 708, 794, 891, 1000, 1122, @@ -378,6 +379,7 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, struct complex16 dl_ch_estimates[][estimateSz], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { + TracyCZone(ctx, true); int ret = 0; DevAssert(ue); @@ -422,6 +424,7 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, LOG_E(PHY, "[UE %d] frame %d, nr_slot_rx %d, Error decoding PBCH!\n", ue->Mod_id, frame_rx, nr_slot_rx); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); + TracyCZoneEnd(ctx); return ret; } @@ -632,18 +635,6 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, return 0; } -// This function release the Tx working thread for one pending information, like dlsch ACK/NACK -static void send_dl_done_to_tx_thread(notifiedFIFO_t *nf, int rx_slot) -{ - if (nf) { - notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(int), 0, NULL, NULL); - // We put rx slot only for tracing purpose - int *msgData = (int *) NotifiedFifoData(newElt); - *msgData = rx_slot; - pushNotifiedFIFO(nf, newElt); - } -} - static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config) { uint32_t unav_res = 0; @@ -737,7 +728,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, // don't wait anymore LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid); const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame; - send_dl_done_to_tx_thread(ue->tx_resume_ind_fifo + ack_nack_slot, proc->nr_slot_rx); + dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]); return false; } @@ -873,7 +864,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, // DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH if (dlsch[0].rnti_type == TYPE_C_RNTI_) { const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame; - send_dl_done_to_tx_thread(ue->tx_resume_ind_fifo + ack_nack_slot, proc->nr_slot_rx); + dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]); } if (ue->phy_sim_dlsch_b) @@ -894,6 +885,7 @@ static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index) int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) { + TracyCZone(ctx, true); int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; int gNB_id = proc->gNB_id; @@ -1044,6 +1036,7 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ LOG_D(PHY, "[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); phy_pdcch_config->nb_search_space = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); + TracyCZoneEnd(ctx); return sampleShift; } @@ -1138,6 +1131,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_IN); // it returns -1 in case of internal failure, or 0 in case of normal result int ret_pdsch = nr_ue_pdsch_procedures(ue, proc, dlsch, llr, rxdataF, G); + TracyCPlot("pdsch mcs", dlsch->dlsch_config.mcs); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_OUT); @@ -1152,9 +1146,8 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G); else { LOG_E(NR_PHY, "Demodulation impossible, internal error\n"); - send_dl_done_to_tx_thread( - ue->tx_resume_ind_fifo + (proc->nr_slot_rx + dlsch_config->k1_feedback) % ue->frame_parms.slots_per_frame, - proc->nr_slot_rx); + int ack_nack_slot = (proc->nr_slot_rx + dlsch_config->k1_feedback) % ue->frame_parms.slots_per_frame; + dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]); LOG_W(NR_PHY, "nr_ue_pdsch_procedures failed in slot %d\n", proc->nr_slot_rx); } diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index f2fd64252c0fa1956dabd36569972d48622643fb..3d096c33e0b9804b14405d3ff8880810111f1552 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -27,19 +27,19 @@ #include <netinet/in.h> #include <netinet/sctp.h> #include "common/ngran_types.h" -#include "f1ap_messages_types.h" -#include "ngap_messages_types.h" +#include "common/platform_types.h" +#include "common/5g_platform_types.h" +/* Definitions according to 3GPP TS 38.463 */ #define E1AP_MAX_NUM_TRANSAC_IDS 4 #define E1AP_MAX_NUM_PLMNS 4 #define E1AP_MAX_NUM_SLICES 1024 #define E1AP_MAX_NUM_CELL_GROUPS 4 -#define E1AP_MAX_NUM_QOS_FLOWS 4 -#define E1AP_MAX_NUM_NGRAN_DRB 4 +#define E1AP_MAX_NUM_QOS_FLOWS 64 #define E1AP_MAX_NUM_PDU_SESSIONS 4 -#define E1AP_MAX_NUM_DRBS 4 -#define E1AP_MAX_NUM_DRBS 4 +#define E1AP_MAX_NUM_DRBS 32 #define E1AP_MAX_NUM_UP_PARAM 4 +#define E1AP_SECURITY_KEY_SIZE 16 // keys have 128 bits length #define E1AP_REGISTER_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_register_req #define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req @@ -61,6 +61,17 @@ typedef enum BEARER_CONTEXT_STATUS_e { BEARER_RESUME, } BEARER_CONTEXT_STATUS_t; +typedef enum activity_notification_level_e { + ANL_DRB = 0, + ANL_PDU_SESSION, + ANL_UE, +} activity_notification_level_t; + +typedef enum cell_group_id_e { + MCG = 0, + SCG, +} cell_group_id_t; + typedef struct PLMN_ID_s { int mcc; int mnc; @@ -107,10 +118,6 @@ typedef struct e1ap_setup_fail_s { long transac_id; } e1ap_setup_fail_t; -typedef struct cell_group_s { - long id; -} cell_group_t; - typedef struct up_params_s { in_addr_t tlAddress; long teId; @@ -144,22 +151,27 @@ typedef struct drb_to_setup_s { in_addr_t tlAddress; long teId; int numCellGroups; - cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; + cell_group_id_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; } drb_to_setup_t; typedef struct qos_characteristics_s { union { struct { - long fiveqi; - long qos_priority_level; + uint16_t fiveqi; + uint8_t qos_priority_level; } non_dynamic; struct { - long fiveqi; // -1 -> optional - long qos_priority_level; - long packet_delay_budget; + // Range 5QI [0 - 255] + uint16_t fiveqi; + /* Range [0 - 15] + 15 = "no priority," 1-14 = decreasing priority (1 highest), 0 = logical error if received */ + uint8_t qos_priority_level; + // Range [0, 1023]: Upper bound for packet delay in 0.5ms units + uint16_t packet_delay_budget; struct { - long per_scalar; - long per_exponent; + // PER = Scalar x 10^-k (k: 0-9) + uint8_t per_scalar; + uint8_t per_exponent; } packet_error_rate; } dynamic; }; @@ -168,8 +180,10 @@ typedef struct qos_characteristics_s { typedef struct ngran_allocation_retention_priority_s { uint16_t priority_level; - long preemption_capability; - long preemption_vulnerability; + // Pre-emption capability on other QoS flows + uint8_t preemption_capability; + // Vulnerability of the QoS flow to pre-emption of other QoS flows + uint8_t preemption_vulnerability; } ngran_allocation_retention_priority_t; typedef struct qos_flow_level_qos_parameters_s { @@ -203,13 +217,31 @@ typedef struct DRB_nGRAN_to_setup_s { /* Cell Group Information (clause 9.3.1.11) */ int numCellGroups; - cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; + cell_group_id_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; /* DRB QoS Flows Parameters (clause 9.3.1.26) */ int numQosFlow2Setup; qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; } DRB_nGRAN_to_setup_t, DRB_nGRAN_to_mod_t; +typedef enum e1ap_indication_e { + SECURITY_REQUIRED = 0, + SECURITY_PREFERRED, + SECURITY_NOT_NEEDED +} e1ap_indication_t; + +typedef struct security_indication_s { + e1ap_indication_t integrityProtectionIndication; + e1ap_indication_t confidentialityProtectionIndication; + // Maximum Integrity Protected Data Rate + long maxIPrate; +} security_indication_t; + +typedef struct UP_TL_information_s { + in_addr_t tlAddress; + int32_t teId; +} UP_TL_information_t; + /** * PDU Session Resource To Setup List (clause 9.3.3.10) * PDU Session Resource To Modify List (clause 9.3.3.11) @@ -218,18 +250,12 @@ typedef struct pdu_session_to_setup_s { long sessionId; long sessionType; e1ap_nssai_t nssai; - long integrityProtectionIndication; - long confidentialityProtectionIndication; - in_addr_t tlAddress; - in_addr_t tlAddress_dl; - int32_t teId; - int32_t teId_dl; - int tl_port; - int tl_port_dl; + security_indication_t securityIndication; + UP_TL_information_t UP_TL_information; long numDRB2Setup; - DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; + DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; long numDRB2Modify; - DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; + DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; } pdu_session_to_setup_t, pdu_session_to_mod_t; /** @@ -239,15 +265,15 @@ typedef struct pdu_session_to_setup_s { */ typedef struct e1ap_bearer_setup_req_s { uint32_t gNB_cu_cp_ue_id; - uint32_t gNB_cu_up_ue_id; + uint32_t gNB_cu_up_ue_id; // Bearer Context Modification Request only uint64_t cipheringAlgorithm; uint64_t integrityProtectionAlgorithm; - char encryptionKey[128]; - char integrityProtectionKey[128]; + char encryptionKey[E1AP_SECURITY_KEY_SIZE]; + char integrityProtectionKey[E1AP_SECURITY_KEY_SIZE]; long ueDlAggMaxBitRate; PLMN_ID_t servingPLMNid; BEARER_CONTEXT_STATUS_t bearerContextStatus; - long activityNotificationLevel; + activity_notification_level_t activityNotificationLevel; int numPDUSessions; pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; int numPDUSessionsMod; @@ -293,16 +319,16 @@ typedef struct pdu_session_setup_s { in_addr_t tlAddress; long teId; int numDRBSetup; - DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; + DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_DRBS]; int numDRBFailed; - DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_NGRAN_DRB]; + DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_DRBS]; } pdu_session_setup_t; typedef struct pdu_session_modif_s { long id; // setup as part of PDU session modification not supported yet int numDRBModified; - DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; + DRB_nGRAN_modified_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; } pdu_session_modif_t; typedef struct e1ap_bearer_setup_resp_s { diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index cdba1c5e2de40795db098e79bbcae0738689478f..2ac5652a9f8f84b0751adb1643a6d9e665028205 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -29,6 +29,7 @@ #ifndef NGAP_MESSAGES_TYPES_H_ #define NGAP_MESSAGES_TYPES_H_ +#include "common/5g_platform_types.h" #include "common/platform_constants.h" #include "common/platform_types.h" #include "common/5g_platform_types.h" diff --git a/openair2/E1AP/CMakeLists.txt b/openair2/E1AP/CMakeLists.txt index c7657eed5aa115d230ebb11bcfceda451e916c3b..5849a32fe56b88a133f15268d8c938284a755821 100644 --- a/openair2/E1AP/CMakeLists.txt +++ b/openair2/E1AP/CMakeLists.txt @@ -1,7 +1,12 @@ add_subdirectory(MESSAGES) +add_subdirectory(lib) add_library(e1ap e1ap.c e1ap_common.c) target_link_libraries(e1ap - PUBLIC asn1_e1ap f1ap + PUBLIC asn1_e1ap e1ap_lib PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap UTIL e1_if) target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR}) + +if(ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 1e28ebd52a8204bbc173236e59128c11d8f3b6c5..79b326593b00271e94296a84658a14306b348ec6 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -33,6 +33,7 @@ #include "e1ap_default_values.h" #include "gtp_itf.h" #include "openair2/LAYER2/nr_pdcp/cucp_cuup_handler.h" +#include "lib/e1ap_bearer_context_management.h" #define E1AP_NUM_MSG_HANDLERS 14 typedef int (*e1ap_message_processing_t)(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p); @@ -572,296 +573,17 @@ int e1ap_handle_RELEASE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, return -1; } -/* - BEARER CONTEXT SETUP REQUEST -*/ - -static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) -{ - pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu->choice.initiatingMessage, msg); - msg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; - msg->criticality = E1AP_Criticality_reject; - msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest; - E1AP_BearerContextSetupRequest_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; - /* mandatory */ - /* c1. gNB-CU-UP UE E1AP ID */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC1); - ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; - ieC1->criticality = E1AP_Criticality_reject; - ieC1->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; - ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; - /* mandatory */ - /* c2. Security Information */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC2); - ieC2->id = E1AP_ProtocolIE_ID_id_SecurityInformation; - ieC2->criticality = E1AP_Criticality_reject; - ieC2->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation; - ieC2->value.choice.SecurityInformation.securityAlgorithm.cipheringAlgorithm = bearerCxt->cipheringAlgorithm; - OCTET_STRING_fromBuf(&ieC2->value.choice.SecurityInformation.uPSecuritykey.encryptionKey, - bearerCxt->encryptionKey, 16); - - asn1cCallocOne(ieC2->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm, bearerCxt->integrityProtectionAlgorithm); - asn1cCalloc(ieC2->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey, protKey); - OCTET_STRING_fromBuf(protKey, bearerCxt->integrityProtectionKey, 16); - /* mandatory */ - /* c3. UE DL Aggregate Maximum Bit Rate */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC3); - ieC3->id = E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate; - ieC3->criticality = E1AP_Criticality_reject; - ieC3->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_BitRate; - asn_long2INTEGER(&ieC3->value.choice.BitRate, bearerCxt->ueDlAggMaxBitRate); - /* mandatory */ - /* c4. Serving PLMN */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC4); - ieC4->id = E1AP_ProtocolIE_ID_id_Serving_PLMN; - ieC4->criticality = E1AP_Criticality_ignore; - ieC4->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity; - PLMN_ID_t *servingPLMN = &bearerCxt->servingPLMNid; - MCC_MNC_TO_PLMNID(servingPLMN->mcc, servingPLMN->mnc, servingPLMN->mnc_digit_length, &ieC4->value.choice.PLMN_Identity); - /* mandatory */ - /* Activity Notification Level */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC5); - ieC5->id = E1AP_ProtocolIE_ID_id_ActivityNotificationLevel; - ieC5->criticality = E1AP_Criticality_reject; - ieC5->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel; - ieC5->value.choice.ActivityNotificationLevel = E1AP_ActivityNotificationLevel_pdu_session;// TODO: Remove hard coding - /* mandatory */ - /* */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC6); - ieC6->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest; - ieC6->criticality = E1AP_Criticality_reject; - ieC6->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest; - ieC6->value.choice.System_BearerContextSetupRequest.present = E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest; - E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P19_t)); - ieC6->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; - asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupRequest_t, msgNGRAN); - msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List; - msgNGRAN->criticality = E1AP_Criticality_reject; - msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List; - E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; - for (pdu_session_to_setup_t *i = bearerCxt->pduSession; i < bearerCxt->pduSession + bearerCxt->numPDUSessions; i++) { - asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Item_t, ieC6_1); - ieC6_1->pDU_Session_ID = i->sessionId; - ieC6_1->pDU_Session_Type = i->sessionType; - - INT8_TO_OCTET_STRING(i->nssai.sst, &ieC6_1->sNSSAI.sST); - if (i->nssai.sd != 0xffffff) { - ieC6_1->sNSSAI.sD = malloc(sizeof(*ieC6_1->sNSSAI.sD)); - AssertFatal(ieC6_1->sNSSAI.sD != NULL, "out of memory\n"); - INT24_TO_OCTET_STRING(i->nssai.sd, ieC6_1->sNSSAI.sD); - } - - ieC6_1->securityIndication.integrityProtectionIndication = i->integrityProtectionIndication; - ieC6_1->securityIndication.confidentialityProtectionIndication = i->confidentialityProtectionIndication; - - ieC6_1->nG_UL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; - asn1cCalloc(ieC6_1->nG_UL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); - - for (DRB_nGRAN_to_setup_t *j = i->DRBnGRanList; j < i->DRBnGRanList + i->numDRB2Setup; j++) { - asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); - ieC6_1_1->dRB_ID = j->id; - /* SDAP config */ - ieC6_1_1->sDAP_Configuration.defaultDRB = j->sdap_config.defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; - ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sdap_config.sDAP_Header_UL; - ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sdap_config.sDAP_Header_DL; - /* PDCP Config */ - ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pdcp_config.pDCP_SN_Size_UL; - ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pdcp_config.pDCP_SN_Size_DL; - asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->pdcp_config.discardTimer); - E1AP_T_ReorderingTimer_t *roTimer = calloc(1, sizeof(E1AP_T_ReorderingTimer_t)); - ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer; - roTimer->t_Reordering = j->pdcp_config.reorderingTimer; - ieC6_1_1->pDCP_Configuration.rLC_Mode = j->pdcp_config.rLC_Mode; - /* Cell Group config */ - for (cell_group_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { - asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); - ieC6_1_1_1->cell_Group_ID = k->id; - } - /* QoS Flows */ - for (qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { - asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); - ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; - /* QoS Characteristics */ - qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; - if (qos_char_in->qos_type == NON_DYNAMIC) { // non Dynamic 5QI - ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); - non_Dynamic_5QI->fiveQI = qos_char_in->non_dynamic.fiveqi; - } else { // dynamic 5QI - ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); - dynamic_5QI->qoSPriorityLevel = qos_char_in->dynamic.qos_priority_level; - dynamic_5QI->packetDelayBudget = qos_char_in->dynamic.packet_delay_budget; - dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar; - dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent; - } - /* QoS Retention Priority */ - ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority; - ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = rent_priority_in->priority_level; - ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = - rent_priority_in->preemption_capability; - ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = - rent_priority_in->preemption_vulnerability; - } - } - } - return 0; -} - void e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const bearerCxt) { - E1AP_E1AP_PDU_t pdu = {0}; - fill_BEARER_CONTEXT_SETUP_REQUEST(bearerCxt, &pdu); - e1ap_encode_send(CPtype, assoc_id, &pdu, 0, __func__); -} - -static void fill_BEARER_CONTEXT_SETUP_RESPONSE(const e1ap_bearer_setup_resp_t *resp, E1AP_E1AP_PDU_t *pdu) -{ - /* Create */ - /* 0. pdu Type */ - pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu->choice.successfulOutcome, msg); - msg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; - msg->criticality = E1AP_Criticality_reject; - msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse; - E1AP_BearerContextSetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; - /* mandatory */ - /* c1. gNB-CU-CP UE E1AP ID */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC1); - ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; - ieC1->criticality = E1AP_Criticality_reject; - ieC1->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; - ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_cp_ue_id; - /* mandatory */ - /* c2. gNB-CU-UP UE E1AP ID */ - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC2); - ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; - ieC2->criticality = E1AP_Criticality_reject; - ieC2->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; - ieC2->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_up_ue_id; - - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC3); - ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse; - ieC3->criticality = E1AP_Criticality_reject; - ieC3->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse; - /*if (0) { // EUTRAN - ieC3->value.choice.System_BearerContextSetupResponse.present = - E1AP_System_BearerContextSetupResponse_PR_e_UTRAN_BearerContextSetupResponse; - E1AP_ProtocolIE_Container_4932P21_t *msgEUTRAN_list = calloc(1, - sizeof(E1AP_ProtocolIE_Container_4932P21_t)); - ieC3->value.choice.System_BearerContextSetupResponse.choice.e_UTRAN_BearerContextSetupResponse - = (struct E1AP_ProtocolIE_Container *) msgEUTRAN_list; - asn1cSequenceAdd(msgEUTRAN_list->list, - E1AP_EUTRAN_BearerContextSetupResponse_t, msgEUTRAN); msgEUTRAN->id = - E1AP_ProtocolIE_ID_id_DRB_Setup_List_EUTRAN; msgEUTRAN->criticality = - E1AP_Criticality_reject; msgEUTRAN->value.present = - E1AP_EUTRAN_BearerContextSetupResponse__value_PR_DRB_Setup_List_EUTRAN; - E1AP_DRB_Setup_List_EUTRAN_t *drbSetup = - &msgEUTRAN->value.choice.DRB_Setup_List_EUTRAN; - - for (drb_setup_t *i=resp->DRBList; i < resp->DRBList+resp->numDRBs; i++) { - asn1cSequenceAdd(drbSetup->list, E1AP_DRB_Setup_Item_EUTRAN_t, ieC3_1); - ieC3_1->dRB_ID = i->drbId; - - ieC3_1->s1_DL_UP_TNL_Information.present = - E1AP_UP_TNL_Information_PR_gTPTunnel; - asn1cCalloc(ieC3_1->s1_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, - &gTPTunnel->transportLayerAddress); INT32_TO_OCTET_STRING(i->teId, - &gTPTunnel->gTP_TEID); - - for (up_params_t *j=i->UpParamList; j < i->UpParamList+i->numUpParam; j++) - { asn1cSequenceAdd(ieC3_1->uL_UP_Transport_Parameters.list, - E1AP_UP_Parameters_Item_t, ieC3_1_1); ieC3_1_1->uP_TNL_Information.present = - E1AP_UP_TNL_Information_PR_gTPTunnel; - asn1cCalloc(ieC3_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(j->tlAddress, - &gTPTunnel->transportLayerAddress); INT32_TO_OCTET_STRING(j->teId, - &gTPTunnel->gTP_TEID); - } - } - } else */ - { - ieC3->value.choice.System_BearerContextSetupResponse.present = - E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse; - E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P22_t)); - ieC3->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse = - (struct E1AP_ProtocolIE_Container *)msgNGRAN_list; - asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupResponse_t, msgNGRAN); - msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List; - msgNGRAN->criticality = E1AP_Criticality_reject; - msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List; - E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; - - for (const pdu_session_setup_t *i = resp->pduSession; i < resp->pduSession + resp->numPDUSessions; i++) { - asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1); - ieC3_1->pDU_Session_ID = i->id; - - ieC3_1->nG_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; - asn1cCalloc(ieC3_1->nG_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); - - for (const DRB_nGRAN_setup_t *j = i->DRBnGRanList; j < i->DRBnGRanList + i->numDRBSetup; j++) { - asn1cSequenceAdd(ieC3_1->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1); - ieC3_1_1->dRB_ID = j->id; - - for (const up_params_t *k = j->UpParamList; k < j->UpParamList + j->numUpParam; k++) { - asn1cSequenceAdd(ieC3_1_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1); - ieC3_1_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; - asn1cCalloc(ieC3_1_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); - INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); - } - - for (const qos_flow_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlowSetup; k++) { - asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); - ieC3_1_1_1->qoS_Flow_Identifier = k->qfi; - } - } - - if (i->numDRBFailed > 0) - ieC3_1->dRB_Failed_List_NG_RAN = calloc(1, sizeof(E1AP_DRB_Failed_List_NG_RAN_t)); - - for (const DRB_nGRAN_failed_t *j = i->DRBnGRanFailedList; j < i->DRBnGRanFailedList + i->numDRBFailed; j++) { - asn1cSequenceAdd(ieC3_1->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1); - ieC3_1_1->dRB_ID = j->id; - - ieC3_1_1->cause.present = j->cause_type; - switch (ieC3_1_1->cause.present) { - case E1AP_Cause_PR_radioNetwork: - ieC3_1_1->cause.choice.radioNetwork = j->cause; - break; - - case E1AP_Cause_PR_transport: - ieC3_1_1->cause.choice.transport = j->cause; - break; - - case E1AP_Cause_PR_protocol: - ieC3_1_1->cause.choice.protocol = j->cause; - break; - - case E1AP_Cause_PR_misc: - ieC3_1_1->cause.choice.misc = j->cause; - break; - - default: - LOG_E(E1AP, "DRB setup failure cause out of expected range\n"); - break; - } - } - } - } + E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_setup_request(bearerCxt); + e1ap_encode_send(CPtype, assoc_id, pdu, 0, __func__); } void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, const e1ap_bearer_setup_resp_t *resp) { - E1AP_E1AP_PDU_t pdu = {0}; - fill_BEARER_CONTEXT_SETUP_RESPONSE(resp, &pdu); - e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__); + // Encode + E1AP_E1AP_PDU_t *pdu = encode_E1_bearer_context_setup_response(resp); + e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance) @@ -870,287 +592,27 @@ int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance) return -1; } -static void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *bearerCxt) -{ - const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; - E1AP_BearerContextSetupRequestIEs_t *ie; - - LOG_D(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); - - for (int i = 0; i < in->protocolIEs.list.count; i++) { - ie = in->protocolIEs.list.array[i]; - - switch(ie->id) { - case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); - bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; - break; - - case E1AP_ProtocolIE_ID_id_SecurityInformation: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation); - bearerCxt->cipheringAlgorithm = ie->value.choice.SecurityInformation.securityAlgorithm.cipheringAlgorithm; - memcpy(bearerCxt->encryptionKey, - ie->value.choice.SecurityInformation.uPSecuritykey.encryptionKey.buf, - ie->value.choice.SecurityInformation.uPSecuritykey.encryptionKey.size); - if (ie->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm) { - bearerCxt->integrityProtectionAlgorithm = *ie->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm; - } - if (ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey) { - memcpy(bearerCxt->integrityProtectionKey, - ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey->buf, - ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey->size); - } - break; - - case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_BitRate); - asn_INTEGER2long(&ie->value.choice.BitRate, &bearerCxt->ueDlAggMaxBitRate); - break; - - case E1AP_ProtocolIE_ID_id_Serving_PLMN: - DevAssert(ie->criticality == E1AP_Criticality_ignore); - DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity); - PLMNID_TO_MCC_MNC(&ie->value.choice.PLMN_Identity, - bearerCxt->servingPLMNid.mcc, - bearerCxt->servingPLMNid.mnc, - bearerCxt->servingPLMNid.mnc_digit_length); - break; - - case E1AP_ProtocolIE_ID_id_ActivityNotificationLevel: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel); - bearerCxt->activityNotificationLevel = ie->value.choice.ActivityNotificationLevel; - break; - - case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest); - DevAssert(ie->value.choice.System_BearerContextSetupRequest.present == - E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest); - DevAssert(ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest); - E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P19_t *) ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest; - E1AP_NG_RAN_BearerContextSetupRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; - DevAssert(msgNGRAN_list->list.count == 1); - DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List); - DevAssert(msgNGRAN->value.present == E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List); - - E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2SetupList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; - bearerCxt->numPDUSessions = pdu2SetupList->list.count; - for (int i = 0; i < pdu2SetupList->list.count; i++) { - pdu_session_to_setup_t *pdu_session = bearerCxt->pduSession + i; - E1AP_PDU_Session_Resource_To_Setup_Item_t *pdu2Setup = pdu2SetupList->list.array[i]; - - pdu_session->sessionId = pdu2Setup->pDU_Session_ID; - pdu_session->sessionType = pdu2Setup->pDU_Session_Type; - - OCTET_STRING_TO_INT8(&pdu2Setup->sNSSAI.sST, pdu_session->nssai.sst); - pdu_session->nssai.sd = 0xffffff; - if (pdu2Setup->sNSSAI.sD != NULL) - OCTET_STRING_TO_INT24(pdu2Setup->sNSSAI.sD, pdu_session->nssai.sd); - - pdu_session->integrityProtectionIndication = pdu2Setup->securityIndication.integrityProtectionIndication; - pdu_session->confidentialityProtectionIndication = pdu2Setup->securityIndication.confidentialityProtectionIndication; - - if (pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel) { // Optional IE - DevAssert(pdu2Setup->nG_UL_UP_TNL_Information.present == - E1AP_UP_TNL_Information_PR_gTPTunnel); - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, - pdu_session->tlAddress); - OCTET_STRING_TO_INT32(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pdu_session->teId); - } - - E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &pdu2Setup->dRB_To_Setup_List_NG_RAN; - pdu_session->numDRB2Setup = drb2SetupList->list.count; - for (int j = 0; j < drb2SetupList->list.count; j++) { - DRB_nGRAN_to_setup_t *drb = pdu_session->DRBnGRanList + j; - E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; - - drb->id = drb2Setup->dRB_ID; - /* SDAP */ - drb->sdap_config.defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB == E1AP_DefaultDRB_true; - drb->sdap_config.sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL; - drb->sdap_config.sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL; - /* PDCP */ - drb->pdcp_config.pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL; - drb->pdcp_config.pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL; - if (drb2Setup->pDCP_Configuration.discardTimer) { - drb->pdcp_config.discardTimer = *drb2Setup->pDCP_Configuration.discardTimer; - } - if (drb2Setup->pDCP_Configuration.t_ReorderingTimer) { - drb->pdcp_config.reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering; - } - drb->pdcp_config.rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode; - - E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; - drb->numCellGroups = cellGroupList->list.count; - for (int k = 0; k < cellGroupList->list.count; k++) { - E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k]; - - drb->cellGroupList[k].id = cg2Setup->cell_Group_ID; - } - - E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; - drb->numQosFlow2Setup = qos2SetupList->list.count; - for (int k = 0; k < qos2SetupList->list.count; k++) { - qos_flow_to_setup_t *qos_flow = drb->qosFlows + k; - E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; - - qos_flow->qfi = qos2Setup->qoS_Flow_Identifier; - - qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; - if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - qos_char->qos_type = NON_DYNAMIC; - qos_char->non_dynamic.fiveqi = - qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; - } else { - E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; - qos_char->qos_type = DYNAMIC; - qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel; - qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget; - qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar; - qos_char->dynamic.packet_error_rate.per_exponent = dynamic5QI->packetErrorRate.pER_Exponent; - } - - ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority; - rent_priority->priority_level = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel; - rent_priority->preemption_capability = - qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability; - rent_priority->preemption_vulnerability = - qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability; - } - } - } - break; - - default: - LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); - break; - } - } -} - int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) { - DevAssert(pdu != NULL); - DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); - DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup); - DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); - DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest); - + // Decode E1AP message e1ap_bearer_setup_req_t bearerCxt = {0}; - extract_BEARER_CONTEXT_SETUP_REQUEST(pdu, &bearerCxt); - + if (!decode_E1_bearer_context_setup_request(pdu, &bearerCxt)) { + LOG_E(E1AP, "Failed to decode E1 Bearer Context Setup Request\n"); + return -1; + } e1_bearer_context_setup(&bearerCxt); return 0; } -void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_resp_t *bearerCxt) -{ - const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; - E1AP_BearerContextSetupResponseIEs_t *ie; - - LOG_D(E1AP, "Bearer context setup response number of IEs %d\n", in->protocolIEs.list.count); - - for (int i = 0; i < in->protocolIEs.list.count; i++) { - ie = in->protocolIEs.list.array[i]; - - switch(ie->id) { - case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); - bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; - break; - - case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); - bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; - break; - - case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse: - DevAssert(ie->criticality == E1AP_Criticality_reject); - DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse); - DevAssert(ie->value.choice.System_BearerContextSetupResponse.present - == E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse); - E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = - (E1AP_ProtocolIE_Container_4932P22_t *) - ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; - DevAssert(msgNGRAN_list->list.count == 1); - E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; - DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List); - DevAssert(msgNGRAN->criticality == E1AP_Criticality_reject); - DevAssert(msgNGRAN->value.present == E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List); - E1AP_PDU_Session_Resource_Setup_List_t *pduSetupList = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; - bearerCxt->numPDUSessions = pduSetupList->list.count; - - for (int i = 0; i < pduSetupList->list.count; i++) { - pdu_session_setup_t *pduSetup = bearerCxt->pduSession + i; - E1AP_PDU_Session_Resource_Setup_Item_t *pdu_session = pduSetupList->list.array[i]; - pduSetup->id = pdu_session->pDU_Session_ID; - - if (pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel) { - DevAssert(pdu_session->nG_DL_UP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4( - &pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, - pduSetup->tlAddress); - OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pduSetup->teId); - } - - pduSetup->numDRBSetup = pdu_session->dRB_Setup_List_NG_RAN.list.count; - for (int j = 0; j < pdu_session->dRB_Setup_List_NG_RAN.list.count; j++) { - DRB_nGRAN_setup_t *drbSetup = pduSetup->DRBnGRanList + j; - E1AP_DRB_Setup_Item_NG_RAN_t *drb = pdu_session->dRB_Setup_List_NG_RAN.list.array[j]; - - drbSetup->id = drb->dRB_ID; - - drbSetup->numUpParam = drb->uL_UP_Transport_Parameters.list.count; - for (int k = 0; k < drb->uL_UP_Transport_Parameters.list.count; k++) { - up_params_t *UL_UP_param = drbSetup->UpParamList + k; - E1AP_UP_Parameters_Item_t *in_UL_UP_param = drb->uL_UP_Transport_Parameters.list.array[k]; - - DevAssert(in_UL_UP_param->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); - E1AP_GTPTunnel_t *gTPTunnel = in_UL_UP_param->uP_TNL_Information.choice.gTPTunnel; - if (gTPTunnel) { - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UL_UP_param->tlAddress); - OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UL_UP_param->teId); - } else { - AssertFatal(false, "gTPTunnel information in required\n"); - } - } - - // Qos Flow Information - drbSetup->numQosFlowSetup = drb->flow_Setup_List.list.count; - for (int q = 0; q < drb->flow_Setup_List.list.count; q++) { - qos_flow_setup_t *qosflowSetup = &drbSetup->qosFlows[q]; - E1AP_QoS_Flow_Item_t *in_qosflowSetup = drb->flow_Setup_List.list.array[q]; - qosflowSetup->qfi = in_qosflowSetup->qoS_Flow_Identifier; - } - } - } - break; - - // TODO: remaining IE handlers - - default: - LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); - break; - } - } -} - int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) { - DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); - DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup); - DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); - DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse); - MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); + // Decode e1ap_bearer_setup_resp_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); - extract_BEARER_CONTEXT_SETUP_RESPONSE(pdu, bearerCxt); + if (!decode_E1_bearer_context_setup_response(pdu, bearerCxt)) { + LOG_E(E1AP, "Failed to decode Bearer Context Setup Response\n"); + return -1; + } msg->ittiMsgHeader.originInstance = assoc_id; // Fixme: instance is the NGAP instance, no good way to set it here instance_t instance = 0; @@ -1976,6 +1438,7 @@ void *E1AP_CUCP_task(void *arg) case E1AP_BEARER_CONTEXT_SETUP_REQ: e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); + free_e1ap_context_setup_request(&E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); break; case E1AP_BEARER_CONTEXT_MODIFICATION_REQ: @@ -2042,6 +1505,7 @@ void *E1AP_CUUP_task(void *arg) const e1ap_upcp_inst_t *inst = getCxtE1(myInstance); AssertFatal(inst, "no E1 instance found for instance %ld\n", myInstance); e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst->cuup.assoc_id, resp); + free_e1ap_context_setup_response(resp); } break; case E1AP_BEARER_CONTEXT_MODIFICATION_RESP: { diff --git a/openair2/E1AP/lib/CMakeLists.txt b/openair2/E1AP/lib/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6e766581fa8d01e8f8478d5eb4198262a5638650 --- /dev/null +++ b/openair2/E1AP/lib/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(e1ap_lib OBJECT + e1ap_bearer_context_management.c +) + +target_link_libraries(e1ap_lib PRIVATE asn1_e1ap) +target_include_directories(e1ap_lib PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c new file mode 100644 index 0000000000000000000000000000000000000000..5e359512ed3ba5e7e1087b1040a5ff0e9db7646a --- /dev/null +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -0,0 +1,971 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file e1ap_bearer_context_management.c + * \brief E1AP library for E1 Bearer Context Management + * \author Guido Casati + * \date 2024 + * \version 0.1 + */ + +#include <string.h> + +#include "common/utils/assertions.h" +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" + +#include "e1ap_lib_common.h" +#include "e1ap_bearer_context_management.h" +#include "e1ap_lib_includes.h" + +/* ==================================== + * E1AP Bearer Context Setup Request + * ==================================== */ + +/** + * @brief Equality check for bearer_context_pdcp_config_t + */ +static bool eq_pdcp_config(const bearer_context_pdcp_config_t *a, const bearer_context_pdcp_config_t *b) +{ + _E1_EQ_CHECK_LONG(a->pDCP_SN_Size_UL, b->pDCP_SN_Size_UL); + _E1_EQ_CHECK_LONG(a->pDCP_SN_Size_DL, b->pDCP_SN_Size_DL); + _E1_EQ_CHECK_LONG(a->rLC_Mode, b->rLC_Mode); + _E1_EQ_CHECK_LONG(a->reorderingTimer, b->reorderingTimer); + _E1_EQ_CHECK_LONG(a->discardTimer, b->discardTimer); + _E1_EQ_CHECK_INT(a->pDCP_Reestablishment, b->pDCP_Reestablishment); + return true; +} + +/** + * @brief Equality check for bearer_context_sdap_config_t + */ +static bool eq_sdap_config(const bearer_context_sdap_config_t *a, const bearer_context_sdap_config_t *b) +{ + _E1_EQ_CHECK_LONG(a->defaultDRB, b->defaultDRB); + _E1_EQ_CHECK_LONG(a->sDAP_Header_UL, b->sDAP_Header_UL); + _E1_EQ_CHECK_LONG(a->sDAP_Header_DL, b->sDAP_Header_DL); + return true; +} + +/** + * @brief Equality check for qos_flow_to_setup_t + */ +static bool eq_qos_flow(const qos_flow_to_setup_t *a, const qos_flow_to_setup_t *b) +{ + _E1_EQ_CHECK_LONG(a->qfi, b->qfi); + const ngran_allocation_retention_priority_t *arp_a = &a->qos_params.alloc_reten_priority; + const ngran_allocation_retention_priority_t *arp_b = &b->qos_params.alloc_reten_priority; + _E1_EQ_CHECK_INT(arp_a->preemption_capability, arp_b->preemption_capability); + _E1_EQ_CHECK_INT(arp_a->preemption_vulnerability, arp_b->preemption_vulnerability); + _E1_EQ_CHECK_INT(arp_a->priority_level, arp_b->priority_level); + const qos_characteristics_t *qos_a = &a->qos_params.qos_characteristics; + const qos_characteristics_t *qos_b = &b->qos_params.qos_characteristics; + _E1_EQ_CHECK_INT(qos_a->qos_type, qos_b->qos_type); + _E1_EQ_CHECK_INT(qos_a->dynamic.fiveqi, qos_b->dynamic.fiveqi); + _E1_EQ_CHECK_INT(qos_a->dynamic.packet_delay_budget, qos_b->dynamic.packet_delay_budget); + _E1_EQ_CHECK_INT(qos_a->dynamic.packet_error_rate.per_exponent, qos_b->dynamic.packet_error_rate.per_exponent); + _E1_EQ_CHECK_INT(qos_a->dynamic.packet_error_rate.per_scalar, qos_b->dynamic.packet_error_rate.per_scalar); + _E1_EQ_CHECK_INT(qos_a->dynamic.qos_priority_level, qos_b->dynamic.qos_priority_level); + _E1_EQ_CHECK_INT(qos_a->non_dynamic.fiveqi, qos_b->non_dynamic.fiveqi); + _E1_EQ_CHECK_INT(qos_a->non_dynamic.qos_priority_level, qos_b->non_dynamic.qos_priority_level); + return true; +} + +/** + * @brief Equality check for DRB_nGRAN_to_setup_t + */ +static bool eq_drb_to_setup(const DRB_nGRAN_to_setup_t *a, const DRB_nGRAN_to_setup_t *b) +{ + bool result = true; + _E1_EQ_CHECK_LONG(a->id, b->id); + _E1_EQ_CHECK_INT(a->numCellGroups, b->numCellGroups); + for (int i = 0; i < a->numCellGroups; i++) { + _E1_EQ_CHECK_INT(a->cellGroupList[i], b->cellGroupList[i]); + } + _E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup); + for (int i = 0; i < a->numQosFlow2Setup; i++) { + result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]); + } + result &= eq_pdcp_config(&a->pdcp_config, &b->pdcp_config); + result &= eq_sdap_config(&a->sdap_config, &b->sdap_config); + return result; +} + +/** + * @brief Equality check for DRB_nGRAN_to_mod_t + */ +static bool eq_drb_to_mod(const DRB_nGRAN_to_mod_t *a, const DRB_nGRAN_to_mod_t *b) +{ + bool result = true; + _E1_EQ_CHECK_LONG(a->id, b->id); + _E1_EQ_CHECK_INT(a->numCellGroups, b->numCellGroups); + for (int i = 0; i < a->numCellGroups; i++) { + _E1_EQ_CHECK_INT(a->cellGroupList[i], b->cellGroupList[i]); + } + _E1_EQ_CHECK_INT(a->numQosFlow2Setup, b->numQosFlow2Setup); + for (int i = 0; i < a->numQosFlow2Setup; i++) { + result &= eq_qos_flow(&a->qosFlows[i], &b->qosFlows[i]); + } + _E1_EQ_CHECK_INT(a->tlAddress, b->tlAddress); + _E1_EQ_CHECK_INT(a->teId, b->teId); + _E1_EQ_CHECK_INT(a->numDlUpParam, b->numDlUpParam); + for (int i = 0; i < a->numDlUpParam; i++) { + _E1_EQ_CHECK_INT(a->DlUpParamList[i].cell_group_id, b->DlUpParamList[i].cell_group_id); + _E1_EQ_CHECK_LONG(a->DlUpParamList[i].teId, b->DlUpParamList[i].teId); + _E1_EQ_CHECK_INT(a->DlUpParamList[i].tlAddress, b->DlUpParamList[i].tlAddress); + } + result &= eq_pdcp_config(&a->pdcp_config, &b->pdcp_config); + result &= eq_sdap_config(&a->sdap_config, &b->sdap_config); + return result; +} + +/* PDU Session To Setup Item */ + +static bool e1_encode_pdu_session_to_setup_item(E1AP_PDU_Session_Resource_To_Setup_Item_t *item, const pdu_session_to_setup_t *in) +{ + item->pDU_Session_ID = in->sessionId; + item->pDU_Session_Type = in->sessionType; + // SNSSAI + INT8_TO_OCTET_STRING(in->nssai.sst, &item->sNSSAI.sST); + if (in->nssai.sd != 0xffffff) { + item->sNSSAI.sD = malloc_or_fail(sizeof(*item->sNSSAI.sD)); + INT24_TO_OCTET_STRING(in->nssai.sd, item->sNSSAI.sD); + } + // Security Indication + E1AP_SecurityIndication_t *siOut = &item->securityIndication; + const security_indication_t *siIn = &in->securityIndication; + siOut->integrityProtectionIndication = siIn->integrityProtectionIndication; + siOut->confidentialityProtectionIndication = siIn->confidentialityProtectionIndication; + if (siIn->integrityProtectionIndication != SECURITY_NOT_NEEDED) { + asn1cCalloc(siOut->maximumIPdatarate, ipDataRate); + ipDataRate->maxIPrate = siIn->maxIPrate; + } + // TNL Information + item->nG_UL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(item->nG_UL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + const UP_TL_information_t *UP_TL_information = &in->UP_TL_information; + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(UP_TL_information->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(UP_TL_information->teId, &gTPTunnel->gTP_TEID); + // DRB to setup + for (const DRB_nGRAN_to_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRB2Setup; j++) { + asn1cSequenceAdd(item->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); + ieC6_1_1->dRB_ID = j->id; + // SDAP Config + E1AP_SDAP_Configuration_t *sdap = &ieC6_1_1->sDAP_Configuration; + sdap->defaultDRB = j->sdap_config.defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; + sdap->sDAP_Header_UL = j->sdap_config.sDAP_Header_UL; + sdap->sDAP_Header_DL = j->sdap_config.sDAP_Header_DL; + // PDCP Config + E1AP_PDCP_Configuration_t *pdcp = &ieC6_1_1->pDCP_Configuration; + pdcp->pDCP_SN_Size_UL = j->pdcp_config.pDCP_SN_Size_UL; + pdcp->pDCP_SN_Size_DL = j->pdcp_config.pDCP_SN_Size_DL; + asn1cCallocOne(pdcp->discardTimer, j->pdcp_config.discardTimer); + E1AP_T_ReorderingTimer_t *roTimer = calloc_or_fail(1, sizeof(*roTimer)); + pdcp->t_ReorderingTimer = roTimer; + roTimer->t_Reordering = j->pdcp_config.reorderingTimer; + pdcp->rLC_Mode = j->pdcp_config.rLC_Mode; + // Cell Group + for (const cell_group_id_t *k = j->cellGroupList; k < j->cellGroupList + j->numCellGroups; k++) { + asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); + ieC6_1_1_1->cell_Group_ID = *k; + } + // QoS Flows + for (const qos_flow_to_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlow2Setup; k++) { + asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); + ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; + // QoS Characteristics + const qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; + if (qos_char_in->qos_type == NON_DYNAMIC) { // non Dynamic 5QI + ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); + non_Dynamic_5QI->fiveQI = qos_char_in->non_dynamic.fiveqi; + } else { // dynamic 5QI + ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); + dynamic_5QI->qoSPriorityLevel = qos_char_in->dynamic.qos_priority_level; + dynamic_5QI->packetDelayBudget = qos_char_in->dynamic.packet_delay_budget; + dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar; + dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent; + } + // QoS Retention Priority + const ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority; + E1AP_NGRANAllocationAndRetentionPriority_t *arp = &ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority; + arp->priorityLevel = rent_priority_in->priority_level; + arp->pre_emptionCapability = rent_priority_in->preemption_capability; + arp->pre_emptionVulnerability = rent_priority_in->preemption_vulnerability; + } + } + return true; +} + +static bool e1_decode_pdu_session_to_setup_item(pdu_session_to_setup_t *out, E1AP_PDU_Session_Resource_To_Setup_Item_t *item) +{ + // PDU Session ID (M) + out->sessionId = item->pDU_Session_ID; + // PDU Session Type (M) + out->sessionType = item->pDU_Session_Type; + /* S-NSSAI (M) */ + // SST (M) + OCTET_STRING_TO_INT8(&item->sNSSAI.sST, out->nssai.sst); + out->nssai.sd = 0xffffff; + // SD (O) + if (item->sNSSAI.sD != NULL) + OCTET_STRING_TO_INT24(item->sNSSAI.sD, out->nssai.sd); + /* Security Indication (M) */ + E1AP_SecurityIndication_t *securityIndication = &item->securityIndication; + // Integrity Protection Indication (M) + security_indication_t *sec = &out->securityIndication; + sec->integrityProtectionIndication = securityIndication->integrityProtectionIndication; + // Confidentiality Protection Indication (M) + sec->confidentialityProtectionIndication = securityIndication->confidentialityProtectionIndication; + // Maximum Integrity Protected Data Rate (Conditional) + if (sec->integrityProtectionIndication != SECURITY_NOT_NEEDED) { + if (securityIndication->maximumIPdatarate) + sec->maxIPrate = securityIndication->maximumIPdatarate->maxIPrate; + else { + PRINT_ERROR("Received integrityProtectionIndication but maximumIPdatarate IE is missing\n"); + return false; + } + } + /* NG UL UP Transport Layer Information (M) (9.3.2.1 of 3GPP TS 38.463) */ + // GTP Tunnel + struct E1AP_GTPTunnel *gTPTunnel = item->nG_UL_UP_TNL_Information.choice.gTPTunnel; + if (!gTPTunnel) { + PRINT_ERROR("Missing mandatory IE item->nG_UL_UP_TNL_Information.choice.gTPTunnel\n"); + return false; + } + _E1_EQ_CHECK_INT(item->nG_UL_UP_TNL_Information.present, E1AP_UP_TNL_Information_PR_gTPTunnel); + // Transport Layer Address + UP_TL_information_t *UP_TL_information = &out->UP_TL_information; + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UP_TL_information->tlAddress); + // GTP-TEID + OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UP_TL_information->teId); + // DRB To Setup List ( > 1 item ) + E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &item->dRB_To_Setup_List_NG_RAN; + _E1_EQ_CHECK_GENERIC(drb2SetupList->list.count > 0, "%d", drb2SetupList->list.count, 0); + out->numDRB2Setup = drb2SetupList->list.count; + _E1_EQ_CHECK_INT(out->numDRB2Setup, 1); // can only handle one DRB per PDU session + for (int j = 0; j < drb2SetupList->list.count; j++) { + DRB_nGRAN_to_setup_t *drb = out->DRBnGRanList + j; + E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; + // DRB ID (M) + drb->id = drb2Setup->dRB_ID; + // >SDAP Configuration (M) + E1AP_SDAP_Configuration_t *sdap = &drb2Setup->sDAP_Configuration; + drb->sdap_config.defaultDRB = sdap->defaultDRB == E1AP_DefaultDRB_true; + drb->sdap_config.sDAP_Header_UL = sdap->sDAP_Header_UL; + drb->sdap_config.sDAP_Header_DL = sdap->sDAP_Header_DL; + // PDCP Configuration (M) + E1AP_PDCP_Configuration_t *pdcp = &drb2Setup->pDCP_Configuration; + drb->pdcp_config.pDCP_SN_Size_UL = pdcp->pDCP_SN_Size_UL; + drb->pdcp_config.pDCP_SN_Size_DL = pdcp->pDCP_SN_Size_DL; + if (pdcp->discardTimer) { + drb->pdcp_config.discardTimer = *pdcp->discardTimer; + } + if (pdcp->t_ReorderingTimer) { + drb->pdcp_config.reorderingTimer = pdcp->t_ReorderingTimer->t_Reordering; + } + drb->pdcp_config.rLC_Mode = pdcp->rLC_Mode; + // Cell Group Information (M) ( > 1 item ) + E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; + _E1_EQ_CHECK_GENERIC(cellGroupList->list.count > 0, "%d", cellGroupList->list.count, 0); + drb->numCellGroups = cellGroupList->list.count; + for (int k = 0; k < cellGroupList->list.count; k++) { + E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k]; + // Cell Group ID + drb->cellGroupList[k] = cg2Setup->cell_Group_ID; + } + // QoS Flows Information To Be Setup (M) + E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; + drb->numQosFlow2Setup = qos2SetupList->list.count; + for (int k = 0; k < qos2SetupList->list.count; k++) { + qos_flow_to_setup_t *qos_flow = drb->qosFlows + k; + E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; + // QoS Flow Identifier (M) + qos_flow->qfi = qos2Setup->qoS_Flow_Identifier; + qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; + // QoS Flow Level QoS Parameters (M) + E1AP_QoSFlowLevelQoSParameters_t *qosParams = &qos2Setup->qoSFlowLevelQoSParameters; + E1AP_QoS_Characteristics_t *qoS_Characteristics = &qosParams->qoS_Characteristics; + switch (qoS_Characteristics->present) { + case E1AP_QoS_Characteristics_PR_non_Dynamic_5QI: + qos_char->qos_type = NON_DYNAMIC; + qos_char->non_dynamic.fiveqi = qoS_Characteristics->choice.non_Dynamic_5QI->fiveQI; + break; + case E1AP_QoS_Characteristics_PR_dynamic_5QI: { + E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qoS_Characteristics->choice.dynamic_5QI; + qos_char->qos_type = DYNAMIC; + qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel; + qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget; + qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar; + qos_char->dynamic.packet_error_rate.per_exponent = dynamic5QI->packetErrorRate.pER_Exponent; + break; + } + default: + PRINT_ERROR("Unexpected QoS Characteristics type: %d\n", qoS_Characteristics->present); + return false; + break; + } + // NG-RAN Allocation and Retention Priority (M) + ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority; + E1AP_NGRANAllocationAndRetentionPriority_t *aRP = &qosParams->nGRANallocationRetentionPriority; + rent_priority->priority_level = aRP->priorityLevel; + rent_priority->preemption_capability = aRP->pre_emptionCapability; + rent_priority->preemption_vulnerability = aRP->pre_emptionVulnerability; + } + } + return true; +} + +/** + * @brief Equality check for PDU session item to modify/setup + */ +static bool eq_pdu_session_item(const pdu_session_to_setup_t *a, const pdu_session_to_setup_t *b) +{ + _E1_EQ_CHECK_LONG(a->sessionId, b->sessionId); + _E1_EQ_CHECK_LONG(a->sessionType, b->sessionType); + _E1_EQ_CHECK_INT(a->UP_TL_information.tlAddress, b->UP_TL_information.tlAddress); + _E1_EQ_CHECK_INT(a->UP_TL_information.teId, b->UP_TL_information.teId); + _E1_EQ_CHECK_LONG(a->numDRB2Setup, b->numDRB2Setup); + if (a->numDRB2Setup != b->numDRB2Setup) + return false; + for (int i = 0; i < a->numDRB2Setup; i++) + if (!eq_drb_to_setup(&a->DRBnGRanList[i], &b->DRBnGRanList[i])) + return false; + _E1_EQ_CHECK_LONG(a->numDRB2Modify, b->numDRB2Modify); + if (a->numDRB2Modify != b->numDRB2Modify) + return false; + for (int i = 0; i < a->numDRB2Modify; i++) + if (!eq_drb_to_mod(&a->DRBnGRanModList[i], &b->DRBnGRanModList[i])) + return false; + return true; +} + +static bool cp_pdu_session_item(pdu_session_to_setup_t *cp, const pdu_session_to_setup_t *msg) +{ + // Copy basic fields + *cp = *msg; + // Copy DRB to Setup List + for (int j = 0; j < msg->numDRB2Setup; j++) { + cp->DRBnGRanList[j].id = msg->DRBnGRanList[j].id; + cp->DRBnGRanList[j].sdap_config = msg->DRBnGRanList[j].sdap_config; + cp->DRBnGRanList[j].pdcp_config = msg->DRBnGRanList[j].pdcp_config; + cp->DRBnGRanList[j].tlAddress = msg->DRBnGRanList[j].tlAddress; + cp->DRBnGRanList[j].teId = msg->DRBnGRanList[j].teId; + cp->DRBnGRanList[j].numDlUpParam = msg->DRBnGRanList[j].numDlUpParam; + // Copy DL UP Params List + for (int k = 0; k < msg->DRBnGRanList[j].numDlUpParam; k++) { + cp->DRBnGRanList[j].DlUpParamList[k] = msg->DRBnGRanList[j].DlUpParamList[k]; + } + cp->DRBnGRanList[j].numCellGroups = msg->DRBnGRanList[j].numCellGroups; + // Copy Cell Group List + for (int k = 0; k < msg->DRBnGRanList[j].numCellGroups; k++) { + cp->DRBnGRanList[j].cellGroupList[k] = msg->DRBnGRanList[j].cellGroupList[k]; + } + cp->DRBnGRanList[j].numQosFlow2Setup = msg->DRBnGRanList[j].numQosFlow2Setup; + // Copy QoS Flow To Setup List + for (int k = 0; k < msg->DRBnGRanList[j].numQosFlow2Setup; k++) { + cp->DRBnGRanList[j].qosFlows[k].qfi = msg->DRBnGRanList[j].qosFlows[k].qfi; + cp->DRBnGRanList[j].qosFlows[k].qos_params = msg->DRBnGRanList[j].qosFlows[k].qos_params; + } + } + // Copy DRB to Modify List + for (int j = 0; j < msg->numDRB2Modify; j++) { + cp->DRBnGRanModList[j] = msg->DRBnGRanModList[j]; + } + return true; +} + +/** + * @brief E1AP Bearer Context Setup Request encoding (9.2.2 of 3GPP TS 38.463) + */ +E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg) +{ + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; + initMsg->criticality = E1AP_Criticality_reject; + initMsg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest; + E1AP_BearerContextSetupRequest_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; + /* mandatory */ + /* c1. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = msg->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. Security Information */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_SecurityInformation; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation; + E1AP_SecurityAlgorithm_t *securityAlgorithm = &ieC2->value.choice.SecurityInformation.securityAlgorithm; + E1AP_UPSecuritykey_t *uPSecuritykey = &ieC2->value.choice.SecurityInformation.uPSecuritykey; + securityAlgorithm->cipheringAlgorithm = msg->cipheringAlgorithm; + OCTET_STRING_fromBuf(&uPSecuritykey->encryptionKey, msg->encryptionKey, E1AP_SECURITY_KEY_SIZE); + asn1cCallocOne(securityAlgorithm->integrityProtectionAlgorithm, msg->integrityProtectionAlgorithm); + asn1cCalloc(uPSecuritykey->integrityProtectionKey, protKey); + OCTET_STRING_fromBuf(protKey, msg->integrityProtectionKey, E1AP_SECURITY_KEY_SIZE); + /* mandatory */ + /* c3. UE DL Aggregate Maximum Bit Rate */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_BitRate; + asn_long2INTEGER(&ieC3->value.choice.BitRate, msg->ueDlAggMaxBitRate); + /* mandatory */ + /* c4. Serving PLMN */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC4); + ieC4->id = E1AP_ProtocolIE_ID_id_Serving_PLMN; + ieC4->criticality = E1AP_Criticality_ignore; + ieC4->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity; + const PLMN_ID_t *servingPLMN = &msg->servingPLMNid; + MCC_MNC_TO_PLMNID(servingPLMN->mcc, servingPLMN->mnc, servingPLMN->mnc_digit_length, &ieC4->value.choice.PLMN_Identity); + /* mandatory */ + /* Activity Notification Level */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC5); + ieC5->id = E1AP_ProtocolIE_ID_id_ActivityNotificationLevel; + ieC5->criticality = E1AP_Criticality_reject; + ieC5->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel; + ieC5->value.choice.ActivityNotificationLevel = E1AP_ActivityNotificationLevel_pdu_session; // TODO: Remove hard coding + /* mandatory */ + /* */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC6); + ieC6->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest; + ieC6->criticality = E1AP_Criticality_reject; + ieC6->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest; + ieC6->value.choice.System_BearerContextSetupRequest.present = + E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest; + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = calloc_or_fail(1, sizeof(*msgNGRAN_list)); + ieC6->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest = + (struct E1AP_ProtocolIE_Container *)msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupRequest_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List; + E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; + for (int i = 0; i < msg->numPDUSessions; i++) { + const pdu_session_to_setup_t *pdu_session = &msg->pduSession[i]; + asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Item_t, ieC6_1); + e1_encode_pdu_session_to_setup_item(ieC6_1, pdu_session); + } + return pdu; +} + +/** + * @brief E1AP Bearer Context Setup Request memory management + */ +void free_e1ap_context_setup_request(e1ap_bearer_setup_req_t *msg) +{ + // Do nothing +} + +/** + * @brief E1AP Bearer Context Setup Request decoding + * gNB-CU-CP → gNB-CU-UP (9.2.2.1 of 3GPP TS 38.463) + */ +bool decode_E1_bearer_context_setup_request(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_req_t *out) +{ + DevAssert(pdu != NULL); + + // Check message type + _E1_EQ_CHECK_INT(pdu->present,E1AP_E1AP_PDU_PR_initiatingMessage); + _E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup); + _E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->criticality, E1AP_Criticality_reject); + _E1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest); + + const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; + E1AP_BearerContextSetupRequestIEs_t *ie; + + // Check mandatory IEs first + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_SecurityInformation, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_Serving_PLMN, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_ActivityNotificationLevel, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupRequestIEs_t, ie, in, E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest, true); + + // Loop over all IEs + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + AssertFatal(ie != NULL, "in->protocolIEs.list.array[i] shall not be null"); + switch (ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_SecurityInformation: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation); + E1AP_SecurityInformation_t *SecurityInformation = &ie->value.choice.SecurityInformation; + E1AP_SecurityAlgorithm_t *securityAlgorithm = &SecurityInformation->securityAlgorithm; + E1AP_EncryptionKey_t *encryptionKey = &SecurityInformation->uPSecuritykey.encryptionKey; + E1AP_IntegrityProtectionKey_t *integrityProtectionKey = SecurityInformation->uPSecuritykey.integrityProtectionKey; + + out->cipheringAlgorithm = securityAlgorithm->cipheringAlgorithm; + memcpy(out->encryptionKey, encryptionKey->buf, encryptionKey->size); + if (securityAlgorithm->integrityProtectionAlgorithm) + out->integrityProtectionAlgorithm = *securityAlgorithm->integrityProtectionAlgorithm; + if (integrityProtectionKey) + memcpy(out->integrityProtectionKey, integrityProtectionKey->buf, integrityProtectionKey->size); + break; + + case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_BitRate); + asn_INTEGER2long(&ie->value.choice.BitRate, &out->ueDlAggMaxBitRate); + break; + + case E1AP_ProtocolIE_ID_id_Serving_PLMN: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity); + PLMNID_TO_MCC_MNC(&ie->value.choice.PLMN_Identity, + out->servingPLMNid.mcc, + out->servingPLMNid.mnc, + out->servingPLMNid.mnc_digit_length); + break; + + case E1AP_ProtocolIE_ID_id_ActivityNotificationLevel: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel); + out->activityNotificationLevel = ie->value.choice.ActivityNotificationLevel; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest); + E1AP_System_BearerContextSetupRequest_t *System_BearerContextSetupRequest = + &ie->value.choice.System_BearerContextSetupRequest; + switch (System_BearerContextSetupRequest->present) { + case E1AP_System_BearerContextSetupRequest_PR_NOTHING: + PRINT_ERROR("System Bearer Context Setup Request: no choice present\n"); + break; + case E1AP_System_BearerContextSetupRequest_PR_e_UTRAN_BearerContextSetupRequest: + AssertError(System_BearerContextSetupRequest->present == E1AP_System_BearerContextSetupRequest_PR_e_UTRAN_BearerContextSetupRequest, + return false, "E1AP_System_BearerContextSetupRequest_PR_e_UTRAN_BearerContextSetupRequest in E1 Setup Request not supported"); + break; + case E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest: + // Handle nG-RAN Bearer Context Setup Request + _E1_EQ_CHECK_INT(System_BearerContextSetupRequest->present, + E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest); + AssertFatal(System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest != NULL, + "System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest shall not be null"); + break; + default: + PRINT_ERROR("System Bearer Context Setup Request: No valid choice present.\n"); + break; + } + + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = + (E1AP_ProtocolIE_Container_4932P19_t *)System_BearerContextSetupRequest->choice.nG_RAN_BearerContextSetupRequest; + E1AP_NG_RAN_BearerContextSetupRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; + // NG-RAN + _E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1); // only one RAN is expected + _E1_EQ_CHECK_LONG(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List); + _E1_EQ_CHECK_INT(msgNGRAN->value.present, + E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List); + // PDU Session Resource To Setup List (9.3.3.2 of 3GPP TS 38.463) + E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2SetupList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; + out->numPDUSessions = pdu2SetupList->list.count; + // Loop through all PDU sessions + for (int i = 0; i < pdu2SetupList->list.count; i++) { + pdu_session_to_setup_t *pdu_session = out->pduSession + i; + E1AP_PDU_Session_Resource_To_Setup_Item_t *pdu2Setup = pdu2SetupList->list.array[i]; + if (!e1_decode_pdu_session_to_setup_item(pdu_session, pdu2Setup)) { + PRINT_ERROR("Failed to decode PDU Session to setup item %d\n", i); + return false; + } + } + break; + default: + PRINT_ERROR("Handle for this IE %ld is not implemented (or) invalid IE detected\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief Deep copy function for E1 BEARER CONTEXT SETUP REQUEST + */ +e1ap_bearer_setup_req_t cp_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg) +{ + e1ap_bearer_setup_req_t cp = {0}; + // Copy basi fields + cp = *msg; + strncpy(cp.encryptionKey, msg->encryptionKey, sizeof(cp.encryptionKey)); + strncpy(cp.integrityProtectionKey, msg->integrityProtectionKey, sizeof(cp.integrityProtectionKey)); + // Copy PDU Sessions + for (int i = 0; i < msg->numPDUSessions; i++) + cp_pdu_session_item(&cp.pduSession[i], &msg->pduSession[i]); + return cp; +} + +/** + * @brief E1AP Bearer Context Setup Request equality check + */ +bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1ap_bearer_setup_req_t *b) +{ + // Primitive data types + _E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id); + _E1_EQ_CHECK_LONG(a->cipheringAlgorithm, b->cipheringAlgorithm); + _E1_EQ_CHECK_LONG(a->integrityProtectionAlgorithm, b->integrityProtectionAlgorithm); + _E1_EQ_CHECK_LONG(a->ueDlAggMaxBitRate, b->ueDlAggMaxBitRate); + _E1_EQ_CHECK_INT(a->activityNotificationLevel, b->activityNotificationLevel); + _E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions); + _E1_EQ_CHECK_INT(a->numPDUSessionsMod, b->numPDUSessionsMod); + // PLMN + _E1_EQ_CHECK_INT(a->servingPLMNid.mcc, b->servingPLMNid.mcc); + _E1_EQ_CHECK_INT(a->servingPLMNid.mnc, b->servingPLMNid.mnc); + _E1_EQ_CHECK_INT(a->servingPLMNid.mnc_digit_length, b->servingPLMNid.mnc_digit_length); + // Security Keys + _E1_EQ_CHECK_STR(a->encryptionKey, b->encryptionKey); + _E1_EQ_CHECK_STR(a->integrityProtectionKey, b->integrityProtectionKey); + // PDU Sessions + if (a->numPDUSessions != b->numPDUSessions) + return false; + for (int i = 0; i < a->numPDUSessions; i++) + if (!eq_pdu_session_item(&a->pduSession[i], &b->pduSession[i])) + return false; + if (a->numPDUSessionsMod != b->numPDUSessionsMod) + return false; + for (int i = 0; i < a->numPDUSessionsMod; i++) + if (!eq_pdu_session_item(&a->pduSessionMod[i], &b->pduSessionMod[i])) + return false; + return true; +} + +/* ====================================== + * E1AP Bearer Context Setup Response + * ====================================== */ + +/* PDU Session Resource Setup Item */ + +/** + * @brief Decode an item of the E1 PDU Session Resource Setup List (9.3.3.5 of 3GPP TS 38.463) + */ +static bool e1_decode_pdu_session_setup_item(pdu_session_setup_t *pduSetup, E1AP_PDU_Session_Resource_Setup_Item_t *in) +{ + // PDU Session ID + pduSetup->id = in->pDU_Session_ID; + pduSetup->numDRBSetup = in->dRB_Setup_List_NG_RAN.list.count; + // NG DL UP Transport Layer Information (M) + E1AP_UP_TNL_Information_t *DL_UP_TNL_Info = &in->nG_DL_UP_TNL_Information; + if (DL_UP_TNL_Info->choice.gTPTunnel) { + _E1_EQ_CHECK_INT(DL_UP_TNL_Info->present, E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&DL_UP_TNL_Info->choice.gTPTunnel->transportLayerAddress, pduSetup->tlAddress); + OCTET_STRING_TO_INT32(&DL_UP_TNL_Info->choice.gTPTunnel->gTP_TEID, pduSetup->teId); + } + // DRB Setup List (1..<maxnoofDRBs>) + for (int j = 0; j < in->dRB_Setup_List_NG_RAN.list.count; j++) { + DRB_nGRAN_setup_t *drbSetup = pduSetup->DRBnGRanList + j; + E1AP_DRB_Setup_Item_NG_RAN_t *drb = in->dRB_Setup_List_NG_RAN.list.array[j]; + // DRB ID (M) + drbSetup->id = drb->dRB_ID; + // UL UP Parameters (M) + drbSetup->numUpParam = drb->uL_UP_Transport_Parameters.list.count; + for (int k = 0; k < drb->uL_UP_Transport_Parameters.list.count; k++) { + up_params_t *UL_UP_param = drbSetup->UpParamList + k; + // UP Parameters List (1..<maxnoofUPParameters>) + E1AP_UP_Parameters_Item_t *UL_UP_item = drb->uL_UP_Transport_Parameters.list.array[k]; + // UP Transport Layer Information (M) + DevAssert(UL_UP_item->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); + // GTP Tunnel (M) + E1AP_GTPTunnel_t *gTPTunnel = UL_UP_item->uP_TNL_Information.choice.gTPTunnel; + AssertError(gTPTunnel != NULL, return false, "gTPTunnel information in required in UP Transport Layer Information\n"); + if (gTPTunnel) { + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, UL_UP_param->tlAddress); + OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, UL_UP_param->teId); + } else { + } + // Cell Group ID (M) + UL_UP_param->cell_group_id = UL_UP_item->cell_Group_ID; + } + // Flow Setup List (M) + drbSetup->numQosFlowSetup = drb->flow_Setup_List.list.count; + for (int q = 0; q < drb->flow_Setup_List.list.count; q++) { + qos_flow_setup_t *qosflowSetup = &drbSetup->qosFlows[q]; + E1AP_QoS_Flow_Item_t *in_qosflowSetup = drb->flow_Setup_List.list.array[q]; + qosflowSetup->qfi = in_qosflowSetup->qoS_Flow_Identifier; + } + } + return true; +} + +/** + * @brief Encode an item of the E1 PDU Session Resource Setup List (9.3.3.5 of 3GPP TS 38.463) + */ +static bool e1_encode_pdu_session_setup_item(E1AP_PDU_Session_Resource_Setup_Item_t *item, const pdu_session_setup_t *in) +{ + // PDU Session ID (M) + item->pDU_Session_ID = in->id; + // NG DL UP Transport Layer Information (M) + item->nG_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(item->nG_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(in->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(in->teId, &gTPTunnel->gTP_TEID); + // DRB Setup List (1..<maxnoofDRBs>) + for (const DRB_nGRAN_setup_t *j = in->DRBnGRanList; j < in->DRBnGRanList + in->numDRBSetup; j++) { + asn1cSequenceAdd(item->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1); + // DRB ID (M) + ieC3_1_1->dRB_ID = j->id; + // UL UP Parameters (M) + for (const up_params_t *k = j->UpParamList; k < j->UpParamList + j->numUpParam; k++) { + asn1cSequenceAdd(ieC3_1_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1); + ieC3_1_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); + } + // Flow Setup List(M) + for (const qos_flow_setup_t *k = j->qosFlows; k < j->qosFlows + j->numQosFlowSetup; k++) { + asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); + ieC3_1_1_1->qoS_Flow_Identifier = k->qfi; + } + } + // DRB Failed List (O) + if (in->numDRBFailed > 0) + item->dRB_Failed_List_NG_RAN = calloc_or_fail(1, sizeof(*item->dRB_Failed_List_NG_RAN)); + // DRB Failed Item + for (const DRB_nGRAN_failed_t *j = in->DRBnGRanFailedList; j < in->DRBnGRanFailedList + in->numDRBFailed; j++) { + asn1cSequenceAdd(item->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1); + // DRB ID (M) + ieC3_1_1->dRB_ID = j->id; + // Cause (M) + ieC3_1_1->cause.present = j->cause_type; + switch (ieC3_1_1->cause.present) { + case E1AP_Cause_PR_radioNetwork: + ieC3_1_1->cause.choice.radioNetwork = j->cause; + break; + case E1AP_Cause_PR_transport: + ieC3_1_1->cause.choice.transport = j->cause; + break; + case E1AP_Cause_PR_protocol: + ieC3_1_1->cause.choice.protocol = j->cause; + break; + case E1AP_Cause_PR_misc: + ieC3_1_1->cause.choice.misc = j->cause; + break; + default: + PRINT_ERROR("DRB setup failure cause out of expected range\n"); + break; + } + } + return true; +} + +/** + * @brief Encode E1 Bearer Context Setup Response (9.2.2.2 of 3GPP TS 38.463) + */ +E1AP_E1AP_PDU_t *encode_E1_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *in) +{ + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + // PDU Type + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse; + E1AP_BearerContextSetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; + // gNB-CU-CP UE E1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = in->gNB_cu_cp_ue_id; + // gNB-CU-UP UE E1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_CP_UE_E1AP_ID = in->gNB_cu_up_ue_id; + // Message Type (M) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse; + // CHOICE System: default NG-RAN (M) + ieC3->value.choice.System_BearerContextSetupResponse.present = + E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse; + E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = calloc_or_fail(1, sizeof(*msgNGRAN_list)); + ieC3->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse = + (struct E1AP_ProtocolIE_Container *)msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupResponse_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List; + E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; + for (const pdu_session_setup_t *i = in->pduSession; i < in->pduSession + in->numPDUSessions; i++) { + asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1); + e1_encode_pdu_session_setup_item(ieC3_1, i); + } + return pdu; +} + +/** + * @brief Decode E1 Bearer Context Setup Response (9.2.2.2 of 3GPP TS 38.463) + */ +bool decode_E1_bearer_context_setup_response(const E1AP_E1AP_PDU_t *pdu, e1ap_bearer_setup_resp_t *out) +{ + // Check message type + _E1_EQ_CHECK_INT(pdu->present, E1AP_E1AP_PDU_PR_successfulOutcome); + _E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->procedureCode, E1AP_ProcedureCode_id_bearerContextSetup); + _E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->criticality, E1AP_Criticality_reject); + _E1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse); + + const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; + E1AP_BearerContextSetupResponseIEs_t *ie; + // Check mandatory IEs first + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID, true); + E1AP_LIB_FIND_IE(E1AP_BearerContextSetupResponseIEs_t, ie, in, E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse, true); + // Loop over all IEs + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch (ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + out->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + out->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse: + _E1_EQ_CHECK_INT(ie->value.present, E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse); + switch (ie->value.choice.System_BearerContextSetupResponse.present) { + case E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse: { + E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = + (E1AP_ProtocolIE_Container_4932P22_t *) + ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; + _E1_EQ_CHECK_INT(msgNGRAN_list->list.count, 1); + E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; + _E1_EQ_CHECK_INT(msgNGRAN->id, E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List); + _E1_EQ_CHECK_INT(msgNGRAN->value.present, + E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List); + E1AP_PDU_Session_Resource_Setup_List_t *pduSetupList = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; + out->numPDUSessions = pduSetupList->list.count; + for (int i = 0; i < pduSetupList->list.count; i++) { + pdu_session_setup_t *pduSetup = out->pduSession + i; + E1AP_PDU_Session_Resource_Setup_Item_t *pdu_session = pduSetupList->list.array[i]; + e1_decode_pdu_session_setup_item(pduSetup, pdu_session); + } + } break; + + case E1AP_System_BearerContextSetupResponse_PR_e_UTRAN_BearerContextSetupResponse: + PRINT_ERROR("DRB Setup List E-UTRAN not supported in E1 Setup Response\n"); + return false; + break; + + default: + PRINT_ERROR("Unknown DRB Setup List in E1 Setup Response\n"); + return false; + break; + } + break; + + default: + PRINT_ERROR("Handle for this IE is not implemented (or) invalid IE detected\n"); + return false; + break; + } + } + return true; +} + +/** + * @brief Deep copy function for E1 BEARER CONTEXT SETUP RESPONSE + */ +e1ap_bearer_setup_resp_t cp_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg) +{ + e1ap_bearer_setup_resp_t cp = {0}; + // Copy basic fields + cp = *msg; + // Copy PDU Sessions Setup + for (int i = 0; i < msg->numPDUSessions; i++) { + cp.pduSession[i] = msg->pduSession[i]; + // Copy DRB Setup + for (int j = 0; j < msg->pduSession[i].numDRBSetup; j++) { + cp.pduSession[i].DRBnGRanList[j] = msg->pduSession[i].DRBnGRanList[j]; + for (int k = 0; k < msg->pduSession[i].DRBnGRanList[j].numQosFlowSetup; k++) { + cp.pduSession[i].DRBnGRanList[j].qosFlows[k] = msg->pduSession[i].DRBnGRanList[j].qosFlows[k]; + } + } + cp.pduSession[i].numDRBFailed = msg->pduSession[i].numDRBFailed; + // Copy DRB Failed + for (int j = 0; j < msg->pduSession[i].numDRBFailed; j++) { + cp.pduSession[i].DRBnGRanFailedList[j] = msg->pduSession[i].DRBnGRanFailedList[j]; + } + } + return cp; +} + +/** + * @brief E1AP Bearer Context Setup Response equality check + */ +bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e1ap_bearer_setup_resp_t *b) +{ + // Check basic members + _E1_EQ_CHECK_INT(a->gNB_cu_cp_ue_id, b->gNB_cu_cp_ue_id); + _E1_EQ_CHECK_INT(a->gNB_cu_up_ue_id, b->gNB_cu_up_ue_id); + _E1_EQ_CHECK_INT(a->numPDUSessions, b->numPDUSessions); + // Check PDU Sessions Setup + if (a->numPDUSessions != b->numPDUSessions) + return false; + for (int i = 0; i < a->numPDUSessions; i++) { + const pdu_session_setup_t *ps_a = &a->pduSession[i]; + const pdu_session_setup_t *ps_b = &b->pduSession[i]; + _E1_EQ_CHECK_LONG(ps_a->id, ps_b->id); + _E1_EQ_CHECK_INT(ps_a->tlAddress, ps_b->tlAddress); + _E1_EQ_CHECK_LONG(ps_a->teId, ps_b->teId); + _E1_EQ_CHECK_INT(ps_a->numDRBSetup, ps_b->numDRBSetup); + _E1_EQ_CHECK_INT(ps_a->numDRBFailed, ps_b->numDRBFailed); + // Check DRB Setup + for (int j = 0; j < ps_a->numDRBSetup; j++) { + const DRB_nGRAN_setup_t *drb_a = &ps_a->DRBnGRanList[j]; + const DRB_nGRAN_setup_t *drb_b = &ps_b->DRBnGRanList[j]; + _E1_EQ_CHECK_LONG(drb_a->id, drb_b->id); + _E1_EQ_CHECK_INT(drb_a->numUpParam, drb_b->numUpParam); + _E1_EQ_CHECK_INT(drb_a->numQosFlowSetup, drb_b->numQosFlowSetup); + } + // Check DRB Failed + for (int j = 0; j < ps_a->numDRBFailed; j++) { + const DRB_nGRAN_failed_t *drbf_a = &ps_a->DRBnGRanFailedList[j]; + const DRB_nGRAN_failed_t *drbf_b = &ps_b->DRBnGRanFailedList[j]; + _E1_EQ_CHECK_LONG(drbf_a->id, drbf_b->id); + _E1_EQ_CHECK_LONG(drbf_a->cause_type, drbf_b->cause_type); + _E1_EQ_CHECK_LONG(drbf_a->cause, drbf_b->cause); + } + } + return true; +} + +/** + * @brief E1AP Bearer Context Setup Response memory management + */ +void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg) +{ + // Do nothing (no dynamic allocation) +} diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.h b/openair2/E1AP/lib/e1ap_bearer_context_management.h new file mode 100644 index 0000000000000000000000000000000000000000..95e4cb0e159c93c964dd261a40a86a5af64c4f34 --- /dev/null +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.h @@ -0,0 +1,43 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef E1AP_BEARER_CONTEXT_MANAGEMENT_H_ +#define E1AP_BEARER_CONTEXT_MANAGEMENT_H_ + +#include <stdbool.h> +#include "openair2/COMMON/e1ap_messages_types.h" +#include "common/platform_types.h" + +struct E1AP_E1AP_PDU; + +struct E1AP_E1AP_PDU *encode_E1_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg); +bool decode_E1_bearer_context_setup_request(const struct E1AP_E1AP_PDU *pdu, e1ap_bearer_setup_req_t *out); +e1ap_bearer_setup_req_t cp_bearer_context_setup_request(const e1ap_bearer_setup_req_t *msg); +void free_e1ap_context_setup_request(e1ap_bearer_setup_req_t *msg); +bool eq_bearer_context_setup_request(const e1ap_bearer_setup_req_t *a, const e1ap_bearer_setup_req_t *b); + +struct E1AP_E1AP_PDU *encode_E1_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg); +bool decode_E1_bearer_context_setup_response(const struct E1AP_E1AP_PDU *pdu, e1ap_bearer_setup_resp_t *out); +void free_e1ap_context_setup_response(const e1ap_bearer_setup_resp_t *msg); +e1ap_bearer_setup_resp_t cp_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *msg); +bool eq_bearer_context_setup_response(const e1ap_bearer_setup_resp_t *a, const e1ap_bearer_setup_resp_t *b); + +#endif /* E1AP_BEARER_CONTEXT_MANAGEMENT_H_ */ diff --git a/openair2/E1AP/lib/e1ap_lib_common.h b/openair2/E1AP/lib/e1ap_lib_common.h new file mode 100644 index 0000000000000000000000000000000000000000..f3c6b24da24af5c23228d1a0169215c23e8465e5 --- /dev/null +++ b/openair2/E1AP/lib/e1ap_lib_common.h @@ -0,0 +1,69 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef E1AP_LIB_COMMON_H_ +#define E1AP_LIB_COMMON_H_ + +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include "openair3/UTILS/conversions.h" + +#ifdef ENABLE_TESTS +#define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__); +#else +#define PRINT_ERROR(...) // Do nothing +#endif + +#define _E1_EQ_CHECK_GENERIC(condition, fmt, ...) \ + do { \ + if (!(condition)) { \ + PRINT_ERROR("E1 Equality Check failure: %s:%d: Condition '%s' failed: " fmt " != " fmt "\n", \ + __FILE__, \ + __LINE__, \ + #condition, \ + ##__VA_ARGS__); \ + return false; \ + } \ + } while (0) + +#define _E1_EQ_CHECK_LONG(A, B) _E1_EQ_CHECK_GENERIC(A == B, "%ld", A, B); +#define _E1_EQ_CHECK_INT(A, B) _E1_EQ_CHECK_GENERIC(A == B, "%d", A, B); +#define _E1_EQ_CHECK_STR(A, B) _E1_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B); + +// Macro to look up IE. If mandatory and not found, macro will log an error and return false. +#define E1AP_LIB_FIND_IE(IE_TYPE, ie, container, IE_ID, mandatory) \ + do { \ + ie = NULL; \ + for (int i = 0; i < (container)->protocolIEs.list.count; ++i) { \ + IE_TYPE *current_ie = (container)->protocolIEs.list.array[i]; \ + if (current_ie->id == (IE_ID)) { \ + ie = current_ie; \ + break; \ + } \ + } \ + if (mandatory && ie == NULL) { \ + fprintf(stderr, "%s(): Mandatory element not found: ID" #IE_ID " with type " #IE_TYPE "\n", __func__); \ + return false; \ + } \ + } while (0) + +#endif /* E1AP_LIB_COMMON_H_ */ diff --git a/openair2/E1AP/lib/e1ap_lib_includes.h b/openair2/E1AP/lib/e1ap_lib_includes.h new file mode 100644 index 0000000000000000000000000000000000000000..58da8f6c3001bc2e26824000dc98b9df5537e43a --- /dev/null +++ b/openair2/E1AP/lib/e1ap_lib_includes.h @@ -0,0 +1,57 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef E1AP_LIB_INCLUDES_H_ +#define E1AP_LIB_INCLUDES_H_ + +#include "E1AP_E1AP-PDU.h" +#include "E1AP_ProcedureCode.h" +#include "E1AP_SuccessfulOutcome.h" +#include "E1AP_InitiatingMessage.h" +#include "E1AP_ProtocolIE-ID.h" +#include "E1AP_ProtocolIE-Field.h" +#include "E1AP_UP-TNL-Information.h" +#include "E1AP_DefaultDRB.h" +#include "E1AP_QoS-Characteristics.h" +#include "E1AP_PDU-Session-Resource-To-Setup-Item.h" +#include "E1AP_GTPTunnel.h" +#include "E1AP_DRB-To-Setup-Item-NG-RAN.h" +#include "E1AP_T-ReorderingTimer.h" +#include "E1AP_QoS-Flow-QoS-Parameter-Item.h" +#include "E1AP_Cell-Group-Information-Item.h" +#include "E1AP_Dynamic5QIDescriptor.h" +#include "E1AP_Non-Dynamic5QIDescriptor.h" +// E1 Bearer Context Setup Request +#include "E1AP_BearerContextSetupRequest.h" +#include "E1AP_GNB-CU-CP-E1SetupRequest.h" +#include "E1AP_GNB-CU-UP-E1SetupRequest.h" +#include "E1AP_System-BearerContextSetupRequest.h" +#include "E1AP_MaximumIPdatarate.h" +#include "E1AP_PDU-Session-Type.h" +// E1 Bearer Context Setup Response +#include "E1AP_PDU-Session-Resource-Setup-Item.h" +#include "E1AP_DRB-Setup-Item-NG-RAN.h" +#include "E1AP_UP-Parameters-Item.h" +#include "E1AP_QoS-Flow-Item.h" +#include "E1AP_DRB-Failed-List-NG-RAN.h" +#include "E1AP_DRB-Failed-Item-NG-RAN.h" + +#endif /* E1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/E1AP/tests/CMakeLists.txt b/openair2/E1AP/tests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fcec103f9c171af479954a1075965b80048cffb6 --- /dev/null +++ b/openair2/E1AP/tests/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(e1ap_lib_test e1ap_lib_test.c) +add_dependencies(tests e1ap_lib_test) +add_test(NAME e1ap_lib_test COMMAND e1ap_lib_test) +target_link_libraries(e1ap_lib_test PRIVATE e1ap_lib) +target_link_libraries(e1ap_lib_test PRIVATE asn1_e1ap) +target_include_directories(e1ap_lib_test PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair2/E1AP/tests/e1ap_lib_test.c b/openair2/E1AP/tests/e1ap_lib_test.c new file mode 100644 index 0000000000000000000000000000000000000000..9e3a1035d8227426ed65dc0d0790ba69d2a83019 --- /dev/null +++ b/openair2/E1AP/tests/e1ap_lib_test.c @@ -0,0 +1,225 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file e1ap_lib_test.c + * \brief Unit tests for E1AP libraries + * \author Guido Casati + * \date 2024 + * \version 0.1 + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> + +#include "E1AP/lib/e1ap_bearer_context_management.h" +#include "E1AP/lib/e1ap_lib_includes.h" +#include "common/utils/assertions.h" + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + printf("detected error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +static E1AP_E1AP_PDU_t *e1ap_encode_decode(const E1AP_E1AP_PDU_t *enc_pdu) +{ + // xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, enc_pdu); + + DevAssert(enc_pdu != NULL); + char errbuf[2048]; + size_t errlen = sizeof(errbuf); + int ret = asn_check_constraints(&asn_DEF_E1AP_E1AP_PDU, enc_pdu, errbuf, &errlen); + AssertFatal(ret == 0, "asn_check_constraints() failed: %s\n", errbuf); + + uint8_t msgbuf[16384]; + asn_enc_rval_t enc = aper_encode_to_buffer(&asn_DEF_E1AP_E1AP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf)); + AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n"); + + E1AP_E1AP_PDU_t *dec_pdu = NULL; + asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; + asn_dec_rval_t dec = aper_decode(&st, &asn_DEF_E1AP_E1AP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0); + AssertFatal(dec.code == RC_OK, "aper_decode() failed\n"); + + // xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, dec_pdu); + return dec_pdu; +} + +static void e1ap_msg_free(E1AP_E1AP_PDU_t *pdu) +{ + ASN_STRUCT_FREE(asn_DEF_E1AP_E1AP_PDU, pdu); +} + +/** + * @brief Test E1AP Bearer Context Setup Request encoding/decoding + */ +static void test_bearer_context_setup_request(void) +{ + bearer_context_pdcp_config_t pdcp = { + .discardTimer = E1AP_DiscardTimer_ms10, + .pDCP_Reestablishment = E1AP_PDCP_Reestablishment_true, + .pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_12, + .pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_12, + .reorderingTimer = 10, + .rLC_Mode = E1AP_RLC_Mode_rlc_am, + }; + + bearer_context_sdap_config_t sdap = { + .defaultDRB = 1, + .sDAP_Header_DL = true, + .sDAP_Header_UL = true, + }; + + qos_flow_to_setup_t qos = { + .qfi = 1, + .qos_params.alloc_reten_priority.preemption_capability = E1AP_Pre_emptionCapability_shall_not_trigger_pre_emption, + .qos_params.alloc_reten_priority.preemption_vulnerability = E1AP_Pre_emptionVulnerability_not_pre_emptable, + .qos_params.alloc_reten_priority.priority_level = E1AP_PriorityLevel_highest, + .qos_params.qos_characteristics.non_dynamic.fiveqi = 9, + }; + + security_indication_t security = { + .confidentialityProtectionIndication = E1AP_ConfidentialityProtectionIndication_required, + .integrityProtectionIndication = E1AP_IntegrityProtectionIndication_required, + .maxIPrate = E1AP_MaxIPrate_max_UErate, + }; + + // Step 1: Initialize the E1AP Bearer Context Setup Request + e1ap_bearer_setup_req_t orig = { + .gNB_cu_cp_ue_id = 1234, + .cipheringAlgorithm = 0x01, + .integrityProtectionAlgorithm = 0x01, + .ueDlAggMaxBitRate = 1000000000, + .bearerContextStatus = 0, + .servingPLMNid.mcc = 001, + .servingPLMNid.mnc = 01, + .servingPLMNid.mnc_digit_length = 0x02, + .activityNotificationLevel = ANL_PDU_SESSION, + .numPDUSessions = 1, + .pduSession[0].sessionId = 1, + .pduSession[0].sessionType = E1AP_PDU_Session_Type_ipv4, + .pduSession[0].nssai.sd = 0x01, + .pduSession[0].nssai.sst = 0x01, + .pduSession[0].securityIndication = security, + .pduSession[0].numDRB2Setup = 1, + .pduSession[0].UP_TL_information.tlAddress = 167772161, + .pduSession[0].UP_TL_information.teId = 0x12345, + .pduSession[0].DRBnGRanList[0].id = 1, + .pduSession[0].DRBnGRanList[0].sdap_config = sdap, + .pduSession[0].DRBnGRanList[0].pdcp_config = pdcp, + .pduSession[0].DRBnGRanList[0].id = 1, + .pduSession[0].DRBnGRanList[0].numCellGroups = 1, + .pduSession[0].DRBnGRanList[0].cellGroupList[0] = MCG, + .pduSession[0].DRBnGRanList[0].numQosFlow2Setup = 1, + .pduSession[0].DRBnGRanList[0].qosFlows[0] = qos, + }; + memset(orig.encryptionKey, 0xAB, sizeof(orig.encryptionKey)); + memset(orig.integrityProtectionKey, 0xCD, sizeof(orig.integrityProtectionKey)); + // E1AP encode the original message + E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_request(&orig); + // E1AP decode the encoded message + E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc); + // Free the E1AP encoded message + e1ap_msg_free(enc); + // E1 message decode + e1ap_bearer_setup_req_t decoded = {0}; + bool ret = decode_E1_bearer_context_setup_request(dec, &decoded); + AssertFatal(ret, "decode_E1_bearer_context_setup_request(): could not decode message\n"); + // Free the E1AP decoded message + e1ap_msg_free(dec); + // Equality check original/decoded + ret = eq_bearer_context_setup_request(&orig, &decoded); + AssertFatal(ret, "eq_bearer_context_setup_request(): decoded message doesn't match\n"); + // Free the memory for the decoded message + free_e1ap_context_setup_request(&decoded); + // Deep copy and equality check of the original message + e1ap_bearer_setup_req_t cp = cp_bearer_context_setup_request(&orig); + ret = eq_bearer_context_setup_request(&orig, &cp); + AssertFatal(ret, "eq_bearer_context_setup_request(): copied message doesn't match\n"); + // Free the copied message and original + free_e1ap_context_setup_request(&cp); + free_e1ap_context_setup_request(&orig); +} + +/** + * @brief Test E1AP Bearer Context Setup Response encoding/decoding + */ +static void test_bearer_context_setup_response(void) +{ + // Step 1: Initialize the E1AP Bearer Context Setup Response + e1ap_bearer_setup_resp_t orig = { + .gNB_cu_cp_ue_id = 1234, + .gNB_cu_up_ue_id = 5678, + .numPDUSessions = 1, + .pduSession[0].id = 1, + .pduSession[0].tlAddress = 167772161, + .pduSession[0].teId = 0x12345, + .pduSession[0].numDRBSetup = 1, + .pduSession[0].numDRBFailed = 0, + .pduSession[0].DRBnGRanList[0].id = 1, + .pduSession[0].DRBnGRanList[0].numUpParam = 1, + .pduSession[0].DRBnGRanList[0].numQosFlowSetup = 1, + .pduSession[0].DRBnGRanList[0].qosFlows[0].qfi = 1, + .pduSession[0].DRBnGRanList[0].UpParamList[0].cell_group_id = MCG, + .pduSession[0].DRBnGRanList[0].UpParamList[0].teId = 0x34345, + .pduSession[0].DRBnGRanList[0].UpParamList[0].tlAddress = 167772161, + }; + // E1AP encode the original message + E1AP_E1AP_PDU_t *enc = encode_E1_bearer_context_setup_response(&orig); + + // E1AP decode the encoded message + E1AP_E1AP_PDU_t *dec = e1ap_encode_decode(enc); + + // Free the E1AP encoded message + e1ap_msg_free(enc); + + // E1 message decode + e1ap_bearer_setup_resp_t decoded = {0}; + bool ret = decode_E1_bearer_context_setup_response(dec, &decoded); + AssertFatal(ret, "decode_E1_bearer_context_setup_response(): could not decode message\n"); + + // Free the E1AP decoded message + e1ap_msg_free(dec); + + // Equality check original/decoded + ret = eq_bearer_context_setup_response(&orig, &decoded); + AssertFatal(ret, "eq_bearer_context_setup_response(): decoded message doesn't match\n"); + + // Free the memory for the decoded message + free_e1ap_context_setup_response(&decoded); + + // Deep copy and equality check of the original message + e1ap_bearer_setup_resp_t cp = cp_bearer_context_setup_response(&orig); + ret = eq_bearer_context_setup_response(&orig, &cp); + AssertFatal(ret, "eq_bearer_context_setup_response(): copied message doesn't match\n"); + + // Free the copied message and original + free_e1ap_context_setup_response(&cp); + free_e1ap_context_setup_response(&orig); +} + +int main() +{ + // E1 Bearer Context Setup + test_bearer_context_setup_request(); + test_bearer_context_setup_response(); + return 0; +} diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt index cb8d8b9712fea03ad2191a6353d9d2a979ba14c7..0c6137dc306d8898d5aa75df728a7e6aa678f170 100644 --- a/openair2/F1AP/lib/CMakeLists.txt +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -8,3 +8,7 @@ target_include_directories(f1ap_lib PUBLIC ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) + +if(ENABLE_TESTS) + target_compile_definitions(f1ap_lib PRIVATE ENABLE_TESTS) +endif() diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index fe079faa4c730c459aea9f94785248389306bb74..f067985a2daa320f3d5688a45a4afbb752b6f614 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -72,7 +72,7 @@ static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, /** * @brief F1AP Setup Request memory management */ -static void free_f1ap_cell(const f1ap_served_cell_info_t *info, const f1ap_gnb_du_system_info_t *sys_info) +void free_f1ap_cell(const f1ap_served_cell_info_t *info, const f1ap_gnb_du_system_info_t *sys_info) { if (sys_info) { free(sys_info->mib); @@ -83,72 +83,76 @@ static void free_f1ap_cell(const f1ap_served_cell_info_t *info, const f1ap_gnb_d free(info->tac); } +/** + * @brief Encode NR Frequency Info (9.3.1.17 of 3GPP TS 38.473) + */ +static F1AP_NRFreqInfo_t encode_frequency_info(const f1ap_nr_frequency_info_t *info) +{ + F1AP_NRFreqInfo_t nrFreqInfo = {0}; + // NR ARFCN + nrFreqInfo.nRARFCN = info->arfcn; + int num_bands = 1; + // Frequency Band List + for (int j = 0; j < num_bands; j++) { + asn1cSequenceAdd(nrFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + // NR Frequency Band + nr_freqBandNrItem->freqBandIndicatorNr = info->band; + } + return nrFreqInfo; +} + +/** + * @brief Encode Transmission Bandwidth (9.3.1.15 of 3GPP TS 38.473) + */ +static F1AP_Transmission_Bandwidth_t encode_tx_bandwidth(const f1ap_transmission_bandwidth_t *info) +{ + F1AP_Transmission_Bandwidth_t tb = {0}; + tb.nRSCS = info->scs; + tb.nRNRB = to_NRNRB(info->nrb); + return tb; +} + /** * @brief Encoding of Served Cell Information (9.3.1.10 of 3GPP TS 38.473) */ static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_cell_info_t *c) { F1AP_Served_Cell_Information_t scell_info = {0}; - // NR CGI + // NR CGI (M) MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &(scell_info.nRCGI.pLMN_Identity)); NR_CELL_ID_TO_BIT_STRING(c->nr_cellid, &(scell_info.nRCGI.nRCellIdentity)); - // NR PCI + // NR PCI (M) scell_info.nRPCI = c->nr_pci; // int 0..1007 - // 5GS TAC + // 5GS TAC (O) if (c->tac != NULL) { uint32_t tac = htonl(*c->tac); asn1cCalloc(scell_info.fiveGS_TAC, netOrder); OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3); } - // Served PLMNs + // Served PLMNs 1..<maxnoofBPLMNs> asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); + // PLMN Identity (M) MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); - // NR-Mode-Info + // NR-Mode-Info (M) F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info; - if (c->mode == F1AP_MODE_FDD) { // FDD + if (c->mode == F1AP_MODE_FDD) { // FDD Info const f1ap_fdd_info_t *fdd = &c->fdd; nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); - /* FDD.1.1 UL NRFreqInfo ARFCN */ - fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; - /* FDD.1.3 freqBandListNr */ - int ul_band = 1; - for (int j = 0; j < ul_band; j++) { - asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band; - } - /* FDD.2.1 DL NRFreqInfo ARFCN */ - fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; - /* FDD.2.3 freqBandListNr */ - int dl_bands = 1; - for (int j = 0; j < dl_bands; j++) { - asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.2.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band; - } // for FDD : DL freq_Bands - /* FDD.3 UL Transmission Bandwidth */ - fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs; - fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb); - /* FDD.4 DL Transmission Bandwidth */ - fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs; - fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb); - } else if (c->mode == F1AP_MODE_TDD) { + // NR Frequency Info + fDD_Info->uL_NRFreqInfo = encode_frequency_info(&fdd->ul_freqinfo); + fDD_Info->dL_NRFreqInfo = encode_frequency_info(&fdd->dl_freqinfo); + // Transmission Bandwidth + fDD_Info->uL_Transmission_Bandwidth = encode_tx_bandwidth(&fdd->ul_tbw); + fDD_Info->dL_Transmission_Bandwidth = encode_tx_bandwidth(&fdd->dl_tbw); + } else if (c->mode == F1AP_MODE_TDD) { // TDD Info const f1ap_tdd_info_t *tdd = &c->tdd; nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); - /* TDD.1.1 nRFreqInfo ARFCN */ - tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; - /* TDD.1.3 freqBandListNr */ - int bands = 1; - for (int j = 0; j < bands; j++) { - asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* TDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band; - } - /* TDD.2 transmission_Bandwidth */ - tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs; - tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb); + // NR Frequency Info + tDD_Info->nRFreqInfo = encode_frequency_info(&tdd->freqinfo); + // Transmission Bandwidth + tDD_Info->transmission_Bandwidth = encode_tx_bandwidth(&tdd->tbw); } else { AssertFatal(false, "unknown duplex mode %d\n", c->mode); } @@ -530,16 +534,16 @@ bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out return true; } -static void copy_f1ap_served_cell_info(f1ap_served_cell_info_t *dest, const f1ap_served_cell_info_t *src) { +void copy_f1ap_served_cell_info(f1ap_served_cell_info_t *dest, const f1ap_served_cell_info_t *src) +{ + // shallow copy *dest = *src; - dest->mode = src->mode; - dest->tdd = src->tdd; - dest->fdd = src->fdd; - dest->plmn = src->plmn; + // tac if (src->tac) { dest->tac = malloc_or_fail(sizeof(*dest->tac)); *dest->tac = *src->tac; } + // measurement timing config if (src->measurement_timing_config_len) { dest->measurement_timing_config = calloc_or_fail(src->measurement_timing_config_len, sizeof(*dest->measurement_timing_config)); memcpy(dest->measurement_timing_config, src->measurement_timing_config, src->measurement_timing_config_len); @@ -955,7 +959,7 @@ bool decode_f1ap_setup_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_failure_t */ bool eq_f1ap_setup_failure(const f1ap_setup_failure_t *a, const f1ap_setup_failure_t *b) { - _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); return true; } diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h index bdceee9a61845647a42be348dede126c250e8595..e483a743015447c59361121df9ebeaeeac1e1f68 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.h +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -32,6 +32,8 @@ bool decode_f1ap_setup_request(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_req_t f1ap_setup_req_t cp_f1ap_setup_request(const f1ap_setup_req_t *msg); bool eq_f1ap_setup_request(const f1ap_setup_req_t *a, const f1ap_setup_req_t *b); void free_f1ap_setup_request(const f1ap_setup_req_t *msg); +void copy_f1ap_served_cell_info(f1ap_served_cell_info_t *a, const f1ap_served_cell_info_t *b); +void free_f1ap_cell(const f1ap_served_cell_info_t *info, const f1ap_gnb_du_system_info_t *sys_info); /* F1 Setup Response */ struct F1AP_F1AP_PDU *encode_f1ap_setup_response(const f1ap_setup_resp_t *msg); diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 71d2bea95335f50eab418064e4db5107891d7814..4c75aa944e3353c94414a44062e79e0fc506a0c8 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -119,9 +119,8 @@ static void test_initial_ul_rrc_message_transfer(void) */ static void test_dl_rrc_message_transfer(void) { - uint8_t *rrc = calloc(strlen("RRC Container") + 1, sizeof(uint8_t)); - uint32_t *old_gNB_DU_ue_id = calloc(1, sizeof(uint32_t)); - AssertFatal(rrc != NULL && old_gNB_DU_ue_id != NULL, "out of memory\n"); + uint8_t *rrc = calloc_or_fail(strlen("RRC Container") + 1, sizeof(*rrc)); + uint32_t *old_gNB_DU_ue_id = calloc_or_fail(1, sizeof(*old_gNB_DU_ue_id)); memcpy((void *)rrc, "RRC Container", strlen("RRC Container") + 1); f1ap_dl_rrc_message_t orig = { @@ -194,12 +193,11 @@ static void test_f1ap_setup_request(void) { /* allocate memory */ /* gNB_DU_name */ - uint8_t *gNB_DU_name = calloc(strlen("OAI DU") + 1, sizeof(uint8_t)); - AssertFatal(gNB_DU_name != NULL, "out of memory\n"); + uint8_t *gNB_DU_name = calloc_or_fail(strlen("OAI DU") + 1, sizeof(*gNB_DU_name)); memcpy(gNB_DU_name, "OAI DU", strlen("OAI DU") + 1); /* sys_info */ - uint8_t *mib = calloc(3, sizeof(uint8_t)); - uint8_t *sib1 = calloc(3, sizeof(uint8_t)); + uint8_t *mib = calloc_or_fail(3, sizeof(*mib)); + uint8_t *sib1 = calloc_or_fail(3, sizeof(*sib1)); f1ap_gnb_du_system_info_t sys_info = { .mib_length = 3, .mib = mib, @@ -208,11 +206,10 @@ static void test_f1ap_setup_request(void) }; /* measurement_timing_information */ int measurement_timing_config_len = strlen("0") + 1; - uint8_t *measurement_timing_information = calloc(measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(measurement_timing_information != NULL, "out of memory\n"); + uint8_t *measurement_timing_information = calloc_or_fail(measurement_timing_config_len, sizeof(*measurement_timing_information)); memcpy((void *)measurement_timing_information, "0", measurement_timing_config_len); /* TAC */ - uint32_t *tac = calloc(1, sizeof(uint32_t)); + uint32_t *tac = calloc_or_fail(1, sizeof(*tac)); /* * TDD test */ @@ -245,7 +242,7 @@ static void test_f1ap_setup_request(void) .rrc_ver[2] = 56, .cell[0].info = info, }; - orig.cell[0].sys_info = calloc(1, sizeof(*orig.cell[0].sys_info)); + orig.cell[0].sys_info = calloc_or_fail(1, sizeof(*orig.cell[0].sys_info)); *orig.cell[0].sys_info = sys_info; // encode F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_request(&orig); @@ -311,8 +308,7 @@ static void test_f1ap_setup_response(void) /* gNB_CU_name */ char *cu_name = "OAI-CU"; int len = strlen(cu_name) + 1; - uint8_t *gNB_CU_name = calloc(len, sizeof(uint8_t)); - AssertFatal(gNB_CU_name != NULL, "out of memory\n"); + uint8_t *gNB_CU_name = calloc_or_fail(len, sizeof(*gNB_CU_name)); memcpy((void *)gNB_CU_name, cu_name, len); /* create message */ f1ap_setup_resp_t orig = { @@ -393,8 +389,8 @@ static void test_f1ap_setup_failure(void) static void test_f1ap_du_configuration_update(void) { /* sys_info */ - uint8_t *mib = calloc(3, sizeof(uint8_t)); - uint8_t *sib1 = calloc(3, sizeof(uint8_t)); + uint8_t *mib = calloc_or_fail(3, sizeof(*mib)); + uint8_t *sib1 = calloc_or_fail(3, sizeof(*sib1)); f1ap_gnb_du_system_info_t sys_info = { .mib_length = 3, .mib = mib, @@ -404,12 +400,10 @@ static void test_f1ap_du_configuration_update(void) /* measurement_timing_information modify */ char *s = "1"; int measurement_timing_config_len = strlen(s) + 1; - uint8_t *measurement_timing_config_mod = calloc(measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(measurement_timing_config_mod != NULL, "out of memory\n"); + uint8_t *measurement_timing_config_mod = calloc_or_fail(measurement_timing_config_len, sizeof(*measurement_timing_config_mod)); memcpy((void *)measurement_timing_config_mod, s, measurement_timing_config_len); /* TAC modify */ - uint32_t *tac = calloc(1, sizeof(uint32_t)); - AssertFatal(tac != NULL, "out of memory\n"); + uint32_t *tac = calloc_or_fail(1, sizeof(*tac)); *tac = 456; /* info modify */ f1ap_served_cell_info_t info = { @@ -437,8 +431,7 @@ static void test_f1ap_du_configuration_update(void) .cell_to_delete[0].plmn.mnc = 1, .cell_to_delete[0].plmn.mnc_digit_length = 3, }; - orig.cell_to_modify[0].sys_info = calloc(1, sizeof(*orig.cell_to_modify[0].sys_info)); - AssertFatal(orig.cell_to_modify[0].sys_info != NULL, "out of memory\n"); + orig.cell_to_modify[0].sys_info = calloc_or_fail(1, sizeof(*orig.cell_to_modify[0].sys_info)); *orig.cell_to_modify[0].sys_info = sys_info; F1AP_F1AP_PDU_t *f1enc = encode_f1ap_du_configuration_update(&orig); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 4e591b6a7ab99cfc0bcb2e106524fd49f55701e9..befe1ec3c785415caa59b733d2aa2728551ecf6e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1006,18 +1006,11 @@ static bool get_feasible_msg3_tda(frame_type_t frame_type, return false; } -static void nr_get_Msg3alloc(module_id_t module_id, - int CC_id, - NR_ServingCellConfigCommon_t *scc, - sub_frame_t current_slot, - frame_t current_frame, - NR_RA_t *ra) +static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, frame_t current_frame, NR_RA_t *ra) { - // msg3 is scheduled in mixed slot in the following TDD period DevAssert(ra->Msg3_tda_id >= 0 && ra->Msg3_tda_id < 16); uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes - gNB_MAC_INST *mac = RC.nrmac[module_id]; NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; @@ -1056,7 +1049,10 @@ static void nr_get_Msg3alloc(module_id_t module_id, rbSize = 0; while (rbStart < bwpSize && (vrb_map_UL[rbStart + bwpStart] & SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nbSymb))) rbStart++; - AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n"); + if (rbStart + msg3_nb_rb > bwpSize) { + LOG_D(NR_MAC, "No space to allocate Msg 3\n"); + return false; + } while (rbStart + rbSize < bwpSize && !(vrb_map_UL[rbStart + bwpStart + rbSize] & SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nbSymb)) && rbSize < msg3_nb_rb) rbSize++; @@ -1064,6 +1060,7 @@ static void nr_get_Msg3alloc(module_id_t module_id, ra->msg3_nb_rb = msg3_nb_rb; ra->msg3_first_rb = rbStart; ra->msg3_bwp_start = bwpStart; + return true; } static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, @@ -1493,6 +1490,13 @@ static void nr_generate_Msg2(module_id_t module_idP, return; } + bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, ra); + if (!msg3_ret) { + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + return; + } + LOG_D(NR_MAC, "Msg2 startSymbolIndex.nrOfSymbols %d.%d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols); // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially @@ -1659,7 +1663,6 @@ static void nr_generate_Msg2(module_id_t module_idP, nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; // Program UL processing for Msg3 - nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra); nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2) @@ -2426,7 +2429,8 @@ void nr_schedule_RA(module_id_t module_idP, NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { NR_RA_t *ra = &cc->ra[i]; - LOG_D(NR_MAC, "RA[state:%d]\n", ra->ra_state); + if (ra->ra_state != nrRA_gNB_IDLE) + LOG_D(NR_MAC, "RA[%d] frame.slot %d.%d state: %d\n", i, frameP, slotP, ra->ra_state); // Check RA Contention Resolution timer if (ra->ra_type == RA_4_STEP && ra->ra_state >= nrRA_WAIT_Msg3) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 8a38c6e66d234ef359cdf7b621f708b9dda113c8..e161fa50ab32c2db42cb40a24f41929a0952877b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -585,38 +585,36 @@ void handle_nr_ul_harq(const int CC_idP, const nfapi_nr_crc_t *crc_pdu) { gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; - NR_SCHED_LOCK(&nrmac->sched_lock); - - NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); - bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(nrmac, CC_idP, frame, slot, crc_pdu->rnti); + if (nrmac->radio_config.disable_harq) { + LOG_D(NR_MAC, "skipping UL feedback handling as HARQ is disabled\n"); + return; + } - if (!UE || UE_waiting_CFRA_msg3 == true) { - LOG_D(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti); - for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i]; - if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == crc_pdu->rnti) { - NR_SCHED_UNLOCK(&nrmac->sched_lock); - return; - } + NR_SCHED_LOCK(&nrmac->sched_lock); + for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { + NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i]; + // if we find any ongoing RA that has already scheduled MSG3 + // and it is expecting its reception in current frame and slot with matching RNTI + // we can exit the function (no HARQ involved) + if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) { + LOG_D(NR_MAC, "UL for rnti %04x in RA (MSG3), no need to process HARQ\n", crc_pdu->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return; } - NR_SCHED_UNLOCK(&nrmac->sched_lock); - LOG_D(NR_MAC, "no RA proc for RNTI 0x%04x in Msg3/MsgA-PUSCH\n", crc_pdu->rnti); - return; } - if (nrmac->radio_config.disable_harq) { - LOG_D(NR_MAC, "skipping UL feedback handling as HARQ is disabled\n"); + + NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); + if (!UE) { NR_SCHED_UNLOCK(&nrmac->sched_lock); + LOG_E(NR_MAC, "Couldn't identify UE connected with current UL HARQ process\n"); return; } + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; int8_t harq_pid = sched_ctrl->feedback_ul_harq.head; LOG_D(NR_MAC, "Comparing crc_pdu->harq_id vs feedback harq_pid = %d %d\n",crc_pdu->harq_id, harq_pid); while (crc_pdu->harq_id != harq_pid || harq_pid < 0) { - LOG_W(NR_MAC, - "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x (ignore this warning for RA)\n", - crc_pdu->harq_id, - harq_pid, - crc_pdu->rnti); + LOG_W(NR_MAC, "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x\n", crc_pdu->harq_id, harq_pid, crc_pdu->rnti); if (harq_pid < 0) { NR_SCHED_UNLOCK(&nrmac->sched_lock); return; @@ -727,6 +725,10 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, timing_advance, sduP, rssi); + if (harq_pid < 0) { + LOG_E(NR_MAC, "UE %04x received ULSCH when feedback UL HARQ %d (unexpected ULSCH transmission)\n", rntiP, harq_pid); + return; + } // if not missed detection (10dB threshold for now) if (rssi > 0) { @@ -1403,10 +1405,10 @@ void handle_nr_srs_measurements(const module_id_t module_id, const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold; uint16_t *ulprbbl = nr_mac->ulprbbl; - uint16_t num_rbs = nr_srs_bf_report.prg_size * nr_srs_bf_report.prgs.num_prgs; + uint16_t num_rbs = nr_srs_bf_report.prg_size * nr_srs_bf_report.reported_symbol_list[0].num_prgs; memset(ulprbbl, 0, num_rbs * sizeof(uint16_t)); for (int rb = 0; rb < num_rbs; rb++) { - int snr = (nr_srs_bf_report.prgs.prg_list[rb / nr_srs_bf_report.prg_size].rb_snr >> 1) - 64; + int snr = (nr_srs_bf_report.reported_symbol_list[0].prg_list[rb / nr_srs_bf_report.prg_size].rb_snr >> 1) - 64; if (snr < wide_band_snr_dB - ul_prbblack_SNR_threshold) { ulprbbl[rb] = 0x3FFF; // all symbols taken } diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index ab2756c3cdbb4f0dbdf03bcefebf11f0aa861d67..1d3394e7888f5fbd0e0cbd1c3d2d669716a733f1 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -88,11 +88,12 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); *pdcp_config->t_Reordering = drb->pdcp_config.reorderingTimer; pdcp_config->ext1 = NULL; - if (pdu->integrityProtectionIndication == 0 || // Required - pdu->integrityProtectionIndication == 1) { // Preferred - asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + const security_indication_t *sec = &pdu->securityIndication; + if (sec->integrityProtectionIndication == SECURITY_REQUIRED || + sec->integrityProtectionIndication == SECURITY_PREFERRED) { + asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); } - if (pdu->confidentialityProtectionIndication == 2) { // Not Needed + if (sec->confidentialityProtectionIndication == SECURITY_NOT_NEEDED) { asn1cCalloc(pdcp_config->ext1, ext1); asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); } @@ -188,8 +189,8 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) req_drb->id, req_pdu->sessionId, qfi, - req_pdu->tlAddress, - req_pdu->teId, + req_pdu->UP_TL_information.tlAddress, + req_pdu->UP_TL_information.teId, nr_pdcp_data_req_drb, sdap_data_req, &resp_n3); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index fd392ceae8d39be788bddccdc210640b5dfd0af8..507e4191d0e0721b0bdc9137b9654c0ebd292397 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -146,20 +146,17 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) static bool crc_sfn_slot_matcher(void *wanted, void *candidate) { - nfapi_p7_message_header_t *msg = candidate; - int sfn_sf = *(int*)wanted; + nfapi_nr_p7_message_header_t *msg = candidate; + int sfn_sf = *(int *)wanted; - switch (msg->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - { + switch (msg->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: { nfapi_nr_crc_indication_t *ind = candidate; return NFAPI_SFNSLOT2SFN(sfn_sf) == ind->sfn && NFAPI_SFNSLOT2SLOT(sfn_sf) == ind->slot; } default: LOG_E(NR_MAC, "sfn_slot_match bad ID: %d\n", msg->message_id); - } return false; } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 798ec5ce4e8851f49a3e95731fcb5031382288de..e70d7b66ebaa1a39dd2fb8da5d4a7ee36e111d6b 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -56,6 +56,7 @@ #include "utils.h" #include "xer_encoder.h" +#define PUCCH2_SIZE 8 const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; static NR_BWP_t clone_generic_parameters(const NR_BWP_t *gp) @@ -187,6 +188,24 @@ static NR_PUSCH_Config_t *clone_pusch_config(const NR_PUSCH_Config_t *pc) return clone; } +static int get_nb_pucch2_per_slot(const NR_ServingCellConfigCommon_t *scc, int bwp_size) +{ + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; + int ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0) : n_slots_frame; + int n_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; + int max_meas_report_period = 320; // slots + int max_csi_reports = MAX_MOBILES_PER_GNB << 1; // 2 reports per UE (RSRP and RI-PMI-CQI) + int available_report_occasions = max_meas_report_period * ul_slots_period / n_slots_period; + int nb_pucch2 = (max_csi_reports / (available_report_occasions + 1)) + 1; + // in current implementation we need (nb_pucch2 * PUCCH2_SIZE) prbs for PUCCH2 + // and MAX_MOBILES_PER_GNB prbs for PUCCH1 + AssertFatal((nb_pucch2 * PUCCH2_SIZE) + MAX_MOBILES_PER_GNB <= bwp_size, + "Cannot allocate all required PUCCH resources for max number of %d UEs in BWP with %d PRBs\n", + MAX_MOBILES_PER_GNB, bwp_size); + return nb_pucch2; +} + NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { @@ -295,7 +314,7 @@ static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) static int set_ideal_period(const int n_slots_period, const int n_ul_slots_period) { - return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE + return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE (RSRP and RI-PMI-CQI) } static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, @@ -307,7 +326,6 @@ static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset)); // TODO ideal period to be set according to estimation by the gNB on how fast the channel changes const int offset = nb_slots_per_period * id; - if (ideal_period < 5) { nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots4; nzpcsi0->periodicityAndOffset->choice.slots4 = offset; @@ -974,7 +992,11 @@ static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedbac } // PUCCH resource set 0 for configuration with O_uci <= 2 bits and/or a positive or negative SR (section 9.2.1 of 38.213) -static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, int uid, int curr_bwp, const NR_UE_NR_Capability_t *uecap) +static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, + int uid, + int curr_bwp, + int num_pucch2, + const NR_UE_NR_Capability_t *uecap) { NR_PUCCH_ResourceSet_t *pucchresset = calloc(1,sizeof(*pucchresset)); pucchresset->pucch_ResourceSetId = 0; @@ -990,7 +1012,7 @@ static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, int uid, int c NR_PUCCH_Resource_t *pucchres0 = calloc(1,sizeof(*pucchres0)); pucchres0->pucch_ResourceId = *pucchid; - pucchres0->startingPRB = 8 + uid; + pucchres0->startingPRB = (PUCCH2_SIZE * num_pucch2) + uid; AssertFatal(pucchres0->startingPRB < curr_bwp, "Not enough resources in current BWP (size %d) to allocate uid %d\n", curr_bwp, uid); pucchres0->intraSlotFrequencyHopping = NULL; pucchres0->secondHopPRB = NULL; @@ -1006,7 +1028,10 @@ static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, int uid, int c // PUCCH resource set 1 for configuration with O_uci > 2 bits (currently format2) -static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config, const NR_UE_NR_Capability_t *uecap) +static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config, + int uid, + int num_pucch2, + const NR_UE_NR_Capability_t *uecap) { NR_PUCCH_ResourceSet_t *pucchresset=calloc(1,sizeof(*pucchresset)); pucchresset->pucch_ResourceSetId = 1; @@ -1022,12 +1047,12 @@ static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config, const NR_UE_NR NR_PUCCH_Resource_t *pucchres2 = calloc(1,sizeof(*pucchres2)); pucchres2->pucch_ResourceId = *pucchressetid; - pucchres2->startingPRB = 0; + pucchres2->startingPRB = PUCCH2_SIZE * (uid % num_pucch2); pucchres2->intraSlotFrequencyHopping = NULL; pucchres2->secondHopPRB = NULL; pucchres2->format.present = NR_PUCCH_Resource__format_PR_format2; pucchres2->format.choice.format2 = calloc(1,sizeof(*pucchres2->format.choice.format2)); - pucchres2->format.choice.format2->nrofPRBs = 8; + pucchres2->format.choice.format2->nrofPRBs = PUCCH2_SIZE; pucchres2->format.choice.format2->nrofSymbols = 1; pucchres2->format.choice.format2->startingSymbolIndex = 13; asn1cSeqAdd(&pucch_Config->resourceToAddModList->list,pucchres2); @@ -1501,8 +1526,9 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, pucch_Config->resourceSetToReleaseList = NULL; pucch_Config->resourceToAddModList = calloc(1,sizeof(*pucch_Config->resourceToAddModList)); pucch_Config->resourceToReleaseList = NULL; - config_pucch_resset0(pucch_Config, uid, curr_bwp, uecap); - config_pucch_resset1(pucch_Config, uecap); + int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); + config_pucch_resset0(pucch_Config, uid, curr_bwp, num_pucch2, uecap); + config_pucch_resset1(pucch_Config, uid, num_pucch2, uecap); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing); set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, ubwp->bwp_Common->genericParameters.subcarrierSpacing); @@ -1545,7 +1571,11 @@ static void set_phr_config(NR_MAC_CellGroupConfig_t *mac_CellGroupConfig) mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB1; } -static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, NR_CSI_ReportConfig_t *csirep, int uid, bool is_rsrp) +static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, + NR_CSI_ReportConfig_t *csirep, + int uid, + int curr_bwp, + bool is_rsrp) { const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; @@ -1553,7 +1583,8 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, NR const int n_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; const int ideal_period = set_ideal_period(n_slots_period, n_ul_slots_period); const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; - const int idx = (uid << 1) + is_rsrp; + const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); + const int idx = (uid * 2 / num_pucch2) + is_rsrp; const int offset = first_ul_slot_period + idx % n_ul_slots_period + (idx / n_ul_slots_period) * n_slots_period; AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n"); @@ -1703,7 +1734,8 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, const nr_pdsch_AntennaPorts_t *antennaports, const int max_layers, int rep_id, - int uid) + int uid, + int curr_bwp) { int resource_id = -1; int im_id = -1; @@ -1732,7 +1764,7 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, csirep->nzp_CSI_RS_ResourcesForInterference = NULL; csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic)); - set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, false); + set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, false); asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires); csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI; csirep->reportQuantity.choice.cri_RI_PMI_CQI = (NULL_t)0; @@ -1767,6 +1799,7 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, int do_csi, // if rsrp is based on CSI or SSB int rep_id, int uid, + int curr_bwp, int num_antenna_ports) { int resource_id = -1; @@ -1793,7 +1826,7 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, csirep->nzp_CSI_RS_ResourcesForInterference = NULL; csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic)); - set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, true); + set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, true); asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires); if (do_csi && num_antenna_ports < 4) { csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP; @@ -2848,8 +2881,9 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, pucch_Config->resourceSetToReleaseList = NULL; pucch_Config->resourceToAddModList = calloc(1, sizeof(*pucch_Config->resourceToAddModList)); pucch_Config->resourceToReleaseList = NULL; - config_pucch_resset0(pucch_Config, uid, curr_bwp, NULL); - config_pucch_resset1(pucch_Config, NULL); + int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); + config_pucch_resset0(pucch_Config, uid, curr_bwp, num_pucch2, NULL); + config_pucch_resset1(pucch_Config, uid, num_pucch2, NULL); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); initialUplinkBWP->pusch_Config = config_pusch(NULL, configuration->use_deltaMCS, scc, NULL); @@ -3060,12 +3094,13 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, &configuration->pdsch_AntennaPorts, *pdsch_servingcellconfig->ext1->maxMIMO_Layers, bwp_id, - uid); + uid, + curr_bwp); } NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp)); pucchrsrp->uplinkBandwidthPartId = bwp_id; pucchrsrp->pucch_Resource = pucch_Resource; - config_rsrp_meas_report(csi_MeasConfig, scc, pucchrsrp, configuration->do_CSIRS, bwp_id + 10, uid, pdsch_AntennaPorts); + config_rsrp_meas_report(csi_MeasConfig, scc, pucchrsrp, configuration->do_CSIRS, bwp_id + 10, uid, curr_bwp, pdsch_AntennaPorts); } fill_harq_IEs(SpCellConfig->spCellConfigDedicated, configuration->num_dlharq, configuration->num_ulharq); @@ -3561,8 +3596,23 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC pucchcsires1->uplinkBandwidthPartId = bwp->bwp_Id; pucchcsires1->pucch_Resource = 2; - config_csi_meas_report(csi_MeasConfig, servingcellconfigcommon, pucchcsires1, bwp->bwp_Dedicated->pdsch_Config, pdschap, *pdsch_servingcellconfig->ext1->maxMIMO_Layers, bwp->bwp_Id, uid); - config_rsrp_meas_report(csi_MeasConfig, servingcellconfigcommon, pucchcsires1, do_csirs, bwp->bwp_Id + 10, uid, dl_antenna_ports); + config_csi_meas_report(csi_MeasConfig, + servingcellconfigcommon, + pucchcsires1, + bwp->bwp_Dedicated->pdsch_Config, + pdschap, + *pdsch_servingcellconfig->ext1->maxMIMO_Layers, + bwp->bwp_Id, + uid, + curr_bwp); + config_rsrp_meas_report(csi_MeasConfig, + servingcellconfigcommon, + pucchcsires1, + do_csirs, + bwp->bwp_Id + 10, + uid, + curr_bwp, + dl_antenna_ports); } secondaryCellGroup->spCellConfig->spCellConfigDedicated->sCellDeactivationTimer = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig = NULL; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e94358f274f5a1e4c8745f7ae6d182e5b1094e9f..e8c7fcdc2cc2e9de4d4b8f13c405f87cbc4c635e 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -94,6 +94,7 @@ #include "utils.h" #include "x2ap_messages_types.h" #include "xer_encoder.h" +#include "E1AP/lib/e1ap_bearer_context_management.h" #ifdef E2_AGENT #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" @@ -2595,6 +2596,7 @@ void *rrc_gnb_task(void *args_p) { case E1AP_BEARER_CONTEXT_SETUP_RESP: rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance); + free_e1ap_context_setup_response(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p)); break; case E1AP_BEARER_CONTEXT_MODIFICATION_RESP: diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index c2a641db3204e2f18ca05a6aecfbd2a58747f4a4..bf71357aeda5454d578c6e18451f08a38ac55f79 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -349,11 +349,13 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession if (cuup_nssai.sst == 0) cuup_nssai = pdu->nssai; /* for CU-UP selection below */ - pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed; - - pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed; - pdu->teId = session->gtp_teid; - memcpy(&pdu->tlAddress, session->upf_addr.buffer, 4); // Fixme: dirty IPv4 target + security_indication_t *sec = &pdu->securityIndication; + sec->integrityProtectionIndication = rrc->security.do_drb_integrity ? SECURITY_REQUIRED + : SECURITY_NOT_NEEDED; + sec->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? SECURITY_REQUIRED + : SECURITY_NOT_NEEDED; + pdu->UP_TL_information.teId = session->gtp_teid; + memcpy(&pdu->UP_TL_information.tlAddress, session->upf_addr.buffer, sizeof(in_addr_t)); /* we assume for the moment one DRB per PDU session. Activate the bearer, * and configure in RRC. */ @@ -380,9 +382,10 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession drb->numCellGroups = 1; // assume one cell group associated with a DRB + // Set all Cell Group IDs to MCG for (int k=0; k < drb->numCellGroups; k++) { - cell_group_t *cellGroup = drb->cellGroupList + k; - cellGroup->id = 0; // MCG + cell_group_id_t *cellGroup = drb->cellGroupList + k; + *cellGroup = MCG; } drb->numQosFlow2Setup = session->nb_qos; diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 639c279d4decf9084196b191bb933f954185ed33..bc3c564516a8edb9738aed38f77155cde38fb857 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -446,19 +446,9 @@ static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_i AssertFatal(du->setup_req->num_cells_available == 1, "expected 1 cell for DU, but has %d\n", du->setup_req->num_cells_available); f1ap_served_cell_info_t *ci = &du->setup_req->cell[0].info; - - ci->nr_cellid = new_ci->nr_cellid; - ci->nr_pci = new_ci->nr_pci; - if (new_ci->tac != NULL) - *ci->tac = *new_ci->tac; - ci->num_ssi = new_ci->num_ssi; - for (int s = 0; s < new_ci->num_ssi; ++s) - ci->nssai[s] = new_ci->nssai[s]; - ci->mode = new_ci->mode; - if (ci->mode == F1AP_MODE_TDD) - ci->tdd = new_ci->tdd; - else - ci->fdd = new_ci->fdd; + // make sure no memory is allocated + free_f1ap_cell(ci, NULL); + copy_f1ap_served_cell_info(ci, new_ci); NR_MeasurementTimingConfiguration_t *new_mtc = extract_mtc(new_ci->measurement_timing_config, new_ci->measurement_timing_config_len); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index e9d1f20fb369c26dfbc94f96a4c9fb5c25efff81..b46da323740d789ef5fbef00f3262bbe9aea2edd 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -972,9 +972,12 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, NR_Rec NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; nr_timer_stop(&tac->T310); - int t304_value = nr_rrc_get_T304(reconfigurationWithSync->t304); - nr_timer_setup(&tac->T304, t304_value, 10); // 10ms step - nr_timer_start(&tac->T304); + if (!get_softmodem_params()->phy_test) { + // T304 is stopped upon completion of RA procedure which is not done in phy-test mode + int t304_value = nr_rrc_get_T304(reconfigurationWithSync->t304); + nr_timer_setup(&tac->T304, t304_value, 10); // 10ms step + nr_timer_start(&tac->T304); + } rrc->rnti = reconfigurationWithSync->newUE_Identity; // reset the MAC entity of this cell group (done at MAC in handle_reconfiguration_with_sync) } diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index 588edb1461fb77e3a98e36d8f2a831c4ed9392bf..31a479cab683af7244bfcd87357c2125788b3848 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -31,7 +31,7 @@ ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24)) # define hton_int16(x) \ - (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8) + ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8)) # define ntoh_int32_buf(bUF) \ ((*((uint8_t*)bUF)) << 24) | ((*((uint8_t*)bUF + 1)) << 16) | ((*((uint8_t*)bUF + 2)) << 8) \ @@ -285,19 +285,6 @@ do { \ BUFFER_TO_UINT32((aSN)->buf, x); \ } while (0) -#define BIT_STRING_TO_INT32(aSN, x) \ -do { \ - DevCheck((aSN)->bits_unused == 0, (aSN)->bits_unused, 0, 0); \ - OCTET_STRING_TO_INT32(aSN, x); \ -} while(0) - -#define BIT_STRING_TO_CELL_IDENTITY(aSN, vALUE) \ -do { \ - DevCheck((aSN)->bits_unused == 4, (aSN)->bits_unused, 4, 0); \ - vALUE = ((aSN)->buf[0] << 20) | ((aSN)->buf[1] << 12) | \ - ((aSN)->buf[2] << 4) | (aSN)->buf[3]; \ -} while(0) - #define BIT_STRING_TO_NR_CELL_IDENTITY(aSN, vALUE) \ do { \ DevCheck((aSN)->bits_unused == 4, (aSN)->bits_unused, 4, 0); \ @@ -315,14 +302,6 @@ do { \ #define MCC_MNC_DIGIT(vALUE) \ ((vALUE) % 10) -#define MCC_TO_BUFFER(mCC, bUFFER) \ -do { \ - DevAssert(bUFFER != NULL); \ - (bUFFER)[0] = MCC_HUNDREDS(mCC); \ - (bUFFER)[1] = MCC_MNC_DECIMAL(mCC); \ - (bUFFER)[2] = MCC_MNC_DIGIT(mCC); \ -} while(0) - #define MCC_MNC_TO_PLMNID(mCC, mNC, mNCdIGITlENGTH, oCTETsTRING) \ do { \ (oCTETsTRING)->buf = calloc(3, sizeof(uint8_t)); \ @@ -459,14 +438,6 @@ do { \ (bITsTRING)->bits_unused = 4; \ } while(0) -/* -#define INT16_TO_3_BYTE_BUFFER(x, buf) \ -do { \ - (buf)[0] = 0x00; \ - (buf)[1] = (x) >> 8; \ - (buf)[2] = (x); \ -} while(0) -*/ #define NR_FIVEGS_TAC_ID_TO_BIT_STRING(x, aSN) \ do { \ @@ -497,20 +468,6 @@ do { \ (bITsTRING)->bits_unused = 0; \ } while(0) -#define BIT_STRING_TO_MaskedIMEISV(bITsTRING, mACRO) \ -do { \ - DevCheck((bITsTRING)->size == 8, (bITsTRING)->size, 8, 0); \ - DevCheck((bITsTRING)->bits_unused == 0, (bITsTRING)->bits_unused, 0, 0); \ - mACRO = ((bITsTRING)->buf[0] << 56) + \ - ((bITsTRING)->buf[1] << 48) + \ - ((bITsTRING)->buf[2] << 40) + \ - ((bITsTRING)->buf[3] << 32) + \ - ((bITsTRING)->buf[4] << 24) + \ - ((bITsTRING)->buf[5] << 16) + \ - ((bITsTRING)->buf[6] << 8) + \ - ((bITsTRING)->buf[7]); \ -} while (0) - /* TS 36.413 v10.9.0 section 9.2.1.37: * Macro eNB ID: * Equal to the 20 leftmost bits of the Cell