Fix NFAPI integration
This commit fixes issues introduced by the previous commit.
Summary of work:
- cleanup:
- fix LOG_XX to be less verbose
- fix cmake_targets/CMakeLists.txt
- fix oaienv
- remove dead code
- bug fixes:
- in openair1/SCHED/fapi_l1.c we had:
eNB->pdcch_vars[subframe&1].num_dci = number_dci;
should be:
eNB->pdcch_vars[subframe&1].num_dci = 0;
This bug let the PHY send more DCIs than what should have been
sent because num_dci is incremented later on in the code.
This fix may be a problem for fapi mode, to be checked.
- add new T VCD traces
- revert openair1/PHY/TOOLS/file_output.c to 'develop' version
- remove thread_id in logRecord/logRecord_mt
- revert (and adapt) configuration files
- be careful when doing frame++, we need to % 1024
- revert target_rx_power in openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
- NFAPI:
- the open-nFAPI code has been included in the repository. See nfapi/README.
Maybe we should "git clone" the Cisco repository instead. We have to be
careful of availability though.
What has been tested:
- monolithic eNB FDD 5/10MHz with one UE, iperf UDP/TCP uplink/downlink
Anything else may fail to work, especially the FAPI mode, which has not
been tested at all.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
|
||||
AUTOMAKE_OPTIONS=subdir-objects
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/vnf/inc\
|
||||
-I$(top_srcdir)/vnf/public_inc\
|
||||
-I$(top_srcdir)/nfapi/public_inc\
|
||||
-I$(top_srcdir)/common/public_inc\
|
||||
-Wall -Werror -g
|
||||
|
||||
|
||||
noinst_LIBRARIES = libnfapi_vnf.a
|
||||
|
||||
libnfapi_vnf_a_SOURCES = src/vnf.c\
|
||||
src/vnf_p7.c\
|
||||
src/vnf_interface.c\
|
||||
src/vnf_p7_interface.c
|
||||
|
||||
LDADD = -lsctp ../common/bin/libnfapi_common.a
|
||||
|
||||
libnfapi_vnf_a_CFLAGS =$(AM_CFLAGS)
|
||||
|
||||
lib_LTLIBRARIES = libnfapi_vnf.la
|
||||
|
||||
libnfapi_vnf_la_SOURCES = src/vnf.c\
|
||||
src/vnf_p7.c\
|
||||
src/vnf_interface.c\
|
||||
src/vnf_p7_interface.c
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _VNF_H_
|
||||
#define _VNF_H_
|
||||
|
||||
#include "nfapi_vnf_interface.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
nfapi_vnf_config_t _public;
|
||||
|
||||
uint8_t terminate;
|
||||
uint8_t sctp;
|
||||
|
||||
uint8_t tx_message_buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE];
|
||||
uint16_t next_phy_id;
|
||||
|
||||
} vnf_t;
|
||||
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf);
|
||||
|
||||
void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info);
|
||||
nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id);
|
||||
void nfapi_vnf_pnf_list_add(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* node);
|
||||
nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5_idx);
|
||||
#endif // _VNF_H_
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _VNF_P7_H_
|
||||
#define _VNF_P7_H_
|
||||
|
||||
#include "nfapi_vnf_interface.h"
|
||||
|
||||
#define TIMEHR_SEC(_time_hr) ((uint32_t)(_time_hr) >> 20)
|
||||
#define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF)
|
||||
#define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF))
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t* buffer;
|
||||
uint16_t length;
|
||||
} vnf_p7_rx_message_segment_t;
|
||||
|
||||
typedef struct vnf_p7_rx_message vnf_p7_rx_message_t;
|
||||
|
||||
typedef struct vnf_p7_rx_message {
|
||||
uint8_t sequence_number;
|
||||
uint8_t num_segments_received;
|
||||
uint8_t num_segments_expected;
|
||||
|
||||
// the spec allows of upto 128 segments, this does seem excessive
|
||||
vnf_p7_rx_message_segment_t segments[128];
|
||||
|
||||
uint32_t rx_hr_time;
|
||||
|
||||
vnf_p7_rx_message_t* next;
|
||||
} vnf_p7_rx_message_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
vnf_p7_rx_message_t* msg_queue;
|
||||
|
||||
} vnf_p7_rx_reassembly_queue_t;
|
||||
|
||||
typedef struct nfapi_vnf_p7_connection_info {
|
||||
|
||||
/*! The PHY id */
|
||||
int phy_id;
|
||||
|
||||
|
||||
// this does not belong here...
|
||||
uint8_t stream_id;
|
||||
|
||||
/*! Flag indicating the sync state of the P7 conenction */
|
||||
uint8_t in_sync;
|
||||
|
||||
int dl_out_sync_offset;
|
||||
int dl_out_sync_period; // ms (as a pow2)
|
||||
|
||||
int dl_in_sync_offset;
|
||||
int dl_in_sync_period; // ms (as a pow2)
|
||||
|
||||
uint8_t filtered_adjust;
|
||||
uint16_t min_sync_cycle_count;
|
||||
uint32_t latency[8];
|
||||
uint32_t average_latency;
|
||||
int32_t sf_offset_filtered;
|
||||
int32_t sf_offset_trend;
|
||||
int32_t sf_offset;
|
||||
uint16_t zero_count;
|
||||
int32_t adjustment;
|
||||
int32_t insync_minor_adjustment;
|
||||
int32_t insync_minor_adjustment_duration;
|
||||
|
||||
uint32_t previous_t1;
|
||||
uint32_t previous_t2;
|
||||
int32_t previous_sf_offset_filtered;
|
||||
|
||||
int sfn_sf;
|
||||
|
||||
int socket;
|
||||
struct sockaddr_in local_addr;
|
||||
struct sockaddr_in remote_addr;
|
||||
|
||||
vnf_p7_rx_reassembly_queue_t reassembly_queue;
|
||||
uint8_t* reassembly_buffer;
|
||||
uint32_t reassembly_buffer_size;
|
||||
|
||||
uint32_t sequence_number;
|
||||
|
||||
struct nfapi_vnf_p7_connection_info* next;
|
||||
|
||||
} nfapi_vnf_p7_connection_info_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
nfapi_vnf_p7_config_t _public;
|
||||
|
||||
// private data
|
||||
uint8_t terminate;
|
||||
nfapi_vnf_p7_connection_info_t* p7_connections;
|
||||
int socket;
|
||||
uint32_t sf_start_time_hr;
|
||||
uint8_t* rx_message_buffer; // would this be better put in the p7 conenction info?
|
||||
uint16_t rx_message_buffer_size;
|
||||
|
||||
} vnf_p7_t;
|
||||
|
||||
uint32_t vnf_get_current_time_hr(void);
|
||||
|
||||
uint16_t increment_sfn_sf(uint16_t sfn_sf);
|
||||
int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info);
|
||||
int send_mac_subframe_indications(vnf_p7_t* config);
|
||||
int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7 );
|
||||
|
||||
void vnf_p7_connection_info_list_add(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* node);
|
||||
nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p7, uint16_t phy_id);
|
||||
nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id);
|
||||
|
||||
int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header);
|
||||
|
||||
void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header);
|
||||
void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu);
|
||||
|
||||
|
||||
#endif // _VNF_P7_H_
|
||||
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _NFAPI_VNF_INTERFACE_H_
|
||||
#define _NFAPI_VNF_INTERFACE_H_
|
||||
|
||||
#include "nfapi_interface.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "netinet/in.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192
|
||||
|
||||
/*! The nfapi VNF phy configuration information
|
||||
*/
|
||||
typedef struct nfapi_vnf_phy_info
|
||||
{
|
||||
/*! The P5 Index */
|
||||
int p5_idx; //which p5 connection
|
||||
/*! The PHY ID */
|
||||
int phy_id; //phy_id
|
||||
|
||||
/*! Timing window */
|
||||
uint8_t timing_window;
|
||||
/*! Timing info mode */
|
||||
uint8_t timing_info_mode;
|
||||
/*! Timing info period */
|
||||
uint8_t timing_info_period;
|
||||
|
||||
/*! P7 UDP socket information for the pnf */
|
||||
struct sockaddr_in p7_pnf_address;
|
||||
/*! P7 UDP socket information for the vnf */
|
||||
struct sockaddr_in p7_vnf_address;
|
||||
|
||||
struct nfapi_vnf_phy_info* next;
|
||||
} nfapi_vnf_phy_info_t;
|
||||
|
||||
/*! The nfapi VNF pnf configuration information
|
||||
*/
|
||||
typedef struct nfapi_vnf_pnf_info
|
||||
{
|
||||
/*! The P5 Index */
|
||||
int p5_idx;
|
||||
/*! The P5 socket */
|
||||
int p5_sock;
|
||||
/*! Flag indicating if the pnf is connected */
|
||||
uint8_t connected;
|
||||
|
||||
/*! P5 SCTP socket information for the pnf */
|
||||
struct sockaddr_in p5_pnf_sockaddr;
|
||||
|
||||
/*! Flag indicating if this pnf should be deleted */
|
||||
uint8_t to_delete;
|
||||
|
||||
struct nfapi_vnf_pnf_info* next;
|
||||
|
||||
} nfapi_vnf_pnf_info_t;
|
||||
|
||||
typedef struct nfapi_vnf_config nfapi_vnf_config_t;
|
||||
|
||||
/*! The nfapi VNF configuration information
|
||||
*/
|
||||
typedef struct nfapi_vnf_config
|
||||
{
|
||||
/*! A user define callback to override the default memory allocation */
|
||||
void* (*malloc)(size_t size);
|
||||
/*! A user define callback to override the default memory deallocation */
|
||||
void (*free)(void*);
|
||||
/*! A user define callback to handle trace from the pnf */
|
||||
void (*trace)(nfapi_trace_level_t level, const char* message, ...);
|
||||
|
||||
/*! The port the VNF P5 SCTP connection listens on
|
||||
*
|
||||
* By default this will be set to 7701. However this can be changed if
|
||||
* required.
|
||||
*/
|
||||
int vnf_p5_port;
|
||||
|
||||
// todo : for enabling ipv4/ipv6
|
||||
int vnf_ipv4;
|
||||
int vnf_ipv6;
|
||||
|
||||
/*! List of connected pnfs */
|
||||
nfapi_vnf_pnf_info_t* pnf_list;
|
||||
|
||||
/*! List of configured phys */
|
||||
nfapi_vnf_phy_info_t* phy_list;
|
||||
|
||||
/*! Configuration options for the p4 p5 pack unpack functions */
|
||||
nfapi_p4_p5_codec_config_t codec_config;
|
||||
|
||||
/*! Optional user defined data that will be avaliable in the callbacks*/
|
||||
void* user_data;
|
||||
|
||||
/*! \brief Callback indicating that a pnf has established connection
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 used to indicate this pnf p5 connection
|
||||
*
|
||||
* The client is expected to send the PNF_PARAM.request in response to
|
||||
* the connection indication
|
||||
*
|
||||
* \todo Do we need to send the address information of the PNF?
|
||||
*/
|
||||
int (*pnf_connection_indication)(nfapi_vnf_config_t* config, int p5_idx);
|
||||
|
||||
/*! \brief Callback indicating that a pnf has lost connection
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 used to indicate this pnf p5 connection
|
||||
*
|
||||
* The p5_idx may be used for future new p5 connections
|
||||
*
|
||||
* The client is responsiable for communicating to the p7 instance(s) that
|
||||
* may be associated with this p5 that they should be deleted using the
|
||||
* nfapi_vnf_p7_del_pnf functon
|
||||
*
|
||||
*/
|
||||
int (*pnf_disconnect_indication)(nfapi_vnf_config_t* config, int p5_idx);
|
||||
|
||||
// p5 interface functions
|
||||
|
||||
/*! \brief A callback to handle the PNF_PARAM.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded PNF_PARAM.response. This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The PNF_PARAM.resp contains the capability of the PNF identified by the
|
||||
* p5_idx.
|
||||
*
|
||||
* The client is expected to send the PNF_CONFIG.request after receiving the
|
||||
* PNF_PARAM.resp. This can be done in the call back.
|
||||
*
|
||||
* It is expected that the client when building the PNF_CONFIG.request will
|
||||
* used the nfapi_vnf_allocate_phy() to allocate unique phy id for each FAPI
|
||||
* instance the client wishes to create.
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*pnf_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_response_t* resp);
|
||||
|
||||
/*! A callback for the PNF_CONFIG.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded PNF_CONFIG.response. This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The PNF_CONFIG.resp contains the result of the PNF_CONFIG.request for the
|
||||
* PNF identified by the p5_idx.
|
||||
*
|
||||
* The client is expected to send the PNF_START.request after receiving the
|
||||
* PNF_PARAM.resp. This can be done in the call back.
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*pnf_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_response_t* resp);
|
||||
|
||||
/*! A callback for the PNF_START.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded PNF_START.response. This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The PNF_START.resp contains the result of the PNF_START.request for the
|
||||
* PNF identified by the p5_idx.
|
||||
*
|
||||
* The client is expected to send the PARAM.request for each FAPI instance
|
||||
* that has been created in the PNF.
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*pnf_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp);
|
||||
|
||||
/*! A callback for the PNF_STOP.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded PNF_STOP.response. This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The PNF_STOP.response contains the result of the PNF_STOP.request for the
|
||||
* PNF identified by the p5_idx.
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*pnf_stop_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_response_t* resp);
|
||||
|
||||
/*! A callback for the PARAM.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded PARAM.resposne. This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The PARAM.request contains the capabilities of the FAPI instance identified
|
||||
* by the phy_id
|
||||
*
|
||||
* The client is expected to send the CONFIG.request after receiving the
|
||||
* PARAM.response. This can be done in the call back. The PARAM.response
|
||||
* contains the PNF P7 address (ipv4 or ipv6) and port. This information
|
||||
* is used when calling the nfapi_vnf_p7_add_pnf()
|
||||
*
|
||||
* The client is responsible for identifing the VNF P7 ip address
|
||||
* (ipv4 or ipv6) and port for the VNF P7 entity which will be sent to the
|
||||
* PNF P7 entity. That endpoint should be valid before send the
|
||||
* CONFIG.request.
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_response_t* resp);
|
||||
|
||||
/*! A callback for the CONFIG.response
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded CONFIG.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The CONFIG.response contains the result of the CONFIG.request
|
||||
*
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_response_t* resp);
|
||||
|
||||
/*! A callback for the START.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded START.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The START.response contains the result of the START.request
|
||||
*
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* resp);
|
||||
|
||||
/*! A callback for the STOP.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded STOP.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The STOP.response contains the result of the STOP.request
|
||||
*
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*stop_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_response_t* resp);
|
||||
|
||||
/*! A callback for the MEASUREMENT.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded MEASUREMENT.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The MEASUREMENT.response contains the result of the MEASUREMENT.request
|
||||
*
|
||||
* The resp may contain pointers to dyanmically allocated sub structures
|
||||
* such as the vendor_extention. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*measurement_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_response_t* resp);
|
||||
|
||||
// p4 interface functions
|
||||
/*! A callback for the RSSI.resp
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded RSSI.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*rssi_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_response_t* resp);
|
||||
|
||||
/*! A callback for the RSSI.indication
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded RSSI.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*rssi_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_indication_t* ind);
|
||||
|
||||
/*! A callback for the CELL_SEARCH.response
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded CELL_SEARCH.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*cell_search_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_response_t* resp);
|
||||
|
||||
/*! A callback for the CELL_SEARCH.indication
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded CELL_SEARCH.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*cell_search_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_indication_t* ind);
|
||||
|
||||
/*! A callback for the BROADCAST_DETECT.response
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded BROADCAST_DETECT.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used. */
|
||||
int (*broadcast_detect_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_response_t* resp);
|
||||
|
||||
/*! A callback for the BROADCAST_DETECT.indication
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded BROADCAST_DETECT.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*broadcast_detect_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_indication_t* ind);
|
||||
|
||||
/*! A callback for the SYSTEM_INFORMATION_SCHEUDLE.response
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded SYSTEM_INFORMATION_SCHEUDLE.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*system_information_schedule_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_response_t* resp);
|
||||
|
||||
/*! A callback for the SYSTEM_INFORMATION_SCHEUDLE.indication
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded SYSTEM_INFORMATION_SCHEUDLE.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*system_information_schedule_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_indication_t* ind);
|
||||
|
||||
/*! A callback for the SYSTEM_INFORMATION.response
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded SYSTEM_INFORMATION.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*system_information_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_response_t* resp);
|
||||
|
||||
/*! A callback for the SYSTEM_INFORMATION.indication
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded SYSTEM_INFORMATION.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*system_information_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_indication_t* ind);
|
||||
|
||||
/*! A callback for the NMM_STOP.response
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded NMM_STOP.response This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*nmm_stop_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nmm_stop_response_t* resp);
|
||||
|
||||
|
||||
/*! A callback for any vendor extension message received
|
||||
* \param config A pointer to the vnf configuration
|
||||
* \param p5_idx The p5 index used to indicate a particular pnf p5 connection
|
||||
* \param resp A data structure for the decoded vendor extention message
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*vendor_ext)(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg);
|
||||
|
||||
/*! A callback to allocate vendor extension messages
|
||||
* \param message_id The message is taken from the message header
|
||||
* \param msg_size The is the vendor extention message that has been allocated.
|
||||
* The callee must set this value
|
||||
* \return A pointer to an allocated vendor extention message
|
||||
*/
|
||||
nfapi_p4_p5_message_header_t* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size);
|
||||
|
||||
/*! A callback to deallocate vendor extension messages
|
||||
* \param header A pointer to an allocated vendor extention message
|
||||
*/
|
||||
void (*deallocate_p4_p5_vendor_ext)(nfapi_p4_p5_message_header_t* header);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} nfapi_vnf_config_t;
|
||||
|
||||
/*! Creates and initialise the vnf config structure before use
|
||||
* \return A pointer to a vnf config structure
|
||||
*/
|
||||
nfapi_vnf_config_t* nfapi_vnf_config_create(void);
|
||||
|
||||
/*! Delete an vnf config
|
||||
*/
|
||||
void nfapi_vnf_config_destory(nfapi_vnf_config_t* config);
|
||||
|
||||
|
||||
/*! Start the VNF library.
|
||||
* \param config A pointer to a vnf config
|
||||
* \return 0 means success, -1 failure
|
||||
*
|
||||
* The config should be initailize with port the vnf should listen on and
|
||||
* the callback set to functions that will be called when a nFAPI message is
|
||||
* recevied before calling nfapi_vnf_start.
|
||||
*
|
||||
* This function will not return untill nfapi_vnf_stop is called
|
||||
*/
|
||||
int nfapi_vnf_start(nfapi_vnf_config_t* config);
|
||||
|
||||
/*! Stop the VNF library.
|
||||
* \param config A pointer to a vnf config
|
||||
* \return 0 means success, -1 failure
|
||||
*
|
||||
* This function will cause the nfapi_vnf_start function to return
|
||||
*/
|
||||
int nfapi_vnf_stop(nfapi_vnf_config_t* config);
|
||||
|
||||
/*! Allocates a PHY ID for the PNF PHY instance managed by this VNF
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index return by the callbacks
|
||||
* \param phy_id A pointer to a phy_id that will be set by this function
|
||||
* \return 0 means success, -1 failure
|
||||
*
|
||||
* Called before nfapi_vnf_config_req to allocate a vnf phy instance. This
|
||||
* function will return unqiue phy_id to be used for this identify the phy
|
||||
*
|
||||
*/
|
||||
int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy_id);
|
||||
|
||||
// P5 Request functions
|
||||
//
|
||||
/*! Send the PNF_PARAM.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a PNF_PARAM.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req);
|
||||
|
||||
/*! Send the PNF_CONFIG.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a PNF_CONFIG.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_config_request_t* req);
|
||||
|
||||
/*! Send the PNF_START.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a PNF_START.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_start_request_t* req);
|
||||
|
||||
/*! Send the PNF_STOP.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a PNF_STOP.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_stop_request_t* req);
|
||||
|
||||
/*! Send the PARAM.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a PARAM.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req);
|
||||
|
||||
/*! Send the CONFIG.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a CONFIG.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req);
|
||||
|
||||
/*! Send the START.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a START.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req);
|
||||
|
||||
/*! Send the STOP.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a STOP.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req);
|
||||
|
||||
/*! Send the MEASUREMENT.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a MEASUREMENT.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req);
|
||||
|
||||
// P4 Request functions
|
||||
/*! Send the RSSI.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a RSSI.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_rssi_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_request_t* req);
|
||||
|
||||
/*! Send the CELL_SEARCH.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a CELL_SEARCH.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_cell_search_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_request_t* req);
|
||||
|
||||
/*! Send the BROADCAST_DETECT.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a BROADCAST_DETECT.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_broadcast_detect_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_request_t* req);
|
||||
|
||||
/*! Send the SYSTEM_INFORMATION_SCHEDULE.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a SYSTEM_INFORMATION_SCHEDULE.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_system_information_schedule_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_request_t* req);
|
||||
|
||||
/*! Send the SYSTEM_INFORMATION.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a SYSTEM_INFORMATION.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_system_information_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_request_t* req);
|
||||
|
||||
/*! Send the NMM_STOP.request
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param req A pointer to a NMM_STOP.request message structure
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_nmm_stop_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_nmm_stop_request_t* req);
|
||||
|
||||
/*! Send a vendor extension message
|
||||
* \param config A pointer to a vnf config
|
||||
* \param p5_idx The P5 index
|
||||
* \param msg A poiner to a vendor extention message
|
||||
* \return 0 means success, -1 failure
|
||||
*/
|
||||
int nfapi_vnf_vendor_extension(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! The nfapi VNF P7 connection information
|
||||
*/
|
||||
typedef struct nfapi_vnf_p7_config nfapi_vnf_p7_config_t;
|
||||
|
||||
/*! The nfapi VNF P7 configuration information
|
||||
*/
|
||||
typedef struct nfapi_vnf_p7_config
|
||||
{
|
||||
/*! A user define callback to override the default memory allocation
|
||||
* \param size Size of the memory block to allocate
|
||||
* \return a pointer to a memory block
|
||||
*
|
||||
* If not set the vnf p7 library will use malloc
|
||||
*/
|
||||
void* (*malloc)(size_t size);
|
||||
|
||||
/*! A user define callback to override the default memory deallocation
|
||||
* \param ptr Pointer to a memory block to deallocate
|
||||
*
|
||||
* If not set the vnf p7 library will use free
|
||||
*/
|
||||
void (*free)(void*);
|
||||
|
||||
/*! A user define callback to handle trace from the pnf
|
||||
* \param level The trace level
|
||||
* \param message The trace string
|
||||
*/
|
||||
void (*trace)(nfapi_trace_level_t level, const char* message, ...);
|
||||
|
||||
/*! The port the vnf p7 will receive on */
|
||||
int port;
|
||||
|
||||
/*! Flag to indicate of the pnf should use the P7 checksum */
|
||||
uint8_t checksum_enabled;
|
||||
|
||||
/*! The maxium size of a P7 segement. If a message is large that this it
|
||||
* will be segemented */
|
||||
uint16_t segment_size;
|
||||
uint16_t max_num_segments;
|
||||
|
||||
/*! Configuration option for the p7 pack unpack functions*/
|
||||
nfapi_p7_codec_config_t codec_config;
|
||||
|
||||
/* ! Call back to indicate the sync state with the PNF PHY
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param sync Indicating if the pnf is in sync or not
|
||||
* \return not currently used
|
||||
*
|
||||
* sync = 0 : in sync
|
||||
* sync != 0 : out of sync
|
||||
*/
|
||||
int (*sync_indication)(struct nfapi_vnf_p7_config* config, uint8_t sync);
|
||||
|
||||
/*! A callback for the subframe indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param phy_id The ID for the PNF PHY instance
|
||||
* \param sfn_sf The SFN SF number formated as per the FAPI specification
|
||||
* \return not currently used
|
||||
*
|
||||
* This callback is an indication for the VNF to generate the downlink subframe messages
|
||||
* for sfn/sf. This indicatoin is called every millisecond
|
||||
*
|
||||
* The VNF P7 Lib will adjust the subframe timing to 'catch-up' or 'slow-down' with the PNF PHY's
|
||||
*
|
||||
* \todo Need some way the tell the VNF how long it has
|
||||
*/
|
||||
|
||||
int (*subframe_indication)(struct nfapi_vnf_p7_config* config, uint16_t phy_id, uint16_t sfn_sf);
|
||||
|
||||
/*! A callback for the HARQ.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded HARQ.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*harq_indication)(struct nfapi_vnf_p7_config* config, nfapi_harq_indication_t* ind);
|
||||
|
||||
/*! A callback for the CRC.ind
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded CRC.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*crc_indication)(struct nfapi_vnf_p7_config* config, nfapi_crc_indication_t* ind);
|
||||
|
||||
/*! A callback for the RX_ULSCH.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded RX_ULSCH.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*
|
||||
* Note that the rx_indication may hold one or many uplink pdus in the
|
||||
* ind.rx_indication_body.rx_pdu_list
|
||||
*/
|
||||
int (*rx_indication)(struct nfapi_vnf_p7_config* config, nfapi_rx_indication_t* ind);
|
||||
|
||||
/*! A callback for the RACH.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded RACH.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*rach_indication)(struct nfapi_vnf_p7_config* config, nfapi_rach_indication_t* ind);
|
||||
|
||||
/*! A callback for the SRS.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded SRS.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*srs_indication)(struct nfapi_vnf_p7_config* config, nfapi_srs_indication_t* ind);
|
||||
|
||||
/*! A callback for the RX_SR.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded RX_SR.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*sr_indication)(struct nfapi_vnf_p7_config* config, nfapi_sr_indication_t* ind);
|
||||
|
||||
/*! A callback for the RX_CQI.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded RX_CQI.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*cqi_indication)(struct nfapi_vnf_p7_config* config, nfapi_cqi_indication_t* ind);
|
||||
|
||||
/*! A callback for the LBT_DL.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded LBT_DL.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*lbt_dl_indication)(struct nfapi_vnf_p7_config* config, nfapi_lbt_dl_indication_t* ind);
|
||||
|
||||
/*! A callback for the NB_HARQ.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded LBT_DL.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*nb_harq_indication)(struct nfapi_vnf_p7_config* config, nfapi_nb_harq_indication_t* ind);
|
||||
|
||||
/*! A callback for the NRACH.indication
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param ind A data structure for the decoded LBT_DL.indication This will
|
||||
* have been allocated on the stack.
|
||||
* \return not currently used.
|
||||
*
|
||||
* The ind may contain pointers to dyanmically allocated sub structures
|
||||
* such as the pdu. The dyanmically allocated structure will
|
||||
* be deallocated on return. If the client wishes to 'keep' the structures
|
||||
* then the substructure pointers should be set to 0 and then the client should
|
||||
* use the codec_config.deallocate function to release it at a future point
|
||||
*/
|
||||
int (*nrach_indication)(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind);
|
||||
|
||||
/*! A callback for any vendor extension messages
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param msg A data structure for the decoded vendor extention message allocated
|
||||
* using the allocate_p7_vendor_ext callback
|
||||
* \return not currently used.
|
||||
*/
|
||||
int (*vendor_ext)(struct nfapi_vnf_p7_config* config, nfapi_p7_message_header_t* msg);
|
||||
|
||||
/*! Optional userdata that will be passed back in the callbacks*/
|
||||
void* user_data;
|
||||
|
||||
/*! A callback to allocate a memory for a vendor extension message
|
||||
* \param message_id The message is taken from the p7 message header
|
||||
* \param msg_size The is the vendor extention message that has been allocated.
|
||||
* The callee must set this value
|
||||
* \return A pointer to an allocated vendor extention message
|
||||
*/
|
||||
nfapi_p7_message_header_t* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size);
|
||||
|
||||
/*! A callback to deallocate a vendor extension message
|
||||
* \param header A pointer to an allocated vendor extention message
|
||||
*/
|
||||
void (*deallocate_p7_vendor_ext)(nfapi_p7_message_header_t* header);
|
||||
|
||||
|
||||
} nfapi_vnf_p7_config_t;
|
||||
|
||||
/*! Creates and initializes the nfapi_vnf_p7_config structure before use
|
||||
* \return A pointer to an allocated vnf p7 configuration
|
||||
*/
|
||||
nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create(void);
|
||||
|
||||
/*! Cleanup and delete nfapi_vnf_p7_config structure
|
||||
* \param config A pointer to an vnf p7 configuration structure
|
||||
*
|
||||
* The pointer to the config will not long be valid after this call
|
||||
*/
|
||||
|
||||
void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config);
|
||||
|
||||
/*! Start the VNF P7 library.
|
||||
* \param config A pointer to an vnf p7 configuration structure
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* This function is blocking and will not return until the nfapi_vnf_p7_stop
|
||||
* function is called.
|
||||
*/
|
||||
|
||||
int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config);
|
||||
|
||||
/*! Stop the VNF P7 library.
|
||||
* \param config A pointer to an vnf p7 configuration structure
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* This function will cause the nfapi_vnf_p7_start function to return
|
||||
*/
|
||||
int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t* config);
|
||||
|
||||
/*! Release a P7 message back to the vnf_p7 library. This should be used if the
|
||||
* callback return 0 in the case where MAC wants to keep the message for
|
||||
* futher processing.
|
||||
* This function will release any pdu's is they are non-null. If the uplink
|
||||
* PDU need to be kept then they pdu pointer should be set to 0 in the message
|
||||
* and then the nfapi_vnf_p7_release_pdu message can be used to release the
|
||||
* pdu later.
|
||||
*/
|
||||
int nfapi_vnf_p7_release_msg(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t*);
|
||||
|
||||
/*! Release a P7 pdu's back to the vnf_p7 library.
|
||||
*/
|
||||
int nfapi_vnf_p7_release_pdu(nfapi_vnf_p7_config_t* config, void*);
|
||||
|
||||
/*! Add a vnf p7 instance to the vnf p7 module
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param pnf_p7_addr The udp address the pnf p7 entity has chosen
|
||||
* \param pnf_p7_port The udp port the pnf p7 entity has chosen
|
||||
* \param phy_id The unique phy id for the pnf p7 entity
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* This function should be used to each pnf p7 entity that is to be added to this
|
||||
* vnf p7 entity. Once added the vnf p7 entity will start establish sync with the
|
||||
* pnf p7 entity and that has been sucessfull will generate subframe indications for it
|
||||
*/
|
||||
int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, int pnf_p7_port, int phy_id);
|
||||
|
||||
/*! Delete a vnf p7 instance to the vnf p7 module
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param phy_id The unique phy id for the pnf p7 entity
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* This function should be used to remove a pnf p7 entity from the vnf p7 entity
|
||||
*/
|
||||
int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t* config, int phy_id);
|
||||
|
||||
/*! Send the DL_CONFIG.request
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param req A data structure for the decoded DL_CONFIG.request.
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* The caller is responsiable for memory management of any pointers set in the req, which
|
||||
* may be released after this function call has returned or at a later pointer
|
||||
*/
|
||||
int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_request_t* req);
|
||||
|
||||
/*! Send the UL_CONFIG.request
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param req A data structure for the decoded UL_CONFIG.request.
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* The caller is responsiable for memory management of any pointers set in the req, which
|
||||
* may be released after this function call has returned or at a later pointer
|
||||
*/
|
||||
int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req);
|
||||
|
||||
/*! Send the HI_DCI0.request
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param req A data structure for the decoded HI_DCI0.request.
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* The caller is responsiable for memory management of any pointers set in the req, which
|
||||
* may be released after this function call has returned or at a later pointer
|
||||
*/
|
||||
int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req);
|
||||
|
||||
/*! Send the TX.req
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param req A data structure for the decoded HI_DCI0.request.
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* The caller is responsiable for memory management of any pointers set in the req, which
|
||||
* may be released after this function call has returned or at a later pointer
|
||||
*/
|
||||
int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req);
|
||||
|
||||
/*! Send the LBT_DL_CONFIG.requst
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param req A data structure for the decoded LBT_DL_CONFIG.request.
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* The caller is responsiable for memory management of any pointers set in the req, which
|
||||
* may be released after this function call has returned or at a later pointer
|
||||
*/
|
||||
int nfapi_vnf_p7_lbt_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req);
|
||||
|
||||
/*! Send a vendor extension message
|
||||
* \param config A pointer to the vnf p7 configuration
|
||||
* \param msg A data structure for the decoded vendor extention message
|
||||
* \return A status value. 0 equal success, -1 indicates failure
|
||||
*
|
||||
* The caller is responsiable for memory management of any pointers set in the req, which
|
||||
* may be released after this function call has returned or at a later pointer
|
||||
*/
|
||||
int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* msg);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _NFAPI_PNF_INTERFACE_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,676 @@
|
||||
/*
|
||||
* 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 <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vnf.h"
|
||||
|
||||
|
||||
|
||||
nfapi_vnf_config_t* nfapi_vnf_config_create()
|
||||
{
|
||||
vnf_t* _this = (vnf_t*)calloc(1, sizeof(vnf_t));
|
||||
|
||||
if(_this == 0)
|
||||
return 0;
|
||||
|
||||
_this->sctp = 1;
|
||||
|
||||
_this->next_phy_id = 1;
|
||||
|
||||
// Set the default P5 port
|
||||
_this->_public.vnf_p5_port = NFAPI_P5_SCTP_PORT;
|
||||
|
||||
// set the default memory allocation
|
||||
_this->_public.malloc = &malloc;
|
||||
_this->_public.free = &free;
|
||||
|
||||
// set the default memory allocation
|
||||
_this->_public.codec_config.allocate = &malloc;
|
||||
_this->_public.codec_config.deallocate = &free;
|
||||
|
||||
|
||||
return &(_this->_public);
|
||||
}
|
||||
|
||||
void nfapi_vnf_config_destory(nfapi_vnf_config_t* config)
|
||||
{
|
||||
free(config);
|
||||
}
|
||||
|
||||
int nfapi_vnf_start(nfapi_vnf_config_t* config)
|
||||
{
|
||||
// Verify that config is not null
|
||||
if(config == 0)
|
||||
return -1;
|
||||
|
||||
// Make sure to set the defined trace function before using NFAPI_TRACE
|
||||
if(config->trace)
|
||||
nfapi_trace_g = (nfapi_trace_fn_t)config->trace;
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
|
||||
|
||||
int p5ListenSock, p5Sock;
|
||||
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrSize;
|
||||
|
||||
struct sockaddr_in6 addr6;
|
||||
|
||||
struct sctp_event_subscribe events;
|
||||
struct sctp_initmsg initMsg;
|
||||
int noDelay;
|
||||
|
||||
(void)memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
(void)memset(&addr6, 0, sizeof(struct sockaddr_in6));
|
||||
(void)memset(&events, 0, sizeof(struct sctp_event_subscribe));
|
||||
(void)memset(&initMsg, 0, sizeof(struct sctp_initmsg));
|
||||
|
||||
vnf_t* vnf = (vnf_t*)(config);
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port);
|
||||
|
||||
/*
|
||||
char * host = 0;
|
||||
char * port = "4242";
|
||||
struct addrinfo hints;
|
||||
bzero(&hints, sizeof(struct addrinfo));
|
||||
//hints.ai_flags=AI_PASSIVE;
|
||||
//hints.ai_flags=AI_DEFAULT;
|
||||
hints.ai_family=AF_UNSPEC;
|
||||
//hints.ai_family=AF_INET6;
|
||||
hints.ai_socktype=SOCK_STREAM;
|
||||
//hints.ai_protocol=IPPROTO_SCTP
|
||||
|
||||
struct addrinfo *aiHead = 0;
|
||||
|
||||
|
||||
|
||||
int result = getaddrinfo(host, port, &hints, &aiHead);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno);
|
||||
|
||||
while(aiHead->ai_next != NULL)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n",
|
||||
aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP,
|
||||
aiHead->ai_flags, AI_PASSIVE);
|
||||
|
||||
char hostBfr[ NI_MAXHOST ];
|
||||
char servBfr[ NI_MAXSERV ];
|
||||
|
||||
getnameinfo(aiHead->ai_addr,
|
||||
aiHead->ai_addrlen,
|
||||
hostBfr,
|
||||
sizeof( hostBfr ),
|
||||
servBfr,
|
||||
sizeof( servBfr ),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV );
|
||||
|
||||
switch(aiHead->ai_family)
|
||||
{
|
||||
case PF_INET:
|
||||
{
|
||||
struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr;
|
||||
printf(
|
||||
" ai_addr = sin_family: %d (AF_INET = %d, "
|
||||
"AF_INET6 = %d)\n"
|
||||
" sin_addr: %s\n"
|
||||
" sin_port: %s\n",
|
||||
pSadrIn->sin_family,
|
||||
AF_INET,
|
||||
AF_INET6,
|
||||
hostBfr,
|
||||
servBfr );
|
||||
}
|
||||
break;
|
||||
case PF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr;
|
||||
fprintf( stderr,
|
||||
" ai_addr = sin6_family: %d (AF_INET = %d, "
|
||||
"AF_INET6 = %d) \n"
|
||||
" sin6_addr: %s\n"
|
||||
" sin6_port: %s\n"
|
||||
" sin6_flowinfo: %d\n"
|
||||
" sin6_scope_id: %d\n",
|
||||
pSadrIn6->sin6_family,
|
||||
AF_INET,
|
||||
AF_INET6,
|
||||
hostBfr,
|
||||
servBfr,
|
||||
pSadrIn6->sin6_flowinfo,
|
||||
pSadrIn6->sin6_scope_id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n");
|
||||
break;
|
||||
}
|
||||
|
||||
aiHead = aiHead->ai_next;
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
int protocol;
|
||||
int domain;
|
||||
|
||||
if (vnf->sctp)
|
||||
protocol = IPPROTO_SCTP;
|
||||
else
|
||||
protocol = IPPROTO_IP;
|
||||
|
||||
if(config->vnf_ipv6)
|
||||
{
|
||||
domain = PF_INET6;
|
||||
}
|
||||
else
|
||||
{
|
||||
domain = AF_INET;
|
||||
}
|
||||
|
||||
// open the SCTP socket
|
||||
if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
|
||||
return 0;
|
||||
}
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock);
|
||||
}
|
||||
|
||||
if (vnf->sctp)
|
||||
{
|
||||
// configure for MSG_NOTIFICATION
|
||||
if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno);
|
||||
close(p5ListenSock);
|
||||
return 0;
|
||||
}
|
||||
NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n");
|
||||
// configure the SCTP socket options
|
||||
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(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno)
|
||||
close(p5ListenSock);
|
||||
return 0;
|
||||
}
|
||||
noDelay = 1;
|
||||
if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno);
|
||||
close(p5ListenSock);
|
||||
return 0;
|
||||
}
|
||||
struct sctp_event_subscribe events;
|
||||
memset( (void *)&events, 0, sizeof(events) );
|
||||
events.sctp_data_io_event = 1;
|
||||
|
||||
if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
|
||||
close(p5ListenSock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(config->vnf_ipv6)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock);
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = htons(config->vnf_p5_port);
|
||||
addr6.sin6_addr = in6addr_any;
|
||||
|
||||
// bind to the configured address and port
|
||||
if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
|
||||
close(p5ListenSock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if(config->vnf_ipv4)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(config->vnf_p5_port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// bind to the configured address and port
|
||||
if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
|
||||
//if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
|
||||
close(p5ListenSock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock);
|
||||
|
||||
// put the socket into listen mode
|
||||
if (listen(p5ListenSock, 2) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno);
|
||||
close(p5ListenSock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n");
|
||||
|
||||
struct timeval tv;
|
||||
fd_set read_fd_set;
|
||||
|
||||
|
||||
int p5_idx = 0;
|
||||
while(vnf->terminate == 0)
|
||||
{
|
||||
FD_ZERO(&read_fd_set);
|
||||
|
||||
FD_SET(p5ListenSock, &read_fd_set);
|
||||
int max_fd = p5ListenSock;
|
||||
|
||||
tv.tv_sec = 5;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
nfapi_vnf_pnf_info_t* pnf = config->pnf_list;
|
||||
while(pnf != 0)
|
||||
{
|
||||
if(pnf->connected)
|
||||
{
|
||||
FD_SET(pnf->p5_sock, &read_fd_set);
|
||||
if (pnf->p5_sock > max_fd)
|
||||
{
|
||||
max_fd = pnf->p5_sock;
|
||||
}
|
||||
}
|
||||
|
||||
pnf = pnf->next;
|
||||
}
|
||||
|
||||
int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv);
|
||||
|
||||
if(select_result == -1)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno);
|
||||
close(p5ListenSock);
|
||||
return 0;
|
||||
}
|
||||
else if(select_result)
|
||||
{
|
||||
if(FD_ISSET(p5ListenSock, &read_fd_set))
|
||||
{
|
||||
addrSize = sizeof(struct sockaddr_in);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n");
|
||||
|
||||
p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
|
||||
|
||||
if (p5Sock < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
nfapi_vnf_pnf_info_t* pnf = (nfapi_vnf_pnf_info_t*)malloc(sizeof(nfapi_vnf_pnf_info_t));
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf);
|
||||
memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t));
|
||||
pnf->p5_sock = p5Sock;
|
||||
pnf->p5_idx = p5_idx++;
|
||||
pnf->p5_pnf_sockaddr = addr;
|
||||
pnf->connected = 1;
|
||||
|
||||
nfapi_vnf_pnf_list_add(config, pnf);
|
||||
|
||||
// Inform mac that a pnf connection has been established
|
||||
// todo : allow mac to 'accept' the connection. i.e. to
|
||||
// reject it.
|
||||
if(config->pnf_connection_indication != 0)
|
||||
{
|
||||
(config->pnf_connection_indication)(config, pnf->p5_idx);
|
||||
}
|
||||
|
||||
|
||||
// check the connection status
|
||||
{
|
||||
struct sctp_status status;
|
||||
(void)memset(&status, 0, sizeof(struct sctp_status));
|
||||
socklen_t optLen = (socklen_t) sizeof(struct sctp_status);
|
||||
if (getsockopt(p5Sock, 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, "VNF Association ID = %d\n", status.sstat_assoc_id);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t delete_pnfs = 0;
|
||||
|
||||
nfapi_vnf_pnf_info_t* pnf = config->pnf_list;
|
||||
while(pnf != 0)
|
||||
{
|
||||
if(FD_ISSET(pnf->p5_sock, &read_fd_set))
|
||||
{
|
||||
if(vnf_read_dispatch_message(config, pnf) == 0)
|
||||
{
|
||||
if(config->pnf_disconnect_indication != 0)
|
||||
{
|
||||
(config->pnf_disconnect_indication)(config, pnf->p5_idx);
|
||||
}
|
||||
|
||||
close(pnf->p5_sock);
|
||||
|
||||
pnf->to_delete = 1;
|
||||
delete_pnfs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pnf = pnf->next;
|
||||
}
|
||||
|
||||
if(delete_pnfs)
|
||||
{
|
||||
nfapi_vnf_pnf_info_t* pnf = config->pnf_list;
|
||||
nfapi_vnf_pnf_info_t* prev = 0;
|
||||
while(pnf != 0)
|
||||
{
|
||||
nfapi_vnf_pnf_info_t* curr = pnf;
|
||||
|
||||
if(pnf->to_delete == 1)
|
||||
{
|
||||
if(prev == 0)
|
||||
{
|
||||
config->pnf_list = pnf->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = pnf->next;
|
||||
}
|
||||
|
||||
pnf = pnf->next;
|
||||
|
||||
free(curr);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = pnf;
|
||||
pnf = pnf->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// timeout
|
||||
|
||||
// Should we test for socket closure here every second?
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n");
|
||||
{
|
||||
nfapi_vnf_pnf_info_t* curr = config->pnf_list;
|
||||
while(curr != NULL)
|
||||
{
|
||||
if(config->pnf_disconnect_indication)
|
||||
{
|
||||
(config->pnf_disconnect_indication)(config, curr->p5_idx);
|
||||
}
|
||||
|
||||
close(curr->p5_sock);
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n");
|
||||
close(p5ListenSock);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int nfapi_vnf_stop(nfapi_vnf_config_t* config)
|
||||
{
|
||||
// Verify that config is not null
|
||||
if(config == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
_this->terminate = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_param_request_t));
|
||||
}
|
||||
|
||||
int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_config_request_t));
|
||||
}
|
||||
|
||||
int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_start_request_t));
|
||||
}
|
||||
|
||||
int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_stop_request_t));
|
||||
}
|
||||
|
||||
int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_param_request_t));
|
||||
}
|
||||
int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id);
|
||||
|
||||
if(phy == NULL)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_WARN, "%s failed to find phy inforation phy_id:%d\n", __FUNCTION__, req->header.phy_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set the timing parameters
|
||||
req->nfapi_config.timing_window.tl.tag = NFAPI_NFAPI_TIMING_WINDOW_TAG;
|
||||
req->nfapi_config.timing_window.value = phy->timing_window;
|
||||
req->num_tlv++;
|
||||
|
||||
req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NFAPI_TIMING_INFO_MODE_TAG;
|
||||
req->nfapi_config.timing_info_mode.value = phy->timing_info_mode;
|
||||
req->num_tlv++;
|
||||
|
||||
req->nfapi_config.timing_info_period.tl.tag = NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG;
|
||||
req->nfapi_config.timing_info_period.value = phy->timing_info_period;
|
||||
req->num_tlv++;
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_config_request_t));
|
||||
}
|
||||
int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_start_request_t));
|
||||
}
|
||||
int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_stop_request_t));
|
||||
}
|
||||
int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_measurement_request_t));
|
||||
}
|
||||
int nfapi_vnf_rssi_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_rssi_request_t));
|
||||
}
|
||||
int nfapi_vnf_cell_search_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_cell_search_request_t));
|
||||
}
|
||||
int nfapi_vnf_broadcast_detect_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_broadcast_detect_request_t));
|
||||
}
|
||||
int nfapi_vnf_system_information_schedule_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_schedule_request_t));
|
||||
}
|
||||
int nfapi_vnf_system_information_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_request_t));
|
||||
}
|
||||
int nfapi_vnf_nmm_stop_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_nmm_stop_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_nmm_stop_request_t));
|
||||
}
|
||||
int nfapi_vnf_vendor_extension(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg)
|
||||
{
|
||||
if(config == 0 || msg == 0)
|
||||
return -1;
|
||||
|
||||
vnf_t* _this = (vnf_t*)(config);
|
||||
|
||||
return vnf_pack_and_send_p5_message(_this, p5_idx, msg, sizeof(nfapi_p4_p5_message_header_t));
|
||||
}
|
||||
|
||||
int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy_id)
|
||||
{
|
||||
vnf_t* vnf = (vnf_t*)config;
|
||||
|
||||
nfapi_vnf_phy_info_t* info = (nfapi_vnf_phy_info_t*)calloc(1, sizeof(nfapi_vnf_phy_info_t));
|
||||
info->p5_idx = p5_idx;
|
||||
info->phy_id = vnf->next_phy_id++;
|
||||
|
||||
info->timing_window = 30; // This seems to override what gets set by the user - why???
|
||||
info->timing_info_mode = 0x03;
|
||||
info->timing_info_period = 128;
|
||||
|
||||
nfapi_vnf_phy_info_list_add(config, info);
|
||||
|
||||
(*phy_id) = info->phy_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,562 @@
|
||||
/*
|
||||
* 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/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "vnf_p7.h"
|
||||
|
||||
#define FAPI2_IP_DSCP 0
|
||||
|
||||
nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create()
|
||||
{
|
||||
vnf_p7_t* _this = (vnf_p7_t*)calloc(1, sizeof(vnf_p7_t));
|
||||
|
||||
if(_this == 0)
|
||||
return 0;
|
||||
|
||||
// todo : initialize
|
||||
_this->_public.segment_size = 1400;
|
||||
_this->_public.max_num_segments = 8;
|
||||
_this->_public.checksum_enabled = 1;
|
||||
|
||||
_this->_public.malloc = &malloc;
|
||||
_this->_public.free = &free;
|
||||
|
||||
_this->_public.codec_config.allocate = &malloc;
|
||||
_this->_public.codec_config.deallocate = &free;
|
||||
|
||||
|
||||
return &(_this->_public);
|
||||
}
|
||||
|
||||
void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config)
|
||||
{
|
||||
free(config);
|
||||
}
|
||||
|
||||
|
||||
struct timespec timespec_add(struct timespec lhs, struct timespec rhs)
|
||||
{
|
||||
struct timespec result;
|
||||
|
||||
result.tv_sec = lhs.tv_sec + rhs.tv_sec;
|
||||
result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec;
|
||||
|
||||
if(result.tv_nsec > 1e9)
|
||||
{
|
||||
result.tv_sec++;
|
||||
result.tv_nsec-= 1e9;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct timespec timespec_sub(struct timespec lhs, struct timespec rhs)
|
||||
{
|
||||
struct timespec result;
|
||||
if ((lhs.tv_nsec-rhs.tv_nsec)<0)
|
||||
{
|
||||
result.tv_sec = lhs.tv_sec-rhs.tv_sec-1;
|
||||
result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.tv_sec = lhs.tv_sec-rhs.tv_sec;
|
||||
result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// monitor the p7 endpoints and the timing loop and
|
||||
// send indications to mac
|
||||
int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config)
|
||||
{
|
||||
if(config == 0)
|
||||
return -1;
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
|
||||
// Create p7 receive udp port
|
||||
// todo : this needs updating for Ipv6
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port);
|
||||
|
||||
// open the UDP socket
|
||||
if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n");
|
||||
|
||||
// configure the UDP socket options
|
||||
int iptos_value = FAPI2_IP_DSCP << 2;
|
||||
if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n");
|
||||
|
||||
// Create the address structure
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(config->port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// bind to the configured port
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
|
||||
//if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n");
|
||||
|
||||
|
||||
//struct timespec original_pselect_timeout;
|
||||
struct timespec pselect_timeout;
|
||||
pselect_timeout.tv_sec = 0;
|
||||
pselect_timeout.tv_nsec = 1000000; // ns in a 1 us
|
||||
|
||||
|
||||
struct timespec pselect_start;
|
||||
struct timespec pselect_stop;
|
||||
|
||||
//struct timespec sf_end;
|
||||
|
||||
long last_millisecond = -1;
|
||||
|
||||
|
||||
struct timespec sf_duration;
|
||||
sf_duration.tv_sec = 0;
|
||||
sf_duration.tv_nsec = 1e6; // We want 1ms pause
|
||||
|
||||
struct timespec sf_start;
|
||||
clock_gettime(CLOCK_MONOTONIC, &sf_start);
|
||||
long millisecond = sf_start.tv_nsec / 1e6;
|
||||
sf_start = timespec_add(sf_start, sf_duration);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
|
||||
|
||||
while(vnf_p7->terminate == 0)
|
||||
{
|
||||
fd_set rfds;
|
||||
int maxSock = 0;
|
||||
FD_ZERO(&rfds);
|
||||
int selectRetval = 0;
|
||||
|
||||
// Add the p7 socket
|
||||
FD_SET(vnf_p7->socket, &rfds);
|
||||
maxSock = vnf_p7->socket;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &pselect_start);
|
||||
//long millisecond = pselect_start.tv_nsec / 1e6;
|
||||
|
||||
if((last_millisecond == -1) || (millisecond == last_millisecond) || (millisecond == (last_millisecond + 1) % 1000) )
|
||||
{
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec);
|
||||
|
||||
|
||||
if((pselect_start.tv_sec > sf_start.tv_sec) ||
|
||||
((pselect_start.tv_sec == sf_start.tv_sec) && (pselect_start.tv_nsec > sf_start.tv_nsec)))
|
||||
{
|
||||
// overran the end of the subframe we do not want to wait
|
||||
pselect_timeout.tv_sec = 0;
|
||||
pselect_timeout.tv_nsec = 0;
|
||||
|
||||
//struct timespec overrun = timespec_sub(pselect_start, sf_start);
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// still time before the end of the subframe wait
|
||||
pselect_timeout = timespec_sub(sf_start, pselect_start);
|
||||
|
||||
#if 0
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sf_start:%d.%ld pselect_start:%d.%ld pseclect_timeout:%d.%ld\n",
|
||||
__FUNCTION__,
|
||||
sf_start.tv_sec, sf_start.tv_nsec,
|
||||
pselect_start.tv_sec, pselect_start.tv_nsec,
|
||||
pselect_timeout.tv_sec, pselect_timeout.tv_nsec);
|
||||
#endif
|
||||
}
|
||||
|
||||
//original_pselect_timeout = pselect_timeout;
|
||||
|
||||
// detemine how long to sleep in ns before the start of the next 1ms
|
||||
//pselect_timeout.tv_nsec = 1e6 - (pselect_start.tv_nsec % 1000000);
|
||||
|
||||
//uint8_t underrun_possible =0;
|
||||
|
||||
// if we are not sleeping until the next milisecond due to the
|
||||
// insycn minor adjment flag it so we don't consider it an error
|
||||
//uint8_t underrun_possible =0;
|
||||
/*
|
||||
{
|
||||
nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections;
|
||||
if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0 && pselect_start.tv_nsec != 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] Subframe minor adjustment %d (%d->%d)\n", phy->insync_minor_adjustment,
|
||||
pselect_timeout.tv_nsec, pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000))
|
||||
if(phy->insync_minor_adjustment > 0)
|
||||
{
|
||||
// todo check we don't go below 0
|
||||
if((phy->insync_minor_adjustment * 1000) > pselect_timeout.tv_nsec)
|
||||
pselect_timeout.tv_nsec = 0;
|
||||
else
|
||||
pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
|
||||
|
||||
|
||||
//underrun_possible = 1;
|
||||
}
|
||||
else if(phy->insync_minor_adjustment < 0)
|
||||
{
|
||||
// todo check we don't go below 0
|
||||
pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
|
||||
}
|
||||
|
||||
//phy->insync_minor_adjustment = 0;
|
||||
phy->insync_minor_adjustment_duration--;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//long wraps = pselect_timeout.tv_nsec % 1e9;
|
||||
|
||||
|
||||
selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &pselect_stop);
|
||||
|
||||
nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections;
|
||||
|
||||
if (selectRetval==-1 && errno == 22)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n",
|
||||
pselect_timeout.tv_sec, pselect_timeout.tv_nsec,
|
||||
phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment,
|
||||
sf_duration.tv_sec, sf_duration.tv_nsec);
|
||||
}
|
||||
#if 0
|
||||
if (selectRetval != 0 || phy->insync_minor_adjustment_duration != 0)
|
||||
NFAPI_TRACE(NFAPI_TRACE_NOTE, "pselect()=%d maxSock:%d vnf_p7->socket:%d pselect_timeout:%u.%u original_pselect_timeout:%u.%u\n",
|
||||
selectRetval, maxSock, vnf_p7->socket, pselect_timeout.tv_sec, pselect_timeout.tv_nsec,
|
||||
original_pselect_timeout.tv_sec, original_pselect_timeout.tv_nsec);
|
||||
#endif
|
||||
|
||||
if(selectRetval == 0)
|
||||
{
|
||||
// calculate the start of the next subframe
|
||||
sf_start = timespec_add(sf_start, sf_duration);
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
|
||||
|
||||
if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0)
|
||||
{
|
||||
long insync_minor_adjustment_ns = (phy->insync_minor_adjustment * 1000);
|
||||
|
||||
sf_start.tv_nsec -= insync_minor_adjustment_ns;
|
||||
|
||||
#if 1
|
||||
if (sf_start.tv_nsec > 1e9)
|
||||
{
|
||||
sf_start.tv_sec++;
|
||||
sf_start.tv_nsec-=1e9;
|
||||
}
|
||||
else if (sf_start.tv_nsec < 0)
|
||||
{
|
||||
sf_start.tv_sec--;
|
||||
sf_start.tv_nsec+=1e9;
|
||||
}
|
||||
#else
|
||||
//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] BEFORE adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d\n", phy->insync_minor_adjustment, sf_start.tv_nsec);
|
||||
if(phy->insync_minor_adjustment > 0)
|
||||
{
|
||||
// decrease the subframe duration a little
|
||||
if (sf_start.tv_nsec > insync_minor_adjustment_ns)
|
||||
sf_start.tv_nsec -= insync_minor_adjustment_ns;
|
||||
else
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] Adjustment would make it negative sf:%d.%ld adjust:%ld\n\n\n", sf_start.tv_sec, sf_start.tv_nsec, insync_minor_adjustment_ns);
|
||||
sf_start.tv_sec--;
|
||||
sf_start.tv_nsec += 1e9 - insync_minor_adjustment_ns;
|
||||
}
|
||||
}
|
||||
else if(phy->insync_minor_adjustment < 0)
|
||||
{
|
||||
// todo check we don't go below 0
|
||||
// increase the subframe duration a little
|
||||
sf_start.tv_nsec += insync_minor_adjustment_ns;
|
||||
|
||||
if (sf_start.tv_nsec < 0)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] OVERFLOW %d.%ld\n\n\n\n", sf_start.tv_sec, sf_start.tv_nsec);
|
||||
sf_start.tv_sec++;
|
||||
sf_start.tv_nsec += 1e9;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//phy->insync_minor_adjustment = 0;
|
||||
phy->insync_minor_adjustment_duration--;
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d duration:%u\n",
|
||||
phy->insync_minor_adjustment, sf_start.tv_nsec, phy->insync_minor_adjustment_duration);
|
||||
|
||||
if (phy->insync_minor_adjustment_duration==0)
|
||||
{
|
||||
phy->insync_minor_adjustment = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
long pselect_stop_millisecond = pselect_stop.tv_nsec / 1e6;
|
||||
if(millisecond == pselect_stop_millisecond)
|
||||
{
|
||||
// we have woke up in the same subframe
|
||||
if(underrun_possible == 0)
|
||||
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect underrun %ld (%d.%d)\n", millisecond, pselect_stop.tv_sec, pselect_stop.tv_nsec);
|
||||
}
|
||||
else if(((millisecond + 1) % 1000) != pselect_stop_millisecond)
|
||||
{
|
||||
// we have overrun the subframe
|
||||
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect overrun %ld %ld\n", millisecond, pselect_stop_millisecond);
|
||||
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe underrun %ld\n", millisecond);
|
||||
}
|
||||
last_millisecond = millisecond;
|
||||
*/
|
||||
|
||||
millisecond ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have overrun the subframe advance to go and collect $200
|
||||
if((millisecond - last_millisecond) > 3)
|
||||
NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe overrun %ld %ld (%ld)\n", millisecond, last_millisecond, millisecond - last_millisecond + 1);
|
||||
|
||||
last_millisecond = ( last_millisecond + 1 ) % 1000;
|
||||
selectRetval = 0;
|
||||
}
|
||||
|
||||
if(selectRetval == 0)
|
||||
{
|
||||
vnf_p7->sf_start_time_hr = vnf_get_current_time_hr();
|
||||
|
||||
// pselect timed out
|
||||
nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
|
||||
|
||||
while(curr != 0)
|
||||
{
|
||||
curr->sfn_sf = increment_sfn_sf(curr->sfn_sf);
|
||||
|
||||
vnf_sync(vnf_p7, curr);
|
||||
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
send_mac_subframe_indications(vnf_p7);
|
||||
|
||||
}
|
||||
else if(selectRetval > 0)
|
||||
{
|
||||
// have a p7 message
|
||||
if(FD_ISSET(vnf_p7->socket, &rfds))
|
||||
{
|
||||
vnf_p7_read_dispatch_message(vnf_p7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pselect error
|
||||
if(selectRetval == -1 && errno == EINTR)
|
||||
{
|
||||
// a sigal was received.
|
||||
}
|
||||
else
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond);
|
||||
// should we exit now?
|
||||
if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration
|
||||
{
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n");
|
||||
close(vnf_p7->socket);
|
||||
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t* config)
|
||||
{
|
||||
if(config == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
vnf_p7->terminate =1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, int pnf_p7_port, int phy_id)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p phy_id:%d pnf_addr:%s pnf_p7_port:%d)\n", __FUNCTION__, config, phy_id, pnf_p7_addr, pnf_p7_port);
|
||||
|
||||
if(config == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
|
||||
nfapi_vnf_p7_connection_info_t* node = (nfapi_vnf_p7_connection_info_t*)malloc(sizeof(nfapi_vnf_p7_connection_info_t));
|
||||
|
||||
memset(node, 0, sizeof(nfapi_vnf_p7_connection_info_t));
|
||||
node->phy_id = phy_id;
|
||||
node->in_sync = 0;
|
||||
node->dl_out_sync_offset = 30;
|
||||
node->dl_out_sync_period = 10;
|
||||
node->dl_in_sync_offset = 30;
|
||||
node->dl_in_sync_period = 512;
|
||||
node->sfn_sf = 0;
|
||||
|
||||
node->min_sync_cycle_count = 8;
|
||||
|
||||
// save the remote endpoint information
|
||||
node->remote_addr.sin_family = AF_INET;
|
||||
node->remote_addr.sin_port = htons(pnf_p7_port);
|
||||
node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr);
|
||||
|
||||
vnf_p7_connection_info_list_add(vnf_p7, node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t* config, int phy_id)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d)\n", __FUNCTION__, phy_id);
|
||||
|
||||
if(config == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
|
||||
nfapi_vnf_p7_connection_info_t* to_delete = vnf_p7_connection_info_list_delete(vnf_p7, phy_id);
|
||||
|
||||
if(to_delete)
|
||||
{
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d) deleting connection info\n", __FUNCTION__, phy_id);
|
||||
free(to_delete);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_request_t* req)
|
||||
{
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p req:%p)\n", __FUNCTION__, config, req);
|
||||
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
|
||||
}
|
||||
|
||||
int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
|
||||
}
|
||||
int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
|
||||
}
|
||||
int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
|
||||
}
|
||||
int nfapi_vnf_p7_lbt_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req)
|
||||
{
|
||||
if(config == 0 || req == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
|
||||
}
|
||||
int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* header)
|
||||
{
|
||||
if(config == 0 || header == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
return vnf_p7_pack_and_send_p7_msg(vnf_p7, header);
|
||||
}
|
||||
|
||||
|
||||
int nfapi_vnf_p7_release_msg(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* header)
|
||||
{
|
||||
if(config == 0 || header == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
vnf_p7_release_msg(vnf_p7, header);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int nfapi_vnf_p7_release_pdu(nfapi_vnf_p7_config_t* config, void* pdu)
|
||||
{
|
||||
if(config == 0 || pdu == 0)
|
||||
return -1;
|
||||
|
||||
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
|
||||
vnf_p7_release_pdu(vnf_p7, pdu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#vnf unit test
|
||||
#AUTOMAKE_OPTIONS=subdir-objects
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/vnf/public_inc $(CFLAGS_CUNIT) -Wall -Werror
|
||||
|
||||
check_PROGRAMS= test_vnf
|
||||
|
||||
test_vnf_SOURCES = vnf_cunit_main.c ../..//common/src/debug.c
|
||||
test_vnf_LDADD=$(top_builddir)/vnf/libnfapi_vnf.a $(top_builddir)/nfapi/libnfapi.a -L$(libdir) -lpthread -lrt -lsctp -lz -lcunit
|
||||
|
||||
LOG_DRIVER = $(top_srcdir)/tap-driver.sh
|
||||
TESTS=test_vnf
|
||||
EXTRA_DIST = $(TESTS)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user