LTE and NR NFAPI integration

This commit is contained in:
Mahesh
2020-11-11 15:10:32 +05:30
parent 643fc632d6
commit e6bf90e2dd
35 changed files with 5371 additions and 454 deletions
+349 -20
View File
@@ -102,7 +102,7 @@ nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5
return 0;
}
/*
void vnf_nr_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
@@ -135,7 +135,7 @@ void vnf_nr_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_
config->codec_config.deallocate(msg.vendor_extension);
}
}
*/
void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
@@ -169,6 +169,40 @@ void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_con
}
}
void vnf_nr_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
if (pRecvMsg == NULL || config == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_CONFIG_RESPONSE\n");
nfapi_nr_pnf_config_response_t msg;
// unpack the message
if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
{
// Invoke the call back
if(config->pnf_nr_config_resp)
{
(config->pnf_nr_config_resp)(config, p5_idx, &msg);
}
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
}
// make sure to release any dyanmic part of the message
if(msg.vendor_extension)
config->codec_config.deallocate(msg.vendor_extension);
}
}
void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
@@ -202,6 +236,38 @@ void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_co
}
}
void vnf_nr_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
if (pRecvMsg == NULL || config == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_START_RESPONSE\n");
nfapi_nr_pnf_start_response_t msg;
// unpack the message
if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
{
if(config->pnf_nr_start_resp)
{
(config->pnf_nr_start_resp)(config, p5_idx, &msg);
}
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
}
// make sure to release any dyanmic part of the message
if(msg.vendor_extension)
config->codec_config.deallocate(msg.vendor_extension);
}
}
void vnf_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
@@ -279,7 +345,7 @@ void vnf_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PARAM_RESPONSE\n");
nfapi_nr_param_response_scf_t msg;
nfapi_param_response_t msg;
// unpack the message
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
@@ -333,6 +399,110 @@ void vnf_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_
}
}
void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
if (pRecvMsg == NULL || config == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PARAM_RESPONSE\n");
nfapi_nr_param_response_scf_t msg;
// unpack the message
if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
{
if (msg.error_code == NFAPI_MSG_OK)
{
nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id);
if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag)
{
struct sockaddr_in sockAddr;
(void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH);
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr));
// store address
phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr;
}
if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag)
{
struct sockaddr_in6 sockAddr6;
char addr6[64];
(void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH);
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6)));
}
if (msg.nfapi_config.p7_pnf_port.tl.tag)
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value);
// store port
phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value);
}
}
if(config->nr_param_resp)
{
(config->nr_param_resp)(config, p5_idx, &msg);
}
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
}
// make sure to release any dyanmic part of the message
if(msg.vendor_extension)
config->codec_config.deallocate(msg.vendor_extension);
}
}
void vnf_nr_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
if (pRecvMsg == NULL || config == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CONFIG_RESPONSE\n");
nfapi_nr_config_response_scf_t msg;
// unpack the message
if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 )
{
// check the error code:
if (msg.error_code == NFAPI_MSG_OK){
if(config->nr_config_resp)
{
(config->nr_config_resp)(config, p5_idx, &msg);
}
}
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
}
// make sure to release any dyanmic part of the message
if(msg.vendor_extension)
config->codec_config.deallocate(msg.vendor_extension);
}
}
void vnf_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
@@ -381,15 +551,47 @@ void vnf_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received START_RESPONSE\n");
nfapi_nr_start_response_scf_t msg;
nfapi_start_response_t msg;
// unpack the message
if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
{
if(config->start_resp)
{
(config->start_resp)(config, p5_idx, &msg);
}
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
}
// make sure to release any dyanmic part of the message
if(msg.vendor_extension)
config->codec_config.deallocate(msg.vendor_extension);
}
}
void vnf_nr_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
{
// ensure it's valid
if (pRecvMsg == NULL || config == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received START_RESPONSE\n");
nfapi_nr_start_response_scf_t msg;
// unpack the message
if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
{ // check the error code
if (msg.error_code == NFAPI_MSG_OK){
if(config->start_resp)
if(config->nr_start_resp)
{
(config->start_resp)(config, p5_idx, &msg);
(config->nr_start_resp)(config, p5_idx, &msg);
}
}
}
@@ -853,7 +1055,6 @@ void vnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, nfapi_vnf_confi
}
}
#if 0
void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config)
{
nfapi_p4_p5_message_header_t messageHeader;
@@ -874,32 +1075,32 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa
switch (messageHeader.message_id)
{
case NFAPI_PNF_PARAM_RESPONSE:
case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE:
vnf_nr_handle_pnf_param_response(pRecvMsg, recvMsgLen, config, p5_idx);
break;
case NFAPI_PNF_CONFIG_RESPONSE:
vnf_handle_pnf_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE:
vnf_nr_handle_pnf_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
break;
case NFAPI_PNF_START_RESPONSE:
vnf_handle_pnf_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE:
vnf_nr_handle_pnf_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
break;
case NFAPI_PNF_STOP_RESPONSE:
vnf_handle_pnf_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
break;
case NFAPI_PARAM_RESPONSE:
vnf_handle_param_response(pRecvMsg, recvMsgLen, config, p5_idx);
case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
vnf_nr_handle_param_response(pRecvMsg, recvMsgLen, config, p5_idx);
break;
case NFAPI_CONFIG_RESPONSE:
vnf_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
vnf_nr_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
break;
case NFAPI_START_RESPONSE:
vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
vnf_nr_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
break;
case NFAPI_STOP_RESPONSE:
@@ -969,7 +1170,7 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa
break;
}
}
#endif
void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config)
{
nfapi_p4_p5_message_header_t messageHeader;
@@ -1086,6 +1287,136 @@ void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_
}
}
int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf)
{
if(1)
{
int socket_connected = 1;
// 1. Peek the message header
// 2. If the message is larger than the stack buffer then create a dynamic buffer
// 3. Read the buffer
// 4. Handle the p5 message
uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
uint8_t header_buffer[header_buffer_size];
uint32_t stack_buffer_size = 32; //should it be the size of then sctp_notificatoin structure
uint8_t stack_buffer[stack_buffer_size];
uint8_t* dynamic_buffer = 0;
uint8_t* read_buffer = &stack_buffer[0];
uint32_t message_size = 0;
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
struct sctp_sndrcvinfo sndrcvinfo;
(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
{
int flags = MSG_PEEK;
message_size = sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags);
if(message_size == -1)
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno);
return 0;
}
nfapi_p4_p5_message_header_t header;
int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0);
if(unpack_result < 0)
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header %d\n", unpack_result);
return 0;
}
message_size = header.message_length;
// now have the size of the mesage
}
if(message_size > stack_buffer_size)
{
dynamic_buffer = (uint8_t*)malloc(message_size);
if(dynamic_buffer == NULL)
{
// todo : add error mesage
NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size);
return -1;
}
read_buffer = dynamic_buffer;
}
{
int flags = 0;
(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags);
if(recvmsg_result == -1)
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno);
}
else
{
if (flags & MSG_NOTIFICATION)
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
// todo - handle the events
}
else
{
/*
NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n",
pnf->p5_sock,
inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port),
sndrcvinfo.sinfo_assoc_id,
sndrcvinfo.sinfo_stream,
ntohl(sndrcvinfo.sinfo_ppid),
message_size,
flags);
*/
// handle now if complete message in one or more segments
if ((flags & 0x80) == 0x80)
{
printf("\nVNF RECEIVES:\n");
for(int i=0; i<message_size; i++){
printf("%d", read_buffer[i]);
}
printf("\n");
vnf_nr_handle_p4_p5_message(read_buffer, message_size, pnf->p5_idx, config);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags);
// assume socket disconnected
NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n");
socket_connected = 0;
}
}
}
}
if(dynamic_buffer)
{
free(dynamic_buffer);
}
return socket_connected;
}
}
int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf)
{
if(1)
@@ -1243,7 +1574,6 @@ static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len,
return 0;
}
/*
int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len)
{
nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx);
@@ -1266,7 +1596,6 @@ int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_mes
return -1;
}
}
*/
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)
+90 -14
View File
@@ -62,7 +62,7 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config)
{
free(config);
}
#if 0
int nfapi_nr_vnf_start(nfapi_vnf_config_t* config)
{
// Verify that config is not null
@@ -390,7 +390,7 @@ int nfapi_nr_vnf_start(nfapi_vnf_config_t* config)
{
if(FD_ISSET(pnf->p5_sock, &read_fd_set))
{
if(vnf_read_dispatch_message(config, pnf) == 0)
if(vnf_nr_read_dispatch_message(config, pnf) == 0)
{
if(config->pnf_disconnect_indication != 0)
{
@@ -474,7 +474,7 @@ int nfapi_nr_vnf_start(nfapi_vnf_config_t* config)
return 0;
}
#endif
int nfapi_vnf_start(nfapi_vnf_config_t* config)
{
// Verify that config is not null
@@ -898,15 +898,15 @@ int nfapi_vnf_stop(nfapi_vnf_config_t* config)
return 0;
}
// int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_request_t* req)
// {
// if(config == 0 || req == 0)
// return -1;
int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_request_t* req)
{
if(config == 0 || req == 0)
return -1;
// vnf_t* _this = (vnf_t*)(config);
vnf_t* _this = (vnf_t*)(config);
// return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t));
// }
return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t));
}
int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req)
{
@@ -918,6 +918,17 @@ int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_pa
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_param_request_t));
}
int nfapi_nr_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_config_request_t* req)
{
if(config == 0 || req == 0)
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_config_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)
@@ -938,6 +949,16 @@ int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_st
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_start_request_t));
}
int nfapi_nr_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_request_t* req)
{
if(config == 0 || req == 0)
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_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)
@@ -948,6 +969,16 @@ int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_sto
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_stop_request_t));
}
int nfapi_nr_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_param_request_scf_t* req)
{
if(config == 0 || req == 0)
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_param_request_scf_t));
}
int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req)
{
if(config == 0 || req == 0)
@@ -957,7 +988,8 @@ int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_requ
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_nr_config_request_scf_t* req)
int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config_request_scf_t* req)
{
if(config == 0 || req == 0)
return -1;
@@ -985,17 +1017,61 @@ int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config
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_nr_config_request_scf_t));
return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t));
}
int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_request_scf_t * req)
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);
return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t));
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_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_request_scf_t * req)
{
if(config == 0 || req == 0)
return -1;
vnf_t* _this = (vnf_t*)(config);
return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t));
}
int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req)
{
if(config == 0 || req == 0)
+848 -20
View File
@@ -299,7 +299,7 @@ struct timespec timespec_delta(struct timespec start, struct timespec end)
return temp;
}
/*static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr)
static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr)
{
if(now_hr < sf_start_hr)
{
@@ -319,7 +319,7 @@ struct timespec timespec_delta(struct timespec start, struct timespec end)
return now_us - sf_start_us;
}
}*/
}
static uint32_t get_slot_time(uint32_t now_hr, uint32_t slot_start_hr)
{
@@ -343,7 +343,7 @@ static uint32_t get_slot_time(uint32_t now_hr, uint32_t slot_start_hr)
}
}
/*uint32_t calculate_t1(uint16_t sfn_sf, uint32_t sf_start_time_hr)
uint32_t calculate_t1(uint16_t sfn_sf, uint32_t sf_start_time_hr)
{
uint32_t now_time_hr = vnf_get_current_time_hr();
@@ -352,9 +352,9 @@ static uint32_t get_slot_time(uint32_t now_hr, uint32_t slot_start_hr)
uint32_t t1 = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us;
return t1;
}*/
}
uint32_t calculate_t1(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr)
uint32_t calculate_nr_t1(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr)
{
uint32_t now_time_hr = vnf_get_current_time_hr();
@@ -366,7 +366,7 @@ uint32_t calculate_t1(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr)
}
/*uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_time_hr)
uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_time_hr)
{
uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr);
@@ -374,9 +374,9 @@ uint32_t calculate_t1(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr)
return t4;
}*/
}
uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr)
uint32_t calculate_nr_t4(uint32_t now_time_hr, uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr)
{
uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr);
@@ -465,6 +465,100 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u
return 0;
}
int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header)
{
nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id);
if(p7_connection)
{
int send_result = 0;
uint8_t buffer[1024 * 32];
header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, p7_connection->sequence_number);
int len = nfapi_nr_p7_message_pack(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config);
//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size);
if(len < 0)
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id);
return -1;
}
if(len > vnf_p7->_public.segment_size)
{
// todo : consider replacing with the sendmmsg call
// todo : worry about blocking writes?
// segmenting the transmit
int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ;
int seg_body_len = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ;
int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0);
int segment = 0;
int offset = NFAPI_P7_HEADER_LENGTH;
uint8_t tx_buffer[vnf_p7->_public.segment_size];
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size);
for(segment = 0; segment < segment_count; ++segment)
{
uint8_t last = 0;
uint16_t size = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH;
if(segment + 1 == segment_count)
{
last = 1;
size = (msg_body_len) - (seg_body_len * segment);
}
uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH;
// Update the header with the m and segement
memcpy(&tx_buffer[0], buffer, NFAPI_P7_HEADER_LENGTH);
// set the segment length
tx_buffer[4] = (segment_size & 0xFF00) >> 8;
tx_buffer[5] = (segment_size & 0xFF);
// set the m & segment number
tx_buffer[6] = ((!last) << 7) + segment;
memcpy(&tx_buffer[NFAPI_P7_HEADER_LENGTH], &buffer[0] + offset, size);
offset += size;
if(vnf_p7->_public.checksum_enabled)
{
nfapi_p7_update_checksum(tx_buffer, segment_size);
}
nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr));
send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size);
}
}
else
{
if(vnf_p7->_public.checksum_enabled)
{
nfapi_p7_update_checksum(buffer, len);
}
nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr));
// simple case that the message fits in a single segement
send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len);
}
p7_connection->sequence_number++;
return send_result;
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id);
return -1;
}
}
int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header)
{
@@ -558,23 +652,35 @@ int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* hea
return -1;
}
}
int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
{
{
nfapi_dl_node_sync_t dl_node_sync;
memset(&dl_node_sync, 0, sizeof(dl_node_sync));
dl_node_sync.header.phy_id = p7_info->phy_id;
dl_node_sync.header.message_id = NFAPI_DL_NODE_SYNC;
//dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr);
dl_node_sync.t1 = calculate_t1(p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr);
dl_node_sync.delta_sfn_slot = 0;
dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr);
dl_node_sync.delta_sfn_sf = 0;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header);
}
int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
{
nfapi_nr_dl_node_sync_t dl_node_sync;
memset(&dl_node_sync, 0, sizeof(dl_node_sync));
dl_node_sync.header.phy_id = p7_info->phy_id;
dl_node_sync.header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC;
//dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr);
dl_node_sync.t1 = calculate_nr_t1(p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr);
dl_node_sync.delta_sfn_slot = 0;
return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header);
}
int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
{
if(p7_info->in_sync == 1)
@@ -586,7 +692,7 @@ int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
//if ((((sfn_sf_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0)
if ((((sfn_slot_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSLOTDEC) & dl_sync_period_mask) == 0)
{
vnf_build_send_dl_node_sync(vnf_p7, p7_info);
vnf_nr_build_send_dl_node_sync(vnf_p7, p7_info);
}
}
else
@@ -597,6 +703,33 @@ int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
//if ((((sfn_sf_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0)
if ((((sfn_slot_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSLOTDEC) & dl_sync_period_mask) == 0)
{
vnf_nr_build_send_dl_node_sync(vnf_p7, p7_info);
}
}
return 0;
}
int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
{
if(p7_info->in_sync == 1)
{
uint16_t dl_sync_period_mask = p7_info->dl_in_sync_period-1;
uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf);
if ((((sfn_sf_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0)
{
vnf_build_send_dl_node_sync(vnf_p7, p7_info);
}
}
else
{
uint16_t dl_sync_period_mask = p7_info->dl_out_sync_period-1;
uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf);
if ((((sfn_sf_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0)
{
vnf_build_send_dl_node_sync(vnf_p7, p7_info);
}
@@ -949,9 +1082,7 @@ void vnf_handle_p7_vendor_extension(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vn
void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
{
//printf("received UL Node sync");
{
uint32_t now_time_hr = vnf_get_current_time_hr();
if (pRecvMsg == NULL || vnf_p7 == NULL)
@@ -970,7 +1101,382 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
//NFAPI_TRACE(NFAPI_TRACE_INFO, "Received UL_NODE_SYNC phy_id:%d t1:%d t2:%d t3:%d\n", ind.header.phy_id, ind.t1, ind.t2, ind.t3);
nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, ind.header.phy_id);
uint32_t t4 = calculate_t4(now_time_hr, phy->sfn, phy->slot, vnf_p7->slot_start_time_hr);
uint32_t t4 = calculate_t4(now_time_hr, phy->sfn_sf, vnf_p7->sf_start_time_hr);
uint32_t tx_2_rx = t4>ind.t1 ? t4 - ind.t1 : t4 + NFAPI_MAX_SFNSFDEC - ind.t1 ;
uint32_t pnf_proc_time = ind.t3 - ind.t2;
// divide by 2 using shift operator
uint32_t latency = (tx_2_rx - pnf_proc_time) >> 1;
if(!(phy->filtered_adjust))
{
phy->latency[phy->min_sync_cycle_count] = latency;
NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n",
NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4,
tx_2_rx, pnf_proc_time, latency);
}
else
{
phy->latency[phy->min_sync_cycle_count] = latency;
//if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT)
{
if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1)
{
// Only t2 wrap has occurred!!!
phy->sf_offset = (NFAPI_MAX_SFNSFDEC + ind.t2) - ind.t1 - latency;
}
else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1)
{
// Only t1 wrap has occurred
phy->sf_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSFDEC) - latency;
}
else
{
// Either no wrap or both have wrapped
phy->sf_offset = ind.t2 - ind.t1 - latency;
}
if (phy->sf_offset_filtered == 0)
{
phy->sf_offset_filtered = phy->sf_offset;
}
else
{
int32_t oldFilteredValueShifted = phy->sf_offset_filtered << 5;
int32_t newOffsetShifted = phy->sf_offset << 5;
// 1/8 of new and 7/8 of old
phy->sf_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5;
}
}
if(1)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n",
NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ts.tv_sec, ts.tv_nsec, ind.header.phy_id,
ind.t1, ind.t2, ind.t3, t4,
tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->sf_offset, phy->sf_offset_filtered,
(ind.t1<phy->previous_t1), (ind.t2<phy->previous_t2));
}
}
if (phy->filtered_adjust && (phy->sf_offset_filtered > 1e6 || phy->sf_offset_filtered < -1e6))
{
phy->filtered_adjust = 0;
phy->zero_count=0;
phy->min_sync_cycle_count = 2;
phy->in_sync = 0;
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->sf_offset_filtered:%d\n", __FUNCTION__, phy->sf_offset_filtered);
}
if(phy->min_sync_cycle_count)
phy->min_sync_cycle_count--;
if(phy->min_sync_cycle_count == 0)
{
uint32_t curr_sfn_sf = phy->sfn_sf;
int32_t sfn_sf_dec = NFAPI_SFNSF2DEC(phy->sfn_sf);
if(!phy->filtered_adjust)
{
int i = 0;
//phy->average_latency = 0;
for(i = 0; i < SYNC_CYCLE_COUNT; ++i)
{
phy->average_latency += phy->latency[i];
}
phy->average_latency /= SYNC_CYCLE_COUNT;
phy->sf_offset = ind.t2 - (ind.t1 - phy->average_latency);
sfn_sf_dec += (phy->sf_offset / 1000);
}
else
{
sfn_sf_dec += ((phy->sf_offset_filtered + 500) / 1000); //Round up go from microsecond to subframe(1ms)
}
if(sfn_sf_dec < 0)
{
sfn_sf_dec += NFAPI_MAX_SFNSFDEC;
}
else if( sfn_sf_dec >= NFAPI_MAX_SFNSFDEC)
{
sfn_sf_dec -= NFAPI_MAX_SFNSFDEC;
}
uint16_t new_sfn_sf = NFAPI_SFNSFDEC2SFNSF(sfn_sf_dec);
{
phy->adjustment = NFAPI_SFNSF2DEC(new_sfn_sf) - NFAPI_SFNSF2DEC(curr_sfn_sf);
NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_sf_offset_filtered:%d phy->previous_sf_offset_filtered:%d phy->sf_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_sf_offset_filtered, phy->previous_sf_offset_filtered, phy->sf_offset_trend);
phy->previous_t1 = 0;
phy->previous_t2 = 0;
if(phy->previous_sf_offset_filtered > 0)
{
if( phy->sf_offset_filtered > phy->previous_sf_offset_filtered)
{
// pnf is getting futher ahead of vnf
//phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered;
phy->sf_offset_trend = (phy->sf_offset_filtered + phy->previous_sf_offset_filtered)/2;
}
else
{
// pnf is getting back in sync
}
}
else if(phy->previous_sf_offset_filtered < 0)
{
if(phy->sf_offset_filtered < phy->previous_sf_offset_filtered)
{
// vnf is getting future ahead of pnf
//phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered);
phy->sf_offset_trend = (-(phy->sf_offset_filtered + phy->previous_sf_offset_filtered)) /2;
}
else
{
// vnf is getting back in sync
}
}
int insync_minor_adjustment_1 = phy->sf_offset_trend / 6;
int insync_minor_adjustment_2 = phy->sf_offset_trend / 2;
if(insync_minor_adjustment_1 == 0)
insync_minor_adjustment_1 = 2;
if(insync_minor_adjustment_2 == 0)
insync_minor_adjustment_2 = 10;
if(!phy->filtered_adjust)
{
if(phy->adjustment < 10)
{
phy->zero_count++;
if(phy->zero_count >= 10)
{
phy->filtered_adjust = 1;
phy->zero_count = 0;
NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n");
}
}
else
{
phy->zero_count = 0;
}
}
else
{
// Fine level of adjustment
if (phy->adjustment == 0)
{
if (phy->zero_count >= 10)
{
if(phy->in_sync == 0)
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id);
if(vnf_p7->_public.sync_indication)
(vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1);
}
phy->in_sync = 1;
}
else
{
phy->zero_count++;
}
if(phy->in_sync)
{
// in sync
if(phy->sf_offset_filtered > 250)
{
// VNF is slow
phy->insync_minor_adjustment = insync_minor_adjustment_1; //25;
phy->insync_minor_adjustment_duration = ((phy->sf_offset_filtered) / insync_minor_adjustment_1);
}
else if(phy->sf_offset_filtered < -250)
{
// VNF is fast
phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25;
phy->insync_minor_adjustment_duration = (((phy->sf_offset_filtered) / -(insync_minor_adjustment_1)));
}
else
{
phy->insync_minor_adjustment = 0;
}
if(phy->insync_minor_adjustment != 0)
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d subframes (sf_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n",
NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id,
phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration,
phy->sf_offset_filtered,
insync_minor_adjustment_1, insync_minor_adjustment_2, phy->sf_offset_trend,
NFAPI_SFNSF2DEC(new_sfn_sf),
NFAPI_SFNSF2DEC(curr_sfn_sf),
phy->adjustment);
}
}
}
else
{
if (phy->in_sync)
{
if(phy->adjustment == 0)
{
}
else if(phy->adjustment > 0)
{
// VNF is slow
//if(phy->adjustment == 1)
{
//
if(phy->sf_offset_filtered > 250)
{
// VNF is slow
phy->insync_minor_adjustment = insync_minor_adjustment_2;
phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered - 250) / insync_minor_adjustment_2);
}
else if(phy->sf_offset_filtered < -250)
{
// VNF is fast
phy->insync_minor_adjustment = -(insync_minor_adjustment_2);
phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered + 250) / -(insync_minor_adjustment_2));
}
}
//else
{
// out of sync?
}
NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d subframes (adjustment:%d sf_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n",
NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id,
phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->sf_offset_filtered,
insync_minor_adjustment_1, insync_minor_adjustment_2, phy->sf_offset_trend,
NFAPI_SFNSF2DEC(new_sfn_sf),
NFAPI_SFNSF2DEC(curr_sfn_sf),
phy->adjustment);
}
else if(phy->adjustment < 0)
{
// VNF is fast
//if(phy->adjustment == -1)
{
//
if(phy->sf_offset_filtered > 250)
{
// VNF is slow
phy->insync_minor_adjustment = insync_minor_adjustment_2;
phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered - 250) / insync_minor_adjustment_2);
}
else if(phy->sf_offset_filtered < -250)
{
// VNF is fast
phy->insync_minor_adjustment = -(insync_minor_adjustment_2);
phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered + 250) / -(insync_minor_adjustment_2));
}
}
//else
{
// out of sync?
}
NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d subframes (adjustment:%d sf_offset_filtered:%d) %d %d %d\n",
NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id,
phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->sf_offset_filtered,
insync_minor_adjustment_1, insync_minor_adjustment_2, phy->sf_offset_trend);
}
/*
if (phy->adjustment > 10 || phy->adjustment < -10)
{
phy->zero_count++; // Add one to the getting out of sync counter
}
else
{
phy->zero_count = 0; // Small error - zero the out of sync counter
}
if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n");
//pP7SockInfo->syncAchieved = 0;
}
*/
}
}
}
if(phy->in_sync == 0)
{
/*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n",
ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"),
NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment,
phy->filtered_adjust ? "FILTERED" : "ABSOLUTE",
phy->zero_count,
phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/
phy->sfn_sf = new_sfn_sf;
}
}
// reset for next cycle
phy->previous_sf_offset_filtered = phy->sf_offset_filtered;
phy->min_sync_cycle_count = 2;
phy->sf_offset_filtered = 0;
phy->sf_offset = 0;
}
else
{
phy->previous_t1 = ind.t1;
phy->previous_t2 = ind.t2;
}
}
void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
{
//printf("received UL Node sync");
uint32_t now_time_hr = vnf_get_current_time_hr();
if (pRecvMsg == NULL || vnf_p7 == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_ul_node_sync: NULL parameters\n");
return;
}
nfapi_nr_ul_node_sync_t ind;
if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_nr_ul_node_sync_t), &vnf_p7->_public.codec_config) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_node_sync\n");
return;
}
//NFAPI_TRACE(NFAPI_TRACE_INFO, "Received UL_NODE_SYNC phy_id:%d t1:%d t2:%d t3:%d\n", ind.header.phy_id, ind.t1, ind.t2, ind.t3);
nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, ind.header.phy_id);
uint32_t t4 = calculate_nr_t4(now_time_hr, phy->sfn, phy->slot, vnf_p7->slot_start_time_hr);
uint32_t tx_2_rx = t4>ind.t1 ? t4 - ind.t1 : t4 + NFAPI_MAX_SFNSLOTDEC - ind.t1 ; //time taken to receive ul node sync - time taken to send dl node sync
uint32_t pnf_proc_time = ind.t3 - ind.t2;
@@ -1346,6 +1852,39 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
return;
}
if (vnf_p7 && vnf_p7->p7_connections)
{
int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf);
//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta);
// Panos: Careful here!!! Modification of the original nfapi-code
//if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1)
if (vnf_pnf_sfnsf_delta>0 || vnf_pnf_sfnsf_delta < 0)
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnsf_delta, NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), NFAPI_SFNSF2DEC(ind.last_sfn_sf));
// Panos: Careful here!!! Modification of the original nfapi-code
vnf_p7->p7_connections[0].sfn_sf = ind.last_sfn_sf;
}
}
}
void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
{
if (pRecvMsg == NULL || vnf_p7 == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n");
return;
}
nfapi_nr_timing_info_t ind;
if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack timing_info\n");
return;
}
if (vnf_p7 && vnf_p7->p7_connections)
{
//int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf);
@@ -1460,6 +1999,101 @@ void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
}
}
void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
{
nfapi_p7_message_header_t header;
// validate the input params
if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
return;
}
// unpack the message header
if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
return;
}
// ensure the message is sensible
if (recvMsgLen < 8 || pRecvMsg == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen);
return;
}
switch (header.message_id)
{
case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC:
vnf_nr_handle_ul_node_sync(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_TIMING_INFO:
vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_HARQ_INDICATION:
vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_CRC_INDICATION:
vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_RX_ULSCH_INDICATION:
vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_RACH_INDICATION:
vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_SRS_INDICATION:
vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_RX_SR_INDICATION:
vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_RX_CQI_INDICATION:
vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_LBT_DL_INDICATION:
vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_NB_HARQ_INDICATION:
vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_NRACH_INDICATION:
vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7);
break;
case NFAPI_UE_RELEASE_RESPONSE:
vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7);
break;
default:
{
if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
{
vnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, vnf_p7, header.message_id);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Unknown message ID %d\n", header.message_id);
}
}
break;
}
}
void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
{
nfapi_p7_message_header_t messageHeader;
@@ -1578,6 +2212,200 @@ void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
}
}
void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
{
nfapi_p7_message_header_t messageHeader;
// validate the input params
if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%d %d %d)\n", pRecvMsg, recvMsgLen, vnf_p7);
return;
}
// unpack the message header
if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &vnf_p7->_public.codec_config) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
return;
}
if(vnf_p7->_public.checksum_enabled)
{
uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen);
if(checksum != messageHeader.checksum)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d msg:%d len:%d\n", checksum, messageHeader.checksum, messageHeader.message_id, recvMsgLen);
return;
}
}
uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence);
uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence);
uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence);
if(m == 0 && segment_num == 0)
{
// we have a complete message
// ensure the message is sensible
if (recvMsgLen < 8 || pRecvMsg == NULL)
{
NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen);
return;
}
//vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7);
vnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, vnf_p7);
}
else
{
nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id);
if(phy)
{
vnf_p7_rx_message_t* rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, &(phy->reassembly_queue), sequence_num, segment_num, m, pRecvMsg, recvMsgLen);
if(rx_msg->num_segments_received == rx_msg->num_segments_expected)
{
// send the buffer on
uint16_t i = 0;
uint16_t length = 0;
for(i = 0; i < rx_msg->num_segments_expected; ++i)
{
length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0);
}
if(phy->reassembly_buffer_size < length)
{
vnf_p7_free(vnf_p7, phy->reassembly_buffer);
phy->reassembly_buffer = 0;
}
if(phy->reassembly_buffer == 0)
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length);
phy->reassembly_buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, length);
if(phy->reassembly_buffer == 0)
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length);
return;
}
memset(phy->reassembly_buffer, 0, length);
phy->reassembly_buffer_size = length;
}
uint16_t offset = 0;
for(i = 0; i < rx_msg->num_segments_expected; ++i)
{
if(i == 0)
{
memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length);
offset += rx_msg->segments[i].length;
}
else
{
memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH);
offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH;
}
}
//pnf_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time);
vnf_nr_dispatch_p7_message(phy->reassembly_buffer, length , vnf_p7);
// delete the structure
vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg);
}
vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 1000);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id);
}
}
}
int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7)
{
int recvfrom_result = 0;
struct sockaddr_in remote_addr;
socklen_t remote_addr_size = sizeof(remote_addr);
do
{
// peek the header
uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH];
recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size);
if(recvfrom_result > 0)
{
// get the segment size
nfapi_p7_message_header_t header;
if(nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
return -1;
}
// resize the buffer if we have a large segment
if(header.message_length > vnf_p7->rx_message_buffer_size)
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length);
vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length);
vnf_p7->rx_message_buffer_size = header.message_length;
}
// read the segment
recvfrom_result = recvfrom(vnf_p7->socket, vnf_p7->rx_message_buffer, header.message_length, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size);
// todo : how to handle incomplete readfroms, need some sort of buffer/select
if(recvfrom_result == 0)
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom returned 0\n");
}
else if(recvfrom_result != header.message_length)
{
NFAPI_TRACE(NFAPI_TRACE_NOTE, "did not receive the entire message %d %d\n", recvfrom_result, header.message_length);
recvfrom_result += recvfrom(vnf_p7->socket, &vnf_p7->rx_message_buffer[recvfrom_result], header.message_length - recvfrom_result, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size);
}
if(recvfrom_result > 0)
{
vnf_nr_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno);
}
}
if(recvfrom_result == -1)
{
if(errno == EAGAIN || errno == EWOULDBLOCK)
{
// return to the select
//NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno);
}
else
{
NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno);
}
}
}
while(recvfrom_result > 0);
return 0;
}
int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7)
{
int recvfrom_result = 0;
+327 -7
View File
@@ -91,7 +91,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs)
// monitor the p7 endpoints and the timing loop and
// send indications to mac
int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config)
int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config)
{
if(config == 0)
return -1;
@@ -410,7 +410,7 @@ struct timespec current_time;
{
curr->slot++;
}
vnf_sync(vnf_p7, curr);
vnf_nr_sync(vnf_p7, curr);
//printf("\nsfn:%d, slot:%d\n current time:%d.%d",curr->sfn,curr->slot,current_time.tv_sec, current_time.tv_nsec); //remove later - gokul
//printf("next slot will start at %d.%d\n",current_time.tv_sec, current_time.tv_nsec);
curr = curr->next;
@@ -423,7 +423,7 @@ struct timespec current_time;
// have a p7 message
if(FD_ISSET(vnf_p7->socket, &rfds))
{
vnf_p7_read_dispatch_message(vnf_p7);
vnf_nr_p7_read_dispatch_message(vnf_p7);
}
}
else
@@ -455,6 +455,326 @@ struct timespec current_time;
return 0;
}
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);
}
//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(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)
@@ -538,7 +858,7 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
}
int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req)
@@ -547,7 +867,7 @@ int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_reque
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
return vnf_nr_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)
@@ -564,7 +884,7 @@ int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_reque
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
return vnf_nr_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)
{
@@ -580,7 +900,7 @@ int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_req
return -1;
vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
return vnf_nr_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)
{