Files
openairinterface5g/nfapi/open-nFAPI/vnf/tests/vnf_cunit_main.c
T
Robert Schmidt 970eb04a84 Remove hardcoding of numerology in VNF
Similar to the parent commit, make the numerology in the VNF
configurable. Unlike for the PNF change, the VNF frame/slot info is in a
per-PNF connection structure to which the "oai_integration" code has no
access. So we need to hack the nfapi_vnf_p7_add_pnf() function signature
to take the numerology, to be able to save this on a per-PNF basis.

The fact that we store this on a per-PNF basis is not strictly required,
as the VNF cannot handle multiple numerologies as of now, either.
However, we might want to extend this in the future, so it seems prudent
to store this on a per-PNF basis, so that we could start handling
multiple numerologies at the L2 without the need to change the L1 or
nFAPI code itself.

Also, the numerology is not needed except for some code that deals with
timing over nFAPI. As of now, we don't use this code (nFAPI gets a
trigger every slot, as per the VNF request, see an earlier commit in
this series), but also here, let's not make the future more complicated
by storing the numerology for each PNF now (this could always be reverted).

For 4G, put numerology 0 (15kHZ SCS), which is the SCS that LTE uses.
2025-01-27 10:59:40 +01:00

1498 lines
44 KiB
C

/*
* Copyright 2017 Cisco Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "CUnit.h"
#include "Basic.h"
#include "Automated.h"
//#include "CUnit/Console.h"
#include "nfapi_interface.h"
#include "nfapi_vnf_interface.h"
#include "nfapi.h"
#include <stdio.h> // for printf
#include <pthread.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include "debug.h"
#include <unistd.h>
#include <stdlib.h>
/* Test Suite setup and cleanup functions: */
int init_suite(void) { return 0; }
int clean_suite(void) { return 0; }
#define MAX_PACKED_MESSAGE_SIZE 8192
#define SFNSF2SFN(_sfnsf) ((_sfnsf) >> 4)
#define SFNSF2SF(_sfnsf) ((_sfnsf) & 0xF)
typedef struct
{
uint8_t enabled;
uint8_t started;
uint16_t phy_id;
int p7_rx_port;
char* p7_rx_addr;
struct sockaddr_in p7_rx_sockaddr;
int p7_rx_sock;
struct sockaddr_in p7_tx_sockaddr;
int p7_tx_sock;
} pnf_test_config_phy_t;
typedef struct
{
uint8_t enabled;
char* vnf_p5_addr;
int vnf_p5_port;
struct sockaddr_in p5_tx_sockaddr;
int p5_sock;
int p7_rx_port_base;
pnf_test_config_phy_t phys[4];
} pnf_test_config_t;
pnf_test_config_t pnf_test_config[5];
typedef struct
{
uint8_t enabled;
uint8_t state;
uint16_t p5_idx;
uint16_t phy_id;
uint8_t vnf_idx;
//struct sockaddr_in p7_rx_sockaddr;
struct sockaddr_in p7_tx_sockaddr;
} vnf_test_config_phy_t;
typedef struct
{
uint8_t enabled;
pthread_t thread;
char* vnf_p7_addr;
int vnf_p7_port;
struct sockaddr_in p7_rx_sockaddr;
nfapi_vnf_p7_config_t* config;
uint8_t max_phys;
uint8_t phy_count;
//uint8_t phy_ids[4];
} vnf_test_config_vnf_t;
typedef struct
{
char* p5_addr;
int p5_port;
pthread_t thread;
vnf_test_config_vnf_t vnfs[2];
uint8_t phy_count;
vnf_test_config_phy_t phys[5];
nfapi_vnf_config_t* p5_vnf_config;
} vnf_test_config_t;
vnf_test_config_t vnf_test_config[5];
void reset_test_configs()
{
memset(&pnf_test_config, 0, sizeof(pnf_test_config));
memset(&vnf_test_config, 0, sizeof(vnf_test_config));
}
void pnf_create_p5_sock(pnf_test_config_t* config)
{
config->p5_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
config->p5_tx_sockaddr.sin_family = AF_INET;
config->p5_tx_sockaddr.sin_port = htons(config->vnf_p5_port);
config->p5_tx_sockaddr.sin_addr.s_addr = inet_addr(config->vnf_p5_addr);
}
void pnf_p5_connect(pnf_test_config_t* config)
{
int connect_result = connect(config->p5_sock, (struct sockaddr *)&config->p5_tx_sockaddr, sizeof(config->p5_tx_sockaddr) );
printf("connect_result %d %d\n", connect_result, errno);
}
pnf_test_config_phy_t* find_pnf_phy_config(pnf_test_config_t* config, uint16_t phy_id)
{
int i = 0;
for(i = 0; i < 4; ++i)
{
if(config->phys[i].phy_id == phy_id)
return &(config->phys[i]);
}
return 0;
}
vnf_test_config_phy_t* find_vnf_phy_config(vnf_test_config_t* config, uint16_t phy_id)
{
int i = 0;
for(i = 0; i < 4; ++i)
{
if(config->phys[i].phy_id == phy_id)
return &(config->phys[i]);
}
return 0;
}
/************* Test case functions ****************/
void vnf_test_start_no_config(void)
{
int result = nfapi_vnf_start(0);
CU_ASSERT_EQUAL(result, -1);
}
void* vnf_test_start_thread(void* ptr)
{
int result = nfapi_vnf_start((nfapi_vnf_config_t*)ptr);
return (void*)(intptr_t)result;
}
int pnf_connection_indication_called = 0;
int pnf_connection_indication(nfapi_vnf_config_t* config, int p5_idx)
{
printf("[VNF] pnf_connection_indication p5_idx:%d\n", p5_idx);
pnf_connection_indication_called++;
nfapi_pnf_param_request_t req;
memset(&req, 0, sizeof(req));
req.header.message_id = NFAPI_PNF_PARAM_REQUEST;
req.header.message_length = 0;
nfapi_vnf_pnf_param_req(config, p5_idx, &req);
return 1;
}
int pnf_disconnect_indication(nfapi_vnf_config_t* config, int p5_idx)
{
printf("[VNF] pnf_disconnect_indication p5_idx:%d\n", p5_idx);
pnf_connection_indication_called++;
vnf_test_config_t* test_config = (vnf_test_config_t*)(config->user_data);
printf("[VNF] pnf_disconnect_indication user_data %p\n", config->user_data);
int i = 0;
for(i = 0; i < test_config->phy_count; ++i)
{
vnf_test_config_phy_t* phy = &test_config->phys[i];
vnf_test_config_vnf_t* vnf = &test_config->vnfs[phy->p5_idx];
// need to send stop request/response
nfapi_vnf_p7_del_pnf((vnf->config), phy->phy_id);
vnf->phy_count--;
}
for(i = 0; i < 2; ++i)
{
vnf_test_config_vnf_t* vnf = &test_config->vnfs[i];
printf("[VNF] pnf_disconnect_indication phy_count:%d\n", vnf->phy_count);
if(vnf->enabled == 1)
{
nfapi_vnf_p7_stop(vnf->config);
//vnf->config->terminate = 1;
int* result;
printf("[VNF] waiting for vnf p7 thread to exit\n");
pthread_join((vnf->thread), (void**)&result);
CU_ASSERT_EQUAL(result, 0);
vnf->enabled = 0;
}
}
return 1;
}
int send_p5_message(int p5Sock, nfapi_p4_p5_message_header_t* msg, unsigned msg_size, struct sockaddr_in* addr, socklen_t addr_size)
{
char buffer[256];
int encoded_size = nfapi_p5_message_pack(msg, msg_size, buffer, sizeof(buffer), 0);
int result = sendto(p5Sock, buffer, encoded_size, 0, (struct sockaddr*)addr, addr_size);
(void)result;
return 0;
}
int recv_p5_message(int p5Sock, nfapi_p4_p5_message_header_t* msg, unsigned msg_size)
{
struct sockaddr_in addr2;
socklen_t addr2len;
char buffer2[256];
int result2 = recvfrom(p5Sock, buffer2, sizeof(buffer2), 0, (struct sockaddr*)&addr2, &addr2len);
int unpack_result = nfapi_p5_message_unpack(buffer2, result2, msg, msg_size, 0); //, sizeof(resp));
(void)unpack_result;
return 0;
}
int send_pnf_param_response(pnf_test_config_t* config) //int p5Sock, struct sockaddr_in* addr, socklen_t addr_size)
{
nfapi_pnf_param_response_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
resp.header.message_length = 0;
resp.error_code = NFAPI_MSG_OK;
//send_p5_message(p5Sock, &resp, sizeof(resp), addr, addr_size);
send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
return 0;
}
int create_p7_rx_socket(const char* addr, int port)
{
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in sock_addr;
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons(port);
if(addr == 0)
sock_addr.sin_addr.s_addr = INADDR_ANY;
else
sock_addr.sin_addr.s_addr = inet_addr(addr);
int bind_result = bind(fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
if(bind_result != 0)
{
printf("Failed to bind p7 rx socket %d(%d) to %s:%d\n", bind_result, errno, addr, port);
}
return fd;
}
int create_p7_tx_socket()
{
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
return fd;
}
int send_param_response(pnf_test_config_t* config, uint16_t phy_id)
{
nfapi_param_response_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_PARAM_RESPONSE;
resp.header.phy_id = phy_id;
pnf_test_config_phy_t* phy = find_pnf_phy_config(config, phy_id);
resp.error_code = NFAPI_MSG_OK;
resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NFAPI_P7_PNF_PORT_TAG;
resp.nfapi_config.p7_pnf_port.value = phy->p7_rx_port;
struct sockaddr_in pnf_p7_sockaddr;
pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(phy->p7_rx_addr);
resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG;
memcpy(&resp.nfapi_config.p7_pnf_address_ipv4.address[0], &pnf_p7_sockaddr.sin_addr.s_addr, 4);
send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
return 0;
}
int receive_pnf_param_request(pnf_test_config_t* config)
{
nfapi_pnf_param_request_t req;
recv_p5_message(config->p5_sock, &req.header, sizeof(req));
CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_PARAM_REQUEST);
if(req.header.message_id == NFAPI_PNF_PARAM_REQUEST)
{
printf("[PNF] nfapi_pnf_param_request\n");
}
return 0;
}
int receive_param_request(pnf_test_config_t* config)
{
nfapi_param_request_t req;
recv_p5_message(config->p5_sock, &req.header, sizeof(req));
CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PARAM_REQUEST);
if(req.header.message_id == NFAPI_PARAM_REQUEST)
{
printf("[PNF] nfapi_param_request phy_id:%d\n", req.header.phy_id);
}
else
{
printf("[PNF] ERROR, unexpected message %d phy_id:%d\n", req.header.message_id, req.header.phy_id);
}
return req.header.phy_id;
}
int send_pnf_config_response(pnf_test_config_t* config)
{
nfapi_pnf_config_response_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
resp.header.message_length = 0;
resp.error_code = NFAPI_MSG_OK;
send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
return 0;
}
int send_config_response(pnf_test_config_t* config, uint16_t phy_id)
{
nfapi_config_response_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_CONFIG_RESPONSE;
resp.header.message_length = 0;
resp.header.phy_id = phy_id;
resp.error_code = NFAPI_MSG_OK;
send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
return 0;
}
int receive_pnf_config_request(pnf_test_config_t* config)
{
nfapi_pnf_config_request_t req;
recv_p5_message(config->p5_sock, &req.header, sizeof(req));
CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_CONFIG_REQUEST);
if(req.header.message_id == NFAPI_PNF_CONFIG_REQUEST)
{
printf("decoded nfapi_pnf_config_request\n");
int i = 0;
for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i)
{
nfapi_phy_rf_config_info_t* info = &(req.pnf_phy_rf_config.phy_rf_config[i]);
printf("adding pnf phy %d id %d\n", i, info->phy_id);
config->phys[i].enabled = 1;
config->phys[i].phy_id = info->phy_id;
}
}
return 0;
}
int receive_config_request(pnf_test_config_t* config)
{
nfapi_config_request_t req;
recv_p5_message(config->p5_sock, &req.header, sizeof(req));
CU_ASSERT_EQUAL(req.header.message_id, NFAPI_CONFIG_REQUEST);
if(req.header.message_id == NFAPI_CONFIG_REQUEST)
{
printf("[PNF] nfapi_config_request phy_id:%d\n", req.header.phy_id);
pnf_test_config_phy_t* phy = find_pnf_phy_config(config, req.header.phy_id);
// todo verify that this is the same as a vnf config?
phy->p7_tx_sockaddr.sin_family = AF_INET;
phy->p7_tx_sockaddr.sin_port = htons(req.nfapi_config.p7_vnf_port.value);
memcpy(&phy->p7_tx_sockaddr.sin_addr.s_addr, &req.nfapi_config.p7_vnf_address_ipv4.address, 4);
phy->p7_tx_sock = create_p7_tx_socket();
printf("[PNF] vnf p7 address %s:%d\n", inet_ntoa(phy->p7_tx_sockaddr.sin_addr), ntohs(phy->p7_tx_sockaddr.sin_port));
return req.header.phy_id;
}
return NFAPI_PHY_ID_NA;
}
int send_pnf_start_response(pnf_test_config_t* config)
{
nfapi_pnf_start_response_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_PNF_START_RESPONSE;
resp.header.message_length = 0;
resp.error_code = NFAPI_MSG_OK;
send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
return 0;
}
int send_start_response(pnf_test_config_t* config, uint16_t phy_id)
{
nfapi_start_response_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_START_RESPONSE;
resp.header.message_length = 0;
resp.header.phy_id = phy_id;
resp.error_code = NFAPI_MSG_OK;
send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
return 0;
}
int receive_pnf_start_request(pnf_test_config_t* config)
{
nfapi_pnf_start_request_t req;
recv_p5_message(config->p5_sock, &req.header, sizeof(req));
CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_START_REQUEST);
if(req.header.message_id == NFAPI_PNF_START_REQUEST)
{
printf("decoded nfapi_pnf_start_request\n");
int phy_idx = 0;
for(phy_idx = 0; phy_idx < 4; ++phy_idx)
{
if(config->phys[phy_idx].enabled)
{
pnf_test_config_phy_t* phy = &(config->phys[phy_idx]);
phy->p7_rx_port = config->p7_rx_port_base + phy_idx;
phy->p7_rx_addr = "127.0.0.1";
}
}
}
return 0;
}
int receive_start_request(pnf_test_config_t* config)
{
nfapi_start_request_t req;
recv_p5_message(config->p5_sock, &req.header, sizeof(req));
CU_ASSERT_EQUAL(req.header.message_id, NFAPI_START_REQUEST);
if(req.header.message_id == NFAPI_START_REQUEST)
{
printf("[PNF] nfapi_start_request\n");
pnf_test_config_phy_t* phy = find_pnf_phy_config(config, req.header.phy_id);
printf("[PNF] creating p7 rx socket %s:%d\n", phy->p7_rx_addr, phy->p7_rx_port);
phy->p7_rx_sock = create_p7_rx_socket(phy->p7_rx_addr, phy->p7_rx_port);
phy->started = 1;
}
return req.header.phy_id;
}
int send_pnf_stop_response(pnf_test_config_t* config, uint16_t phy_id)
{
printf("pnf_stop_response\n");
nfapi_pnf_stop_response_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_PNF_STOP_RESPONSE;
resp.header.message_length = 0;
resp.error_code = NFAPI_MSG_OK;
send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
return 0;
}
int receive_pnf_stop_request(pnf_test_config_t* config)
{
printf("pnf_stop_request\n");
nfapi_pnf_stop_request_t req;
recv_p5_message(config->p5_sock, &req.header, sizeof(req));
CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_STOP_REQUEST);
if(req.header.message_id == NFAPI_PNF_STOP_REQUEST)
{
printf("decoded nfapi_pnf_stop_request\n");
}
return 0;
}
int pnf_param_response(nfapi_vnf_config_t* config, int p5_idx,nfapi_pnf_param_response_t* response)
{
printf("[VNF] pnf_param_response p5_idx:%d\n", p5_idx);
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
uint16_t phy_id;
nfapi_vnf_allocate_phy(config, p5_idx, &phy_id);
nfapi_pnf_config_request_t req;
memset(&req, 0, sizeof(req));
req.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
req.header.message_length = 0;
req.header.phy_id = NFAPI_PHY_ID_NA;
req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
req.pnf_phy_rf_config.number_phy_rf_config_info = 2;
nfapi_vnf_allocate_phy(config, p5_idx, &req.pnf_phy_rf_config.phy_rf_config[0].phy_id);
nfapi_vnf_allocate_phy(config, p5_idx, &req.pnf_phy_rf_config.phy_rf_config[1].phy_id);
uint16_t i = vnf_test_config[0].phy_count;
vnf_test_config[0].phys[i].enabled = 1;
vnf_test_config[0].phys[i].p5_idx = p5_idx;
vnf_test_config[0].phys[i].phy_id = req.pnf_phy_rf_config.phy_rf_config[0].phy_id;
i++;
vnf_test_config[0].phys[i].enabled = 1;
vnf_test_config[0].phys[i].p5_idx = p5_idx;
vnf_test_config[0].phys[i].phy_id = req.pnf_phy_rf_config.phy_rf_config[1].phy_id;
i++;
vnf_test_config[0].phy_count = i;
nfapi_vnf_pnf_config_req(config, p5_idx, &req);
return 0;
}
int pnf_config_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_response_t* response)
{
printf("pnf_config_response\n");
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
nfapi_pnf_start_request_t req;
memset(&req, 0, sizeof(req));
req.header.message_id = NFAPI_PNF_START_REQUEST;
req.header.message_length = 0;
req.header.phy_id = response->header.phy_id;
nfapi_vnf_pnf_start_req(config, p5_idx, &req);
return 0;
}
void* vnf_test_start_p7_thread(void* ptr)
{
int result = nfapi_vnf_p7_start((nfapi_vnf_p7_config_t*)ptr);
(void)result;
return 0;
}
int test_subframe_indication(nfapi_vnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf)
{
//printf("[VNF:%d] (%d:%d) SUBFRAME_IND\n", phy_id, SFNSF2SFN(sfn_sf), SFNSF2SF(sfn_sf));
nfapi_dl_config_request_t dl_config_req;
memset(&dl_config_req, 0, sizeof(dl_config_req));
dl_config_req.header.message_id = NFAPI_DL_CONFIG_REQUEST;
dl_config_req.header.phy_id = phy_id;
dl_config_req.sfn_sf = sfn_sf;
nfapi_vnf_p7_dl_config_req(config, &dl_config_req);
nfapi_ul_config_request_t ul_config_req;
memset(&ul_config_req, 0, sizeof(ul_config_req));
ul_config_req.header.message_id = NFAPI_UL_CONFIG_REQUEST;
ul_config_req.header.phy_id = phy_id;
ul_config_req.sfn_sf = sfn_sf;
nfapi_vnf_p7_ul_config_req(config, &ul_config_req);
nfapi_hi_dci0_request_t hi_dci0_req;
memset(&hi_dci0_req, 0, sizeof(hi_dci0_req));
hi_dci0_req.header.message_id = NFAPI_HI_DCI0_REQUEST;
hi_dci0_req.header.phy_id = phy_id;
hi_dci0_req.sfn_sf = sfn_sf;
nfapi_vnf_p7_hi_dci0_req(config, &hi_dci0_req);
nfapi_tx_request_t tx_req;
memset(&tx_req, 0, sizeof(tx_req));
tx_req.header.message_id = NFAPI_TX_REQUEST;
tx_req.header.phy_id = phy_id;
tx_req.sfn_sf = sfn_sf;
nfapi_vnf_p7_tx_req(config, &tx_req);
return 0;
}
int test_harq_indication(nfapi_vnf_p7_config_t* config, nfapi_harq_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) HARQ_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_nb_harq_indication(nfapi_vnf_p7_config_t* config, nfapi_nb_harq_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) HARQ_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_crc_indication(nfapi_vnf_p7_config_t* config, nfapi_crc_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) CRC_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_rx_indication(nfapi_vnf_p7_config_t* config, nfapi_rx_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) RX_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_rach_indication(nfapi_vnf_p7_config_t* config, nfapi_rach_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) RACH_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_nrach_indication(nfapi_vnf_p7_config_t* config, nfapi_nrach_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) RACH_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_srs_indication(nfapi_vnf_p7_config_t* config, nfapi_srs_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) SRS_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_sr_indication(nfapi_vnf_p7_config_t* config, nfapi_sr_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) SR_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int test_cqi_indication(nfapi_vnf_p7_config_t* config, nfapi_cqi_indication_t* ind)
{
//printf("[VNF:%d] (%d:%d) CQI_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
return 0;
}
int pnf_start_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* response)
{
printf("[VNF] pnf_start_response p5_idx:%d\n", p5_idx);
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
return 0;
}
int pnf_stop_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_response_t* response)
{
printf("pnf_stop_response\n");
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
nfapi_vnf_p7_stop(vnf_test_config[0].vnfs[0].config);
return 0;
}
int param_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_response_t* response)
{
printf("[VNF] param_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
struct sockaddr_in addr;
memcpy(&addr.sin_addr.s_addr, &response->nfapi_config.p7_pnf_address_ipv4.address, 4);
printf("[VNF] param_response pnf p7 %s:%d\n", inet_ntoa(addr.sin_addr), response->nfapi_config.p7_pnf_port.value);
// find the vnf phy configuration
vnf_test_config_phy_t* phy = find_vnf_phy_config(&(vnf_test_config[0]), response->header.phy_id);
// save the pnf p7 connection information
phy->p7_tx_sockaddr.sin_port = response->nfapi_config.p7_pnf_port.value;
memcpy(&phy->p7_tx_sockaddr.sin_addr.s_addr, &response->nfapi_config.p7_pnf_address_ipv4.address, 4);
nfapi_config_request_t req;
memset(&req, 0, sizeof(req));
req.header.message_id = NFAPI_CONFIG_REQUEST;
req.header.phy_id = response->header.phy_id;
vnf_test_config_vnf_t* vnf = &(vnf_test_config[0].vnfs[phy->vnf_idx]);
req.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
memcpy(&req.nfapi_config.p7_vnf_address_ipv4.address, &vnf->p7_rx_sockaddr.sin_addr.s_addr, 4);
req.nfapi_config.p7_vnf_port.tl.tag = NFAPI_NFAPI_P7_VNF_PORT_TAG;
req.nfapi_config.p7_vnf_port.value = vnf->p7_rx_sockaddr.sin_port;
nfapi_vnf_config_req(config, p5_idx, &req);
return 0;
}
int config_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_response_t* response)
{
printf("[VNF] config_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
return 0;
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
}
int send_vnf_start_req(vnf_test_config_t* config, vnf_test_config_phy_t* phy)
{
nfapi_start_request_t req;
memset(&req, 0, sizeof(req));
req.header.message_id = NFAPI_START_REQUEST;
req.header.phy_id = phy->phy_id;
nfapi_vnf_start_req(config->p5_vnf_config, phy->p5_idx, &req);
return 0;
}
int start_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* response)
{
printf("[VNF] start_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
sleep(1);
vnf_test_config_phy_t* phy = find_vnf_phy_config(&(vnf_test_config[0]), response->header.phy_id);
char* addr = inet_ntoa(phy->p7_tx_sockaddr.sin_addr);
int port = phy->p7_tx_sockaddr.sin_port;
vnf_test_config_vnf_t* vnf = &(vnf_test_config[0].vnfs[phy->vnf_idx]);
nfapi_vnf_p7_add_pnf(vnf->config, addr, port, response->header.phy_id, 0);
return 0;
}
int stop_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_response_t* response)
{
printf("stop_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
return 0;
}
void start_vnf_p5(vnf_test_config_t* test_config)
{
test_config->p5_vnf_config = nfapi_vnf_config_create();
test_config->p5_vnf_config->vnf_p5_port = test_config->p5_port;
test_config->p5_vnf_config->vnf_ipv4 = 1;
test_config->p5_vnf_config->pnf_connection_indication = &pnf_connection_indication;
test_config->p5_vnf_config->pnf_disconnect_indication = &pnf_disconnect_indication;
test_config->p5_vnf_config->pnf_param_resp = &pnf_param_response;
test_config->p5_vnf_config->pnf_config_resp = &pnf_config_response;
test_config->p5_vnf_config->pnf_start_resp = &pnf_start_response;
test_config->p5_vnf_config->pnf_stop_resp = &pnf_stop_response;
test_config->p5_vnf_config->param_resp = &param_response;
test_config->p5_vnf_config->config_resp = &config_response;
test_config->p5_vnf_config->start_resp = &start_response;
test_config->p5_vnf_config->stop_resp = &stop_response;
test_config->p5_vnf_config->user_data = test_config;
pthread_create(&test_config->thread, NULL, &vnf_test_start_thread, test_config->p5_vnf_config);
sleep(1);
}
void start_vnf_p7(vnf_test_config_vnf_t* vnf)
{
// todo : select which vnf to use for these phy's
vnf->enabled = 1;
vnf->p7_rx_sockaddr.sin_addr.s_addr = inet_addr(vnf->vnf_p7_addr);
vnf->p7_rx_sockaddr.sin_port = vnf->vnf_p7_port;
vnf->config = nfapi_vnf_p7_config_create();
vnf->config->checksum_enabled = 0;
vnf->config->port = vnf->vnf_p7_port;
vnf->config->subframe_indication = &test_subframe_indication;
vnf->config->harq_indication = &test_harq_indication;
vnf->config->crc_indication = &test_crc_indication;
vnf->config->rx_indication = &test_rx_indication;
vnf->config->rach_indication = &test_rach_indication;
vnf->config->srs_indication = &test_srs_indication;
vnf->config->sr_indication = &test_sr_indication;
vnf->config->cqi_indication = &test_cqi_indication;
vnf->config->nb_harq_indication = &test_nb_harq_indication;
vnf->config->nrach_indication = &test_nrach_indication;
vnf->config->segment_size = 1400;
vnf->config->max_num_segments = 6;
pthread_create(&(vnf->thread), NULL, &vnf_test_start_p7_thread, vnf->config);
vnf->enabled = 1;
//vnf->phy_count++;
sleep(1);
}
void send_p7_segmented_msg(int sock, char* msg, int len, int segment_size, struct sockaddr* addr, socklen_t addr_len)
{
static uint8_t sequence_num = 0;
if(len < segment_size)
{
msg[7] = sequence_num;
sendto(sock, msg, len, 0, addr, addr_len);
}
else
{
int msg_body_len = len - 12 ;
int seg_body_len = segment_size - 12 ;
int segments = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0);
//printf("sending segmented message len:%d seg_size:%d count:%d\n", len, segment_size, segments);
int segment = 0;
int offset = 12;
for(segment = 0; segment < segments; ++segment)
{
uint8_t last = 0;
uint16_t size = segment_size - 12;
if(segment + 1 == segments)
{
last = 1;
size = (msg_body_len) - (seg_body_len * segment);
}
char buffer[segment_size];
memcpy(&buffer[0], msg, 12);
buffer[6] = ((!last) << 7) + segment;
buffer[7] = sequence_num;
// msg length
uint8_t* p = (uint8_t*)&buffer[4];
push16(size + 12, &p, (uint8_t*)&buffer[size + 12]);
memcpy(&buffer[12], msg + offset, size);
offset += size;
sendto(sock, &buffer[0], size + 12, 0, addr, addr_len);
}
}
sequence_num++;
}
void start_phy(vnf_test_config_phy_t* phy)
{
nfapi_param_request_t req;
memset(&req, 0, sizeof(req));
req.header.message_id = NFAPI_PARAM_REQUEST;
req.header.phy_id = phy->phy_id;
nfapi_vnf_config_t* p5_vnf_config = (vnf_test_config[0].p5_vnf_config);
nfapi_vnf_param_req(p5_vnf_config, phy->p5_idx, &req);
}
void vnf_test_start_connect(void)
{
reset_test_configs();
int segment_size = 256;
vnf_test_config[0].p5_addr = "127.0.0.1";
vnf_test_config[0].p5_port = 4242;
vnf_test_config[0].vnfs[0].enabled = 0;
vnf_test_config[0].vnfs[0].vnf_p7_addr = "127.0.0.1";
vnf_test_config[0].vnfs[0].vnf_p7_port = 7878;
vnf_test_config[0].vnfs[0].max_phys = 1;
vnf_test_config[0].vnfs[1].enabled = 0;
vnf_test_config[0].vnfs[1].vnf_p7_addr = "127.0.0.1";
vnf_test_config[0].vnfs[1].vnf_p7_port = 7879;
vnf_test_config[0].vnfs[1].max_phys = 1;
// this is the action that p9 would take to set the vnf p5 address/port
pnf_test_config[0].enabled = 1;
pnf_test_config[0].vnf_p5_port = vnf_test_config[0].p5_port;
pnf_test_config[0].vnf_p5_addr = vnf_test_config[0].p5_addr;
pnf_test_config[0].p7_rx_port_base = 8000;
pnf_test_config[1].enabled = 1;
pnf_test_config[1].vnf_p5_port = vnf_test_config[0].p5_port;
pnf_test_config[1].vnf_p5_addr = vnf_test_config[0].p5_addr;
pnf_test_config[1].p7_rx_port_base = 8100;
pnf_connection_indication_called = 0;
start_vnf_p5(&vnf_test_config[0]);
pnf_create_p5_sock(&pnf_test_config[0]);
pnf_p5_connect(&pnf_test_config[0]);
receive_pnf_param_request(&pnf_test_config[0]);
send_pnf_param_response(&pnf_test_config[0]);
receive_pnf_config_request(&pnf_test_config[0]);
send_pnf_config_response(&pnf_test_config[0]);
receive_pnf_start_request(&pnf_test_config[0]);
send_pnf_start_response(&pnf_test_config[0]);
pnf_create_p5_sock(&pnf_test_config[1]);
pnf_p5_connect(&pnf_test_config[1]);
receive_pnf_param_request(&pnf_test_config[1]);
send_pnf_param_response(&pnf_test_config[1]);
receive_pnf_config_request(&pnf_test_config[1]);
send_pnf_config_response(&pnf_test_config[1]);
receive_pnf_start_request(&pnf_test_config[1]);
send_pnf_start_response(&pnf_test_config[1]);
// start the vnf_p7 thread and assign by phys to that instance
start_vnf_p7(&vnf_test_config[0].vnfs[0]);
//start_vnf_p7(&vnf_test_config[0].vnfs[1]);
printf("---- configuring phy %d -----\n", vnf_test_config[0].phys[0].phy_id);
vnf_test_config[0].phys[0].vnf_idx = 0;
start_phy(&vnf_test_config[0].phys[0]);
int phy_id = receive_param_request(&pnf_test_config[0]);
send_param_response(&pnf_test_config[0], phy_id);
phy_id = receive_config_request(&pnf_test_config[0]);
send_config_response(&pnf_test_config[0], phy_id);
printf("---- configuring phy %d -----\n", vnf_test_config[0].phys[2].phy_id);
vnf_test_config[0].phys[2].vnf_idx = 0;
start_phy(&vnf_test_config[0].phys[2]);
phy_id = receive_param_request(&pnf_test_config[1]);
send_param_response(&pnf_test_config[1], phy_id);
phy_id = receive_config_request(&pnf_test_config[1]);
send_config_response(&pnf_test_config[1], phy_id);
printf("---- configuring phy %d -----\n", vnf_test_config[0].phys[1].phy_id);
vnf_test_config[0].phys[1].vnf_idx = 0;
start_phy(&vnf_test_config[0].phys[1]);
phy_id = receive_param_request(&pnf_test_config[0]);
send_param_response(&pnf_test_config[0], phy_id);
phy_id = receive_config_request(&pnf_test_config[0]);
send_config_response(&pnf_test_config[0], phy_id);
//-------------
printf("---- starting phy %d -----\n", vnf_test_config[0].phys[0].phy_id);
send_vnf_start_req(&vnf_test_config[0], &vnf_test_config[0].phys[0]);
phy_id = receive_start_request(&pnf_test_config[0]);
send_start_response(&pnf_test_config[0], phy_id);
/*
printf("---- starting phy %d -----\n", vnf_test_config[0].phys[2].phy_id);
send_vnf_start_req(&vnf_test_config[0], &vnf_test_config[0].phys[2]);
phy_id = receive_start_request(&pnf_test_config[1]);
send_start_response(&pnf_test_config[1], phy_id);
printf("---- starting phy %d -----\n", vnf_test_config[0].phys[1].phy_id);
send_vnf_start_req(&vnf_test_config[0], &vnf_test_config[0].phys[1]);
phy_id = receive_start_request(&pnf_test_config[0]);
send_start_response(&pnf_test_config[0], phy_id);
*/
//close(pnf_test_config[0].p5_sock);
char buffer[2048];
int buffer_size = sizeof(buffer);
fd_set rdfs;
int exit = 0;
while(exit != 1)
{
int pnf_idx, phy_idx;
int max_fd = 0;
FD_ZERO(&rdfs);
for(pnf_idx = 0; pnf_idx < 4; ++pnf_idx)
{
if(pnf_test_config[pnf_idx].enabled)
{
FD_SET(pnf_test_config[pnf_idx].p5_sock, &rdfs);
if(pnf_test_config[pnf_idx].p5_sock > max_fd)
max_fd = pnf_test_config[pnf_idx].p5_sock;
}
for(phy_idx = 0; phy_idx < 4; ++phy_idx)
{
pnf_test_config_phy_t* phy_info = &(pnf_test_config[pnf_idx].phys[phy_idx]);
if(phy_info->started == 1 && phy_info->enabled == 1)
{
//////////////////printf("adding %d/%d %d %d\n", pnf_idx, phy_idx, phy_info->phy_id, phy_info->p7_rx_sock);
FD_SET(phy_info->p7_rx_sock, &rdfs);
if(phy_info->p7_rx_sock > max_fd)
max_fd = phy_info->p7_rx_sock;
}
}
}
// changed to select,
int select_result = select(max_fd + 1, &rdfs, NULL, NULL, NULL);
(void)select_result;
for(pnf_idx = 0; pnf_idx < 4; ++pnf_idx)
{
if(pnf_test_config[pnf_idx].enabled)
{
//pnf_test_config_t* pnf_config = &(pnf_test_config[pnf_idx]);
}
for(phy_idx = 0; phy_idx < 4; ++phy_idx)
{
pnf_test_config_phy_t* phy_info = &(pnf_test_config[pnf_idx].phys[phy_idx]);
if(phy_info->enabled)
{
if(FD_ISSET(phy_info->p7_rx_sock, &rdfs))
{
//struct sockaddr_in recv_addr;
//memset(&recv_addr, 0, sizeof(recv_addr));
//socklen_t recv_addr_size;
int len = recvfrom(phy_info->p7_rx_sock, &buffer[0], buffer_size, 0, 0, 0);// (struct sockaddr*)&recv_addr, &recv_addr_size);
if(len == -1)
{
printf("recvfrom %d failed %d\n", phy_info->p7_rx_sock, errno);
continue;
}
nfapi_p7_message_header_t header;
nfapi_p7_message_header_unpack(buffer, len, &header, sizeof(header), 0);
switch(header.message_id)
{
case NFAPI_DL_NODE_SYNC:
{
nfapi_dl_node_sync_t msg;
nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
printf("[PNF:%d] NFAPI_DL_NODE_SYNC t1:%d\n", msg.header.phy_id, msg.t1);
nfapi_ul_node_sync_t resp;
memset(&resp, 0, sizeof(resp));
resp.header.message_id = NFAPI_UL_NODE_SYNC;
resp.header.phy_id = msg.header.phy_id;
resp.t1 = msg.t1;
usleep(50);
resp.t2 = msg.t1 + 50; // 50 us rx latency
resp.t3 = msg.t1 + 10; // 10 us pnf proc
usleep(50);
len = nfapi_p7_message_pack(&resp, buffer, buffer_size, 0);
// send ul node sycn
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
}
break;
case NFAPI_DL_CONFIG_REQUEST:
{
nfapi_dl_config_request_t msg;
nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
//printf("[PNF:%d] (%d/%d) NFAPI_DL_CONFIG_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
if(SFNSF2SFN(msg.sfn_sf) == 500)
exit = 1;
// simulate the uplink messages
nfapi_harq_indication_t harq_ind;
memset(&harq_ind, 0, sizeof(harq_ind));
harq_ind.header.message_id = NFAPI_HARQ_INDICATION;
harq_ind.header.phy_id = msg.header.phy_id;
harq_ind.sfn_sf = msg.sfn_sf;
harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
harq_ind.harq_indication_body.number_of_harqs = 2;
harq_ind.harq_indication_body.harq_pdu_list = (nfapi_harq_indication_pdu_t*)(malloc(sizeof(nfapi_harq_indication_pdu_t) * harq_ind.harq_indication_body.number_of_harqs));
int i = 0;
for(i = 0; i < harq_ind.harq_indication_body.number_of_harqs; ++i)
{
harq_ind.harq_indication_body.harq_pdu_list[i].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
}
len = nfapi_p7_message_pack(&harq_ind, buffer, buffer_size, 0);
//sendto(phy_info->p7_tx_sock, &buffer[0], len, 0, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
//sendto(phy_info->p7_tx_sock, &buffer[0], len, 0, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
free(harq_ind.harq_indication_body.harq_pdu_list);
nfapi_crc_indication_t crc_ind;
memset(&crc_ind, 0, sizeof(crc_ind));
crc_ind.header.message_id = NFAPI_CRC_INDICATION;
crc_ind.header.phy_id = msg.header.phy_id;
crc_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&crc_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
nfapi_sr_indication_t sr_ind;
memset(&sr_ind, 0, sizeof(sr_ind));
sr_ind.header.message_id = NFAPI_RX_SR_INDICATION;
sr_ind.header.phy_id = msg.header.phy_id;
sr_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&sr_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
nfapi_cqi_indication_t cqi_ind;
memset(&cqi_ind, 0, sizeof(cqi_ind));
cqi_ind.header.message_id = NFAPI_RX_CQI_INDICATION;
cqi_ind.header.phy_id = msg.header.phy_id;
cqi_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&cqi_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
nfapi_rach_indication_t rach_ind;
memset(&rach_ind, 0, sizeof(rach_ind));
rach_ind.header.message_id = NFAPI_RACH_INDICATION;
rach_ind.header.phy_id = msg.header.phy_id;
rach_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&rach_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
nfapi_srs_indication_t srs_ind;
memset(&srs_ind, 0, sizeof(srs_ind));
srs_ind.header.message_id = NFAPI_SRS_INDICATION;
srs_ind.header.phy_id = msg.header.phy_id;
srs_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&srs_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
nfapi_rx_indication_t rx_ind;
memset(&rx_ind, 0, sizeof(rx_ind));
rx_ind.header.message_id = NFAPI_RX_ULSCH_INDICATION;
rx_ind.header.phy_id = msg.header.phy_id;
rx_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&rx_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
if(msg.sfn_sf % 5 == 0)
{
// periodically send the timing info
nfapi_timing_info_t timing_info;
memset(&timing_info, 0, sizeof(timing_info));
timing_info.header.message_id = NFAPI_TIMING_INFO;
timing_info.header.phy_id = msg.header.phy_id;
len = nfapi_p7_message_pack(&timing_info, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
}
nfapi_nb_harq_indication_t nb_harq_ind;
memset(&nb_harq_ind, 0, sizeof(nb_harq_ind));
nb_harq_ind.header.message_id = NFAPI_NB_HARQ_INDICATION;
nb_harq_ind.header.phy_id = msg.header.phy_id;
nb_harq_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&nb_harq_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
nfapi_nrach_indication_t nrach_ind;
memset(&nrach_ind, 0, sizeof(nrach_ind));
nrach_ind.header.message_id = NFAPI_NRACH_INDICATION;
nrach_ind.header.phy_id = msg.header.phy_id;
nrach_ind.sfn_sf = msg.sfn_sf;
len = nfapi_p7_message_pack(&nrach_ind, buffer, buffer_size, 0);
send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
}
break;
case NFAPI_UL_CONFIG_REQUEST:
{
nfapi_ul_config_request_t msg;
nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
//printf("[PNF:%d] (%d/%d) NFAPI_UL_CONFIG_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
}
break;
case NFAPI_HI_DCI0_REQUEST:
{
nfapi_hi_dci0_request_t msg;
nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
//printf("[PNF:%d] (%d/%d) NFAPI_HI_DCI0_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
}
break;
case NFAPI_TX_REQUEST:
{
nfapi_tx_request_t msg;
nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
//printf("[PNF:%d] (%d/%d) NFAPI_TX_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
}
break;
}
}
}
}
}
}
printf("Triggering p5 shutdown\n");
// vnf p5 trigger shutdown
nfapi_pnf_stop_request_t stop_req;
memset(&stop_req, 0, sizeof(stop_req));
stop_req.header.message_id = NFAPI_PNF_STOP_REQUEST;
nfapi_vnf_pnf_stop_req(vnf_test_config[0].p5_vnf_config, 0, &stop_req);
phy_id = receive_pnf_stop_request(&pnf_test_config[0]);
send_pnf_stop_response(&pnf_test_config[0], phy_id);
nfapi_vnf_stop(vnf_test_config[0].p5_vnf_config);
int* result;
pthread_join((vnf_test_config[0].thread), (void**)&result);
CU_ASSERT_EQUAL(result, 0);
//CU_ASSERT_EQUAL(pnf_connection_indication_called, 1);
close(pnf_test_config[0].p5_sock);
}
void vnf_test_start_connect_ipv6(void)
{
char* vnf_addr = "::1";
int vnf_port = 4242;
pnf_connection_indication_called = 0;
nfapi_vnf_config_t* config = nfapi_vnf_config_create();
config->vnf_p5_port = vnf_port;
config->vnf_ipv4 = 0;
config->vnf_ipv6 = 1;
config->pnf_connection_indication = &pnf_connection_indication;
config->pnf_disconnect_indication = &pnf_disconnect_indication;
config->pnf_param_resp = &pnf_param_response;
config->pnf_config_resp = &pnf_config_response;
config->pnf_start_resp = &pnf_start_response;
pthread_t thread;
pthread_create(&thread, NULL, &vnf_test_start_thread, config);
sleep(1);
int p5Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
struct sockaddr_in6 addr;
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(vnf_port);
//addr.sin6_addr = inet_addr(vnf_addr);
inet_pton(AF_INET6, vnf_addr, &addr.sin6_addr);
/*
int connect_result = connect(p5Sock, (struct sockaddr *)&addr, sizeof(addr) );
printf("connect_result %d %d\n", connect_result, errno);
receive_pnf_param_request(p5Sock);
send_pnf_param_response(p5Sock, &addr, sizeof(addr));
receive_pnf_config_request(p5Sock);
send_pnf_config_response(p5Sock, &addr, sizeof(addr));
receive_pnf_start_request(p5Sock);
send_pnf_start_response(p5Sock, &addr, sizeof(addr));
*/
sleep(4);
nfapi_vnf_stop(config);
int* result;
pthread_join(thread, (void**)&result);
CU_ASSERT_EQUAL(result, 0);
CU_ASSERT_EQUAL(pnf_connection_indication_called, 1);
close(p5Sock);
}
void vnf_test_start_connect_2(void)
{
char* vnf_addr = "127.0.0.1";
int vnf_port = 4242;
pnf_connection_indication_called = 0;
nfapi_vnf_config_t * config = nfapi_vnf_config_create();
config->vnf_p5_port = vnf_port;
config->pnf_connection_indication = &pnf_connection_indication;
pthread_t thread;
pthread_create(&thread, NULL, &vnf_test_start_thread, config);
sleep(1);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(vnf_port);
addr.sin_addr.s_addr = inet_addr(vnf_addr);
int p5Sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
int connect_result_1 = connect(p5Sock1, (struct sockaddr *)&addr, sizeof(addr) );
printf("connect_result_1 %d %d\n", connect_result_1, errno);
int p5Sock2 = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
int connect_result_2 = connect(p5Sock2, (struct sockaddr *)&addr, sizeof(addr) );
printf("connect_result_2 %d %d\n", connect_result_2, errno);
sleep(1);
close(p5Sock1);
sleep(1);
close(p5Sock2);
sleep(1);
nfapi_vnf_stop(config);
int* result;
pthread_join(thread, (void**)&result);
CU_ASSERT_EQUAL(result, 0);
CU_ASSERT_EQUAL(pnf_connection_indication_called, 2);
close(p5Sock1);
close(p5Sock2);
}
void vnf_test_p7_segmentation_test1(void)
{
}
/************* Test Runner Code goes here **************/
int main ( void )
{
CU_pSuite pSuite = NULL;
/* initialize the CUnit test registry */
if ( CUE_SUCCESS != CU_initialize_registry() )
return CU_get_error();
/* add a suite to the registry */
pSuite = CU_add_suite( "vnf_test_suite", init_suite, clean_suite );
if ( NULL == pSuite )
{
CU_cleanup_registry();
return CU_get_error();
}
//(NULL == CU_add_test(pSuite, "vnf_test_start_connect_2", vnf_test_start_connect_2))
/* add the tests to the suite */
if ( (NULL == CU_add_test(pSuite, "vnf_test_start_no_config", vnf_test_start_no_config)) ||
(NULL == CU_add_test(pSuite, "vnf_test_start_connect", vnf_test_start_connect)) ||
(NULL == CU_add_test(pSuite, "vnf_test_p7_segmentation_test1", vnf_test_p7_segmentation_test1))
)
{
CU_cleanup_registry();
return CU_get_error();
}
// Run all tests using the basic interface
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_set_output_filename("vnf_unit_test_results.xml");
CU_basic_run_tests();
CU_pSuite s = CU_get_registry()->pSuite;
int count = 0;
while(s)
{
CU_pTest t = s->pTest;
while(t)
{
count++;
t = t->pNext;
}
s = s->pNext;
}
printf("%d..%d\n", 1, count);
s = CU_get_registry()->pSuite;
count = 1;
while(s)
{
CU_pTest t = s->pTest;
while(t)
{
int pass = 1;
CU_FailureRecord* failures = CU_get_failure_list();
while(failures)
{
if(strcmp(failures->pSuite->pName, s->pName) == 0 &&
strcmp(failures->pTest->pName, t->pName) == 0)
{
pass = 0;
failures = 0;
}
else
{
failures = failures->pNext;
}
}
if(pass)
printf("ok %d - %s:%s\n", count, s->pName, t->pName);
else
printf("not ok %d - %s:%s\n", count, s->pName, t->pName);
count++;
t = t->pNext;
}
s = s->pNext;
}
CU_cleanup_registry();
return CU_get_error();
}