Files
openairinterface5g/nfapi/oai_integration/wls_integration/wls_common.c
T
Rúben Soares Silva e08d904af0 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
2025-10-23 14:08:37 +01:00

129 lines
5.8 KiB
C

/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "wls_common.h"
#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;
currElem->num_message_in_block = numMsgInBlock;
currElem->align_offset = alignOffset;
currElem->msg_len = numMsgInBlock * alignOffset;
currElem->p_next = nextElem;
currElem->p_tx_data_elm_list = NULL;
currElem->time_stamp = 0;
}
uint64_t dequeueBlock(PWLS_MAC_CTX pWls)
{
uint64_t pa = WLS_DequeueBlock(pWls->hWls);
AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n");
unsigned long* va = WLS_PA2VA(pWls->hWls, pa);
AssertFatal(va, "WLS_PA2VA failed for headerElem\n");
while (*va != -1) {
pa = WLS_DequeueBlock(pWls->hWls);
AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n");
va = WLS_PA2VA(pWls->hWls, pa);
}
return pa;
}
uint8_t wls_msg_send(PWLS_MAC_CTX pWls, p_fapi_api_queue_elem_t currMsg)
{
uint32_t msgLen = 0;
AssertFatal(currMsg, "currMsg can't be NULL");
AssertFatal(currMsg->p_next, "There needs to be at least 2 blocks to send!");
msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t);
// Send the first block
if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, WLS_SG_FIRST) != 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the header block\n");
return false;
}
// Iterate over the linked list, until a NULL block or a block set to 0xFFFFFFFFFFFFFFFF ( invalid )
while (((currMsg = currMsg->p_next)) && (uint64_t)(currMsg) != -1) {
msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t);
/* Send the block with appropriate flags, either WLS_SG_NEXT or WLS_SG_LAST */
const unsigned short flags = currMsg->p_next != NULL ? WLS_SG_NEXT : WLS_SG_LAST;
if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, flags) != 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the message block\n");
return false;
}
}
return true;
}
void wls_return_msg_to_master(PWLS_MAC_CTX pWls,const uint64_t msg_PA)
{
p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, msg_PA);
AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n");
const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle
// No need to return the message contents, just the block
fill_fapi_list_elem(fapiMsgElem, NULL, FAPI_VENDOR_MSG_HEADER_IND, 1, 2);
memcpy((uint8_t *)(fapiMsgElem + 1), wls_header, 2);
const uint32_t msgLen = fapiMsgElem->msg_len + sizeof(fapi_api_queue_elem_t);
/* Send the block with appropriate only WLS_SG_FIRST flag, since we send only 1 block*/
if (WLS_Put(pWls->hWls, msg_PA, msgLen, FAPI_VENDOR_MSG_HEADER_IND, WLS_SG_FIRST) != 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR,"Failure in sending block back to master\n");
}
}
uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const int packed_len, const uint8_t *message)
{
int num_avail_blocks = WLS_NumBlocks(pWls->hWls);
NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks);
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);
AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n");
uint64_t pa_msg = dequeueBlock(pWls);
AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n");
p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr);
AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n");
p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg);
AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n");
fill_fapi_list_elem(fapiMsgElem, NULL, message_id, 1, packed_len + NFAPI_HEADER_LENGTH);
memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH);
uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle
if (NFAPI_MODE == NFAPI_MODE_VNF) {
// Use the opaque handle to signal to our PNF to not progress the FAPI PNF state machine
wls_header[1] = 0xff;
}
fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2);
memcpy((uint8_t *)(headerElem + 1), wls_header, 2);
uint8_t retval = wls_msg_send(pWls->hWls, headerElem);
return retval;
}