Commit c942fe43 authored by Robert Schmidt's avatar Robert Schmidt

Merge branch 'integration_2024_w48' into 'develop'

Integration: `2024.w48`

See merge request oai/openairinterface5g!3134

* !2951 Integrate Tracy with NR UE
* !2985 E1AP Bearer Context Setup encoding/decoding library and unit tests
* !3115 T2: minor fix for 4x4 processing
* !3117 F1AP lib: minor fixes
* !3126 NR MSG3 scheduling improvements
* !3128 NR UE RRC T304 in phy-test mode
* !3132 Run the last job of gNB pusch channel estimation inline
* !3133 NR UL HARQ handling improvements
* !3091 Update NR UE threading model
* !3030 Imscope updates
* !3131 FAPI P7 Refactoring and unitary test creation
* !3033 Increase the number of UE supported at gNB by having more than 1 PUCCH2 frequency occasion per slot
parents 03946cd4 fb0a9b64
......@@ -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
#######################################
......
......@@ -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()
/*
* 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
......@@ -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)
add_library(actor actor.c)
target_include_directories(actor PUBLIC ./)
target_link_libraries(actor PUBLIC thread-pool)
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
# 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
/*
* 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);
}
/*
* 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
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)
/*
* 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();
}
add_library(barrier barrier.c)
target_include_directories(barrier PUBLIC ./)
target_link_libraries(barrier PUBLIC pthread)
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
/*
* 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);
}
/*
* 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
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)
/*
* 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();
}
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()
......@@ -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 ../../..
)
......@@ -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"
......
......@@ -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 ##
......
......@@ -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
![design](nr-ue-threads.svg)
## 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
```
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -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]);
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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")
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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);
}
......
This diff is collapsed.
......@@ -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
This diff is collapsed.
This diff is collapsed.
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 ()
......@@ -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
......@@ -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);
......
......@@ -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);
......
/*
* 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
/*
* 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
/*
* 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);
}
This diff is collapsed.
......@@ -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));
......
This diff is collapsed.
This diff is collapsed.
/*
* 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
......@@ -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
......@@ -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
......@@ -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;
......
......@@ -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) {
......
This diff is collapsed.
......@@ -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);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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);
......
......@@ -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);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment