From 244819c6275396098247f2dcf9a3545d8cfe9004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Tue, 26 Aug 2025 15:10:46 +0100 Subject: [PATCH 1/5] Allocate VNF_info directly in config instead of global variable This allows access to the VNF configuration in the various transport mechanisms straight from config, without this, the transport specific thread would cause a segmentation fault when trying to access the pack/unpack function pointers. Add 2 functions to access the P5 and P7 VNF structures, to avoid having to always cast user_data and p7_vnfs --- nfapi/oai_integration/aerial/fapi_nvIPC.c | 27 +++-- nfapi/oai_integration/aerial/fapi_nvIPC.h | 2 +- nfapi/oai_integration/nfapi_vnf.c | 99 +++++++++++-------- nfapi/oai_integration/nfapi_vnf.h | 4 +- nfapi/oai_integration/socket/socket_pnf.c | 5 +- nfapi/oai_integration/socket/socket_vnf.c | 9 +- .../wls_integration/include/wls_vnf.h | 1 - .../oai_integration/wls_integration/wls_vnf.c | 16 +-- openair1/SCHED/nfapi_lte_dummy.c | 3 - 9 files changed, 87 insertions(+), 79 deletions(-) diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index b1bfae5415..9cd964cc0c 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -63,12 +63,8 @@ char cpu_buf_recv[RECV_BUF_LEN]; uint16_t sfn = 0, slot = 0; nv_ipc_t *ipc; -nfapi_vnf_config_t *vnf_config = 0; -void set_config(nfapi_vnf_config_t *conf) -{ - vnf_config = conf; -} + static uint16_t old_sfn = 0; static uint16_t old_slot = 0; //////////////////////////////////////////////////////////////////////// @@ -84,6 +80,7 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) uint8_t *end = msg->msg_buf + msg->msg_len; // unpack FAPI messages and handle them + nfapi_vnf_config_t * vnf_config = get_config(); if (vnf_config != 0) { // first, unpack the header fapi_phy_api_msg fapi_msg; @@ -576,13 +573,13 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s) 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); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_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); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_tti_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); @@ -598,11 +595,11 @@ 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) { - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_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); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_dci_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { @@ -613,12 +610,12 @@ 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) { - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_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); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &tx_data_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { @@ -630,10 +627,10 @@ 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) { - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_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); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &dl_config_req->header); dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; @@ -644,9 +641,9 @@ int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) } 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_vnf_p7_config_t *p7_config = get_p7_vnf_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); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &nr_slot_resp.header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 482d8103f0..72cf66bde7 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -56,7 +56,7 @@ bool aerial_send_P7_msg_with_data(void *packedBuf, 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); diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 5ea99de7ea..c2193fcaa3 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -70,10 +70,25 @@ #endif #define TEST - +static nfapi_vnf_config_t *config; extern RAN_CONTEXT_t RC; extern UL_RCC_IND_t UL_RCC_INFO; +nfapi_vnf_config_t * get_config() +{ + return config; +} +vnf_p7_t *get_p7_vnf() +{ + vnf_info *vnf = config->user_data; + return (vnf_p7_t *)vnf->p7_vnfs->config; +} + +nfapi_vnf_p7_config_t *get_p7_vnf_config() +{ + return &get_p7_vnf()->_public; +} + 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; @@ -1341,7 +1356,6 @@ void *configure_nr_p7_vnf(void *ptr) 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 @@ -1735,32 +1749,30 @@ void vnf_start_thread(void *ptr) { nfapi_vnf_start((nfapi_vnf_config_t *)ptr); } -static vnf_info vnf; - 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; - vnf.p7_vnfs[0].periodic_timing_enabled = 0; - 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(); + vnf_info *vnf = calloc(1, sizeof(vnf_info)); + memset(vnf->p7_vnfs, 0, sizeof(vnf->p7_vnfs)); + vnf->p7_vnfs[0].timing_window = 30; + vnf->p7_vnfs[0].periodic_timing_enabled = 0; + 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", + "[VNF] %s() vnf->p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, - vnf.p7_vnfs[0].config, + vnf->p7_vnfs[0].config, 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; + 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(); + vnf->p7_vnfs[0].mac = malloc(sizeof(mac_t)); + config = nfapi_vnf_config_create(); config->malloc = malloc; config->free = free; config->vnf_p5_port = params.my_portc; @@ -1780,7 +1792,7 @@ void configure_nr_nfapi_vnf(eth_params_t params) 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; + config->user_data = vnf; // To allow custom vendor extentions to be added to nfapi config->codec_config.unpack_vendor_extension_tlv = &vnf_nr_unpack_vendor_extension_tlv; config->codec_config.pack_vendor_extension_tlv = &vnf_nr_pack_vendor_extension_tlv; @@ -1817,7 +1829,6 @@ void configure_nr_nfapi_vnf(eth_params_t params) 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); @@ -1826,7 +1837,6 @@ void configure_nr_nfapi_vnf(eth_params_t params) 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) { @@ -1863,18 +1873,23 @@ void configure_nr_nfapi_vnf(eth_params_t params) void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { nfapi_setmode(NFAPI_MODE_VNF); - memset(&vnf, 0, sizeof(vnf)); - memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); - vnf.p7_vnfs[0].timing_window = 32; - vnf.p7_vnfs[0].periodic_timing_enabled = 1; - vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; - vnf.p7_vnfs[0].periodic_timing_period = 10; - vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port); - strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); - vnf.p7_vnfs[0].local_port = vnf_p7_port; - vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); - nfapi_vnf_config_t *config = nfapi_vnf_config_create(); + vnf_info *vnf = calloc(1, sizeof(vnf_info)); + memset(vnf->p7_vnfs, 0, sizeof(vnf->p7_vnfs)); + vnf->p7_vnfs[0].timing_window = 32; + vnf->p7_vnfs[0].periodic_timing_enabled = 1; + vnf->p7_vnfs[0].aperiodic_timing_enabled = 0; + vnf->p7_vnfs[0].periodic_timing_period = 10; + vnf->p7_vnfs[0].config = nfapi_vnf_p7_config_create(); + NFAPI_TRACE(NFAPI_TRACE_INFO, + "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", + __FUNCTION__, + vnf->p7_vnfs[0].config, + vnf_addr, + vnf_p5_port); + strcpy(vnf->p7_vnfs[0].local_addr, vnf_addr); + vnf->p7_vnfs[0].local_port = vnf_p7_port; + vnf->p7_vnfs[0].mac = malloc(sizeof(mac_t)); + config = nfapi_vnf_config_create(); config->malloc = malloc; config->free = free; config->vnf_p5_port = vnf_p5_port; @@ -1893,7 +1908,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int config->config_resp = &config_resp_cb; config->start_resp = &start_resp_cb; config->vendor_ext = &vendor_ext_cb; - config->user_data = &vnf; + config->user_data = vnf; // To allow custom vendor extentions to be added to nfapi config->codec_config.unpack_vendor_extension_tlv = &vnf_unpack_vendor_extension_tlv; config->codec_config.pack_vendor_extension_tlv = &vnf_pack_vendor_extension_tlv; @@ -1910,7 +1925,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! dl_config_req->header.message_id = NFAPI_DL_CONFIG_REQUEST; LOG_D(PHY, "[VNF] %s() DL_CONFIG_REQ sfn_sf:%d_%d number_of_pdus:%d\n", __FUNCTION__, @@ -1946,7 +1961,7 @@ int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { LOG_D(NR_PHY, "Entering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n", dl_config_req->SFN, dl_config_req->Slot); - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); 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!!!! @@ -1965,7 +1980,7 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_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; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_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); @@ -1982,7 +1997,7 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); tx_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! tx_req->header.message_id = NFAPI_TX_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); @@ -1998,7 +2013,7 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); 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); @@ -2014,7 +2029,7 @@ int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { } int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); hi_dci0_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! hi_dci0_req->header.message_id = NFAPI_HI_DCI0_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); @@ -2050,7 +2065,7 @@ static void remove_ul_config_req_pdu(int index, nfapi_ul_config_request_t *ul_co } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); 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; @@ -2070,7 +2085,7 @@ int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { } int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); ul_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_config_req->header.message_id = NFAPI_UL_CONFIG_REQUEST; //LOG_D(PHY, "[VNF] %s() header message_id:%02x\n", __FUNCTION__, ul_config_req->header.message_id); @@ -2130,7 +2145,7 @@ int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { int oai_nfapi_ue_release_req(nfapi_ue_release_request_t *release_req){ if(release_req->ue_release_request_body.number_of_TLVs <= 0) return 0; - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); release_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! release_req->header.message_id = NFAPI_UE_RELEASE_REQUEST; diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 104cff44f4..3e72896d37 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -148,5 +148,7 @@ typedef struct { 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(eth_params_t params); - +nfapi_vnf_config_t *get_config(); +vnf_p7_t *get_p7_vnf(); +nfapi_vnf_p7_config_t *get_p7_vnf_config(); #endif /* NFAPI_VNF_H_ */ diff --git a/nfapi/oai_integration/socket/socket_pnf.c b/nfapi/oai_integration/socket/socket_pnf.c index fe4999c998..ad6c0dec0c 100644 --- a/nfapi/oai_integration/socket/socket_pnf.c +++ b/nfapi/oai_integration/socket/socket_pnf.c @@ -21,6 +21,9 @@ #include "socket_pnf.h" #include "nfapi.h" +#include "nfapi.h" +static nfapi_pnf_config_t *config; + bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) { int packed_len = @@ -148,7 +151,7 @@ bool pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *head 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; + config = (nfapi_pnf_config_t *)ptr; struct sched_param sp; sp.sched_priority = 20; pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp); diff --git a/nfapi/oai_integration/socket/socket_vnf.c b/nfapi/oai_integration/socket/socket_vnf.c index 6440109ed6..518f57c2e3 100644 --- a/nfapi/oai_integration/socket/socket_vnf.c +++ b/nfapi/oai_integration/socket/socket_vnf.c @@ -21,6 +21,8 @@ #include "socket_vnf.h" #include "nfapi.h" +#include "nfapi_vnf.h" +#include #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) @@ -279,7 +281,6 @@ 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; @@ -293,7 +294,7 @@ static int nfapi_nr_vnf_p5_start(nfapi_vnf_config_t *config) struct sctp_initmsg initMsg = {0}; int noDelay; - vnf_t *vnf = (vnf_t *)(config); + vnf_t *vnf = (vnf_t *)(get_config()); NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); @@ -747,8 +748,8 @@ static int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t *config) return -1; NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - - vnf_p7_t *vnf_p7 = (vnf_p7_t *)config; + vnf_p7_t *vnf_p7 = get_p7_vnf(); + vnf_p7 = (vnf_p7_t *)config; // Create p7 receive udp port // todo : this needs updating for Ipv6 diff --git a/nfapi/oai_integration/wls_integration/include/wls_vnf.h b/nfapi/oai_integration/wls_integration/include/wls_vnf.h index 645b24d056..46a8766b6d 100644 --- a/nfapi/oai_integration/wls_integration/include/wls_vnf.h +++ b/nfapi/oai_integration/wls_integration/include/wls_vnf.h @@ -27,7 +27,6 @@ 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_vnf.c b/nfapi/oai_integration/wls_integration/wls_vnf.c index ccc68b4905..79934164f4 100644 --- a/nfapi/oai_integration/wls_integration/wls_vnf.c +++ b/nfapi/oai_integration/wls_integration/wls_vnf.c @@ -33,14 +33,7 @@ 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) { @@ -258,7 +251,7 @@ 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; } @@ -294,11 +287,11 @@ static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) 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); + vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, get_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); + vnf_nr_handle_p7_message(msg_buf, msg_size + NFAPI_NR_P7_HEADER_LENGTH, get_p7_vnf()); break; } default: @@ -308,6 +301,7 @@ static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) { + nfapi_vnf_config_t * config = get_config(); config = cfg; if (config == 0) { @@ -403,7 +397,7 @@ bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t * 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); diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index d61f0d0548..0028055c61 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -100,9 +100,6 @@ bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t * 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) { From 3247c2933f5e1eba18bb4e4f9ad6f6909c92cfec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Mon, 13 Oct 2025 08:20:52 +0100 Subject: [PATCH 2/5] Rework WLS VNF to be able to start before the PNF The WLS VNF is reworked to be able to start before the PNF, by calling call rte_eal_init and rte_dev_probe to determine if dpdk has been initialized properly, before calling rte_eal_init in the intended process when it is appropriate to do so --- .../oai_integration/wls_integration/wls_vnf.c | 59 +++++++++++++++---- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/nfapi/oai_integration/wls_integration/wls_vnf.c b/nfapi/oai_integration/wls_integration/wls_vnf.c index 79934164f4..ab2d5d4454 100644 --- a/nfapi/oai_integration/wls_integration/wls_vnf.c +++ b/nfapi/oai_integration/wls_integration/wls_vnf.c @@ -26,8 +26,10 @@ #include #include #include -#include #include +#include "common/utils/LOG/log.h" +#include +#include #include static nfapi_vnf_config_t *config; @@ -92,17 +94,54 @@ static bool wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pMemArr return true; } -void mac_dpdk_init() +bool primary_process_running(int argc, char *argv[]) { - 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 the PNF was stopped normally, this is enough, as the mp_socket file does not exist + if (access("/var/run/dpdk/" WLS_DEV_NAME "/mp_socket", W_OK | R_OK) != 0) + return false; - if (rte_eal_init(RTE_DIM(my_argv), my_argv) < 0) - rte_panic("\nCannot init EAL\n"); + // If we run rte_eal_init before the primary process is running, it will result in a 'Connection Refused' error in the logs, but + // the call itself will succeed ( retval not -1 ) + // + // We can use rte_eal_primary_proc_alive to determine if the primary process is running, the issue is that since the init had a + // refused connection, if we try to open WLS after rte_eal_primary_proc_alive reports that the primary is running, it will fail, + // since rte_eal_init failed to connect to the primary process, and we can't call rte_eal_init in the same process more than once, + // or it will result in an EALREADY error + // + // Given this, a new process is created that calls rte_eal_init and checks whether the primary process is running, exiting + // right after and reporting to our VNF the primary status + // + // When the VNF receives the status from the forked process that the + // primary process is running, it then calls rte_eal_init, which at this point we know will be successful, and continue to open + // the WLS instance + pid_t pid = fork(); + if (pid == 0) { + // We set the log level to emergency , effectively disabling logs in the child process + // This prevents too many logs being printed out to the terminal while we wait for the primary process to be available + rte_log_set_global_level(RTE_LOG_EMERG); + AssertFatal(rte_eal_init(argc, argv) != -1, "rte_eal_init() failed\n"); + int status = rte_eal_primary_proc_alive(NULL) == 0; + rte_eal_cleanup(); + _exit(status); + } + int status; + waitpid(pid, &status, 0); + return WIFEXITED(status) && WEXITSTATUS(status) == 0; +} + +bool mac_dpdk_init() +{ + char *my_argv[] = {"OAI_VNF", "-c3", "--proc-type=secondary", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa"}; + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "\nCalling rte_eal_init: "); + for (int i = 0; i < RTE_DIM(my_argv); i++) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s ", my_argv[i]); + } + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "\n"); + while (!primary_process_running(RTE_DIM(my_argv), my_argv)) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "DPDK primary process not available yet, retrying in 1 second...\n"); + sleep(1); + } + return rte_eal_init(RTE_DIM(my_argv), my_argv) >= 0; } static uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock) From e08d904af0c06738249136046259a9917750ce7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Tue, 26 Aug 2025 15:29:21 +0100 Subject: [PATCH 3/5] Implementation of STOP exchange This implements the STOP.request/indication for all 3 transport mechanisms, the VNF will send the STOP.request to the PNF, indicating it will disconnect, and await a STOP.indication from the PNF The WLS VNF is reworked to be able to start before the PNF, by calling call rte_eal_init and rte_dev_probe to determine if dpdk has been initialized properly, before calling rte_eal_init in the intended process when it is appropriate to do so --- executables/nr-softmodem.c | 2 + nfapi/oai_integration/aerial/fapi_nvIPC.c | 28 ++++++--- nfapi/oai_integration/aerial/fapi_nvIPC.h | 2 + nfapi/oai_integration/nfapi_pnf.c | 30 ++++++++++ nfapi/oai_integration/nfapi_pnf.h | 2 +- nfapi/oai_integration/nfapi_vnf.c | 57 +++++++++++++++++++ nfapi/oai_integration/nfapi_vnf.h | 1 + .../socket/include/socket_pnf.h | 1 + .../socket/include/socket_vnf.h | 1 + nfapi/oai_integration/socket/socket_pnf.c | 10 +++- nfapi/oai_integration/socket/socket_vnf.c | 15 +++++ .../wls_integration/include/wls_common.h | 1 - .../wls_integration/include/wls_pnf.h | 2 + .../wls_integration/include/wls_vnf.h | 2 + .../wls_integration/wls_common.c | 12 +++- .../oai_integration/wls_integration/wls_pnf.c | 35 +++++++++++- .../oai_integration/wls_integration/wls_vnf.c | 38 ++++++++++++- nfapi/open-nFAPI/nfapi/src/nfapi_p5.c | 8 +++ .../pnf/public_inc/nfapi_pnf_interface.h | 8 +++ nfapi/open-nFAPI/pnf/src/pnf_interface.c | 12 ++++ .../vnf/public_inc/nfapi_vnf_interface.h | 19 +++++++ nfapi/open-nFAPI/vnf/src/vnf.c | 28 +++++++++ nfapi/open-nFAPI/vnf/src/vnf_interface.c | 12 ++++ openair1/SCHED/nfapi_lte_dummy.c | 24 ++++++++ openair2/GNB_APP/gnb_config.c | 12 ++++ openair2/GNB_APP/gnb_config.h | 2 +- 26 files changed, 344 insertions(+), 20 deletions(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index d8df770cb8..a11941bff4 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -716,6 +716,8 @@ int main( int argc, char **argv ) { itti_wait_tasks_end(NULL); printf("Returned from ITTI signal handler\n"); + nfapi_stop_l1(); + if (RC.nb_nr_L1_inst > 0 || RC.nb_RU > 0) stop_L1(0); diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index 9cd964cc0c..05c08d391d 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -63,6 +63,18 @@ char cpu_buf_recv[RECV_BUF_LEN]; uint16_t sfn = 0, slot = 0; nv_ipc_t *ipc; +void nvIPC_Stop() +{ + LOG_I(NR_MAC, "Received STOP.indication\n"); + ((vnf_t *)get_config())->terminate = true; +} + +void nvIPC_send_stop_request() +{ + nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0}; + LOG_I(NR_MAC, "Sending NFAPI STOP.request\n"); + nfapi_nr_vnf_stop_req(get_config(), get_config()->pnf_list->p5_idx, &req); +} static uint16_t old_sfn = 0; @@ -476,7 +488,6 @@ static int aerial_recv_msg(nv_ipc_t *ipc, nv_ipc_msg_t *recv_msg) return 0; } -bool recv_task_running = false; void *epoll_recv_task(void *arg) { struct epoll_event ev, events[MAX_EVENTS]; @@ -494,11 +505,12 @@ void *epoll_recv_task(void *arg) if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) { LOG_E(NFAPI_VNF, "%s epoll_ctl failed\n", __func__); } - - while (1) { - if (!recv_task_running) { - recv_task_running = true; - } + // From here on out the thread is ready to receive data, simulate the reception + // of a PARAM.response to get the VNF to send a CONFIG.request + nfapi_nr_param_response_scf_t resp_msg = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE}; + nfapi_vnf_config_t * vnf_config = get_config(); + vnf_config->nr_param_resp(vnf_config, 1, &resp_msg); + while (((vnf_t *)vnf_config)->terminate == false) { LOG_D(NFAPI_VNF, "%s: epoll_wait fd_rx=%d ...\n", __func__, ipc_rx_event_fd); int nfds; @@ -521,6 +533,7 @@ void *epoll_recv_task(void *arg) } } close(epoll_fd); + ipc->ipc_destroy(ipc); return NULL; } @@ -565,9 +578,6 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s) LOG_I(NFAPI_VNF, "%s: create IPC interface successful\n", __func__); sleep(1); create_recv_thread(nvipc_params_s.nvipc_poll_core); - while(!recv_task_running){usleep(100000);} - nfapi_nr_param_response_scf_t resp_msg; - vnf_config->nr_param_resp(vnf_config, 1, &resp_msg); return 0; } diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 72cf66bde7..8740c1ecd3 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -63,4 +63,6 @@ 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); +void nvIPC_Stop(); +void nvIPC_send_stop_request(); #endif // OPENAIRINTERFACE_FAPI_NVIPC_H diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 3de11d8003..f884ad9187 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1836,6 +1836,35 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf return 0; } +void stop_nr_nfapi_pnf() +{ +#ifdef ENABLE_WLS + wls_fapi_nr_pnf_stop(); +#endif +#ifdef ENABLE_SOCKET + socket_nfapi_nr_pnf_stop(); +#endif +} +static bool has_sent_stop_ind = false; +int nr_stop_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_stop_request_scf_t *req) +{ + if (has_sent_stop_ind) { + // STOP.indication already sent, nothing to do + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "Send STOP.indication\n"); + nfapi_nr_stop_indication_scf_t resp = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION, + .header.phy_id = req->header.phy_id}; + nfapi_nr_stop_indication(config, &resp); + has_sent_stop_ind = true; +#ifdef ENABLE_WLS + wls_pnf_close(pnf_p5_init_and_receive_pthread); +#endif + // raise the SIGTERM to simulate CTRL+C + raise(SIGTERM); + return 0; +} + int measurement_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_measurement_request_t *req) { nfapi_measurement_response_t resp; memset(&resp, 0, sizeof(resp)); @@ -2191,6 +2220,7 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->nr_param_req = &nr_param_request; config->nr_config_req = &nr_config_request; config->nr_start_req = &nr_start_request; + config->nr_stop_req = &nr_stop_request; config->rssi_req = &rssi_request; config->broadcast_detect_req = &broadcast_detect_request; config->system_information_schedule_req = &system_information_schedule_request; diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 0ba0676f10..b9362785c9 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -37,5 +37,5 @@ int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); - +void stop_nr_nfapi_pnf(); #endif /* NFAPI_PNF_H_ */ diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index c2193fcaa3..0e9d641666 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1749,6 +1749,62 @@ void vnf_start_thread(void *ptr) { nfapi_vnf_start((nfapi_vnf_config_t *)ptr); } +static bool has_stop_ind = false; +static bool waiting_stop_ind = false; +int nr_stop_ind_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_stop_indication_scf_t *resp) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_STOP_IND idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + has_stop_ind = true; +#ifdef ENABLE_AERIAL + nvIPC_Stop(); +#endif +#ifdef ENABLE_SOCKET + nfapi_vnf_p7_stop(get_p7_vnf_config()); +#endif +#ifdef ENABLE_WLS + wls_vnf_stop(); +#endif + if (!waiting_stop_ind) { + // hasn't been initialized yet, means the PNF stopped before the VNF did + // raise a SIGINT to stop the VNF + raise(SIGINT); + } + return 0; +} + +void stop_nr_nfapi_vnf() +{ + if (has_stop_ind) { + // If it got here with the STOP.indication flag already set, it means it was triggered by the PNF, + // no need to send a STOP.request + return; + } +#ifdef ENABLE_WLS + wls_vnf_send_stop_request(); +#endif +#ifdef ENABLE_AERIAL + nvIPC_send_stop_request(); +#endif +#ifdef ENABLE_SOCKET + socket_nfapi_send_stop_request((vnf_t *)config); +#endif + waiting_stop_ind = true; + uint64_t counter = 0; + vnf_p7_t *p7_vnf = get_p7_vnf(); + while (p7_vnf->terminate == 0 && counter < 50) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Not terminated yet, counter %ld\n", counter); + usleep(1000); + counter++; + } + if (p7_vnf->terminate == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "STOP.indication timed out, exiting\n"); + nfapi_nr_stop_indication_scf_t msg = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION, .header.phy_id = 0}; + config->nr_stop_ind(config, 0, &msg); + } else { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Terminated, exiting\n"); + } +} + void configure_nr_nfapi_vnf(eth_params_t params) { #ifndef ENABLE_AERIAL @@ -1790,6 +1846,7 @@ void configure_nr_nfapi_vnf(eth_params_t params) 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_stop_ind = &nr_stop_ind_cb; config->nr_error_ind = &nr_error_ind_cb; config->vendor_ext = &vendor_nr_ext_cb; config->user_data = vnf; diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 3e72896d37..d71f9a2926 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -148,6 +148,7 @@ typedef struct { 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(eth_params_t params); +void stop_nr_nfapi_vnf(); nfapi_vnf_config_t *get_config(); vnf_p7_t *get_p7_vnf(); nfapi_vnf_p7_config_t *get_p7_vnf_config(); diff --git a/nfapi/oai_integration/socket/include/socket_pnf.h b/nfapi/oai_integration/socket/include/socket_pnf.h index ccb3eaea3a..cf5258eabb 100644 --- a/nfapi/oai_integration/socket/include/socket_pnf.h +++ b/nfapi/oai_integration/socket/include/socket_pnf.h @@ -36,4 +36,5 @@ bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, ui 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); +void socket_nfapi_nr_pnf_stop(); #endif // SOCKET_PNF_H diff --git a/nfapi/oai_integration/socket/include/socket_vnf.h b/nfapi/oai_integration/socket/include/socket_vnf.h index c11e009153..65c36d034f 100644 --- a/nfapi/oai_integration/socket/include/socket_vnf.h +++ b/nfapi/oai_integration/socket/include/socket_vnf.h @@ -31,4 +31,5 @@ bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_head 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); +void socket_nfapi_send_stop_request(vnf_t *vnf); #endif // SOCKET_VNF_H diff --git a/nfapi/oai_integration/socket/socket_pnf.c b/nfapi/oai_integration/socket/socket_pnf.c index ad6c0dec0c..6a96247b74 100644 --- a/nfapi/oai_integration/socket/socket_pnf.c +++ b/nfapi/oai_integration/socket/socket_pnf.c @@ -19,10 +19,16 @@ * contact@openairinterface.org */ #include "socket_pnf.h" -#include "nfapi.h" - #include "nfapi.h" static nfapi_pnf_config_t *config; +void socket_nfapi_nr_pnf_stop() +{ + AssertFatal(config->nr_stop_req, "STOP.request Handler should be set!"); + nfapi_nr_stop_request_scf_t req = {0}; + req.header.phy_id = 0; + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST; + config->nr_stop_req(config, 0, &req); +} bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) { diff --git a/nfapi/oai_integration/socket/socket_vnf.c b/nfapi/oai_integration/socket/socket_vnf.c index 518f57c2e3..75d4a37026 100644 --- a/nfapi/oai_integration/socket/socket_vnf.c +++ b/nfapi/oai_integration/socket/socket_vnf.c @@ -20,11 +20,26 @@ */ #include "socket_vnf.h" +#include "common/utils/LOG/log.h" #include "nfapi.h" #include "nfapi_vnf.h" #include #include "nfapi/oai_integration/vendor_ext.h" //TODO: Remove this include when removing the Aerial transport stuff + +void socket_stop_nfapi_p5_p7() +{ + get_p7_vnf()->terminate = 1; + get_config()->pnf_disconnect_indication = NULL; +} + +void socket_nfapi_send_stop_request(vnf_t *vnf) +{ + nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0}; + nfapi_nr_vnf_stop_req(&vnf->_public, 0, &req); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Sent NFAPI STOP.request\n"); +} + 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); diff --git a/nfapi/oai_integration/wls_integration/include/wls_common.h b/nfapi/oai_integration/wls_integration/include/wls_common.h index 1b6a8e4cdf..e823e93380 100644 --- a/nfapi/oai_integration/wls_integration/include/wls_common.h +++ b/nfapi/oai_integration/wls_integration/include/wls_common.h @@ -25,7 +25,6 @@ #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" diff --git a/nfapi/oai_integration/wls_integration/include/wls_pnf.h b/nfapi/oai_integration/wls_integration/include/wls_pnf.h index c678345967..ca89761b27 100644 --- a/nfapi/oai_integration/wls_integration/include/wls_pnf.h +++ b/nfapi/oai_integration/wls_integration/include/wls_pnf.h @@ -30,4 +30,6 @@ bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *m void *wls_fapi_pnf_nr_start_thread(void *ptr); int wls_fapi_nr_pnf_start(); void wls_pnf_set_p7_config(void *p7_config); +void wls_fapi_nr_pnf_stop(); +void wls_pnf_close(pthread_t p5_thread); #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 index 46a8766b6d..9206a03d62 100644 --- a/nfapi/oai_integration/wls_integration/include/wls_vnf.h +++ b/nfapi/oai_integration/wls_integration/include/wls_vnf.h @@ -29,4 +29,6 @@ void *wls_fapi_vnf_nr_start_thread(void *ptr); int wls_fapi_nr_vnf_start(); 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); +void wls_vnf_send_stop_request(); +void wls_vnf_stop(); #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 index fe4112eba8..6b471e0e96 100644 --- a/nfapi/oai_integration/wls_integration/wls_common.c +++ b/nfapi/oai_integration/wls_integration/wls_common.c @@ -20,7 +20,7 @@ */ #include "wls_common.h" - +#include "wls_lib.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; @@ -90,9 +90,19 @@ uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const in { int num_avail_blocks = WLS_NumBlocks(pWls->hWls); NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + int counter = 0; 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); + if (message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION) { + // In the case of the STOP.indication, it can happen that this is called after the VNF stopped + // For example, if it crashed for some reason, in that case, implement a timeout and return + usleep(10 * 1000); + counter++; + if (counter == 10) { + return true; + } + } } /* get PA blocks for header and msg */ uint64_t pa_hdr = dequeueBlock(pWls); diff --git a/nfapi/oai_integration/wls_integration/wls_pnf.c b/nfapi/oai_integration/wls_integration/wls_pnf.c index bed517ad01..e6fd609346 100644 --- a/nfapi/oai_integration/wls_integration/wls_pnf.c +++ b/nfapi/oai_integration/wls_integration/wls_pnf.c @@ -29,9 +29,10 @@ #include #include +#include "wls_lib.h" #include "pnf.h" #include "nr_nfapi_p7.h" -#include "nr_fapi_p5.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.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 @@ -65,6 +66,28 @@ void *wls_fapi_pnf_nr_start_thread(void *ptr) return (void *)0; } +void wls_pnf_close(pthread_t p5_thread) +{ + _this->terminate = 1; + WLS_WakeUp(wls_mac_get_ctx()->hWls); + pthread_join(p5_thread, NULL); + if (WLS_Close(wls_mac_get_ctx()->hWls) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] WLS_CLose call failed...\n"); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] WLS_CLose called successfully...\n"); + } + rte_eal_cleanup(); +} + +void wls_fapi_nr_pnf_stop() +{ + AssertFatal(cfg->nr_stop_req, "STOP.request Handler should be set!"); + nfapi_nr_stop_request_scf_t req = {0}; + req.header.phy_id = 0; + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST; + cfg->nr_stop_req(cfg, 0, &req); +} + int wls_fapi_nr_pnf_start() { int64_t ret; @@ -194,6 +217,9 @@ bool wls_pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t * 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); + if (_this->terminate) { + return false; + } NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks); } /* get PA blocks for header and msg */ @@ -254,7 +280,7 @@ void phy_mac_recv() bool to_return = false; while (_this->terminate == 0) { int numMsgToGet = WLS_Wait(pWls->hWls); - if (numMsgToGet == 0) { + if (numMsgToGet == 0 || _this->terminate) { continue; } uint64_t PAs[numMsgToGet]; @@ -279,6 +305,11 @@ void phy_mac_recv() } } } + // A STOP.indication might have been processed, which set's terminate to 1 + // don't return pages in that case + if (_this->terminate) { + break; + } 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 diff --git a/nfapi/oai_integration/wls_integration/wls_vnf.c b/nfapi/oai_integration/wls_integration/wls_vnf.c index ab2d5d4454..c72e17a2b6 100644 --- a/nfapi/oai_integration/wls_integration/wls_vnf.c +++ b/nfapi/oai_integration/wls_integration/wls_vnf.c @@ -21,7 +21,8 @@ #include "wls_vnf.h" #include "vnf_p7.h" - +#include "common/utils/LOG/log.h" +#include "wls_lib.h" #include #include #include @@ -31,8 +32,9 @@ #include #include #include +#include +#include "nfapi_vnf.h" -static nfapi_vnf_config_t *config; static WLS_MAC_CTX wls_mac_iface; vnf_t *_vnf = NULL; @@ -306,6 +308,33 @@ static int vnf_wls_init() return 1; } +void wls_vnf_stop() +{ + vnf_p7_t *p7_vnf = get_p7_vnf(); + _vnf->terminate = 1; + p7_vnf->terminate = 1; + rte_eal_cleanup(); +} + +void wls_vnf_send_stop_request() +{ + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0}; + vnf_p7_t *p7_vnf = get_p7_vnf(); + nfapi_vnf_config_t * config = get_config(); + if (p7_vnf == NULL || pWls->hWls == NULL) { + nfapi_nr_stop_indication_scf_t msg; + msg.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION; + msg.header.phy_id = 0; + config->nr_stop_ind(config, 0, &msg); + return; + } + + if (pWls->hWls != NULL) { + nfapi_nr_vnf_stop_req(config, 0, &req); + } +} + void *wls_fapi_vnf_nr_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] IN WLS PNF NFAPI start thread %s\n", __FUNCTION__); @@ -366,7 +395,7 @@ int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) PWLS_MAC_CTX pWls = wls_mac_get_ctx(); while (_vnf->terminate == 0) { int numMsgToGet = WLS_Wait(pWls->hWls); - if (numMsgToGet == 0) { + if (numMsgToGet == 0 || _vnf->terminate) { continue; } @@ -384,6 +413,9 @@ int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) procPhyMessages(len, (void *)(msg + 1), msg->msg_type); } } + if (_vnf->terminate) { + break; + } 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]); diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index 4516302e48..7d7388bad5 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -1254,6 +1254,10 @@ uint8_t pack_nr_p5_message_body(nfapi_nr_p4_p5_message_header_t *header, result = pack_stop_request(header, ppWritePackedMsg, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + result = pack_nr_stop_indication(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: result = pack_stop_response(header, ppWritePackedMsg, end, config); break; @@ -2447,6 +2451,10 @@ bool nfapi_nr_p5_message_unpack(void *pMessageBuf, result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + result = unpack_nr_stop_indication(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); break; 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 957e032f69..c6d5ee7c4d 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -497,6 +497,14 @@ int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_ */ int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp); +/*! Send the STOP.indication + * \param config A pointer to a pnf configuration + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_nr_stop_indication(nfapi_pnf_config_t* config, nfapi_nr_stop_indication_scf_t* resp); + /*! Send the MEASUREMENT.response * \param config A pointer to a pnf configuraiton * \param resp A pointer to the message structure diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index d80ab168fa..76db8ac2d5 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -387,6 +387,18 @@ int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp) return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_stop_response_t)); } +int nfapi_nr_stop_indication(nfapi_pnf_config_t* config, nfapi_nr_stop_indication_scf_t* resp) +{ + if (config == NULL || resp == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_stop_indication_scf_t)); +} + int nfapi_pnf_measurement_resp(nfapi_pnf_config_t* config, nfapi_measurement_response_t* resp) { if (config == NULL || resp == NULL) 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 db303b8b4a..3f326e841c 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -210,6 +210,24 @@ typedef struct nfapi_vnf_config int (*pnf_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp); int (*pnf_nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_response_t* resp); + /*! A callback for the STOP.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 STOP.indication This will + * have been allocated on the stack. + * \return not currently used. + * + * The STOP.indication contains the result of the STOP.request + * + * + * ind may contain pointers to dynamically allocated sub structures + * such as the vendor_extention. 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_stop_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_indication_scf_t* ind); + /*! A callback for the PNF_STOP.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -640,6 +658,7 @@ int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_star * \return 0 means success, -1 failure */ int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req); +int nfapi_nr_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_request_scf_t* req); /*! Send the MEASUREMENT.request * \param config A pointer to a vnf config diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index b61d5f26ae..84d4026188 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -665,6 +665,30 @@ void vnf_nr_handle_error_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_co } } +void vnf_nr_handle_stop_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 STOP.indication\n"); + + nfapi_nr_stop_indication_scf_t msg; + + // unpack the message + if (config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config)) { + if (config->nr_stop_ind) { + (config->nr_stop_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) { @@ -1172,6 +1196,10 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa vnf_handle_stop_response(pRecvMsg, recvMsgLen, config, p5_idx); break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + vnf_nr_handle_stop_indication(pRecvMsg, recvMsgLen, config, p5_idx); + break; + default: { if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 111d88e8dc..d421976cf1 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -665,6 +665,18 @@ int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_reques return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_stop_request_t)); } + +int nfapi_nr_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_request_scf_t* req) +{ + if (config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI STOP.request\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_stop_request_scf_t)); +} + int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req) { if(config == 0 || req == 0) diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index 0028055c61..500f69ae86 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -130,3 +130,27 @@ void wls_pnf_set_p7_config(void *p7_config) { } + +void wls_fapi_nr_pnf_stop() +{ +} + +void wls_pnf_close(pthread_t p5_thread) +{ +} + +void wls_vnf_send_stop_request() +{ +} + +void wls_vnf_stop() +{ +} + +void socket_nfapi_nr_pnf_stop() +{ +} + +void socket_nfapi_send_stop_request(vnf_t *vnf) +{ +} diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index dcd17efe22..ee318c6a85 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1354,6 +1354,18 @@ void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t *pdcp_co pdcp_config->drb.discard_timer = config_get_processedint(cfg, &pdcp_params[CONFIG_NR_PDCP_DRB_DISCARD_TIMER_IDX]); } +void nfapi_stop_l1() +{ + if (NFAPI_MODE && (NFAPI_MODE == NFAPI_MODE_AERIAL || NFAPI_MODE == NFAPI_MODE_VNF)) { + stop_nr_nfapi_vnf(); + } else if (NFAPI_MODE && NFAPI_MODE == NFAPI_MODE_PNF) { + // PNF should just wait for the STOP.request to come from the L2 + // If instead it was stopped first, in some cases it makes sense for it to terminate itself (WLS) + // Sends a STOP.indication to the VNF + stop_nr_nfapi_pnf(); + } +} + static void get_bwp_config(nr_mac_config_t *configuration) { char path[MAX_OPTNAME_SIZE * 2 + 8]; diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index 200400144b..96cf898ba0 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -64,7 +64,7 @@ f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCC int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); MessageDef *RCconfig_NR_CU_E1(const E1_t *entity); ngran_node_t get_node_type(void); - +void nfapi_stop_l1(); #ifdef E2_AGENT #include "openair2/E2AP/e2_agent_arg.h" e2_agent_args_t RCconfig_NR_E2agent(void); From c83bd8745943842331fa4374808b49d313f6f0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 1 Aug 2025 13:19:04 +0100 Subject: [PATCH 4/5] Fixup WLS documentation and Makefile patch --- cmake_targets/tools/install_wls_lib.patch | 61 ++++++++++++----------- doc/nfapi.md | 9 +++- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/cmake_targets/tools/install_wls_lib.patch b/cmake_targets/tools/install_wls_lib.patch index 5050b79a4e..c551f842b5 100644 --- a/cmake_targets/tools/install_wls_lib.patch +++ b/cmake_targets/tools/install_wls_lib.patch @@ -1,5 +1,5 @@ diff --git a/wls_lib/Makefile b/wls_lib/Makefile -index 2f8e4b2..e657488 100644 +index 2f8e4b2..7b99a26 100644 --- a/wls_lib/Makefile +++ b/wls_lib/Makefile @@ -1,20 +1,6 @@ @@ -23,7 +23,7 @@ index 2f8e4b2..e657488 100644 +################################################################ +# +################################################################ - + MYCUSTOMTAB=' ' MYCUSTOMSPACE='============================================================================================' @@ -24,11 +10,17 @@ MYCUSTOMSPACE1='------------------------------------------------------------' @@ -48,9 +48,12 @@ index 2f8e4b2..e657488 100644 else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icx) CC := icx CPP := icx -@@ -44,9 +36,9 @@ ifeq ($(WIRELESS_SDK_TARGET_ISA),sse) +@@ -42,11 +34,11 @@ endif + ifeq ($(WIRELESS_SDK_TARGET_ISA),sse) + TARGET_PROCESSOR := -xSSE4.2 else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx2) - TARGET_PROCESSOR := -xCORE-AVX2 +- TARGET_PROCESSOR := -xCORE-AVX2 ++ TARGET_PROCESSOR := -march=core-avx2 else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx512) - TARGET_PROCESSOR := -xCORE-AVX512 + TARGET_PROCESSOR := -march=skylake-avx512 @@ -63,7 +66,7 @@ index 2f8e4b2..e657488 100644 @@ -66,15 +58,38 @@ PROJECT_DIR := ./ BUILDDIR := make PROJECT_BINARY := $(PROJECT_NAME).so - + +PKGCONF ?= pkg-config +LIBDPDK_VERSION=20.11.3 + @@ -79,7 +82,7 @@ index 2f8e4b2..e657488 100644 +$(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 + @@ -88,10 +91,10 @@ index 2f8e4b2..e657488 100644 +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 \ @@ -104,74 +107,74 @@ index 2f8e4b2..e657488 100644 @@ -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)),) @@ -179,17 +182,17 @@ index 2f8e4b2..e657488 100644 - @$(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 +############################################################## diff --git a/doc/nfapi.md b/doc/nfapi.md index 214aa2799f..c372de6744 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -194,14 +194,19 @@ 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 +Build the O-DU (More details can be found in O-RAN's documentation page [here](https://docs.o-ran-sc.org/projects/o-ran-sc-o-du-l2/en/latest/user-guide.html#i-execution-on-locally-compiling-o-du-high-source-code)) 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 +The O-DU requires some virtual interfaces to be setup in order to enable communication between the O-DU, CU_stub and RIC_stub Setup local interfaces for the cu_stub, ric_stub and o_du +The IP addresses shown match the ones specified in OSC ODU configuration file, found in /build/config/tdd_odu_config.xml +The parameters referenced are , and - 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" + sudo ifconfig :ODU "192.168.130.81" + sudo ifconfig :CU_STUB "192.168.130.82" + sudo ifconfig :RIC_STUB "192.168.130.80" Run cu_stu and ric_stub in separate terminals From 09d9bb5b6aa0b50d3b4ef49ee2734a4f3d4c28af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 1 Aug 2025 17:15:17 +0100 Subject: [PATCH 5/5] Fix build for simulators This change is needed due to the previous addition of the function nfapi_stop_l1() in gnb_config.c which in turn calls 2 functions that do not exist in the simulators, since they're not linked against the nfapi libraries --- openair1/SIMULATION/NR_PHY/nr_unitary_defs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index 74fbf1051b..a84e57aa7f 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -79,6 +79,16 @@ int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) return (0); } +void stop_nr_nfapi_vnf() +{ + abort(); +} + +void stop_nr_nfapi_pnf() +{ + abort(); +} + void fill_scc_sim(NR_ServingCellConfigCommon_t *scc, uint64_t *ssb_bitmap, int N_RB_DL, int N_RB_UL, int mu_dl, int mu_ul); void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap); void prepare_scc(NR_ServingCellConfigCommon_t *scc);