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
484 lines
18 KiB
C
484 lines
18 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_vnf.h"
|
|
|
|
#include "vnf_p7.h"
|
|
#include "common/utils/LOG/log.h"
|
|
#include "wls_lib.h"
|
|
#include <rte_eal.h>
|
|
#include <rte_string_fns.h>
|
|
#include <rte_common.h>
|
|
#include <rte_lcore.h>
|
|
#include <nr_fapi_p5.h>
|
|
#include "common/utils/LOG/log.h"
|
|
#include <rte_errno.h>
|
|
#include <unistd.h>
|
|
#include <common/platform_constants.h>
|
|
#include <sys/wait.h>
|
|
#include "nfapi_vnf.h"
|
|
|
|
static WLS_MAC_CTX wls_mac_iface;
|
|
vnf_t *_vnf = NULL;
|
|
|
|
|
|
static PWLS_MAC_CTX wls_mac_get_ctx(void)
|
|
{
|
|
return &wls_mac_iface;
|
|
}
|
|
|
|
static uint8_t alloc_track[ALLOC_TRACK_SIZE];
|
|
//-------------------------------------------------------------------------------------------
|
|
/** @ingroup group_testmac
|
|
*
|
|
* @param[in] pMemArray Pointer to WLS Memory management structure
|
|
* @param[in] pMemArrayMemory Pointer to flat buffer that was allocated
|
|
* @param[in] totalSize Total Size of flat buffer allocated
|
|
* @param[in] nBlockSize Size of each block that needs to be partitioned by memory manager
|
|
*
|
|
* @return 0 if SUCCESS
|
|
*
|
|
* @description
|
|
* This function creates memory blocks from a flat buffer which will be used for communciation
|
|
* between MAC and PHY
|
|
*
|
|
**/
|
|
//-------------------------------------------------------------------------------------------
|
|
static bool wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pMemArrayMemory, uint32_t totalSize, uint32_t nBlockSize)
|
|
{
|
|
const uint32_t numBlocks = totalSize / nBlockSize;
|
|
|
|
printf("wls_mac_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
|
|
pMemArray,
|
|
pMemArrayMemory,
|
|
totalSize,
|
|
nBlockSize,
|
|
numBlocks);
|
|
AssertFatal(nBlockSize >= sizeof(void *), "WLS nBlockSize too small");
|
|
AssertFatal(totalSize > sizeof(void *), "WLS Can't allocate less than 1 block");
|
|
pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
|
|
pMemArray->pStorage = pMemArrayMemory;
|
|
pMemArray->pEndOfStorage = ((unsigned long *)pMemArrayMemory) + numBlocks * nBlockSize / sizeof(unsigned long);
|
|
pMemArray->nBlockSize = nBlockSize;
|
|
pMemArray->nBlockCount = numBlocks;
|
|
|
|
// Initialize single-linked list of free blocks;
|
|
void **ptr = (void **)pMemArrayMemory;
|
|
for (uint32_t i = 0; i < pMemArray->nBlockCount; i++) {
|
|
if (i == pMemArray->nBlockCount - 1) {
|
|
*ptr = NULL; // End of list
|
|
} else {
|
|
// Points to the next block
|
|
*ptr = (void **)(((uint8_t *)ptr) + nBlockSize);
|
|
ptr += nBlockSize / sizeof(unsigned long);
|
|
}
|
|
}
|
|
|
|
memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool primary_process_running(int argc, char *argv[])
|
|
{
|
|
// 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 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)
|
|
{
|
|
int idx;
|
|
|
|
if (pMemArray->ppFreeBlock == NULL) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "wls_mac_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
|
|
return 1;
|
|
}
|
|
|
|
// FIXME: Remove after debugging
|
|
if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR,
|
|
"wls_mac_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
|
|
pMemArray,
|
|
pMemArray->pStorage,
|
|
pMemArray->ppFreeBlock);
|
|
return 1;
|
|
}
|
|
|
|
pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
|
|
*pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
|
|
|
|
if ((*pMemArray->ppFreeBlock != NULL)
|
|
&& (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) || ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) {
|
|
fprintf(stderr,
|
|
"ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
|
|
pMemArray,
|
|
pMemArray->pStorage,
|
|
pMemArray->ppFreeBlock,
|
|
*pMemArray->ppFreeBlock);
|
|
return 1;
|
|
}
|
|
|
|
*ppBlock = (void *)pMemArray->ppFreeBlock;
|
|
pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock);
|
|
|
|
idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
|
|
if (alloc_track[idx]) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR,
|
|
"wls_mac_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
|
|
pMemArray,
|
|
pMemArray->pStorage,
|
|
pMemArray->ppFreeBlock,
|
|
*pMemArray->ppFreeBlock);
|
|
} else {
|
|
alloc_track[idx] = 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void wls_mac_print_stats(void)
|
|
{
|
|
PWLS_MAC_CTX pWls = wls_mac_get_ctx();
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "wls_mac_free_list_all:\n");
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG,
|
|
" nTotalBlocks[%d] nAllocBlocks[%d] nFreeBlocks[%d]\n",
|
|
pWls->nTotalBlocks,
|
|
pWls->nAllocBlocks,
|
|
(pWls->nTotalBlocks - pWls->nAllocBlocks));
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG,
|
|
" nTotalAllocCnt[%d] nTotalFreeCnt[%d] Diff[%d]\n",
|
|
pWls->nTotalAllocCnt,
|
|
pWls->nTotalFreeCnt,
|
|
(pWls->nTotalAllocCnt - pWls->nTotalFreeCnt));
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG,
|
|
" nDlBufAllocCnt[%d] nDlBufFreeCnt[%d] Diff[%d]\n",
|
|
pWls->nTotalDlBufAllocCnt,
|
|
pWls->nTotalDlBufFreeCnt,
|
|
(pWls->nTotalDlBufAllocCnt - pWls->nTotalDlBufFreeCnt));
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG,
|
|
" nUlBufAllocCnt[%d] nUlBufFreeCnt[%d] Diff[%d]\n\n",
|
|
pWls->nTotalUlBufAllocCnt,
|
|
pWls->nTotalUlBufFreeCnt,
|
|
(pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt));
|
|
}
|
|
|
|
static void *wls_mac_alloc_buffer(PWLS_MAC_CTX pWls, uint32_t size, uint32_t loc)
|
|
{
|
|
void *pBlock = NULL;
|
|
pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
|
|
if (wls_mac_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != 0) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "wls_mac_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc);
|
|
wls_mac_print_stats();
|
|
pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
|
|
return NULL;
|
|
}
|
|
pWls->nAllocBlocks++;
|
|
pWls->nTotalAllocCnt++;
|
|
if (loc < MAX_DL_BUF_LOCATIONS)
|
|
pWls->nTotalDlBufAllocCnt++;
|
|
else if (loc < MAX_UL_BUF_LOCATIONS)
|
|
pWls->nTotalUlBufAllocCnt++;
|
|
|
|
pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
|
|
|
|
return pBlock;
|
|
}
|
|
|
|
static bool mac_wls_init()
|
|
{
|
|
uint64_t nWlsMacMemorySize = 0;
|
|
uint64_t nWlsPhyMemorySize = 0;
|
|
PWLS_MAC_CTX pWls = wls_mac_get_ctx();
|
|
|
|
pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL);
|
|
pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL);
|
|
|
|
pWls->nTotalAllocCnt = 0;
|
|
pWls->nTotalFreeCnt = 0;
|
|
pWls->nTotalUlBufAllocCnt = 0;
|
|
pWls->nTotalUlBufFreeCnt = 0;
|
|
pWls->nTotalDlBufAllocCnt = 0;
|
|
pWls->nTotalDlBufFreeCnt = 0;
|
|
|
|
/* Start by opening the WLS instance with WLS_MASTER_CLIENT */
|
|
if ((pWls->hWls = WLS_Open(WLS_DEV_NAME, WLS_MASTER_CLIENT, &nWlsMacMemorySize, &nWlsPhyMemorySize)) == NULL) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not open WLS Interface \n");
|
|
return false;
|
|
}
|
|
|
|
/* WLS_Open was successful, we can allocate memory */
|
|
if ((pWls->pWlsMemBase = WLS_Alloc(pWls->hWls, nWlsMacMemorySize + nWlsPhyMemorySize)) == NULL) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not allocate WLS Memory \n");
|
|
return false;
|
|
}
|
|
/* Set the total memory that MAC has access to */
|
|
pWls->nTotalMemorySize = nWlsMacMemorySize;
|
|
|
|
/* Partition the WLS memory */
|
|
memset(pWls->pWlsMemBase, 0xCC, pWls->nTotalMemorySize);
|
|
pWls->pPartitionMemBase = pWls->pWlsMemBase;
|
|
pWls->nPartitionMemSize = pWls->nTotalMemorySize;
|
|
pWls->nTotalBlocks = pWls->nTotalMemorySize / (NFAPI_MAX_PACKED_MESSAGE_SIZE);
|
|
/* Create the memory array */
|
|
if (!wls_mac_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase, pWls->nPartitionMemSize, NFAPI_MAX_PACKED_MESSAGE_SIZE)) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "\nCould not create WLS Memory Array \n");
|
|
return false;
|
|
}
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "\nTotalBlocks is %d \n", pWls->nTotalBlocks);
|
|
int nBlocks = 0;
|
|
for(int i = 0 ; i< pWls->nTotalBlocks; i++){
|
|
void* pMsg = wls_mac_alloc_buffer(pWls, 0, i);
|
|
/* Enqueue all blocks */
|
|
nBlocks += WLS_EnqueueBlock(pWls->hWls, WLS_VA2PA(pWls->hWls, pMsg));
|
|
}
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "\nAllocated %d Blocks \n", nBlocks);
|
|
return true;
|
|
}
|
|
|
|
static int vnf_wls_init()
|
|
{
|
|
mac_dpdk_init();
|
|
|
|
if (!mac_wls_init()) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void wls_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__);
|
|
wls_fapi_nr_vnf_start((nfapi_vnf_config_t *)ptr);
|
|
return (void *)0;
|
|
}
|
|
|
|
static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "[VNF] Received Msg ID 0x%02x\n", msg_id);
|
|
if (msg_buf == NULL || _vnf == NULL) {
|
|
AssertFatal(msg_buf != NULL && _vnf != NULL, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
// Add the size of the header to the message_size, because the size in the header does not include the header length
|
|
msg_size += NFAPI_NR_P5_HEADER_LENGTH;
|
|
switch (msg_id) {
|
|
case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
|
|
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
|
|
case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
|
|
case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
|
|
vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, 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, get_p7_vnf());
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg)
|
|
{
|
|
nfapi_vnf_config_t * config = get_config();
|
|
config = cfg;
|
|
|
|
if (config == 0) {
|
|
return -1;
|
|
}
|
|
_vnf = (vnf_t *)(config);
|
|
|
|
// init WLS connection
|
|
if (vnf_wls_init() == 0) {
|
|
return -1;
|
|
}
|
|
_vnf->terminate = 0;
|
|
|
|
// Connect to the PNF
|
|
if (config->pnf_nr_start_resp != 0) {
|
|
(config->pnf_nr_start_resp)(config, 0, NULL);
|
|
}
|
|
/* VNF receive loop */
|
|
/* Number of Memory blocks to get */
|
|
uint32_t msgSize;
|
|
uint16_t msgType;
|
|
uint16_t flags;
|
|
PWLS_MAC_CTX pWls = wls_mac_get_ctx();
|
|
while (_vnf->terminate == 0) {
|
|
int numMsgToGet = WLS_Wait(pWls->hWls);
|
|
if (numMsgToGet == 0 || _vnf->terminate) {
|
|
continue;
|
|
}
|
|
|
|
uint64_t PAs[numMsgToGet];
|
|
uint8_t pa_idx = 0;
|
|
while (numMsgToGet--) {
|
|
PAs[pa_idx] = WLS_Get(pWls->hWls, &msgSize, &msgType, &flags);
|
|
pa_idx++;
|
|
}
|
|
for (int i = 0; i < pa_idx; i++) {
|
|
p_fapi_api_queue_elem_t msg = WLS_PA2VA(pWls->hWls, PAs[i]);
|
|
if (msg->msg_type != FAPI_VENDOR_MSG_HEADER_IND) {
|
|
uint8_t *msgt = (uint8_t *)(msg + 1);
|
|
uint32_t len = msgt[7] | (msgt[6] << 8) | (msgt[5] << 16) | (msgt[4] << 24);
|
|
procPhyMessages(len, (void *)(msg + 1), msg->msg_type);
|
|
}
|
|
}
|
|
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]);
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
bool wls_vnf_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len)
|
|
{
|
|
UNUSED_VARIABLE(p5_idx);
|
|
int packed_len =
|
|
vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config);
|
|
|
|
if (packed_len < 0) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len);
|
|
return false;
|
|
}
|
|
|
|
// printf("fapi_nr_p5_message_pack succeeded having packed %d bytes\n", packed_len);
|
|
// printf("in msg, msg_len is %d\n", msg->message_length);
|
|
PWLS_MAC_CTX pWls = wls_mac_get_ctx();
|
|
|
|
int retval = wls_send_fapi_msg(pWls, msg->message_id, packed_len, vnf->tx_message_buffer);
|
|
if (retval) {
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "wls_send_fapi_msg success\n");
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *msg)
|
|
{
|
|
uint32_t message_id = msg->message_id;
|
|
PWLS_MAC_CTX pWls = wls_mac_get_ctx();
|
|
int num_avail_blocks = WLS_NumBlocks(pWls->hWls);
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks);
|
|
while (num_avail_blocks < 2) {
|
|
num_avail_blocks = WLS_NumBlocks(pWls->hWls);
|
|
NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks);
|
|
}
|
|
/* get PA blocks for header and msg */
|
|
uint64_t pa_hdr = dequeueBlock(pWls);
|
|
AssertFatal(pa_hdr, "WLS_DequeueBlock failed for pa_hdr\n");
|
|
uint64_t pa_msg = dequeueBlock(pWls);
|
|
AssertFatal(pa_msg, "WLS_DequeueBlock failed for pa_msg\n");
|
|
p_fapi_api_queue_elem_t headerElem = WLS_PA2VA(pWls->hWls, pa_hdr);
|
|
AssertFatal(headerElem, "WLS_PA2VA failed for headerElem\n");
|
|
p_fapi_api_queue_elem_t fapiMsgElem = WLS_PA2VA(pWls->hWls, pa_msg);
|
|
AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n");
|
|
//memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH);
|
|
const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle
|
|
|
|
fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2);
|
|
memcpy((uint8_t *)(headerElem + 1), wls_header, 2);
|
|
int packed_len = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(msg, (fapiMsgElem + 1), NFAPI_MAX_PACKED_MESSAGE_SIZE, NULL);
|
|
if (packed_len < 0) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "fapi_p7_message_pack failed (%d)\n", packed_len);
|
|
return false;
|
|
}
|
|
fill_fapi_list_elem(fapiMsgElem, NULL, message_id, 1, packed_len + NFAPI_HEADER_LENGTH);
|
|
uint8_t retval = wls_msg_send(pWls->hWls, headerElem);
|
|
return retval;
|
|
//return wls_send_fapi_msg(pWls, msg->message_id, packed_len, _vnf->tx_message_buffer);
|
|
}
|