1. update ethernet library-raw/udp modes supported 2. rrh_gw UE/eNB_trasport files updated accordingly
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
/* 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 {
|
||||
return eth_get_dev_conf(device);
|
||||
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;
|
||||
}
|
||||
/* 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 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);
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
return nsamps;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
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 ************************/
|
||||
if (option== SND_BUF_SIZE) { /* transmit socket buffer size */
|
||||
/****************** 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" : " ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
// --------------------------------
|
||||
int num_underflows;
|
||||
int num_overflows;
|
||||
int num_seq_errors;
|
||||
int num_rx_errors;
|
||||
int num_tx_errors;
|
||||
|
||||
/*!\brief number of I/Q samples to be printed */
|
||||
int iqdumpcnt;
|
||||
|
||||
uint64_t tx_actual_nsamps; // actual number of samples transmitted
|
||||
/*!\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;
|
||||
|
||||
/*!\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
|
||||
|
||||
Reference in New Issue
Block a user