Commit 5d778a5c authored by Cedric Roux's avatar Cedric Roux

add debugging tool tcp_bridge

internal use, no documentation, no support.
parent 43d12970
......@@ -563,6 +563,15 @@ add_library(oai_mobipass MODULE ${TPLIB_MOBIPASS_SOURCE} )
get_target_property(mobipas_cflags oai_mobipass COMPILE_FLAGS)
set_target_properties(oai_mobipass PROPERTIES COMPILE_FLAGS "${mobipass_cflags} -fvisibility=hidden")
set(HWLIB_TCP_BRIDGE_SOURCE
${OPENAIR_TARGETS}/ARCH/tcp_bridge/tcp_bridge.c
)
add_library(oai_tcp_bridge MODULE ${HWLIB_TCP_BRIDGE_SOURCE} )
#get_target_property(tcp_bridge_cflags oai_tcp_bridge COMPILE_FLAGS)
#set_target_properties(oai_tcp_bridge PROPERTIES COMPILE_FLAGS "${tcp_bridge_cflags} -fvisibility=hidden")
set_target_properties(oai_tcp_bridge PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
##########################################################
include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON")
......
This is sort of a "TCP driver" to ease debugging. This is mostly internal
to EURECOM. You probably don't want to use it.
Same license as the rest.
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int fullread(int fd, void *_buf, int count)
{
char *buf = _buf;
int ret = 0;
int l;
while (count) {
l = read(fd, buf, count);
if (l <= 0) return -1;
count -= l;
buf += l;
ret += l;
}
return ret;
}
int fullwrite(int fd, void *_buf, int count)
{
char *buf = _buf;
int ret = 0;
int l;
while (count) {
l = write(fd, buf, count);
if (l <= 0) return -1;
count -= l;
buf += l;
ret += l;
}
return ret;
}
#include "common_lib.h"
typedef struct {
int32_t data[30720]; /* max 20MHz */
unsigned long timestamp;
int size;
} input_buffer;
#define BSIZE 16
typedef struct {
int sock;
int samples_per_subframe;
input_buffer b[BSIZE];
int bstart;
int blen;
unsigned long read_timestamp;
} tcp_bridge_state_t;
/****************************************************************************/
/* buffer management */
/* (could be simpler, we are synchronous) */
/* maybe we should lock */
/****************************************************************************/
void put_buffer(tcp_bridge_state_t *t, void *data, int size, unsigned long timestamp)
{
int nextpos;
if (t->blen == BSIZE) { printf("tcp_bridge: buffer full\n"); exit(1); }
if (size > 30720*4) abort();
if (t->blen) {
int lastpos = (t->bstart+t->blen-1) % BSIZE;
if (timestamp != t->b[lastpos].timestamp + t->samples_per_subframe)
{ printf("tcp_bridge: discontinuity\n"); exit(1); }
}
nextpos = (t->bstart+t->blen) % BSIZE;
t->b[nextpos].timestamp = timestamp;
t->b[nextpos].size = size;
memcpy(t->b[nextpos].data, data, size);
t->blen++;
}
void get_buffer(tcp_bridge_state_t *t, void *data, int size, unsigned long timestamp)
{
int pos;
if (t->blen == 0) { printf("tcp_bridge: buffer empty\n"); exit(1); }
if (size >30720*4) abort();
pos = t->bstart;
if (size != t->b[pos].size) { printf("tcp_bridge: bad size\n"); exit(1); }
memcpy(data, t->b[pos].data, size);
t->bstart = (t->bstart + 1) % BSIZE;
t->blen--;
}
/****************************************************************************/
/* end of buffer management */
/****************************************************************************/
/****************************************************************************/
/* network management (read/write) */
/****************************************************************************/
void read_data_from_network(int sock, input_buffer *b)
{
if (fullread(sock, &b->timestamp, sizeof(b->timestamp)) != sizeof(b->timestamp)) goto err;
if (fullread(sock, &b->size, sizeof(b->size)) != sizeof(b->size)) goto err;
if (fullread(sock, b->data, b->size) != b->size) goto err;
return;
err:
printf("tcp_bridge: read_data_from_network fails\n");
exit(1);
}
void write_data_to_network(int sock, input_buffer *b)
{
if (fullwrite(sock, &b->timestamp, sizeof(b->timestamp)) != sizeof(b->timestamp)) goto err;
if (fullwrite(sock, &b->size, sizeof(b->size)) != sizeof(b->size)) goto err;
if (fullwrite(sock, b->data, b->size) != b->size) goto err;
return;
err:
printf("tcp_bridge: write_data_to_network fails\n");
exit(1);
}
/****************************************************************************/
/* end of network management */
/****************************************************************************/
int tcp_bridge_start(openair0_device *device)
{
int i;
int port = 4042;
tcp_bridge_state_t *tcp_bridge = device->priv;
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) { perror("tcp_bridge: socket"); exit(1); }
int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)))
{ perror("tcp_bridge: SO_REUSEADDR"); exit(1); }
struct sockaddr_in addr = {
sin_family: AF_INET,
sin_port: htons(port),
sin_addr: { s_addr: INADDR_ANY }
};
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
{ perror("tcp_bridge: bind"); exit(1); }
if (listen(sock, 5))
{ perror("tcp_bridge: listen"); exit(1); }
printf("tcp_bridge: wait for connection on port %d\n", port);
socklen_t len = sizeof(addr);
int sock2 = accept(sock, (struct sockaddr *)&addr, &len);
if (sock2 == -1)
{ perror("tcp_bridge: accept"); exit(1); }
close(sock);
tcp_bridge->sock = sock2;
/* the other end has to send 10 subframes at startup */
for (i = 0; i < 10; i++)
read_data_from_network(sock2, &tcp_bridge->b[i]);
tcp_bridge->bstart = 0;
tcp_bridge->blen = 10;
printf("tcp_bridge: connection established\n");
return 0;
}
int tcp_bridge_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
int tcp_bridge_reply(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
int tcp_bridge_get_stats(openair0_device* device) { return 0; }
int tcp_bridge_reset_stats(openair0_device* device) { return 0; }
void tcp_bridge_end(openair0_device *device) {}
int tcp_bridge_stop(openair0_device *device) { return 0; }
int tcp_bridge_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { return 0; }
int tcp_bridge_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { return 0; }
int tcp_bridge_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
{
tcp_bridge_state_t *t = device->priv;
input_buffer out;
int i;
//printf("write ts %ld nsamps %d\n", timestamp, nsamps);
if (nsamps > 30720) abort();
/* read buffer timestamped with 'timestamp' if not already here */
for (i = 0; i < t->blen; i++) {
input_buffer *b = &t->b[(t->bstart + i) % BSIZE];
if (b->timestamp == timestamp) break;
}
if (i == t->blen) {
int nextpos = (t->bstart + t->blen) % BSIZE;
if (t->blen == BSIZE) abort();
read_data_from_network(t->sock, &t->b[nextpos]);
t->blen++;
if (t->b[nextpos].timestamp != timestamp) abort();
}
memcpy(out.data, buff[0], nsamps * 4);
out.timestamp = timestamp;
out.size = nsamps * 4;
write_data_to_network(t->sock, &out);
return nsamps;
}
int tcp_bridge_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc)
{
tcp_bridge_state_t *t = device->priv;
input_buffer *b;
if (cc != 1) abort();
if (t->blen == 0) abort();
b = &t->b[t->bstart];
#if 0
typedef struct {
int32_t data[30720]; /* max 20MHz */
unsigned long timestamp;
int size;
} input_buffer;
#endif
if (b->timestamp != t->read_timestamp) abort();
if (b->size != nsamps * 4) abort();
*timestamp = b->timestamp;
memcpy(buff[0], b->data, b->size);
t->read_timestamp += nsamps;
t->bstart = (t->bstart + 1) % BSIZE;
t->blen--;
static unsigned long ts = 0;
//printf("read ts %ld nsamps %d\n", ts, nsamps);
*timestamp = ts;
ts += nsamps;
return nsamps;
}
__attribute__((__visibility__("default")))
int device_init(openair0_device* device, openair0_config_t *openair0_cfg)
{
tcp_bridge_state_t *tcp_bridge = (tcp_bridge_state_t*)malloc(sizeof(tcp_bridge_state_t));
memset(tcp_bridge, 0, sizeof(tcp_bridge_state_t));
/* only 25 or 50 PRBs handled for the moment */
if (openair0_cfg[0].sample_rate != 30720000 &&
openair0_cfg[0].sample_rate != 15360000 &&
openair0_cfg[0].sample_rate != 7680000) {
printf("tcp_bridge: ERROR: only 25, 50 or 100 PRBs supported\n");
exit(1);
}
device->trx_start_func = tcp_bridge_start;
device->trx_get_stats_func = tcp_bridge_get_stats;
device->trx_reset_stats_func = tcp_bridge_reset_stats;
device->trx_end_func = tcp_bridge_end;
device->trx_stop_func = tcp_bridge_stop;
device->trx_set_freq_func = tcp_bridge_set_freq;
device->trx_set_gains_func = tcp_bridge_set_gains;
device->trx_write_func = tcp_bridge_write;
device->trx_read_func = tcp_bridge_read;
device->priv = tcp_bridge;
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000: tcp_bridge->samples_per_subframe = 30720; break;
case 15360000: tcp_bridge->samples_per_subframe = 15360; break;
case 7680000: tcp_bridge->samples_per_subframe = 7680; break;
}
/* let's pretend to be a b2x0 */
device->type = USRP_B200_DEV;
device->openair0_cfg=&openair0_cfg[0];
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment