1126 lines
30 KiB
C
1126 lines
30 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 <netinet/in.h>
|
|
#include <netinet/sctp.h>
|
|
#include <arpa/inet.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "vnf.h"
|
|
|
|
|
|
void* vnf_malloc(nfapi_vnf_config_t* config, size_t size)
|
|
{
|
|
if(config->malloc)
|
|
{
|
|
return (config->malloc)(size);
|
|
}
|
|
else
|
|
{
|
|
return calloc(1, size);
|
|
}
|
|
}
|
|
void vnf_free(nfapi_vnf_config_t* config, void* ptr)
|
|
{
|
|
if(config->free)
|
|
{
|
|
return (config->free)(ptr);
|
|
}
|
|
else
|
|
{
|
|
return free(ptr);
|
|
}
|
|
}
|
|
|
|
void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Adding phy p5_idx:%d phy_id:%d\n", info->p5_idx, info->phy_id);
|
|
info->next = config->phy_list;
|
|
config->phy_list = info;
|
|
}
|
|
|
|
nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id)
|
|
{
|
|
nfapi_vnf_phy_info_t* curr = config->phy_list;
|
|
while(curr != 0)
|
|
{
|
|
if(curr->phy_id == phy_id)
|
|
return curr;
|
|
|
|
curr = curr->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
void nfapi_vnf_pnf_list_add(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* node)
|
|
{
|
|
node->next = config->pnf_list;
|
|
config->pnf_list = node;
|
|
}
|
|
|
|
|
|
nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : config->pnf_list:%p\n", __FUNCTION__, config->pnf_list);
|
|
|
|
nfapi_vnf_pnf_info_t* curr = config->pnf_list;
|
|
while(curr != 0)
|
|
{
|
|
if(curr->p5_idx == p5_idx)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : curr->p5_idx:%d p5_idx:%d\n", __FUNCTION__, curr->p5_idx, p5_idx);
|
|
return curr;
|
|
}
|
|
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : curr->next:%p\n", __FUNCTION__, curr->next);
|
|
|
|
curr = curr->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_PARAM.reponse\n");
|
|
|
|
nfapi_pnf_param_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
// Invoke the call back
|
|
if(config->pnf_param_resp)
|
|
{
|
|
(config->pnf_param_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_CONFIG_RESPONSE\n");
|
|
|
|
nfapi_pnf_config_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
// Invoke the call back
|
|
if(config->pnf_config_resp)
|
|
{
|
|
(config->pnf_config_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_START_RESPONSE\n");
|
|
|
|
nfapi_pnf_start_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->pnf_start_resp)
|
|
{
|
|
(config->pnf_start_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_pnf_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_STOP_RESPONSE\n");
|
|
|
|
nfapi_pnf_stop_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->pnf_stop_resp)
|
|
{
|
|
(config->pnf_stop_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
|
|
}
|
|
}
|
|
|
|
void vnf_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PARAM_RESPONSE\n");
|
|
|
|
nfapi_param_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
|
|
if (msg.error_code == NFAPI_MSG_OK)
|
|
{
|
|
nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id);
|
|
|
|
if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag)
|
|
{
|
|
struct sockaddr_in sockAddr;
|
|
|
|
(void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH);
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr));
|
|
|
|
// store address
|
|
phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr;
|
|
}
|
|
|
|
if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag)
|
|
{
|
|
struct sockaddr_in6 sockAddr6;
|
|
char addr6[64];
|
|
(void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH);
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6)));
|
|
}
|
|
|
|
if (msg.nfapi_config.p7_pnf_port.tl.tag)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value);
|
|
|
|
// store port
|
|
phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value);
|
|
}
|
|
}
|
|
|
|
if(config->param_resp)
|
|
{
|
|
(config->param_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CONFIG_RESPONSE\n");
|
|
|
|
nfapi_config_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 )
|
|
{
|
|
if(config->config_resp)
|
|
{
|
|
(config->config_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received START_RESPONSE\n");
|
|
|
|
nfapi_start_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->start_resp)
|
|
{
|
|
(config->start_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received STOP.response\n");
|
|
|
|
nfapi_stop_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->stop_resp)
|
|
{
|
|
(config->stop_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_measurement_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received MEASUREMENT.response\n");
|
|
|
|
nfapi_measurement_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->measurement_resp)
|
|
{
|
|
(config->measurement_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_rssi_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received RSSI.response\n");
|
|
|
|
nfapi_rssi_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->rssi_resp)
|
|
{
|
|
(config->rssi_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_rssi_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received RSSI.indication\n");
|
|
|
|
nfapi_rssi_indication_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->rssi_ind)
|
|
{
|
|
(config->rssi_ind)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_cell_search_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CELL_SEARCH.response\n");
|
|
|
|
nfapi_cell_search_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->cell_search_resp)
|
|
{
|
|
(config->cell_search_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_cell_search_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_cell_search_indication: NULL parameters\n");
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CELL_SEARCH.indication\n");
|
|
|
|
nfapi_cell_search_indication_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->cell_search_ind)
|
|
{
|
|
(config->cell_search_ind)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_cell_search_response: Unpack message failed, ignoring\n");
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_broadcast_detect_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received BROADCAST_DETECT.response\n");
|
|
|
|
nfapi_broadcast_detect_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->broadcast_detect_resp)
|
|
{
|
|
(config->broadcast_detect_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_broadcast_detect_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received BROADCAST_DETECT.indication\n");
|
|
|
|
nfapi_broadcast_detect_indication_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->broadcast_detect_ind)
|
|
{
|
|
(config->broadcast_detect_ind)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_system_information_schedule_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION_SCHEDULE.response\n");
|
|
|
|
nfapi_system_information_schedule_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->system_information_schedule_resp)
|
|
{
|
|
(config->system_information_schedule_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_system_information_schedule_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION_SCHEDULE.indication\n");
|
|
|
|
nfapi_system_information_schedule_indication_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->system_information_schedule_ind)
|
|
{
|
|
(config->system_information_schedule_ind)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_system_information_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION.response\n");
|
|
|
|
nfapi_system_information_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
|
|
{
|
|
if(config->system_information_resp)
|
|
{
|
|
(config->system_information_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_system_information_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION.indication\n");
|
|
|
|
nfapi_system_information_indication_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
if(config->system_information_ind)
|
|
{
|
|
(config->system_information_ind)(config, p5_idx, &msg);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
}
|
|
|
|
void vnf_handle_nmm_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
|
|
{
|
|
// ensure it's valid
|
|
if (pRecvMsg == NULL || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received NMM_STOP.response\n");
|
|
|
|
nfapi_nmm_stop_response_t msg;
|
|
|
|
// unpack the message
|
|
if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(nfapi_nmm_stop_response_t), &config->codec_config) >= 0)
|
|
{
|
|
if(config->nmm_stop_resp)
|
|
{
|
|
(config->nmm_stop_resp)(config, p5_idx, &msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
// make sure to release any dyanmic part of the message
|
|
if(msg.vendor_extension)
|
|
config->codec_config.deallocate(msg.vendor_extension);
|
|
}
|
|
|
|
}
|
|
|
|
void vnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx, uint16_t message_id)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
|
|
|
|
if(config->allocate_p4_p5_vendor_ext && config->deallocate_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)
|
|
{
|
|
if(nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &config->codec_config) >= 0)
|
|
{
|
|
if(config->vendor_ext)
|
|
config->vendor_ext(config, p5_idx, msg);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
|
|
}
|
|
|
|
config->deallocate_p4_p5_vendor_ext(msg);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config)
|
|
{
|
|
nfapi_p4_p5_message_header_t messageHeader;
|
|
|
|
// validate the input params
|
|
if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH || config == NULL)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p4_p5_message: invalid input params\n");
|
|
return;
|
|
}
|
|
|
|
// unpack the message header
|
|
if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &config->codec_config) < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
|
|
return;
|
|
}
|
|
|
|
switch (messageHeader.message_id)
|
|
{
|
|
case NFAPI_PNF_PARAM_RESPONSE:
|
|
vnf_handle_pnf_param_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_PNF_CONFIG_RESPONSE:
|
|
vnf_handle_pnf_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_PNF_START_RESPONSE:
|
|
vnf_handle_pnf_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_PNF_STOP_RESPONSE:
|
|
vnf_handle_pnf_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_PARAM_RESPONSE:
|
|
vnf_handle_param_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_CONFIG_RESPONSE:
|
|
vnf_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_START_RESPONSE:
|
|
vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_STOP_RESPONSE:
|
|
vnf_handle_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_MEASUREMENT_RESPONSE:
|
|
vnf_handle_measurement_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_RSSI_RESPONSE:
|
|
vnf_handle_rssi_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_RSSI_INDICATION:
|
|
vnf_handle_rssi_indication(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_CELL_SEARCH_RESPONSE:
|
|
vnf_handle_cell_search_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_CELL_SEARCH_INDICATION:
|
|
vnf_handle_cell_search_indication(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_BROADCAST_DETECT_RESPONSE:
|
|
vnf_handle_broadcast_detect_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_BROADCAST_DETECT_INDICATION:
|
|
vnf_handle_broadcast_detect_indication(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE:
|
|
vnf_handle_system_information_schedule_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION:
|
|
vnf_handle_system_information_schedule_indication(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_RESPONSE:
|
|
vnf_handle_system_information_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_SYSTEM_INFORMATION_INDICATION:
|
|
vnf_handle_system_information_indication(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
case NFAPI_NMM_STOP_RESPONSE:
|
|
vnf_handle_nmm_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
|
|
messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
|
|
{
|
|
vnf_handle_vendor_extension(pRecvMsg, recvMsgLen, config, p5_idx, messageHeader.message_id);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf)
|
|
{
|
|
if(1)
|
|
{
|
|
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];
|
|
memset(header_buffer, 0, 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;
|
|
memset(&addr, 0, sizeof(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, &sndrcvinfo, &flags);
|
|
|
|
if(message_size == -1)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF 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, "VNF Failed to decode message header %d\n", unpack_result);
|
|
return 0;
|
|
}
|
|
message_size = header.message_length;
|
|
|
|
// 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, "VNF 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 (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)
|
|
{
|
|
vnf_handle_p4_p5_message(read_buffer, message_size, pnf->p5_idx, config);
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, uint8_t stream)
|
|
{
|
|
//NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s len:%d stream:%d\n", __FUNCTION__, len, stream);
|
|
|
|
int result = sctp_sendmsg(pnf->p5_sock, msg, len, (struct sockaddr*)&pnf->p5_pnf_sockaddr, sizeof(pnf->p5_pnf_sockaddr),1, 0, stream, 0, 4);
|
|
|
|
if(result != len)
|
|
{
|
|
if(result < 0)
|
|
{
|
|
// error
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp sendto failed errno: %d\n", errno);
|
|
}
|
|
else
|
|
{
|
|
// did not send all the message
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len)
|
|
{
|
|
nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx);
|
|
|
|
if(pnf)
|
|
{
|
|
// pack the message for transmission
|
|
int packedMessageLength = nfapi_p5_message_pack(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config);
|
|
|
|
if (packedMessageLength < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed with return %d\n", packedMessageLength);
|
|
return -1;
|
|
}
|
|
|
|
return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len)
|
|
{
|
|
nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx);
|
|
|
|
if(pnf)
|
|
{
|
|
// pack the message for transmission
|
|
int packedMessageLength = nfapi_p4_message_pack(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config);
|
|
|
|
if (packedMessageLength < 0)
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p4_message_pack failed with return %d\n", packedMessageLength);
|
|
return -1;
|
|
}
|
|
|
|
return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/);
|
|
}
|
|
else
|
|
{
|
|
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx);
|
|
return -1;
|
|
}
|
|
}
|
|
|