diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c new file mode 100644 index 0000000000000000000000000000000000000000..f8d1a314624baec9e3d313dbb4708dfeb9c48432 --- /dev/null +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -0,0 +1,317 @@ +/******************************************************************************* + 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 <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ +/*! \file ethernet_lib.c + * \brief API to stream I/Q samples over standard ethernet + * \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp + * \date 2015 + * \version 0.2 + * \company Eurecom + * \maintainer: navid.nikaein@eurecom.fr + * \note + * \warning + */ + +#include <arpa/inet.h> +#include <linux/if_packet.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/ether.h> +#include <unistd.h> +#include <errno.h> + +#include "common_lib.h" +#include "ethernet_lib.h" + +#define DEBUG 1 + +struct sockaddr_ll dest_addr[MAX_INST]; +struct sockaddr_ll local_addr[MAX_INST]; +int addr_len[MAX_INST]; +struct ifreq if_index[MAX_INST]; +struct ether_header eh; + +int eth_socket_init_raw(openair0_device *device) { + + int i = 0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + const char *local_mac, *remote_mac; + int local_port=0, remote_port=0; + int sock_dom=0; + int sock_type=0; + int sock_proto=0; + + if (device->host_type == RRH_HOST ) { + local_mac = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_mac = "0:0:0:0:0:0"; + remote_port = device->openair0_cfg.my_port; + printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac); + } else { + local_mac = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_mac = device->openair0_cfg.remote_addr; + remote_port = device->openair0_cfg.remote_port; + printf("[%s] local MAC addr %s remote MAC addr %s\n","BBU", local_mac,remote_mac); + } + + + /* Open a RAW socket to send on */ + sock_dom=AF_PACKET; + sock_type=SOCK_RAW; + sock_proto=IPPROTO_RAW; + if ((eth->sockfd[Mod_id] = socket(sock_dom, sock_type, sock_proto)) == -1) { + perror("ETHERNET: Error opening RAW socket"); + exit(0); + } + + /* initialize destination address */ + for (i=0; i< MAX_INST; i++) { + bzero((void *)&(local_addr[i]), sizeof(struct sockaddr_ll)); + bzero((void *)&(if_index[i]), sizeof(struct ifreq)); + } + /* Get the index of the interface to send on */ + strcpy(if_index[Mod_id].ifr_name,eth->if_name[Mod_id]); + if (ioctl(eth->sockfd[Mod_id], SIOCGIFINDEX, &(if_index[Mod_id])) < 0) + perror("SIOCGIFINDEX"); + + local_addr[Mod_id].sll_family = AF_PACKET; + local_addr[Mod_id].sll_ifindex = if_index[Mod_id].ifr_ifindex; + /* hear traffic from specific protocol*/ + local_addr[Mod_id].sll_protocol = htons((short)device->openair0_cfg.my_port); + local_addr[Mod_id].sll_halen = ETH_ALEN; + local_addr[Mod_id].sll_pkttype = PACKET_OTHERHOST; + addr_len[Mod_id] = sizeof(struct sockaddr_ll); + + if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) { + perror("ETHERNET: Cannot bind to socket"); + exit(0); + } + + /* Construct the Ethernet header */ + ether_aton_r(device->openair0_cfg.my_addr, (struct ether_addr *)(&(eh.ether_shost))); + ether_aton_r(device->openair0_cfg.remote_addr, (struct ether_addr *)(&(eh.ether_dhost))); + eh.ether_type = htons((short)device->openair0_cfg.my_port); + + printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5]); + + return 0; +} + + +int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { + + int bytes_sent=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + int sendto_flag =0; + int i=0; + //sendto_flag|=flags; + + eth->tx_nsamps=nsamps; + + for (i=0;i<cc;i++) { + /* buff[i] points to the position in tx buffer where the payload to be sent is + buff2 points to the position in tx buffer where the packet header will be placed */ + void *buff2 = (void*)(buff[i]-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES); + + /* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/ + struct ether_header temp = *(struct ether_header *)buff2; + int32_t temp0 = *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES); + openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); + + bytes_sent = 0; + memcpy(buff2,(void*)&eh,MAC_HEADER_SIZE_BYTES); + *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t))=1+(i<<1); + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = timestamp; + + /*printf("[RRH]write mod_%d %d , len %d, buff %p \n", + Mod_id,eth->sockfd[Mod_id],RAW_PACKET_SIZE_BYTES(nsamps), buff2);*/ + + while(bytes_sent < RAW_PACKET_SIZE_BYTES(nsamps)) { +#if DEBUG + printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n", + (void *)(buff2+bytes_sent), + RAW_PACKET_SIZE_BYTES(nsamps) - bytes_sent, + bytes_sent); +#endif + /* Send packet */ + bytes_sent += send(eth->sockfd[Mod_id], + buff2, + RAW_PACKET_SIZE_BYTES(nsamps), + sendto_flag); + if ( bytes_sent == -1) { + eth->num_tx_errors++; + perror("ETHERNET WRITE: "); + exit(-1); + } else { +#if DEBUG + printf("------- TX ------: nu=%x an_id=%d ts%d bytes_sent=%d\n", + *(uint8_t *)(buff2+ETH_ALEN), + *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), + bytes_sent); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps), TX_FLAG); +#endif + eth->tx_actual_nsamps=bytes_sent>>2; + eth->tx_count++; + } + } + + /* tx buffer values restored */ + *(struct ether_header *)buff2 = temp; + *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0; + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1; + } + return (bytes_sent-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2; +} + + +int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + + int bytes_received=0; + int i=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + int rcvfrom_flag =0; + + eth->rx_nsamps=nsamps; + + for (i=0;i<cc;i++) { + /* buff[i] points to the position in rx buffer where the payload to be received will be placed + buff2 points to the position in rx buffer where the packet header will be placed */ + void *buff2 = (void*)(buff[i]-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES); + + /* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/ + struct ether_header temp = *(struct ether_header *)buff2; + int32_t temp0 = *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES); + openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); + + bytes_received=0; + + while(bytes_received < RAW_PACKET_SIZE_BYTES(nsamps)) { + bytes_received +=recv(eth->sockfd[Mod_id], + buff2, + RAW_PACKET_SIZE_BYTES(nsamps), + rcvfrom_flag); + + if (bytes_received ==-1) { + eth->num_rx_errors++; + perror("ETHERNET READ: "); + exit(-1); + } else { + /* store the timestamp value from packet's header */ + *timestamp = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); + eth->rx_actual_nsamps=bytes_received>>2; + eth->rx_count++; + } + } + +#if DEBUG + printf("------- RX------: nu=%x an_id=%d ts%d bytes_recv=%d \n", + *(uint8_t *)(buff2+ETH_ALEN), + *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), + bytes_received); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps),RX_FLAG); + +#endif + + /* tx buffer values restored */ + *(struct ether_header *)buff2 = temp; + *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0; + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1; + } + return (bytes_received-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2; +} + + + + +int eth_set_dev_conf_raw(openair0_device *device) { + + int Mod_id = device->Mod_id; + eth_state_t *eth = (eth_state_t*)device->priv; + void *msg; + ssize_t msg_len; + + /* a BBU client sends to RRH a set of configuration parameters (openair0_config_t) + so that RF front end is configured appropriately and + frame/packet size etc. can be set */ + + msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t)); + msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t); + + + memcpy(msg,(void*)&eh,MAC_HEADER_SIZE_BYTES); + memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)&device->openair0_cfg,sizeof(openair0_config_t)); + + if (send(eth->sockfd[Mod_id], + msg, + msg_len, + 0)==-1) { + perror("ETHERNET: "); + exit(0); + } + + return 0; +} + + +int eth_get_dev_conf_raw(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + char str[INET_ADDRSTRLEN]; + void *msg; + ssize_t msg_len; + + msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t)); + msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t); + + /* RRH receives from BBU openair0_config_t */ + if (recv(eth->sockfd[Mod_id], + msg, + msg_len, + 0)==-1) { + perror("ETHERNET: "); + exit(0); + } + + /* RRH stores the remote MAC address */ + memcpy(eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN); + memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t)); + printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5],eh.ether_dhost[0],eh.ether_dhost[1],eh.ether_dhost[2],eh.ether_dhost[3],eh.ether_dhost[4],eh.ether_dhost[5]); + + return 0; +} diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c new file mode 100644 index 0000000000000000000000000000000000000000..fe4d4db0db3efe6d228c66923878d8f3485b0733 --- /dev/null +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -0,0 +1,379 @@ +/******************************************************************************* + 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 <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ +/*! \file ethernet_lib.c + * \brief API to stream I/Q samples over standard ethernet + * \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp + * \date 2015 + * \version 0.2 + * \company Eurecom + * \maintainer: navid.nikaein@eurecom.fr + * \note + * \warning + */ + +#include <arpa/inet.h> +#include <linux/if_packet.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/ether.h> +#include <unistd.h> +#include <errno.h> + +#include "common_lib.h" +#include "ethernet_lib.h" + +#define DEBUG 0 +struct sockaddr_in dest_addr[MAX_INST]; +struct sockaddr_in local_addr[MAX_INST]; +int addr_len[MAX_INST]; + + + int eth_socket_init_udp(openair0_device *device) { + + int i = 0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + char str_local[INET_ADDRSTRLEN]; + char str_remote[INET_ADDRSTRLEN]; + const char *local_ip, *remote_ip; + int local_port=0, remote_port=0; + int sock_dom=0; + int sock_type=0; + int sock_proto=0; + int enable=1; + + if (device->host_type == RRH_HOST ) { + local_ip = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_ip = "0.0.0.0"; + remote_port = 0; + printf("[%s] local ip addr %s port %d\n", "RRH", local_ip, local_port); + } else { + local_ip = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_ip = device->openair0_cfg.remote_addr; + remote_port = device->openair0_cfg.remote_port; + printf("[%s] local ip addr %s port %d\n","BBU", local_ip, local_port); + } + + /* Open socket to send on */ + sock_dom=AF_INET; + sock_type=SOCK_DGRAM; + sock_proto=IPPROTO_UDP; + + if ((eth->sockfd[Mod_id] = socket(sock_dom, sock_type, sock_proto)) == -1) { + perror("ETHERNET: Error opening socket"); + exit(0); + } + + /* initialize addresses */ + for (i=0; i< MAX_INST; i++) { + bzero((void *)&(dest_addr[i]), sizeof(dest_addr[i])); + bzero((void *)&(local_addr[i]), sizeof(local_addr[i])); + } + + addr_len[Mod_id] = sizeof(struct sockaddr_in); + + dest_addr[Mod_id].sin_family = AF_INET; + inet_pton(AF_INET,remote_ip,&(dest_addr[Mod_id].sin_addr.s_addr)); + dest_addr[Mod_id].sin_port=htons(remote_port); + inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str_remote, INET_ADDRSTRLEN); + + + local_addr[Mod_id].sin_family = AF_INET; + inet_pton(AF_INET,local_ip,&(local_addr[Mod_id].sin_addr.s_addr)); + local_addr[Mod_id].sin_port=htons(local_port); + inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str_local, INET_ADDRSTRLEN); + + + /* set reuse address flag */ + if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))) { + perror("ETHERNET: Cannot set SO_REUSEADDR option on socket"); + exit(0); + } + + /* apply additional configuration */ + //ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet)); + + /* if RRH, then I am the server, so bind */ + if (device->host_type == RRH_HOST) { + if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) { + perror("ETHERNET: Cannot bind to socket"); + exit(0); + } else { + printf("[%s] binding mod_%d to %s:%d\n","RRH",Mod_id,str_local,ntohs(local_addr[Mod_id].sin_port)); + } + /* if BBU, then I am a client, so connect */ + } else { + printf("[%s] Connecting to %s:%d\n","BBU",str_remote,ntohs(dest_addr[Mod_id].sin_port)); + } + + + + return 0; +} + +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { + + int bytes_sent=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + int sendto_flag =0; + int i=0; + //sendto_flag|=flags; + eth->tx_nsamps=nsamps; + + for (i=0;i<cc;i++) { + /* buff[i] points to the position in tx buffer where the payload to be sent is + buff2 points to the position in tx buffer where the packet header will be placed */ + void *buff2 = (void*)(buff[i]- APP_HEADER_SIZE_BYTES); + + /* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/ + int32_t temp0 = *(int32_t *)buff2; + openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); + + bytes_sent = 0; + + *(int16_t *)(buff2 + sizeof(int16_t))=1+(i<<1); + *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp; + + + while(bytes_sent < UDP_PACKET_SIZE_BYTES(nsamps)) { +#if DEBUG + printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n", + (void *)(buff2+bytes_sent), + UDP_PACKET_SIZE_BYTES(nsamps) - bytes_sent, + bytes_sent); +#endif + /* Send packet */ + bytes_sent += sendto(eth->sockfd[Mod_id], + buff2, + UDP_PACKET_SIZE_BYTES(nsamps), + sendto_flag, + (struct sockaddr*)&dest_addr[Mod_id], + addr_len[Mod_id]); + + if ( bytes_sent == -1) { + eth->num_tx_errors++; + perror("ETHERNET WRITE: "); + exit(-1); + } else { +#if DEBUG + printf("------- TX ------: nu=%d an_id=%d ts%d bytes_send=%d\n", + *(int16_t *)buff2, + *(int16_t *)(buff2 + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + sizeof(int32_t)), + bytes_sent); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps), TX_FLAG); +#endif + eth->tx_actual_nsamps=bytes_sent>>2; + eth->tx_count++; + } + } + /* tx buffer values restored */ + *(int32_t *)buff2 = temp0; + *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; + } + + return (bytes_sent-APP_HEADER_SIZE_BYTES)>>2; +} + + + +int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + + int bytes_received=0; + eth_state_t *eth = (eth_state_t*)device->priv; + openair0_timestamp prev_timestamp = -1; + int Mod_id = device->Mod_id; + int rcvfrom_flag =0; + int block_cnt=0; + int again_cnt=0; + int i=0; + + eth->rx_nsamps=nsamps; + + for (i=0;i<cc;i++) { + /* buff[i] points to the position in rx buffer where the payload to be received will be placed + buff2 points to the position in rx buffer where the packet header will be placed */ + void *buff2 = (void*)(buff[i]- APP_HEADER_SIZE_BYTES); + + /* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/ + int32_t temp0 = *(int32_t *)buff2; + openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); + + bytes_received=0; + block_cnt=0; + + + while(bytes_received < UDP_PACKET_SIZE_BYTES(nsamps)) { + again: +#if DEBUG + printf("------- RX------: buff2 current position=%d remaining_bytes=%d bytes_recv=%d \n", + (void *)(buff2+bytes_received), + UDP_PACKET_SIZE_BYTES(nsamps) - bytes_received, + bytes_received); +#endif + bytes_received +=recvfrom(eth->sockfd[Mod_id], + buff2, + UDP_PACKET_SIZE_BYTES(nsamps), + rcvfrom_flag, + (struct sockaddr *)&dest_addr[Mod_id], + (socklen_t *)&addr_len[Mod_id]); + + 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 { + printf("AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN \n"); + 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 { +#if DEBUG + printf("------- RX------: nu=%d an_id=%d ts%d bytes_recv=%d\n", + *(int16_t *)buff2, + *(int16_t *)(buff2 + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + sizeof(int32_t)), + bytes_received); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps),RX_FLAG); +#endif + /* store the timestamp value from packet's header */ + if (prev_timestamp == -1) { + prev_timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); + } else { + prev_timestamp =timestamp; + } + /* store the timestamp value from packet's header */ + *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); + eth->rx_actual_nsamps=bytes_received>>2; + eth->rx_count++; + } + + } + /* tx buffer values restored */ + *(int32_t *)buff2 = temp0; + *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; + + } + return (bytes_received-APP_HEADER_SIZE_BYTES)>>2; +} + + + + +int eth_set_dev_conf_udp(openair0_device *device) { + + int Mod_id = device->Mod_id; + eth_state_t *eth = (eth_state_t*)device->priv; + void *msg; + ssize_t msg_len; + + + /* a BBU client sents to RRH a set of configuration parameters (openair0_config_t) + so that RF front end is configured appropriately and + frame/packet size etc. can be set */ + + msg=malloc(sizeof(openair0_config_t)); + msg_len=sizeof(openair0_config_t); + memcpy(msg,(void*)&device->openair0_cfg,msg_len); + + if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&dest_addr[Mod_id],addr_len[Mod_id])==-1) { + perror("ETHERNET: "); + exit(0); + } + + /* printf("[RRHbbb] mod_%d socket %d connected to BBU %s:%d\n", Mod_id, eth->sockfd[Mod_id], inet_ntoa(dest_addr[Mod_id].sin_addr), */ + /* ntohs(dest_addr[Mod_id].sin_port)); */ + return 0; +} + +int eth_get_dev_conf_udp(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + char str1[INET_ADDRSTRLEN],str[INET_ADDRSTRLEN]; + void *msg; + ssize_t msg_len; + + msg=malloc(sizeof(openair0_config_t)); + msg_len=sizeof(openair0_config_t); + + inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); + + /* printf("[RRH] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id], str1, */ + /* ntohs(dest_addr[Mod_id].sin_port),str, */ + /* ntohs(local_addr[Mod_id].sin_port)); */ + + /* RRH receives from BBU openair0_config_t */ + if (recvfrom(eth->sockfd[Mod_id], + msg, + msg_len, + 0, + (struct sockaddr *)&dest_addr[Mod_id], + (socklen_t *)&addr_len[Mod_id])==-1) { + perror("ETHERNET: "); + exit(0); + } + + memcpy((void*)&device->openair0_cfg,msg,msg_len); + + /* get remote ip address and port */ + inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); + device->openair0_cfg.remote_port =ntohs(dest_addr[Mod_id].sin_port); + device->openair0_cfg.remote_addr =str1; + + /* restore local ip address and port */ + inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); + device->openair0_cfg.my_port =ntohs(local_addr[Mod_id].sin_port); + device->openair0_cfg.my_addr =str; + + /* printf("[RRH2] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id],str1, device->openair0_cfg.remote_port, str, device->openair0_cfg.my_port); */ + return 0; +} diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index ce90d2cff967e03d90d3c82bc401f3b93a156768..995ced1f0d672236d767d3f7954e64a0cb33a54c 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -28,7 +28,7 @@ *******************************************************************************/ /*! \file ethernet_lib.c * \brief API to stream I/Q samples over standard ethernet - * \author Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp + * \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp * \date 2015 * \version 0.2 * \company Eurecom @@ -52,186 +52,43 @@ #include "common_lib.h" #include "ethernet_lib.h" -//#define DEBUG 1 int num_devices_eth = 0; +struct sockaddr_in dest_addr[MAX_INST]; int dest_addr_len[MAX_INST]; -char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/ - - -/*! \fn static int eth_socket_init(openair0_device *device) -* \brief initialization of UDP Socket to communicate with one destination -* \param[in] *device openair device for which the socket will be created -* \param[out] -* \return 0 on success, otherwise -1 -* \note -* @ingroup _oai -*/ -static int eth_socket_init(openair0_device *device); - -/*! \fn static int eth_set_dev_conf(openair0_device *device) -* \brief -* \param[in] *device openair device -* \param[out] -* \return 0 on success, otherwise -1 -* \note -* @ingroup _oai -*/ -static int eth_set_dev_conf(openair0_device *device); - -/*! \fn static int eth_get_dev_conf(openair0_device *device) -* \brief -* \param[in] *device openair device -* \param[out] -* \return 0 on success, otherwise -1 -* \note -* @ingroup _oai -*/ -static int eth_get_dev_conf(openair0_device *device); - int trx_eth_start(openair0_device *device) { - - /* initialize socket */ - if (eth_socket_init(device)!=0) { - return -1; - } - - /* RRH gets openair0 device configuration BBU sets openair0 device configuration*/ - if (device->func_type == BBU_FUNC) { - return eth_set_dev_conf(device); - } else { - return eth_get_dev_conf(device); - } - - return 0; -} - -int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { - - int n_written=0,i; - uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp); eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - int sendto_flag =0; - sendto_flag|=MSG_DONTWAIT; - for (i=0;i<cc;i++) { - /* buff[i] points to the position in tx buffer where the payload to be sent is - buff2 points to the position in tx buffer where the packet header will be placed */ - void *buff2 = (void*)(buff[i]-header_size); - - /* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/ - int32_t temp0 = *(int32_t *)buff2; - openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - - n_written = 0; - - *(int16_t *)(buff2 + sizeof(int16_t))=1+(i<<1); - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp; - - /* printf("[RRH]write mod_%d %d , len %d, buff %p antenna %d\n", - Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/ - - while(n_written < nsamps) { - /* Send packet */ - if ((n_written += sendto(eth->sockfd[Mod_id], - buff2, - (nsamps<<2)+header_size, - 0, - (struct sockaddr*)ð->dest_addr[Mod_id], - dest_addr_len[Mod_id])) < 0) { - perror("ETHERNET WRITE"); - exit(-1); - } + /* initialize socket */ + if ((eth->flags & ETH_RAW_MODE) != 0 ) { + if (eth_socket_init_raw(device)!=0) return -1; + /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ + if (device->host_type == BBU_HOST) { + if(eth_set_dev_conf_raw(device)!=0) return -1; + } else { + if(eth_get_dev_conf_raw(device)!=0) return -1; } - -#if DEBUG - printf("Buffer head TX: nu=%d an_id=%d ts%d samples_send=%d i=%d data=%x\n", - *(int16_t *)buff2, - *(int16_t *)(buff2 + sizeof(int16_t)), - *(openair0_timestamp *)(buff2 + sizeof(int32_t)), - n_written>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t))); -#endif - - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; - } - return n_written; - -} - -int trx_eth_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { - - int bytes_received=0; - int block_cnt=0; - int ret=0,i; - uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp); - - eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - - for (i=0;i<cc;i++) { - /* buff[i] points to the position in rx buffer where the payload to be received will be placed - buff2 points to the position in rx buffer where the packet header will be placed */ - void *buff2 = (void*)(buff[i]-header_size); - - /* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/ - int32_t temp0 = *(int32_t *)buff2; - openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - - bytes_received=0; - block_cnt=0; - ret=0; - - /* printf("[RRH] read mod_%d %d,len %d, buff %p antenna %d\n", - Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/ - - while(bytes_received < (int)((nsamps<<2))) { - ret=recvfrom(eth->sockfd[Mod_id], - buff2+bytes_received, - (nsamps<<2)+header_size-bytes_received, - 0,//MSG_DONTWAIT, - (struct sockaddr *)ð->dest_addr[Mod_id], - (socklen_t *)&dest_addr_len[Mod_id]); - - if (ret==-1) { - if (errno == EAGAIN) { - perror("ETHERNET READ: "); - return((nsamps<<2) + header_size); - } else if (errno == EWOULDBLOCK) { - block_cnt++; - usleep(10); - - if (block_cnt == 100) return(-1); - } - } else { - bytes_received+=ret; - } + /* adjust MTU wrt number of samples per packet */ + if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet))!=0) return -1; + } else { + if (eth_socket_init_udp(device)!=0) return -1; + /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ + if (device->host_type == BBU_HOST) { + if(eth_set_dev_conf_udp(device)!=0) return -1; + } else { + if(eth_get_dev_conf_udp(device)!=0) return -1; } - -#if DEBUG - printf("Buffer head RX: nu=%d an_id=%d ts%d samples_recv=%d i=%d data=%x\n", - *(int16_t *)buff2, - *(int16_t *)(buff2 + sizeof(int16_t)), - *(openair0_timestamp *)(buff2 + sizeof(int32_t)), - ret>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t))); -#endif - - /* store the timestamp value from packet's header */ - *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; + /* adjust MTU wrt number of samples per packet */ + if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet))!=0) return -1; } - return nsamps; - + + return 0; } + void trx_eth_end(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; @@ -241,7 +98,7 @@ void trx_eth_end(openair0_device *device) { perror("ETHERNET: Failed to close socket"); exit(0); } else { - printf("[RRH] socket for mod_id %d has been successfully closed.\n",Mod_id); + printf("[%s] socket for mod_id %d has been successfully closed.\n",(device->host_type == BBU_HOST)? "BBU":"RRH",Mod_id); } } @@ -253,7 +110,7 @@ int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) { eth_state_t *eth = (eth_state_t*)device->priv; /* BBU sends a message to RRH */ - if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) { + if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) { perror("ETHERNET: "); exit(0); } @@ -262,7 +119,6 @@ int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) { } - int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { eth_state_t *eth = (eth_state_t*)device->priv; @@ -273,7 +129,7 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { msg, msg_len, 0, - (struct sockaddr *)ð->dest_addr[Mod_id], + (struct sockaddr *)&dest_addr[Mod_id], (socklen_t *)&dest_addr_len[Mod_id])==-1) { perror("ETHERNET: "); exit(0); @@ -283,65 +139,6 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { } -static int eth_set_dev_conf(openair0_device *device) { - - int Mod_id = device->Mod_id; - eth_state_t *eth = (eth_state_t*)device->priv; - void *msg; - ssize_t msg_len; - - - /* a BBU client sents to RRH a set of configuration parameters (openair0_config_t) - so that RF front end is configured appropriately and - frame/packet size etc. can be set */ - - msg=malloc(sizeof(openair0_config_t)); - msg_len=sizeof(openair0_config_t); - memcpy(msg,(void*)&device->openair0_cfg,msg_len); - - if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) { - perror("ETHERNET: "); - exit(0); - } - - return 0; -} - - -static int eth_get_dev_conf(openair0_device *device) { - - eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - char str[INET_ADDRSTRLEN]; - void *msg; - ssize_t msg_len; - - msg=malloc(sizeof(openair0_config_t)); - msg_len=sizeof(openair0_config_t); - - /* RRH receives from BBU openair0_config_t */ - if (recvfrom(eth->sockfd[Mod_id], - msg, - msg_len, - 0, - (struct sockaddr *)ð->dest_addr[Mod_id], - (socklen_t *)&dest_addr_len[Mod_id])==-1) { - perror("ETHERNET: "); - exit(0); - } - - memcpy((void*)&device->openair0_cfg,msg,msg_len); - inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); - device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port); - device->openair0_cfg.remote_ip=str; - /*apply additional configuration*/ - //ethernet_tune (device, RING_PAR); - // printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port)); - - return 0; -} - - int trx_eth_stop(int card) { return(0); @@ -364,186 +161,310 @@ int trx_eth_reset_stats(openair0_device* device) { } -static int eth_socket_init(openair0_device *device) { - - int i = 0; - eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - char str[INET_ADDRSTRLEN]; - const char *dest_ip; - int dest_port=0; - - if (device->func_type == RRH_FUNC ) { - dest_ip = device->openair0_cfg.my_ip; - dest_port = device->openair0_cfg.my_port; - printf("[RRH] ip addr %s port %d\n",dest_ip, dest_port); - } else { - dest_ip = device->openair0_cfg.remote_ip; - dest_port = device->openair0_cfg.remote_port; - printf("[BBU] ip addr %s port %d\n",dest_ip, dest_port); - } - - /* Open RAW socket to send on */ - if ((eth->sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { - perror("ETHERNET: Error opening socket"); - exit(0); - } - - /* initialize destination address */ - for (i=0; i< MAX_INST; i++) { - bzero((void *)&(eth->dest_addr[i]), sizeof(eth->dest_addr[i])); - } - - // bzero((void *)dest,sizeof(struct sockaddr_in)); - eth->dest_addr[Mod_id].sin_family = AF_INET; - inet_pton(AF_INET,dest_ip,&(eth->dest_addr[Mod_id].sin_addr.s_addr)); - eth->dest_addr[Mod_id].sin_port=htons(dest_port); - dest_addr_len[Mod_id] = sizeof(struct sockaddr_in); - inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); - - /* if RRH, then I am the server, so bind */ - if (device->func_type == RRH_FUNC ) { - if (bind(eth->sockfd[Mod_id],(struct sockaddr *)ð->dest_addr[Mod_id], dest_addr_len[Mod_id])<0) { - perror("ETHERNET: Cannot bind to socket"); - exit(0); - } else { - printf("[RRH] binding mod_%d to %s:%d\n",Mod_id,str,ntohs(eth->dest_addr[Mod_id].sin_port)); - } - - } else { - printf("[BBU] Connecting to %s:%d\n",str,ntohs(eth->dest_addr[Mod_id].sin_port)); - } - - return 0; -} - - -int ethernet_tune(openair0_device *device , eth_opt_t option) { +int ethernet_tune(openair0_device *device, unsigned int option, int value) { eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id=device->Mod_id; - - unsigned int sndbuf_size=0, rcvbuf_size=0; - struct timeval snd_timeout, rcv_timeout; + struct timeval timeout; struct ifreq ifr; char system_cmd[256]; char* if_name=DEFAULT_IF; - - /****************** socket level options ************************/ - if (option== SND_BUF_SIZE) { /* transmit socket buffer size */ + struct in_addr ia; + struct if_nameindex *ids; + int ret=0; + int i=0; + + + /***************** get working interface name ***************************/ + /* /\* convert ascii ip address from config file to network binary format *\/ */ + /* inet_aton(device->openair0_cfg.my_addr, &ia); */ + /* /\* look for the interface used, we have its ip address *\/ */ + /* /\* get info on all our network interfaces *\/ */ + /* ids = if_nameindex(); */ + /* /\* loop on these network interfaces *\/ */ + /* for (i=0; ids[i].if_index != 0 ; i++) { */ + /* /\* skip unamed interfaces *\/ */ + /* if (ids[i].if_name == NULL) */ + /* continue; */ + /* /\* get ip address of current network interface *\/ */ + /* strcpy(ifr.ifr_name,ids[i].if_name); */ + /* if (-1 == ioctl(eth->sockfd[Mod_id], SIOCGIFADDR, &ifr)) { */ + /* printf( " Interface %i: %s isn't configured (no ip addr), skipped\n",ids[i].if_index, ifr.ifr_name) ; */ + /* continue; */ + /* } */ + /* /\* test if this is the interface to be used *\/ */ + /* if ( ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr != ia.s_addr) */ + /* continue; */ + /* /\* store interface name *\/ */ + /* if_name = ids[i].if_name; */ + /* break; */ + + /* } */ + /* if_freenameindex(ids); */ + /* if( if_name == NULL) { */ + /* printf("Unable to find interface name for %s\n",device->openair0_cfg.my_addr); */ + /* return -1; */ + /* } */ + /* eth->if_name[Mod_id]=if_name; */ + + /****************** socket level options ************************/ + switch(option) { + case SND_BUF_SIZE: /* transmit socket buffer size */ if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_SNDBUF, - &sndbuf_size,sizeof(sndbuf_size))) { + &value,sizeof(value))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "sndbuf_size= %d bytes\n", sndbuf_size); - } - } else if (option== RCV_BUF_SIZE) { /* receive socket buffer size */ + printf("send buffer size= %d bytes\n",value); + } + break; + + case RCV_BUF_SIZE: /* receive socket buffer size */ if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_RCVBUF, - &rcvbuf_size,sizeof(rcvbuf_size))) { + &value,sizeof(value))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "rcvbuf_size= %d bytes\n", rcvbuf_size); + printf("receive bufffer size= %d bytes\n",value); } - } else if (option==RCV_TIMEOUT) { - rcv_timeout.tv_sec = 0; - rcv_timeout.tv_usec = 180;//less than rt_period + break; + + case RCV_TIMEOUT: + timeout.tv_sec = value/1000000000; + timeout.tv_usec = value%1000000000;//less than rt_period? if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_RCVTIMEO, - (char *)&rcv_timeout,sizeof(rcv_timeout))) { + (char *)&timeout,sizeof(timeout))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "rcv_timeout= %d usecs\n", rcv_timeout.tv_usec); + printf( "receive timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec); } - } else if (option==SND_TIMEOUT) { - snd_timeout.tv_sec = 0; - snd_timeout.tv_usec = 180;//less than rt_period + break; + + case SND_TIMEOUT: + timeout.tv_sec = value/1000000000; + timeout.tv_usec = value%1000000000;//less than rt_period? if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_SNDTIMEO, - (char *)&snd_timeout,sizeof(snd_timeout))) { + (char *)&timeout,sizeof(timeout))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "snd_timeout= %d usecs\n", snd_timeout.tv_usec); + printf( "send timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec); } - } - - /******************* interface level options *************************/ - else if (option==MTU_SIZE) { /* change MTU of the eth interface */ + break; + + + /******************* interface level options *************************/ + case MTU_SIZE: /* change MTU of the eth interface */ ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name)); - ifr.ifr_mtu =8960; + strncpy(ifr.ifr_name,eth->if_name[Mod_id], sizeof(ifr.ifr_name)); + ifr.ifr_mtu =value; if (ioctl(eth->sockfd[Mod_id],SIOCSIFMTU,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the MTU"); else - printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu); - } else if (option==TX_Q_LEN) { /* change TX queue length of eth interface */ + printf("[ETHERNET] %s MTU size has changed to %d\n",eth->if_name[Mod_id],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,if_name, sizeof(ifr.ifr_name)); - ifr.ifr_qlen =3000 ; + strncpy(ifr.ifr_name,eth->if_name[Mod_id], sizeof(ifr.ifr_name)); + ifr.ifr_qlen =value; if (ioctl(eth->sockfd[Mod_id],SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the txqueuelen"); else - printf("[ETHERNET] %s txqueuelen size has changed to %d\n",DEFAULT_IF,ifr.ifr_qlen); - - + printf("[ETHERNET] %s txqueuelen size has changed to %d\n",eth->if_name[Mod_id],ifr.ifr_qlen); + break; + /******************* device level options *************************/ - } else if (option==COALESCE_PAR) { - if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs 3",DEFAULT_IF) > 0) { - system(system_cmd); + case COALESCE_PAR: + ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs %d",eth->if_name[Mod_id],value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + } printf("[ETHERNET] Coalesce parameters %s\n",system_cmd); } else { perror("[ETHERNET] Can't set coalesce parameters\n"); } + break; - } else if (option==PAUSE_PAR ) { - if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",DEFAULT_IF) > 0) { - system(system_cmd); + case PAUSE_PAR: + if (value==1) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",eth->if_name[Mod_id]); + else if (value==0) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg on rx on tx on",eth->if_name[Mod_id]); + else break; + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + } printf("[ETHERNET] Pause parameters %s\n",system_cmd); } else { perror("[ETHERNET] Can't set pause parameters\n"); } - } else if (option==RING_PAR ) { - if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx 4096 tx 4096",DEFAULT_IF) > 0) { - system(system_cmd); + break; + + case RING_PAR: + ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx %d tx %d",eth->if_name[Mod_id],value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + } printf("[ETHERNET] Ring parameters %s\n",system_cmd); } else { perror("[ETHERNET] Can't set ring parameters\n"); } + break; + default: + break; } + return 0; } -int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg) { +int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) { eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t)); - int card = 0; memset(eth, 0, sizeof(eth_state_t)); - eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 - eth->sample_rate = (unsigned int)openair0_cfg[card].sample_rate; - device->priv = eth; + int card = 0; - printf("ETHERNET: Initializing openair0_device for %s ...\n", ((device->func_type == BBU_FUNC) ? "BBU": "RRH")); + /*hoedcoded!!!!*/ + eth->flags = ETH_UDP_MODE; + eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 + + printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); device->Mod_id = num_devices_eth++; + device->transp_type = ETHERNET_TP; device->trx_start_func = trx_eth_start; device->trx_request_func = trx_eth_request; device->trx_reply_func = trx_eth_reply; - device->trx_write_func = trx_eth_write; - device->trx_read_func = trx_eth_read; device->trx_get_stats_func = trx_eth_get_stats; device->trx_reset_stats_func = trx_eth_reset_stats; - device->trx_end_func = trx_eth_end; - device->trx_stop_func = trx_eth_stop; + device->trx_end_func = trx_eth_end; + device->trx_stop_func = trx_eth_stop; device->trx_set_freq_func = trx_eth_set_freq; device->trx_set_gains_func = trx_eth_set_gains; + + if ((eth->flags & ETH_RAW_MODE) != 0 ) { + device->trx_write_func = trx_eth_write_raw; + device->trx_read_func = trx_eth_read_raw; + } else { + device->trx_write_func = trx_eth_write_udp; + device->trx_read_func = trx_eth_read_udp; + } + /*hoedcoded!!!!*/ + eth->if_name[device->Mod_id] = "eth0"; + device->priv = eth; memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); + + /*iqoffset*/ + /*keep conf*/ + /*usrsignal */ return 0; } + + +/************************************************************************************************************************** + * DEBUGING-RELATED FUNCTIONS * + **************************************************************************************************************************/ +void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag) { + + static int numSend = 1; + static int numRecv = 1; + int num, k; + char tmp[48]; + unsigned short int cksum; + + num = (tx_rx_flag)? numSend++:numRecv++; + for (k = 0; k < 24; k++) sprintf(tmp+k, "%02X", pkt[k]); + cksum = calc_csum((unsigned short *)pkt, bytes>>2); + printf("%s-%s (%06d): %s 0x%04X\n", title,(tx_rx_flag)? "TX":"RX", num, tmp, cksum); +} + +unsigned short calc_csum (unsigned short *buf, int nwords) { + + unsigned long sum; + for (sum = 0; nwords > 0; nwords--) + sum += *buf++; + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return ~sum; +} + +void dump_dev(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + + printf("Ethernet device interface %i configuration:\n" ,device->openair0_cfg.Mod_id); + printf(" Log level is %i :\n" ,device->openair0_cfg.log_level); + printf(" RB number: %i, sample rate: %lf \n" , + device->openair0_cfg.num_rb_dl, device->openair0_cfg.sample_rate); + printf(" Delay: %i, Forward samples: %u \n" , + device->openair0_cfg.tx_delay, device->openair0_cfg.tx_forward_nsamps); + printf(" BBU configured for %i tx/%i rx channels)\n", + device->openair0_cfg.tx_num_channels,device->openair0_cfg.rx_num_channels); + printf(" Running flags: %s %s %s\n", + ((eth->flags & ETH_RAW_MODE) ? "RAW socket mode - ":""), + ((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":""), + ((eth->flags & ETH_LOOP_MODE) ? "loopback mode - ":"")); + printf(" Number of iqs dumped when displaying packets: %i\n\n",eth->iqdumpcnt); + +} + +void inline dump_txcounters(openair0_device *device) { + eth_state_t *eth = (eth_state_t*)device->priv; + printf(" Ethernet device interface %i, tx counters:\n" ,device->openair0_cfg.Mod_id); + printf(" Sent packets: %llu send errors: %i\n", eth->tx_count, eth->num_tx_errors); +} + +void inline dump_rxcounters(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + printf(" Ethernet device interface %i rx counters:\n" ,device->openair0_cfg.Mod_id); + printf(" Received packets: %llu missed packets errors: %i\n", eth->rx_count, eth->num_underflows); +} + +void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag, int nsamps) { + + char *strptr; + eth_state_t *eth = (eth_state_t*)device->priv; + /*need to add ts number of iqs in printf need to fix dump iqs call */ + strptr = (( tx_rx_flag == TX_FLAG) ? "TX" : "RX"); + printf("\n %s, nsamps=%i \n" ,strptr,nsamps); + + if (tx_rx_flag == 1) { + dump_txcounters(device); + printf(" First %i iqs of TX buffer\n",eth->iqdumpcnt); + dump_iqs(buff,eth->iqdumpcnt); + } else { + dump_rxcounters(device); + printf(" First %i iqs of RX buffer\n",eth->iqdumpcnt); + dump_iqs(buff,eth->iqdumpcnt); + } + +} + +void dump_iqs(char * buff, int iq_cnt) { + int i; + for (i=0;i<iq_cnt;i++) { + printf("s%02i: Q=%+ij I=%+i%s",i, + ((iqoai_t *)(buff))[i].q, + ((iqoai_t *)(buff))[i].i, + ((i+1)%3 == 0) ? "\n" : " "); + } +} diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index eabec94ebcba082f1c72929664e452919f7cd5bd..7cf884f8ace52d7c253c36702f0d24987298487d 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -36,6 +36,8 @@ * \note * \warning */ +#ifndef ETHERNET_LIB_H +#define ETHERNET_LIB_H #include <arpa/inet.h> #include <linux/if_packet.h> @@ -47,61 +49,95 @@ #include <net/if.h> #include <netinet/ether.h> -#define MAX_INST 4 -#define DEFAULT_IF "lo" -#define BUF_SIZ 8960 /*Jumbo frame size*/ +#define MAX_INST 4 +#define DEFAULT_IF "lo" + +#define ETH_RAW_MODE 1 +#define ETH_UDP_MODE (1<<1) +#define ETH_LOOP_MODE (1<<2) + +#define TX_FLAG 1 +#define RX_FLAG 0 + + +#define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header)) +#define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp)) +#define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2) +#define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) +#define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) +/* +#define RRH_DEST_MAC0 0x74 +#define RRH_DEST_MAC1 0xd4 +#define RRH_DEST_MAC2 0x35 +#define RRH_DEST_MAC3 0xcc +#define RRH_DEST_MAC4 0x88 +#define RRH_DEST_MAC5 0x45 + +#define BBU_DEST_MAC0 0xd4 +#define BBU_DEST_MAC1 0xbe +#define BBU_DEST_MAC2 0xd9 +#define BBU_DEST_MAC3 0x22 +#define BBU_DEST_MAC4 0x0a +#define BBU_DEST_MAC5 0xac +*/ +/*!\brief opaque ethernet data structure */ typedef struct { - - // opaque eth data struct - //struct eth_if *dev; - // An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend) - + + /*!\brief socket file desc */ int sockfd[MAX_INST]; - struct sockaddr_in dest_addr[MAX_INST]; - + /*!\brief interface name */ + char *if_name[MAX_INST]; + /*!\brief buffer size */ unsigned int buffer_size; - unsigned int timeout_ns; - - //struct eth_metadata meta_rx; - //struct eth_metadata meta_tx; - - unsigned int sample_rate; - // time offset between transmiter timestamp and receiver timestamp; + /*!\brief timeout ms */ + unsigned int rx_timeout_ms; + /*!\brief timeout ms */ + unsigned int tx_timeout_ms; + /*!\brief runtime flags */ + uint32_t flags; + /*!\ time offset between transmiter timestamp and receiver timestamp */ double tdiff; - // use brf_time_offset to get this value - int tx_forward_nsamps; //166 for 20Mhz - - + /*!\ calibration */ + int tx_forward_nsamps; + // -------------------------------- // Debug and output control // -------------------------------- + + /*!\brief number of I/Q samples to be printed */ + int iqdumpcnt; + + /*!\brief number of underflows in interface */ int num_underflows; + /*!\brief number of overflows in interface */ int num_overflows; + /*!\brief number of concesutive errors in interface */ int num_seq_errors; + /*!\brief number of errors in interface's receiver */ int num_rx_errors; + /*!\brief umber of errors in interface's transmitter */ int num_tx_errors; - - uint64_t tx_actual_nsamps; // actual number of samples transmitted + + /*!\brief current TX timestamp */ + openair0_timestamp tx_current_ts; + /*!\brief socket file desc */ + openair0_timestamp rx_current_ts; + /*!\brief actual number of samples transmitted */ + uint64_t tx_actual_nsamps; + /*!\brief actual number of samples received */ uint64_t rx_actual_nsamps; - uint64_t tx_nsamps; // number of planned samples + /*!\brief number of samples to be transmitted */ + uint64_t tx_nsamps; + /*!\brief number of samples to be received */ uint64_t rx_nsamps; - uint64_t tx_count; // number pf packets + /*!\brief number of packets transmitted */ + uint64_t tx_count; + /*!\brief number of packets received */ uint64_t rx_count; - //openair0_timestamp rx_timestamp; } eth_state_t; -#define ETH_META_STATUS_OVERRUN (1 << 0) -#define ETH_META_STATUS_UNDERRUN (1 << 1) - -struct eth_meta_data{ - uint64_t timestamp; - uint32_t flags; - uint32_t status; - unsigned int actual_count; -}; - /*!\brief packet header */ @@ -138,9 +174,37 @@ typedef enum { MAX_OPT } eth_opt_t; +/* +#define SND_BUF_SIZE 1 +#define RCV_BUF_SIZE 1<<1 +#define SND_TIMEOUT 1<<2 +#define RCV_TIMEOUT 1<<3 +#define MTU_SIZE 1<<4 +#define TX_Q_LEN 1<<5 +#define RING_PAR 1<<5 +#define COALESCE_PAR 1<<6 +#define PAUSE_PAR 1<<7 +*/ + +/*!\brief I/Q samples */ +typedef struct { + /*!\brief phase */ + short i; + /*!\brief quadrature */ + short q; +} iqoai_t ; + +void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag); +unsigned short calc_csum (unsigned short *buf, int nwords); +void dump_dev(openair0_device *device); +void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag,int nsamps); +void inline dump_rxcounters(openair0_device *device); +void inline dump_txcounters(openair0_device *device); +void dump_iqs(char * buff, int iq_cnt); + -/*! \fn int ethernet_tune (openair0_device *device, eth_opt_t option) +/*! \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 * \param[in] openair0 device which bears the socket * \param[in] name of parameter to configure @@ -148,6 +212,37 @@ typedef enum { * \note * @ingroup _oai */ -int ethernet_tune (openair0_device *device, eth_opt_t option); -int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc) ; -int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int cc); +int ethernet_tune(openair0_device *device, unsigned int option, int value); + + + +/*! \fn int eth_socket_init_udp(openair0_device *device) +* \brief initialization of UDP Socket to communicate with one destination +* \param[in] *device openair device for which the socket will be created +* \param[out] +* \return 0 on success, otherwise -1 +* \note +* @ingroup _oai +*/ +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, void **buff, int nsamps, int cc); +int eth_get_dev_conf_udp(openair0_device *device); + +/*! \fn static int eth_set_dev_conf_udp(openair0_device *device) +* \brief +* \param[in] *device openair device +* \param[out] +* \return 0 on success, otherwise -1 +* \note +* @ingroup _oai +*/ +int eth_set_dev_conf_udp(openair0_device *device); +int eth_socket_init_raw(openair0_device *device); +int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int eth_get_dev_conf_raw(openair0_device *device); +int eth_set_dev_conf_raw(openair0_device *device); + + +#endif diff --git a/targets/RT/USER/UE_transport_IQ.c b/targets/RT/USER/UE_transport_IQ.c index a52e3654aec845ab9666e7402fc0db65f2db81d1..055b45ba727ba42a5af06aecbb8ac8234143ac29 100644 --- a/targets/RT/USER/UE_transport_IQ.c +++ b/targets/RT/USER/UE_transport_IQ.c @@ -284,7 +284,7 @@ void *rrh_UE_thread(void *arg) { tx_buffer_UE[i]=(tmp+4*sizeof(int32_t)); } - printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg.remote_ip, + printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg.remote_addr, dev->eth_dev.openair0_cfg.remote_port, dev->eth_dev.openair0_cfg.num_rb_dl, dev->eth_dev.openair0_cfg.rx_num_channels, diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index fffe93ab5fa6d46876ffb568d8dddac86225fcd8..0b4b6c5fc6aa8cbef61f8ca3e8e3cd3d4f13fc8a 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -140,17 +140,17 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { RT_flag_eNB=RT_flag; NRT_flag_eNB=NRT_flag; - - /* handshake with client to exchange parameters */ + + /* init socket and have handshake-like msg with client to exchange parameters */ mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id - + if (1==0) { /* if a RF iterface is added to RRH module get the configuration parameters sent from eNB */ - if (mod_enb->devs->type != NONE_IF ) { +if (mod_enb->devs->type != NONE_DEV ) { memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); /* certain parameters have to be updated (calibration related)*/ - if ( mod_enb->devs->type == EXMIMO_IF ) { + if ( mod_enb->devs->type == EXMIMO_DEV ) { if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { mod_enb->devs->openair0_cfg.samples_per_packet = 2048; mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; @@ -172,7 +172,7 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { mod_enb->devs->openair0_cfg.tx_delay = 8; } } - else if (mod_enb->devs->type == USRP_IF) { + else if (mod_enb->devs->type == USRP_DEV) { if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { mod_enb->devs->openair0_cfg.samples_per_packet = 2048; mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; @@ -194,7 +194,7 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { mod_enb->devs->openair0_cfg.tx_delay = 8; } } - else if(mod_enb->devs->type == BLADERF_IF) { + else if(mod_enb->devs->type == BLADERF_DEV) { if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { mod_enb->devs->openair0_cfg.samples_per_packet = 2048; mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; @@ -221,24 +221,42 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { check_dev_config(mod_enb); /* initialize and configure the RF device */ - if (openair0_device_init(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){ + if (openair0_device_load(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){ LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); exit(-1); - } - else { + } else { LOG_I(RRH,"RF device has been successfully initialized.\n"); - } + } + + } - /* start RF device */ - if (mod_enb->devs->type == EXMIMO_IF ) { - } else { - if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0) - LOG_E(RRH,"Unable to initiate RF device.\n"); - } - LOG_I(RRH,"RF device has been initiated.\n"); + + memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); + + /* check sanity of configuration parameters and print */ + check_dev_config(mod_enb); + + /* initialize and configure the RF device */ + if (openair0_device_load(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){ + LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); + exit(-1); + } else { + if (mod_enb->devs->type != NONE_DEV) { + /* start RF device */ + if (mod_enb->devs->type == EXMIMO_DEV) { + //call start function for exmino + } else { + if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0) + LOG_E(RRH,"Unable to initiate RF device.\n"); + else + LOG_I(RRH,"RF device has been initiated.\n"); + } + + } + } } - + /* create main eNB module thread main_rrh_eNB_thread allocates memory for TX/RX buffers and creates TX/RX @@ -287,14 +305,14 @@ void *rrh_eNB_thread(void *arg) { tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32)); rx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) ); - LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p\n",i,rx_buffer_eNB[i],tmp); + LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p samples_per_frame=%d\n",i,rx_buffer_eNB[i],tmp, samples_per_frame); } /* tx_buffer_eNB points to the beginning of data */ for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) { tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32)); tx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) ); - LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p \n",i,tx_buffer_eNB[i],tmp); + LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p samples_per_frame=%d\n",i,tx_buffer_eNB[i],tmp, samples_per_frame); } /* dummy initialization for TX/RX buffers */ for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) { @@ -353,7 +371,7 @@ void *rrh_eNB_thread(void *arg) { } /* create timer thread; when no RF device is present a software clock is generated */ - if (dev->devs->type == NONE_IF) { + if (dev->devs->type == NONE_DEV) { int error_code_timer; pthread_t main_timer_proc_thread; @@ -405,10 +423,11 @@ void *rrh_eNB_thread(void *arg) { return(0); } +/* Receive from RF and transmit to RRH */ void *rrh_eNB_rx_thread(void *arg) { - /* measuremnt related vars */ + /* measurement related vars */ struct timespec time0,time1,time2; unsigned long long max_rx_time=0, min_rx_time=rt_period, total_rx_time=0, average_rx_time=rt_period, s_period=0, trial=0; int trace_cnt=0; @@ -463,7 +482,7 @@ void *rrh_eNB_rx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, pck_rx ); LOG_D(RRH,"pack=%d rx_pos=%d subframe=%d frame=%d\n ",pck_rx, rx_pos, subframe,frame); - if (dev->devs->type == NONE_IF) { + if (dev->devs->type == NONE_DEV) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT, hw_counter ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT, last_hw_counter ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_CNT, s_cnt ); @@ -506,7 +525,7 @@ void *rrh_eNB_rx_thread(void *arg) { LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_rx); } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos ); - if (dev->devs->type != NONE_IF) { + if (dev->devs->type != NONE_DEV) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF, 1 ); /* Read operation to RF device (RX)*/ if ( dev->devs->trx_read_func (dev->devs, @@ -533,7 +552,7 @@ void *rrh_eNB_rx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); /* when there is no RF timestamp is updated by number of samples */ - if (dev->devs->type == NONE_IF) { + if (dev->devs->type == NONE_DEV) { timestamp_rx+=spp_eth; last_hw_counter=hw_counter; } @@ -559,7 +578,7 @@ void *rrh_eNB_rx_thread(void *arg) { } if (s_period++ == PRINTF_PERIOD) { s_period=0; - LOG_I(RRH,"Average eNB RX time : %lu\tMax RX time : %lu\tMin RX time : %lu\n",average_rx_time,max_rx_time,min_rx_time); + LOG_I(RRH,"Average eNB RX time : %lu ns\tMax RX time : %lu ns\tMin RXX time : %lu ns\n",average_rx_time,max_rx_time,min_rx_time); } } @@ -577,17 +596,7 @@ void *rrh_eNB_rx_thread(void *arg) { next_rx_pos=(rx_pos+spp_eth); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 ); - /**/ - if (frame>50) { - pthread_mutex_lock(&sync_trx_mutex); - while (sync_trx) { - pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex); - } - sync_trx=1; - LOG_D(RRH,"out of while send:%d %d\n",sync_trx,frame); - pthread_cond_signal(&sync_trx_cond); - pthread_mutex_unlock(&sync_trx_mutex); - } + } // while subframe++; @@ -609,6 +618,7 @@ void *rrh_eNB_rx_thread(void *arg) { return 0; } +/* Receive from eNB and transmit to RF */ void *rrh_eNB_tx_thread(void *arg) { @@ -660,45 +670,13 @@ void *rrh_eNB_tx_thread(void *arg) { while (rrh_exit == 0) { while (tx_pos < (1 + subframe)*samples_per_subframe) { - LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame); - pthread_mutex_lock(&sync_trx_mutex); - - while (!sync_trx) { - LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame); - pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex); - } - LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, subframe ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK, pck_tx ); - - /* - if (dev->devs->type == NONE_IF) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT, hw_counter ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, last_hw_counter ); - - if (!eNB_tx_started) { - eNB_tx_started=1; // set this flag to 1 to indicate that eNB started - if (RT_flag_eNB==1) { - last_hw_counter=hw_counter; - } - } else { - if (RT_flag_eNB==1) { - if (hw_counter > last_hw_counter+1) { - printf("LT"); - } else { - while ((hw_counter < last_hw_counter+1)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 1 ); - nanosleep(&time_req_1us,&time_rem_1us); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 0 ); - } - } - } - } - } */ - + if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1); for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos]; //RF!!!!! @@ -715,7 +693,7 @@ void *rrh_eNB_tx_thread(void *arg) { } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - if (dev->devs->type != NONE_IF) { + if (dev->devs->type != NONE_DEV) { LOG_D(RRH," tx_buffer_eNB[i][tx_pos]=%x t_buffer_eNB[i][tx_pos+1]=%x t_buffer_eNB[i][tx_pos+2]=%x \n",tx_buffer_eNB[0][tx_pos],tx_buffer_eNB[0][tx_pos+1],tx_buffer_eNB[0][tx_pos+2]); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 1 ); /* Write operation to RF device (TX)*/ @@ -733,7 +711,7 @@ void *rrh_eNB_tx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_tx&0xffffffff ); - if (dev->devs->type == NONE_IF) last_hw_counter=hw_counter; + if (dev->devs->type == NONE_DEV) last_hw_counter=hw_counter; if (loopback ==1 ) { @@ -755,9 +733,7 @@ void *rrh_eNB_tx_thread(void *arg) { pck_tx++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 ); - sync_trx=0; - pthread_cond_signal(&sync_trx_cond); - pthread_mutex_unlock(&sync_trx_mutex); + } /* wrap around tx buffer index */ @@ -784,8 +760,7 @@ static void calc_rt_period_ns( openair0_config_t openair0_cfg) { static void check_dev_config( rrh_module_t *mod_enb) { - - + AssertFatal( (mod_enb->devs->openair0_cfg.num_rb_dl==100 || mod_enb->devs->openair0_cfg.num_rb_dl==50 || mod_enb->devs->openair0_cfg.num_rb_dl==25 || mod_enb->devs->openair0_cfg.num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg.num_rb_dl); AssertFatal( mod_enb->devs->openair0_cfg.samples_per_frame > 0 , "Invalid number of samples per frame! %d\n",mod_enb->devs->openair0_cfg.samples_per_frame); AssertFatal( mod_enb->devs->openair0_cfg.sample_rate > 0.0, "Invalid sample rate! %f\n", mod_enb->devs->openair0_cfg.sample_rate); @@ -802,7 +777,7 @@ static void check_dev_config( rrh_module_t *mod_enb) { printf("\n---------------------RF device configuration parameters---------------------\n"); - printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_delay=%d\n \ttx_forward_nsamps=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n \trem_addr %s:%d\n \tmy_addr %s:%d\n", + printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_delay=%d\n \ttx_forward_nsamps=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n", mod_enb->devs->openair0_cfg.Mod_id, mod_enb->devs->openair0_cfg.log_level, mod_enb->devs->openair0_cfg.num_rb_dl, @@ -836,11 +811,7 @@ static void check_dev_config( rrh_module_t *mod_enb) { mod_enb->devs->openair0_cfg.rx_gain_offset[3], mod_enb->devs->openair0_cfg.rx_bw, mod_enb->devs->openair0_cfg.tx_bw, - mod_enb->devs->openair0_cfg.autocal[0], - mod_enb->devs->openair0_cfg.remote_ip, - mod_enb->devs->openair0_cfg.remote_port, - mod_enb->devs->openair0_cfg.my_ip, - mod_enb->devs->openair0_cfg.my_port + mod_enb->devs->openair0_cfg.autocal[0] ); printf("----------------------------------------------------------------------------\n"); diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index 39b726ae07472a200c274f307005e399903848db..c479c2a2118eb7116f1b53f9c9c97c24f74fafbd 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -51,9 +51,9 @@ #include <time.h> #include "common_lib.h" -#include "rrh_gw.h" // change to rrh_new.h, put externs in rrh_extern.h +#include "rrh_gw.h" #include "rt_wrapper.h" -#include "rrh_gw_externs.h" // change to rrh_new.h, put externs in rrh_extern.h +#include "rrh_gw_externs.h" #include "log_if.h" @@ -72,7 +72,8 @@ -char rrh_ip[20] = "192.168.12.242"; // there is code to detect the my ip address +char rrh_ip[20] = "0.0.0.0"; // there is code to detect my ip address +unsigned char rrh_mac[6] = "0:0:0:0:0:0"; int rrh_port = 50000; // has to be an option /* log */ @@ -86,7 +87,7 @@ int16_t ue_log_level = LOG_INFO; int16_t ue_log_verbosity = LOG_MED; -/* flags definitions */ +/* flag definitions */ uint8_t eNB_flag=0; uint8_t UE_flag=0; uint8_t EXMIMO_flag=0; @@ -102,10 +103,8 @@ uint8_t measurements_flag=0; - default ethernet interface is local */ uint8_t num_eNB_mod=0; uint8_t num_UE_mod=0; -uint8_t num_EXMIMO_mod=0; -uint8_t num_USRP_mod=0; -uint8_t hardware_target=NONE_IF; char* if_name="lo"; +uint8_t eth_mode=ETH_UDP_MODE; rrh_module_t *enb_array; rrh_module_t *ue_array; @@ -128,14 +127,14 @@ static void print_help(void); */ static rrh_module_t new_module(unsigned int id); -/*!\fn static int get_ip_address(char* if_name) +/*!\fn static int get_address(char* if_name, uint8_t flag); * \brief retrieves IP address from the specified network interface * \param[in] name of network interface * \return 0 * \note * @ingroup _oai */ -static int get_ip_address(char* if_name); +static int get_address(char* if_name, uint8_t flag); @@ -192,48 +191,45 @@ static rrh_module_t new_module (unsigned int id) { rrh_mod.measurements=measurements_flag; /* each module is associated with an ethernet device */ - rrh_mod.eth_dev.type=ETH_IF; + rrh_mod.eth_dev.type=NONE_DEV; + rrh_mod.eth_dev.transp_type=NONE_TP; /* ethernet device is functioning within RRH */ - rrh_mod.eth_dev.func_type=RRH_FUNC; - /* specify IP address */ - get_ip_address(if_name); - openair0_cfg.my_ip=&rrh_ip[0]; - openair0_cfg.my_port=rrh_port; + rrh_mod.eth_dev.host_type=RRH_HOST; + /* get IP and MAC address */ + get_address(if_name,eth_mode); + + if(eth_mode==ETH_UDP_MODE) { + openair0_cfg.my_addr = &rrh_ip[0]; + openair0_cfg.my_port = rrh_port; + LOG_I(RRH,"UDP mode selected for ethernet.\n"); + } else if (eth_mode==ETH_RAW_MODE) { + openair0_cfg.my_addr = &rrh_mac[0]; + openair0_cfg.my_port = rrh_port; + LOG_I(RRH,"RAW mode selected for ethernet.\n"); + } + + /* if use setrunnig parameters we should keep in device->priv keep if_name and raw/udp flag*/ /* ethernet device initialization */ - if (openair0_dev_init_eth(&rrh_mod.eth_dev, &openair0_cfg)<0){ + if (openair0_transport_load(&rrh_mod.eth_dev, &openair0_cfg)<0,NULL) { LOG_E(RRH,"Exiting, cannot initialize ethernet interface.\n"); exit(-1); } /* allocate space and specify associated RF device */ openair0_device *oai_dv = (openair0_device *)malloc(sizeof(openair0_device)); - memset(oai_dv,0, sizeof(openair0_device)); - -#ifdef EXMIMO + memset(oai_dv,0,sizeof(openair0_device)); rrh_mod.devs=oai_dv; - rrh_mod.devs->type=EXMIMO_IF; - LOG_I(RRH,"Setting RF device to EXMIMO\n"); -#elif OAI_USRP - rrh_mod.devs=oai_dv; - rrh_mod.devs->type=USRP_IF; - LOG_I(RRH,"Setting RF device to USRP\n"); -#elif OAI_BLADERF - rrh_mod.devs=oai_dv; - rrh_mod.devs->type=BLADERF_IF; - LOG_I(RRH,"Setting RF device to BLADERF\n"); -#else - rrh_mod.devs=oai_dv; - rrh_mod.devs->type=NONE_IF; - LOG_I(RRH,"Setting RF interface to NONE_IF... \n"); -#endif - + rrh_mod.devs->type=NONE_DEV; + rrh_mod.devs->transp_type=NONE_TP; + rrh_mod.devs->host_type=RRH_HOST; + return rrh_mod; } static void debug_init(void) { - // log initialization + /* log initialization */ logInit(); set_glog(glog_level, glog_verbosity); @@ -241,7 +237,7 @@ static void debug_init(void) { //set_comp_log(ENB_LOG, enb_log_level, enb_log_verbosity, 1); //set_comp_log(UE_LOG, ue_log_level, ue_log_verbosity, 1); - // vcd initialization + /* vcd initialization */ if (ouput_vcd) { vcd_signal_dumper_init("/tmp/openair_dump_rrh.vcd"); @@ -253,7 +249,7 @@ static void get_options(int argc, char *argv[]) { int opt; - while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:w:i:")) != -1) { + while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:m:i:")) != -1) { switch (opt) { case 'n': @@ -273,6 +269,9 @@ static void get_options(int argc, char *argv[]) { printf("RRH interface name is set to %s\n", if_name); } break; + case 'm': + eth_mode=atoi(optarg); + break; case 'r': //rrh_log_level=atoi(optarg); break; @@ -293,49 +292,48 @@ static void get_options(int argc, char *argv[]) { loopback_flag=1; break; case 't': - /*When measurements are enabled statistics related to TX/RX time are printed*/ + /* When measurements are enabled statistics related to TX/RX time are printed */ measurements_flag=1; - break; - case 'w': - /* force to use this target*/ - hardware_target=1; - break; - case 'h': - print_help(); - exit(-1); + break; + case 'h': + print_help(); + exit(-1); default: /* '?' */ //fprintf(stderr, "Usage: \n", argv[0]); exit(-1); - } + } } } -static int get_ip_address(char* if_name) { +static int get_address(char* if_name, uint8_t flag) { int fd; struct ifreq ifr; - - - fd = socket(AF_INET, SOCK_DGRAM, 0); - + + fd = socket(AF_INET, SOCK_DGRAM, 0); /* I want to get an IPv4 IP address */ - ifr.ifr_addr.sa_family = AF_INET; - + ifr.ifr_addr.sa_family = AF_INET; /* I want IP address attached to "if_name" */ strncpy(ifr.ifr_name, if_name, IFNAMSIZ-1); - - if ( ioctl(fd, SIOCGIFADDR, &ifr)<0 ) { - perror("IOCTL:"); - exit(-1); - } + + if (flag==ETH_UDP_MODE) { + if ( ioctl(fd, SIOCGIFADDR, &ifr)<0 ) { + perror("IOCTL:"); + exit(-1); + } + snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); + LOG_I(RRH,"%s: IP address: %s\n",if_name,rrh_ip); + } else if (flag==ETH_RAW_MODE) { + if ( ioctl(fd, SIOCGIFHWADDR, &ifr)<0 ) { + perror("IOCTL:"); + exit(-1); + } + ether_ntoa_r ((unsigned char *)ifr.ifr_hwaddr.sa_data, rrh_mac); + LOG_I(RRH,"%s: MAC address: %s\n",if_name,rrh_mac); + } close(fd); - - /* display result */ - snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); - LOG_I(RRH,"Got IP address %s from interface %s\n", rrh_ip,if_name); - return 0; } @@ -343,19 +341,19 @@ static int get_ip_address(char* if_name) { static void print_help(void) { puts("Usage: \n"); - puts(" sudo -E chrt 99 ./rrh -n1 -g6 -v -t"); + puts(" sudo -E chrt 99 ./rrh -n1 -g6 -v -t -i lo -m1"); puts("Options:\n"); puts("\t -n create eNB module\n"); puts("\t -u create UE module\n"); puts("\t -g define global log level\n"); puts("\t -i set the RRH interface (default lo)\n"); + puts("\t -m set ethernet mode to be used by RRH, valid options: (1:raw, 2:udp) \n"); puts("\t -r define rrh log level\n"); puts("\t -e define eNB log level\n"); puts("\t -x enable real time bahaviour\n"); puts("\t -v enable vcd dump\n"); puts("\t -l enable loopback mode\n"); puts("\t -t enable measurements\n"); - puts("\t -w force to use specified HW\n"); puts("\t -h display info\n"); }