Files
openairinterface5g/nfapi/oai_integration/wls_integration/wls_common.c
T
Rúben Soares Silva 3d34917626 Implementation of PNF using WLS as message transport
The common library exposes functions for the PNF to return the received blocks to the VNF for it to call WLS_Enqueue on them.
This is done in order to ensure the Blocks are returned after processing, also preventing the Dequeueing of blocks that are still being used, i.e. the internal value is not -1
All saved blocks are to be enqueued at the reception of a SLOT.indication by the VNF

Additionally, the definition of NFAPI_MAX_PACKED_MESSAGE_SIZE was moved to nfapi_interface.h and removed from the other headers, this is done to allow to set the maximum message size when using WLS by only changing the value in one place

Fixup fapi_nr_message_header_unpack call in nfapi_hex_parser
2025-07-11 10:01:26 +01:00

119 lines
5.4 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"
void fill_fapi_list_elem(p_fapi_api_queue_elem_t currElem, p_fapi_api_queue_elem_t nextElem, const uint8_t msgType, const uint8_t numMsgInBlock, const uint32_t alignOffset)
{
currElem->msg_type = msgType;
currElem->num_message_in_block = numMsgInBlock;
currElem->align_offset = alignOffset;
currElem->msg_len = numMsgInBlock * alignOffset;
currElem->p_next = nextElem;
currElem->p_tx_data_elm_list = NULL;
currElem->time_stamp = 0;
}
uint64_t dequeueBlock(PWLS_MAC_CTX pWls)
{
uint64_t pa = WLS_DequeueBlock(pWls->hWls);
AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n");
unsigned long* va = WLS_PA2VA(pWls->hWls, pa);
AssertFatal(va, "WLS_PA2VA failed for headerElem\n");
while (*va != -1) {
pa = WLS_DequeueBlock(pWls->hWls);
AssertFatal(pa, "WLS_DequeueBlock failed for pa_hdr\n");
va = WLS_PA2VA(pWls->hWls, pa);
}
return pa;
}
uint8_t wls_msg_send(PWLS_MAC_CTX pWls, p_fapi_api_queue_elem_t currMsg)
{
uint32_t msgLen = 0;
AssertFatal(currMsg, "currMsg can't be NULL");
AssertFatal(currMsg->p_next, "There needs to be at least 2 blocks to send!");
msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t);
// Send the first block
if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, WLS_SG_FIRST) != 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the header block\n");
return false;
}
// Iterate over the linked list, until a NULL block or a block set to 0xFFFFFFFFFFFFFFFF ( invalid )
while (((currMsg = currMsg->p_next)) && (uint64_t)(currMsg) != -1) {
msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t);
/* Send the block with appropriate flags, either WLS_SG_NEXT or WLS_SG_LAST */
const unsigned short flags = currMsg->p_next != NULL ? WLS_SG_NEXT : WLS_SG_LAST;
if (WLS_Put(pWls, WLS_VA2PA(pWls, currMsg), msgLen, currMsg->msg_type, flags) != 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failure in sending the message block\n");
return false;
}
}
return true;
}
void wls_return_msg_to_master(PWLS_MAC_CTX pWls,const uint64_t msg_PA)
{
p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, msg_PA);
AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n");
const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle
// No need to return the message contents, just the block
fill_fapi_list_elem(fapiMsgElem, NULL, FAPI_VENDOR_MSG_HEADER_IND, 1, 2);
memcpy((uint8_t *)(fapiMsgElem + 1), wls_header, 2);
const uint32_t msgLen = fapiMsgElem->msg_len + sizeof(fapi_api_queue_elem_t);
/* Send the block with appropriate only WLS_SG_FIRST flag, since we send only 1 block*/
if (WLS_Put(pWls->hWls, msg_PA, msgLen, FAPI_VENDOR_MSG_HEADER_IND, WLS_SG_FIRST) != 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR,"Failure in sending block back to master\n");
}
}
uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const int packed_len, const uint8_t *message)
{
int num_avail_blocks = WLS_NumBlocks(pWls->hWls);
NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks);
while (num_avail_blocks < 2) {
num_avail_blocks = WLS_NumBlocks(pWls->hWls);
NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks);
}
/* get PA blocks for header and msg */
uint64_t pa_hdr = dequeueBlock(pWls);
AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n");
uint64_t pa_msg = dequeueBlock(pWls);
AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n");
p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr);
AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n");
p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg);
AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n");
fill_fapi_list_elem(fapiMsgElem, NULL, message_id, 1, packed_len + NFAPI_HEADER_LENGTH);
memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH);
uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle
if (NFAPI_MODE == NFAPI_MODE_VNF) {
// Use the opaque handle to signal to our PNF to not progress the FAPI PNF state machine
wls_header[1] = 0xff;
}
fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2);
memcpy((uint8_t *)(headerElem + 1), wls_header, 2);
uint8_t retval = wls_msg_send(pWls->hWls, headerElem);
return retval;
}