diff --git a/CMakeLists.txt b/CMakeLists.txt index 38168ae460..99c537dc22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -715,6 +715,11 @@ add_library(NFAPI_LIB ${NFAPI_SRC}) target_link_libraries(NFAPI_LIB PUBLIC nfapi_common) target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5 nr_fapi_p7) +if(OAI_WLS) + target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_WLS) +else() + target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_SOCKET) +endif() include_directories(${NFAPI_DIR}/nfapi/public_inc) include_directories(${NFAPI_DIR}/nfapi/inc) @@ -728,6 +733,9 @@ add_library(NFAPI_PNF_LIB ${NFAPI_PNF_SRC}) target_link_libraries(NFAPI_PNF_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) target_link_libraries(NFAPI_PNF_LIB PUBLIC nr_fapi_p7) +if(OAI_WLS) + target_compile_definitions(NFAPI_PNF_LIB PRIVATE ENABLE_WLS) +endif() include_directories(${NFAPI_DIR}/pnf/public_inc) include_directories(${NFAPI_DIR}/pnf/inc) @@ -746,6 +754,9 @@ endif() include_directories(${NFAPI_DIR}/vnf/public_inc) include_directories(${NFAPI_DIR}/vnf/inc) +if(OAI_WLS) + target_compile_definitions(NFAPI_VNF_LIB PRIVATE ENABLE_WLS) +endif() # nFAPI user defined code ############################# set(NFAPI_USER_SRC @@ -755,11 +766,15 @@ set(NFAPI_USER_SRC ${NFAPI_USER_DIR}/gnb_ind_vars.c ) add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC}) +if(OAI_WLS) + target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_WLS) +elseif (OAI_AERIAL) + target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_AERIAL) +else() + target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_SOCKET) +endif() 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) -if(OAI_AERIAL) - target_compile_definitions(NFAPI_USER_LIB PRIVATE ENABLE_AERIAL) -endif() include_directories(${NFAPI_USER_DIR}) # Layer 1 @@ -1047,7 +1062,7 @@ 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) +target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5) add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC}) target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common) @@ -1839,6 +1854,12 @@ target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +add_boolean_option(OAI_WLS OFF "Activate OAI's WLS driver" OFF) +if (OAI_WLS) + target_link_libraries(nr-softmodem PUBLIC wls_integration_lib) +else() + target_link_libraries(nr-softmodem PUBLIC nfapi_socket_lib) +endif() add_boolean_option(OAI_AERIAL OFF "Activate OAI's AERIAL driver" OFF) if (OAI_AERIAL) target_compile_definitions(nr-softmodem PUBLIC ENABLE_AERIAL) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 5e9bfaf444..cbe197c973 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -99,7 +99,7 @@ Options: USRP, BLADERF, LMSSDR, IRIS, SIMU, AW2SORI, AERIAL, None (Default) Adds this RF board support (in external packages installation and in compilation) -t | --transport - Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g, oran_fhlib_5g_mplane + Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g, oran_fhlib_5g_mplane, WLS -P | --phy_simulators Makes the unitary tests Layer 1 simulators -s | --check @@ -308,6 +308,9 @@ function main() { TARGET_LIST="$TARGET_LIST $2" CMAKE_CMD="$CMAKE_CMD -DOAI_FHI72=ON -DOAI_FHI72_MPLANE=ON" ;; + "WLS"|"Wls"|"wls") + CMAKE_CMD="$CMAKE_CMD -DOAI_WLS=ON" + ;; "None") ;; *) diff --git a/cmake_targets/tools/install_wls_lib.patch b/cmake_targets/tools/install_wls_lib.patch new file mode 100644 index 0000000000..5050b79a4e --- /dev/null +++ b/cmake_targets/tools/install_wls_lib.patch @@ -0,0 +1,209 @@ +diff --git a/wls_lib/Makefile b/wls_lib/Makefile +index 2f8e4b2..e657488 100644 +--- a/wls_lib/Makefile ++++ b/wls_lib/Makefile +@@ -1,20 +1,6 @@ +-############################################################################### +-# +-# Copyright (c) 2021 Intel. +-# +-# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +-# +-# 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. +-# +-############################################################################### ++################################################################ ++# ++################################################################ + + MYCUSTOMTAB=' ' + MYCUSTOMSPACE='============================================================================================' +@@ -24,11 +10,17 @@ MYCUSTOMSPACE1='------------------------------------------------------------' + # Tools configuration + ############################################################## + ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) +-CC := icc ++ CC := icc + CPP := icpc +-AS := as +-AR := ar +-LD := icc ++ AS := as ++ AR := ar ++ LD := icc ++else ifeq ($(WIRELESS_SDK_TOOLCHAIN),gcc) ++ CC := gcc ++ CPP := g++ ++ AS := as ++ AR := ar ++ LD := gcc + else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icx) + CC := icx + CPP := icx +@@ -44,9 +36,9 @@ ifeq ($(WIRELESS_SDK_TARGET_ISA),sse) + else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx2) + TARGET_PROCESSOR := -xCORE-AVX2 + else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx512) +- TARGET_PROCESSOR := -xCORE-AVX512 ++ TARGET_PROCESSOR := -march=skylake-avx512 + else ifeq ($(WIRELESS_SDK_TARGET_ISA),snc) +- TARGET_PROCESSOR := -xicelake-server ++ TARGET_PROCESSOR := -march=icelake-server + else ifeq ($(WIRELESS_SDK_TARGET_ISA),spr) + TARGET_PROCESSOR := -march=sapphirerapids + endif +@@ -66,15 +58,38 @@ PROJECT_DIR := ./ + BUILDDIR := make + PROJECT_BINARY := $(PROJECT_NAME).so + ++PKGCONF ?= pkg-config ++LIBDPDK_VERSION=20.11.3 ++ ++ifeq ($(shell $(PKGCONF) --modversion "libdpdk = '$(LIBDPDK_VERSION)'"),$(LIBDPDK_VERSION)) ++ DPDK_INSTALLED=1 ++else ++ DPDK_INSTALLED=0 ++endif ++ + ifeq ($(RTE_SDK),) +-$(error "Please define RTE_SDK environment variable") ++ifeq ($(DPDK_INSTALLED),0) ++$(error "Please define RTE_SDK environment variable OR install DPDK version $(LIBDPDK_VERSION)") ++endif + endif + +-RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++# At least one of the options is defined ++ ++ifneq ($(RTE_SDK),) ++ RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++else ifeq ($(DPDK_INSTALLED),1) ++ RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig $(PKGCONF) --cflags-only-I libdpdk) ++endif + + CC_SRC = wls_lib_dpdk.c \ + syslib.c + ++CC_HDR = syslib.h \ ++ ttypes.h \ ++ wls.h \ ++ wls_debug.h \ ++ wls_lib.h ++ + CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ + -fdata-sections \ + -ffunction-sections \ +@@ -84,18 +99,19 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ + -Wimplicit-function-declaration \ + -g -O3 -mcmodel=large $(TARGET_PROCESSOR) + +-INC := -I$(RTE_INC) ++INC := -I$(RTE_INC) -I../intel_fapi/ + DEF := + + AS_FLAGS := + AR_FLAGS := rc + + PROJECT_OBJ_DIR := $(BUILDDIR)/obj ++PROJECT_DEP_DIR := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep.d + + CC_OBJS := $(patsubst %.c,%.o,$(CC_SRC)) + AS_OBJS := $(patsubst %.s,%.o,$(AS_SRC)) + OBJS := $(CC_OBJS) $(AS_OBJS) $(LIBS) +-DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS)))) ++DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS)))) $(PROJECT_DEP_DIR) + + CC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CC_OBJS)) + +@@ -104,9 +120,7 @@ CC_FLAGS_FULL := $(CC_FLAGS) $(INC) $(DEF) + + AS_FLAGS := $(AS_FLAGS) $(INC) + +-PROJECT_DEP_FILE := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep +- +-ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE)) ++ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR)) + GENERATE_DEPS := + else + +@@ -119,11 +133,11 @@ all : welcome_line $(PROJECT_BINARY) + + .PHONY : clear_dep + clear_dep: +- @$(RM) $(PROJECT_DEP_FILE) +- @echo [DEP] $(subst $(PROJECT_OBJ_DIR)/,,$(PROJECT_DEP_FILE)) ++ @echo [DEP] rm $(PROJECT_DEP_DIR)/$(@F).dep ++ @$(RM) $(PROJECT_DEP_DIR)/$(@F).dep + +-$(CC_DEPS) : +- @$(CC) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) $(CC_FLAGS_FULL) >> $(PROJECT_DEP_FILE) ++$(CC_DEPS) : $(PROJECT_DEP_DIR) ++ @$(CC) $(CC_FLAGS_FULL) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) >> $(PROJECT_DEP_DIR)/$(@F).dep + + .PHONY : generate_deps + generate_deps : clear_dep $(CC_DEPS) +@@ -136,17 +150,17 @@ echo_start_build : + $(DIRLIST) : + -@$(MD) $@ + +-$(CC_OBJTARGETS) : ++$(CC_OBJTARGETS) : $(GENERATE_DEPS) + @echo [CC] $(subst $(PROJECT_OBJ_DIR)/,,$@) + @$(CC) -c $(CC_FLAGS_FULL) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@)) + +-$(AS_OBJTARGETS) : ++$(AS_OBJTARGETS) : $(CC_OBJTARGETS) $(CPP_OBJTARGETS) + @echo [AS] $(subst $(PROJECT_OBJ_DIR)/,,$@) + @$(AS) $(AS_FLAGS) -o"$@" $(patsubst %.o,%.s,$(subst $(PROJECT_OBJ_DIR)/,,$@)) + +-ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE)) ++ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR)) + +-include $(PROJECT_DEP_FILE) ++include $(PROJECT_DEP_DIR)/* + + endif + +@@ -156,7 +170,7 @@ clean: + @$(RM) $(CC_OBJTARGETS) $(AS_OBJTARGETS) + ifneq ($(wildcard $(PROJECT_DIR)/$(PROJECT_MAKE)),) + @echo [CLEAN] : $(PROJECT_NAME) +- @$(RM) $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_FILE) ++ @$(RM) -rf $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_DIR) + endif + + xclean: clean +@@ -172,7 +186,24 @@ welcome_line : + debug : all + release : all + +-$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(PRE_BUILD) $(CC_OBJTARGETS) $(AS_OBJTARGETS) ++$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(CC_OBJTARGETS) $(AS_OBJTARGETS) + @echo [AR] $(subst $(BUILDDIR)/,,$@) + @$(CC) $(CC_OBJTARGETS) $(AS_OBJTARGETS) -shared -fPIC -o $@ + ++############################################################## ++# Install configuration ++############################################################## ++ ++INSTALL_DIR := /usr/local ++INCLUDE_DIR := $(INSTALL_DIR)/include/ ++ ++.PHONY : install ++install: $(PROJECT_BINARY) install_headers ++ @echo [INSTALL] : $(PROJECT_BINARY) ++ @$(CP) $(PROJECT_BINARY) $(INSTALL_DIR)/lib ++ ++.PHONY : install_headers ++install_headers: $(CC_SRC) ++ @echo [INSTALL] : $(PROJECT_NAME) headers ++ @$(MD) $(INCLUDE_DIR) ++ @$(CP) $(CC_HDR) $(INCLUDE_DIR) diff --git a/doc/NR_NFAPI_archi.md b/doc/NR_NFAPI_archi.md index 59c511fb52..8065ddb4fc 100644 --- a/doc/NR_NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -1,53 +1,90 @@ -# global +This document describes the broad way in which the VNF and PNF work internally, +from configuration, to P5 and P7 message exchange and processing. +Their internal processing is broadly independent on which transport mechanism +is responsible for exchanging data between the 2 components. -xnf is pnf or vnf +To read more about the transport mechanisms available, and how to run the split, please refer to +[this file](./nfapi.md). -The xnf starting functions are configure_nfapi_xnf() +[[_TOC_]] -The OAI code that read the configuration parameters call these functions that will create autonomous thread for xnf control part +# VNF/PNF Split -These control threads create a SCTP socket by Linux API call (no use of OpenAir internal architecture with SCTP itti thread). +The gNB is split into VNF(L2+) and PNF(L1) -The main() function of softmodem has to create and start the other threads+loop on event for appropriate work: RF Rx in pnf, NGAP, GTP-U, X2, RLC, PDCP for vnf +These component are configured via the functions: -NFAPI has it's own code directly on Linux+Posix, it doesn't reuse any piece of the OpenAir framework: SCTP thread, thread creation and management, ... +- configure_nr_nfapi_vnf() +- configure_nr_nfapi_pnf() -## signaling (P5) xnf main loop +These functions initialize the configuration appropriate for the transport mechanism selected ( setting the +pack/unpack function pointers, as well as the appropriate send functions ) -nfapi_vnf_start() create the SCTP socket, then do event waiting in a infinite loop while(vnf->terminate == 0). It accepts the pnf connections, then process the messages on reception +After this, a thread is created for the P5 receive loop, which initializes the transport and receive loop -nfapi_pnf_start() initiate connection to vnf until it has a link. Then it enter a similar infinite loop in pnf_message_pump() +This created thread may be only for P5 messages, or P5 and P7, depending on the transport type -After some checks, when a message is obtained, it calls pnf_handle_p5_message() or vnf_handle_p4_p5_message() that have a switch on each p5 message types: the enum nfapi_message_id_e +- When using socket-based communication (which uses nFAPI encoding), the receiving loop for P7 messages is separate from + P5, it starts upon the PNF_START exchange +- In the other transport mechanisms (WLS and nvIPC, which use FAPI encoding), the receiving loop is the same for P5 and + P7 messages, the P7 configuration is done immediately after the P5 configuration. + +Since the first P7 messages is only sent/received after the START exchange, we can logically treat the loops as separate +, we won't receive P7 messages before finishing the P5 ones ( except for the STOP exchange ) + +## P5 interface main loop + +After the P5 configuration, both the VNF and PNF have a thread waiting to "consume" (n)FAPI messages exchanged between +them + +Upon the reception of a message (whether in its entirety or segmented in the case of nFAPI), the messages are sent to +the appropriate handler: + +- pnf_nr_handle_p5_message +- vnf_nr_handle_p4_p5_message + +In each of these functions, there's a switch calling the appropriate handler according to the message ID, for example: -Each message type has it's own processing function in the switch, like ``` -case NFAPI_START_RESPONSE: - vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); - break; +case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + vnf_nr_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; ``` These loops are autonomous in their thread waiting incoming message. -## P7 xnf main loop +## P7 interface main loop -When the p5 interface receives appropriate message, it starts the p7 interface by launching a thread (see the calls to pthread_create() in nfapi/oai_integration/nfapi_xnf.c) +- Note: As explained before, the P7 reception loop is the same as the P5 messages when not using socket-based + communication -The p7 main loops starting is a bit simpler, thanks to UDP non connected protocol. The xnf_dispatch_p7_message() do p7 fragments re-assembly, then -calls xnf_dispatch_p7_message() that have the big switch on message type (as in p5 above description) +In this case, when the P5 interface receives appropriate message, it starts the p7 interface by launching a thread -So, we have the logic for UL reception in vnf, and DL reception in pnf +- On the PNF, this is done in the START.request handler ( nr_start_request(...) ) +- On the VNF, this is done in ( configure_nr_p7_vnf(...) ) + +Much in the same way as when processing P5 messages, the following functions are called to unpack and process them: + +- pnf_nr_handle_p7_message +- vnf_nr_handle_p7_message + +``` +case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + vnf_handle_nr_slot_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; +``` ## P7 UL transmission by PNF -RF samples are received, and decoding is done by the PNF using control data transmitted by the VNF to the PNF through downlink p7 messages (UL_TTI_req and UL_DCI_req). +RF samples are received, and decoding is done by the PNF using control data transmitted by the VNF to the PNF through +downlink p7 messages (UL_TTI.request and UL_DCI.request). -After decoding, results are accumulated into the xNB->UL_INFO structure at the PNF. +After decoding, results are accumulated into the gNB->UL_INFO structure at the PNF. -The data in the UL_INFO struct is transmitted through a socket in the form of 'uplink indication functions' from the PNF to the VNF. Each uplink indication message is transmitted from their respective handle functions in NR_UL_indication(). For example, +The data in the UL_INFO struct is transmitted through the configured send function pointer (send_p7_msg), which packs +the message into a buffer according to the encoding and sends it to the VNF ``` - void handle_nr_rach(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->rach_ind.number_of_pdus>0) { @@ -56,67 +93,186 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } } -``` +.... -## P7 UL reception at VNF +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; + return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind); +} -Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vnf_p7_start(), the VNF receives and unpacks the uplink indication message received on its socket. Based on the unpacked messages, UL_INFO struct on the VNF side gets populated. +..... -``` - -// have a p7 message - if(FD_ISSET(vnf_p7->socket, &rfds)) - { - vnf_nr_p7_read_dispatch_message(vnf_p7); - } - -``` - -vnf_nr_dispatch_p7_message() is the function that contains the switch on various message headers so that the appropriate unpack function is called. - -## P7 DL Transmission by VNF - -DL messages are scheduled at the VNF, through NR_UL_indication(). NR_UL_indication() is called when the SFN/slot in the UL_info structure changes (this acts as a trigger for next slot processing, instead of running a separate clock at the VNF). The SFN/slot at the VNF in UL_info is updated using the slot_indication uplink p7 message, which is sent at the beginning of every slot by the PNF. The slot_indication message contains SFN/slot of the TX_thread, so that the scheduler operates slot_ahead slots ahead of the RX thread. This ensures that UL_tti_req is received before RX slot processing at the PNF. - -The function NR_schedule_response calls oai_nfapi_[DL P7 msg]_req(), which contains the routines for packing + transmission of scheduled messages through the socket to the PNF. For example, to send the 'TX_data_req' p7 message - -``` - -if (Sched_INFO->TX_req->Number_of_PDUs > 0) +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) { - oai_nfapi_tx_data_req(Sched_INFO->TX_req); + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); } ``` +## P7 UL reception at VNF + +Through the P7 reception loop, the VNF receives a buffer containing the messages, which it handles by the following +process: + +- Unpack the header by use of the hdr_unpack_func function pointer +- According to the Message ID in the header, send the buffer to the appropriate handler by use of a switch statement: + +``` + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + vnf_handle_nr_slot_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + +``` + +- In the handler function, unpack the entire message, by using the unpack_func function pointer. +- If the unpack procedure is successful, call the previously configure callback for that message type: + +``` + nfapi_nr_slot_indication_scf_t ind = {0}; + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s: Handling NR SLOT Indication\n", __FUNCTION__); + if(vnf_p7->_public.nr_slot_indication) + { + (vnf_p7->_public.nr_slot_indication)(&ind); + } + free_slot_indication(&ind); + } + +``` + +vnf_nr_dispatch_p7_message() is the function that contains the switch on various message headers so that the appropriate +unpack function is called. + +## P7 DL Transmission by VNF + +DL messages are scheduled at the VNF, through gNB_dlsch_ulsch_scheduler(). gNB_dlsch_ulsch_scheduler() is called when +handling a SLOT.indication message in trigger_scheduler(). + +The function trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_ +req(), calling in turn call the send_p7_msg function pointer, which contain the logic to pack the message into a buffer +and send it to the PNF. +Finally, NR_UL_indication is called to process the other P7 messages received from the PNF that were put in theire +respective queues. +For example, the TX_DATA.request message is sent in the following manner: + +``` + if (g_sched_resp.TX_req.Number_of_PDUs > 0) + oai_nfapi_tx_data_req(&g_sched_resp.TX_req); + +... + +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) +{ + LOG_D(NR_PHY, "Entering oai_nfapi_nr_tx_data_req sfn:%d,slot:%d\n", tx_data_req->SFN, tx_data_req->Slot); + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + tx_data_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! + tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; + //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); + bool retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + + if (!retval) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + tx_data_req->Number_of_PDUs = 0; + } + + return retval; +} + +... + +bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); +} + +``` + +## VNF functional flowchart + ```mermaid graph TD - pselect[VNF socket pselect] -- timed out : end of slot --> call_sched[Call Scheduler NR_UL_indication] -- oai_nfapi_***_req sends the DL p7 msg--> slot_inc[Increment sfn/slot]; - pselect[VNF socket pselect] -- UL p7 xyz msg recvd --> msg_recvd[Read message vnf_nr_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Handle Message vnf_handle_nr_xyz] --> fill_ul_info[Fill UL info struct with fn pointer vnf_p7->_public.nr_rx_xyz]; - fill_ul_info -- update pselect_timeout: next_slot_start - time_xyz_msg_recvd-->pselect; - slot_inc -- next slot --> pselect + softmodem_start[nr-softmodem init] --> P5_configuration[configure_nr_nfapi_vnf] --> transport_init[Transport mechanism init] --> send_first_msg[Send first P5 message to PNF] + transport_init[Transport mechanism init] --> P5_recv_loop[P5 receive loop] -- P5 Message processing --> P5_recv_loop[P5 receive loop] + P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call trigger_scheduler] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop] + slot_ind[Is a SLOT.indication?] -- No --> put_queue[Put message in queue] --> P7_loop[P7 Loop]; + ``` -Note that since DL P7 message reception and TX/RX processing are done on separate threads, there is the issue of the L1 processing threads trying to do their job before the required P7 message is received. In the case of RX processing, since the scheduler operates slot_ahead slots ahead of the RX thread, the required messages conveniently arrive earlier than they are required. However, in the case of TX processing, this cannot be ensured if the scheduler is exactly in sync with the TX thread. -Therefore, we operate the VNF vnf_slot_ahead (which is currently 2) slots ahead of the PNF. This is to ensure that the DL fapi structures for a particular TX slot are all received before TX processing for that slot. +## P7 DL Reception at PNF -## P7 DL Reception at PNF +Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and +unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message +structures are filled in the PNF, and these are used further down the pipeline for processing. +Through the P7 reception loop, the PNF receives a buffer containing a P7 message from the VNF, which it processes the +following way: -Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message structures are filled in the PNF, and these are used further down the pipeline for processing. +- Unpack the header by use of the hdr_unpack_func function pointer +- According to the Message ID in the header, send the buffer to the appropriate handler by use of a switch statement: -While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). Note that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). +``` + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; +``` + +- In the handler function, the SFN and Slot are peeked from the message +- The SFN and slot are checked to determine if the message is inside the appropriate timing window +- If so, the message is unpacked into the P7 Slot buffer: + +``` + pnf_p7->slot_buffer[buffer_index].sfn = frame; + pnf_p7->slot_buffer[buffer_index].slot = slot; + nfapi_nr_dl_tti_request_t *req = &pnf_p7->slot_buffer[buffer_index].dl_tti_req; + pnf_p7->nr_stats.dl_tti.ontime++; + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + "POPULATE DL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", + pnf_p7->sfn, + pnf_p7->slot, + frame, + slot, + buffer_index); + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + + ``` + +- The messages are later processed in the NR_slot_indication function, which is called in the tx_func function ( + L1_tx_thread ) + +## PNF functional flowchart ```mermaid -graph TB - pselect[PNF socket pselect] -- timed out : end of slot --> slot_inc[Increment sfn/slot]; - pselect[PNF socket pselect] -- DL p7 xyz msg recvd --> msg_recvd[Read message pnf_nr_nfapi_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Unpack Message pnf_handle_nr_xyz] --> fill_pnf_p7[Fill pnf_p7 global structure pnf_handle_nr_xyz] --Data from pnf_p7 struct copied to fapi structures using pnf_phy_***_req. Called every slot from handle_nr_slot_ind-->pselect; - - slot_inc -- next slot --> pselect +graph TD + softmodem_start[nr-softmodem init] --> init_l1_tx_thread[Init L1 TX Thread] --> tx_func[Call tx_func] --> nr_slot_ind[Call NR_slot_indication] --> pnf_slot_ind[Call handle_nr_slot_ind] --> send_slot_ind[Send SLOT.ind to VNF] --> get_from_slot_buffer[Get P7 messages from slot_buffer] --> proc_p7_dl[Process P7 messages from VNF] --> tx_func + softmodem_start[nr-softmodem init] --> init_l1_rx_thread[Init L1 RX Thread] --> rx_func[Call rx_func] --> nr_ul_ind[Call NR_UL_indication] --> send_p7_vnf[Send P7 messages to VNF] --> rx_func + softmodem_start[nr-softmodem init] --> P5_configuration[configure_nr_nfapi_pnf] --> transport_init[Transport mechanism init] --> p5_loop[P5 Loop] -- Process P5 messages --> p5_loop + p5_loop -- START.request callback called --> p7_config[P7 Configuration] --> l1_north_init_gnb[Call l1_north_init_gNB] --> nr_if_module_init[Call NR_IF_Module_Init] --> install_slot_ind_cb[Install NR_slot_indication callback] + p7_config[P7 Configuration] --> p7_loop[P7 Loop] --> p7_recv[Receive P7 message] --> pnf_handle_p7[Call pnf_nr_handle_p7_message] --> hdr_unpack[Unpack header with hdr_unpack] --> p7_handler[Call pnf_handle_] --> peek_sfn[Peek SFN/Slot and check if in timing window] --> p7_unpack[Unpack message into slot_buffer] --> p7_loop ``` -Once the messages are received, they are filled into slot buffers, and are stored until the processing of the slot that they were meant for. diff --git a/doc/README.md b/doc/README.md index 24050666a7..756294fb5d 100644 --- a/doc/README.md +++ b/doc/README.md @@ -57,7 +57,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https:// - [How to use the L2 simulator](./L2NFAPI.md) - [How to use the OAI channel simulator](../openair1/SIMULATION/TOOLS/DOC/channel_simulation.md) - [How to use multiple BWPs](./RUN_NR_multiple_BWPs.md) -- [How to run OAI-VNF and OAI-PNF](./nfapi.md): how to run the nFAPI split, +- [How to run OAI-VNF and OAI-PNF](./nfapi.md): how to run the FAPI/nFAPI split, including some general remarks on FAPI/nFAPI. - [How to use the positioning reference signal (PRS)](./RUN_NR_PRS.md) - [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.txt) diff --git a/doc/nfapi.md b/doc/nfapi.md index 366b5fb4ac..41a3770be4 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -1,5 +1,6 @@ This document describes the SmallCellForum (SCF) (n)FAPI split in 5G, i.e., -between the MAC/L2 and PHY/L1. +between the MAC/L2 and PHY/L1. It also describes how to make use of the +multiple transport mechanisms between the 2. The interested reader is recommended to read a copy of the SCF 222.10 specification ("FAPI"). This includes information on what is P5, P7, and how @@ -7,6 +8,8 @@ FAPI works. The currently used version is SCF 222.10.02, with some messages upgraded to SCF 222.10.04 due to bugfixes in the spec. Further information about nFAPI can be found in SCF 225.2.0. +[[_TOC_]] + # Quickstart Compile OAI as normal. Start the CN and make sure that the VNF configuration @@ -108,6 +111,125 @@ can proceed as follows: Note: all L1-specific options have to be passed to the PNF, and remaining options to the VNF. +## Transport mechanisms between VNF and PNF + +Currently, the VNF/PNF split supports three transport mechanisms between each +other: + +1. Socket communication (either regular, or SCTP), this is the default + + The socket type may be changed by editing `nfapi_pnf_config_create()` and + `nfapi_vnf_config_create()`, in both of which `_this->sctp = ;` indicate whether SCTP or regular sockets are to be used. Note: The + value of `_this->sctp` **must** be the same on the VNF and PNF. +2. Intel WLS Lib, which uses DPDK to achieve a shared memory communication between components. +3. nvIPC, which is used exclusively for the NVIDIA Aerial L1. Thus, it is only + applicable for the VNF. + +The change between transport mechanisms is done at compilation time: +- No changes to the `build_oai` call are required in order to select socket communication, as it is the default. +- In order to select WLS as the transport mechanism between VNF and PNF, first install the WLS library, and afterwards use `-t WLS` as a parameter of `build_oai`: + +### How to use nFAPI + +nFAPI is used by default. Compile and configure as indicated above. + +### How to use Aerial + +Refer to [this document](./Aerial_FAPI_Split_Tutorial.md) for more information. + +### How to use WLS lib + +Before the first compilation with WLS support, the [WLS +library](https://docs.o-ran-sc.org/projects/o-ran-sc-o-du-phy/en/latest/wls-lib.html) +must first be compiled and installed to the system. + +The WLS library has a few dependencies: + - [DPDK](https://doc.dpdk.org/guides/prog_guide/build-sdk-meson.html), specifically version [20.11.3](https://fast.dpdk.org/rel/dpdk-20.11.3.tar.xz). + - libelf-dev + - libhugetlbfs-dev + +Additionally, a patch needs to be applied to the WLS lib Makefile in order for +the shared library and headers to be installed into the system, the necessary +patch is available [here](../cmake_targets/tools/install_wls_lib.patch) + +Clone the code and apply the patch + + git clone -b oran_f_release https://gerrit.o-ran-sc.org/r/o-du/phy.git + cd phy/wls_lib/ + git apply ~/openairinterface5g/cmake_targets/tools/install_wls_lib.patch + +Then compile and install the library + + WIRELESS_SDK_TOOLCHAIN=gcc WIRELESS_SDK_TARGET_ISA=avx2 make + sudo WIRELESS_SDK_TOOLCHAIN=gcc WIRELESS_SDK_TARGET_ISA=avx2 make install + +After installing WLS, you can run the build command as shown below: + + ./build_oai -t WLS -w USRP --gNB --nrUE --ninja -C + +#### How to run OAI PNF with OAI VNF + +Refer to the above steps in [Quickstart](.#quickstart), but run the PNF first as it is the WLS "master". + +#### How to run OAI PNF with OSC/Radisys O-DU + +Set up the hugepages for DPDK (1GB page size, 6 pages; this only needs to be +done once): + + sudo nano /etc/default/grub + GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_DEFAULT} default_hugepagesz=1G hugepagesz=1G hugepages=6" + +Then rewrite the bootloader and reboot + + sudo update-grub + sudo reboot + +Install dependencies: + + sudo apt-get install libstdc++-14-dev libnsl-dev libpcap-dev libxml2-dev + +Clone the Radisys repository (We're currently using the `oai_integration` branch): + + git clone https://gerrit.o-ran-sc.org/r/o-du/l2 -b oai-integration + +Build the O-DU + + cd ~/l2/build/odu + make clean_all;make odu PHY=INTEL_L1 MACHINE=BIT64 MODE=TDD;make cu_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD;make ric_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD + +Setup local interfaces for the cu_stub, ric_stub and o_du + + sudo ifconfig enp7s0:ODU "192.168.130.81" && sudo ifconfig enp7s0:CU_STUB "192.168.130.82" && sudo ifconfig enp7s0:RIC_STUB "192.168.130.80" + +Run cu_stu and ric_stub in separate terminals + + cd ~/l2/bin/ + ./cu_stub/cu_stub + clear && ./ric_stub/ric_stub + +Run the OAI PNF first, as it is the WLS memory master + + sudo NFAPI_TRACE_LEVEL=info ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.2x2.conf --nfapi PNF --rfsim --rfsimulator.serveraddr server + +Run the O-DU over GDB + + sudo -E gdb -ex run --readnever --args ./odu/odu + +Note: If you see the following prompt in GDB + + This GDB supports auto-downloading debuginfo from the following URLs: + + Enable debuginfod for this session? (y or [n]) + +You can run the following command one time before executing gdb to disable it: + + export DEBUGINFOD_URLS= + +Run the OAI-UE + + sudo ./nr-uesoftmodem -r 273 --numerology 1 --band 78 -C 3400140000 --ssb 1518 --uicc0.imsi 001010000000001 --rfsim + # nFAPI logging system nFAPI has its own logging system, independent of OAI's. It can be activated by diff --git a/nfapi/CMakeLists.txt b/nfapi/CMakeLists.txt index d6c5b0e92a..6b9c75b5a8 100644 --- a/nfapi/CMakeLists.txt +++ b/nfapi/CMakeLists.txt @@ -1,3 +1,9 @@ add_subdirectory(oai_integration/aerial) +if (OAI_WLS) + add_subdirectory(oai_integration/wls_integration) +else () # Not WLS, means its SOCKET-based comms, maybe add a flag specific for UDP + message(STATUS "No Support for WLS") + add_subdirectory(oai_integration/socket) +endif () add_subdirectory(open-nFAPI) add_subdirectory(tests) diff --git a/nfapi/oai_integration/aerial/CMakeLists.txt b/nfapi/oai_integration/aerial/CMakeLists.txt index 74b1ad9fbf..2df4eb7ee0 100644 --- a/nfapi/oai_integration/aerial/CMakeLists.txt +++ b/nfapi/oai_integration/aerial/CMakeLists.txt @@ -3,7 +3,6 @@ if (OAI_AERIAL) add_library(aerial_lib fapi_nvIPC.c fapi_vnf_p7.c - fapi_vnf_p5.c ) find_library(NVIPC_LIB nvipc REQUIRED) diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index ed087204b0..b1bfae5415 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -48,12 +48,13 @@ #include #include #include "fapi_nvIPC.h" +#include +#include #include "nfapi_interface.h" #include "nfapi.h" #include "nfapi_nr_interface_scf.h" #include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h" - -#include "fapi_vnf_p5.h" +#include "system.h" #include "fapi_vnf_p7.h" #define MAX_EVENTS 10 @@ -93,90 +94,12 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) return -1; } + vnf_p7_t *vnf_p7_config = (vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config; switch (fapi_msg.message_id) { - case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: - - if (vnf_config->nr_param_resp) { - nfapi_nr_param_response_scf_t msg_param_resp; - aerial_unpack_nr_param_response(&pReadPackedMessage, end, &msg_param_resp, &vnf_config->codec_config); - (vnf_config->nr_param_resp)(vnf_config, vnf_config->pnf_list->p5_idx, &msg_param_resp); - } + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE ... NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: + vnf_nr_handle_p4_p5_message(msg->msg_buf, msg->msg_len, 1, vnf_config); break; - - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: { - // unpack message - nfapi_nr_config_response_scf_t msg_config_response; - aerial_unpack_nr_config_response(&pReadPackedMessage, end, &msg_config_response, &vnf_config->codec_config); - // Check the error code - if (msg_config_response.error_code == NFAPI_NR_CONFIG_MSG_OK) { - // Invoke the call back - if (vnf_config->nr_config_resp) { - (vnf_config->nr_config_resp)(vnf_config, vnf_config->pnf_list->p5_idx, &msg_config_response); - } - } else { - // Error code not OK (MSG_INVALID_CONFIG) - /* MSG_INVALID_CONFIG.response structure - * Error code uint8_t - * Number of invalid or unsupported TLVs uint8_t - * Number of invalid TLVs that can only be configured in IDLE state uint8_t - * Number of invalid TLVs that can only be configured in RUNNING state uint8_t - * Number of missing TLVs uint8_t - * List of invalid or unsupported TLVs - * List of invalid TLVs that can only be configured in IDLE state - * List of invalid TLVs that can only be configured in RUNNING state - * List of missing TLVs - * */ - } - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: { - // TODO : ADD Support for NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION (0x06) - LOG_D(NFAPI_VNF,"Received NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION\n"); - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: { - // TODO: Add Support for NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION (0x07) - LOG_D(NFAPI_VNF,"Received NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION\n"); - //for (int i = 0; i < msg->msg_len; i++) { - // printf(" msg->msg_buf[%d] = 0x%02x\n", i, ((uint8_t *) msg->msg_buf)[i]); - //} - LOG_D(NFAPI_VNF,"old sfn %u\n", old_sfn); - LOG_D(NFAPI_VNF,"old slot %u\n", old_slot); - - break; - } // P7 Messages - // P7 Message Handlers -> ((vnf_info *)vnf_config->user_data)->p7_vnfs->config-> - case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: { - nfapi_nr_slot_indication_scf_t ind; - aerial_unpack_nr_slot_indication(&pReadPackedMessage, - end, - &ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); - // check if the sfn/slot unpacked come wrong at any time, should be old + 1 (slot 0 -- 19, sfn 0 -- 1023) - // add 1 to current sfn number - uint16_t old_slot_plus = ((old_slot + 1) % 20); - uint16_t old_sfn_plus = old_slot_plus == 0 ? ((old_sfn + 1) % 1024) : old_sfn; - if (old_slot_plus != ind.slot || old_sfn_plus != ind.sfn) { - LOG_E(NFAPI_VNF, - "\n============================================================================\n" - "sfn slot doesn't match unpacked one! L2->L1 %d.%d vs L1->L2 %d.%d \n" - "============================================================================\n", - old_sfn, - old_slot, - ind.sfn, - ind.slot); - } - old_sfn = ind.sfn; - old_slot = ind.slot; - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_slot_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_slot_indication)(&ind); - } - break; - } - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: { uint8_t *pReadData = msg->data_buf; int dataBufLen = msg->data_len; @@ -190,10 +113,10 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) &pReadData, data_end, &ind, - &((vnf_p7_t *)((vnf_info *)vnf_config->user_data)->p7_vnfs->config)->_public.codec_config); + &vnf_p7_config->_public.codec_config); NFAPI_TRACE(NFAPI_TRACE_INFO, "%s: Handling RX Indication\n", __FUNCTION__); - if (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_rx_data_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_rx_data_indication)(&ind); + if (vnf_p7_config->_public.nr_rx_data_indication) { + (vnf_p7_config->_public.nr_rx_data_indication)(&ind); for (int i = 0; i < ind.number_of_pdus; ++i) { free(ind.pdu_list[i].pdu); } @@ -202,53 +125,6 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) break; } - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: { - nfapi_nr_crc_indication_t crc_ind; - crc_ind.header.message_id = fapi_msg.message_id; - crc_ind.header.message_length = fapi_msg.message_length; - aerial_unpack_nr_crc_indication(&pReadPackedMessage, - end, - &crc_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_crc_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_crc_indication)(&crc_ind); - free(crc_ind.crc_list); - } - break; - } - - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: { - nfapi_nr_uci_indication_t ind; - aerial_unpack_nr_uci_indication(&pReadPackedMessage, - 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_uci_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_uci_indication)(&ind); - for (int i = 0; i < ind.num_ucis; i++) { - if (ind.uci_list[i].pdu_type == NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE) { - if (ind.uci_list[i].pucch_pdu_format_2_3_4.sr.sr_payload) { - free(ind.uci_list[i].pucch_pdu_format_2_3_4.sr.sr_payload); - } - if(ind.uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload){ - free(ind.uci_list[i].pucch_pdu_format_2_3_4.harq.harq_payload); - } - if(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload){ - free(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part1.csi_part1_payload); - } - if(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload){ - free(ind.uci_list[i].pucch_pdu_format_2_3_4.csi_part2.csi_part2_payload); - } - } - } - free(ind.uci_list); - ind.uci_list = NULL; - } - - break; - } - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: { uint8_t *pReadData = msg->data_buf; int dataBufLen = msg->data_len; @@ -259,26 +135,47 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) &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) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_srs_indication)(&ind); + &vnf_p7_config->_public.codec_config); + if (vnf_p7_config->_public.nr_srs_indication) { + (vnf_p7_config->_public.nr_srs_indication)(&ind); } break; } + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: { + nfapi_nr_slot_indication_scf_t ind; + if (!vnf_p7_config->_public.unpack_func(msg->msg_buf, msg->msg_len, &ind, sizeof(ind), &vnf_p7_config->_public.codec_config)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } else { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s: Handling NR SLOT Indication\n", __FUNCTION__); + // check if the sfn/slot unpacked come wrong at any time, should be old + 1 (slot 0 -- 19, sfn 0 -- 1023) + // add 1 to current sfn number + uint16_t old_slot_plus = ((old_slot + 1) % 20); + uint16_t old_sfn_plus = old_slot_plus == 0 ? ((old_sfn + 1) % 1024) : old_sfn; + if (old_slot_plus != ind.slot || old_sfn_plus != ind.sfn) { + LOG_E(NFAPI_VNF, + "\n============================================================================\n" + "sfn slot doesn't match unpacked one! L2->L1 %d.%d vs L1->L2 %d.%d \n" + "============================================================================\n", + old_sfn, + old_slot, + ind.sfn, + ind.slot); + } + old_sfn = ind.sfn; + old_slot = ind.slot; + if (vnf_p7_config->_public.nr_slot_indication) { + (vnf_p7_config->_public.nr_slot_indication)(&ind); + } + } + break; + } + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: { - nfapi_nr_rach_indication_t ind; - aerial_unpack_nr_rach_indication(&pReadPackedMessage, - 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_rach_indication) { - (((vnf_info *)vnf_config->user_data)->p7_vnfs->config->nr_rach_indication)(&ind); - free(ind.pdu_list); - } + vnf_nr_handle_p7_message(msg->msg_buf, msg->msg_len, vnf_p7_config); break; } - default: { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, fapi_msg.message_id); @@ -293,10 +190,26 @@ int8_t buf[1024]; nv_ipc_config_t nv_ipc_config; -int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header) +bool aerial_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + nfapi_vnf_pnf_info_t *pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); + + if (pnf) { + uint8_t tx_messagebufferFAPI[sizeof(vnf->tx_message_buffer)]; + int packedMessageLengthFAPI = -1; + packedMessageLengthFAPI = + vnf->_public.pack_func(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); + return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg) == 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); + return false; + } +} + +bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header) { if (ipc == NULL) { - return -1; + return false; } nv_ipc_msg_t send_msg = {0}; // look for the specific message @@ -334,7 +247,7 @@ int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5 if (alloc_retval != 0) { LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); ipc->tx_release(ipc, &send_msg); - return alloc_retval; + return false; } memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); @@ -350,17 +263,17 @@ int aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5 if (send_retval < 0) { LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); ipc->tx_release(ipc, &send_msg); - return send_retval; + return false; } ipc->notify(ipc, 1); // notify that there's 1 message in queue - return 0; + return true; } -int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header) +bool aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header) { if (ipc == NULL) { - return -1; + return false; } nv_ipc_msg_t send_msg; uint8_t *pPacketBodyField = &((uint8_t *)packedBuf)[8]; @@ -421,7 +334,7 @@ int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_me if (alloc_retval != 0) { LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); ipc->tx_release(ipc, &send_msg); - return alloc_retval; + return false; } memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); @@ -437,21 +350,21 @@ int aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_me if (send_retval < 0) { LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); ipc->tx_release(ipc, &send_msg); - return send_retval; + return false; } ipc->notify(ipc, 1); // notify that there's 1 message in queue - return 0; + return true; } -int aerial_send_P7_msg_with_data(void *packedBuf, +bool aerial_send_P7_msg_with_data(void *packedBuf, uint32_t packedMsgLength, void *dataBuf, uint32_t dataLength, nfapi_nr_p7_message_header_t *header) { if (ipc == NULL) { - return -1; + return false; } nv_ipc_msg_t send_msg; uint8_t *pPacketBodyField = &((uint8_t *)packedBuf)[8]; @@ -510,7 +423,7 @@ int aerial_send_P7_msg_with_data(void *packedBuf, if (alloc_retval != 0) { LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); ipc->tx_release(ipc, &send_msg); - return alloc_retval; + return false; } memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); @@ -527,11 +440,11 @@ int aerial_send_P7_msg_with_data(void *packedBuf, if (send_retval != 0) { LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); ipc->tx_release(ipc, &send_msg); - return send_retval; + return false; } ipc->notify(ipc, 1); // notify that there's 1 message in queue - return 0; + return true; } // Always allocate message buffer, but allocate data buffer only when data_len > 0 @@ -656,6 +569,87 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s) sleep(1); create_recv_thread(nvipc_params_s.nvipc_poll_core); while(!recv_task_running){usleep(100000);} - aerial_pnf_nr_connection_indication_cb(vnf_config, 1); + nfapi_nr_param_response_scf_t resp_msg; + vnf_config->nr_param_resp(vnf_config, 1, &resp_msg); return 0; } + +int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + + ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; + + // int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_tti_req->header); + + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + // Reset number of PDUs so that it is not resent + ul_tti_req->n_pdus = 0; + ul_tti_req->n_group = 0; + ul_tti_req->n_ulcch = 0; + ul_tti_req->n_ulsch = 0; + } + return retval; +} + +int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; + // int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_dci_req->header); + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + ul_dci_req->numPdus = 0; + } + return retval; +} + +int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; + // LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN), + // tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &tx_data_req->header); + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + tx_data_req->Number_of_PDUs = 0; + } + + return retval; +} + +int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) +{ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; + dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &dl_config_req->header); + dl_config_req->dl_tti_request_body.nPDUs = 0; + dl_config_req->dl_tti_request_body.nGroup = 0; + + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } + return retval; +} + +int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){ + nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot}; + int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &nr_slot_resp.header); + if (retval != 0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } + return retval; +} + diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 5b8b995964..482d8103f0 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -36,6 +36,7 @@ #include "nv_ipc_utils.h" #include "nvlog.h" #include "nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h" +#include "vnf.h" #include "debug.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" @@ -47,14 +48,19 @@ typedef struct { uint32_t message_length; } fapi_phy_api_msg; -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, +bool aerial_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len); +bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header); +bool aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header); +bool aerial_send_P7_msg_with_data(void *packedBuf, 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); - +int oai_fapi_send_end_request(int cell_id, uint32_t frame, uint32_t slot); +int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); +int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); +int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); +int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); #endif // OPENAIRINTERFACE_FAPI_NVIPC_H diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p5.c b/nfapi/oai_integration/aerial/fapi_vnf_p5.c deleted file mode 100644 index 1b01fd6c09..0000000000 --- a/nfapi/oai_integration/aerial/fapi_vnf_p5.c +++ /dev/null @@ -1,610 +0,0 @@ -/* -* 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 fapi/oai-integration/fapi_vnf_p5.c -* \brief OAI FAPI VNF P5 message handler procedures -* \author Ruben S. Silva -* \date 2023 -* \version 0.1 -* \company OpenAirInterface Software Alliance -* \email: contact@openairinterface.org, rsilva@allbesmart.pt -* \note -* \warning - */ - -#include "fapi_vnf_p5.h" -#include "fapi_vnf_p7.h" -#include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h" -#include "nr_fapi.h" -#include "nr_fapi_p5.h" - -extern RAN_CONTEXT_t RC; -extern UL_RCC_IND_t UL_RCC_INFO; -extern int sf_ahead; -extern int slot_ahead; - -void *aerial_vnf_nr_p7_config_init(void *ptr) -{ - vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; - - init_queue(&gnb_rach_ind_queue); - init_queue(&gnb_rx_ind_queue); - init_queue(&gnb_crc_ind_queue); - init_queue(&gnb_uci_ind_queue); - - p7_vnf->config->port = p7_vnf->local_port; - p7_vnf->config->sync_indication = NULL; - p7_vnf->config->slot_indication = NULL; - p7_vnf->config->harq_indication = NULL; - p7_vnf->config->nr_crc_indication = &aerial_phy_nr_crc_indication; - p7_vnf->config->nr_rx_data_indication = &aerial_phy_nr_rx_data_indication; - p7_vnf->config->nr_rach_indication = &aerial_phy_nr_rach_indication; - p7_vnf->config->nr_uci_indication = &aerial_phy_nr_uci_indication; - p7_vnf->config->srs_indication = NULL; - p7_vnf->config->sr_indication = NULL; - p7_vnf->config->cqi_indication = NULL; - p7_vnf->config->lbt_dl_indication = NULL; - p7_vnf->config->nb_harq_indication = NULL; - p7_vnf->config->nrach_indication = NULL; - p7_vnf->config->nr_slot_indication = &aerial_phy_nr_slot_indication; - p7_vnf->config->nr_srs_indication = &aerial_phy_nr_srs_indication; - p7_vnf->config->malloc = &aerial_vnf_allocate; - p7_vnf->config->free = &aerial_vnf_deallocate; - p7_vnf->config->vendor_ext = &aerial_phy_vendor_ext; - p7_vnf->config->user_data = p7_vnf; - p7_vnf->mac->user_data = p7_vnf; - p7_vnf->config->codec_config.unpack_p7_vendor_extension = &aerial_phy_unpack_p7_vendor_extension; - p7_vnf->config->codec_config.pack_p7_vendor_extension = &aerial_phy_pack_p7_vendor_extension; - p7_vnf->config->codec_config.unpack_vendor_extension_tlv = &aerial_phy_unpack_vendor_extension_tlv; - p7_vnf->config->codec_config.pack_vendor_extension_tlv = &aerial_phy_pack_vendor_extension_tlv; - p7_vnf->config->codec_config.allocate = &aerial_vnf_allocate; - p7_vnf->config->codec_config.deallocate = &aerial_vnf_deallocate; - p7_vnf->config->allocate_p7_vendor_ext = &aerial_phy_allocate_p7_vendor_ext; - p7_vnf->config->deallocate_p7_vendor_ext = &aerial_phy_deallocate_p7_vendor_ext; - - return 0; -} - - -int aerial_pnf_nr_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) -{ - printf("[VNF] pnf connection indication idx:%d\n", p5_idx); - // in aerial, send first CONFIG.request, not PARAM.request - nfapi_nr_config_request_scf_t conf_req; - memset(&conf_req, 0, sizeof(conf_req)); - conf_req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; - printf("Try to send first CONFIG.request\n"); - aerial_nr_send_config_request(config, p5_idx); - return 0; -} - -int aerial_pnf_disconnection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] pnf disconnection indication idx:%d\n", p5_idx); - vnf_info *vnf = (vnf_info *)(config->user_data); - pnf_info *pnf = vnf->pnfs; - phy_info *phy = pnf->phys; - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - nfapi_vnf_p7_del_pnf((p7_vnf->config), phy->id); - return 0; -} - -int aerial_pnf_nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_param_response_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] pnf param response idx:%d error:%d\n", p5_idx, resp->error_code); - vnf_info *vnf = (vnf_info *)(config->user_data); - pnf_info *pnf = vnf->pnfs; - - for (int i = 0; i < resp->pnf_phy.number_of_phys; ++i) { - phy_info phy; - memset(&phy, 0, sizeof(phy)); - phy.index = resp->pnf_phy.phy[i].phy_config_index; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) phy_config_idx:%d\n", i, resp->pnf_phy.phy[i].phy_config_index); - nfapi_vnf_allocate_phy(config, p5_idx, &(phy.id)); - - for (int j = 0; j < resp->pnf_phy.phy[i].number_of_rfs; ++j) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) (RF%d) %d\n", i, j, resp->pnf_phy.phy[i].rf_config[j].rf_config_index); - phy.rfs[0] = resp->pnf_phy.phy[i].rf_config[j].rf_config_index; - } - - pnf->phys[0] = phy; - } - nfapi_nr_pnf_config_request_t req; - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_PNF_CONFIG_REQUEST; - req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG; - req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // DJP pnf.phys.size(); - NFAPI_TRACE(NFAPI_TRACE_INFO, "DJP:Hard coded num phy rf to 2\n"); - - for (unsigned i = 0; i < 2; ++i) { - req.pnf_phy_rf_config.phy_rf_config[i].phy_id = pnf->phys[i].id; - req.pnf_phy_rf_config.phy_rf_config[i].phy_config_index = pnf->phys[i].index; - req.pnf_phy_rf_config.phy_rf_config[i].rf_config_index = pnf->phys[i].rfs[0]; - } - - nfapi_nr_vnf_pnf_config_req(config, p5_idx, &req); - return 0; -} - -int aerial_pnf_nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_config_response_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] pnf config response idx:%d resp[header[phy_id:%u message_id:%02x message_length:%u]]\n", - p5_idx, - resp->header.phy_id, - resp->header.message_id, - resp->header.message_length); - - if (1) { - nfapi_nr_pnf_start_request_t req; - memset(&req, 0, sizeof(req)); - req.header.phy_id = resp->header.phy_id; - req.header.message_id = NFAPI_PNF_START_REQUEST; - nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); - } else { - // Rather than send the pnf_start_request we will demonstrate - // sending a vendor extention message. The start request will be - // send when the vendor extension response is received - // vnf_info* vnf = (vnf_info*)(config->user_data); - vendor_ext_p5_req req; - memset(&req, 0, sizeof(req)); - req.header.message_id = P5_VENDOR_EXT_REQ; - req.dummy1 = 45; - req.dummy2 = 1977; - nfapi_vnf_vendor_extension(config, p5_idx, &req.header); - } - - return 0; -} - -int aerial_pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_start_response_t *resp) -{ - vnf_info *vnf = (vnf_info *)(config->user_data); - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - pnf_info *pnf = vnf->pnfs; - nfapi_nr_param_request_scf_t req; - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", - p5_idx, - config, - config->user_data, - vnf->p7_vnfs[0].config, - vnf->p7_vnfs[0].thread_started); - - aerial_vnf_nr_p7_config_init(p7_vnf); - - // start all the phys in the pnf. - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST; - req.header.phy_id = pnf->phys[0].id; - nfapi_nr_vnf_param_req(config, p5_idx, &req); - return 0; -} - -int aerial_nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_response_scf_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_PARAM_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); - vnf_info *vnf = (vnf_info *)(config->user_data); - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - pnf_info *pnf = vnf->pnfs; - phy_info *phy = pnf->phys; - struct sockaddr_in pnf_p7_sockaddr; - nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; // check - phy->remote_port = resp->nfapi_config.p7_pnf_port.value; - // phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; - memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); - phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr); - // for now just 1 - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", - p5_idx, - phy->id, - phy->remote_addr, - phy->remote_port, - p7_vnf->timing_window, - p7_vnf->periodic_timing_period, - p7_vnf->aperiodic_timing_enabled, - p7_vnf->periodic_timing_period); - req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; - req->header.phy_id = phy->id; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Send NFAPI_CONFIG_REQUEST\n"); - // NFAPI_TRACE(NFAPI_TRACE_INFO, "\n NR bandP =%d\n",req->nfapi_config.rf_bands.rf_band[0]); - - req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; - req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port; - req->num_tlv++; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_port:%d\n", ntohs(p7_vnf->local_port)); - req->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; - struct sockaddr_in vnf_p7_sockaddr; - vnf_p7_sockaddr.sin_addr.s_addr = inet_addr(p7_vnf->local_addr); - memcpy(&(req->nfapi_config.p7_vnf_address_ipv4.address[0]), &vnf_p7_sockaddr.sin_addr.s_addr, 4); - req->num_tlv++; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_addr:%s\n", p7_vnf->local_addr); - req->nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; - req->nfapi_config.timing_window.value = p7_vnf->timing_window; - NFAPI_TRACE(NFAPI_TRACE_INFO, - "\n[VNF]Timing window tag : %d Timing window:%u\n", - NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, - p7_vnf->timing_window); - req->num_tlv++; - - if (p7_vnf->periodic_timing_enabled || p7_vnf->aperiodic_timing_enabled) { - req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; - req->nfapi_config.timing_info_mode.value = (p7_vnf->aperiodic_timing_enabled << 1) | (p7_vnf->periodic_timing_enabled); - req->num_tlv++; - - if (p7_vnf->periodic_timing_enabled) { - req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; - req->nfapi_config.timing_info_period.value = p7_vnf->periodic_timing_period; - req->num_tlv++; - } - } - // TODO: Assign tag and value for P7 message offsets - req->nfapi_config.dl_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_DL_TTI_TIMING_OFFSET; - req->nfapi_config.ul_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_TTI_TIMING_OFFSET; - req->nfapi_config.ul_dci_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_DCI_TIMING_OFFSET; - req->nfapi_config.tx_data_timing_offset.tl.tag = NFAPI_NR_NFAPI_TX_DATA_TIMING_OFFSET; - - vendor_ext_tlv_2 ve2; - memset(&ve2, 0, sizeof(ve2)); - ve2.tl.tag = VENDOR_EXT_TLV_2_TAG; - ve2.dummy = 2016; - req->vendor_extension = &ve2.tl; - nfapi_nr_vnf_config_req(config, p5_idx, req); - printf("[VNF] Sent NFAPI_VNF_CONFIG_REQ num_tlv:%u\n", req->num_tlv); - return 0; -} - -int aerial_nr_send_config_request(nfapi_vnf_config_t *config, int p5_idx) -{ - vnf_info *vnf = (vnf_info *)(config->user_data); - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - pnf_info *pnf = vnf->pnfs; - phy_info *phy = pnf->phys; - - nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; - - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", - p5_idx, - phy->id, - phy->remote_addr, - phy->remote_port, - p7_vnf->timing_window, - p7_vnf->periodic_timing_period, - p7_vnf->aperiodic_timing_enabled, - p7_vnf->periodic_timing_period); - req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; - 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); - - if (vnf_phy == NULL) { - printf("%s failed to find phy information phy_id:%d\n", __FUNCTION__, req->header.phy_id); - return -1; - } - - 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; - packedMessageLengthFAPI = - fapi_nr_p5_message_pack(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &_this->_public.codec_config); - - aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg); - - return 0; -} - -int aerial_nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_config_response_scf_t *resp) -{ - nfapi_nr_start_request_scf_t req; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_CONFIG_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); - LOG_I(NFAPI_VNF, "Received CONFIG.response, gNB is ready! \n"); - - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_REQUEST; - req.header.phy_id = resp->header.phy_id; - nfapi_nr_vnf_start_req(config, p5_idx, &req); - return 0; -} - -int aerial_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_response_scf_t *resp) -{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_START_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); - return 0; -} - -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 (((nfapi_nr_p4_p5_message_header_t *)msg)->message_id) { - case P5_VENDOR_EXT_RSP: { - vendor_ext_p5_rsp *rsp = (vendor_ext_p5_rsp *)msg; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] P5_VENDOR_EXT_RSP error_code:%d\n", rsp->error_code); - // send the start request - nfapi_nr_pnf_start_request_t req; - memset(&req, 0, sizeof(req)); - req.header.message_id = NFAPI_PNF_START_REQUEST; - nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); - } break; - } - - return 0; -} - -int aerial_vnf_unpack_vendor_extension_tlv(nfapi_tl_t *tl, - uint8_t **ppReadPackedMessage, - uint8_t *end, - void **ve, - nfapi_p4_p5_codec_config_t *codec) -{ - return -1; -} - -int aerial_vnf_pack_vendor_extension_tlv(void *vext, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) -{ - nfapi_tl_t *tlv = (nfapi_tl_t *)vext; - - switch (tlv->tag) { - case VENDOR_EXT_TLV_2_TAG: { - vendor_ext_tlv_2 *ve = (vendor_ext_tlv_2 *)tlv; - - if (!push32(ve->dummy, ppWritePackedMsg, end)) - return 0; - - return 1; - } break; - } - - return -1; -} - -int aerial_vnf_unpack_p4_p5_vendor_extension(void *header, - uint8_t **ppReadPackedMessage, - uint8_t *end, - nfapi_p4_p5_codec_config_t *codec) -{ - if (((nfapi_nr_p4_p5_message_header_t *)header)->message_id == P5_VENDOR_EXT_RSP) { - vendor_ext_p5_rsp *req = (vendor_ext_p5_rsp *)(header); - return (!pull16(ppReadPackedMessage, &req->error_code, end)); - } - - return 0; -} - -int aerial_vnf_pack_p4_p5_vendor_extension(void *header, - uint8_t **ppWritePackedMsg, - uint8_t *end, - nfapi_p4_p5_codec_config_t *codec) -{ - 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))); - } - - return 0; -} - -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 malloc(sizeof(vendor_ext_p5_rsp)); - } - - return 0; -} - -void aerial_vnf_deallocate_p4_p5_vendor_ext(void *header) -{ - free(header); -} - -void *aerial_vnf_p5_allocate(size_t size) -{ - // return (void*)memory_pool::allocate(size); - return (void *)malloc(size); -} - -void aerial_vnf_p5_deallocate(void *ptr) -{ - // memory_pool::deallocate((uint8_t*)ptr); - free(ptr); -} - -static vnf_info aerial_vnf; -void aerial_configure_nr_fapi_vnf() -{ - // TODO: Implement for FAPI - // nfapi_setmode(NFAPI_MODE_VNF); - memset(&aerial_vnf, 0, sizeof(aerial_vnf)); - memset(aerial_vnf.p7_vnfs, 0, sizeof(aerial_vnf.p7_vnfs)); - aerial_vnf.p7_vnfs[0].timing_window = 30; - aerial_vnf.p7_vnfs[0].periodic_timing_enabled = 0; - aerial_vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; - aerial_vnf.p7_vnfs[0].periodic_timing_period = 10; - aerial_vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); - aerial_vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); - nfapi_vnf_config_t *config = nfapi_vnf_config_create(); - config->malloc = malloc; - config->free = free; - config->vnf_ipv4 = 1; - config->vnf_ipv6 = 0; - config->pnf_list = 0; - config->phy_list = 0; - - config->pnf_nr_connection_indication = &aerial_pnf_nr_connection_indication_cb; - config->pnf_disconnect_indication = &aerial_pnf_disconnection_indication_cb; - - config->pnf_nr_param_resp = &aerial_pnf_nr_param_resp_cb; - config->pnf_nr_config_resp = &aerial_pnf_nr_config_resp_cb; - config->pnf_nr_start_resp = &aerial_pnf_nr_start_resp_cb; - config->nr_param_resp = &aerial_nr_param_resp_cb; - config->nr_config_resp = &aerial_nr_config_resp_cb; - config->nr_start_resp = &aerial_nr_start_resp_cb; - config->vendor_ext = &aerial_vendor_ext_cb; - config->user_data = &aerial_vnf; - // To allow custom vendor extentions to be added to nfapi - config->codec_config.unpack_vendor_extension_tlv = &aerial_vnf_unpack_vendor_extension_tlv; - config->codec_config.pack_vendor_extension_tlv = &aerial_vnf_pack_vendor_extension_tlv; - config->codec_config.unpack_p4_p5_vendor_extension = &aerial_vnf_unpack_p4_p5_vendor_extension; - config->codec_config.pack_p4_p5_vendor_extension = &aerial_vnf_pack_p4_p5_vendor_extension; - config->allocate_p4_p5_vendor_ext = &aerial_vnf_allocate_p4_p5_vendor_ext; - config->deallocate_p4_p5_vendor_ext = &aerial_vnf_deallocate_p4_p5_vendor_ext; - config->codec_config.allocate = &aerial_vnf_allocate; - config->codec_config.deallocate = &aerial_vnf_deallocate; - memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_IND_t)); - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); - set_config(config); - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); - nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t)); - NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); - memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); - pnf->p5_idx = 1; - pnf->connected = 1; - // Add needed parameters - - vnf_info *vnf = (vnf_info *)(config->user_data); - pnf_info *pnf_info = vnf->pnfs; - - for (int i = 0; i < 1; ++i) { - phy_info phy; - memset(&phy, 0, sizeof(phy)); - phy.index = 0; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) phy_config_idx:%d\n", i, 0); - nfapi_vnf_allocate_phy(config, 1, &(phy.id)); - - for (int j = 0; j < 1; ++j) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) (RF%d) %d\n", i, j, 0); - phy.rfs[0] = 0; - } - - pnf_info->phys[0] = phy; - } - - - nfapi_vnf_pnf_list_add(config, pnf); - - vnf_p7_info *p7_vnf = vnf->p7_vnfs; - - NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", - 1, - config, - config->user_data, - vnf->p7_vnfs[0].config, - vnf->p7_vnfs[0].thread_started); - - aerial_vnf_nr_p7_config_init(p7_vnf); -} -uint8_t aerial_unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) -{ - return unpack_nr_param_response(ppReadPackedMsg, end, msg, config); -} -uint8_t aerial_unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) -{ - return unpack_nr_config_response(ppReadPackedMsg, end, msg, config); -} - -int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - - ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; - - // int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_tti_req->header); - - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } else { - // Reset number of PDUs so that it is not resent - ul_tti_req->n_pdus = 0; - ul_tti_req->n_group = 0; - ul_tti_req->n_ulcch = 0; - ul_tti_req->n_ulsch = 0; - } - return retval; -} - -int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; - // int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &ul_dci_req->header); - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } else { - ul_dci_req->numPdus = 0; - } - return retval; -} - -int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; - // LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN), - // tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &tx_data_req->header); - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } else { - tx_data_req->Number_of_PDUs = 0; - } - - return retval; -} - -int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) -{ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; - dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &dl_config_req->header); - dl_config_req->dl_tti_request_body.nPDUs = 0; - dl_config_req->dl_tti_request_body.nGroup = 0; - - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } - return retval; -} - -int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){ - nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config; - nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot}; - int retval = fapi_nr_pack_and_send_p7_message((vnf_p7_t *)p7_config, &nr_slot_resp.header); - if (retval != 0) { - LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); - } - return retval; -} diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p5.h b/nfapi/oai_integration/aerial/fapi_vnf_p5.h deleted file mode 100644 index 84fb3ec2f8..0000000000 --- a/nfapi/oai_integration/aerial/fapi_vnf_p5.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -* 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 fapi/oai-integration/fapi_vnf_p5.h -* \brief Header file for fapi_vnf_p5.c -* \author Ruben S. Silva -* \date 2023 -* \version 0.1 -* \company OpenAirInterface Software Alliance -* \email: contact@openairinterface.org, rsilva@allbesmart.pt -* \note -* \warning - */ - -#ifndef OPENAIRINTERFACE_FAPI_VNF_P5_H -#define OPENAIRINTERFACE_FAPI_VNF_P5_H -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfapi_nr_interface_scf.h" -#include "nfapi_vnf_interface.h" -#include "nfapi_vnf.h" -#include "nfapi.h" -#include "nfapi/oai_integration/vendor_ext.h" -#include "fapi_nvIPC.h" - -#include "PHY/defs_eNB.h" -#include "PHY/LTE_TRANSPORT/transport_proto.h" - -#include "common/ran_context.h" -#include "openair2/PHY_INTERFACE/queue_t.h" -#include "gnb_ind_vars.h" -#include "nfapi/open-nFAPI/vnf/inc/vnf.h" - -void aerial_configure_nr_fapi_vnf(); -int aerial_nr_send_config_request(nfapi_vnf_config_t *config, int p5_idx); -int oai_fapi_send_end_request(int cell_id, uint32_t frame, uint32_t slot); -uint8_t aerial_unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config); -uint8_t aerial_unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config); -int aerial_pnf_nr_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx); - -int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); -int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); -int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); -int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); -#endif //OPENAIRINTERFACE_FAPI_VNF_P5_H diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c index cb8fa4550f..d9e3e0027b 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c @@ -35,200 +35,6 @@ #include "nr_fapi_p7.h" #include "nr_fapi_p7_utils.h" -#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" // for handle_nr_srs_measurements() - -extern pthread_cond_t nfapi_sync_cond; -extern pthread_mutex_t nfapi_sync_mutex; -extern int nfapi_sync_var; - -int aerial_phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) -{ - nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind)); - copy_crc_indication(ind, crc_ind); - if (!put_queue(&gnb_crc_ind_queue, crc_ind)) { - LOG_E(NR_MAC, "Put_queue failed for crc_ind\n"); - free_crc_indication(crc_ind); - free(crc_ind); - } - return 1; -} - -int aerial_phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) -{ - nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind)); - copy_rx_data_indication(ind, rx_ind); - if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { - LOG_E(NR_MAC, "Put_queue failed for rx_ind\n"); - free_rx_data_indication(rx_ind); - free(rx_ind); - } - return 1; -} - -int aerial_phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) -{ - nfapi_nr_rach_indication_t *rach_ind = CALLOC(1, sizeof(*rach_ind)); - copy_rach_indication(ind, rach_ind); - if (!put_queue(&gnb_rach_ind_queue, rach_ind)) { - LOG_E(NR_MAC, "Put_queue failed for rach_ind\n"); - free_rach_indication(rach_ind); - free(rach_ind); - } else { - LOG_I(NR_MAC, "RACH.indication put_queue successfull\n"); - } - return 1; -} - -int aerial_phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) -{ - nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind)); - AssertFatal(uci_ind, "Memory not allocated for uci_ind in phy_nr_uci_indication."); - copy_uci_indication(ind, uci_ind); - if (!put_queue(&gnb_uci_ind_queue, uci_ind)) { - LOG_E(NR_MAC, "Put_queue failed for uci_ind\n"); - free_uci_indication(uci_ind); - free(uci_ind); - uci_ind = NULL; - } - return 1; -} - -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slot, NR_Sched_Rsp_t* sched_info); -int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); -int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); -int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t* tx_data_req); -int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t* ul_dci_req); -int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot); -extern int trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind); - -int aerial_phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) -{ - LOG_D(MAC, "VNF SFN/Slot %d.%d \n", ind->sfn, ind->slot); - trigger_scheduler(ind); - - return 1; -} - -int aerial_phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) -{ - // or queue to decouple, but I think it should be fast (in all likelihood, - // the VNF has nothing to do) - for (int i = 0; i < ind->number_of_pdus; ++i) - handle_nr_srs_measurements(0, ind->sfn, ind->slot, &ind->pdu_list[i]); - return 1; -} - -void *aerial_vnf_allocate(size_t size) -{ - // return (void*)memory_pool::allocate(size); - return (void *)malloc(size); -} - -void aerial_vnf_deallocate(void *ptr) -{ - // memory_pool::deallocate((uint8_t*)ptr); - free(ptr); -} - -int aerial_phy_vendor_ext(struct nfapi_vnf_p7_config *config, void *msg) -{ - if (((nfapi_nr_p7_message_header_t *)msg)->message_id == P7_VENDOR_EXT_IND) { - // vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)msg; - // NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] vendor_ext (error_code:%d)\n", ind->error_code); - } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] unknown %02x\n", ((nfapi_nr_p7_message_header_t *)msg)->message_id); - } - - return 0; -} - -int aerial_phy_unpack_p7_vendor_extension(void *header, - uint8_t **ppReadPackedMessage, - uint8_t *end, - nfapi_p7_codec_config_t *config) -{ - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_IND) { - vendor_ext_p7_ind *req = (vendor_ext_p7_ind *)(header); - - if (!pull16(ppReadPackedMessage, &req->error_code, end)) - return 0; - } - - return 1; -} - -int aerial_phy_pack_p7_vendor_extension(void *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) -{ - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - if (((nfapi_nr_p7_message_header_t *)header)->message_id == P7_VENDOR_EXT_REQ) { - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - vendor_ext_p7_req *req = (vendor_ext_p7_req *)(header); - - if (!(push16(req->dummy1, ppWritePackedMsg, end) && push16(req->dummy2, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -int aerial_phy_unpack_vendor_extension_tlv(nfapi_tl_t *tl, - uint8_t **ppReadPackedMessage, - uint8_t *end, - void **ve, - nfapi_p7_codec_config_t *codec) -{ - (void)tl; - (void)ppReadPackedMessage; - (void)ve; - return -1; -} - -int aerial_phy_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *codec) -{ - // NFAPI_TRACE(NFAPI_TRACE_INFO, "phy_pack_vendor_extension_tlv\n"); - nfapi_tl_t *tlv = (nfapi_tl_t *)ve; - - switch (tlv->tag) { - case VENDOR_EXT_TLV_1_TAG: { - // NFAPI_TRACE(NFAPI_TRACE_INFO, "Packing VENDOR_EXT_TLV_1\n"); - vendor_ext_tlv_1 *ve = (vendor_ext_tlv_1 *)tlv; - - if (!push32(ve->dummy, ppWritePackedMsg, end)) - return 0; - - return 1; - } break; - - default: - return -1; - break; - } -} - -void *aerial_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) -{ - if (message_id == P7_VENDOR_EXT_IND) { - *msg_size = sizeof(vendor_ext_p7_ind); - return (nfapi_nr_p7_message_header_t *)malloc(sizeof(vendor_ext_p7_ind)); - } - - return 0; -} - -void aerial_phy_deallocate_p7_vendor_ext(void *header) -{ - free(header); -} - -uint8_t aerial_unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_slot_indication_scf_t *msg, - nfapi_p7_codec_config_t *config) -{ - return unpack_nr_slot_indication(ppReadPackedMsg, end, msg, config); -} - static uint8_t aerial_unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, uint8_t **ppReadPackedMsg, uint8_t *end, @@ -247,6 +53,7 @@ static uint8_t aerial_unpack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t * return 1; } + uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, uint8_t **pDataMsg, @@ -273,11 +80,11 @@ uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, } // After unpacking the PDU headers, unpack the PDU data from the separate buffer for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) { - if(!pullarray8(pDataMsg, - pNfapiMsg->pdu_list[i].pdu, - pNfapiMsg->pdu_list[i].pdu_length, - pNfapiMsg->pdu_list[i].pdu_length, - data_end)){ + if (!pullarray8(pDataMsg, + pNfapiMsg->pdu_list[i].pdu, + pNfapiMsg->pdu_list[i].pdu_length, + pNfapiMsg->pdu_list[i].pdu_length, + data_end)) { return 0; } } @@ -285,19 +92,6 @@ uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, return 1; } -uint8_t aerial_unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - nfapi_nr_crc_indication_t *msg, - nfapi_p7_codec_config_t *config) -{ - return unpack_nr_crc_indication(ppReadPackedMsg, end, msg, config); -} - -uint8_t aerial_unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) -{ - return unpack_nr_uci_indication(ppReadPackedMsg, end, msg, config); -} - uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, uint8_t **pDataMsg, @@ -316,20 +110,13 @@ uint8_t aerial_unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, return retval; } -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) -{ - return unpack_nr_rach_indication(ppReadPackedMsg, end, msg, config); -} - static int32_t aerial_pack_tx_data_request(void *pMessageBuf, void *pPackedBuf, void *pDataBuf, uint32_t packedBufLen, uint32_t dataBufLen, nfapi_p7_codec_config_t *config, + nfapi_vnf_p7_config_t *p7_config, uint32_t *data_len) { if (pMessageBuf == NULL || pPackedBuf == NULL) { @@ -386,16 +173,15 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, uintptr_t dataEnd = (uintptr_t)pPackedDataField; data_len[0] = dataEnd - dataHead; - - if (!fapi_nr_p7_message_pack(pMessageBuf, pPackedBuf, packedBufLen, config)) { - return -1; - } + if (!p7_config->pack_func(pMessageBuf, pPackedBuf, packedBufLen, config)) { + return -1; + } return (int32_t)(pMessageHeader->message_length); } -int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) +bool aerial_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) { uint8_t FAPI_buffer[1024 * 64]; // Check if TX_DATA request, if true, need to pack to data_buf @@ -414,17 +200,20 @@ int fapi_nr_pack_and_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_heade sizeof(FAPI_buffer), sizeof(FAPI_data_buffer), &vnf_p7->_public.codec_config, + ((nfapi_vnf_p7_config_t *)vnf_p7), &data_len); if (len_FAPI <= 0) { LOG_E(NFAPI_VNF, "Problem packing TX_DATA_request\n"); - return len_FAPI; + return false; } else { - int retval = aerial_send_P7_msg_with_data(FAPI_buffer, len_FAPI, FAPI_data_buffer, data_len, header); - return retval; + return aerial_send_P7_msg_with_data(FAPI_buffer, len_FAPI, FAPI_data_buffer, data_len, header) == 0; } } else { // Create and send FAPI P7 message - int len_FAPI = fapi_nr_p7_message_pack(header, FAPI_buffer, sizeof(FAPI_buffer), &vnf_p7->_public.codec_config); - return aerial_send_P7_msg(FAPI_buffer, len_FAPI, header); + int len_FAPI = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(header, + FAPI_buffer, + sizeof(FAPI_buffer), + &vnf_p7->_public.codec_config); + return aerial_send_P7_msg(FAPI_buffer, len_FAPI, header) == 0; } } diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.h b/nfapi/oai_integration/aerial/fapi_vnf_p7.h index ca75b02276..3722411578 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.h +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.h @@ -47,187 +47,21 @@ #include "nfapi_interface.h" #include "nfapi_nr_interface_scf.h" #include "nfapi_vnf_interface.h" -#include "nfapi_vnf.h" -#include "nfapi.h" -#include "nfapi/oai_integration/vendor_ext.h" #include "fapi_nvIPC.h" - -#include "PHY/defs_eNB.h" -#include "PHY/LTE_TRANSPORT/transport_proto.h" -#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" -#include "lte-softmodem.h" - -#include "common/ran_context.h" #include "openair2/PHY_INTERFACE/queue_t.h" -#include "gnb_ind_vars.h" -#include "nfapi/open-nFAPI/vnf/inc/vnf.h" #include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h" -typedef struct { - uint8_t enabled; - uint32_t rx_port; - uint32_t tx_port; - char tx_addr[80]; -} udp_data; - -typedef struct { - uint16_t index; - uint16_t id; - uint8_t rfs[2]; - uint8_t excluded_rfs[2]; - - udp_data udp; - - char local_addr[80]; - int local_port; - - char *remote_addr; - int remote_port; - - uint8_t duplex_mode; - uint16_t dl_channel_bw_support; - uint16_t ul_channel_bw_support; - uint8_t num_dl_layers_supported; - uint8_t num_ul_layers_supported; - uint16_t release_supported; - uint8_t nmm_modes_supported; - - uint8_t dl_ues_per_subframe; - uint8_t ul_ues_per_subframe; - - uint8_t first_subframe_ind; - - // timing information recevied from the vnf - uint8_t timing_window; - uint8_t timing_info_mode; - uint8_t timing_info_period; - -} phy_info; - -typedef struct { - uint16_t index; - uint16_t band; - int16_t max_transmit_power; - int16_t min_transmit_power; - uint8_t num_antennas_supported; - uint32_t min_downlink_frequency; - uint32_t max_downlink_frequency; - uint32_t max_uplink_frequency; - uint32_t min_uplink_frequency; -} rf_info; - -typedef struct { - int release; - phy_info phys[2]; - rf_info rfs[2]; - - uint8_t sync_mode; - uint8_t location_mode; - uint8_t location_coordinates[6]; - uint32_t dl_config_timing; - uint32_t ul_config_timing; - uint32_t tx_timing; - uint32_t hi_dci0_timing; - - uint16_t max_phys; - uint16_t max_total_bw; - uint16_t max_total_dl_layers; - uint16_t max_total_ul_layers; - uint8_t shared_bands; - uint8_t shared_pa; - int16_t max_total_power; - uint8_t oui; - - uint8_t wireshark_test_mode; - -} pnf_info; - -typedef struct mac mac_t; -typedef struct mac { - void *user_data; - - void (*dl_config_req)(mac_t *mac, nfapi_dl_config_request_t *req); - void (*ul_config_req)(mac_t *mac, nfapi_ul_config_request_t *req); - void (*hi_dci0_req)(mac_t *mac, nfapi_hi_dci0_request_t *req); - void (*tx_req)(mac_t *mac, nfapi_tx_request_t *req); -} mac_t; - -typedef struct { - int local_port; - char local_addr[80]; - - unsigned timing_window; - unsigned periodic_timing_enabled; - unsigned aperiodic_timing_enabled; - unsigned periodic_timing_period; - - // This is not really the right place if we have multiple PHY, - // should be part of the phy struct - udp_data udp; - - uint8_t thread_started; - - nfapi_vnf_p7_config_t *config; - - mac_t *mac; - -} vnf_p7_info; - -typedef struct { - uint8_t wireshark_test_mode; - pnf_info pnfs[2]; - vnf_p7_info p7_vnfs[2]; - -} vnf_info; - -int aerial_phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind); -int aerial_phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); -int aerial_phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind); -int aerial_phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind); -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, 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(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); -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, - nfapi_nr_slot_indication_scf_t *msg, - nfapi_p7_codec_config_t *config); uint8_t aerial_unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, uint8_t **pDataMsg, uint8_t *data_end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t *config); -uint8_t aerial_unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, - uint8_t *end, - 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, 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_nr_p7_message_header_t *header); +bool aerial_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header); #endif // OPENAIRINTERFACE_FAPI_VNF_P7_H diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 21b3e1e90e..48e31b7264 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "fapi_stub.h" @@ -62,6 +63,16 @@ #include "executables/lte-softmodem.h" #include "nfapi/open-nFAPI/pnf/inc/pnf_p7.h" +#ifdef ENABLE_WLS +#include +#include +#include "nfapi/oai_integration/wls_integration/include/wls_pnf.h" +#endif + +#ifdef ENABLE_SOCKET +#include +#endif + #define NUM_P5_PHY 2 #define _GNU_SOURCE @@ -185,7 +196,7 @@ typedef struct { } pnf_phy_user_data_t; static pnf_info pnf; -static pthread_t pnf_start_pthread; +static pthread_t pnf_p5_init_and_receive_pthread; int nfapitooai_level(int nfapi_level) { switch(nfapi_level) { @@ -219,12 +230,7 @@ void *pnf_p7_thread_start(void *ptr) { return 0; } -void *pnf_nr_p7_thread_start(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[NR_PNF] NR P7 THREAD %s\n", __FUNCTION__); - nfapi_pnf_p7_config_t *config = (nfapi_pnf_p7_config_t *)ptr; - nfapi_nr_pnf_p7_start(config); - return 0; -} + int pnf_nr_param_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_param_request_t *req) { @@ -991,6 +997,10 @@ int nr_config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n phy_info->timing_window, req->nfapi_config.timing_window.value); num_tlv++; + }else { + // This is a nFAPI TLV, thus not sent when working with FAPI. + // When not sent, we still need a default value, otherwise every message from the L2 is treated as late and not processed + phy_info->timing_window = 30; } if (req->nfapi_config.timing_info_mode.tl.tag == NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG) { @@ -1747,9 +1757,26 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf p7_config->codec_config.pack_p7_vendor_extension = &pnf_nr_phy_pack_p7_vendor_extension; p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_nr_phy_unpack_vendor_extension_tlv; p7_config->codec_config.pack_vendor_extension_tlv = &pnf_nr_phy_pack_vendor_extention_tlv; + +#ifdef ENABLE_WLS + p7_config->unpack_func = &fapi_nr_p7_message_unpack; + p7_config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; + p7_config->pack_func = &fapi_nr_p7_message_pack; + p7_config->send_p7_msg = &wls_pnf_nr_send_p7_message; + // pass p7_config to WLS handler + wls_pnf_set_p7_config(p7_config); +#endif + +#ifdef ENABLE_SOCKET + p7_config->unpack_func = &nfapi_nr_p7_message_unpack; + p7_config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; + p7_config->pack_func = &nfapi_nr_p7_message_pack; + p7_config->send_p7_msg = &pnf_nr_send_p7_message; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__); pthread_t p7_thread; threadCreate(&p7_thread, &pnf_nr_p7_thread_start, p7_config, "pnf_p7_thread", -1, OAI_PRIORITY_RT); +#endif + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__); l1_north_init_gNB(); NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__); @@ -1794,10 +1821,11 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf usleep(50000); printf("[PNF] waiting for OAI to be started\n"); } - +#ifndef ENABLE_WLS printf("[PNF] Sending PNF_START_RESP\n"); nfapi_nr_send_pnf_start_resp(config, p7_config->phy_id); printf("[PNF] Sending first P7 slot indication\n"); +#endif #if 1 nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0); printf("[PNF] Sent first P7 slot ind\n"); @@ -2132,15 +2160,6 @@ void *pnf_start_thread(void *ptr) { return (void *)0; } -void *pnf_nr_start_thread(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); - nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; - struct sched_param sp; - sp.sched_priority = 20; - pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); - nfapi_nr_pnf_start(config); - return (void *)0; -} void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { @@ -2188,9 +2207,29 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->deallocate_p4_p5_vendor_ext = &pnf_nr_sim_deallocate_p4_p5_vendor_ext; config->codec_config.unpack_p4_p5_vendor_extension = &pnf_nr_sim_unpack_p4_p5_vendor_extension; config->codec_config.pack_p4_p5_vendor_extension = &pnf_nr_sim_pack_p4_p5_vendor_extension; + +#ifdef ENABLE_WLS + printf("WLS MODE PNF\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating WLS PNF NFAPI start thread %s\n", __FUNCTION__); + // Assume it's the FAPI handler, change from within the PNF if it's not the case + config->unpack_func = &fapi_nr_p5_message_unpack; + config->hdr_unpack_func = &fapi_nr_message_header_unpack; + config->pack_func = &fapi_nr_p5_message_pack; + config->send_p5_msg = &wls_pnf_nr_send_p5_message; + //wls_fapi_pnf_nr_start_thread(config); + threadCreate(&pnf_p5_init_and_receive_pthread, wls_fapi_pnf_nr_start_thread, config, "NFAPI_WLS_PNF", -1, OAI_PRIORITY_RT_MAX); +#endif + +#ifdef ENABLE_SOCKET NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&pnf_start_pthread, NULL, &pnf_nr_start_thread, config); - pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); + config->unpack_func = &nfapi_nr_p5_message_unpack; + config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; + config->pack_func = &nfapi_nr_p5_message_pack; + config->send_p5_msg = &pnf_nr_send_p5_message; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); + pthread_create(&pnf_p5_init_and_receive_pthread, NULL, &pnf_start_p5_thread, config); + pthread_setname_np(pnf_p5_init_and_receive_pthread, "NFAPI_PNF"); +#endif } void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { @@ -2240,8 +2279,8 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, config->codec_config.unpack_p4_p5_vendor_extension = &pnf_sim_unpack_p4_p5_vendor_extension; config->codec_config.pack_p4_p5_vendor_extension = &pnf_sim_pack_p4_p5_vendor_extension; NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&pnf_start_pthread, NULL, &pnf_start_thread, config); - pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); + pthread_create(&pnf_p5_init_and_receive_pthread, NULL, &pnf_start_thread, config); + pthread_setname_np(pnf_p5_init_and_receive_pthread, "NFAPI_PNF"); } void oai_subframe_ind(uint16_t sfn, uint16_t sf) { @@ -2300,7 +2339,11 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) //send VNF slot indication, which is aligned with TX thread, so that it can call the scheduler //we give four additional slots (2ms) which should be enough time for the VNF to //answer +#ifndef ENABLE_WLS int slot_ahead = 2 << mu; +#else + int slot_ahead = 1; +#endif uint16_t sfn_tx = sfn; uint16_t slot_tx = slot; sfnslot_add_slot(mu, &sfn_tx, &slot_tx, slot_ahead); // modify: do in place diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index e30c939c83..5ea99de7ea 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -32,8 +32,19 @@ #include #include "nfapi_nr_interface_scf.h" -#include "nfapi_vnf_interface.h" #include "nfapi_vnf.h" +#include +#include +#ifdef ENABLE_WLS +#include +#include "nr_fapi_p5.h" +#include "nr_fapi_p7.h" +#endif + +#ifdef ENABLE_SOCKET +#include +#endif + #include "nfapi.h" #include "vendor_ext.h" @@ -48,10 +59,14 @@ #include "openair2/PHY_INTERFACE/queue_t.h" #include "gnb_ind_vars.h" #include "nr_fapi_p7_utils.h" +#include "nr_fapi_p5_utils.h" #include #ifdef ENABLE_AERIAL -#include "aerial/fapi_vnf_p5.h" +#include "aerial/fapi_nvIPC.h" +#include "aerial/fapi_vnf_p7.h" +#include "nr_fapi_p5.h" +#include "nr_fapi_p7.h" #endif #define TEST @@ -59,128 +74,6 @@ extern RAN_CONTEXT_t RC; extern UL_RCC_IND_t UL_RCC_INFO; -typedef struct { - uint8_t enabled; - uint32_t rx_port; - uint32_t tx_port; - char tx_addr[80]; -} udp_data; - -typedef struct { - uint16_t index; - uint16_t id; - uint8_t rfs[2]; - uint8_t excluded_rfs[2]; - - udp_data udp; - - char local_addr[80]; - int local_port; - - char *remote_addr; - int remote_port; - - uint8_t duplex_mode; - uint16_t dl_channel_bw_support; - uint16_t ul_channel_bw_support; - uint8_t num_dl_layers_supported; - uint8_t num_ul_layers_supported; - uint16_t release_supported; - uint8_t nmm_modes_supported; - - uint8_t dl_ues_per_subframe; - uint8_t ul_ues_per_subframe; - - uint8_t first_subframe_ind; - - // timing information recevied from the vnf - uint8_t timing_window; - uint8_t timing_info_mode; - uint8_t timing_info_period; - -} phy_info; - -typedef struct { - uint16_t index; - uint16_t band; - int16_t max_transmit_power; - int16_t min_transmit_power; - uint8_t num_antennas_supported; - uint32_t min_downlink_frequency; - uint32_t max_downlink_frequency; - uint32_t max_uplink_frequency; - uint32_t min_uplink_frequency; -} rf_info; - -typedef struct { - - int release; - phy_info phys[2]; - rf_info rfs[2]; - - uint8_t sync_mode; - uint8_t location_mode; - uint8_t location_coordinates[6]; - uint32_t dl_config_timing; - uint32_t ul_config_timing; - uint32_t tx_timing; - uint32_t hi_dci0_timing; - - uint16_t max_phys; - uint16_t max_total_bw; - uint16_t max_total_dl_layers; - uint16_t max_total_ul_layers; - uint8_t shared_bands; - uint8_t shared_pa; - int16_t max_total_power; - uint8_t oui; - - uint8_t wireshark_test_mode; - -} pnf_info; - -typedef struct mac mac_t; - -typedef struct mac { - - void *user_data; - - void (*dl_config_req)(mac_t *mac, nfapi_dl_config_request_t *req); - void (*ul_config_req)(mac_t *mac, nfapi_ul_config_request_t *req); - void (*hi_dci0_req)(mac_t *mac, nfapi_hi_dci0_request_t *req); - void (*tx_req)(mac_t *mac, nfapi_tx_request_t *req); -} mac_t; - -typedef struct { - - int local_port; - char local_addr[80]; - - unsigned timing_window; - unsigned periodic_timing_enabled; - unsigned aperiodic_timing_enabled; - unsigned periodic_timing_period; - - // This is not really the right place if we have multiple PHY, - // should be part of the phy struct - udp_data udp; - - uint8_t thread_started; - - nfapi_vnf_p7_config_t *config; - - mac_t *mac; - -} vnf_p7_info; - -typedef struct { - - uint8_t wireshark_test_mode; - pnf_info pnfs[2]; - vnf_p7_info p7_vnfs[2]; - -} vnf_info; - int vnf_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "vnf_pack_vendor_extension_tlv\n"); nfapi_tl_t *tlv = (nfapi_tl_t *)ve; @@ -707,7 +600,7 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_rach_indication_t *rach_ind = CALLOC(1, sizeof(*rach_ind)); copy_rach_indication(ind, rach_ind); if (!put_queue(&gnb_rach_ind_queue, rach_ind)) { @@ -724,7 +617,7 @@ int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", __FUNCTION__, ind->sfn, ind->slot, ind->num_ucis); - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind)); AssertFatal(uci_ind, "Memory not allocated for uci_ind in phy_nr_uci_indication."); copy_uci_indication(ind, uci_ind); @@ -829,7 +722,7 @@ int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { LOG_D(NR_MAC, "In %s() NFAPI SFN/SF: %d/%d number_of_pdus :%u\n", __FUNCTION__, ind->sfn, ind->slot, ind->number_crcs); - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind)); copy_crc_indication(ind, crc_ind); if (!put_queue(&gnb_crc_ind_queue, crc_ind)) { @@ -930,7 +823,7 @@ int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) ind->number_of_pdus, ind->pdu_list[0].pdu); - if (NFAPI_MODE == NFAPI_MODE_VNF) { + if (NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL) { nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind)); copy_rx_data_indication(ind, rx_ind); if (!put_queue(&gnb_rx_ind_queue, rx_ind)) { @@ -1389,16 +1282,9 @@ int vnf_nr_pack_p4_p5_vendor_extension(void *header, uint8_t **ppWritePackedMsg, return 0; } -static pthread_t vnf_start_pthread; +static pthread_t vnf_p5_init_and_receive_pthread; static pthread_t vnf_p7_start_pthread; -void *vnf_nr_p7_start_thread(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - pthread_setname_np(pthread_self(), "VNF_P7"); - nfapi_vnf_p7_config_t *config = (nfapi_vnf_p7_config_t *)ptr; - nfapi_nr_vnf_p7_start(config); - return config; -} void *vnf_p7_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); @@ -1408,7 +1294,7 @@ void *vnf_p7_start_thread(void *ptr) { return config; } -void *vnf_nr_p7_thread_start(void *ptr) +void *configure_nr_p7_vnf(void *ptr) { init_queue(&gnb_rach_ind_queue); init_queue(&gnb_rx_ind_queue); @@ -1417,19 +1303,23 @@ void *vnf_nr_p7_thread_start(void *ptr) vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; p7_vnf->config->port = p7_vnf->local_port; +#ifndef ENABLE_AERIAL p7_vnf->config->sync_indication = &phy_sync_indication; p7_vnf->config->slot_indication = &phy_slot_indication; p7_vnf->config->harq_indication = &phy_harq_indication; +#endif p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; p7_vnf->config->nr_rx_data_indication = &phy_nr_rx_data_indication; p7_vnf->config->nr_rach_indication = &phy_nr_rach_indication; p7_vnf->config->nr_uci_indication = &phy_nr_uci_indication; +#ifndef ENABLE_AERIAL p7_vnf->config->srs_indication = &phy_srs_indication; p7_vnf->config->sr_indication = &phy_sr_indication; p7_vnf->config->cqi_indication = &phy_cqi_indication; p7_vnf->config->lbt_dl_indication = &phy_lbt_dl_indication; p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication; p7_vnf->config->nrach_indication = &phy_nrach_indication; +#endif p7_vnf->config->nr_slot_indication = &phy_nr_slot_indication; p7_vnf->config->nr_srs_indication = &phy_nr_srs_indication; p7_vnf->config->malloc = &vnf_allocate; @@ -1445,8 +1335,30 @@ void *vnf_nr_p7_thread_start(void *ptr) p7_vnf->config->codec_config.deallocate = &vnf_deallocate; p7_vnf->config->allocate_p7_vendor_ext = &phy_nr_allocate_p7_vendor_ext; p7_vnf->config->deallocate_p7_vendor_ext = &phy_nr_deallocate_p7_vendor_ext; + +#ifdef ENABLE_WLS + p7_vnf->config->unpack_func = &fapi_nr_p7_message_unpack; + p7_vnf->config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; + p7_vnf->config->pack_func = &fapi_nr_p7_message_pack; + p7_vnf->config->send_p7_msg = &wls_vnf_nr_send_p7_message; + wls_vnf_set_p7_config(p7_vnf->config); +#endif + +#ifdef ENABLE_SOCKET + p7_vnf->config->unpack_func = &nfapi_nr_p7_message_unpack; + p7_vnf->config->hdr_unpack_func = &nfapi_nr_p7_message_header_unpack; + p7_vnf->config->pack_func = &nfapi_nr_p7_message_pack; + p7_vnf->config->send_p7_msg = &vnf_nr_send_p7_msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); - pthread_create(&vnf_p7_start_pthread, NULL, &vnf_nr_p7_start_thread, p7_vnf->config); + threadCreate(&vnf_p7_start_pthread, &vnf_nr_start_p7_thread, p7_vnf->config, "vnf_p7_thread", -1, OAI_PRIORITY_RT); +#endif + +#ifdef ENABLE_AERIAL + p7_vnf->config->unpack_func = &fapi_nr_p7_message_unpack; + p7_vnf->config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; + p7_vnf->config->pack_func = &fapi_nr_p7_message_pack; + p7_vnf->config->send_p7_msg = &aerial_nr_send_p7_message; +#endif return 0; } @@ -1494,7 +1406,7 @@ int pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_st if(p7_vnf->thread_started == 0) { pthread_t vnf_p7_thread; - threadCreate(&vnf_p7_thread, &vnf_nr_p7_thread_start, p7_vnf, "vnf_p7_thread", -1, OAI_PRIORITY_RT); + threadCreate(&vnf_p7_thread, &configure_nr_p7_vnf, p7_vnf, "vnf_p7_thread", -1, OAI_PRIORITY_RT); p7_vnf->thread_started = 1; } else { // P7 thread already running. @@ -1504,7 +1416,12 @@ int pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_st NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST; +#ifdef ENABLE_WLS + req.header.phy_id = 0; +#endif +#ifdef ENABLE_SOCKET req.header.phy_id = pnf->phys[0].id; +#endif nfapi_nr_vnf_param_req(config, p5_idx, &req); return 0; } @@ -1542,8 +1459,9 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp vnf_p7_info *p7_vnf = vnf->p7_vnfs; pnf_info *pnf = vnf->pnfs; phy_info *phy = pnf->phys; - struct sockaddr_in pnf_p7_sockaddr; nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; // check +#ifndef ENABLE_AERIAL + struct sockaddr_in pnf_p7_sockaddr; phy->remote_port = resp->nfapi_config.p7_pnf_port.value; //phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); @@ -1551,6 +1469,7 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp // for now just 1 NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", p5_idx, phy->id, phy->remote_addr, phy->remote_port, p7_vnf->timing_window, p7_vnf->periodic_timing_period, p7_vnf->aperiodic_timing_enabled, p7_vnf->periodic_timing_period); +#endif // Hack? the VNF might need the subcarrier spacing for some calculations // (that we actually don't use as of now...). We therefore need to save the // mu, for the current PNF connection (together with where we have frame/slot @@ -1566,7 +1485,7 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp req->header.phy_id = phy->id; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Send NFAPI_CONFIG_REQUEST\n"); //NFAPI_TRACE(NFAPI_TRACE_INFO, "\n NR bandP =%d\n",req->nfapi_config.rf_bands.rf_band[0]); - +#ifndef ENABLE_AERIAL req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port; req->num_tlv++; @@ -1604,6 +1523,7 @@ req->nfapi_config.tx_data_timing_offset.tl.tag = NFAPI_NR_NFAPI_TX_DATA_TIMING_O ve2.tl.tag = VENDOR_EXT_TLV_2_TAG; ve2.dummy = 2016; req->vendor_extension = &ve2.tl; +#endif nfapi_nr_vnf_config_req(config, p5_idx, req); printf("[VNF] Sent NFAPI_VNF_CONFIG_REQ num_tlv:%u\n",req->num_tlv); return 0; @@ -1703,6 +1623,21 @@ int nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_resp return 0; } +int nr_error_ind_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_error_indication_scf_t *resp) +{ + NFAPI_TRACE(NFAPI_TRACE_WARN, + "[VNF] Received NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION idx:%d phy_id:%d\n", + p5_idx, + resp->header.phy_id); + NFAPI_TRACE(NFAPI_TRACE_WARN, "[VNF] Previous message 0x%02x resulted in an error on the PNF \n", resp->message_id); + NFAPI_TRACE(NFAPI_TRACE_WARN, + "[VNF] Received error code 0x%02x (%s)\n", + resp->error_code, + error_ind_code_to_str(resp->error_code)); + // TODO: add error handling to the VNF instead of only reporting the received error + return 0; +} + int vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, void *msg) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s\n", __FUNCTION__); @@ -1794,28 +1729,19 @@ void vnf_nr_deallocate_p4_p5_vendor_ext(void *header) { free(header); } - -nfapi_vnf_config_t *config = 0; - -void vnf_nr_start_thread(void *ptr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); - pthread_setname_np(pthread_self(), "VNF"); - config = (nfapi_vnf_config_t *)ptr; - nfapi_nr_vnf_start(config); -} - void vnf_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); pthread_setname_np(pthread_self(), "VNF"); - config = (nfapi_vnf_config_t *)ptr; - nfapi_vnf_start(config); + nfapi_vnf_start((nfapi_vnf_config_t *)ptr); } static vnf_info vnf; -void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) +void configure_nr_nfapi_vnf(eth_params_t params) { +#ifndef ENABLE_AERIAL nfapi_setmode(NFAPI_MODE_VNF); +#endif memset(&vnf, 0, sizeof(vnf)); memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); vnf.p7_vnfs[0].timing_window = 30; @@ -1823,19 +1749,21 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; vnf.p7_vnfs[0].periodic_timing_period = 1; vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); +#ifndef ENABLE_AERIAL NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, - vnf_addr, - vnf_p5_port); - strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); - vnf.p7_vnfs[0].local_port = vnf_p7_port; + params.my_addr, + params.my_portc); + strcpy(vnf.p7_vnfs[0].local_addr, params.my_addr); + vnf.p7_vnfs[0].local_port = params.my_portd; +#endif vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); nfapi_vnf_config_t *config = nfapi_vnf_config_create(); config->malloc = malloc; config->free = free; - config->vnf_p5_port = vnf_p5_port; + config->vnf_p5_port = params.my_portc; config->vnf_ipv4 = 1; config->vnf_ipv6 = 0; config->pnf_list = 0; @@ -1850,6 +1778,7 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, config->nr_param_resp = &nr_param_resp_cb; config->nr_config_resp = &nr_config_resp_cb; config->nr_start_resp = &nr_start_resp_cb; + config->nr_error_ind = &nr_error_ind_cb; config->vendor_ext = &vendor_nr_ext_cb; config->user_data = &vnf; // To allow custom vendor extentions to be added to nfapi @@ -1862,9 +1791,73 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, config->codec_config.allocate = &vnf_nr_allocate; config->codec_config.deallocate = &vnf_nr_deallocate; memset(&UL_RCC_INFO, 0, sizeof(UL_RCC_IND_t)); + +#ifdef ENABLE_WLS + config->unpack_func = &fapi_nr_p5_message_unpack; + config->hdr_unpack_func = &fapi_nr_message_header_unpack; + config->pack_func = &fapi_nr_p5_message_pack; + config->send_p5_msg = &wls_vnf_nr_send_p5_message; + printf("WLS MODE PNF\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating WLS VNF NFAPI start thread %s\n", __FUNCTION__); + //wls_fapi_pnf_nr_start_thread(config); + threadCreate(&vnf_p5_init_and_receive_pthread, wls_fapi_vnf_nr_start_thread, config, "NFAPI_WLS_VNF", -1, OAI_PRIORITY_RT_MAX); +#endif + +#ifdef ENABLE_SOCKET + config->unpack_func = &nfapi_nr_p5_message_unpack; + config->hdr_unpack_func = &nfapi_nr_p5_message_header_unpack; + config->pack_func = &nfapi_nr_p5_message_pack; + config->send_p5_msg = &vnf_nr_send_p5_msg; NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_nr_start_thread, config); + pthread_create(&vnf_p5_init_and_receive_pthread, NULL, (void *)&vnf_start_p5_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); +#endif +#ifdef ENABLE_AERIAL + config->unpack_func = &fapi_nr_p5_message_unpack; + config->hdr_unpack_func = &fapi_nr_message_header_unpack; + config->pack_func = &fapi_nr_p5_message_pack; + config->send_p5_msg = &aerial_nr_send_p5_message; + set_config(config); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); + nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); + memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); + pnf->p5_idx = 1; + pnf->connected = 1; + // Add needed parameters + + vnf_info *vnf = (vnf_info *)(config->user_data); + pnf_info *pnf_info = vnf->pnfs; + + for (int i = 0; i < 1; ++i) { + phy_info phy; + memset(&phy, 0, sizeof(phy)); + phy.index = 0; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) phy_config_idx:%d\n", i, 0); + nfapi_vnf_allocate_phy(config, 1, &(phy.id)); + + for (int j = 0; j < 1; ++j) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] (PHY:%d) (RF%d) %d\n", i, j, 0); + phy.rfs[0] = 0; + } + + pnf_info->phys[0] = phy; + } + + + nfapi_vnf_pnf_list_add(config, pnf); + + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + + NFAPI_TRACE(NFAPI_TRACE_INFO, + "[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", + 1, + config, + config->user_data, + vnf->p7_vnfs[0].config, + vnf->p7_vnfs[0].thread_started); + configure_nr_p7_vnf(p7_vnf); +#endif } @@ -1912,7 +1905,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int config->codec_config.deallocate = &vnf_deallocate; memset(&UL_RCC_INFO,0,sizeof(UL_RCC_IND_t)); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); - pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_start_thread, config); + pthread_create(&vnf_p5_init_and_receive_pthread, NULL, (void *)&vnf_start_thread, config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); } @@ -1957,13 +1950,13 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! - int retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); + bool retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } return retval; @@ -1976,9 +1969,9 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) tx_data_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); - int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + bool retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { tx_data_req->Number_of_PDUs = 0; @@ -2009,9 +2002,9 @@ int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { ul_dci_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; //LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi); - int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); + bool retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { ul_dci_req->numPdus = 0; @@ -2062,9 +2055,9 @@ int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { ul_tti_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; - int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); + bool retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); - if (retval!=0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { // Reset number of PDUs so that it is not resent diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 71cc50c2f7..104cff44f4 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -21,8 +21,132 @@ #ifndef NFAPI_VNF_H_ #define NFAPI_VNF_H_ +#include + +#include "nfapi_vnf_interface.h" +typedef struct { + uint8_t enabled; + uint32_t rx_port; + uint32_t tx_port; + char tx_addr[80]; +} udp_data; + +typedef struct { + uint16_t index; + uint16_t id; + uint8_t rfs[2]; + uint8_t excluded_rfs[2]; + + udp_data udp; + + char local_addr[80]; + int local_port; + + char *remote_addr; + int remote_port; + + uint8_t duplex_mode; + uint16_t dl_channel_bw_support; + uint16_t ul_channel_bw_support; + uint8_t num_dl_layers_supported; + uint8_t num_ul_layers_supported; + uint16_t release_supported; + uint8_t nmm_modes_supported; + + uint8_t dl_ues_per_subframe; + uint8_t ul_ues_per_subframe; + + uint8_t first_subframe_ind; + + // timing information recevied from the vnf + uint8_t timing_window; + uint8_t timing_info_mode; + uint8_t timing_info_period; + +} phy_info; + +typedef struct { + uint16_t index; + uint16_t band; + int16_t max_transmit_power; + int16_t min_transmit_power; + uint8_t num_antennas_supported; + uint32_t min_downlink_frequency; + uint32_t max_downlink_frequency; + uint32_t max_uplink_frequency; + uint32_t min_uplink_frequency; +} rf_info; + +typedef struct { + + int release; + phy_info phys[2]; + rf_info rfs[2]; + + uint8_t sync_mode; + uint8_t location_mode; + uint8_t location_coordinates[6]; + uint32_t dl_config_timing; + uint32_t ul_config_timing; + uint32_t tx_timing; + uint32_t hi_dci0_timing; + + uint16_t max_phys; + uint16_t max_total_bw; + uint16_t max_total_dl_layers; + uint16_t max_total_ul_layers; + uint8_t shared_bands; + uint8_t shared_pa; + int16_t max_total_power; + uint8_t oui; + + uint8_t wireshark_test_mode; + +} pnf_info; + +typedef struct mac mac_t; + +typedef struct mac { + + void *user_data; + + void (*dl_config_req)(mac_t *mac, nfapi_dl_config_request_t *req); + void (*ul_config_req)(mac_t *mac, nfapi_ul_config_request_t *req); + void (*hi_dci0_req)(mac_t *mac, nfapi_hi_dci0_request_t *req); + void (*tx_req)(mac_t *mac, nfapi_tx_request_t *req); +} mac_t; + +typedef struct { + + int local_port; + char local_addr[80]; + + unsigned timing_window; + unsigned periodic_timing_enabled; + unsigned aperiodic_timing_enabled; + unsigned periodic_timing_period; + + // This is not really the right place if we have multiple PHY, + // should be part of the phy struct + udp_data udp; + + uint8_t thread_started; + + nfapi_vnf_p7_config_t *config; + + mac_t *mac; + +} vnf_p7_info; + +typedef struct { + + uint8_t wireshark_test_mode; + pnf_info pnfs[2]; + vnf_p7_info p7_vnfs[2]; + +} vnf_info; void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); -void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); +void configure_nr_nfapi_vnf(eth_params_t params); #endif /* NFAPI_VNF_H_ */ diff --git a/nfapi/oai_integration/socket/CMakeLists.txt b/nfapi/oai_integration/socket/CMakeLists.txt new file mode 100644 index 0000000000..57cad36362 --- /dev/null +++ b/nfapi/oai_integration/socket/CMakeLists.txt @@ -0,0 +1,14 @@ +add_library(nfapi_socket_lib + socket_pnf.c + socket_vnf.c + socket_common.c +) + +target_include_directories(nfapi_socket_lib PRIVATE include/) + +target_compile_definitions(nfapi_socket_lib PUBLIC ENABLE_SOCKET) +target_link_libraries(nfapi_socket_lib PRIVATE NFAPI_LIB NFAPI_USER_LIB) +target_link_libraries(nfapi_socket_lib PRIVATE LOG) +add_dependencies(nfapi_socket_lib generate_T) +target_link_libraries(nfapi_socket_lib PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_link_libraries(nfapi_socket_lib PRIVATE nr_fapi_p5 nr_fapi_p7) diff --git a/nfapi/oai_integration/socket/include/socket_common.h b/nfapi/oai_integration/socket/include/socket_common.h new file mode 100644 index 0000000000..1817507733 --- /dev/null +++ b/nfapi/oai_integration/socket/include/socket_common.h @@ -0,0 +1,45 @@ +/* + * 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 SOCKET_COMMON_H +#define SOCKET_COMMON_H + +#define _GNU_SOURCE /* required for pthread_getname_np */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int socket_send_p5_msg(const int sctp, + const int socket, + const void* remote_addr, + const void* msg, + const uint32_t len, + const uint16_t stream); +int socket_send_p7_msg(const int socket, const void* remote_addr, const void* msg, const uint32_t len); + +#endif // SOCKET_COMMON_H diff --git a/nfapi/oai_integration/socket/include/socket_pnf.h b/nfapi/oai_integration/socket/include/socket_pnf.h new file mode 100644 index 0000000000..ccb3eaea3a --- /dev/null +++ b/nfapi/oai_integration/socket/include/socket_pnf.h @@ -0,0 +1,39 @@ +/* + * 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 SOCKET_PNF_H +#define SOCKET_PNF_H +#include "socket_common.h" +#include +#include +#include +#include "pnf.h" +#include "pnf_p7.h" +#include "nr_fapi_p5.h" +#include "nr_nfapi_p7.h" + +int pnf_connect_socket(pnf_t *pnf); +int pnf_nr_message_pump(pnf_t *pnf); +bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len); +bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); +void *pnf_start_p5_thread(void *ptr); +void *pnf_nr_p7_thread_start(void *ptr); +#endif // SOCKET_PNF_H diff --git a/nfapi/oai_integration/socket/include/socket_vnf.h b/nfapi/oai_integration/socket/include/socket_vnf.h new file mode 100644 index 0000000000..c11e009153 --- /dev/null +++ b/nfapi/oai_integration/socket/include/socket_vnf.h @@ -0,0 +1,34 @@ +/* + * 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 SOCKET_VNF_H +#define SOCKET_VNF_H +#include "socket_common.h" +#include "vnf.h" +#include "vnf_p7.h" +#include "nr_fapi_p5.h" +#include "nr_nfapi_p7.h" +#include "nr_fapi_p7.h" +bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t* header); +void vnf_start_p5_thread(void* ptr); +void* vnf_nr_start_p7_thread(void* ptr); +#endif // SOCKET_VNF_H diff --git a/nfapi/oai_integration/socket/socket_common.c b/nfapi/oai_integration/socket/socket_common.c new file mode 100644 index 0000000000..5ec9a13ac6 --- /dev/null +++ b/nfapi/oai_integration/socket/socket_common.c @@ -0,0 +1,58 @@ +/* + * 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 "socket_common.h" +#include "LOG/log.h" + +int socket_send_p5_msg(const int sctp, + const int socket, + const void* remote_addr, + const void* msg, + const uint32_t len, + const uint16_t stream) +{ + if (sctp == 1) { + struct sockaddr* to = (struct sockaddr*)remote_addr; + const int retval = sctp_sendmsg(socket, msg, len, to, 0, 42, 0, stream, 0, 0); + if (retval < 0) { + LOG_E(NR_PHY, "sctp_sendmsg failed errno: %d\n", errno); + return -1; + } + } else { + if (send(socket, msg, len, 0) != len) { + LOG_E(NR_PHY, "write failed errno: %d\n", errno); + return -1; + } + } + + return len; +} + +int socket_send_p7_msg(const int socket, const void* remote_addr, const void* msg, const uint32_t len) +{ + const struct sockaddr* to = (struct sockaddr*)remote_addr; + const long sendto_result = sendto(socket, msg, len, 0, to, sizeof(struct sockaddr_in)); + if (sendto_result != len) { + LOG_E(NR_PHY, "%s() sendto_result %ld %d\n", __FUNCTION__, sendto_result, errno); + return -1; + } + + return 0; +} diff --git a/nfapi/oai_integration/socket/socket_pnf.c b/nfapi/oai_integration/socket/socket_pnf.c new file mode 100644 index 0000000000..fe4999c998 --- /dev/null +++ b/nfapi/oai_integration/socket/socket_pnf.c @@ -0,0 +1,867 @@ +/* + * 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 "socket_pnf.h" +#include "nfapi.h" + +bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + int packed_len = + pnf->_public.pack_func(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "p5_message_pack failed (%d)\n", packed_len); + return false; + } + + return socket_send_p5_msg(pnf->sctp, pnf->p5_sock, NULL, pnf->tx_message_buffer, packed_len, 0) == packed_len; +} + +static int send_p7_msg(pnf_p7_t *pnf_p7, uint8_t *msg, uint32_t len) +{ + // todo : consider how to do this only once + struct sockaddr_in remote_addr = {.sin_family = AF_INET, .sin_port = htons(pnf_p7->_public.remote_p7_port)}; + + if (inet_aton(pnf_p7->_public.remote_p7_addr, &remote_addr.sin_addr) == -1) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "inet_aton failed %d\n", errno); + return -1; + } + + socklen_t remote_addr_len = sizeof(struct sockaddr_in); + + int sendto_result = socket_send_p7_msg((int)pnf_p7->p7_sock, &remote_addr, msg, len); + if (sendto_result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%s %s:%d sendto(%d, %p, %d) %d failed errno: %d\n", + __FUNCTION__, + pnf_p7->_public.remote_p7_addr, + pnf_p7->_public.remote_p7_port, + (int)pnf_p7->p7_sock, + (const char *)msg, + len, + remote_addr_len, + errno); + return -1; + } + + if (sendto_result != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s sendto failed to send the entire message %d %d\n", __FUNCTION__, sendto_result, len); + } + return 0; +} + +bool pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *header, uint32_t msg_len) +{ + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS(0, 0, pnf_p7->sequence_number); + + // Need to guard against different threads calling the encode function at the same time + if (pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return false; + } + + uint8_t tx_buf[131072]; // four times NFAPI_MAX_PACKED_MESSAGE_SIZE as of this commit + int len = pnf_p7->_public.pack_func(header, tx_buf, sizeof(tx_buf), &pnf_p7->_public.codec_config); + + if (len < 0) { + if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return false; + } + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len); + return false; + } + + if (len > pnf_p7->_public.segment_size) { + int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH; + int seg_body_len = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_NR_P7_HEADER_LENGTH; + uint8_t buffer[pnf_p7->_public.segment_size]; + for (segment = 0; segment < segment_count; ++segment) { + uint8_t last = 0; + uint32_t size = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + if (segment + 1 == segment_count) { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&buffer[0], tx_buf, NFAPI_NR_P7_HEADER_LENGTH); + + // set the segment length , update and push m_segment_sequence + uint8_t *buf_ptr = &buffer[4]; + uint8_t *buf_ptr_end = &buffer[10]; + push32(segment_size, (&buf_ptr), buf_ptr_end); + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS((!last), segment, pnf_p7->sequence_number); + push16(header->m_segment_sequence, (&buf_ptr), buf_ptr_end); + memcpy(&buffer[NFAPI_NR_P7_HEADER_LENGTH], tx_buf + offset, size); + offset += size; + + if (pnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(buffer, segment_size); + } + + send_p7_msg(pnf_p7, &buffer[0], segment_size); + } + } else { + if (pnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(tx_buf, len); + } + + // simple case that the message fits in a single segment + send_p7_msg(pnf_p7, tx_buf, len); + } + + pnf_p7->sequence_number++; + + if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return false; + } + + return true; +} + +void *pnf_start_p5_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); + nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; + struct sched_param sp; + sp.sched_priority = 20; + pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp); + + // Verify that config is not null + if (config == 0) + return (void *)-1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_t *_this = (pnf_t *)(config); + + while (_this->terminate == 0) { + int connect_result = pnf_connect_socket(_this); + + if (connect_result > 0) { + pnf_nr_message_pump(_this); + } else if (connect_result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() Error connecting to P5 socket\n", __FUNCTION__); + return 0; + } + + sleep(1); + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__); + + return 0; +} + +int pnf_connect_socket(pnf_t *pnf) +{ + uint8_t socketConnected = 0; + + if (pnf->_public.vnf_ip_addr == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnfIpAddress is null\n"); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 PNF connection to VNF at %s:%u\n", pnf->_public.vnf_ip_addr, pnf->_public.vnf_p5_port); + + // todo split the vnf address list. currently only supporting 1 + + struct addrinfo hints = {0}, *servinfo; + + hints.ai_socktype = SOCK_STREAM; // For SCTP we are only interested in SOCK_STREAM + // todo : allow the client to restrict IPV4 or IPV6 + // todo : randomize which address to connect to? + + char port_str[8]; + snprintf(port_str, sizeof(port_str), "%d", pnf->_public.vnf_p5_port); + if (getaddrinfo(pnf->_public.vnf_ip_addr, port_str, &hints, &servinfo) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to get host (%s) addr info h_errno:%d \n", pnf->_public.vnf_ip_addr, h_errno); + return -1; + } + + struct addrinfo *p = servinfo; + int connected = 0; + + while (p != NULL && connected == 0) { +#ifdef NFAPI_TRACE_ENABLED + char *family = "Unknown"; + char *address = "Unknown"; + char _addr[128]; + + if (p->ai_family == AF_INET6) { + family = "IPV6"; + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)p->ai_addr; + inet_ntop(AF_INET6, &addr->sin6_addr, _addr, sizeof(_addr)); + address = &_addr[0]; + } else if (p->ai_family == AF_INET) { + family = "IPV4"; + struct sockaddr_in *addr = (struct sockaddr_in *)p->ai_addr; + address = inet_ntoa(addr->sin_addr); + } + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Host address info %d Family:%s Address:%s\n", i++, family, address); +#endif + + if (pnf->sctp) { + // open the SCTP socket + if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_SCTP)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + int noDelay; + struct sctp_initmsg initMsg = {0}; + + // configure the socket options + NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF Setting the SCTP_INITMSG\n"); + initMsg.sinit_num_ostreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + initMsg.sinit_max_instreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + noDelay = 1; + if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + + struct sctp_event_subscribe events = {0}; + events.sctp_data_io_event = 1; + + if (setsockopt(pnf->p5_sock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + } else { + // Create an IP socket point + if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_IP)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + freeaddrinfo(servinfo); + return -1; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created...\n"); + + if (connect(pnf->p5_sock, p->ai_addr, p->ai_addrlen) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "After connect (address:%s port:%d) errno: %d\n", + pnf->_public.vnf_ip_addr, + pnf->_public.vnf_p5_port, + errno); + + if (errno == EINVAL) { + freeaddrinfo(servinfo); + return -1; + } + if (pnf->terminate != 0) { + freeaddrinfo(servinfo); + return 0; + } + close(pnf->p5_sock); + sleep(1); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "connect succeeded...\n"); + + connected = 1; + } + + p = p->ai_next; + } + + freeaddrinfo(servinfo); + + // If we have failed to connect return 0 and it is retry + if (connected == 0) + return 0; + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "After connect loop\n"); + if (pnf->sctp) { + socklen_t optLen; + struct sctp_status status = {0}; + + // check the connection status + optLen = (socklen_t)sizeof(struct sctp_status); + if (getsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Association ID = %d\n", status.sstat_assoc_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Receiver window size = %d\n", status.sstat_rwnd); + NFAPI_TRACE(NFAPI_TRACE_INFO, "In Streams = %d\n", status.sstat_instrms); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Out Streams = %d\n", status.sstat_outstrms); + + socketConnected = 1; + } + } else { + int error; + socklen_t len = sizeof(error); + + if (getsockopt(pnf->p5_sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + // If error is zero, the socket is connected + if (error == 0) { + socketConnected = 1; + } + } + } + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Socket %s\n", socketConnected ? "CONNECTED" : "NOT_CONNECTED"); + return socketConnected; +} + +static int pnf_nr_read_dispatch_message(pnf_t *pnf) +{ + int socket_connected = 1; + + // 1. Peek the message header + // 2. If the message is larger than the stack buffer, then create a dynamic buffer + // 3. Read the buffer + // 4. Handle the p5 message + + uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + + uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure + uint8_t stack_buffer[stack_buffer_size]; + + uint8_t *dynamic_buffer = 0; + + uint8_t *read_buffer = &stack_buffer[0]; + uint32_t message_size = 0; + + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + struct sctp_sndrcvinfo sndrcvinfo = {0}; + + { + int flags = MSG_PEEK; + if (pnf->sctp) { + message_size = sctp_recvmsg(pnf->p5_sock, + header_buffer, + header_buffer_size, + /*(struct sockaddr*)&addr, &addr_len*/ + 0, + 0, + &sndrcvinfo, + &flags); + } else { + message_size = recv(pnf->p5_sock, header_buffer, header_buffer_size, flags); + } + + if (message_size < NFAPI_NR_P5_HEADER_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + + nfapi_nr_p4_p5_message_header_t header; + const bool result = pnf->_public.hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); + return 0; + } + message_size = header.message_length + header_buffer_size; + + // now have the size of the mesage + } + + if (message_size > stack_buffer_size) { + dynamic_buffer = (uint8_t *)malloc(message_size); + + if (dynamic_buffer == NULL) { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + + ssize_t recvmsg_result = 0; + if (pnf->sctp) { + recvmsg_result = + sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr *)&addr, &addr_len, &sndrcvinfo, &flags); + } else { + if ((recvmsg_result = recv(pnf->p5_sock, read_buffer, message_size, flags)) <= 0) { + recvmsg_result = -1; + } + } + if (recvmsg_result == -1) { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size error %s errno:%d\n", strerror(tmp), tmp); + } else { +#if 0 + // print the received message + printf("\n MESSAGE RECEIVED: \n"); + for(int i=0; ip5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + */ + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80 || !pnf->sctp) { + pnf_nr_handle_p5_message(pnf, read_buffer, message_size); + } else { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_WARN, + "sctp_recvmsg: unhandled mode with flags 0x%x and error %s errno:%d\n", + flags, + strerror(tmp), + tmp); + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + } + } + } + + if (dynamic_buffer) { + free(dynamic_buffer); + } + + return socket_connected; +} + +int pnf_nr_message_pump(pnf_t *pnf) +{ + uint8_t socketConnected = 1; + + while (socketConnected && pnf->terminate == 0) { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf->p5_sock, &rfds); + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + selectRetval = select(pnf->p5_sock + 1, &rfds, NULL, NULL, &timeout); + + if (selectRetval == 0) { + // timeout + continue; + } else if (selectRetval == -1 && (errno == EINTR)) { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno); + continue; + } else if (selectRetval == -1) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n"); + sleep(1); + continue; + } + + if (FD_ISSET(pnf->p5_sock, &rfds)) { + socketConnected = pnf_nr_read_dispatch_message(pnf); + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n"); + } + } + + // Drop back to idle if we have lost connection + pnf->_public.state = NFAPI_PNF_IDLE; + + // close the connection and socket + if (close(pnf->p5_sock) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno); + } + + return 0; +} + +static void pnf_nr_reassemble_nfapi_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t *pnf_p7, uint32_t rx_hr_time) +{ + nfapi_nr_p7_message_header_t messageHeader; + + // validate the input params + if (pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, pnf_p7); + return; + } + + // unpack the message header + const bool result = + pnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &pnf_p7->_public.codec_config); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + + if (pnf_p7->_public.checksum_enabled) { + uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if (checksum != messageHeader.checksum) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); + return; + } + } + + if (m == 0 && segment_num == 0) { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + pnf_nr_handle_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + } else { + pnf_p7_rx_message_t *rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, + &(pnf_p7->reassembly_queue), + rx_hr_time, + sequence_num, + segment_num, + m, + pRecvMsg, + recvMsgLen); + + if (rx_msg->num_segments_received == rx_msg->num_segments_expected) { + // send the buffer on + uint16_t i = 0; + uint32_t length = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); + } + + if (pnf_p7->reassemby_buffer_size < length) { + pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); + pnf_p7->reassemby_buffer = 0; + } + + if (pnf_p7->reassemby_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); + pnf_p7->reassemby_buffer = (uint8_t *)pnf_p7_malloc(pnf_p7, length); + + if (pnf_p7->reassemby_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(pnf_p7->reassemby_buffer, 0, length); + pnf_p7->reassemby_buffer_size = length; + } + + uint32_t offset = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + if (i == 0) { + memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } else { + memcpy(pnf_p7->reassemby_buffer + offset, + rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, + rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; + } + } + + pnf_nr_handle_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); + + // delete the structure + pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); + } + } + + // The timeout used to be 1000, i.e., 1ms, which is too short. The below 10ms + // is selected to be able to encompass any "reasonable" slot ahead time for the VNF. + // Ideally, we would remove old msg (segments) if we detect packet loss + // (e.g., if the sequence numbers advances sufficiently); in the branch of + // this commit, our goal is to make the PNF work, so we content ourselves to + // just remove very old messages. + pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 10000); +} + +static void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t *pnf_p7, uint32_t now_hr_time) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + remote_addr.sin_family = 2; // hardcoded + do { + // peek the header + uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(pnf_p7->p7_sock, + header_buffer, + NFAPI_NR_P7_HEADER_LENGTH, + MSG_DONTWAIT | MSG_PEEK, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + if (recvfrom_result > 0) { + // get the segment size + nfapi_nr_p7_message_header_t header; + pnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, 34, 0); + + // resize the buffer if we have a large segment + if (header.message_length > pnf_p7->rx_message_buffer_size) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); + pnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(pnf_p7->p7_sock, + pnf_p7->rx_message_buffer, + header.message_length, + MSG_DONTWAIT, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + + now_hr_time = pnf_get_current_time_hr(); // moved to here - get closer timestamp??? + + if (recvfrom_result > 0) { + pnf_nr_reassemble_nfapi_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); + // printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); + } + } else if (recvfrom_result == 0) { + // recv zero length message + recvfrom_result = + recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr *)&remote_addr, &remote_addr_size); + } + + if (recvfrom_result == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // return to the select + // NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + + // need to update the time as we would only use the value from the + // select + } while (recvfrom_result > 0); +} + +int pnf_nr_p7_message_pump(pnf_p7_t *pnf_p7) +{ + // initialize the mutex lock + if (pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + if (pthread_mutex_init(&(pnf_p7->pack_mutex), NULL) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + // create the pnf p7 socket + if ((pnf_p7->p7_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 socket created (%d)...\n", pnf_p7->p7_sock); + + // configure the UDP socket options + int reuseaddr_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_enable, sizeof(int)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEADDR) failed errno: %d\n", errno); + return -1; + } + + /* + int reuseport_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEPORT, &reuseport_enable, sizeof(int)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEPORT) failed errno: %d\n", errno); + return -1; + } + */ + + int iptos_value = 0; + if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); + return -1; + } + + struct sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(pnf_p7->_public.local_p7_port); + + if (pnf_p7->_public.local_p7_addr == 0) { + addr.sin_addr.s_addr = INADDR_ANY; + } else { + // addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.local_p7_addr); + if (inet_aton(pnf_p7->_public.local_p7_addr, &addr.sin_addr) == -1) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "inet_aton failed\n"); + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 binding %d too %s:%d\n", pnf_p7->p7_sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(pnf_p7->p7_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 bind error fd:%d errno: %d\n", pnf_p7->p7_sock, errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); + + // Initializaing timing structures needed for slot ticking + + struct timespec slot_start; + clock_gettime(CLOCK_MONOTONIC, &slot_start); + + struct timespec pselect_start; + + struct timespec slot_duration; + slot_duration.tv_sec = 0; + slot_duration.tv_nsec = 0.5e6; + + // Infinite loop + + while (pnf_p7->terminate == 0) { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf_p7->p7_sock, &rfds); + + struct timespec timeout; + timeout.tv_sec = 100; + timeout.tv_nsec = 0; + clock_gettime(CLOCK_MONOTONIC, &pselect_start); + + // setting the timeout + + if ((pselect_start.tv_sec > slot_start.tv_sec) + || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) { + // overran the end of the subframe we do not want to wait + timeout.tv_sec = 0; + timeout.tv_nsec = 0; + + // struct timespec overrun = pnf_timespec_sub(pselect_start, sf_start); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); + } else { + // still time before the end of the subframe wait + timeout = pnf_timespec_sub(slot_start, pselect_start); + } + + selectRetval = pselect(pnf_p7->p7_sock + 1, &rfds, NULL, NULL, &timeout, NULL); + + uint32_t now_hr_time = pnf_get_current_time_hr(); + + if (selectRetval == 0) { + // timeout + + // update slot start timing + slot_start = pnf_timespec_add(slot_start, slot_duration); + + // increment sfn/slot + if (++pnf_p7->slot == 20) { + pnf_p7->slot = 0; + pnf_p7->sfn = (pnf_p7->sfn + 1) % 1024; + } + + continue; + } else if (selectRetval == -1 && (errno == EINTR)) { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 Signal Interrupt %d\n", errno); + continue; + } else if (selectRetval == -1) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 select() failed\n"); + sleep(1); + continue; + } + + if (FD_ISSET(pnf_p7->p7_sock, &rfds)) + + { + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + } + } + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); + + // close the connection and socket + if (close(pnf_p7->p7_sock) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close failed errno: %d\n", errno); + } + + if (pthread_mutex_destroy(&(pnf_p7->pack_mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + if (pthread_mutex_destroy(&(pnf_p7->mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + return 0; +} + +static int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t *config) +{ + // Verify that config is not null + if (config == 0) + return -1; + + pnf_p7_t *_this = (pnf_p7_t *)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_nr_p7_message_pump(_this); + + return 0; +} + +void *pnf_nr_p7_thread_start(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[NR_PNF] NR P7 THREAD %s\n", __FUNCTION__); + nfapi_pnf_p7_config_t *config = (nfapi_pnf_p7_config_t *)ptr; + nfapi_nr_pnf_p7_start(config); + return 0; +} diff --git a/nfapi/oai_integration/socket/socket_vnf.c b/nfapi/oai_integration/socket/socket_vnf.c new file mode 100644 index 0000000000..6440109ed6 --- /dev/null +++ b/nfapi/oai_integration/socket/socket_vnf.c @@ -0,0 +1,847 @@ +/* + * 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 "socket_vnf.h" + +#include "nfapi.h" +#include "nfapi/oai_integration/vendor_ext.h" //TODO: Remove this include when removing the Aerial transport stuff + +static bool send_p5_msg(vnf_t *vnf, nfapi_vnf_pnf_info_t *pnf, const void *msg, int len, uint8_t stream) +{ + int result = socket_send_p5_msg(vnf->sctp, pnf->p5_sock, &pnf->p5_pnf_sockaddr, msg, len, stream); + + if (result != len) { + if (result < 0) { + // error + NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp sendto failed errno: %d\n", errno); + } else { + // did not send the entire message + } + } + return result == len; +} + +bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + nfapi_vnf_pnf_info_t *pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); + + if (pnf) { + // pack the message for transmission + int packedMessageLength = 0; + + packedMessageLength = + vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); + + if (packedMessageLength < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed with return %d\n", packedMessageLength); + return false; + } + + return send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); + return false; + } +} + +bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) +{ + nfapi_vnf_p7_connection_info_t *p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); + if (p7_connection) { + int send_result = 0; + uint8_t buffer[1024 * 1024 * 3]; + + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS(0, 0, p7_connection->sequence_number); + + int len = vnf_p7->_public.pack_func(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config); + + if (len < 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id); + return false; + } + + if (len > vnf_p7->_public.segment_size) { + // todo : consider replacing with the sendmmsg call + // todo : worry about blocking writes? + + // segmenting the transmit + int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH; + int seg_body_len = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_NR_P7_HEADER_LENGTH; + uint8_t tx_buffer[vnf_p7->_public.segment_size]; + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", + __FUNCTION__, + header->phy_id, + len, + vnf_p7->_public.segment_size); + for (segment = 0; segment < segment_count; ++segment) { + uint8_t last = 0; + uint16_t size = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; + if (segment + 1 == segment_count) { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&tx_buffer[0], buffer, NFAPI_NR_P7_HEADER_LENGTH); + + // set the segment length, update and push m_segment_sequence + uint8_t *buf_ptr = &tx_buffer[4]; + uint8_t *buf_ptr_end = &tx_buffer[10]; + push32(segment_size, (&buf_ptr), buf_ptr_end); + header->m_segment_sequence = NFAPI_NR_P7_SET_MSS((!last), segment, p7_connection->sequence_number); + push16(header->m_segment_sequence, (&buf_ptr), buf_ptr_end); + + memcpy(&tx_buffer[NFAPI_NR_P7_HEADER_LENGTH], &buffer[0] + offset, size); + offset += size; + + if (vnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(tx_buffer, segment_size); + } + const uint32_t time = + calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr); + nfapi_nr_p7_update_transmit_timestamp(tx_buffer, time); + send_result = socket_send_p7_msg(vnf_p7->socket, &(p7_connection->remote_addr), &tx_buffer[0], segment_size); + } + } else { + if (vnf_p7->_public.checksum_enabled) { + nfapi_nr_p7_update_checksum(buffer, len); + } + const uint32_t time = + calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr); + nfapi_nr_p7_update_transmit_timestamp(buffer, time); + send_result = socket_send_p7_msg(vnf_p7->socket, &(p7_connection->remote_addr), &buffer[0], len); + } + p7_connection->sequence_number++; + return send_result == 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id); + return false; + } +} + +static int vnf_nr_read_dispatch_message(nfapi_vnf_config_t *config, nfapi_vnf_pnf_info_t *pnf) +{ + if (1) { + int socket_connected = 1; + vnf_t *vnf = (vnf_t *)(config); + // 1. Peek the message header + // 2. If the message is larger than the stack buffer then create a dynamic buffer + // 3. Read the buffer + // 4. Handle the p5 message + + uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + + uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure + uint8_t stack_buffer[stack_buffer_size]; + + uint8_t *dynamic_buffer = 0; + + uint8_t *read_buffer = &stack_buffer[0]; + uint32_t message_size = 0; + + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + struct sctp_sndrcvinfo sndrcvinfo; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + { + int flags = MSG_PEEK; + if (vnf->sctp) { + message_size = + sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr *)&addr, &addr_len, &sndrcvinfo, &flags); + } else { + message_size = recv(pnf->p5_sock, header_buffer, header_buffer_size, flags); + } + + if (message_size == -1) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Peeked message with length :0x%02x\n", message_size); + + for (int i = 0; i < message_size; i++) { + printf("%02x ", header_buffer[i]); + } + printf("\n"); + + nfapi_nr_p4_p5_message_header_t header; + const bool result = config->hdr_unpack_func(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header\n"); + return 0; + } + message_size = header.message_length + header_buffer_size; + + // now have the size of the mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF After header unpacking msg size is :0x%02x\n", message_size); + } + + if (message_size > stack_buffer_size) { + dynamic_buffer = (uint8_t *)malloc(message_size); + + if (dynamic_buffer == NULL) { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + ssize_t recvmsg_result = 0; + if (vnf->sctp) { + recvmsg_result = + sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr *)&addr, &addr_len, &sndrcvinfo, &flags); + } else { + recvmsg_result = recv(pnf->p5_sock, read_buffer, message_size, 0); + } + + if (recvmsg_result == -1) { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size error %s errno:%d\n", strerror(tmp), tmp); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF after recv flags are :0x%02x\n", flags); + + if (flags & MSG_NOTIFICATION) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + // todo - handle the events + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, + "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", + pnf->p5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80 || !vnf->sctp) { + vnf_nr_handle_p4_p5_message(read_buffer, message_size, pnf->p5_idx, config); + } else { + int tmp = errno; + NFAPI_TRACE(NFAPI_TRACE_WARN, + "sctp_recvmsg: unhandled mode with flags 0x%x and error %s errno:%d\n", + flags, + strerror(tmp), + tmp); + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + } + } + } + + if (dynamic_buffer) { + free(dynamic_buffer); + } + + return socket_connected; + } +} + +static int nfapi_nr_vnf_p5_start(nfapi_vnf_config_t *config) +{ + // Verify that config is not null + if (config == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + int p5ListenSock, p5Sock; + + struct sockaddr_in addr = {0}; + socklen_t addrSize; + + struct sockaddr_in6 addr6 = {0}; + + struct sctp_event_subscribe events = {0}; + struct sctp_initmsg initMsg = {0}; + int noDelay; + + vnf_t *vnf = (vnf_t *)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); + + { + int protocol; + int domain; + + if (vnf->sctp) + protocol = IPPROTO_SCTP; + else + protocol = IPPROTO_IP; + + if (config->vnf_ipv6) { + domain = PF_INET6; + } else { + domain = AF_INET; + } + + // open the SCTP socket + if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock); + } + + if (vnf->sctp) { + // configure for MSG_NOTIFICATION + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n"); + // configure the SCTP socket options + initMsg.sinit_num_ostreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + initMsg.sinit_max_instreams = 5; // MAX_SCTP_STREAMS; // number of output streams can be greater + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + noDelay = 1; + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + struct sctp_event_subscribe events; + memset((void *)&events, 0, sizeof(events)); + events.sctp_data_io_event = 1; + + if (setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + close(p5ListenSock); + return -1; + } + } else { + int error; + socklen_t len = sizeof(error); + + if (getsockopt(p5ListenSock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + close(p5ListenSock); + return -1; + } + } + + if (config->vnf_ipv6) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(config->vnf_p5_port); + addr6.sin6_addr = in6addr_any; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + } else if (config->vnf_ipv4) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->vnf_p5_port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + AssertFatal(1 == 0, "Failed to bind socket with errno: %d\n", errno); + return 0; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock); + + // put the socket into listen mode + if (listen(p5ListenSock, 2) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n"); + + struct timeval tv; + fd_set read_fd_set; + + int p5_idx = 0; + while (vnf->terminate == 0) { + FD_ZERO(&read_fd_set); + + FD_SET(p5ListenSock, &read_fd_set); + int max_fd = p5ListenSock; + + tv.tv_sec = 5; + tv.tv_usec = 0; + + nfapi_vnf_pnf_info_t *pnf = config->pnf_list; + while (pnf != 0) { + if (pnf->connected) { + FD_SET(pnf->p5_sock, &read_fd_set); + if (pnf->p5_sock > max_fd) { + max_fd = pnf->p5_sock; + } + } + + pnf = pnf->next; + } + + int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv); + + if (select_result == -1) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno); + close(p5ListenSock); + return 0; + } else if (select_result) { + if (FD_ISSET(p5ListenSock, &read_fd_set)) { + addrSize = sizeof(struct sockaddr_in); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n"); + + p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize); + + if (p5Sock < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, + "PNF connection (fd:%d) accepted from %s:%d \n", + p5Sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port)); + nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); + memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); + pnf->p5_sock = p5Sock; + pnf->p5_idx = p5_idx++; + pnf->p5_pnf_sockaddr = addr; + pnf->connected = 1; + + nfapi_vnf_pnf_list_add(config, pnf); + + // Inform mac that a pnf connection has been established + // todo : allow mac to 'accept' the connection. i.e. to + // reject it. + if (config->pnf_nr_connection_indication != 0) { + (config->pnf_nr_connection_indication)(config, pnf->p5_idx); + } + + // check the connection status + if (vnf->sctp) { + struct sctp_status status; + (void)memset(&status, 0, sizeof(struct sctp_status)); + socklen_t optLen = (socklen_t)sizeof(struct sctp_status); + if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms); + } + } + } + } else { + uint8_t delete_pnfs = 0; + + nfapi_vnf_pnf_info_t *pnf = config->pnf_list; + while (pnf != 0) { + if (FD_ISSET(pnf->p5_sock, &read_fd_set)) { + if (vnf_nr_read_dispatch_message(config, pnf) == 0) { + if (config->pnf_disconnect_indication != 0) { + (config->pnf_disconnect_indication)(config, pnf->p5_idx); + } + + close(pnf->p5_sock); + + pnf->to_delete = 1; + delete_pnfs = 1; + } + } + + pnf = pnf->next; + } + + if (delete_pnfs) { + nfapi_vnf_pnf_info_t *pnf = config->pnf_list; + nfapi_vnf_pnf_info_t *prev = 0; + while (pnf != 0) { + nfapi_vnf_pnf_info_t *curr = pnf; + + if (pnf->to_delete == 1) { + if (prev == 0) { + config->pnf_list = pnf->next; + } else { + prev->next = pnf->next; + } + + pnf = pnf->next; + + free(curr); + } else { + prev = pnf; + pnf = pnf->next; + } + } + } + } + + continue; + } else { + // timeout + + // Should we test for socket closure here every second? + + continue; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n"); + { + nfapi_vnf_pnf_info_t *curr = config->pnf_list; + while (curr != NULL) { + if (config->pnf_disconnect_indication) { + (config->pnf_disconnect_indication)(config, curr->p5_idx); + } + + close(curr->p5_sock); + curr = curr->next; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n"); + close(p5ListenSock); + + return 0; +} + +void vnf_start_p5_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF"); + nfapi_nr_vnf_p5_start((nfapi_vnf_config_t *)ptr); +} + +void vnf_nr_reassemble_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t *vnf_p7) +{ + nfapi_nr_p7_message_header_t messageHeader; + + // validate the input params + if (pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, vnf_p7); + return; + } + + // unpack the message header + const bool result = + vnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &vnf_p7->_public.codec_config); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + if (vnf_p7->_public.checksum_enabled) { + uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if (checksum != messageHeader.checksum) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "Checksum verification failed %d %d msg:%d len:%d\n", + checksum, + messageHeader.checksum, + messageHeader.message_id, + recvMsgLen); + return; + } + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + + if (m == 0 && segment_num == 0) { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + // vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7); + vnf_nr_handle_p7_message(pRecvMsg, recvMsgLen, vnf_p7); + } else { + nfapi_vnf_p7_connection_info_t *phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id); + + if (phy) { + vnf_p7_rx_message_t *rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, + &(phy->reassembly_queue), + sequence_num, + segment_num, + m, + pRecvMsg, + recvMsgLen); + + if (rx_msg->num_segments_received == rx_msg->num_segments_expected) { + // send the buffer on + uint16_t i = 0; + uint16_t length = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); + } + + if (phy->reassembly_buffer_size < length) { + vnf_p7_free(vnf_p7, phy->reassembly_buffer); + phy->reassembly_buffer = 0; + } + + if (phy->reassembly_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length); + phy->reassembly_buffer = (uint8_t *)vnf_p7_malloc(vnf_p7, length); + + if (phy->reassembly_buffer == 0) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(phy->reassembly_buffer, 0, length); + phy->reassembly_buffer_size = length; + } + + uint16_t offset = 0; + for (i = 0; i < rx_msg->num_segments_expected; ++i) { + if (i == 0) { + memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } else { + memcpy(phy->reassembly_buffer + offset, + rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, + rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; + } + } + + vnf_nr_handle_p7_message(phy->reassembly_buffer, length, vnf_p7); + + // delete the structure + vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg); + } + + // see corresponding comment in pnf_nr_handle_p7_message() [same commit] + vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 10000); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id); + } + } +} + +int vnf_nr_p7_read_dispatch_message(vnf_p7_t *vnf_p7) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + + do { + // peek the header + uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(vnf_p7->socket, + header_buffer, + NFAPI_NR_P7_HEADER_LENGTH, + MSG_DONTWAIT | MSG_PEEK, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + + if (recvfrom_result > 0) { + // get the segment size + nfapi_nr_p7_message_header_t header; + const bool result = vnf_p7->_public.hdr_unpack_func(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, sizeof(header), 0); + if (!result) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return -1; + } + + // resize the buffer if we have a large segment + if (header.message_length > vnf_p7->rx_message_buffer_size) { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length); + vnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(vnf_p7->socket, + vnf_p7->rx_message_buffer, + header.message_length, + MSG_WAITALL | MSG_TRUNC, + (struct sockaddr *)&remote_addr, + &remote_addr_size); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "recvfrom_result = %d from %s():%d\n", recvfrom_result, __FUNCTION__, __LINE__); + + // todo : how to handle incomplete readfroms, need some sort of buffer/select + + if (recvfrom_result > 0) { + if (recvfrom_result != header.message_length) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "(%d) Received unexpected number of bytes. %d != %d", + __LINE__, + recvfrom_result, + header.message_length); + break; + } + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Calling vnf_nr_reassemble_p7_message from %d\n", __LINE__); + vnf_nr_reassemble_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno); + } + } + + if (recvfrom_result == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // return to the select + } else { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + } while (recvfrom_result > 0); + + return 0; +} + +static int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t *config) +{ + if (config == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + vnf_p7_t *vnf_p7 = (vnf_p7_t *)config; + + // Create p7 receive udp port + // todo : this needs updating for Ipv6 + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port); + + // open the UDP socket + if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); + + // configure the UDP socket options + int iptos_value = 0; + if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n"); + + // Create the address structure + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured port + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) + // if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n"); + + // struct timespec original_pselect_timeout; + struct timespec pselect_timeout; + pselect_timeout.tv_sec = 100; + pselect_timeout.tv_nsec = 0; + + struct timespec ref_time; + clock_gettime(CLOCK_MONOTONIC, &ref_time); + while (vnf_p7->terminate == 0) { + fd_set rfds; + int maxSock = 0; + FD_ZERO(&rfds); + int selectRetval = 0; + + // Add the p7 socket + FD_SET(vnf_p7->socket, &rfds); + maxSock = vnf_p7->socket; + + selectRetval = pselect(maxSock + 1, &rfds, NULL, NULL, &pselect_timeout, NULL); + + if (selectRetval == 0) { + // pselect timed out, continue + } else if (selectRetval > 0) { + // have a p7 message + if (FD_ISSET(vnf_p7->socket, &rfds)) { + vnf_nr_p7_read_dispatch_message(vnf_p7); + } + } else { + // pselect error + if (selectRetval == -1 && errno == EINTR) { + // a sigal was received. + } else { + // should we exit now? + if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration + { + usleep(100000); + } + } + } + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); + close(vnf_p7->socket); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__); + + return 0; +} + +void *vnf_nr_start_p7_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF_P7"); + nfapi_vnf_p7_config_t *config = (nfapi_vnf_p7_config_t *)ptr; + nfapi_nr_vnf_p7_start(config); + return config; +} diff --git a/nfapi/oai_integration/wls_integration/CMakeLists.txt b/nfapi/oai_integration/wls_integration/CMakeLists.txt new file mode 100644 index 0000000000..6d225f18b8 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/CMakeLists.txt @@ -0,0 +1,22 @@ +message(STATUS "Building with support for WLS") +add_library(wls_integration_lib + wls_pnf.c + wls_vnf.c + wls_common.c +) + +find_library(WLS_LIB wls REQUIRED) +message(STATUS " wls library found in ${WLS_LIB}") + +find_library(hugetlbfs_LIB hugetlbfs REQUIRED) +message(STATUS " hugetlbfs library found in ${hugetlbfs_LIB}") + +pkg_check_modules(dpdk REQUIRED libdpdk=20.11.3) +target_link_libraries(wls_integration_lib PRIVATE ${dpdk_LINK_LIBRARIES}) +target_include_directories(wls_integration_lib PRIVATE ${dpdk_INCLUDE_DIRS}) +target_include_directories(wls_integration_lib PRIVATE include/) + +target_compile_definitions(wls_integration_lib PUBLIC ENABLE_WLS) +target_link_libraries(wls_integration_lib PRIVATE NFAPI_LIB NFAPI_USER_LIB) +target_link_libraries(wls_integration_lib PRIVATE nr_fapi_p5 nr_fapi_p7) +target_link_libraries(wls_integration_lib PRIVATE "${WLS_LIB}" "${hugetlbfs_LIB}") diff --git a/nfapi/oai_integration/wls_integration/include/wls_common.h b/nfapi/oai_integration/wls_integration/include/wls_common.h new file mode 100644 index 0000000000..1b6a8e4cdf --- /dev/null +++ b/nfapi/oai_integration/wls_integration/include/wls_common.h @@ -0,0 +1,108 @@ +/* +* 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_WLS_COMMON_H +#define OPENAIRINTERFACE_WLS_COMMON_H + +#include +#include +#include +#include "wls_lib.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h" + +#define WLS_DEV_NAME "wls" +#define WLS_MAC_MEMORY_SIZE 0x7F000000 +#define WLS_PHY_MEMORY_SIZE 0x7F000000 + +#define MAX_NUM_LOCATIONS (508) + +#define MIN_DL_BUF_LOCATIONS (0) /* Used for stats collection 0-49 */ +#define MIN_UL_BUF_LOCATIONS (MIN_DL_BUF_LOCATIONS + MAX_NUM_LOCATIONS) /* Used for stats collection 50-99 */ + +#define MAX_DL_BUF_LOCATIONS (MIN_DL_BUF_LOCATIONS + MAX_NUM_LOCATIONS) /* Used for stats collection 0-49 */ +#define MAX_UL_BUF_LOCATIONS (MIN_UL_BUF_LOCATIONS + MAX_NUM_LOCATIONS) /* Used for stats collection 50-99 */ + +#define ALLOC_TRACK_SIZE ( 16384 ) + +typedef struct { + uint64_t *values; + uint16_t values_size; + uint16_t values_count; +}pa_store_t; + +/* ----- WLS Operation --- */ +#define FAPI_VENDOR_MSG_HEADER_IND 0x1A +// Linked list header present at the top of all messages +typedef struct _fapi_api_queue_elem { + struct _fapi_api_queue_elem *p_next; + // p_tx_data_elm_list used for TX_DATA.request processing + struct _fapi_api_queue_elem *p_tx_data_elm_list; + uint8_t msg_type; + uint8_t num_message_in_block; + uint32_t msg_len; + uint32_t align_offset; + uint64_t time_stamp; +} fapi_api_queue_elem_t, + *p_fapi_api_queue_elem_t; + + +typedef struct wls_mac_mem_array +{ + void **ppFreeBlock; + void *pStorage; + void *pEndOfStorage; + uint32_t nBlockSize; + uint32_t nBlockCount; +} WLS_MAC_MEM_SRUCT, *PWLS_MAC_MEM_SRUCT; + +typedef struct wls_mac_ctx +{ + void *hWls; + void *pWlsMemBase; + void *pWlsMemBaseUsable; + WLS_MAC_MEM_SRUCT sWlsStruct; + + uint64_t nTotalMemorySize; + uint64_t nTotalMemorySizeUsable; + uint32_t nBlockSize; + uint32_t nTotalBlocks; + uint32_t nAllocBlocks; + uint32_t nTotalAllocCnt; + uint32_t nTotalFreeCnt; + uint32_t nTotalUlBufAllocCnt; + uint32_t nTotalUlBufFreeCnt; + uint32_t nTotalDlBufAllocCnt; + uint32_t nTotalDlBufFreeCnt; + // Support for FAPI Translator + uint32_t nPartitionMemSize; + void *pPartitionMemBase; + + volatile pthread_mutex_t lock; + volatile pthread_mutex_t lock_alloc; +} WLS_MAC_CTX, *PWLS_MAC_CTX; + +void fill_fapi_list_elem(p_fapi_api_queue_elem_t currElem, p_fapi_api_queue_elem_t nextElem, const uint8_t msgType, const uint8_t numMsgInBlock, const uint32_t alignOffset); +uint64_t dequeueBlock(PWLS_MAC_CTX pWls); +void wls_return_msg_to_master(PWLS_MAC_CTX pWls, const uint64_t msg_PA); +uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const int packed_len, const uint8_t *message ); +uint8_t wls_msg_send(PWLS_MAC_CTX pWls, p_fapi_api_queue_elem_t currMsg); +#endif //OPENAIRINTERFACE_WLS_COMMON_H diff --git a/nfapi/oai_integration/wls_integration/include/wls_pnf.h b/nfapi/oai_integration/wls_integration/include/wls_pnf.h new file mode 100644 index 0000000000..c678345967 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/include/wls_pnf.h @@ -0,0 +1,33 @@ +/* + * 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_WLS_PNF_H +#define OPENAIRINTERFACE_WLS_PNF_H +#include "nfapi_pnf_interface.h" +#include "pnf.h" +#include "wls_common.h" + +bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *msg, uint32_t msg_len); +void *wls_fapi_pnf_nr_start_thread(void *ptr); +int wls_fapi_nr_pnf_start(); +void wls_pnf_set_p7_config(void *p7_config); +#endif // OPENAIRINTERFACE_WLS_PNF_H diff --git a/nfapi/oai_integration/wls_integration/include/wls_vnf.h b/nfapi/oai_integration/wls_integration/include/wls_vnf.h new file mode 100644 index 0000000000..645b24d056 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/include/wls_vnf.h @@ -0,0 +1,33 @@ +/* +* 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_WLS_VNF_H +#define OPENAIRINTERFACE_WLS_VNF_H +#include "nfapi_vnf_interface.h" +#include "vnf.h" +#include "wls_common.h" + +void *wls_fapi_vnf_nr_start_thread(void *ptr); +int wls_fapi_nr_vnf_start(); +void wls_vnf_set_p7_config(void *p7_config); +bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +bool wls_vnf_nr_send_p7_message(vnf_p7_t* vnf_p7,nfapi_nr_p7_message_header_t* msg); +#endif //OPENAIRINTERFACE_WLS_VNF_H diff --git a/nfapi/oai_integration/wls_integration/wls_common.c b/nfapi/oai_integration/wls_integration/wls_common.c new file mode 100644 index 0000000000..fe4112eba8 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/wls_common.c @@ -0,0 +1,118 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "wls_common.h" + +void fill_fapi_list_elem(p_fapi_api_queue_elem_t currElem, p_fapi_api_queue_elem_t nextElem, const uint8_t msgType, const uint8_t numMsgInBlock, const uint32_t alignOffset) +{ + currElem->msg_type = msgType; + currElem->num_message_in_block = numMsgInBlock; + currElem->align_offset = alignOffset; + currElem->msg_len = numMsgInBlock * alignOffset; + currElem->p_next = nextElem; + currElem->p_tx_data_elm_list = NULL; + currElem->time_stamp = 0; +} + +uint64_t dequeueBlock(PWLS_MAC_CTX pWls) +{ + uint64_t pa = WLS_DequeueBlock(pWls->hWls); + AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n"); + unsigned long* va = WLS_PA2VA(pWls->hWls, pa); + AssertFatal(va, "WLS_PA2VA failed for headerElem\n"); + while (*va != -1) { + pa = WLS_DequeueBlock(pWls->hWls); + AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n"); + va = WLS_PA2VA(pWls->hWls, pa); + } + return pa; +} + +uint8_t wls_msg_send(PWLS_MAC_CTX pWls, p_fapi_api_queue_elem_t currMsg) +{ + uint32_t msgLen = 0; + + AssertFatal(currMsg, "currMsg can't be NULL"); + AssertFatal(currMsg->p_next, "There needs to be at least 2 blocks to send!"); + msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t); + // Send the first block + if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, WLS_SG_FIRST) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the header block\n"); + return false; + } + // Iterate over the linked list, until a NULL block or a block set to 0xFFFFFFFFFFFFFFFF ( invalid ) + while (((currMsg = currMsg->p_next)) && (uint64_t)(currMsg) != -1) { + msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t); + /* Send the block with appropriate flags, either WLS_SG_NEXT or WLS_SG_LAST */ + const unsigned short flags = currMsg->p_next != NULL ? WLS_SG_NEXT : WLS_SG_LAST; + if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, flags) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the message block\n"); + return false; + } + } + return true; +} + +void wls_return_msg_to_master(PWLS_MAC_CTX pWls,const uint64_t msg_PA) +{ + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, msg_PA); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + // No need to return the message contents, just the block + fill_fapi_list_elem(fapiMsgElem, NULL, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(fapiMsgElem + 1), wls_header, 2); + const uint32_t msgLen = fapiMsgElem->msg_len + sizeof(fapi_api_queue_elem_t); + /* Send the block with appropriate only WLS_SG_FIRST flag, since we send only 1 block*/ + if (WLS_Put(pWls->hWls, msg_PA, msgLen, FAPI_VENDOR_MSG_HEADER_IND, WLS_SG_FIRST) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR,"Failure in sending block back to master\n"); + } +} + +uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const int packed_len, const uint8_t *message) +{ + int num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + while (num_avail_blocks < 2) { + num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + } + /* get PA blocks for header and msg */ + uint64_t pa_hdr = dequeueBlock(pWls); + AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n"); + uint64_t pa_msg = dequeueBlock(pWls); + AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n"); + p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr); + AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n"); + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + fill_fapi_list_elem(fapiMsgElem, NULL, message_id, 1, packed_len + NFAPI_HEADER_LENGTH); + memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH); + uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + if (NFAPI_MODE == NFAPI_MODE_VNF) { + // Use the opaque handle to signal to our PNF to not progress the FAPI PNF state machine + wls_header[1] = 0xff; + } + fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(headerElem + 1), wls_header, 2); + uint8_t retval = wls_msg_send(pWls->hWls, headerElem); + return retval; +} + diff --git a/nfapi/oai_integration/wls_integration/wls_pnf.c b/nfapi/oai_integration/wls_integration/wls_pnf.c new file mode 100644 index 0000000000..e02cef30a4 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/wls_pnf.c @@ -0,0 +1,290 @@ +/* + * 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 "wls_pnf.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "pnf.h" +#include "nr_nfapi_p7.h" +#include "nr_fapi_p5.h" + +// A copy of the PNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a +// different thread, the config is passed to it upon the thread creation +nfapi_pnf_p7_config_t *wls_pnf_p7_config = NULL; + +void wls_pnf_set_p7_config(void *p7_config) +{ + wls_pnf_p7_config = (nfapi_pnf_p7_config_t *)p7_config; +} + +static WLS_MAC_CTX g_phy_wls; +uint8_t phy_dpdk_init(void); +uint8_t phy_wls_init(const char *dev_name, uint64_t nWlsMacMemSize, uint64_t nWlsPhyMemSize); +void phy_mac_recv(); +void wls_mac_print_stats(void); + +pnf_t *_this = NULL; + +static PWLS_MAC_CTX wls_mac_get_ctx(void) +{ + return &g_phy_wls; +} + +static nfapi_pnf_config_t *cfg; + +void *wls_fapi_pnf_nr_start_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN WLS PNF NFAPI start thread %s\n", __FUNCTION__); + cfg = (nfapi_pnf_config_t *)ptr; + wls_fapi_nr_pnf_start(); + return (void *)0; +} + +int wls_fapi_nr_pnf_start() +{ + int64_t ret; + // Verify that config is not null + if (cfg == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + _this = (pnf_t *)(cfg); + _this->terminate = 0; + // Init PNF config + nfapi_pnf_phy_config_t *phy = (nfapi_pnf_phy_config_t *)malloc(sizeof(nfapi_pnf_phy_config_t)); + memset(phy, 0, sizeof(nfapi_pnf_phy_config_t)); + + phy->state = NFAPI_PNF_PHY_IDLE; + phy->phy_id = 0; + phy->next = (_this->_public).phys; + (_this->_public).phys = phy; + _this->_public.state = NFAPI_PNF_RUNNING; + + // DPDK init + ret = phy_dpdk_init(); + if (!ret) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "[PNF] DPDK Init - Failed\n"); + return false; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] DPDK Init - Done\n"); + + // WLS init + ret = phy_wls_init(WLS_DEV_NAME, WLS_MAC_MEMORY_SIZE, WLS_PHY_MEMORY_SIZE); + if (!ret) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "[PNF] WLS Init - Failed\n"); + return false; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] WLS Init - Done\n"); + + // Start Receiving loop from the VNF + NFAPI_TRACE(NFAPI_TRACE_INFO, "Start Receiving loop from the VNF\n"); + phy_mac_recv(); + // Should never get here, to be removed, align with present implementation of PNF loop + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] Exiting...\n"); + + return true; +} + +uint8_t phy_dpdk_init(void) +{ + unsigned long i; + char *argv[] = {"OAI_PNF", "--proc-type=primary", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa", "--no-pci"}; + int argc = RTE_DIM(argv); + /* initialize EAL first */ + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[PHY] Calling rte_eal_init: "); + + for (i = 0; i < RTE_DIM(argv); i++) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s ", argv[i]); + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "\n"); + + if (rte_eal_init(argc, argv) < 0) + rte_panic("Cannot init EAL\n"); + + return true; +} + +uint8_t phy_wls_init(const char *dev_name, uint64_t nWlsMacMemSize, uint64_t nWlsPhyMemSize) +// uint8_t phy_wls_init(const char *dev_name, uint64_t nBlockSize) +{ + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + pWls->nTotalAllocCnt = 0; + pWls->nTotalFreeCnt = 0; + pWls->nTotalUlBufAllocCnt = 0; + pWls->nTotalUlBufFreeCnt = 0; + pWls->nTotalDlBufAllocCnt = 0; + pWls->nTotalDlBufFreeCnt = 0; + + pWls->hWls = WLS_Open(dev_name, WLS_SLAVE_CLIENT, &nWlsMacMemSize, &nWlsPhyMemSize); + if (pWls->hWls) { + /* allocate chuck of memory */ + if (WLS_Alloc(pWls->hWls, nWlsMacMemSize + nWlsPhyMemSize) != NULL) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "WLS Memory allocated successfully\n"); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unable to alloc WLS Memory\n"); + return false; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "can't open WLS instance"); + return false; + } + return true; +} + +bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + int packed_len = cfg->pack_func(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len); + return false; + } + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "fapi_nr_p5_message_pack succeeded having packed %d bytes\n", packed_len); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "in msg, msg_len is %d\n", msg->message_length); + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + + return wls_send_fapi_msg(pWls, msg->message_id, packed_len, pnf->tx_message_buffer); +} + +bool wls_pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *msg, uint32_t msg_len) +{ + UNUSED_VARIABLE(msg_len); + + if (!isFAPIMessageIDValid(msg->message_id)) { + return false; + } + + // if it's an nFAPI message, ignore + if ((msg->message_id == NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC || msg->message_id == NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC + || msg->message_id == NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO)) { + return false; + } + + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + int num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks); + while (num_avail_blocks < 2) { + num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks); + } + /* get PA blocks for header and msg */ + const uint64_t pa_hdr = dequeueBlock(pWls); + AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n"); + const uint64_t pa_msg = dequeueBlock(pWls); + AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n"); + p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr); + AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n"); + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(headerElem + 1), wls_header, 2); + + const int packed_len = ((nfapi_pnf_p7_config_t *)pnf_p7)->pack_func(msg, (fapiMsgElem + 1), NFAPI_MAX_PACKED_MESSAGE_SIZE, NULL); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed (%d)\n", packed_len); + return false; + } + fill_fapi_list_elem(fapiMsgElem, NULL, msg->message_id, 1, packed_len + NFAPI_HEADER_LENGTH); + const uint8_t retval = wls_msg_send(pWls->hWls, headerElem); + return retval; +} + +static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) +{ + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "[PHY] Received Msg ID 0x%02x Length %d\n", msg_id, msg_size); + if (msg_buf == NULL || _this == NULL) { + AssertFatal(msg_buf != NULL && _this != NULL, "%s: NULL parameters\n", __FUNCTION__); + } + // Add the size of the header to the message_size, because the size in the header does not include the header length + msg_size += NFAPI_NR_P5_HEADER_LENGTH; + switch (msg_id) { + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + pnf_nr_handle_p5_message(_this, msg_buf, msg_size); + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: { + pnf_nr_handle_p7_message(msg_buf, msg_size, (pnf_p7_t *)wls_pnf_p7_config, 0); + break; + } + default: + printf("\n Unknown Msg ID 0x%02x\n", msg_id); + break; + } +} + +void phy_mac_recv() +{ + /* Number of Memory blocks to get */ + uint32_t msgSize; + uint16_t msgType; + uint16_t flags; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + // This flag is used to determine whether to return the received blocks to the PNF + bool to_return = false; + while (_this->terminate == 0) { + int numMsgToGet = WLS_Wait(pWls->hWls); + if (numMsgToGet == 0) { + continue; + } + uint64_t PAs[numMsgToGet]; + uint8_t pa_idx = 0; + while (numMsgToGet--) { + PAs[pa_idx] = WLS_Get(pWls->hWls, &msgSize, &msgType, &flags); + pa_idx++; + } + for (int i = 0; i < pa_idx; i++) { + p_fapi_api_queue_elem_t msg = WLS_PA2VA(pWls->hWls, PAs[i]); + if (msg->msg_type != FAPI_VENDOR_MSG_HEADER_IND) { + uint8_t *msgt = (uint8_t *)(msg + 1); + uint32_t len = msgt[7] | (msgt[6] << 8) | (msgt[5] << 16) | (msgt[4] << 24); + procPhyMessages(len, (void *)(msg + 1), msg->msg_type); + } else { + // We check the header block to determine if it's the OAI VNF, if so, we're required to return the pages for enqueueing + if (!to_return) { + uint8_t *msgt = (uint8_t *)(msg + 1); + if (msgt[1] == 0xff) { + to_return = true; + } + } + } + } + if (to_return) { + // We only return the pages to be enqueued in case we're using the OAI VNF, + // The Radisys O-DU handles enqueueing the blocks differently, and also doesn't handle receiving a single block + for (int i = 0; i < pa_idx; i++) { + wls_return_msg_to_master(pWls, PAs[i]); + } + } + } +} diff --git a/nfapi/oai_integration/wls_integration/wls_vnf.c b/nfapi/oai_integration/wls_integration/wls_vnf.c new file mode 100644 index 0000000000..ccc68b4905 --- /dev/null +++ b/nfapi/oai_integration/wls_integration/wls_vnf.c @@ -0,0 +1,418 @@ +/* + * 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 "wls_vnf.h" + +#include "vnf_p7.h" + +#include +#include +#include +#include +#include +#include +#include + +static nfapi_vnf_config_t *config; +static WLS_MAC_CTX wls_mac_iface; +vnf_t *_vnf = NULL; +// A copy of the VNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a +// different thread, the config is passed to it upon the thread creation +nfapi_vnf_p7_config_t *wls_vnf_p7_config = NULL; + +void wls_vnf_set_p7_config(void *p7_config) +{ + wls_vnf_p7_config = (nfapi_vnf_p7_config_t *)p7_config; +} + +static PWLS_MAC_CTX wls_mac_get_ctx(void) +{ + return &wls_mac_iface; +} + +static uint8_t alloc_track[ALLOC_TRACK_SIZE]; +//------------------------------------------------------------------------------------------- +/** @ingroup group_testmac + * + * @param[in] pMemArray Pointer to WLS Memory management structure + * @param[in] pMemArrayMemory Pointer to flat buffer that was allocated + * @param[in] totalSize Total Size of flat buffer allocated + * @param[in] nBlockSize Size of each block that needs to be partitioned by memory manager + * + * @return 0 if SUCCESS + * + * @description + * This function creates memory blocks from a flat buffer which will be used for communciation + * between MAC and PHY + * + **/ +//------------------------------------------------------------------------------------------- +static bool wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pMemArrayMemory, uint32_t totalSize, uint32_t nBlockSize) +{ + const uint32_t numBlocks = totalSize / nBlockSize; + + printf("wls_mac_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n", + pMemArray, + pMemArrayMemory, + totalSize, + nBlockSize, + numBlocks); + AssertFatal(nBlockSize >= sizeof(void *), "WLS nBlockSize too small"); + AssertFatal(totalSize > sizeof(void *), "WLS Can't allocate less than 1 block"); + pMemArray->ppFreeBlock = (void **)pMemArrayMemory; + pMemArray->pStorage = pMemArrayMemory; + pMemArray->pEndOfStorage = ((unsigned long *)pMemArrayMemory) + numBlocks * nBlockSize / sizeof(unsigned long); + pMemArray->nBlockSize = nBlockSize; + pMemArray->nBlockCount = numBlocks; + + // Initialize single-linked list of free blocks; + void **ptr = (void **)pMemArrayMemory; + for (uint32_t i = 0; i < pMemArray->nBlockCount; i++) { + if (i == pMemArray->nBlockCount - 1) { + *ptr = NULL; // End of list + } else { + // Points to the next block + *ptr = (void **)(((uint8_t *)ptr) + nBlockSize); + ptr += nBlockSize / sizeof(unsigned long); + } + } + + memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE); + + return true; +} + +void mac_dpdk_init() +{ + char *my_argv[] = {"OAI_VNF", "-c3", "--proc-type=auto", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa"}; + printf("\nCalling rte_eal_init: "); + for (unsigned long i = 0; i < RTE_DIM(my_argv); i++) { + printf("%s ", my_argv[i]); + } + printf("\n"); + + if (rte_eal_init(RTE_DIM(my_argv), my_argv) < 0) + rte_panic("\nCannot init EAL\n"); +} + +static uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock) +{ + int idx; + + if (pMemArray->ppFreeBlock == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "wls_mac_alloc_mem_array pMemArray->ppFreeBlock = NULL\n"); + return 1; + } + + // FIXME: Remove after debugging + if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "wls_mac_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n", + pMemArray, + pMemArray->pStorage, + pMemArray->ppFreeBlock); + return 1; + } + + pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0); + *pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0); + + if ((*pMemArray->ppFreeBlock != NULL) + && (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) || ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) { + fprintf(stderr, + "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n", + pMemArray, + pMemArray->pStorage, + pMemArray->ppFreeBlock, + *pMemArray->ppFreeBlock); + return 1; + } + + *ppBlock = (void *)pMemArray->ppFreeBlock; + pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock); + + idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize; + if (alloc_track[idx]) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "wls_mac_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n", + pMemArray, + pMemArray->pStorage, + pMemArray->ppFreeBlock, + *pMemArray->ppFreeBlock); + } else { + alloc_track[idx] = 1; + } + + return 0; +} + +void wls_mac_print_stats(void) +{ + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "wls_mac_free_list_all:\n"); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nTotalBlocks[%d] nAllocBlocks[%d] nFreeBlocks[%d]\n", + pWls->nTotalBlocks, + pWls->nAllocBlocks, + (pWls->nTotalBlocks - pWls->nAllocBlocks)); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nTotalAllocCnt[%d] nTotalFreeCnt[%d] Diff[%d]\n", + pWls->nTotalAllocCnt, + pWls->nTotalFreeCnt, + (pWls->nTotalAllocCnt - pWls->nTotalFreeCnt)); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nDlBufAllocCnt[%d] nDlBufFreeCnt[%d] Diff[%d]\n", + pWls->nTotalDlBufAllocCnt, + pWls->nTotalDlBufFreeCnt, + (pWls->nTotalDlBufAllocCnt - pWls->nTotalDlBufFreeCnt)); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, + " nUlBufAllocCnt[%d] nUlBufFreeCnt[%d] Diff[%d]\n\n", + pWls->nTotalUlBufAllocCnt, + pWls->nTotalUlBufFreeCnt, + (pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt)); +} + +static void *wls_mac_alloc_buffer(PWLS_MAC_CTX pWls, uint32_t size, uint32_t loc) +{ + void *pBlock = NULL; + pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc); + if (wls_mac_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "wls_mac_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc); + wls_mac_print_stats(); + pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc); + return NULL; + } + pWls->nAllocBlocks++; + pWls->nTotalAllocCnt++; + if (loc < MAX_DL_BUF_LOCATIONS) + pWls->nTotalDlBufAllocCnt++; + else if (loc < MAX_UL_BUF_LOCATIONS) + pWls->nTotalUlBufAllocCnt++; + + pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc); + + return pBlock; +} + +static bool mac_wls_init() +{ + uint64_t nWlsMacMemorySize = 0; + uint64_t nWlsPhyMemorySize = 0; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL); + pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL); + + pWls->nTotalAllocCnt = 0; + pWls->nTotalFreeCnt = 0; + pWls->nTotalUlBufAllocCnt = 0; + pWls->nTotalUlBufFreeCnt = 0; + pWls->nTotalDlBufAllocCnt = 0; + pWls->nTotalDlBufFreeCnt = 0; + + /* Start by opening the WLS instance with WLS_MASTER_CLIENT */ + if ((pWls->hWls = WLS_Open(WLS_DEV_NAME, WLS_MASTER_CLIENT, &nWlsMacMemorySize, &nWlsPhyMemorySize)) == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not open WLS Interface \n"); + return false; + } + + /* WLS_Open was successful, we can allocate memory */ + if ((pWls->pWlsMemBase = WLS_Alloc(pWls->hWls, nWlsMacMemorySize + nWlsPhyMemorySize)) == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not allocate WLS Memory \n"); + return false; + } + /* Set the total memory that MAC has access to */ + pWls->nTotalMemorySize = nWlsMacMemorySize; + + /* Partition the WLS memory */ + memset(pWls->pWlsMemBase, 0xCC, pWls->nTotalMemorySize); + pWls->pPartitionMemBase = pWls->pWlsMemBase; + pWls->nPartitionMemSize = pWls->nTotalMemorySize; + pWls->nTotalBlocks = pWls->nTotalMemorySize / (NFAPI_MAX_PACKED_MESSAGE_SIZE); + /* Create the memory array */ + if (!wls_mac_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase, pWls->nPartitionMemSize, NFAPI_MAX_PACKED_MESSAGE_SIZE)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not create WLS Memory Array \n"); + return false; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "\nTotalBlocks is %d \n", pWls->nTotalBlocks); +int nBlocks = 0; +for(int i = 0 ; i< pWls->nTotalBlocks; i++){ + void* pMsg = wls_mac_alloc_buffer(pWls, 0, i); + /* Enqueue all blocks */ + nBlocks += WLS_EnqueueBlock(pWls->hWls, WLS_VA2PA(pWls->hWls, pMsg)); +} + NFAPI_TRACE(NFAPI_TRACE_INFO, "\nAllocated %d Blocks \n", nBlocks); + return true; +} + +static int vnf_wls_init() +{ + mac_dpdk_init(); + + if (!mac_wls_init()) { + return 0; + } + + return 1; +} + +void *wls_fapi_vnf_nr_start_thread(void *ptr) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] IN WLS PNF NFAPI start thread %s\n", __FUNCTION__); + wls_fapi_nr_vnf_start((nfapi_vnf_config_t *)ptr); + return (void *)0; +} + +static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) +{ + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "[VNF] Received Msg ID 0x%02x\n", msg_id); + if (msg_buf == NULL || _vnf == NULL) { + AssertFatal(msg_buf != NULL && _vnf != NULL, "%s: NULL parameters\n", __FUNCTION__); + } + // Add the size of the header to the message_size, because the size in the header does not include the header length + msg_size += NFAPI_NR_P5_HEADER_LENGTH; + switch (msg_id) { + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: { + vnf_nr_handle_p7_message(msg_buf, msg_size + NFAPI_NR_P7_HEADER_LENGTH, (vnf_p7_t *)wls_vnf_p7_config); + break; + } + default: + break; + } +} + +int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) +{ + config = cfg; + + if (config == 0) { + return -1; + } + _vnf = (vnf_t *)(config); + + // init WLS connection + if (vnf_wls_init() == 0) { + return -1; + } + _vnf->terminate = 0; + + // Connect to the PNF + if (config->pnf_nr_start_resp != 0) { + (config->pnf_nr_start_resp)(config, 0, NULL); + } + /* VNF receive loop */ + /* Number of Memory blocks to get */ + uint32_t msgSize; + uint16_t msgType; + uint16_t flags; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + while (_vnf->terminate == 0) { + int numMsgToGet = WLS_Wait(pWls->hWls); + if (numMsgToGet == 0) { + continue; + } + + uint64_t PAs[numMsgToGet]; + uint8_t pa_idx = 0; + while (numMsgToGet--) { + PAs[pa_idx] = WLS_Get(pWls->hWls, &msgSize, &msgType, &flags); + pa_idx++; + } + for (int i = 0; i < pa_idx; i++) { + p_fapi_api_queue_elem_t msg = WLS_PA2VA(pWls->hWls, PAs[i]); + if (msg->msg_type != FAPI_VENDOR_MSG_HEADER_IND) { + uint8_t *msgt = (uint8_t *)(msg + 1); + uint32_t len = msgt[7] | (msgt[6] << 8) | (msgt[5] << 16) | (msgt[4] << 24); + procPhyMessages(len, (void *)(msg + 1), msg->msg_type); + } + } + for (int i = 0; i < pa_idx; i++) { + if (WLS_EnqueueBlock(pWls->hWls, PAs[i]) == -1) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Error in WLS_EnqueueBlock for block %lu\n", PAs[i]); + } + } + } + return 1; +} + +bool wls_vnf_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + UNUSED_VARIABLE(p5_idx); + int packed_len = + vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); + + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len); + return false; + } + + // printf("fapi_nr_p5_message_pack succeeded having packed %d bytes\n", packed_len); + // printf("in msg, msg_len is %d\n", msg->message_length); + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + + int retval = wls_send_fapi_msg(pWls, msg->message_id, packed_len, vnf->tx_message_buffer); + if (retval) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "wls_send_fapi_msg success\n"); + } + return retval; +} + +bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *msg) +{ + uint32_t message_id = msg->message_id; + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + int num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + while (num_avail_blocks < 2) { + num_avail_blocks = WLS_NumBlocks(pWls->hWls); + NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + } + /* get PA blocks for header and msg */ + uint64_t pa_hdr = dequeueBlock(pWls); + AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n"); + uint64_t pa_msg = dequeueBlock(pWls); + AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n"); + p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr); + AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n"); + p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg); + AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); + //memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH); + const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle + + fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); + memcpy((uint8_t *)(headerElem + 1), wls_header, 2); + int packed_len = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(msg, (fapiMsgElem + 1), NFAPI_MAX_PACKED_MESSAGE_SIZE, NULL); + if (packed_len < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "fapi_p7_message_pack failed (%d)\n", packed_len); + return false; + } + fill_fapi_list_elem(fapiMsgElem, NULL, message_id, 1, packed_len + NFAPI_HEADER_LENGTH); + uint8_t retval = wls_msg_send(pWls->hWls, headerElem); + return retval; + //return wls_send_fapi_msg(pWls, msg->message_id, packed_len, _vnf->tx_message_buffer); +} diff --git a/nfapi/open-nFAPI/common/src/nfapi.c b/nfapi/open-nFAPI/common/src/nfapi.c index 716387ae7d..f997552c1e 100644 --- a/nfapi/open-nFAPI/common/src/nfapi.c +++ b/nfapi/open-nFAPI/common/src/nfapi.c @@ -889,8 +889,8 @@ int unpack_nr_tlv_list(unpack_tlv_t unpack_fns[], nfapi_tl_t generic_tl; uint8_t numBadTags = 0; uint16_t idx = 0; - - while ((uint8_t *)(*ppReadPackedMsg) < end) { + if (size == 0) { return 1; } + while ((uint8_t *)(*ppReadPackedMsg) + 4 < end) { // unpack the tl and process the values accordingly if (unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) return 0; diff --git a/nfapi/open-nFAPI/fapi/CMakeLists.txt b/nfapi/open-nFAPI/fapi/CMakeLists.txt index b332ef6a8e..cf7f85052f 100644 --- a/nfapi/open-nFAPI/fapi/CMakeLists.txt +++ b/nfapi/open-nFAPI/fapi/CMakeLists.txt @@ -22,3 +22,9 @@ if (OAI_AERIAL) target_compile_definitions(nr_fapi_p5 PRIVATE ENABLE_AERIAL) target_compile_definitions(nr_fapi_p7 PRIVATE ENABLE_AERIAL) endif () + +if(OAI_WLS) + target_compile_definitions(nr_fapi_common PRIVATE ENABLE_WLS) +else() + target_compile_definitions(nr_fapi_common PRIVATE ENABLE_SOCKET) +endif() diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h index ee405792d2..e71e1bae5c 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h @@ -77,10 +77,37 @@ 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, +/*! \brief Decodes a FAPI 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 fapi_message_header + * \param unpackedBufLen The size of fapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure. + * + * The function will decode a byte stream pointed to by pMessageBuf into a FAPI p5 header structure pointed to by pUnpackedBuf + */ +bool fapi_nr_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config); +/*! \brief Decodes a FAPI P7 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 fapi_message_header + * \param unpackedBufLen The size of fapi_message_header structure. + * \param config A pointer to the nfapi configuration structure + * \return true on success, false on failure. + * + * This function is a dummy function that points to fapi_nr_message_header_unpack, + * since in FAPI there's no difference in the structure of the message headers for P5 and P7 + */ +bool fapi_nr_p7_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config); + #endif // OPENAIRINTERFACE_NR_FAPI_H diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h index 307b5bad27..d47f0ec929 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h @@ -30,7 +30,7 @@ int fapi_nr_p5_message_pack(void *pMessageBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config); -int fapi_nr_p5_message_unpack(void *pMessageBuf, +bool fapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h index 77ed67e2ef..9d96a3be36 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h @@ -23,7 +23,7 @@ #define OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H #include "stdio.h" #include "stdint.h" -#include "nr_fapi.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi.h" #include "nfapi/oai_integration/vendor_ext.h" bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req); @@ -64,6 +64,7 @@ void dump_start_request(const nfapi_nr_start_request_scf_t *msg); void dump_start_response(const nfapi_nr_start_response_scf_t *msg); void dump_stop_request(const nfapi_nr_stop_request_scf_t *msg); void dump_stop_indication(const nfapi_nr_stop_indication_scf_t *msg); +char* error_ind_code_to_str(nfapi_nr_phy_notifications_errors_e error_code); void dump_error_indication(const nfapi_nr_error_indication_scf_t *msg); diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h index c2701acb5f..80b39f7386 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7.h @@ -23,7 +23,7 @@ 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, +bool fapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h index f915548783..5c1df2dcef 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h @@ -33,7 +33,7 @@ #define OPENAIRINTERFACE_NR_FAPI_P7_UTILS_H #include "stdio.h" #include "stdint.h" -#include "nr_fapi.h" +#include "nfapi/open-nFAPI/fapi/inc/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); diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi.c b/nfapi/open-nFAPI/fapi/src/nr_fapi.c index c36fff4b34..4da483db17 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi.c @@ -54,7 +54,6 @@ bool isFAPIMessageIDValid(const uint16_t id) 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: @@ -165,24 +164,37 @@ int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpacked return retLen; } -int fapi_nr_message_header_unpack(uint8_t **pMessageBuf, +bool fapi_nr_p7_message_header_unpack(void *pMessageBuf, + uint32_t messageBufLen, + void *pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t *config) +{ + return fapi_nr_message_header_unpack(pMessageBuf, + messageBufLen, + pUnpackedBuf, + unpackedBufLen, + NULL); +} + +bool fapi_nr_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { - uint8_t **pReadPackedMessage = pMessageBuf; + 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; + return false; } - uint8_t *end = *pMessageBuf + messageBufLen; + 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); + (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 != 0; } diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 6bf2ff37ea..6936d8b8fa 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -128,41 +128,39 @@ int fapi_nr_p5_message_pack(void *pMessageBuf, return packedMsgLen; } -int fapi_nr_p5_message_unpack(void *pMessageBuf, +bool fapi_nr_p5_message_unpack(void *pMessageBuf, const uint32_t messageBufLen, void *pUnpackedBuf, const uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { fapi_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; AssertFatal(pMessageBuf != NULL && pUnpackedBuf != NULL, "P5 unpack supplied pointers are null"); - uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; AssertFatal(messageBufLen >= NFAPI_HEADER_LENGTH && unpackedBufLen >= sizeof(fapi_message_header_t), "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); - if (fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0) - < 0) { + if (!fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0)) { // failed to read the header - return -1; + return false; } - + uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_HEADER_LENGTH; + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; int result = -1; if (check_nr_fapi_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { // the unpack buffer is not big enough for the struct - return -1; + return false; } // look for the specific message switch (pMessageHeader->message_id) { case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: // PARAM request has no body; - result = 0; + result = 1; break; case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: @@ -210,7 +208,7 @@ int fapi_nr_p5_message_unpack(void *pMessageBuf, break; } - return result; + return result != 0; } uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) @@ -1349,7 +1347,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * nfapi_tl_t generic_tl; uint8_t numBadTags = 0; unsigned long idx = 0; - while ((uint8_t *)(*ppReadPackedMsg) < end) { + while ((uint8_t *)(*ppReadPackedMsg) + 4 < end) { // unpack the tl and process the values accordingly if (unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) return 0; diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index 4c3f32ef27..a810b199ff 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -1469,29 +1469,13 @@ void dump_stop_indication(const nfapi_nr_stop_indication_scf_t *msg) dump_p5_message_header(&msg->header,depth); } -static char *error_code_to_str(uint8_t error_code) +char* error_ind_code_to_str(nfapi_nr_phy_notifications_errors_e error_code) { switch (error_code) { - case NFAPI_NR_PHY_API_MSG_OK: - return "NFAPI_NR_PHY_API_MSG_OK"; - case NFAPI_NR_PHY_API_MSG_INVALID_STATE: - return "NFAPI_NR_PHY_API_MSG_INVALID_STATE"; - case NFAPI_NR_PHY_API_MSG_INVALID_CONFIG: - return "NFAPI_NR_PHY_API_MSG_INVALID_CONFIG"; - case NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC: - return "NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC"; - case NFAPI_NR_PHY_API_MSG_SLOR_ERR: - return "NFAPI_NR_PHY_API_MSG_SLOR_ERR"; - case NFAPI_NR_PHY_API_MSG_BCH_MISSING: - return "NFAPI_NR_PHY_API_MSG_BCH_MISSING"; - case NFAPI_NR_PHY_API_MSG_INVALID_SFN: - return "NFAPI_NR_PHY_API_MSG_INVALID_SFN"; - case NFAPI_NR_PHY_API_MSG_UL_DCI_ERR: - return "NFAPI_NR_PHY_API_MSG_UL_DCI_ERR"; - case NFAPI_NR_PHY_API_MSG_TX_ERR: - return "NFAPI_NR_PHY_API_MSG_TX_ERR"; - default: - return "Unknown Error code"; +#define X(name, value) case name: return #name; + NFAPI_PHY_ERROR_LIST +#undef X + default: return "UNKNOWN_ERROR"; } } @@ -1503,6 +1487,6 @@ void dump_error_indication(const nfapi_nr_error_indication_scf_t *msg) INDENTED_PRINTF("SFN = 0x%02x (%d)\n", msg->sfn, msg->sfn); INDENTED_PRINTF("Slot = 0x%02x (%d)\n", msg->slot, msg->slot); INDENTED_PRINTF("Message ID = 0x%02x\n", msg->message_id); - INDENTED_PRINTF("Error Code = 0x%02x (%s) \n", msg->error_code, error_code_to_str(msg->error_code)); + INDENTED_PRINTF("Error Code = 0x%02x (%s) \n", msg->error_code, error_ind_code_to_str(msg->error_code)); depth--; } diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index 7b840fc126..4945e6da45 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -134,7 +134,7 @@ int fapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packed return packedMsgLen; } -int fapi_nr_p7_message_unpack(void *pMessageBuf, +bool fapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -143,25 +143,24 @@ int fapi_nr_p7_message_unpack(void *pMessageBuf, int result = 0; nfapi_nr_p7_message_header_t *pMessageHeader = (nfapi_nr_p7_message_header_t *)pUnpackedBuf; fapi_message_header_t fapi_hdr; - uint8_t *pReadPackedMessage = pMessageBuf; - AssertFatal(pMessageBuf != NULL && pUnpackedBuf != NULL, "P7 unpack supplied pointers are null"); - uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; + AssertFatal(messageBufLen >= NFAPI_HEADER_LENGTH && unpackedBufLen >= sizeof(fapi_message_header_t), "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - - if (fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &fapi_hdr, sizeof(fapi_message_header_t), 0) < 0) { + if (!fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, &fapi_hdr, sizeof(fapi_message_header_t), 0)) { // failed to read the header - return -1; + return false; } + uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_HEADER_LENGTH; + uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; pMessageHeader->message_length = fapi_hdr.message_length; pMessageHeader->message_id = fapi_hdr.message_id; if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; + return false; } // look for the specific message @@ -232,9 +231,9 @@ int fapi_nr_p7_message_unpack(void *pMessageBuf, if (result == 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Unpack failed to unpack message\n"); - return -1; + return false; } - return 0; + return true; } static uint8_t pack_nr_tx_beamforming_pdu(const nfapi_nr_tx_precoding_and_beamforming_t *beamforming_pdu, diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h index f830e904e2..d146408abf 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h @@ -28,8 +28,11 @@ #define NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH 3 #define NFAPI_MAX_NUM_RF_BANDS 16 +#ifdef ENABLE_WLS +#define NFAPI_MAX_PACKED_MESSAGE_SIZE 1024*1024*2 +#else #define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 - +#endif // The following definition control the size of arrays used in the interface. // These may be changed if desired. They are used in the encoder to make sure // that the user has not specified a 'count' larger than the max array, and also @@ -115,7 +118,8 @@ typedef struct { #define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x8000) >> 15 ) #define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x7F00) >> 8 ) #define NFAPI_P7_GET_SEQUENCE(_mss) ( (_mss) & 0x00FF ) -#define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7) << 4) | ((_sequ) & 0xF) ) +#define NFAPI_NR_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 15) | (((_segm) & 0x7F) << 8) | ((_sequ) & 0xFF) ) +#define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7F) << 4) | ((_sequ) & 0xF) ) #define NFAPI_TAG_LENGTH_PACKED_LEN 4 diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index eb668f3e73..683de59c59 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -110,11 +110,11 @@ uint8_t pack_nr_p5_message_body(nfapi_nr_p4_p5_message_header_t *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. + * \return true on success, false 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, +bool nfapi_nr_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -126,11 +126,11 @@ int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, * \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. + * \return true on success, false on 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, +bool nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -154,13 +154,13 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe * \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. + * \return true on success, false on 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, +bool nfapi_nr_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -172,11 +172,11 @@ int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, * \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. + * \return true on success, false 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, +bool nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index f213868328..e19dab108c 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -701,16 +701,22 @@ typedef enum { } nfapi_nr_stop_errors_e; //3.3.5 PHY Notifications + +#define NFAPI_PHY_ERROR_LIST \ +X(NFAPI_NR_PHY_API_MSG_OK ,0x0)\ +X(NFAPI_NR_PHY_API_MSG_INVALID_STATE ,0x1)\ +X(NFAPI_NR_PHY_API_MSG_INVALID_CONFIG ,0x2)\ +X(NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC ,0X3)\ +X(NFAPI_NR_PHY_API_MSG_SLOR_ERR ,0X4)\ +X(NFAPI_NR_PHY_API_MSG_BCH_MISSING ,0X5)\ +X(NFAPI_NR_PHY_API_MSG_INVALID_SFN ,0X6)\ +X(NFAPI_NR_PHY_API_MSG_UL_DCI_ERR ,0X7)\ +X(NFAPI_NR_PHY_API_MSG_TX_ERR ,0X8) + typedef enum { - NFAPI_NR_PHY_API_MSG_OK =0x0, - NFAPI_NR_PHY_API_MSG_INVALID_STATE =0x1, - NFAPI_NR_PHY_API_MSG_INVALID_CONFIG =0x2, - NFAPI_NR_PHY_API_SFN_OUT_OF_SYNC =0X3, - NFAPI_NR_PHY_API_MSG_SLOR_ERR =0X4, - NFAPI_NR_PHY_API_MSG_BCH_MISSING =0X5, - NFAPI_NR_PHY_API_MSG_INVALID_SFN =0X6, - NFAPI_NR_PHY_API_MSG_UL_DCI_ERR =0X7, - NFAPI_NR_PHY_API_MSG_TX_ERR =0X8 +#define X(name, value) name = value, + NFAPI_PHY_ERROR_LIST +#undef X } nfapi_nr_phy_notifications_errors_e; typedef struct { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index 1aeef4b766..4516302e48 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -2325,7 +2325,7 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, return 8; } -int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, +bool nfapi_nr_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -2336,25 +2336,25 @@ int nfapi_nr_p5_message_header_unpack(void *pMessageBuf, if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n"); - return -1; + return false; } 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; + return false; } // 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 false; } - return NFAPI_NR_P5_HEADER_LENGTH; + return true; } -int nfapi_nr_p5_message_unpack(void *pMessageBuf, +bool nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -2362,11 +2362,11 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, { if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); - return -1; + return false; } 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; + return false; } nfapi_nr_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; @@ -2374,7 +2374,7 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, (void)memset(pUnpackedBuf, 0, unpackedBufLen); // process the header if (!nfapi_nr_p5_message_header_unpack(pMessageBuf, messageBufLen, pMessageHeader, unpackedBufLen, config)) { - return -1; + return false; } uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_NR_P5_HEADER_LENGTH; uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; @@ -2382,7 +2382,7 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, if (check_nr_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { // the unpack buffer is not big enough for the struct - return -1; + return false; } // look for the specific message @@ -2476,7 +2476,7 @@ int nfapi_nr_p5_message_unpack(void *pMessageBuf, break; } - return result; + return result == 1; } int nfapi_p5_message_unpack(void *pMessageBuf, diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index b6e15e294b..e75e418500 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -5930,7 +5930,7 @@ int nfapi_p7_message_header_unpack(void *pMessageBuf, return 0; } -int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -5941,14 +5941,14 @@ int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); - return -1; + return false; } uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; if (messageBufLen < NFAPI_NR_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p7_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; + return false; } // process the header if (!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) @@ -5956,9 +5956,9 @@ int nfapi_nr_p7_message_header_unpack(void *pMessageBuf, && pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - return -1; + return false; - return 0; + return true; } int nfapi_p7_message_unpack(void *pMessageBuf, @@ -6203,7 +6203,14 @@ int nfapi_p7_message_unpack(void *pMessageBuf, bool peek_nr_nfapi_p7_sfn_slot(void *pMessageBuf, uint32_t messageBufLen, uint16_t *SFN, uint16_t *Slot) { +#ifdef ENABLE_SOCKET + // Socket transport will always use nFAPI encoding uint8_t *pReadPackedMessage = &((uint8_t *)pMessageBuf)[NFAPI_NR_P7_HEADER_LENGTH]; +#endif +#ifdef ENABLE_WLS + // WLS transport will always use FAPI encoding + uint8_t *pReadPackedMessage = &((uint8_t *)pMessageBuf)[NFAPI_HEADER_LENGTH]; +#endif uint8_t *end = (uint8_t*)pMessageBuf + messageBufLen; if(!(pull16(&pReadPackedMessage, SFN, end) && pull16(&pReadPackedMessage, Slot, end))) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to peek SFN.Slot\n"); @@ -6213,7 +6220,7 @@ bool peek_nr_nfapi_p7_sfn_slot(void *pMessageBuf, uint32_t messageBufLen, uint16 return true; } -int nfapi_nr_p7_message_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, @@ -6225,14 +6232,14 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; + return false; } uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen; if (messageBufLen < NFAPI_NR_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_nr_p7_message_header_t)) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; + return false; } // process the header @@ -6242,11 +6249,11 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, && pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; + return false; } if ((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; + return false; } /* @@ -6356,7 +6363,7 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, if (result == 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; + return false; } - return 0; + return true; } diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h index 7275db76e1..2dc2ce9de6 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf.h @@ -20,9 +20,8 @@ #include "nfapi_pnf_interface.h" -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 -typedef struct { +struct pnf_t { nfapi_pnf_config_t _public; @@ -33,19 +32,28 @@ typedef struct { uint8_t terminate; -} pnf_t; +}; 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_nr_p4_p5_message_header_t* msg, uint32_t msg_len); +void pnf_nr_handle_p5_message(pnf_t* pnf, void* pRecvMsg, int recvMsgLen); 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); nfapi_pnf_phy_config_t* nfapi_pnf_phy_config_find(nfapi_pnf_config_t* config, uint16_t phy_id); +void pnf_nr_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_handle_pnf_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen); +void pnf_nr_handle_stop_request(pnf_t* pnf, void* pRecvMsg, int recvMsgLen); + + #endif // _PNF_H_ diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 0325c8c242..5805e07445 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -25,7 +25,6 @@ #include "nfapi_pnf_interface.h" -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 typedef struct { uint16_t dl_conf_ontime; @@ -82,7 +81,7 @@ typedef struct { } pnf_p7_rx_reassembly_queue_t; -typedef struct { +struct pnf_p7_t { nfapi_pnf_p7_config_t _public; @@ -139,12 +138,11 @@ typedef struct { pnf_p7_stats_t stats; pnf_p7_nr_stats_t nr_stats; -} pnf_p7_t; +}; int pnf_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); @@ -159,8 +157,11 @@ int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indica pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len); void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg); void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta); - -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); - +void pnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t *pnf_p7, uint32_t rx_hr_time); +struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs); +uint32_t pnf_get_current_time_hr(void); +struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs); +void pnf_p7_free(pnf_p7_t* pnf_p7, void* ptr); +void* pnf_p7_malloc(pnf_p7_t* pnf_p7, size_t size); #endif /* _PNF_P7_H_ */ diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 7403bd7169..957e032f69 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -31,8 +31,8 @@ extern "C" { #include #include "openair1/PHY/defs_gNB.h" - - +typedef struct pnf_t pnf_t; +typedef struct pnf_p7_t pnf_p7_t; /*! This enum is used to describe the states of the pnf */ @@ -319,8 +319,60 @@ typedef struct nfapi_pnf_config */ void (*deallocate_p4_p5_vendor_ext)(void* header); + /*! \brief Encodes an (n)FAPI P5 message to a buffer + * + * This function is called internally in send_p5_msg() + * \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. + */ + int (*pack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pPackedBuf, + uint32_t packedBufLen, + nfapi_p4_p5_codec_config_t* config); + /*! \brief Decodes a (n)FAPI 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 true on success, false on failure. + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); + /*! \brief Decodes an (n)FAPI 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 true on success, false on failure. + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); + + /*! \brief Sends a (N)FAPI P5 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the VNF + * \param pnf A pointer to a pnf_t* + * \param msg A pointer to the P5 message + * \param msg_len The size of the encoded P5 message + * \return true on success, false on failure. + */ + bool (*send_p5_msg)(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); } nfapi_pnf_config_t; /*! Create a pnf configuration @@ -367,7 +419,6 @@ int nfapi_pnf_config_destroy(nfapi_pnf_config_t* config); * \endcode */ int nfapi_pnf_start(nfapi_pnf_config_t* config); -int nfapi_nr_pnf_start(nfapi_pnf_config_t* config); /*! Stop the PNF library. * \param config A pointer to the pnf configuration @@ -726,8 +777,55 @@ typedef struct nfapi_pnf_p7_config */ void (*deallocate_p7_vendor_ext)(void* header); + /*! A callback to pack a P7 message + * + * This function is called internally in send_p7_msg() + * \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. + */ + int (*pack_func)(void* pMessageBuf, void* pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); + /*! A callback to unpack a P7 message + * \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 true success, false on failure. + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); + /*! \brief Decodes a NFAPI P7 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 true on success, false on failure. + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); + + /*! \brief Sends a (N)FAPI P7 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the VNF + * \param pnf_p7 A pointer to a pnf_p7_t struct + * \param header A pointer to the P7 message to pack & send + * \param msg_len The P7 message length + * \return true on success, false on failure. + */ + bool (*send_p7_msg)(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); } nfapi_pnf_p7_config_t; /*! Create and initialise a nfapi_pnf_p7_config structure @@ -748,7 +846,7 @@ int nfapi_pnf_p7_config_destroy(nfapi_pnf_p7_config_t* config); * This function will not return until nfapi_pnf_p7_stop is called. */ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); -int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config); + /*! Stop the PNF P7 library. * \param config A pointer to a PNF P7 config diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index 4cef8e6412..1c851ce277 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -30,6 +30,10 @@ #include "nfapi_nr_interface_scf.h" #include "pnf.h" +#include + +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi.h" + # if 1 // for hard-code (remove later) #include "common/platform_types.h" #include "common/platform_constants.h" @@ -45,7 +49,9 @@ #include "NR_MIB.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" - +#ifdef ENABLE_WLS +#include "wls_integration/include/wls_pnf.h" +#endif #endif #define MAX_SCTP_STREAMS 16 @@ -95,8 +101,9 @@ void pnf_nr_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_PARAM.request received\n"); - // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_nr_pnf_param_request_t), &pnf->_public.codec_config) >= 0) + /// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message + const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_nr_pnf_param_request_t), &pnf->_public.codec_config); + if (result) { if(pnf->_public.state == NFAPI_PNF_IDLE) { @@ -251,8 +258,9 @@ void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_CONFIG.request received\n"); - // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + /// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message + const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config); + if (result) { // ensure correct state if(pnf->_public.state != NFAPI_PNF_RUNNING) @@ -357,8 +365,9 @@ void pnf_nr_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_START.request Received\n"); - // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + /// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message + const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config); + if (result) { if(pnf->_public.state == NFAPI_PNF_CONFIGURED) { @@ -517,7 +526,8 @@ void pnf_nr_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "PARAM.request received\n"); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if(config->state == NFAPI_PNF_RUNNING) { @@ -662,7 +672,8 @@ void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) nfapi_pnf_config_t* config = &(pnf->_public); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if(config->state == NFAPI_PNF_RUNNING) { @@ -806,7 +817,8 @@ void pnf_nr_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() START.request received state:%d\n", __FUNCTION__, config->state); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if(config->state == NFAPI_PNF_RUNNING) { @@ -945,7 +957,8 @@ void pnf_nr_handle_stop_request(pnf_t* pnf, void* pRecvMsg, int recvMsgLen) nfapi_pnf_config_t* config = &(pnf->_public); // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) { + const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config); + if (result) { if (config->state == NFAPI_PNF_RUNNING) { nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); if (phy) { @@ -1525,12 +1538,8 @@ void pnf_nr_handle_p5_message(pnf_t* pnf, void* pRecvMsg, int recvMsgLen) } // unpack the message header - if (nfapi_nr_p5_message_header_unpack(pRecvMsg, - recvMsgLen, - &messageHeader, - sizeof(nfapi_nr_p4_p5_message_header_t), - &pnf->_public.codec_config) - < 0) { + const bool result = pnf->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &pnf->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; } @@ -1702,20 +1711,6 @@ void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } -int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) -{ - int packed_len = - nfapi_nr_p5_message_pack(msg, msg_len, pnf->tx_message_buffer, sizeof(pnf->tx_message_buffer), &pnf->_public.codec_config); - - if (packed_len < 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed (%d)\n", packed_len); - return -1; - } - - return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0 /*msg->stream_id*/); -} - - int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) { int packed_len = nfapi_p5_message_pack(msg, msg_len, @@ -1748,8 +1743,6 @@ int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/); } - - int pnf_connect(pnf_t* pnf) { struct sockaddr_in servaddr; @@ -1932,7 +1925,20 @@ int pnf_connect(pnf_t* pnf) socketConnected = 1; } - } + } else { + int error; + socklen_t len = sizeof(error); + + if (getsockopt(pnf->p5_sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } else { + // If error is zero, the socket is connected + if (error == 0) { + socketConnected = 1; + } + } + } NFAPI_TRACE(NFAPI_TRACE_NOTE, "Socket %s\n", socketConnected ? "CONNECTED" : "NOT_CONNECTED"); return socketConnected; @@ -1941,30 +1947,30 @@ int pnf_connect(pnf_t* pnf) int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream) { - if (pnf->sctp) - { + if (pnf->sctp) + { #if 0 - printf("\nPNF SENDS: \n"); - for(int i=0; ip5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno); - return -1; - } - } - else - { - if (write(pnf->p5_sock, msg, len) != len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "read failed errno: %d\n", errno); - return -1; - } - } + if (sctp_sendmsg(pnf->p5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno); + return -1; + } + } + else + { + if (write(pnf->p5_sock, msg, len) != len) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "read failed errno: %d\n", errno); + return -1; + } + } return 0; } @@ -2101,126 +2107,6 @@ int pnf_read_dispatch_message(pnf_t* pnf) } -int pnf_nr_read_dispatch_message(pnf_t* pnf) -{ - int socket_connected = 1; - - // 1. Peek the message header - // 2. If the message is larger than the stack buffer then create a dynamic buffer - // 3. Read the buffer - // 4. Handle the p5 message - - uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; - uint8_t header_buffer[header_buffer_size]; - - uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure - uint8_t stack_buffer[stack_buffer_size]; - - uint8_t* dynamic_buffer = 0; - - uint8_t* read_buffer = &stack_buffer[0]; - uint32_t message_size = 0; - - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - - struct sctp_sndrcvinfo sndrcvinfo; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - { - int flags = MSG_PEEK; - message_size = sctp_recvmsg(pnf->p5_sock, - header_buffer, - header_buffer_size, - /*(struct sockaddr*)&addr, &addr_len*/ 0, - 0, - &sndrcvinfo, - &flags); - - if (message_size == -1) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno); - return 0; - } - - nfapi_nr_p4_p5_message_header_t header; - int unpack_result = nfapi_nr_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); - if (unpack_result < 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); - return 0; - } - message_size = header.message_length + header_buffer_size; - - // now have the size of the mesage - } - - if (message_size > stack_buffer_size) { - dynamic_buffer = (uint8_t*)malloc(message_size); - - if (dynamic_buffer == NULL) { - // todo : add error mesage - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); - return -1; - } - - read_buffer = dynamic_buffer; - } - - { - int flags = 0; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - int recvmsg_result = - sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); - if (recvmsg_result == -1) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); - } else { -#if 0 - // print the received message - printf("\n MESSAGE RECEIVED: \n"); - for(int i=0; ip5_sock, - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port), - sndrcvinfo.sinfo_assoc_id, - sndrcvinfo.sinfo_stream, - ntohl(sndrcvinfo.sinfo_ppid), - message_size, - flags); - */ - - // handle now if complete message in one or more segments - if ((flags & 0x80) == 0x80) { - pnf_nr_handle_p5_message(pnf, read_buffer, message_size); - } else { - NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); - - // assume socket disconnected - NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); - socket_connected = 0; - } - } - } - } - - if (dynamic_buffer) { - free(dynamic_buffer); - } - - return socket_connected; -} - int pnf_message_pump(pnf_t* pnf) { uint8_t socketConnected = 1; @@ -2272,67 +2158,6 @@ int pnf_message_pump(pnf_t* pnf) pnf->_public.state = NFAPI_PNF_IDLE; - // close the connection and socket - if (close(pnf->p5_sock) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno); - } - - return 0; - -} - -int pnf_nr_message_pump(pnf_t* pnf) -{ - uint8_t socketConnected = 1; - - while(socketConnected && pnf->terminate == 0) - { - fd_set rfds; - int selectRetval = 0; - - // select on a timeout and then get the message - FD_ZERO(&rfds); - FD_SET(pnf->p5_sock, &rfds); - - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - selectRetval = select(pnf->p5_sock+1, &rfds, NULL, NULL, &timeout); - - if(selectRetval == 0) - { - // timeout - continue; - } - else if (selectRetval == -1 && (errno == EINTR)) - { - // interrupted by signal - NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno); - continue; - } - else if (selectRetval == -1) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n"); - sleep(1); - continue; - } - - if(FD_ISSET(pnf->p5_sock, &rfds)) - { - socketConnected = pnf_nr_read_dispatch_message(pnf); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n"); - } - } - - // Drop back to idle if we have lost connection - pnf->_public.state = NFAPI_PNF_IDLE; - - // close the connection and socket if (close(pnf->p5_sock) < 0) { diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index a53604640c..d80ab168fa 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -79,36 +79,6 @@ int nfapi_pnf_start(nfapi_pnf_config_t* config) return 0; } -int nfapi_nr_pnf_start(nfapi_pnf_config_t* config) -{ - // Verify that config is not null - if(config == 0) - return -1; - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - - pnf_t* _this = (pnf_t*)(config); - - while (_this->terminate == 0) - { - int connect_result = pnf_connect(_this); - - if(connect_result > 0) - { - pnf_nr_message_pump(_this); - } - else if(connect_result < 0) - { - return connect_result; - } - - sleep(1); - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__); - - return 0; -} - int nfapi_pnf_stop(nfapi_pnf_config_t* config) { // Verify that config is not null @@ -135,8 +105,8 @@ int nfapi_nr_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_r } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_param_response_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured!"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_pnf_param_response_t)); } int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp) @@ -188,8 +158,8 @@ int nfapi_nr_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_config } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_config_response_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_pnf_config_response_t)); } @@ -227,8 +197,8 @@ int nfapi_nr_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_r } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_start_response_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_pnf_start_response_t)); } @@ -273,8 +243,8 @@ int nfapi_nr_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_param_response_ } pnf_t* _this = (pnf_t*)(config); - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_param_response_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_param_response_scf_t)); } int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp) @@ -329,8 +299,8 @@ int nfapi_nr_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_config_respons NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id); return -1; } - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_config_response_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_config_response_scf_t)); } @@ -384,8 +354,8 @@ int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_ NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknown phy id %d\n", __FUNCTION__, resp->header.phy_id); return -1; } - - return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_start_response_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_start_response_scf_t)); } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index bdc1634ef5..e2b6d253d2 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -32,7 +32,6 @@ #include "common/ran_context.h" #include -#define FAPI2_IP_DSCP 0 extern int sf_ahead; @@ -464,10 +463,10 @@ int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) socklen_t remote_addr_len = sizeof(struct sockaddr_in); int sendto_result; - - if ((sendto_result = sendto((int)pnf_p7->p7_sock, (const char*)msg, len, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) -//if ((sendto_result = sendto((int)pnf_p7->p7_sock,"hello", 6, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) - { + + if ((sendto_result = sendto((int)pnf_p7->p7_sock, (const char*)msg, len, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) + //if ((sendto_result = sendto((int)pnf_p7->p7_sock,"hello", 6, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) + { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s %s:%d sendto(%d, %p, %d) %d failed errno: %d\n", __FUNCTION__, pnf_p7->_public.remote_p7_addr, pnf_p7->_public.remote_p7_port, (int)pnf_p7->p7_sock, (const char*)msg, len, remote_addr_len, errno); return -1; } @@ -569,87 +568,6 @@ int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* return 0; } -int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len) -{ - header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number); - - // Need to guard against different threads calling the encode function at the same time - if (pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); - return -1; - } - - uint8_t tx_buf[131072]; // four times NFAPI_MAX_PACKED_MESSAGE_SIZE as of this commit - int len = nfapi_nr_p7_message_pack(header, tx_buf, sizeof(tx_buf), &pnf_p7->_public.codec_config); - - if (len < 0) { - if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len); - return -1; - } - - if (len > pnf_p7->_public.segment_size) { - int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH; - int seg_body_len = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; - int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); - - int segment = 0; - int offset = NFAPI_NR_P7_HEADER_LENGTH; - uint8_t buffer[pnf_p7->_public.segment_size]; - for (segment = 0; segment < segment_count; ++segment) { - uint8_t last = 0; - uint32_t size = pnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; - if (segment + 1 == segment_count) { - last = 1; - size = (msg_body_len) - (seg_body_len * segment); - } - - uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; - - // Update the header with the m and segement - memcpy(&buffer[0], tx_buf, NFAPI_NR_P7_HEADER_LENGTH); - - // set the segment length - buffer[4] = (segment_size & 0xFF000000) >> 24; - buffer[5] = (segment_size & 0xFF0000) >> 16; - buffer[6] = (segment_size & 0xFF00) >> 8; - buffer[7] = (segment_size & 0xFF); - - // set the m & segment number - buffer[8] = ((!last) << 7) + segment; - - memcpy(&buffer[NFAPI_NR_P7_HEADER_LENGTH], tx_buf + offset, size); - offset += size; - - if (pnf_p7->_public.checksum_enabled) { - nfapi_nr_p7_update_checksum(buffer, segment_size); - } - - pnf_p7_send_message(pnf_p7, &buffer[0], segment_size); - } - } else { - if (pnf_p7->_public.checksum_enabled) { - nfapi_nr_p7_update_checksum(tx_buf, len); - } - - // simple case that the message fits in a single segment - pnf_p7_send_message(pnf_p7, tx_buf, len); - } - - pnf_p7->sequence_number++; - - if (pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; - } - - return 0; -} - void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) { nfapi_timing_info_t timing_info; @@ -707,9 +625,8 @@ void pnf_nr_pack_and_send_timing_info(pnf_p7_t* pnf_p7) timing_info.tx_data_request_earliest_arrival = 0; timing_info.ul_tti_earliest_arrival = 0; timing_info.ul_dci_earliest_arrival = 0; - - - pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(timing_info.header), sizeof(timing_info)); + AssertFatal(pnf_p7->_public.send_p7_msg, "The function pointer to pack and send P7 messages must be set"); + pnf_p7->_public.send_p7_msg(pnf_p7, &(timing_info.header), sizeof(timing_info)); pnf_p7->timing_info_ms_counter = 0; } @@ -1299,8 +1216,8 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)) != 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (!result) NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unpack request\n"); } else { if (pnf_p7->_public.timing_info_mode_aperiodic) @@ -1432,8 +1349,8 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)) != 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (!result) NFAPI_TRACE(NFAPI_TRACE_ERROR, "failed to unpack UL_TTI.request\n"); } else { NFAPI_TRACE(NFAPI_TRACE_NOTE, @@ -1551,8 +1468,8 @@ void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &pnf_p7->_public.codec_config) != 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (!result) NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unpack request\n"); } else { if (pnf_p7->_public.timing_info_mode_aperiodic) { @@ -1664,8 +1581,8 @@ void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 frame, slot, buffer_index); - - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(*req), &pnf_p7->_public.codec_config) == 0) { + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, req, sizeof(*req), &(pnf_p7->_public.codec_config)); + if (result) { for (int i = 0; i < req->Number_of_PDUs; ++i) pnf_p7->nr_stats.dl.bytes += req->pdu_list[i].PDU_length; } else { @@ -2063,7 +1980,8 @@ void pnf_nr_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 } // unpack the message - if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &dl_node_sync, sizeof(dl_node_sync), &pnf_p7->_public.codec_config) < 0) + const bool result = pnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &dl_node_sync, sizeof(dl_node_sync), &pnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); return; @@ -2096,8 +2014,8 @@ void pnf_nr_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); return; } - - pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); + AssertFatal(pnf_p7->_public.send_p7_msg, "Function pointer must be configured|"); + pnf_p7->_public.send_p7_msg(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); //printf("\nSSent UL Node Sync sfn:%d,slot:%d\n",pnf_p7->sfn,pnf_p7->slot); } @@ -2171,7 +2089,7 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, } } -void pnf_nr_dispatch_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +void pnf_nr_handle_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_nr_p7_message_header_t header; @@ -2182,7 +2100,8 @@ void pnf_nr_dispatch_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 } // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config) < 0) { + const bool result = pnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; } @@ -2325,113 +2244,6 @@ void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, ui } -void pnf_nr_handle_p7_message(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) -{ - nfapi_nr_p7_message_header_t messageHeader; - - // validate the input params - if (pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, pnf_p7); - return; - } - - // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, - recvMsgLen, - &messageHeader, - sizeof(nfapi_nr_p7_message_header_t), - &pnf_p7->_public.codec_config) - < 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return; - } - - uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); - uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); - uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); - - if (pnf_p7->_public.checksum_enabled) { - uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); - if (checksum != messageHeader.checksum) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); - return; - } - } - - if (m == 0 && segment_num == 0) { - // we have a complete message - // ensure the message is sensible - if (recvMsgLen < 8 || pRecvMsg == NULL) { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); - return; - } - - pnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); - } else { - pnf_p7_rx_message_t* rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, - &(pnf_p7->reassembly_queue), - rx_hr_time, - sequence_num, - segment_num, - m, - pRecvMsg, - recvMsgLen); - - if (rx_msg->num_segments_received == rx_msg->num_segments_expected) { - // send the buffer on - uint16_t i = 0; - uint32_t length = 0; - for (i = 0; i < rx_msg->num_segments_expected; ++i) { - length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); - } - - if (pnf_p7->reassemby_buffer_size < length) { - pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); - pnf_p7->reassemby_buffer = 0; - } - - if (pnf_p7->reassemby_buffer == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); - pnf_p7->reassemby_buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, length); - - if (pnf_p7->reassemby_buffer == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); - return; - } - memset(pnf_p7->reassemby_buffer, 0, length); - pnf_p7->reassemby_buffer_size = length; - } - - uint32_t offset = 0; - for (i = 0; i < rx_msg->num_segments_expected; ++i) { - if (i == 0) { - memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); - offset += rx_msg->segments[i].length; - } else { - memcpy(pnf_p7->reassemby_buffer + offset, - rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, - rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); - offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; - } - } - - pnf_nr_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); - - // delete the structure - pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); - } - } - - // The timeout used to be 1000, i.e., 1ms, which is too short. The below 10ms - // is selected to be able to encompass any "reasonable" slot ahead time for the VNF. - // Ideally, we would remove old msg (segments) if we detect packet loss - // (e.g., if the sequence numbers advances sufficiently); in the branch of - // this commit, our goal is to make the PNF work, so we content ourselves to - // just remove very old messages. - pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 10000); -} - - void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) { int recvfrom_result = 0; @@ -2501,68 +2313,6 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) while(recvfrom_result > 0); } -void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) -{ - int recvfrom_result = 0; - struct sockaddr_in remote_addr; - socklen_t remote_addr_size = sizeof(remote_addr); - remote_addr.sin_family = 2; // hardcoded - do { - // peek the header - uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; - recvfrom_result = recvfrom(pnf_p7->p7_sock, - header_buffer, - NFAPI_NR_P7_HEADER_LENGTH, - MSG_DONTWAIT | MSG_PEEK, - (struct sockaddr*)&remote_addr, - &remote_addr_size); - if (recvfrom_result > 0) { - // get the segment size - nfapi_nr_p7_message_header_t header; - nfapi_nr_p7_message_header_unpack(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, 34, 0); - - // resize the buffer if we have a large segment - if (header.message_length > pnf_p7->rx_message_buffer_size) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); - pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); - pnf_p7->rx_message_buffer_size = header.message_length; - } - - // read the segment - recvfrom_result = recvfrom(pnf_p7->p7_sock, - pnf_p7->rx_message_buffer, - header.message_length, - MSG_DONTWAIT, - (struct sockaddr*)&remote_addr, - &remote_addr_size); - - now_hr_time = pnf_get_current_time_hr(); // moved to here - get closer timestamp??? - - if (recvfrom_result > 0) { - pnf_nr_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); - // printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); - } - } else if (recvfrom_result == 0) { - // recv zero length message - recvfrom_result = - recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); - } - - if (recvfrom_result == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - // return to the select - // NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); - } else { - NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); - } - } - - // need to update the time as we would only use the value from the - // select - } while (recvfrom_result > 0); -} - - int pnf_p7_message_pump(pnf_p7_t* pnf_p7) { @@ -2604,7 +2354,7 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) } */ - int iptos_value = FAPI2_IP_DSCP << 2; + int iptos_value = 0; if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); @@ -2722,197 +2472,15 @@ struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs) struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs) { struct timespec result; - if ((lhs.tv_nsec-rhs.tv_nsec)<0) + if ((lhs.tv_nsec-rhs.tv_nsec)<0) { result.tv_sec = lhs.tv_sec-rhs.tv_sec-1; result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec; - } - else + } + else { result.tv_sec = lhs.tv_sec-rhs.tv_sec; result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec; } return result; } - -int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) -{ - - // initialize the mutex lock - if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); - return -1; - } - - if(pthread_mutex_init(&(pnf_p7->pack_mutex), NULL) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); - return -1; - } - - // create the pnf p7 socket - if ((pnf_p7->p7_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); - return -1; - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 socket created (%d)...\n", pnf_p7->p7_sock); - - // configure the UDP socket options - int reuseaddr_enable = 1; - if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_enable, sizeof(int)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEADDR) failed errno: %d\n", errno); - return -1; - } - -/* - int reuseport_enable = 1; - if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEPORT, &reuseport_enable, sizeof(int)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEPORT) failed errno: %d\n", errno); - return -1; - } -*/ - - int iptos_value = FAPI2_IP_DSCP << 2; - if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); - return -1; - } - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(pnf_p7->_public.local_p7_port); - - if(pnf_p7->_public.local_p7_addr == 0) - { - addr.sin_addr.s_addr = INADDR_ANY; - } - else - { - //addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.local_p7_addr); - if(inet_aton(pnf_p7->_public.local_p7_addr, &addr.sin_addr) == -1) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "inet_aton failed\n"); - } - } - - - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 binding %d too %s:%d\n", pnf_p7->p7_sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - if (bind(pnf_p7->p7_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 bind error fd:%d errno: %d\n", pnf_p7->p7_sock, errno); - return -1; - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); - - //Initializaing timing structures needed for slot ticking - - struct timespec slot_start; - clock_gettime(CLOCK_MONOTONIC, &slot_start); - - struct timespec pselect_start; - - struct timespec slot_duration; - slot_duration.tv_sec = 0; - slot_duration.tv_nsec = 0.5e6; - - //Infinite loop - - while(pnf_p7->terminate == 0) - { - fd_set rfds; - int selectRetval = 0; - - // select on a timeout and then get the message - FD_ZERO(&rfds); - FD_SET(pnf_p7->p7_sock, &rfds); - - struct timespec timeout; - timeout.tv_sec = 100; - timeout.tv_nsec = 0; - clock_gettime(CLOCK_MONOTONIC, &pselect_start); - - //setting the timeout - - if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) - { - // overran the end of the subframe we do not want to wait - timeout.tv_sec = 0; - timeout.tv_nsec = 0; - - //struct timespec overrun = pnf_timespec_sub(pselect_start, sf_start); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); - } - else - { - // still time before the end of the subframe wait - timeout = pnf_timespec_sub(slot_start, pselect_start); - } - - selectRetval = pselect(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout, NULL); - - uint32_t now_hr_time = pnf_get_current_time_hr(); - - - - - if(selectRetval == 0) - { - // timeout - - //update slot start timing - slot_start = pnf_timespec_add(slot_start, slot_duration); - - //increment sfn/slot - if (++pnf_p7->slot == 20) - { - pnf_p7->slot = 0; - pnf_p7->sfn = (pnf_p7->sfn + 1) % 1024; - } - - continue; - } - else if (selectRetval == -1 && (errno == EINTR)) - { - // interrupted by signal - NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 Signal Interrupt %d\n", errno); - continue; - } - else if (selectRetval == -1) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 select() failed\n"); - sleep(1); - continue; - } - - if(FD_ISSET(pnf_p7->p7_sock, &rfds)) - - { - pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); - } - } - NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); - - // close the connection and socket - if (close(pnf_p7->p7_sock) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "close failed errno: %d\n", errno); - } - - if(pthread_mutex_destroy(&(pnf_p7->pack_mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); - } - - if(pthread_mutex_destroy(&(pnf_p7->mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); - } - - return 0; -} diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 6e5569d972..b021e67fc9 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -74,20 +74,7 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config) return 0; } -int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config) -{ - // Verify that config is not null - if(config == 0) - return -1; - pnf_p7_t* _this = (pnf_p7_t*)(config); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); - - pnf_nr_p7_message_pump(_this); - - return 0; -} int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) @@ -260,7 +247,8 @@ int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indica } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_slot_indication_scf_t)); } int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) @@ -272,8 +260,8 @@ int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_ } pnf_p7_t* _this = (pnf_p7_t*)(config); - - int ret = pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + int ret = _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); if (ret == 0) { for (int i = 0; i < ind->number_of_pdus; ++i) _this->nr_stats.ul.bytes += ind->pdu_list[i].pdu_length; @@ -290,7 +278,8 @@ int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); } int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind) @@ -302,7 +291,8 @@ int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); } int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind) @@ -314,7 +304,8 @@ int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indicati } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); } int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) @@ -326,5 +317,6 @@ int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indica } pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); + AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); + return _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); } diff --git a/nfapi/open-nFAPI/utils/nfapi_hex_parser.c b/nfapi/open-nFAPI/utils/nfapi_hex_parser.c index 342492ba92..a037f1221e 100644 --- a/nfapi/open-nFAPI/utils/nfapi_hex_parser.c +++ b/nfapi/open-nFAPI/utils/nfapi_hex_parser.c @@ -281,10 +281,9 @@ int main(int argc, char *argv[]) printf("\n"); AssertFatal(byte_count >= sizeof(fapi_message_header_t), "Read byte amount not enough to encode the header. Should have a minimum of %lu bytes, aborting...", sizeof(fapi_message_header_t)); uint8_t *ptr = hex_values; // Points to the first element of the array - uint8_t **msg_ptr = &ptr; // Pointer to the pointer fapi_message_header_t hdr = {.num_msg = 0, .opaque_handle = 0, .message_id = 0, .message_length = 0}; - fapi_nr_message_header_unpack(msg_ptr, NFAPI_HEADER_LENGTH, &hdr, sizeof(fapi_message_header_t), 0); + fapi_nr_message_header_unpack(ptr, NFAPI_HEADER_LENGTH, &hdr, sizeof(fapi_message_header_t), 0); printf("Decoded message %s message length 0x%02x\n", message_id_to_str(hdr.message_id), hdr.message_length); // Unpack the message diff --git a/nfapi/open-nFAPI/vnf/inc/vnf.h b/nfapi/open-nFAPI/vnf/inc/vnf.h index 26870f5523..39769314f4 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf.h @@ -20,7 +20,7 @@ #include "nfapi_vnf_interface.h" -typedef struct +struct vnf_t { nfapi_vnf_config_t _public; @@ -31,20 +31,22 @@ typedef struct uint8_t tx_message_buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE]; uint16_t next_phy_id; -} vnf_t; +}; 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_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); int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); -int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); + void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info); nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id); void nfapi_vnf_pnf_list_add(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* node); nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5_idx); + +void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config); + #endif // _VNF_H_ diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index 92623b41b8..7e04d69b49 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -19,7 +19,6 @@ #define _VNF_P7_H_ #include "nfapi_vnf_interface.h" - #define TIMEHR_SEC(_time_hr) ((uint32_t)(_time_hr) >> 20) #define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF) #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF)) @@ -108,7 +107,7 @@ typedef struct nfapi_vnf_p7_connection_info { } nfapi_vnf_p7_connection_info_t; -typedef struct { +struct vnf_p7_t{ nfapi_vnf_p7_config_t _public; @@ -121,7 +120,7 @@ typedef struct { uint8_t* rx_message_buffer; // would this be better put in the p7 conenction info? uint16_t rx_message_buffer_size; -} vnf_p7_t; +}; uint32_t vnf_get_current_time_hr(void); @@ -132,15 +131,20 @@ int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info); int send_mac_subframe_indications(vnf_p7_t* config); int send_mac_slot_indications(vnf_p7_t* config); int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); -int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); +void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7); +vnf_p7_rx_message_t* vnf_p7_rx_reassembly_queue_add_segment(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len); +void* vnf_p7_malloc(vnf_p7_t* vnf_p7, size_t size); +void vnf_p7_free(vnf_p7_t* vnf_p7, void* ptr); +void vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, vnf_p7_rx_message_t* msg); +void vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, uint32_t delta); +uint32_t calculate_transmit_timestamp(int mu, uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr); + void vnf_p7_connection_info_list_add(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* node); nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p7, uint16_t phy_id); 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_nr_p7_message_header_t* header); - void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index 6fd7d733eb..db303b8b4a 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -30,7 +30,9 @@ extern "C" { #endif -#define NFAPI_MAX_PACKED_MESSAGE_SIZE 32768 +typedef struct vnf_t vnf_t; +typedef struct vnf_p7_t vnf_p7_t; + /*! The nfapi VNF phy configuration information */ @@ -292,7 +294,25 @@ typedef struct nfapi_vnf_config */ int (*start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* resp); int (*nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_response_scf_t* resp); - + + /*! A callback for the ERROR.indication + * \param config A pointer to the vnf configuration + * \param p5_idx The p5 index used to indicate a particular pnf p5 connection + * \param ind A data structure for the decoded ERROR.indication This will + * have been allocated on the stack. + * \return not currently used. + * + * The ERROR.indication contains a reported error from the PNF, often signifying that a message has been sent too late + * + * + * The ind may contain pointers to dynamically allocated sub structures + * such as the vendor_extension. The dynamically allocated structure will + * be deallocated on return. If the client wishes to 'keep' the structures + * then the substructure pointers should be set to 0 and then the client should + * use the codec_config.deallocate function to release it at a future point + */ + int (*nr_error_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_error_indication_scf_t* ind); + /*! A callback for the STOP.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -449,10 +469,60 @@ typedef struct nfapi_vnf_config */ void (*deallocate_p4_p5_vendor_ext)(void* header); + /*! \brief Encodes a (n)FAPI P5 message to a buffer + * \param pMessageBuf A pointer to a (n)fapi 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. + */ + int (*pack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pPackedBuf, + uint32_t packedBufLen, + nfapi_p4_p5_codec_config_t* config); + /*! \brief Decodes an (n)FAPI 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 true on success, false on failure + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); + /*! \brief Decodes an (n)FAPI 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 true on success, false on failure + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p4_p5_codec_config_t* config); + + /*! \brief Sends a (n)FAPI P5 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the PNF + * \param vnf A pointer to a vnf_t* + * \param p5_idx The index of the P5 PNF intended to receive the message + * \param msg A pointer to the P5 message + * \param msg_len The size of the encoded P5 message header + * \return true on success, false on failure + */ + bool (*send_p5_msg)(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); - } nfapi_vnf_config_t; @@ -476,7 +546,6 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config); * * This function will not return untill nfapi_vnf_stop is called */ -int nfapi_nr_vnf_start(nfapi_vnf_config_t* config); int nfapi_vnf_start(nfapi_vnf_config_t* config); @@ -878,7 +947,52 @@ typedef struct nfapi_vnf_p7_config */ void (*deallocate_p7_vendor_ext)(void* header); + /*! A callback to pack a P7 message +* \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. +*/ + int (*pack_func)(void* pMessageBuf, void* pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); + /*! A callback to unpack a P7 message + * \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 true on success, false on failure + */ + bool (*unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); + + /*! \brief Decodes an NFAPI P7 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 true on success, false on failure + */ + bool (*hdr_unpack_func)(void* pMessageBuf, + uint32_t messageBufLen, + void* pUnpackedBuf, + uint32_t unpackedBufLen, + nfapi_p7_codec_config_t* config); + + /*! \brief Sends a (n)FAPI P7 message + * + * This function internally packs the given message into a buffer by calling the previously defined pack_func() function pointer + * Then, having the message buffer populated, sends it to the PNF + * \param vnf_p7 A pointer to a vnf_p7_t struct + * \param header A pointer to the P7 message to pack & send + * \return true on success, false on failure + */ + bool (*send_p7_msg)(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header); } nfapi_vnf_p7_config_t; /*! Creates and initializes the nfapi_vnf_p7_config structure before use @@ -902,7 +1016,7 @@ void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config); * function is called. */ int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config); -int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config); + /*! Stop the VNF P7 library. @@ -959,7 +1073,7 @@ int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t* config, int phy_id); * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_request_t* req); -int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req); +bool nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req); /*! Send the UL_CONFIG.request * \param config A pointer to the vnf p7 configuration @@ -970,7 +1084,7 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req); -int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); +bool nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); /*! Send the HI_DCI0.request * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -980,7 +1094,7 @@ int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_reque * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); -int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); +bool nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); /*! Send the TX.req * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -990,7 +1104,7 @@ int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_reque * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req); -int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); +bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); /*! Send the LBT_DL_CONFIG.requst * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded LBT_DL_CONFIG.request. diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 390c4b15d9..b61d5f26ae 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -29,9 +29,14 @@ #include "nfapi_nr_interface_scf.h" #ifdef ENABLE_AERIAL #include "nfapi/oai_integration/aerial/fapi_nvIPC.h" -#include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" #include "nr_fapi_p5.h" #endif +#ifdef ENABLE_WLS +#include +#endif // ENABLE_WLS + +#include + #include "nfapi/oai_integration/vendor_ext.h" void* vnf_malloc(nfapi_vnf_config_t* config, size_t size) @@ -117,7 +122,8 @@ void vnf_nr_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_ nfapi_nr_pnf_param_response_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // Invoke the call back if(config->pnf_nr_param_resp) @@ -188,7 +194,8 @@ void vnf_nr_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf nfapi_nr_pnf_config_response_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // Invoke the call back if(config->pnf_nr_config_resp) @@ -258,7 +265,8 @@ void vnf_nr_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_ nfapi_nr_pnf_start_response_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { if(config->pnf_nr_start_resp) { @@ -428,40 +436,39 @@ void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf nfapi_nr_param_response_scf_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { - - if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) - { - nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id); - - if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag) - { - struct sockaddr_in sockAddr; - - (void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH); - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr)); - - // store address - phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr; - } - - if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag) - { - struct sockaddr_in6 sockAddr6; - char addr6[64]; - (void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH); - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6))); - } - - if (msg.nfapi_config.p7_pnf_port.tl.tag) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value); - - // store port - phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value); - } - } + if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) { + nfapi_vnf_phy_info_t *phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id); + if (phy_info) { + if (msg.nfapi_config.p7_pnf_address_ipv4.tl.tag) { + struct sockaddr_in sockAddr; + + (void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr)); + + // store address + phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr; + } + + if (msg.nfapi_config.p7_pnf_address_ipv6.tl.tag) { + struct sockaddr_in6 sockAddr6; + char addr6[64]; + (void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, + "PNF P7 IPv6 address: %s\n", + inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6))); + } + + if (msg.nfapi_config.p7_pnf_port.tl.tag) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value); + + // store port + phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value); + } + } + } if(config->nr_param_resp) { @@ -495,7 +502,8 @@ void vnf_nr_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_con nfapi_nr_config_response_scf_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 ) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // check the error code: @@ -602,7 +610,8 @@ void vnf_nr_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf nfapi_nr_start_response_scf_t msg; // unpack the message - if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + const bool result = config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config); + if (result) { // check the error code if (msg.error_code == NFAPI_NR_START_MSG_OK){ if(config->nr_start_resp) @@ -624,6 +633,39 @@ void vnf_nr_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_conf } } +void vnf_nr_handle_error_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received ERROR.indication\n"); + + nfapi_nr_error_indication_scf_t msg; + + // unpack the message + if (config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config)) + { + if (config->nr_error_ind){ + (config->nr_error_ind)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dynamic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + + void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { @@ -1085,7 +1127,8 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa } // unpack the message header - if (nfapi_nr_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p4_p5_message_header_t), &config->codec_config) < 0) + const bool result = config->hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p4_p5_message_header_t), &config->codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -1115,7 +1158,11 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: vnf_nr_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx); - break; + break; + + case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION: + vnf_nr_handle_error_indication(pRecvMsg, recvMsgLen, config, p5_idx); + break; case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: vnf_nr_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); @@ -1257,119 +1304,6 @@ void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_ } } -int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) -{ - if (1) { - int socket_connected = 1; - - // 1. Peek the message header - // 2. If the message is larger than the stack buffer then create a dynamic buffer - // 3. Read the buffer - // 4. Handle the p5 message - - uint32_t header_buffer_size = NFAPI_NR_P5_HEADER_LENGTH; - uint8_t header_buffer[header_buffer_size]; - - uint32_t stack_buffer_size = 32; // should it be the size of then sctp_notificatoin structure - uint8_t stack_buffer[stack_buffer_size]; - - uint8_t* dynamic_buffer = 0; - - uint8_t* read_buffer = &stack_buffer[0]; - uint32_t message_size = 0; - - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - - struct sctp_sndrcvinfo sndrcvinfo; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - { - int flags = MSG_PEEK; - message_size = - sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); - - if (message_size == -1) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno); - return 0; - } - - nfapi_nr_p4_p5_message_header_t header; - int unpack_result = nfapi_nr_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); - if (unpack_result < 0) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header %d\n", unpack_result); - return 0; - } - message_size = header.message_length + header_buffer_size; - - // now have the size of the mesage - } - - if (message_size > stack_buffer_size) { - dynamic_buffer = (uint8_t*)malloc(message_size); - - if (dynamic_buffer == NULL) { - // todo : add error mesage - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); - return -1; - } - - read_buffer = dynamic_buffer; - } - - { - int flags = 0; - (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - int recvmsg_result = - sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); - if (recvmsg_result == -1) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); - } else { - if (flags & MSG_NOTIFICATION) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - // todo - handle the events - } else { - /* - NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", - pnf->p5_sock, - inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port), - sndrcvinfo.sinfo_assoc_id, - sndrcvinfo.sinfo_stream, - ntohl(sndrcvinfo.sinfo_ppid), - message_size, - flags); - */ - - // handle now if complete message in one or more segments - if ((flags & 0x80) == 0x80) { - // printf("\nVNF RECEIVES:\n"); - // for(int i=0; ip5_idx, config); - } else { - NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); - - // assume socket disconnected - NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); - socket_connected = 0; - } - } - } - } - - if (dynamic_buffer) { - free(dynamic_buffer); - } - - return socket_connected; - } -} int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) { @@ -1502,7 +1436,7 @@ int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* } } -static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, uint8_t stream) +static int vnf_send_p5_msg(vnf_t *vnf, nfapi_vnf_pnf_info_t *pnf, const void *msg, int len, uint8_t stream) { // printf("\n MESSAGE SENT: \n"); // for(int i=0; ip5_sock, msg, len, (struct sockaddr*)&pnf->p5_pnf_sockaddr, sizeof(pnf->p5_pnf_sockaddr),1, 0, stream, 0, 4); + ssize_t result = -1; + if (vnf->sctp) { + result = sctp_sendmsg(pnf->p5_sock, + msg, + len, + (struct sockaddr *)&pnf->p5_pnf_sockaddr, + sizeof(pnf->p5_pnf_sockaddr), + 1, + 0, + stream, + 0, + 4); + } else { + result = send(pnf->p5_sock, msg, len,0); + } if(result != len) { @@ -1530,53 +1478,6 @@ static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, return 0; } -int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint16_t msg_len) -{ - nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); - - if(pnf) - { - // pack the message for transmission - int packedMessageLength = 0; - if (NFAPI_MODE == NFAPI_MODE_AERIAL) { -#ifdef ENABLE_AERIAL - // In case it is a FAPI message, create 2 messages, one with nFAPI header for OAI PNF and one with no nFAPI header for Aerial - // L1 - // create FAPI tx_buffer - uint8_t tx_messagebufferFAPI[sizeof(vnf->tx_message_buffer)]; - int packedMessageLengthFAPI = -1; - packedMessageLengthFAPI = - fapi_nr_p5_message_pack(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); - return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg); -#else - return 0; -#endif - } else { - packedMessageLength = nfapi_nr_p5_message_pack(msg, - msg_len, - vnf->tx_message_buffer, - sizeof(vnf->tx_message_buffer), - &vnf->_public.codec_config); - - if (packedMessageLength < 0) { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_nr_p5_message_pack failed with return %d\n", packedMessageLength); - return -1; - } - // printf("msg id = 0x%02x, entire message length: %d\n", msg->message_id, packedMessageLength); - // for (int i = 0; i < packedMessageLength; i++) { - // printf(" msg->msg_buf[%d] = 0x%02x\n", i, ((uint8_t *) vnf->tx_message_buffer)[i]); - // } - - return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); - return -1; - } - -} - - 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) { nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); @@ -1592,7 +1493,7 @@ int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_messag return -1; } - return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); + return vnf_send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); } else { @@ -1617,7 +1518,7 @@ int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_messag return -1; } - return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); + return vnf_send_p5_msg(vnf, pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/); } else { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 633dd18f24..111d88e8dc 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -1,12 +1,12 @@ /* * Copyright 2017 Cisco Systems, Inc. - * + * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * + * * 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. @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "assertions.h" #include #include @@ -64,413 +65,6 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config) free(config); } -int nfapi_nr_vnf_start(nfapi_vnf_config_t* config) -{ - // Verify that config is not null - if(config == 0) - return -1; - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - - int p5ListenSock, p5Sock; - - struct sockaddr_in addr; - socklen_t addrSize; - - struct sockaddr_in6 addr6; - - struct sctp_event_subscribe events; - struct sctp_initmsg initMsg; - int noDelay; - - (void)memset(&addr, 0, sizeof(struct sockaddr_in)); - (void)memset(&addr6, 0, sizeof(struct sockaddr_in6)); - (void)memset(&events, 0, sizeof(struct sctp_event_subscribe)); - (void)memset(&initMsg, 0, sizeof(struct sctp_initmsg)); - - vnf_t* vnf = (vnf_t*)(config); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); - - /* - char * host = 0; - char * port = "4242"; - struct addrinfo hints; - bzero(&hints, sizeof(struct addrinfo)); - //hints.ai_flags=AI_PASSIVE; - //hints.ai_flags=AI_DEFAULT; - hints.ai_family=AF_UNSPEC; - //hints.ai_family=AF_INET6; - hints.ai_socktype=SOCK_STREAM; - //hints.ai_protocol=IPPROTO_SCTP - - struct addrinfo *aiHead = 0; - - - - int result = getaddrinfo(host, port, &hints, &aiHead); - NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno); - - while(aiHead->ai_next != NULL) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n", - aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP, - aiHead->ai_flags, AI_PASSIVE); - - char hostBfr[ NI_MAXHOST ]; - char servBfr[ NI_MAXSERV ]; - - getnameinfo(aiHead->ai_addr, - aiHead->ai_addrlen, - hostBfr, - sizeof( hostBfr ), - servBfr, - sizeof( servBfr ), - NI_NUMERICHOST | NI_NUMERICSERV ); - - switch(aiHead->ai_family) - { - case PF_INET: - { - struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr; - printf( - " ai_addr = sin_family: %d (AF_INET = %d, " - "AF_INET6 = %d)\n" - " sin_addr: %s\n" - " sin_port: %s\n", - pSadrIn->sin_family, - AF_INET, - AF_INET6, - hostBfr, - servBfr ); - } - break; - case PF_INET6: - { - struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr; - fprintf( stderr, - " ai_addr = sin6_family: %d (AF_INET = %d, " - "AF_INET6 = %d) \n" - " sin6_addr: %s\n" - " sin6_port: %s\n" - " sin6_flowinfo: %d\n" - " sin6_scope_id: %d\n", - pSadrIn6->sin6_family, - AF_INET, - AF_INET6, - hostBfr, - servBfr, - pSadrIn6->sin6_flowinfo, - pSadrIn6->sin6_scope_id); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n"); - break; - } - - aiHead = aiHead->ai_next; - } - */ - - { - int protocol; - int domain; - - if (vnf->sctp) - protocol = IPPROTO_SCTP; - else - protocol = IPPROTO_IP; - - if(config->vnf_ipv6) - { - domain = PF_INET6; - } - else - { - domain = AF_INET; - } - - // open the SCTP socket - if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); - return 0; - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock); - } - - if (vnf->sctp) - { - // configure for MSG_NOTIFICATION - if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n"); - // configure the SCTP socket options - initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater - initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater - if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - noDelay = 1; - if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - struct sctp_event_subscribe events; - memset( (void *)&events, 0, sizeof(events) ); - events.sctp_data_io_event = 1; - - if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); - close(p5ListenSock); - return -1; - } - - } - - - if(config->vnf_ipv6) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock); - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(config->vnf_p5_port); - addr6.sin6_addr = in6addr_any; - - // bind to the configured address and port - if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - } - else if(config->vnf_ipv4) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port); - addr.sin_family = AF_INET; - addr.sin_port = htons(config->vnf_p5_port); - addr.sin_addr.s_addr = INADDR_ANY; - - // bind to the configured address and port - if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) - //if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock); - - // put the socket into listen mode - if (listen(p5ListenSock, 2) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno); - close(p5ListenSock); - return 0; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n"); - - struct timeval tv; - fd_set read_fd_set; - - - int p5_idx = 0; - while(vnf->terminate == 0) - { - FD_ZERO(&read_fd_set); - - FD_SET(p5ListenSock, &read_fd_set); - int max_fd = p5ListenSock; - - tv.tv_sec = 5; - tv.tv_usec = 0; - - nfapi_vnf_pnf_info_t* pnf = config->pnf_list; - while(pnf != 0) - { - if(pnf->connected) - { - FD_SET(pnf->p5_sock, &read_fd_set); - if (pnf->p5_sock > max_fd) - { - max_fd = pnf->p5_sock; - } - } - - pnf = pnf->next; - } - - int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv); - - if(select_result == -1) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno); - close(p5ListenSock); - return 0; - } - else if(select_result) - { - if(FD_ISSET(p5ListenSock, &read_fd_set)) - { - addrSize = sizeof(struct sockaddr_in); - NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n"); - - p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize); - - if (p5Sock < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - nfapi_vnf_pnf_info_t* pnf = (nfapi_vnf_pnf_info_t*)malloc(sizeof(nfapi_vnf_pnf_info_t)); - NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); - memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); - pnf->p5_sock = p5Sock; - pnf->p5_idx = p5_idx++; - pnf->p5_pnf_sockaddr = addr; - pnf->connected = 1; - - nfapi_vnf_pnf_list_add(config, pnf); - - // Inform mac that a pnf connection has been established - // todo : allow mac to 'accept' the connection. i.e. to - // reject it. - if(config->pnf_nr_connection_indication != 0) - { - (config->pnf_nr_connection_indication)(config, pnf->p5_idx); - } - - - // check the connection status - { - struct sctp_status status; - (void)memset(&status, 0, sizeof(struct sctp_status)); - socklen_t optLen = (socklen_t) sizeof(struct sctp_status); - if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); - return -1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id); - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd); - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms); - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms); - - } - } - } - } - else - { - uint8_t delete_pnfs = 0; - - nfapi_vnf_pnf_info_t* pnf = config->pnf_list; - while(pnf != 0) - { - if(FD_ISSET(pnf->p5_sock, &read_fd_set)) - { - if(vnf_nr_read_dispatch_message(config, pnf) == 0) - { - if(config->pnf_disconnect_indication != 0) - { - (config->pnf_disconnect_indication)(config, pnf->p5_idx); - } - - close(pnf->p5_sock); - - pnf->to_delete = 1; - delete_pnfs = 1; - } - } - - pnf = pnf->next; - } - - if(delete_pnfs) - { - nfapi_vnf_pnf_info_t* pnf = config->pnf_list; - nfapi_vnf_pnf_info_t* prev = 0; - while(pnf != 0) - { - nfapi_vnf_pnf_info_t* curr = pnf; - - if(pnf->to_delete == 1) - { - if(prev == 0) - { - config->pnf_list = pnf->next; - } - else - { - prev->next = pnf->next; - } - - pnf = pnf->next; - - free(curr); - } - else - { - prev = pnf; - pnf = pnf->next; - } - - } - - } - } - - continue; - } - else - { - // timeout - - // Should we test for socket closure here every second? - - continue; - } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n"); - { - nfapi_vnf_pnf_info_t* curr = config->pnf_list; - while(curr != NULL) - { - if(config->pnf_disconnect_indication) - { - (config->pnf_disconnect_indication)(config, curr->p5_idx); - } - - close(curr->p5_sock); - curr = curr->next; - } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n"); - close(p5ListenSock); - - return 0; - -} int nfapi_vnf_start(nfapi_vnf_config_t* config) { @@ -894,8 +488,8 @@ int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_ return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t)); } int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req) @@ -914,8 +508,8 @@ int nfapi_nr_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_config_request_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_config_request_t)); } @@ -945,8 +539,8 @@ int nfapi_nr_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_ return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_start_request_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_start_request_t)); } int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_request_t* req) @@ -965,8 +559,8 @@ int nfapi_nr_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_para return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_param_request_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_param_request_scf_t)); } int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req) @@ -983,9 +577,9 @@ int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_con { if(config == 0 || req == 0) return -1; - + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); vnf_t* _this = (vnf_t*)(config); - +#if !defined(ENABLE_WLS) && !defined(ENABLE_AERIAL) nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); if(phy == NULL) @@ -1006,8 +600,8 @@ int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_con req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; req->nfapi_config.timing_info_period.value = phy->timing_info_period; req->num_tlv++; - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t)); +#endif + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t)); } int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req) @@ -1057,8 +651,8 @@ int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_star return -1; vnf_t* _this = (vnf_t*)(config); - - return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t)); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t)); } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 3d2975d03c..82c5ae7d1c 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -29,6 +29,9 @@ #include "nfapi/oai_integration/aerial/fapi_nvIPC.h" #endif #include "vnf_p7.h" +#ifdef ENABLE_WLS +#include +#endif #include "nr_fapi_p7_utils.h" #ifdef NDEBUG @@ -473,102 +476,6 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u return 0; } -int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_nr_p7_message_header_t* header) -{ - - nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); - if(p7_connection) - { - int send_result = 0; - uint8_t buffer[1024*1024*3]; - - header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, p7_connection->sequence_number); - - int len = nfapi_nr_p7_message_pack(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config); - - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); - - if(len < 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id); - return -1; - } - - if(len > vnf_p7->_public.segment_size) - { - // todo : consider replacing with the sendmmsg call - // todo : worry about blocking writes? - - // segmenting the transmit - int msg_body_len = len - NFAPI_NR_P7_HEADER_LENGTH ; - uint32_t seg_body_len = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH ; - int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); - - int segment = 0; - int offset = NFAPI_NR_P7_HEADER_LENGTH; - uint8_t tx_buffer[vnf_p7->_public.segment_size]; - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); - for(segment = 0; segment < segment_count; ++segment) - { - uint8_t last = 0; - uint32_t size = vnf_p7->_public.segment_size - NFAPI_NR_P7_HEADER_LENGTH; - if(segment + 1 == segment_count) - { - last = 1; - size = (msg_body_len) - (seg_body_len * segment); - } - - uint32_t segment_size = size + NFAPI_NR_P7_HEADER_LENGTH; - - // Update the header with the m and segement - memcpy(&tx_buffer[0], buffer, NFAPI_NR_P7_HEADER_LENGTH); - - // set the segment length - tx_buffer[4] = (segment_size & 0xFF000000) >> 24; - tx_buffer[5] = (segment_size & 0xFF0000) >> 16; - tx_buffer[6] = (segment_size & 0xFF00) >> 8; - tx_buffer[7] = (segment_size & 0xFF); - - // set the m & segment number - tx_buffer[8] = ((!last) << 7) + segment; - - memcpy(&tx_buffer[NFAPI_NR_P7_HEADER_LENGTH], &buffer[0] + offset, size); - offset += size; - - if(vnf_p7->_public.checksum_enabled) - { - nfapi_nr_p7_update_checksum(tx_buffer, segment_size); - } - - nfapi_nr_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); - - send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); - - } - } - else - { - if(vnf_p7->_public.checksum_enabled) - { - nfapi_nr_p7_update_checksum(buffer, len); - } - - nfapi_nr_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->mu, p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); - - // simple case that the message fits in a single segement - send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len); - } - - p7_connection->sequence_number++; - return send_result; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id); - return -1; - } -} - int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header) { @@ -676,7 +583,8 @@ int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t } int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) -{ +{ + nfapi_vnf_p7_config_t* config = (nfapi_vnf_p7_config_t*)vnf_p7; nfapi_nr_dl_node_sync_t dl_node_sync; memset(&dl_node_sync, 0, sizeof(dl_node_sync)); @@ -686,7 +594,7 @@ int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_inf dl_node_sync.t1 = calculate_nr_t1(p7_info->mu, p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr); dl_node_sync.delta_sfn_slot = 0; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); + return config->send_p7_msg(vnf_p7, &dl_node_sync.header); } int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) @@ -1098,10 +1006,8 @@ void vnf_nr_handle_p7_vendor_extension(void *pRecvMsg, int recvMsgLen, vnf_p7_t* NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n", __FUNCTION__); return; } - - int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &vnf_p7->_public.codec_config); - - if(unpack_result == 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, msg, msg_size, &vnf_p7->_public.codec_config); + if(!result) { if(vnf_p7->_public.vendor_ext) vnf_p7->_public.vendor_ext(&(vnf_p7->_public), msg); @@ -1497,8 +1403,8 @@ void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf else { nfapi_nr_slot_indication_scf_t ind = {0}; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1524,8 +1430,8 @@ void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* else { nfapi_nr_rx_data_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1551,8 +1457,8 @@ void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ else { nfapi_nr_crc_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1578,8 +1484,8 @@ void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ else { nfapi_nr_srs_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1604,8 +1510,8 @@ void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ else { nfapi_nr_uci_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1631,8 +1537,8 @@ void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf else { nfapi_nr_rach_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } @@ -1661,7 +1567,8 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 } nfapi_nr_ul_node_sync_t ind; - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_nr_ul_node_sync_t), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_nr_ul_node_sync_t), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_node_sync\n"); return; @@ -2096,7 +2003,8 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } nfapi_nr_timing_info_t ind; - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.unpack_func(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config); + if(!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack timing_info\n"); return; @@ -2220,7 +2128,7 @@ void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } -void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { nfapi_nr_p7_message_header_t header; @@ -2232,7 +2140,8 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 } // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0) + const bool result = vnf_p7->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config); + if (!result) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); return; @@ -2417,196 +2326,6 @@ void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } -void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - nfapi_nr_p7_message_header_t messageHeader; - - // validate the input params - if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%p %d %p)\n", pRecvMsg, recvMsgLen, vnf_p7); - return; - } - - // unpack the message header - if (nfapi_nr_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_nr_p7_message_header_t), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return; - } - - if(vnf_p7->_public.checksum_enabled) - { - uint32_t checksum = nfapi_nr_p7_calculate_checksum(pRecvMsg, recvMsgLen); - if(checksum != messageHeader.checksum) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d msg:%d len:%d\n", checksum, messageHeader.checksum, messageHeader.message_id, recvMsgLen); - return; - } - } - - uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); - uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); - uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); - - - if(m == 0 && segment_num == 0) - { - // we have a complete message - // ensure the message is sensible - if (recvMsgLen < 8 || pRecvMsg == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); - return; - } - - //vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7); - vnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, vnf_p7); - } - else - { - nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id); - - if(phy) - { - vnf_p7_rx_message_t* rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, &(phy->reassembly_queue), sequence_num, segment_num, m, pRecvMsg, recvMsgLen); - - if(rx_msg->num_segments_received == rx_msg->num_segments_expected) - { - // send the buffer on - uint16_t i = 0; - uint16_t length = 0; - for(i = 0; i < rx_msg->num_segments_expected; ++i) - { - length += rx_msg->segments[i].length - (i > 0 ? NFAPI_NR_P7_HEADER_LENGTH : 0); - } - - if(phy->reassembly_buffer_size < length) - { - vnf_p7_free(vnf_p7, phy->reassembly_buffer); - phy->reassembly_buffer = 0; - } - - if(phy->reassembly_buffer == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length); - phy->reassembly_buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, length); - - if(phy->reassembly_buffer == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length); - return; - } - memset(phy->reassembly_buffer, 0, length); - phy->reassembly_buffer_size = length; - } - - uint16_t offset = 0; - for(i = 0; i < rx_msg->num_segments_expected; ++i) - { - if(i == 0) - { - memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); - offset += rx_msg->segments[i].length; - } - else - { - memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_NR_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH); - offset += rx_msg->segments[i].length - NFAPI_NR_P7_HEADER_LENGTH; - } - } - - - //pnf_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); - vnf_nr_dispatch_p7_message(phy->reassembly_buffer, length , vnf_p7); - - - // delete the structure - vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg); - } - - // see corresponding comment in pnf_nr_handle_p7_message() [same commit] - vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 10000); - } - else - { - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id); - } - } -} - -int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7) -{ - int recvfrom_result = 0; - struct sockaddr_in remote_addr; - socklen_t remote_addr_size = sizeof(remote_addr); - - do - { - // peek the header - uint8_t header_buffer[NFAPI_NR_P7_HEADER_LENGTH]; - recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_NR_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); - - if(recvfrom_result > 0) - { - // get the segment size - nfapi_nr_p7_message_header_t header; - if(nfapi_nr_p7_message_header_unpack(header_buffer, NFAPI_NR_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); - return -1; - } - - // resize the buffer if we have a large segment - if(header.message_length > vnf_p7->rx_message_buffer_size) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); - vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length); - vnf_p7->rx_message_buffer_size = header.message_length; - } - - // read the segment - recvfrom_result = recvfrom(vnf_p7->socket, vnf_p7->rx_message_buffer, header.message_length, MSG_WAITALL | MSG_TRUNC, (struct sockaddr*)&remote_addr, &remote_addr_size); - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "recvfrom_result = %d from %s():%d\n", recvfrom_result, __FUNCTION__, __LINE__); - - // todo : how to handle incomplete readfroms, need some sort of buffer/select - - if (recvfrom_result > 0) - { - if (recvfrom_result != header.message_length) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "(%d) Received unexpected number of bytes. %d != %d", - __LINE__, recvfrom_result, header.message_length); - break; - } - NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Calling vnf_nr_handle_p7_message from %d\n", __LINE__); - vnf_nr_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno); - } - } - - if(recvfrom_result == -1) - { - if(errno == EAGAIN || errno == EWOULDBLOCK) - { - // return to the select - //NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); - } - } - } - while(recvfrom_result > 0); - - return 0; -} int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7) { @@ -2652,7 +2371,7 @@ int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7) __LINE__, recvfrom_result, header.message_length); break; } - NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling vnf_nr_handle_p7_message from %d\n", __LINE__); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling vnf_nr_reassemble_p7_message from %d\n", __LINE__); vnf_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); return 0; } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index d3160f4e30..225b0b7d8c 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -30,7 +30,7 @@ #include "common/ran_context.h" #include "openair1/PHY/defs_gNB.h" -#define FAPI2_IP_DSCP 0 + extern RAN_CONTEXT_t RC; @@ -96,115 +96,6 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // monitor the p7 endpoints and the timing loop and // send indications to mac -int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) -{ - if(config == 0) - return -1; - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - - vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - - // Create p7 receive udp port - // todo : this needs updating for Ipv6 - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port); - - // open the UDP socket - if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); - - // configure the UDP socket options - int iptos_value = FAPI2_IP_DSCP << 2; - if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n"); - - // Create the address structure - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(config->port); - addr.sin_addr.s_addr = INADDR_ANY; - - // bind to the configured port - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) - //if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); - return -1; - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n"); - - - //struct timespec original_pselect_timeout; - struct timespec pselect_timeout; - pselect_timeout.tv_sec = 100; - pselect_timeout.tv_nsec = 0; - - struct timespec ref_time; - clock_gettime(CLOCK_MONOTONIC, &ref_time); - while(vnf_p7->terminate == 0) - { - fd_set rfds; - int maxSock = 0; - FD_ZERO(&rfds); - int selectRetval = 0; - - // Add the p7 socket - FD_SET(vnf_p7->socket, &rfds); - maxSock = vnf_p7->socket; - - selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - - if(selectRetval == 0) - { - // pselect timed out, continue - } - else if(selectRetval > 0) - { - // have a p7 message - if(FD_ISSET(vnf_p7->socket, &rfds)) - { - vnf_nr_p7_read_dispatch_message(vnf_p7); - } - } - else - { - // pselect error - if(selectRetval == -1 && errno == EINTR) - { - // a sigal was received. - } - else - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond); - // should we exit now? - if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration - { - usleep(100000); - } - } - } - } - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); - close(vnf_p7->socket); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__); - - return 0; -} int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config) @@ -231,7 +122,7 @@ int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config) NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); // configure the UDP socket options - int iptos_value = FAPI2_IP_DSCP << 2; + int iptos_value = 0; if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); @@ -559,12 +450,12 @@ int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, node->slot = 0; node->min_sync_cycle_count = 8; node->mu = mu; - +#ifndef ENABLE_AERIAL // save the remote endpoint information node->remote_addr.sin_family = AF_INET; node->remote_addr.sin_port = pnf_p7_port;//htons(pnf_p7_port); node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr); - +#endif vnf_p7_connection_info_list_add(vnf_p7, node); return 0; @@ -600,7 +491,7 @@ int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_re return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req) +bool nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p req:%p)\n", __FUNCTION__, config, req); @@ -608,15 +499,17 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req) +bool nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req) { if(config == 0 || req == 0) return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req) @@ -627,13 +520,14 @@ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_re vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req) +bool nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req) { if(config == 0 || req == 0) return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req) { @@ -643,13 +537,14 @@ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_reques vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } -int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) +bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) { if(config == 0 || req == 0) return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + AssertFatal(config->send_p7_msg, "Function pointer must be configured|"); + return config->send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req) { diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 82ce60ca3b..bfb3f7fa21 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -334,7 +334,7 @@ static void test_pack_unpack(nfapi_nr_config_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_config_response_test.c b/nfapi/tests/p5/nr_fapi_config_response_test.c index bc44b4b6fd..36a6389c0c 100644 --- a/nfapi/tests/p5/nr_fapi_config_response_test.c +++ b/nfapi/tests/p5/nr_fapi_config_response_test.c @@ -92,7 +92,7 @@ void test_pack_unpack(nfapi_nr_config_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_error_indication_test.c b/nfapi/tests/p5/nr_fapi_error_indication_test.c index 85ef17b536..772b9bccea 100644 --- a/nfapi/tests/p5/nr_fapi_error_indication_test.c +++ b/nfapi/tests/p5/nr_fapi_error_indication_test.c @@ -40,7 +40,7 @@ void test_pack_unpack(nfapi_nr_error_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_param_request_test.c b/nfapi/tests/p5/nr_fapi_param_request_test.c index d42717eaeb..0af3fd9633 100644 --- a/nfapi/tests/p5/nr_fapi_param_request_test.c +++ b/nfapi/tests/p5/nr_fapi_param_request_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_param_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_param_response_test.c b/nfapi/tests/p5/nr_fapi_param_response_test.c index 1ba14c1655..e94e805bcb 100644 --- a/nfapi/tests/p5/nr_fapi_param_response_test.c +++ b/nfapi/tests/p5/nr_fapi_param_response_test.c @@ -233,7 +233,7 @@ void test_pack_unpack(nfapi_nr_param_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_start_request_test.c b/nfapi/tests/p5/nr_fapi_start_request_test.c index 9a36528db6..d908fbe023 100644 --- a/nfapi/tests/p5/nr_fapi_start_request_test.c +++ b/nfapi/tests/p5/nr_fapi_start_request_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_start_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_start_response_test.c b/nfapi/tests/p5/nr_fapi_start_response_test.c index bb3a096734..9d9423de83 100644 --- a/nfapi/tests/p5/nr_fapi_start_response_test.c +++ b/nfapi/tests/p5/nr_fapi_start_response_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_start_response_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_stop_indication_test.c b/nfapi/tests/p5/nr_fapi_stop_indication_test.c index 4b5d9d4319..e4205d982c 100644 --- a/nfapi/tests/p5/nr_fapi_stop_indication_test.c +++ b/nfapi/tests/p5/nr_fapi_stop_indication_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_stop_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p5/nr_fapi_stop_request_test.c b/nfapi/tests/p5/nr_fapi_stop_request_test.c index 74e5ea31ff..3536ad2272 100644 --- a/nfapi/tests/p5/nr_fapi_stop_request_test.c +++ b/nfapi/tests/p5/nr_fapi_stop_request_test.c @@ -41,7 +41,7 @@ void test_pack_unpack(nfapi_nr_stop_request_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_crc_indication_test.c b/nfapi/tests/p7/nr_fapi_crc_indication_test.c index 472959b0d6..71bb8eca1b 100644 --- a/nfapi/tests/p7/nr_fapi_crc_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_crc_indication_test.c @@ -72,7 +72,7 @@ static void test_pack_unpack(nfapi_nr_crc_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c b/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c index 2cc95260f0..599a3b85a5 100644 --- a/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c +++ b/nfapi/tests/p7/nr_fapi_dl_tti_request_test.c @@ -241,7 +241,7 @@ static void test_pack_unpack(nfapi_nr_dl_tti_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_rach_indication_test.c b/nfapi/tests/p7/nr_fapi_rach_indication_test.c index fd4a0fac32..83f569a7d1 100644 --- a/nfapi/tests/p7/nr_fapi_rach_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_rach_indication_test.c @@ -71,7 +71,7 @@ static void test_pack_unpack(nfapi_nr_rach_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c b/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c index 2f382cf797..18445a0ee2 100644 --- a/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_rx_data_indication_test.c @@ -69,7 +69,7 @@ static void test_pack_unpack(nfapi_nr_rx_data_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_slot_indication_test.c b/nfapi/tests/p7/nr_fapi_slot_indication_test.c index 96c030479c..414b52332f 100644 --- a/nfapi/tests/p7/nr_fapi_slot_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_slot_indication_test.c @@ -47,7 +47,7 @@ static void test_pack_unpack(nfapi_nr_slot_indication_scf_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_srs_indication_test.c b/nfapi/tests/p7/nr_fapi_srs_indication_test.c index 1271606b77..363aa43962 100644 --- a/nfapi/tests/p7/nr_fapi_srs_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_srs_indication_test.c @@ -78,7 +78,7 @@ static void test_pack_unpack(nfapi_nr_srs_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_tx_data_request_test.c b/nfapi/tests/p7/nr_fapi_tx_data_request_test.c index e67b5bf3ca..660c514b9c 100644 --- a/nfapi/tests/p7/nr_fapi_tx_data_request_test.c +++ b/nfapi/tests/p7/nr_fapi_tx_data_request_test.c @@ -132,7 +132,7 @@ static void test_pack_unpack(nfapi_nr_tx_data_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_uci_indication_test.c b/nfapi/tests/p7/nr_fapi_uci_indication_test.c index 9e2dcda6be..53f8469325 100644 --- a/nfapi/tests/p7/nr_fapi_uci_indication_test.c +++ b/nfapi/tests/p7/nr_fapi_uci_indication_test.c @@ -199,7 +199,7 @@ static void test_pack_unpack(nfapi_nr_uci_indication_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c b/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c index b1bc910da8..709c1c9db9 100644 --- a/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c +++ b/nfapi/tests/p7/nr_fapi_ul_dci_request_test.c @@ -103,7 +103,7 @@ static void test_pack_unpack(nfapi_nr_ul_dci_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c index 4f65cbfc9e..f7087c92ef 100644 --- a/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c +++ b/nfapi/tests/p7/nr_fapi_ul_tti_request_test.c @@ -422,7 +422,7 @@ static void test_pack_unpack(nfapi_nr_ul_tti_request_t *req) header_buffer[idx] = msg_buf[idx]; } uint8_t *pReadPackedMessage = header_buffer; - int unpack_header_result = fapi_nr_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); + int unpack_header_result = fapi_nr_p7_message_header_unpack(pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0); DevAssert(unpack_header_result >= 0); DevAssert(header.message_id == req->header.message_id); DevAssert(header.message_length == req->header.message_length); diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index ca453b6e65..7a706f61bf 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -42,6 +42,7 @@ #include "SCHED_NR/fapi_nr_l1.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h" int l1_north_init_gNB() { @@ -363,7 +364,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms; nfapi_nr_config_request_scf_t *gNB_config = &RC.gNB[Mod_id]->gNB_config; - memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg)); + copy_config_request(phy_config->cfg, gNB_config); uint64_t dl_bw_khz = (12*gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<ssb_config.scs_common.value); fp->dl_CarrierFreq = ((dl_bw_khz>>1) + gNB_config->carrier_config.dl_frequency.value)*1000 ; diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index 6856d85806..d61f0d0548 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -4,6 +4,10 @@ #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" #include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" #include "openair1/PHY/LTE_TRANSPORT/transport_common.h" +typedef struct pnf_t pnf_t; +typedef struct pnf_p7_t pnf_p7_t; +typedef struct vnf_t vnf_t; +typedef struct vnf_p7_t vnf_p7_t; void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, int frame, int slot, @@ -52,3 +56,80 @@ void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} +bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) +{ + return false; +} + +void *vnf_nr_start_p7_thread(void *ptr) +{ + return 0; +} + +bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +bool pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *header, uint32_t msg_len) +{ + return false; +} + +void *pnf_start_p5_thread(void *ptr) +{ + return 0; +} + +void vnf_start_p5_thread(void *ptr) +{ +} + +void *pnf_nr_p7_thread_start(void *ptr) +{ + return 0; +} + +bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *msg) +{ + return false; +} + +void wls_vnf_set_p7_config(void *p7_config) +{ +} + +bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) +{ + return false; +} + +void *wls_fapi_vnf_nr_start_thread(void *ptr) +{ + return NULL; +} + +bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) +{ + return false; +} + +void *wls_fapi_pnf_nr_start_thread(void *ptr) +{ + return NULL; +} + +void wls_pnf_set_p7_config(void *p7_config) +{ + +} diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 6b671abcfe..74a2178982 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -29,9 +29,6 @@ * \note * \warning */ -#ifdef ENABLE_AERIAL -#include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" -#endif #include "fapi_nr_l1.h" #include "common/ran_context.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c index 734a62d994..7aca911b7f 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c @@ -112,20 +112,20 @@ int32_t get_uldl_offset(int nr_bandP) void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { } -void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) +void configure_nr_nfapi_vnf(eth_params_t params) { } int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { return 0; } -int nfapi_nr_p7_message_unpack(void *pMessageBuf, +bool nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { - return 0; + return false; } int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 044dc56351..5274a4696d 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -78,9 +78,7 @@ #include "uper_encoder.h" #include "utils.h" #include "x2ap_messages_types.h" -#ifdef ENABLE_AERIAL -#include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" -#endif + static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; @@ -1759,15 +1757,15 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) RC.nrmac[j]->eth_params_s.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr); RC.nrmac[j]->eth_params_s.transp_preference = ETH_UDP_MODE; - configure_nr_nfapi_vnf( - RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc, RC.nrmac[j]->eth_params_s.remote_addr, RC.nrmac[j]->eth_params_s.remote_portd, RC.nrmac[j]->eth_params_s.my_portd); + configure_nr_nfapi_vnf(RC.nrmac[j]->eth_params_s); } else if(strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "aerial") == 0){ #ifdef ENABLE_AERIAL RC.nrmac[j]->nvipc_params_s.nvipc_shm_prefix = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_SHM_PREFIX].strptr)); RC.nrmac[j]->nvipc_params_s.nvipc_poll_core = *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_POLL_CORE].i8ptr); LOG_I(GNB_APP, "Configuring VNF for Aerial connection with prefix %s\n", RC.nrmac[j]->eth_params_s.local_if_name); - aerial_configure_nr_fapi_vnf(); + configure_nr_nfapi_vnf(RC.nrmac[j]->eth_params_s); + #endif } else { // other midhaul AssertFatal(1 == 0, "MACRLC %d: %s unknown southbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index e13ddac506..de5ae571ca 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -853,12 +853,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: { nfapi_nr_dl_tti_request_t *dl_tti_request = malloc16(sizeof(*dl_tti_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, dl_tti_request, - sizeof(*dl_tti_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message dl_tti_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, dl_tti_request, sizeof(*dl_tti_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message dl_tti_request failed to unpack\n"); + break; + } LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST message in sfn/slot %d %d. \n", dl_tti_request->SFN, dl_tti_request->Slot); @@ -877,12 +876,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: { nfapi_nr_tx_data_request_t *tx_data_request = malloc16(sizeof(*tx_data_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, tx_data_request, - sizeof(*tx_data_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message tx_data_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, tx_data_request, sizeof(*tx_data_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message tx_data_request failed to unpack\n"); + break; + } LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST message in SFN/slot %d %d. \n", tx_data_request->SFN, tx_data_request->Slot); if (!put_queue(&nr_tx_req_queue, tx_data_request)) @@ -897,12 +895,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: { nfapi_nr_ul_dci_request_t *ul_dci_request = malloc16(sizeof(*ul_dci_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, ul_dci_request, - sizeof(*ul_dci_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message ul_dci_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, ul_dci_request, sizeof(*ul_dci_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message ul_dci_request failed to unpack\n"); + break; + } LOG_D(NR_PHY, "Received an NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST message in SFN/slot %d %d. \n", ul_dci_request->SFN, ul_dci_request->Slot); if (!put_queue(&nr_ul_dci_req_queue, ul_dci_request)) @@ -917,12 +914,11 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: { nfapi_nr_ul_tti_request_t *ul_tti_request = malloc16(sizeof(*ul_tti_request)); - if (nfapi_nr_p7_message_unpack(buffer, len, ul_tti_request, - sizeof(*ul_tti_request), NULL) < 0) - { - LOG_E(NR_PHY, "Message ul_tti_request failed to unpack\n"); - break; - } + const bool result = nfapi_nr_p7_message_unpack(buffer, len, ul_tti_request, sizeof(*ul_tti_request), NULL); + if (!result) { + LOG_E(NR_PHY, "Message ul_tti_request failed to unpack\n"); + break; + } /* We are filtering UL_TTI_REQs below. We only care about UL_TTI_REQs that will trigger sending a ul_harq (CRC/RX pair). This UL_TTI_REQ will have NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE. If we have not yet completed the CBRA/ diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 2216fb5a75..39b8f426ce 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -6582,15 +6582,11 @@ void process_nr_nsa_msg(nsa_msg_t *msg, int msg_len) } nfapi_nr_dl_tti_request_t dl_tti_request; - int unpack_len = nfapi_nr_p7_message_unpack((void *)msg_buffer, - msg_len, - &dl_tti_request, - sizeof(nfapi_nr_dl_tti_request_t), - NULL); - if (unpack_len < 0) - { - LOG_E(RRC, "%s: SSB PDU unpack failed \n", __FUNCTION__); - break; + const bool result = + nfapi_nr_p7_message_unpack((void *)msg_buffer, msg_len, &dl_tti_request, sizeof(nfapi_nr_dl_tti_request_t), NULL); + if (!result) { + LOG_E(RRC, "%s: SSB PDU unpack failed \n", __FUNCTION__); + break; } int num_pdus = dl_tti_request.dl_tti_request_body.nPDUs; if (num_pdus <= 0)