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
129 lines
5.8 KiB
C
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;
|
|
}
|
|
|