added multiple thread support for ECPRI/IF5 interface. Uses SO_REUSEPORT for listening with multiple sockets in different threads
This commit is contained in:
@@ -80,10 +80,11 @@ int eth_socket_init_raw(openair0_device *device) {
|
||||
perror("ETHERNET: Error opening RAW socket (control)");
|
||||
exit(0);
|
||||
}
|
||||
if ((eth->sockfdd = socket(sock_dom, sock_type, sock_proto)) == -1) {
|
||||
perror("ETHERNET: Error opening RAW socket (user)");
|
||||
exit(0);
|
||||
}
|
||||
for (int i=0;i<eth->num_fd;i++)
|
||||
if ((eth->sockfdd[i] = socket(sock_dom, sock_type, sock_proto)) == -1) {
|
||||
perror("ETHERNET: Error opening RAW socket (user)");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* initialize destination address */
|
||||
bzero((void *)&(eth->local_addrc_ll), sizeof(struct sockaddr_ll));
|
||||
@@ -94,8 +95,9 @@ int eth_socket_init_raw(openair0_device *device) {
|
||||
strcpy(eth->if_index.ifr_name,eth->if_name);
|
||||
if (ioctl(eth->sockfdc, SIOCGIFINDEX, &(eth->if_index)) < 0)
|
||||
perror("SIOCGIFINDEX");
|
||||
if (ioctl(eth->sockfdd, SIOCGIFINDEX, &(eth->if_index)) < 0)
|
||||
perror("SIOCGIFINDEX");
|
||||
for (int i=0;i<eth->num_fd;i++)
|
||||
if (ioctl(eth->sockfdd[i], SIOCGIFINDEX, &(eth->if_index)) < 0)
|
||||
perror("SIOCGIFINDEX");
|
||||
|
||||
eth->local_addrc_ll.sll_family = AF_PACKET;
|
||||
eth->local_addrc_ll.sll_ifindex = eth->if_index.ifr_ifindex;
|
||||
@@ -111,10 +113,11 @@ int eth_socket_init_raw(openair0_device *device) {
|
||||
eth->local_addrd_ll.sll_pkttype = PACKET_OTHERHOST;
|
||||
eth->addr_len = sizeof(struct sockaddr_ll);
|
||||
|
||||
if (bind(eth->sockfdd,(struct sockaddr *)ð->local_addrd_ll,eth->addr_len)<0) {
|
||||
perror("ETHERNET: Cannot bind to socket (user)");
|
||||
exit(0);
|
||||
}
|
||||
for (int i=0;i<eth->num_fd;i++)
|
||||
if (bind(eth->sockfdd[i],(struct sockaddr *)ð->local_addrd_ll,eth->addr_len)<0) {
|
||||
perror("ETHERNET: Cannot bind to socket (user)");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Construct the Ethernet header */
|
||||
ether_aton_r(local_mac, (struct ether_addr *)(&(eth->ehd.ether_shost)));
|
||||
@@ -165,7 +168,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
|
||||
|
||||
/* Send packet */
|
||||
|
||||
bytes_sent += send(eth->sockfdd,
|
||||
bytes_sent += send(eth->sockfdd[cc % eth->num_fd],
|
||||
buff2,
|
||||
pktsize,
|
||||
sendto_flag);
|
||||
@@ -214,7 +217,7 @@ int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestam
|
||||
memcpy(buff[0], (void*)ð->ehd, MAC_HEADER_SIZE_BYTES);
|
||||
|
||||
|
||||
bytes_sent = send(eth->sockfdd,
|
||||
bytes_sent = send(eth->sockfdd[cc % eth->num_fd],
|
||||
buff[0],
|
||||
packet_size,
|
||||
0);
|
||||
@@ -266,7 +269,7 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi
|
||||
|
||||
while(bytes_received < receive_bytes) {
|
||||
again:
|
||||
ret = recv(eth->sockfdd,
|
||||
ret = recv(eth->sockfdd[cc % eth->num_fd],
|
||||
buff2,
|
||||
receive_bytes,
|
||||
rcvfrom_flag);
|
||||
@@ -345,7 +348,7 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam
|
||||
|
||||
while (bytes_received < packet_size) {
|
||||
again:
|
||||
ret = recv(eth->sockfdd,
|
||||
ret = recv(eth->sockfdd[cc % eth->num_fd],
|
||||
buff[0],
|
||||
packet_size,
|
||||
MSG_PEEK);
|
||||
@@ -397,7 +400,7 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam
|
||||
}
|
||||
|
||||
while(bytes_received < packet_size) {
|
||||
ret = recv(eth->sockfdd,
|
||||
ret = recv(eth->sockfdd[cc % eth->num_fd],
|
||||
buff[0],
|
||||
packet_size,
|
||||
0);
|
||||
|
||||
@@ -101,10 +101,11 @@ int eth_socket_init_udp(openair0_device *device) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ((eth->sockfdd = socket(sock_dom, sock_type, sock_proto)) == -1) {
|
||||
perror("ETHERNET: Error opening socket (user)");
|
||||
exit(0);
|
||||
}
|
||||
for (int i = 0;i<eth->num_fd;i++)
|
||||
if ((eth->sockfdd[i] = socket(sock_dom, sock_type, sock_proto)) == -1) {
|
||||
printf("ETHERNET: Error opening socket (user %d)",i);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* initialize addresses */
|
||||
bzero((void *)&(eth->dest_addrc), sizeof(eth->dest_addrc));
|
||||
@@ -141,9 +142,15 @@ int eth_socket_init_udp(openair0_device *device) {
|
||||
perror("ETHERNET: Cannot set SO_REUSEADDR option on socket (control)");
|
||||
exit(0);
|
||||
}
|
||||
if (setsockopt(eth->sockfdd, SOL_SOCKET, SO_NO_CHECK, &enable, sizeof(int))) {
|
||||
perror("ETHERNET: Cannot set SO_NO_CHECK option on socket (user)");
|
||||
exit(0);
|
||||
for (int i=0;i<eth->num_fd;i++) {
|
||||
if (setsockopt(eth->sockfdd[i], SOL_SOCKET, SO_NO_CHECK, &enable, sizeof(int))) {
|
||||
printf("ETHERNET: Cannot set SO_NO_CHECK option on socket (user %d)",i);
|
||||
exit(0);
|
||||
}
|
||||
if (setsockopt(eth->sockfdd[i], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int))) {
|
||||
printf("ETHERNET: Cannot set SO_REUSEPORT option on socket (user %d)",i);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* want to receive -> so bind */
|
||||
@@ -153,12 +160,13 @@ int eth_socket_init_udp(openair0_device *device) {
|
||||
} else {
|
||||
printf("[%s] binding to %s:%d (control)\n",str[hostind],str_local,ntohs(eth->local_addrc.sin_port));
|
||||
}
|
||||
if (bind(eth->sockfdd,(struct sockaddr *)ð->local_addrd,eth->addr_len)<0) {
|
||||
perror("ETHERNET: Cannot bind to socket (user)");
|
||||
exit(0);
|
||||
} else {
|
||||
printf("[%s] binding to %s:%d (user)\n",str[hostind],str_local,ntohs(eth->local_addrd.sin_port));
|
||||
}
|
||||
for (int i=0;i<eth->num_fd;i++)
|
||||
if (bind(eth->sockfdd[i],(struct sockaddr *)ð->local_addrd,eth->addr_len)<0) {
|
||||
printf("ETHERNET: Cannot bind to socket (user %d)",i);
|
||||
exit(0);
|
||||
} else {
|
||||
printf("[%s] binding to %s:%d (user %d)\n",str[hostind],str_local,ntohs(eth->local_addrd.sin_port),i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -180,7 +188,7 @@ int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestam
|
||||
|
||||
while(bytes_received == -1) {
|
||||
again:
|
||||
bytes_received = recvfrom(eth->sockfdd,
|
||||
bytes_received = recvfrom(eth->sockfdd[cc%eth->num_fd],
|
||||
buff[0],
|
||||
packet_size,
|
||||
0,
|
||||
@@ -246,7 +254,7 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam
|
||||
|
||||
eth->tx_nsamps = nblocks;
|
||||
|
||||
bytes_sent = sendto(eth->sockfdd,
|
||||
bytes_sent = sendto(eth->sockfdd[cc%eth->num_fd],
|
||||
buff[0],
|
||||
packet_size,
|
||||
0,
|
||||
@@ -357,7 +365,7 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi
|
||||
bytes_sent);
|
||||
#endif
|
||||
/* Send packet */
|
||||
bytes_sent = sendto(eth->sockfdd,
|
||||
bytes_sent = sendto(eth->sockfdd[cc%eth->num_fd],
|
||||
buff2,
|
||||
sent_byte,
|
||||
sendto_flag,
|
||||
@@ -388,11 +396,70 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi
|
||||
return (bytes_sent-APP_HEADER_SIZE_BYTES)>>2;
|
||||
}
|
||||
|
||||
extern int oai_exit;
|
||||
|
||||
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uint32_t **buff, int nsamps, int packet_idx,int *cc) {
|
||||
void *udp_read_thread(void *arg) {
|
||||
openair0_timestamp TS;
|
||||
|
||||
int aid;
|
||||
udp_read_t *u = (udp_read_t *)arg;
|
||||
openair0_device *device=u->device;
|
||||
fhstate_t *fhstate = &device->fhstate;
|
||||
char buffer[UDP_PACKET_SIZE_BYTES(256)];
|
||||
|
||||
while (oai_exit == 0) {
|
||||
printf("UDP read thread %d, waiting for start\n",u->thread_id);
|
||||
while (fhstate->active > 0) {
|
||||
size_t count = recvfrom(((eth_state_t*)device->priv)->sockfdd[u->thread_id],
|
||||
buffer,sizeof(buffer),0,
|
||||
(struct sockaddr *)&((eth_state_t*)device->priv)->dest_addrd,
|
||||
(socklen_t *)&((eth_state_t*)device->priv)->addr_len);
|
||||
aid = *(uint16_t*)(&buffer[ECPRICOMMON_BYTES]);
|
||||
TS = *(openair0_timestamp *)(&buffer[ECPRICOMMON_BYTES+ECPRIPCID_BYTES]);
|
||||
// convert TS to samples, /6 for AW2S @ 30.72 Ms/s, this is converted for other sample rates in OAI application
|
||||
TS = device->sampling_rate_ratio_n*(TS/device->sampling_rate_ratio_d/6);
|
||||
printf("udp_thread_id %d count %d, aid %d, TS %llu\n",u->thread_id,count,aid,(unsigned long long)TS);
|
||||
if (count <= 0) { printf("problem in recvfrom\n"); exit(-1); }
|
||||
AssertFatal(aid < 8,"Cannot handle more than 8 antennas, got aid %d\n",aid);
|
||||
fhstate->r[aid]=1;
|
||||
if (aid==0 && fhstate->TS[0] == 0) fhstate->TS0 = TS;
|
||||
/* store the timestamp value from packet's header */
|
||||
fhstate->TS[aid] = TS;
|
||||
int64_t offset = TS - fhstate->TS0;
|
||||
if (offset > 0) offset = offset % device->openair0_cfg->rxsize;
|
||||
else offset = TS % device->openair0_cfg->rxsize + ((((uint64_t)1)<<63)-(fhstate->TS0-1)) % device->openair0_cfg->rxsize;
|
||||
printf("udp_thread_id %d aid %d, TS %llu, TS0 %llu, offset %d, size %d\n",u->thread_id,aid,(unsigned long long)TS,fhstate->TS0,offset,device->openair0_cfg->rxsize);
|
||||
// need to do memcpy since there is no guarantee that aid is the same each time, otherwise we could have used
|
||||
// zero-copy and corrected the header component.
|
||||
memcpy((void*)(device->openair0_cfg->rxbase[aid]+offset),
|
||||
(void*)&buffer[APP_HEADER_SIZE_BYTES],
|
||||
count-APP_HEADER_SIZE_BYTES);
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uint32_t **buff, int nsamps) {
|
||||
|
||||
int bytes_received=0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
fhstate_t *fhstate = &device->fhstate;
|
||||
openair0_timestamp prev_read_TS= fhstate->TS_read, min_TS;
|
||||
// block until FH is ready
|
||||
while (fhstate->r[0] == 0 || fhstate->r[1] == 0 || fhstate->r[2] == 0 || fhstate->r[3] == 0 ||
|
||||
fhstate->r[4] == 0 || fhstate->r[5] == 0 || fhstate->r[6] == 0 || fhstate->r[7] == 0) usleep(100);
|
||||
|
||||
// get minimum TS over all antennas
|
||||
min_TS = fhstate->TS[0];
|
||||
for (int i=1;i<device->openair0_cfg->rx_num_channels;i++) min_TS = min(min_TS,fhstate->TS[i]);
|
||||
// poll/sleep until we accumulated enough samples on each antenna port
|
||||
while (min_TS < prev_read_TS + nsamps) {
|
||||
usleep(100);
|
||||
min_TS = fhstate->TS[0];
|
||||
for (int i=1;i<device->openair0_cfg->rx_num_channels;i++) min_TS = min(min_TS,fhstate->TS[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
// openair0_timestamp prev_timestamp = -1;
|
||||
int rcvfrom_flag =0;
|
||||
int block_cnt=0;
|
||||
@@ -411,46 +478,20 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uin
|
||||
block_cnt=0;
|
||||
AssertFatal(eth->compression == NO_COMPRESS, "IF5 compression not supported for now\n");
|
||||
|
||||
while(bytes_received < payload_size) {
|
||||
again:
|
||||
// LOG_I(PHY,"temp_rx0 %p, temp_rx[0] %p temp_rx[APP_HEADER_SIZE_BYTES>>2] %p APP_HEADER_SIZE_BYTES %ld\n",temp_rx0,&temp_rx[0],&temp_rx[APP_HEADER_SIZE_BYTES>>2],APP_HEADER_SIZE_BYTES);
|
||||
bytes_received +=recvfrom(eth->sockfdd,
|
||||
(void*)temp_rx0,
|
||||
payload_size,
|
||||
rcvfrom_flag,
|
||||
(struct sockaddr *)ð->dest_addrd,
|
||||
(socklen_t *)ð->addr_len);
|
||||
packet_cnt++;
|
||||
if (bytes_received ==-1) {
|
||||
bytes_received =recvfrom(eth->sockfdd[sockid%eth->num_fd],
|
||||
(void*)temp_rx0,
|
||||
payload_size,
|
||||
rcvfrom_flag,
|
||||
(struct sockaddr *)ð->dest_addrd,
|
||||
(socklen_t *)ð->addr_len);
|
||||
if (bytes_received ==-1) {
|
||||
eth->num_rx_errors++;
|
||||
if (errno == EAGAIN) {
|
||||
again_cnt++;
|
||||
usleep(10);
|
||||
if (again_cnt == 1000) {
|
||||
perror("ETHERNET READ: ");
|
||||
exit(-1);
|
||||
} else {
|
||||
bytes_received=0;
|
||||
goto again;
|
||||
}
|
||||
} else if (errno == EWOULDBLOCK) {
|
||||
block_cnt++;
|
||||
usleep(10);
|
||||
if (block_cnt == 1000) {
|
||||
perror("ETHERNET READ: ");
|
||||
exit(-1);
|
||||
} else {
|
||||
printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n");
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* store the timestamp value from packet's header */
|
||||
} else {
|
||||
// store the timestamp value from packet's header
|
||||
*timestamp = *(openair0_timestamp *)(temp_rx0 + ECPRICOMMON_BYTES+ECPRIPCID_BYTES);
|
||||
// convert TS to samples, /6 for AW2S @ 30.72 Ms/s, this is converted for other sample rates in OAI application
|
||||
*timestamp = *timestamp/6;
|
||||
*cc = *(uint16_t*)(temp_rx0 + ECPRICOMMON_BYTES);
|
||||
}
|
||||
eth->rx_actual_nsamps=payload_size>>2;
|
||||
eth->rx_count++;
|
||||
}
|
||||
@@ -458,8 +499,10 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uin
|
||||
if (buff) memcpy((void*)(buff[*cc]+packet_idx*nsamps),
|
||||
(void*)(temp_rx+1),
|
||||
nsamps<<2);
|
||||
|
||||
return (payload_size>>2);
|
||||
*/
|
||||
*timestamp = fhstate->TS_read;
|
||||
fhstate->TS_read = prev_read_TS + nsamps;
|
||||
return (nsamps);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -64,8 +64,32 @@ int trx_eth_start(openair0_device *device)
|
||||
AssertFatal(device->thirdparty_init != NULL, "device->thirdparty_init is null\n");
|
||||
AssertFatal(device->thirdparty_init(device) == 0, "third-party init failed\n");
|
||||
device->openair0_cfg->samples_per_packet = 256;
|
||||
}
|
||||
/* initialize socket */
|
||||
eth->num_fd = max(device->openair0_cfg->rx_num_channels,device->openair0_cfg->tx_num_channels);
|
||||
printf("Creating %d UDP threads ...\n",device->openair0_cfg->rx_num_channels);
|
||||
udp_read_t *u[device->openair0_cfg->rx_num_channels];
|
||||
for (int i=0;i<device->openair0_cfg->rx_num_channels;i++) {
|
||||
u[i] = malloc(sizeof(udp_read_t));
|
||||
u[i]->thread_id=i;
|
||||
u[i]->device = device;
|
||||
threadCreate(&u[i]->pthread,udp_read_thread,u[i],"udp read thread",-1,OAI_PRIORITY_RT_MAX);
|
||||
}
|
||||
device->sampling_rate_ratio_n=1;
|
||||
device->sampling_rate_ratio_d=1;
|
||||
if (device->openair0_cfg->nr_flag==1) { // This check if RRU knows about NR numerologies
|
||||
if (device->openair0_cfg->num_rb_dl <= 162 && device->openair0_cfg->num_rb_dl > 106) device->sampling_rate_ratio_n = 2;
|
||||
else if (device->openair0_cfg->num_rb_dl <= 106 && device->openair0_cfg->num_rb_dl > 51) {device->sampling_rate_ratio_d=3;device->sampling_rate_ratio_n=4;}
|
||||
else if (device->openair0_cfg->num_rb_dl == 51) {device->sampling_rate_ratio_n=1;device->sampling_rate_ratio_d=1;}
|
||||
else AssertFatal(1==0,"num_rb_dl %d not ok with ECPRI\n",device->openair0_cfg->num_rb_dl);
|
||||
}
|
||||
else {
|
||||
if (device->openair0_cfg->num_rb_dl == 100) device->sampling_rate_ratio_d = 1;
|
||||
else if (device->openair0_cfg->num_rb_dl == 75) {device->sampling_rate_ratio_d = 4; device->sampling_rate_ratio_n=3;}
|
||||
else if (device->openair0_cfg->num_rb_dl == 50) device->sampling_rate_ratio_d = 2;
|
||||
else if (device->openair0_cfg->num_rb_dl == 25) device->sampling_rate_ratio_d = 4;
|
||||
else AssertFatal(1==0,"num_rb_dl %d not ok with ECPRI\n",device->openair0_cfg->num_rb_dl);
|
||||
}
|
||||
}
|
||||
/* initialize socket */
|
||||
if (eth->flags == ETH_RAW_MODE) {
|
||||
printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n");
|
||||
if (eth_socket_init_raw(device)!=0) return -1;
|
||||
@@ -159,12 +183,13 @@ void trx_eth_end(openair0_device *device)
|
||||
{
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
/* destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
|
||||
if ( close(eth->sockfdd) <0 ) {
|
||||
perror("ETHERNET: Failed to close socket");
|
||||
exit(0);
|
||||
} else {
|
||||
printf("[%s] socket has been successfully closed.\n",(device->host_type == RAU_HOST)? "RAU":"RRU");
|
||||
}
|
||||
for (int i=0;i<eth->num_fd;i++)
|
||||
if ( close(eth->sockfdd[i]) <0 ) {
|
||||
perror("ETHERNET: Failed to close socket");
|
||||
exit(0);
|
||||
} else {
|
||||
printf("[%s] socket has been successfully closed.\n",(device->host_type == RAU_HOST)? "RAU":"RRU");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -224,7 +249,8 @@ int ethernet_tune(openair0_device *device,
|
||||
/****************** socket level options ************************/
|
||||
switch(option) {
|
||||
case SND_BUF_SIZE: /* transmit socket buffer size */
|
||||
if (setsockopt(eth->sockfdd,
|
||||
for (int i=0;i<eth->num_fd;i++)
|
||||
if (setsockopt(eth->sockfdd[i],
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
&value,sizeof(value))) {
|
||||
@@ -232,10 +258,11 @@ int ethernet_tune(openair0_device *device,
|
||||
} else {
|
||||
printf("send buffer size= %d bytes\n",value);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case RCV_BUF_SIZE: /* receive socket buffer size */
|
||||
if (setsockopt(eth->sockfdd,
|
||||
for (int i=0;i<eth->num_fd;i++) {
|
||||
if (setsockopt(eth->sockfdd[i],
|
||||
SOL_SOCKET,
|
||||
SO_RCVBUF,
|
||||
&value,sizeof(value))) {
|
||||
@@ -243,26 +270,29 @@ int ethernet_tune(openair0_device *device,
|
||||
} else {
|
||||
printf("receive bufffer size= %d bytes\n",value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RCV_TIMEOUT:
|
||||
timeout.tv_sec = value/1000000;
|
||||
timeout.tv_usec = value%1000000;//less than rt_period?
|
||||
if (setsockopt(eth->sockfdc,
|
||||
SOL_SOCKET,
|
||||
SO_RCVTIMEO,
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
SOL_SOCKET,
|
||||
SO_RCVTIMEO,
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec);
|
||||
printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec);
|
||||
}
|
||||
if (setsockopt(eth->sockfdd,
|
||||
SOL_SOCKET,
|
||||
SO_RCVTIMEO,
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec);
|
||||
for (int i=0;i<eth->num_fd;i++) {
|
||||
if (setsockopt(eth->sockfdd[i],
|
||||
SOL_SOCKET,
|
||||
SO_RCVTIMEO,
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -277,13 +307,15 @@ int ethernet_tune(openair0_device *device,
|
||||
} else {
|
||||
printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec);
|
||||
}
|
||||
if (setsockopt(eth->sockfdd,
|
||||
SOL_SOCKET,
|
||||
SO_SNDTIMEO,
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec);
|
||||
for (int i=0;i<eth->num_fd;i++) {
|
||||
if (setsockopt(eth->sockfdd[i],
|
||||
SOL_SOCKET,
|
||||
SO_SNDTIMEO,
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -293,20 +325,24 @@ int ethernet_tune(openair0_device *device,
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)-1);
|
||||
ifr.ifr_mtu =value;
|
||||
if (ioctl(eth->sockfdd,SIOCSIFMTU,(caddr_t)&ifr) < 0 )
|
||||
perror ("[ETHERNET] Can't set the MTU");
|
||||
else
|
||||
printf("[ETHERNET] %s MTU size has changed to %d\n",eth->if_name,ifr.ifr_mtu);
|
||||
for (int i=0;i<eth->num_fd;i++) {
|
||||
if (ioctl(eth->sockfdd[i],SIOCSIFMTU,(caddr_t)&ifr) < 0 )
|
||||
perror ("[ETHERNET] Can't set the MTU");
|
||||
else
|
||||
printf("[ETHERNET] %s MTU size has changed to %d\n",eth->if_name,ifr.ifr_mtu);
|
||||
}
|
||||
break;
|
||||
|
||||
case TX_Q_LEN: /* change TX queue length of eth interface */
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)-1);
|
||||
ifr.ifr_qlen =value;
|
||||
if (ioctl(eth->sockfdd,SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 )
|
||||
perror ("[ETHERNET] Can't set the txqueuelen");
|
||||
else
|
||||
printf("[ETHERNET] %s txqueuelen size has changed to %d\n",eth->if_name,ifr.ifr_qlen);
|
||||
for (int i=0;i<eth->num_fd;i++) {
|
||||
if (ioctl(eth->sockfdd[i],SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 )
|
||||
perror ("[ETHERNET] Can't set the txqueuelen");
|
||||
else
|
||||
printf("[ETHERNET] %s txqueuelen size has changed to %d\n",eth->if_name,ifr.ifr_qlen);
|
||||
}
|
||||
break;
|
||||
|
||||
/******************* device level options *************************/
|
||||
@@ -413,7 +449,10 @@ int transport_init(openair0_device *device,
|
||||
eth->compression = ALAW_COMPRESS;
|
||||
}
|
||||
|
||||
eth->num_fd = max(openair0_cfg->rx_num_channels,openair0_cfg->tx_num_channels);
|
||||
|
||||
printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
printf("[ETHERNET]: num_fd %d\n",eth->num_fd);
|
||||
device->Mod_id = 0;//num_devices_eth++;
|
||||
device->transp_type = ETHERNET_TP;
|
||||
device->trx_start_func = trx_eth_start;
|
||||
@@ -438,6 +477,7 @@ int transport_init(openair0_device *device,
|
||||
device->trx_read_func2 = trx_eth_read_udp;
|
||||
device->trx_ctlsend_func = trx_eth_ctlsend_udp;
|
||||
device->trx_ctlrecv_func = trx_eth_ctlrecv_udp;
|
||||
memset((void*)&device->fhstate,0,sizeof(device->fhstate));
|
||||
} else if (eth->flags == ETH_RAW_IF4p5_MODE) {
|
||||
device->trx_write_func = trx_eth_write_raw_IF4p5;
|
||||
device->trx_read_func = trx_eth_read_raw_IF4p5;
|
||||
@@ -454,6 +494,7 @@ int transport_init(openair0_device *device,
|
||||
eth->if_name = eth_params->local_if_name;
|
||||
device->priv = eth;
|
||||
|
||||
|
||||
/* device specific */
|
||||
// openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
|
||||
// openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift
|
||||
|
||||
@@ -59,12 +59,16 @@ typedef struct {
|
||||
|
||||
/*!\brief socket file desc (control)*/
|
||||
int sockfdc;
|
||||
/*!\brief number of sockets for user-plane*/
|
||||
int num_fd;
|
||||
/*!\brief socket file desc (user)*/
|
||||
int sockfdd;
|
||||
int sockfdd[8];
|
||||
/*!\brief interface name */
|
||||
char *if_name;
|
||||
/*!\brief buffer size */
|
||||
unsigned int buffer_size;
|
||||
/*!\brief Fronthaul state */
|
||||
fhstate_t *fhstate;
|
||||
/*!\brief destination address (control) for UDP socket*/
|
||||
struct sockaddr_in dest_addrc;
|
||||
/*!\brief local address (control) for UDP socket*/
|
||||
@@ -214,7 +218,7 @@ void inline dump_txcounters(openair0_device *device);
|
||||
*/
|
||||
void dump_iqs(char * buff, int iq_cnt);
|
||||
|
||||
|
||||
void *udp_read_thread(void *arg);
|
||||
|
||||
/*! \fn int ethernet_tune (openair0_device *device, unsigned int option, int value);
|
||||
* \brief this function allows you to configure certain ethernet parameters in socket or device level
|
||||
@@ -238,7 +242,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value);
|
||||
*/
|
||||
int eth_socket_init_udp(openair0_device *device);
|
||||
int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int cc, int flags);
|
||||
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uint32_t **buff, int nsamps, int packet_idx,int *cc);
|
||||
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uint32_t **buff, int nsamps);
|
||||
|
||||
|
||||
int eth_socket_init_raw(openair0_device *device);
|
||||
|
||||
Reference in New Issue
Block a user