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] 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);