add debugging tool tcp_bridge
internal use, no documentation, no support.
This commit is contained in:
@@ -563,6 +563,15 @@ add_library(oai_mobipass MODULE ${TPLIB_MOBIPASS_SOURCE} )
|
|||||||
get_target_property(mobipas_cflags oai_mobipass COMPILE_FLAGS)
|
get_target_property(mobipas_cflags oai_mobipass COMPILE_FLAGS)
|
||||||
set_target_properties(oai_mobipass PROPERTIES COMPILE_FLAGS "${mobipass_cflags} -fvisibility=hidden")
|
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")
|
include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON")
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
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.
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user