LTE and NR NFAPI integration
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user