/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see . Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ /** ethernet_lib : API to stream I/Q samples over standard ethernet (RRH component) * * Authors: Raymond Knopp * * Changelog: * 06.10.2014: Initial version */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common_lib.h" typedef struct { int port; char *dest_ip; } rrh_desc_t; int rrh_exit=0; int32_t tx_buffer[4][(1+(sizeof(openair0_timestamp)>>2))+76800*4],rx_buffer[4][(1+(sizeof(openair0_timestamp)>>2))+76800*4]; void *rrh_eNB_thread(void *arg) { int sockid=-1; struct sockaddr_in serveraddr; struct sockaddr clientaddr; socklen_t clientaddrlen; rrh_desc_t *rrh_desc = (rrh_desc_t *)arg; char str[INET_ADDRSTRLEN]; int8_t msg_header[4+sizeof(openair0_timestamp)]; int16_t cmd,nsamps,antenna_index; ssize_t bytes_received; openair0_timestamp timestamp_tx,timestamp_rx=0; int local_host = 0; while (rrh_exit==0) { sockid=socket(AF_INET,SOCK_DGRAM,0); if (sockid==-1) { perror("Cannot create socket: "); rrh_exit=1; } bzero((char *)&serveraddr,sizeof(serveraddr)); serveraddr.sin_family=AF_INET; serveraddr.sin_port=htons(rrh_desc->port); inet_pton(AF_INET,"127.0.0.1",&serveraddr.sin_addr.s_addr); inet_ntop(AF_INET, &(serveraddr.sin_addr), str, INET_ADDRSTRLEN); printf("Binding to socket for %s:%d\n",str,ntohs(serveraddr.sin_port)); if (bind(sockid,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0) { perror("Cannot bind to socket: "); rrh_exit = 1; } // now wait for commands from eNB while (rrh_exit==0) { // get header info bytes_received = recvfrom(sockid,msg_header,4+sizeof(openair0_timestamp),0,&clientaddr,&clientaddrlen); cmd = msg_header[0]; antenna_index = cmd>>1; timestamp_tx = *(openair0_timestamp*)(msg_header+4); nsamps = *(int16_t *)(msg_header+2); cmd = cmd&1; inet_ntop(AF_INET, &(((struct sockaddr_in*)&clientaddr)->sin_addr), str, INET_ADDRSTRLEN); if ((((struct sockaddr_in*)&clientaddr)->sin_addr.s_addr) == 0) local_host = 1; else local_host = 0; switch (cmd) { case 0: // RX printf("Received RX request for antenna %d, nsamps %d (from %s:%d)\n",antenna_index,nsamps,str, ntohs(((struct sockaddr_in*)&clientaddr)->sin_port),INET_ADDRSTRLEN); // send return if (sendto(sockid, &rx_buffer[antenna_index][timestamp_rx%(76800*4)], (nsamps<<2)+sizeof(openair0_timestamp), MSG_DONTWAIT, (local_host == 0) ? &clientaddr : (struct sockaddr*)&serveraddr, sizeof(struct sockaddr))<0) perror("RRH: sendto for RX"); timestamp_rx+=nsamps; break; case 1: // TX printf("Received TX request for antenna %d, nsamps %d, timestamp %llu\n",antenna_index,nsamps,timestamp_tx); bytes_received = recvfrom(sockid,&tx_buffer[antenna_index][timestamp_tx%(76800*4)],(nsamps<<2),0,NULL,NULL); printf("Received TX samples for antenna %d, nsamps %d (%d)\n",antenna_index,nsamps,(bytes_received>>2)); break; } } } close(sockid); return(0); } void signal_handler(int sig) { void *array[10]; size_t size; if (sig==SIGSEGV) { // get void*'s for all entries on the stack size = backtrace(array, 10); // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, 2); exit(-1); } else { printf("trying to exit gracefully...\n"); rrh_exit = 1; } } int main(int argc, char **argv) { pthread_t main_rrh_eNB_thread; pthread_attr_t attr; struct sched_param sched_param_rrh; int error_code; rrh_desc_t rrh; rrh.port = 22222; rrh.dest_ip = "127.0.0.1"; pthread_attr_init(&attr); sched_param_rrh.sched_priority = sched_get_priority_max(SCHED_FIFO); pthread_attr_setschedparam(&attr,&sched_param_rrh); pthread_attr_setschedpolicy(&attr,SCHED_FIFO); error_code = pthread_create(&main_rrh_eNB_thread, &attr, rrh_eNB_thread, (void *)&rrh); printf("TYPE TO TERMINATE\n"); while (rrh_exit==0) sleep(1); }