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
2170 lines
58 KiB
C
2170 lines
58 KiB
C
/*
|
|
* Copyright 2017 Cisco Systems, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/sctp.h>
|
|
#include <netdb.h>
|
|
#include <arpa/inet.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include "nfapi_nr_interface.h"
|
|
#include "nfapi_nr_interface_scf.h"
|
|
#include "pnf.h"
|
|
|
|
#include <socket/include/socket_common.h>
|
|
|
|
#include "nfapi/open-nFAPI/fapi/inc/nr_fapi.h"
|
|
|
|
# if 1 // for hard-code (remove later)
|
|
#include "common/platform_types.h"
|
|
#include "common/platform_constants.h"
|
|
#include "common/ran_context.h"
|
|
|
|
#include "common/utils/LOG/log.h"
|
|
#include "common/utils/LOG/vcd_signal_dumper.h"
|
|
|
|
#include "NR_BCCH-BCH-Message.h"
|
|
#include "NR_ServingCellConfigCommon.h"
|
|
|
|
#include "SCHED_NR/phy_frame_config_nr.h"
|
|
|
|
#include "NR_MIB.h"
|
|
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
|
#ifdef ENABLE_WLS
|
|
#include "wls_integration/include/wls_pnf.h"
|
|
#endif
|
|
#endif
|
|
|
|
#define MAX_SCTP_STREAMS 16
|
|
|
|
void nfapi_pnf_phy_config_delete_all(nfapi_pnf_config_t* config)
|
|
{
|
|
nfapi_pnf_phy_config_t* curr = config->phys;
|
|
while(curr != 0)
|
|
{
|
|
nfapi_pnf_phy_config_t* to_delete = curr;
|
|
curr = curr->next;
|
|
free(to_delete);
|
|
}
|
|
|
|
config->phys = 0;
|
|
}
|
|
|
|
void nfapi_pnf_phy_config_add(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy)
|
|
{
|
|
phy->next = config->phys;
|
|
config->phys = phy;
|
|
}
|
|
|
|
nfapi_pnf_phy_config_t* nfapi_pnf_phy_config_find(nfapi_pnf_config_t* config, uint16_t phy_id)
|
|
{
|
|
nfapi_pnf_phy_config_t* curr = config->phys;
|
|
while(curr != 0)
|
|
{
|
|
if(curr->phy_id == phy_id)
|
|
return curr;
|
|
|
|
curr = curr->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void pnf_nr_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_pnf_param_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_PARAM.request received\n");
|
|
|
|
/// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message
|
|
const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_nr_pnf_param_request_t), &pnf->_public.codec_config);
|
|
if (result)
|
|
{
|
|
if(pnf->_public.state == NFAPI_PNF_IDLE)
|
|
{
|
|
if(pnf->_public.pnf_nr_param_req)
|
|
{
|
|
(pnf->_public.pnf_nr_param_req)(&pnf->_public, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in IDLE state\n", __FUNCTION__);
|
|
|
|
nfapi_nr_pnf_param_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_pnf_param_resp(&pnf->_public, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_pnf_param_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_PARAM.request received\n");
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_pnf_param_request_t), &pnf->_public.codec_config) >= 0)
|
|
{
|
|
if(pnf->_public.state == NFAPI_PNF_IDLE)
|
|
{
|
|
if(pnf->_public.pnf_param_req)
|
|
{
|
|
(pnf->_public.pnf_param_req)(&pnf->_public, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in IDLE state\n", __FUNCTION__);
|
|
|
|
nfapi_pnf_param_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_pnf_param_resp(&pnf->_public, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
|
|
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_pnf_config_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_CONFIG.request received\n");
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0)
|
|
{
|
|
// ensure correct state
|
|
if(pnf->_public.state != NFAPI_PNF_RUNNING)
|
|
{
|
|
// delete the phy records
|
|
nfapi_pnf_phy_config_delete_all(&pnf->_public);
|
|
|
|
// create the phy records
|
|
if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG)
|
|
{
|
|
int i = 0;
|
|
for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = (nfapi_pnf_phy_config_t*)malloc(sizeof(nfapi_pnf_phy_config_t));
|
|
memset(phy, 0, sizeof(nfapi_pnf_phy_config_t));
|
|
|
|
phy->state = NFAPI_PNF_PHY_IDLE;
|
|
phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id;
|
|
|
|
nfapi_pnf_phy_config_add(&(pnf->_public), phy);
|
|
}
|
|
}
|
|
|
|
if(pnf->_public.pnf_config_req)
|
|
{
|
|
(pnf->_public.pnf_config_req)(&(pnf->_public), &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in correct state: %d\n", __FUNCTION__, pnf->_public.state);
|
|
|
|
nfapi_pnf_config_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_pnf_config_resp(&(pnf->_public), &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
|
|
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_pnf_config_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_CONFIG.request received\n");
|
|
|
|
/// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message
|
|
const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config);
|
|
if (result)
|
|
{
|
|
// ensure correct state
|
|
if(pnf->_public.state != NFAPI_PNF_RUNNING)
|
|
{
|
|
// delete the phy records
|
|
nfapi_pnf_phy_config_delete_all(&pnf->_public);
|
|
|
|
// create the phy records
|
|
if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG)
|
|
{
|
|
int i = 0;
|
|
for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = (nfapi_pnf_phy_config_t*)malloc(sizeof(nfapi_pnf_phy_config_t));
|
|
memset(phy, 0, sizeof(nfapi_pnf_phy_config_t));
|
|
|
|
phy->state = NFAPI_PNF_PHY_IDLE;
|
|
phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id;
|
|
|
|
nfapi_pnf_phy_config_add(&(pnf->_public), phy);
|
|
}
|
|
}
|
|
|
|
if(pnf->_public.pnf_nr_config_req)
|
|
{
|
|
(pnf->_public.pnf_nr_config_req)(&(pnf->_public), &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in correct state: %d\n", __FUNCTION__, pnf->_public.state);
|
|
|
|
nfapi_nr_pnf_config_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_pnf_config_resp(&(pnf->_public), &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_pnf_start_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_START.request Received\n");
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0)
|
|
{
|
|
if(pnf->_public.state == NFAPI_PNF_CONFIGURED)
|
|
{
|
|
if(pnf->_public.pnf_start_req)
|
|
{
|
|
(pnf->_public.pnf_start_req)(&(pnf->_public), &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_pnf_start_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PNF_START_RESPONSE;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_pnf_start_resp(&(pnf->_public), &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_nr_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_pnf_start_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_START.request Received\n");
|
|
|
|
/// The unpack() function pointer is not called here due to the only possibility of entering being on a nFAPI message
|
|
const bool result = nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config);
|
|
if (result)
|
|
{
|
|
if(pnf->_public.state == NFAPI_PNF_CONFIGURED)
|
|
{
|
|
if(pnf->_public.pnf_nr_start_req)
|
|
{
|
|
(pnf->_public.pnf_nr_start_req)(&(pnf->_public), &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_pnf_start_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PNF_START_RESPONSE;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_pnf_start_resp(&(pnf->_public), &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_pnf_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_pnf_stop_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_STOP.request Received\n");
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0)
|
|
{
|
|
if(pnf->_public.state == NFAPI_PNF_RUNNING)
|
|
{
|
|
if(pnf->_public.pnf_stop_req)
|
|
{
|
|
(pnf->_public.pnf_stop_req)(&(pnf->_public), &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_pnf_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PNF_STOP_RESPONSE;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_pnf_stop_resp(&(pnf->_public), &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_param_request_t req;
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PARAM.request received\n");
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state == NFAPI_PNF_PHY_IDLE)
|
|
{
|
|
if(config->param_req)
|
|
{
|
|
(config->param_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_param_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PARAM_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_param_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_param_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PARAM_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_param_resp(config, &resp);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
nfapi_param_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_PARAM_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_param_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void pnf_nr_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_param_request_scf_t req;
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PARAM.request received\n");
|
|
|
|
// unpack the message
|
|
const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config);
|
|
if (result)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state == NFAPI_PNF_PHY_IDLE)
|
|
{
|
|
if(config->nr_param_req)
|
|
{
|
|
(config->nr_param_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_param_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_param_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_param_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_nr_pnf_param_resp(config, &resp);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_param_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_param_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void pnf_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_config_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "CONFIG.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->config_req)
|
|
{
|
|
(config->config_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_config_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CONFIG_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_config_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_config_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CONFIG_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_config_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_config_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CONFIG_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_config_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
|
|
void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_config_request_scf_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "CONFIG.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
// unpack the message
|
|
const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config);
|
|
if (result)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
|
|
if(phy)
|
|
{
|
|
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->nr_config_req)
|
|
{
|
|
(config->nr_config_req)(config, phy, &req);
|
|
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_config_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CONFIG_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_config_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_config_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CONFIG_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_nr_pnf_config_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_config_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CONFIG_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_config_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_start_request_t req;
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() START.request received state:%d\n", __FUNCTION__, config->state);
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->start_req)
|
|
{
|
|
(config->start_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_start_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_START_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_start_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_start_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_START_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_start_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_start_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_START_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_start_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void pnf_nr_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_start_request_scf_t req;
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() START.request received state:%d\n", __FUNCTION__, config->state);
|
|
|
|
// unpack the message
|
|
const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config);
|
|
if (result)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->nr_start_req)
|
|
{
|
|
(config->nr_start_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_start_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_NR_START_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_start_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_start_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_NR_START_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_start_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_start_response_scf_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_NR_START_MSG_INVALID_STATE;
|
|
nfapi_nr_pnf_start_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void pnf_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_stop_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "STOP.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->stop_req)
|
|
{
|
|
(config->stop_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_stop_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_stop_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_stop_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void pnf_nr_handle_stop_request(pnf_t* pnf, void* pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
} else {
|
|
nfapi_nr_stop_request_scf_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "STOP.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
// unpack the message
|
|
const bool result = pnf->_public.unpack_func(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config);
|
|
if (result) {
|
|
if (config->state == NFAPI_PNF_RUNNING) {
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if (phy) {
|
|
if (phy->state != NFAPI_PNF_PHY_RUNNING) {
|
|
if (config->nr_stop_req) {
|
|
(config->nr_stop_req)(config, phy, &req);
|
|
}
|
|
} else {
|
|
nfapi_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_stop_resp(config, &resp);
|
|
}
|
|
} else {
|
|
nfapi_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_stop_resp(config, &resp);
|
|
}
|
|
} else {
|
|
nfapi_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_stop_resp(config, &resp);
|
|
}
|
|
} else {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if (req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_measurement_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_measurement_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "MEASUREMENT.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->measurement_req)
|
|
{
|
|
(config->measurement_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_measurement_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_measurement_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_measurement_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_measurement_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_measurement_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_measurement_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_rssi_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
|
|
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_rssi_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "RSSI.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state == NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->rssi_req)
|
|
{
|
|
(config->rssi_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_rssi_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_RSSI_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_rssi_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_rssi_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_RSSI_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_rssi_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_rssi_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_RSSI_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_rssi_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void pnf_handle_cell_search_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_cell_search_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "CELL_SEARCH.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state == NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->cell_search_req)
|
|
{
|
|
(config->cell_search_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_cell_search_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_cell_search_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_cell_search_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_cell_search_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_cell_search_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_cell_search_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
|
|
}
|
|
|
|
void pnf_handle_broadcast_detect_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_broadcast_detect_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "BROADCAST_DETECT.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state == NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->broadcast_detect_req)
|
|
{
|
|
(config->broadcast_detect_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_broadcast_detect_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_broadcast_detect_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_broadcast_detect_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_broadcast_detect_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_broadcast_detect_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_broadcast_detect_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void pnf_handle_system_information_schedule_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_schedule_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "SYSTEM_INFORMATION_SCHEDULE.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state == NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->system_information_schedule_req)
|
|
{
|
|
(config->system_information_schedule_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_schedule_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_system_information_schedule_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_schedule_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_system_information_schedule_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_schedule_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_system_information_schedule_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void pnf_handle_system_information_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "SYSTEM_INFORMATION.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state == NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->system_information_req)
|
|
{
|
|
(config->system_information_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_system_information_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_system_information_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_system_information_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_system_information_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
|
|
}
|
|
|
|
void pnf_handle_nmm_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nmm_stop_request_t req;
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "NMM_STOP.request received\n");
|
|
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
|
|
{
|
|
if(config->state == NFAPI_PNF_RUNNING)
|
|
{
|
|
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
|
if(phy)
|
|
{
|
|
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
|
{
|
|
if(config->nmm_stop_req)
|
|
{
|
|
(config->nmm_stop_req)(config, phy, &req);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nmm_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_nmm_stop_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nmm_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_CONFIG;
|
|
nfapi_pnf_nmm_stop_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nfapi_nmm_stop_response_t resp;
|
|
memset(&resp, 0, sizeof(resp));
|
|
resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
|
|
resp.header.phy_id = req.header.phy_id;
|
|
resp.error_code = NFAPI_MSG_INVALID_STATE;
|
|
nfapi_pnf_nmm_stop_resp(config, &resp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(req.vendor_extension)
|
|
pnf->_public.codec_config.deallocate(req.vendor_extension);
|
|
}
|
|
}
|
|
|
|
|
|
void pnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, pnf_t* pnf, uint16_t message_id)
|
|
{
|
|
if (pRecvMsg == NULL || pnf == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
nfapi_pnf_config_t* config = &(pnf->_public);
|
|
|
|
if(config->allocate_p4_p5_vendor_ext)
|
|
{
|
|
uint16_t msg_size;
|
|
nfapi_p4_p5_message_header_t* msg = config->allocate_p4_p5_vendor_ext(message_id, &msg_size);
|
|
|
|
if(msg == 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to allocate vendor extention structure\n");
|
|
return;
|
|
}
|
|
|
|
|
|
int unpack_result = nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &config->codec_config);
|
|
|
|
if(unpack_result == 0)
|
|
{
|
|
if(config->vendor_ext)
|
|
config->vendor_ext(config, msg);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
if(config->deallocate_p4_p5_vendor_ext)
|
|
config->deallocate_p4_p5_vendor_ext(msg);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void pnf_nr_handle_p5_message(pnf_t* pnf, void* pRecvMsg, int recvMsgLen)
|
|
{
|
|
nfapi_nr_p4_p5_message_header_t messageHeader;
|
|
|
|
// validate the input params
|
|
if (pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
// unpack the message header
|
|
const bool result = pnf->_public.hdr_unpack_func(pRecvMsg, recvMsgLen, &messageHeader, sizeof(messageHeader), &pnf->_public.codec_config);
|
|
if (!result) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
|
|
return;
|
|
}
|
|
|
|
switch (messageHeader.message_id) {
|
|
case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST:
|
|
pnf_nr_handle_pnf_param_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST:
|
|
pnf_nr_handle_pnf_config_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST:
|
|
pnf_nr_handle_pnf_start_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_PNF_STOP_REQUEST:
|
|
pnf_handle_pnf_stop_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST:
|
|
pnf_nr_handle_param_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST:
|
|
pnf_nr_handle_config_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST:
|
|
pnf_nr_handle_start_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST:
|
|
pnf_nr_handle_stop_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_MEASUREMENT_REQUEST:
|
|
pnf_handle_measurement_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_RSSI_REQUEST:
|
|
pnf_handle_rssi_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_CELL_SEARCH_REQUEST:
|
|
pnf_handle_cell_search_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_BROADCAST_DETECT_REQUEST:
|
|
pnf_handle_broadcast_detect_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST:
|
|
pnf_handle_system_information_schedule_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_REQUEST:
|
|
pnf_handle_system_information_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NMM_STOP_REQUEST:
|
|
pnf_handle_nmm_stop_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
default: {
|
|
if (messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) {
|
|
pnf_handle_vendor_extension(pRecvMsg, recvMsgLen, pnf, messageHeader.message_id);
|
|
} else {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id);
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
|
|
void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
|
{
|
|
nfapi_p4_p5_message_header_t messageHeader;
|
|
|
|
// validate the input params
|
|
if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
// unpack the message header
|
|
if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &pnf->_public.codec_config) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
|
|
return;
|
|
}
|
|
|
|
switch (messageHeader.message_id)
|
|
{
|
|
case NFAPI_PNF_PARAM_REQUEST:
|
|
pnf_handle_pnf_param_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_PNF_CONFIG_REQUEST:
|
|
pnf_handle_pnf_config_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_PNF_START_REQUEST:
|
|
pnf_handle_pnf_start_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_PNF_STOP_REQUEST:
|
|
pnf_handle_pnf_stop_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_PARAM_REQUEST:
|
|
pnf_handle_param_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_CONFIG_REQUEST:
|
|
pnf_handle_config_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_START_REQUEST:
|
|
pnf_handle_start_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_STOP_REQUEST:
|
|
pnf_handle_stop_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_MEASUREMENT_REQUEST:
|
|
pnf_handle_measurement_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_RSSI_REQUEST:
|
|
pnf_handle_rssi_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_CELL_SEARCH_REQUEST:
|
|
pnf_handle_cell_search_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_BROADCAST_DETECT_REQUEST:
|
|
pnf_handle_broadcast_detect_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST:
|
|
pnf_handle_system_information_schedule_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_REQUEST:
|
|
pnf_handle_system_information_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
case NFAPI_NMM_STOP_REQUEST:
|
|
pnf_handle_nmm_stop_request(pnf, pRecvMsg, recvMsgLen);
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
|
|
messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
|
|
{
|
|
pnf_handle_vendor_extension(pRecvMsg, recvMsgLen, pnf, messageHeader.message_id);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len)
|
|
{
|
|
int packed_len = nfapi_p5_message_pack(msg, msg_len,
|
|
pnf->tx_message_buffer,
|
|
sizeof(pnf->tx_message_buffer),
|
|
&pnf->_public.codec_config);
|
|
|
|
if (packed_len < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len);
|
|
return -1;
|
|
}
|
|
|
|
return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/);
|
|
}
|
|
|
|
int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len)
|
|
{
|
|
int packed_len = nfapi_p4_message_pack(msg, msg_len,
|
|
pnf->tx_message_buffer,
|
|
sizeof(pnf->tx_message_buffer),
|
|
&pnf->_public.codec_config);
|
|
|
|
if (packed_len < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p4_message_pack failed (%d)\n", packed_len);
|
|
return -1;
|
|
}
|
|
|
|
return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/);
|
|
}
|
|
|
|
int pnf_connect(pnf_t* pnf)
|
|
{
|
|
struct sockaddr_in servaddr;
|
|
uint8_t socketConnected = 0;
|
|
|
|
if(pnf->_public.vnf_ip_addr == 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnfIpAddress is null\n");
|
|
return -1;
|
|
}
|
|
|
|
|
|
(void)memset(&servaddr, 0, sizeof(struct sockaddr_in));
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 PNF connection to VNF at %s:%u\n", pnf->_public.vnf_ip_addr, pnf->_public.vnf_p5_port);
|
|
|
|
// todo split the vnf address list. currently only supporting 1
|
|
|
|
struct addrinfo hints, *servinfo;
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_socktype = SOCK_STREAM; // For SCTP we are only interested in SOCK_STREAM
|
|
// todo : allow the client to restrict IPV4 or IPV6
|
|
// todo : randomize which address to connect to?
|
|
|
|
char port_str[8];
|
|
snprintf(port_str, sizeof(port_str), "%d", pnf->_public.vnf_p5_port);
|
|
if(getaddrinfo(pnf->_public.vnf_ip_addr, port_str, &hints, &servinfo) != 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to get host (%s) addr info h_errno:%d \n", pnf->_public.vnf_ip_addr, h_errno);
|
|
return -1;
|
|
}
|
|
|
|
struct addrinfo *p = servinfo;
|
|
int connected = 0;
|
|
|
|
while(p != NULL && connected == 0)
|
|
{
|
|
#ifdef NFAPI_TRACE_ENABLED
|
|
char* family = "Unknown";
|
|
char* address = "Unknown";
|
|
char _addr[128];
|
|
|
|
if(p->ai_family == AF_INET6)
|
|
{
|
|
family = "IPV6";
|
|
struct sockaddr_in6* addr = (struct sockaddr_in6*)p->ai_addr;
|
|
inet_ntop(AF_INET6, &addr->sin6_addr, _addr, sizeof(_addr));
|
|
address = &_addr[0];
|
|
}
|
|
else if(p->ai_family == AF_INET)
|
|
{
|
|
family = "IPV4";
|
|
struct sockaddr_in* addr = (struct sockaddr_in*)p->ai_addr;
|
|
address = inet_ntoa(addr->sin_addr);
|
|
}
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_NOTE, "Host address info %d Family:%s Address:%s\n", i++, family, address);
|
|
#endif
|
|
|
|
if (pnf->sctp)
|
|
{
|
|
// open the SCTP socket
|
|
if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_SCTP)) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
|
|
freeaddrinfo(servinfo);
|
|
return -1;
|
|
}
|
|
int noDelay;
|
|
struct sctp_initmsg initMsg;
|
|
|
|
(void)memset(&initMsg, 0, sizeof(struct sctp_initmsg));
|
|
|
|
// configure the socket options
|
|
NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF Setting the SCTP_INITMSG\n");
|
|
initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater
|
|
initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater
|
|
if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
|
|
freeaddrinfo(servinfo);
|
|
return -1;
|
|
}
|
|
noDelay = 1;
|
|
if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
|
|
freeaddrinfo(servinfo);
|
|
return -1;
|
|
|
|
}
|
|
|
|
struct sctp_event_subscribe events;
|
|
memset( (void *)&events, 0, sizeof(events) );
|
|
events.sctp_data_io_event = 1;
|
|
|
|
if(setsockopt(pnf->p5_sock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
|
|
freeaddrinfo(servinfo);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Create an IP socket point
|
|
if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_IP)) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
|
|
freeaddrinfo(servinfo);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created...\n");
|
|
|
|
if (connect(pnf->p5_sock, p->ai_addr, p->ai_addrlen ) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After connect (address:%s port:%d) errno: %d\n",
|
|
pnf->_public.vnf_ip_addr, pnf->_public.vnf_p5_port, errno);
|
|
|
|
if(errno == EINVAL)
|
|
{
|
|
freeaddrinfo(servinfo);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
if(pnf->terminate != 0)
|
|
{
|
|
freeaddrinfo(servinfo);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
close(pnf->p5_sock);
|
|
sleep(1);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "connect succeeded...\n");
|
|
|
|
connected = 1;
|
|
}
|
|
|
|
p = p->ai_next;
|
|
}
|
|
|
|
freeaddrinfo(servinfo);
|
|
|
|
// If we have failed to connect return 0 and it is retry
|
|
if(connected == 0)
|
|
return 0;
|
|
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_NOTE, "After connect loop\n");
|
|
if (pnf->sctp)
|
|
{
|
|
socklen_t optLen;
|
|
struct sctp_status status;
|
|
|
|
(void)memset(&status, 0, sizeof(struct sctp_status));
|
|
|
|
// check the connection status
|
|
optLen = (socklen_t) sizeof(struct sctp_status);
|
|
if (getsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Association ID = %d\n", status.sstat_assoc_id);
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Receiver window size = %d\n", status.sstat_rwnd);
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "In Streams = %d\n", status.sstat_instrms);
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Out Streams = %d\n", status.sstat_outstrms);
|
|
|
|
socketConnected = 1;
|
|
}
|
|
} else {
|
|
int error;
|
|
socklen_t len = sizeof(error);
|
|
|
|
if (getsockopt(pnf->p5_sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno);
|
|
return -1;
|
|
} else {
|
|
// If error is zero, the socket is connected
|
|
if (error == 0) {
|
|
socketConnected = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_NOTE, "Socket %s\n", socketConnected ? "CONNECTED" : "NOT_CONNECTED");
|
|
return socketConnected;
|
|
}
|
|
|
|
int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream)
|
|
{
|
|
|
|
if (pnf->sctp)
|
|
{
|
|
#if 0
|
|
printf("\nPNF SENDS: \n");
|
|
for(int i=0; i<len; i++){
|
|
printf("%d", msg[i]);
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
|
|
if (sctp_sendmsg(pnf->p5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (write(pnf->p5_sock, msg, len) != len)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "read failed errno: %d\n", errno);
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int pnf_read_dispatch_message(pnf_t* pnf)
|
|
{
|
|
int socket_connected = 1;
|
|
|
|
// 1. Peek the message header
|
|
// 2. If the message is larger than the stack buffer then create a dynamic buffer
|
|
// 3. Read the buffer
|
|
// 4. Handle the p5 message
|
|
|
|
uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
|
|
uint8_t header_buffer[header_buffer_size];
|
|
|
|
uint32_t stack_buffer_size = 32; //should it be the size of then sctp_notificatoin structure
|
|
uint8_t stack_buffer[stack_buffer_size];
|
|
|
|
uint8_t* dynamic_buffer = 0;
|
|
|
|
uint8_t* read_buffer = &stack_buffer[0];
|
|
uint32_t message_size = 0;
|
|
|
|
struct sockaddr_in addr;
|
|
socklen_t addr_len = sizeof(addr);
|
|
|
|
struct sctp_sndrcvinfo sndrcvinfo;
|
|
(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
|
|
|
{
|
|
int flags = MSG_PEEK;
|
|
message_size = sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, /*(struct sockaddr*)&addr, &addr_len*/ 0, 0, &sndrcvinfo, &flags);
|
|
|
|
if(message_size == -1)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno);
|
|
return 0;
|
|
}
|
|
|
|
nfapi_p4_p5_message_header_t header;
|
|
int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0);
|
|
if(unpack_result < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n");
|
|
return 0;
|
|
}else{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Unpack p5 message header success\n");
|
|
}
|
|
message_size = header.message_length+header_buffer_size;
|
|
|
|
// now have the size of the mesage
|
|
}
|
|
|
|
if(message_size > stack_buffer_size)
|
|
{
|
|
dynamic_buffer = (uint8_t*)malloc(message_size);
|
|
|
|
if(dynamic_buffer == NULL)
|
|
{
|
|
// todo : add error mesage
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size);
|
|
return -1;
|
|
}
|
|
|
|
read_buffer = dynamic_buffer;
|
|
}
|
|
|
|
{
|
|
int flags = 0;
|
|
(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
|
|
|
int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags);
|
|
if(recvmsg_result == -1)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno);
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
// print the received message
|
|
printf("\n MESSAGE RECEIVED: \n");
|
|
for(int i=0; i<message_size; i++){
|
|
printf("%d", read_buffer[i]);
|
|
}
|
|
printf("\n");
|
|
#endif
|
|
|
|
if (flags & MSG_NOTIFICATION)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
|
|
|
// todo - handle the events
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n",
|
|
pnf->p5_sock,
|
|
inet_ntoa(addr.sin_addr),
|
|
ntohs(addr.sin_port),
|
|
sndrcvinfo.sinfo_assoc_id,
|
|
sndrcvinfo.sinfo_stream,
|
|
ntohl(sndrcvinfo.sinfo_ppid),
|
|
message_size,
|
|
flags);
|
|
*/
|
|
|
|
// handle now if complete message in one or more segments
|
|
if ((flags & 0x80) == 0x80)
|
|
{
|
|
pnf_handle_p5_message(pnf, read_buffer, message_size);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags);
|
|
|
|
// assume socket disconnected
|
|
NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n");
|
|
socket_connected = 0;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dynamic_buffer)
|
|
{
|
|
free(dynamic_buffer);
|
|
}
|
|
|
|
return socket_connected;
|
|
|
|
|
|
}
|
|
|
|
int pnf_message_pump(pnf_t* pnf)
|
|
{
|
|
uint8_t socketConnected = 1;
|
|
|
|
while(socketConnected && pnf->terminate == 0)
|
|
{
|
|
fd_set rfds;
|
|
int selectRetval = 0;
|
|
|
|
// select on a timeout and then get the message
|
|
FD_ZERO(&rfds);
|
|
FD_SET(pnf->p5_sock, &rfds);
|
|
|
|
struct timeval timeout;
|
|
timeout.tv_sec = 1;
|
|
timeout.tv_usec = 0;
|
|
|
|
selectRetval = select(pnf->p5_sock+1, &rfds, NULL, NULL, &timeout);
|
|
|
|
if(selectRetval == 0)
|
|
{
|
|
// timeout
|
|
continue;
|
|
}
|
|
else if (selectRetval == -1 && (errno == EINTR))
|
|
{
|
|
// interrupted by signal
|
|
NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno);
|
|
continue;
|
|
}
|
|
else if (selectRetval == -1)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n");
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
|
|
if(FD_ISSET(pnf->p5_sock, &rfds))
|
|
{
|
|
socketConnected = pnf_read_dispatch_message(pnf);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n");
|
|
}
|
|
}
|
|
|
|
// Drop back to idle if we have lost connection
|
|
pnf->_public.state = NFAPI_PNF_IDLE;
|
|
|
|
|
|
// close the connection and socket
|
|
if (close(pnf->p5_sock) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno);
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|