ethernet_lib.c 6.65 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/*******************************************************************************
    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@eurecom.fr
  
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE

 *******************************************************************************/

 /** ethernet_lib : API to stream I/Q samples over standard ethernet
 * 
 *  Authors: Pedro Dinis    <pedrodinis20@gmail.com>
 *           Lucio Ferreira <lucio.ferreira@inov.pt>
 *           Raymond Knopp  <raymond.knopp@eurecom.fr>
 * 
 *  Changelog:
 *  06.10.2014: Initial version
 */

#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>
49 50
#include <unistd.h>
#include <errno.h>
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

#include "common_lib.h"

#define DEFAULT_IF	"eth0"
#define BUF_SIZ		8960 /*Jumbo frame size*/
#define MAX_INST        4

int sockfd[MAX_INST];
struct sockaddr_in dest_addr[MAX_INST];
int dest_addr_len[MAX_INST];

int i;
int tx_len = 0;
char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/
 

/**PDF: Initialization of UDP Socket to communicate with one DEST */
int ethernet_socket_init(int Mod_id, char *dest_ip,int dest_port)
{  
  
  /**PDF: To be passed by input argument*/
  //  DEST_port = 32000;
  struct sockaddr_in *dest = &dest_addr[Mod_id];
  char str[INET_ADDRSTRLEN];

  /* Open RAW socket to send on */

78
  if ((sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
79 80 81 82 83 84 85 86 87 88 89
    perror("ETHERNET: Error opening socket");
    exit(0);
  }

  bzero((void *)dest,sizeof(struct sockaddr));
  dest->sin_family = AF_INET;
  dest->sin_addr.s_addr=inet_addr(dest_ip);
  dest->sin_port=htons(dest_port);
  dest_addr_len[Mod_id] = sizeof(struct sockaddr);

  inet_ntop(AF_INET, &(dest->sin_addr), str, INET_ADDRSTRLEN);      
90
  printf("Connecting to %s:%d\n",str,ntohs(dest->sin_port));
91 92 93 94 95 96


}
  


97
int ethernet_write_data(int Mod_id, openair0_timestamp timestamp, const void **buff, int antenna_id, int nsamps) {
98

99
  void *buff2 = (void*)buff[antenna_id]-sizeof(openair0_timestamp)-(sizeof(int16_t)*2);
100 101 102 103 104 105 106 107 108
  int32_t temp0 = *(int32_t *)buff2;
  openair0_timestamp temp1 = *(openair0_timestamp *)(buff2+(sizeof(int16_t)*2));

  int n_written;
  
  n_written = 0;
  ((int16_t *)buff2)[0] = 1+(antenna_id<<1);
  ((int16_t *)buff2)[1] = nsamps;
  *((openair0_timestamp *)(buff2+(sizeof(int16_t)*2))) = timestamp;
109
  //printf("Timestamp TX sent : %d\n",timestamp);
110

111
//  printf("buffer head : %d %d %d %d \n",((int16_t *)buff2)[0],((int16_t *)buff2)[1],((int16_t *)buff2)[2],((int16_t *)buff2)[3]);
112
  while(n_written < (nsamps<<2)) {
113 114 115 116
    /* Send packet */
    if ((n_written += sendto(sockfd[Mod_id], 
			     buff2,
			     (nsamps<<2)+sizeof(openair0_timestamp)+(2*sizeof(int16_t)), 
117
			     MSG_DONTWAIT, 
118 119 120
			     (struct sockaddr*)&dest_addr[Mod_id], 
			     dest_addr_len[Mod_id])) < 0) {
      printf("Send failed for Mod_id %d\n",Mod_id);
121
      perror("ETHERNET:");
122 123 124 125 126 127 128 129 130 131
      exit(-1);
    }    
  }
  *(int32_t *)buff2 = temp0;
  *(openair0_timestamp *)(buff2+2*sizeof(int16_t)) = temp1;
  return n_written;
  
}


132
int ethernet_read_data(int Mod_id,openair0_timestamp *timestamp,void **buff, int antenna_id, int nsamps) {
133

134
  void *buff2 = (void*)buff[antenna_id]-sizeof(openair0_timestamp);
135
  int bytes_received;
136 137
  int block_cnt;
  int ret;
138
  openair0_timestamp temp = *(openair0_timestamp*)(buff2);
139 140 141 142 143
  int16_t mesg[2];

  mesg[0] = 0+(antenna_id<<1);
  mesg[1] = nsamps;

144

145 146
  // send command RX for nsamps samples

147
  sendto(sockfd[Mod_id],mesg,4,MSG_DONTWAIT,(struct sockaddr *)&dest_addr[Mod_id],dest_addr_len[Mod_id]);
148

149
  bytes_received=0;
150
  block_cnt=0;
151
  while(bytes_received < (int)((nsamps<<2))) {
152
    //printf("requesting %d bytes\n",(nsamps<<2));
153
    ret=recvfrom(sockfd[Mod_id],
154 155
		 buff2+bytes_received,
		 (nsamps<<2)+sizeof(openair0_timestamp)-bytes_received,
156 157 158
		 0,//MSG_DONTWAIT,
		 (struct sockaddr *)&dest_addr[Mod_id],
		 &dest_addr_len[Mod_id]);
159
    //printf("bytes_received %d (ret %d)\n",bytes_received+ret,ret);
160 161 162 163 164 165 166 167 168 169 170 171
    if (ret==-1) {
      if (errno == EAGAIN) {
	perror("ETHERNET: ");
	return((nsamps<<2)+sizeof(openair0_timestamp));
      }
      else if (errno == EWOULDBLOCK) {
	block_cnt++;
	usleep(10);
	if (block_cnt == 100) return(-1);
      }
    }
    else {
172
      bytes_received+=ret;
173 174
    }
  }
175 176


177 178
  //printf("buffer head : %x %x %x %x \n",((int32_t *)buff2)[0],((int32_t *)buff2)[1],((int32_t *)buff2)[2],((int32_t *)buff2)[3]);
  *timestamp =  *(openair0_timestamp *)(buff2);
179
//  printf("Received %d samples, timestamp = %d\n",bytes_received>>2,*(int32_t*)timestamp);
180 181
  *(openair0_timestamp *)(buff2) = temp;
  return nsamps;
182 183 184 185 186 187 188 189 190 191
  
}


int trx_eth_start(openair0_device *openair0) {

  return(ethernet_socket_init(openair0->openair0_cfg.Mod_id, openair0->openair0_cfg.rrh_ip,openair0->openair0_cfg.rrh_port));

}

192
void trx_eth_write(openair0_device *device, openair0_timestamp timestamp, const void **buff, int nsamps, int cc, int flags)
193
{
194 195 196
  int i;
  for (i=0;i<cc;i++)
    ethernet_write_data(device->Mod_id,timestamp,buff,i,nsamps);
197
}
198
int trx_eth_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int cc) {
199

200 201
  int i;
  for (i=0;i<cc;i++)
202
    return(ethernet_read_data(device->Mod_id,ptimestamp,buff,i,nsamps));
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225

}

void trx_eth_end(openair0_device *device) {




}

int num_devices = 0;

int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg)
{

  printf("ETHERNET: Initializing openair0_device\n");
  device->Mod_id         = num_devices++;
  device->trx_start_func = trx_eth_start;
  device->trx_end_func   = trx_eth_end;
  device->trx_read_func  = trx_eth_read;
  device->trx_write_func = trx_eth_write;
  memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
}