Commit 11fd202d authored by laurent's avatar laurent

fix compilation, attach complete

parent c17f65f1
...@@ -3299,6 +3299,7 @@ int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, ...@@ -3299,6 +3299,7 @@ int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index,
msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ); msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ);
itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p);
LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n");
} }
} }
#endif #endif
...@@ -5111,6 +5112,7 @@ void *rrc_ue_task( void *args_p ) ...@@ -5111,6 +5112,7 @@ void *rrc_ue_task( void *args_p )
break; // PHY_FIND_CELL_IND break; // PHY_FIND_CELL_IND
case PHY_MEAS_REPORT_IND: { case PHY_MEAS_REPORT_IND: {
LOG_D(RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));
MessageDef *message_p; MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_MEASUREMENT_REPORT_IND); message_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_MEASUREMENT_REPORT_IND);
...@@ -5128,6 +5130,7 @@ void *rrc_ue_task( void *args_p ) ...@@ -5128,6 +5130,7 @@ void *rrc_ue_task( void *args_p )
} }
case RRC_RAL_CONFIGURE_THRESHOLD_REQ: case RRC_RAL_CONFIGURE_THRESHOLD_REQ:
LOG_D(RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));
rrc_ue_ral_handle_configure_threshold_request(ue_mod_id, msg_p); rrc_ue_ral_handle_configure_threshold_request(ue_mod_id, msg_p);
break; break;
......
...@@ -280,7 +280,7 @@ bool flushInput(tcp_bridge_state_t *t) { ...@@ -280,7 +280,7 @@ bool flushInput(tcp_bridge_state_t *t) {
else else
blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ? blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ?
b->remainToTransfer : b->remainToTransfer :
b->circularBufEnd - b->transferPtr; b->circularBufEnd - 1 - b->transferPtr ;
int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
...@@ -294,6 +294,8 @@ bool flushInput(tcp_bridge_state_t *t) { ...@@ -294,6 +294,8 @@ bool flushInput(tcp_bridge_state_t *t) {
AssertFatal((b->remainToTransfer-=sz) >= 0, ""); AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz; b->transferPtr+=sz;
if (b->transferPtr==b->circularBufEnd - 1)
b->transferPtr=(char*)b->circularBuf;
// check the header and start block transfer // check the header and start block transfer
if ( b->headerMode==true && b->remainToTransfer==0) { if ( b->headerMode==true && b->remainToTransfer==0) {
......
...@@ -6,296 +6,447 @@ ...@@ -6,296 +6,447 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <stdbool.h>
#include <errno.h> #include <errno.h>
#include <sys/epoll.h>
#include <string.h>
int fullread(int fd, void *_buf, int count) #include <common/utils/assertions.h>
{ #include <common/utils/LOG/log.h>
char *buf = _buf; #include "common_lib.h"
int ret = 0; #include <openair1/PHY/defs_eNB.h>
int l; #include "openair1/PHY/defs_UE.h"
while (count) {
l = read(fd, buf, count); #define PORT 4043 //TCP port for this simulator
if (l <= 0) return -1; #define CirSize 3072000 // 100ms is enough
count -= l; #define sample_t uint32_t // 2*16 bits complex number
buf += l; #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
ret += l; #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
} #define MAGICeNB 0xA5A5A5A5A5A5A5A5
return ret; #define MAGICUE 0x5A5A5A5A5A5A5A5A
typedef struct {
uint64_t magic;
uint32_t size;
uint32_t nbAnt;
uint64_t timestamp;
} transferHeader;
typedef struct buffer_s {
int conn_sock;
bool alreadyWrote;
uint64_t lastReceivedTS;
bool headerMode;
transferHeader th;
char *transferPtr;
uint64_t remainToTransfer;
char *circularBufEnd;
sample_t *circularBuf;
} buffer_t;
typedef struct {
int listen_sock, epollfd;
uint64_t nextTimestamp;
uint64_t typeStamp;
char *ip;
buffer_t buf[FD_SETSIZE];
} tcp_bridge_state_t;
void allocCirBuf(tcp_bridge_state_t *bridge, int sock) {
buffer_t *ptr=&bridge->buf[sock];
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
ptr->conn_sock=sock;
ptr->headerMode=true;
ptr->transferPtr=(char *)&ptr->th;
ptr->remainToTransfer=sizeof(transferHeader);
int sendbuff=1000*1000*10;
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
struct epoll_event ev= {0};
ev.events = EPOLLIN | EPOLLRDHUP;
ev.data.fd = sock;
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
} }
int fullwrite(int fd, void *_buf, int count) void removeCirBuf(tcp_bridge_state_t *bridge, int sock) {
{ AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, "");
close(sock);
free(bridge->buf[sock].circularBuf);
memset(&bridge->buf[sock], 0, sizeof(buffer_t));
bridge->buf[sock].conn_sock=-1;
}
#define helpTxt "\
\x1b[31m\
tcp_bridge: error: you have to run one UE and one eNB\n\
For this, export TCPBRIDGE=enb (eNB case) or \n\
TCPBRIDGE=<an ip address> (UE case)\n\
\x1b[m"
int fullwrite(int fd, void *_buf, int count) {
char *buf = _buf; char *buf = _buf;
int ret = 0; int ret = 0;
int l; int l;
while (count) { while (count) {
l = write(fd, buf, count); l = write(fd, buf, count);
if (l <= 0) return -1;
if (l <= 0) {
if(errno==EAGAIN || errno==EINTR)
continue;
else
return -1;
}
count -= l; count -= l;
buf += l; buf += l;
ret += l; ret += l;
} }
return ret; return ret;
} }
#include "common_lib.h" enum blocking_t {
blocking,
notBlocking
};
typedef struct { void setblocking(int sock, enum blocking_t active) {
int sock; int opts;
int samples_per_subframe; AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,"");
uint64_t timestamp;
uint64_t next_tx_timestamp;
int is_enb;
} tcp_bridge_state_t;
void verify_connection(int fd, int is_enb) if (active==blocking)
{ opts = opts & ~O_NONBLOCK;
char c = is_enb; else
if (fullwrite(fd, &c, 1) != 1) exit(1); opts = opts | O_NONBLOCK;
if (fullread(fd, &c, 1) != 1) exit(1);
if (c == is_enb) { AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, "");
printf("\x1b[31mtcp_bridge: error: you have to run one UE and one eNB"
" (did you run 'export ENODEB=1' in the eNB terminal?)\x1b[m\n");
exit(1);
}
} }
int tcp_bridge_start(openair0_device *device)
{
int port = 4043;
tcp_bridge_state_t *tcp_bridge = device->priv;
int try;
int max_try = 5;
int sock = socket(AF_INET, SOCK_STREAM, 0); tcp_bridge_state_t *init_bridge(openair0_device *device) {
if (sock == -1) { perror("tcp_bridge: socket"); exit(1); } tcp_bridge_state_t *tcp_bridge;
if (device->priv)
tcp_bridge=(tcp_bridge_state_t *) device->priv;
else
AssertFatal(((tcp_bridge=(tcp_bridge_state_t *)calloc(sizeof(tcp_bridge_state_t),1))) != NULL, "");
for (int i=0; i<FD_SETSIZE; i++)
tcp_bridge->buf[i].conn_sock=-1;
device->priv = tcp_bridge;
AssertFatal((tcp_bridge->epollfd = epoll_create1(0)) != -1,"");
return tcp_bridge;
}
int server_start(openair0_device *device) {
tcp_bridge_state_t *t = init_bridge(device);
t->typeStamp=MAGICeNB;
AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
int enable = 1; int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))) AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
{ 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 }
};
bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
AssertFatal(listen(t->listen_sock, 5) == 0, "");
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = t->listen_sock;
AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, "");
return 0;
}
int start_ue(openair0_device *device) {
tcp_bridge_state_t *t = init_bridge(device);
t->typeStamp=MAGICUE;
int sock;
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
struct sockaddr_in addr = { struct sockaddr_in addr = {
sin_family: AF_INET, sin_family: AF_INET,
sin_port: htons(port), sin_port: htons(PORT),
sin_addr: { s_addr: INADDR_ANY } sin_addr: { s_addr: INADDR_ANY }
}; };
addr.sin_addr.s_addr = inet_addr(t->ip);
bool connected=false;
while(!connected) {
printf("tcp_bridge: trying to connect to %s:%d\n", t->ip, PORT);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) { if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
if (errno == EADDRINUSE) goto client_mode; printf("tcp_bridge: connection established\n");
{ perror("tcp_bridge: bind"); exit(1); } connected=true;
} }
if (listen(sock, 5)) perror("tcp_bridge");
{ perror("tcp_bridge: listen"); exit(1); } sleep(1);
}
printf("tcp_bridge: wait for connection on port %d\n", port); setblocking(sock, notBlocking);
allocCirBuf(t, sock);
t->buf[sock].alreadyWrote=true;
return 0;
}
socklen_t len = sizeof(addr); int tcp_bridge_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
int sock2 = accept(sock, (struct sockaddr *)&addr, &len);
if (sock2 == -1)
{ perror("tcp_bridge: accept"); exit(1); }
close(sock); tcp_bridge_state_t *t = device->priv;
tcp_bridge->sock = sock2; for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *ptr=&t->buf[i];
printf("tcp_bridge: connection established\n"); if (ptr->conn_sock >= 0 ) {
setblocking(ptr->conn_sock, blocking);
transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp};
int n=-1;
verify_connection(sock2, tcp_bridge->is_enb); AssertFatal( fullwrite(ptr->conn_sock,&header, sizeof(header)) == sizeof(header), "");
sample_t tmpSamples[nsamps][nbAnt];
for(int a=0; a<nbAnt; a++) {
sample_t* in=(sample_t*)samplesVoid[a];
for(int s=0; s<nsamps; s++)
tmpSamples[s][a]=in[s];
}
n = fullwrite(ptr->conn_sock, (void*)tmpSamples, sampleToByte(nsamps,nbAnt));
return 0; if (n != sampleToByte(nsamps,nbAnt) ) {
printf("tcp_bridge: write error ret %d (wanted %ld) error %s\n", n, sampleToByte(nsamps,nbAnt), strerror(errno));
abort();
}
client_mode: ptr->alreadyWrote=true;
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); setblocking(ptr->conn_sock, notBlocking);
}
}
for (try = 0; try < max_try; try++) { LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
if (try != 0) sleep(1); nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) );
return nsamps;
}
printf("tcp_bridge: trying to connect to 127.0.0.1:%d (attempt %d/%d)\n", bool flushInput(tcp_bridge_state_t *t) {
port, try+1, max_try); // Process all incoming events on sockets
// store the data in lists
bool completedABuffer=false;
int iterations=10;
while (!completedABuffer && iterations-- ) {
struct epoll_event events[FD_SETSIZE]= {0};
int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 20);
if ( nfds==-1 ) {
if ( errno==EINTR || errno==EAGAIN )
continue;
else
AssertFatal(false,"error in epoll_wait\n");
}
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { //printf("waited iter=%d, res %d, waiting fd %d\n", iterations, nfds, nfds>=1? events[0].data.fd:-1);
printf("tcp_bridge: connection established\n");
tcp_bridge->sock = sock; for (int nbEv = 0; nbEv < nfds; ++nbEv) {
verify_connection(sock, tcp_bridge->is_enb); int fd=events[nbEv].data.fd;
return 0;
if (events[nbEv].events & EPOLLIN && fd == t->listen_sock) {
int conn_sock;
AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, "");
allocCirBuf(t, conn_sock);
LOG_I(HW,"A ue connected\n");
} else {
if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) {
LOG_W(HW,"Lost socket\n");
removeCirBuf(t, fd);
if (t->typeStamp==MAGICUE)
exit(1);
continue;
} }
perror("tcp_bridge"); buffer_t *b=&t->buf[fd];
if ( b->circularBuf == NULL ) {
LOG_E(HW, "received data on not connected socket %d\n", events[nbEv].data.fd);
continue;
} }
printf("tcp_bridge: connection failed\n"); int blockSz;
exit(1); if ( b->headerMode)
} blockSz=b->remainToTransfer;
else
blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ?
b->remainToTransfer :
b->circularBufEnd - b->transferPtr;
int tcp_bridge_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; } int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
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) if ( sz < 0 ) {
{ if ( errno != EAGAIN ) {
if (cc != 1) { printf("tcp_bridge: only 1 antenna supported\n"); exit(1); } LOG_E(HW,"socket failed %s\n", strerror(errno));
tcp_bridge_state_t *t = device->priv;
/* deal with discontinuities in output (think: eNB in TDD mode) */
if (t->next_tx_timestamp && timestamp != t->next_tx_timestamp) {
uint32_t b[4096];
uint64_t to_send = timestamp - t->next_tx_timestamp;
memset(b, 0, 4096 * sizeof(uint32_t));
while (to_send) {
int len = to_send > 4096 ? 4096 : to_send;
int n = fullwrite(t->sock, b, len * 4);
if (n != len * 4) {
printf("tcp_bridge: write error ret %d error %s\n", n, strerror(errno));
abort(); abort();
} }
to_send -= len; } else if ( sz == 0 )
continue;
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz;
// check the header and start block transfer
if ( b->headerMode==true && b->remainToTransfer==0) {
AssertFatal( (t->typeStamp == MAGICUE && b->th.magic==MAGICeNB) ||
(t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "Socket Error in protocol");
b->headerMode=false;
b->lastReceivedTS=b->th.timestamp;
b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
} }
if ( b->headerMode==false ) {
b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt);
if ( b->remainToTransfer==0) {
completedABuffer=true;
LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS);
// First block in UE, resync with the eNB current TS
if ( t->nextTimestamp == 0 )
t->nextTimestamp=b->lastReceivedTS-b->th.size;
b->headerMode=true;
b->transferPtr=(char *)&b->th;
b->remainToTransfer=sizeof(transferHeader);
b->th.magic=-1;
} }
int n = fullwrite(t->sock, buff[0], nsamps * 4);
if (n != nsamps * 4) {
printf("tcp_bridge: write error ret %d (wanted %d) error %s\n", n, nsamps*4, strerror(errno));
abort();
} }
t->next_tx_timestamp = timestamp + nsamps; }
return nsamps; }
}
return completedABuffer;
} }
int tcp_bridge_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) int tcp_bridge_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
{ if (nbAnt != 1) { printf("tcp_bridge: only 1 antenna tested\n"); exit(1); }
if (cc != 1) { printf("tcp_bridge: only 1 antenna supported\n"); exit(1); }
tcp_bridge_state_t *t = device->priv; tcp_bridge_state_t *t = device->priv;
int n = fullread(t->sock, buff[0], nsamps * 4); // deliver data from received data
if (n != nsamps * 4) { // check if a UE is connected
printf("tcp_bridge: read error ret %d nsamps*4 %d error %s\n", n, nsamps * 4, strerror(errno)); int first_sock;
abort();
for (first_sock=0; first_sock<FD_SETSIZE; first_sock++)
if (t->buf[first_sock].circularBuf != NULL )
break;
if ( first_sock == FD_SETSIZE ) {
// no connected device (we are eNB, no UE is connected)
if (!flushInput(t)) {
for (int x=0; x < nbAnt; x++)
memset(samplesVoid[x],0,sampleToByte(nsamps,1));
t->nextTimestamp+=nsamps;
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
for (int a=0; a<nbAnt; a++) {
sample_t *out=(sample_t *)samplesVoid[a];
for ( int i=0; i < nsamps; i++ )
out[i]=0;
} }
*timestamp = t->timestamp;
t->timestamp += nsamps; *ptimestamp = t->nextTimestamp-nsamps;
return nsamps; return nsamps;
} }
} else {
bool have_to_wait;
int tcp_bridge_read_ue(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) do {
{ have_to_wait=false;
if (cc != 1) { printf("tcp_bridge: only 1 antenna supported\n"); exit(1); }
tcp_bridge_state_t *t = device->priv;
int n;
/* In synch mode, UE does not write, but we need to for ( int sock=0; sock<FD_SETSIZE; sock++)
* send something to the eNodeB. if ( t->buf[sock].circularBuf &&
* We know that UE is in synch mode when it reads t->buf[sock].alreadyWrote &&
* 10 subframes at a time. (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
*/ have_to_wait=true;
if (nsamps == t->samples_per_subframe * 10) { break;
uint32_t b[nsamps];
memset(b, 0, nsamps * 4);
n = fullwrite(t->sock, b, nsamps * 4);
if (n != nsamps * 4) {
printf("tcp_bridge: write error ret %d error %s\n", n, strerror(errno));
abort();
} }
if (have_to_wait)
/*printf("Waiting on socket, current last ts: %ld, expected at least : %ld\n",
ptr->lastReceivedTS,
t->nextTimestamp+nsamps);
*/
flushInput(t);
} while (have_to_wait);
} }
return tcp_bridge_read(device, timestamp, buff, nsamps, cc); // Clear the output buffer
} for (int a=0; a<nbAnt; a++) {
sample_t *out=(sample_t *)samplesVoid[a];
for ( int i=0; i < nsamps; i++ )
out[i]=0;
}
/* To startup proper communcation between eNB and UE, // Add all input signal in the output buffer
* we need to understand that: for (int sock=0; sock<FD_SETSIZE; sock++) {
* - eNodeB starts reading subframe 0 buffer_t *ptr=&t->buf[sock];
* - then eNodeB starts sending subframe 4
* and then repeats read/write for each subframe.
* The UE:
* - reads 10 subframes at a time until it is synchronized
* - then reads subframe n and writes subframe n+2
* We also want to enforce that the subframe 0 is read
* at the beginning of the UE RX buffer, not in the middle
* of it.
* So it means:
* - for the eNodeB: let it run as in normal mode (as with a B210)
* - for the UE, on its very first read:
* - we want this read to get data from subframe 0
* but the first write of eNodeB is subframe 4
* so we first need to read and ignore 6 subframes
* - the UE will start its TX only at the subframe 2
* corresponding to the subframe 0 it just read,
* so we need to write 12 subframes before anything
* (the function tcp_bridge_read_ue takes care to
* insert dummy TX data during the synch phase)
*
* Here is a drawing of the beginning of things to make
* this logic clearer.
*
* We see that eNB starts RX at subframe 0, starts TX at subfram 4,
* and that UE starts RX at subframe 10 and TX at subframe 12.
*
* We understand that the UE has to transmit 12 empty
* subframes for the eNodeB to start its processing.
*
* And because the eNodeB starts its TX at subframe 4 and we
* want the UE to start its RX at subframe 10, we need to
* read and ignore 6 subframes in the UE.
*
* -------------------------------------------------------------------------
* eNB RX: | *0* | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 ...
* -------------------------------------------------------------------------
*
* -------------------------------------------------------------------------
* eNB TX: | 0 | 1 | 2 | 3 | *4* | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 ...
* -------------------------------------------------------------------------
*
* -------------------------------------------------------------------------
* UE RX: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | *10* | 11 | 12 | 13 | 14 ...
* -------------------------------------------------------------------------
*
* -------------------------------------------------------------------------
* UE TX: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | *12* | 13 | 14 ...
* -------------------------------------------------------------------------
*
* As a final note, we do TX before RX to ensure that the eNB will
* get some data and send us something so there is no deadlock
* at the beginning of things. Hopefully the kernel buffers for
* the sockets are big enough so that the first (big) TX can
* return to user mode before the buffers are full. If this
* is wrong in some environment, we will need to work by smaller
* units of data at a time.
*/
int tcp_bridge_ue_first_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc)
{
if (cc != 1) { printf("tcp_bridge: only 1 antenna supported\n"); exit(1); }
tcp_bridge_state_t *t = device->priv;
uint32_t b[t->samples_per_subframe * 12]; if ( ptr->circularBuf && ptr->alreadyWrote ) {
memset(b, 0, t->samples_per_subframe * 12 * 4); for (int a=0; a<nbAnt; a++) {
int n = fullwrite(t->sock, b, t->samples_per_subframe * 12 * 4); sample_t *out=(sample_t *)samplesVoid[a];
if (n != t->samples_per_subframe * 12 * 4) { for ( int i=0; i < nsamps; i++ )
printf("tcp_bridge: write error ret %d error %s\n", n, strerror(errno)); out[i]+=ptr->circularBuf[(t->nextTimestamp+(a*nbAnt+i))%CirSize]<<1;
abort(); }
} }
n = fullread(t->sock, b, t->samples_per_subframe * 6 * 4);
if (n != t->samples_per_subframe * 6 * 4) {
printf("tcp_bridge: read error ret %d error %s\n", n, strerror(errno));
abort();
} }
device->trx_read_func = tcp_bridge_read_ue; *ptimestamp = t->nextTimestamp; // return the time of the first sample
t->nextTimestamp+=nsamps;
LOG_D(HW,"Rx to upper layer: %d from %ld to %ld, energy in first antenna %d\n",
nsamps,
*ptimestamp, t->nextTimestamp,
signal_energy(samplesVoid[0], nsamps));
return nsamps;
}
return tcp_bridge_read_ue(device, timestamp, buff, nsamps, cc); 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;
} }
__attribute__((__visibility__("default"))) __attribute__((__visibility__("default")))
int device_init(openair0_device* device, openair0_config_t *openair0_cfg) int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
{ //set_log(HW,OAILOG_DEBUG);
tcp_bridge_state_t *tcp_bridge = (tcp_bridge_state_t*)malloc(sizeof(tcp_bridge_state_t)); tcp_bridge_state_t *tcp_bridge = (tcp_bridge_state_t *)calloc(sizeof(tcp_bridge_state_t),1);
memset(tcp_bridge, 0, sizeof(tcp_bridge_state_t));
tcp_bridge->is_enb = getenv("ENODEB") != NULL; if ((tcp_bridge->ip=getenv("TCPBRIDGE")) == NULL ) {
printf(helpTxt);
exit(1);
}
printf("tcp_bridge: running as %s\n", tcp_bridge->is_enb ? "eNB" : "UE"); tcp_bridge->typeStamp = strncasecmp(tcp_bridge->ip,"enb",3) == 0 ?
MAGICeNB:
MAGICUE;
printf("tcp_bridge: running as %s\n", tcp_bridge-> typeStamp == MAGICeNB ? "eNB" : "UE");
/* only 25, 50 or 100 PRBs handled for the moment */ /* only 25, 50 or 100 PRBs handled for the moment */
if (openair0_cfg[0].sample_rate != 30720000 && if (openair0_cfg[0].sample_rate != 30720000 &&
...@@ -305,7 +456,9 @@ int device_init(openair0_device* device, openair0_config_t *openair0_cfg) ...@@ -305,7 +456,9 @@ int device_init(openair0_device* device, openair0_config_t *openair0_cfg)
exit(1); exit(1);
} }
device->trx_start_func = tcp_bridge_start; device->trx_start_func = tcp_bridge->typeStamp == MAGICeNB ?
server_start :
start_ue;
device->trx_get_stats_func = tcp_bridge_get_stats; device->trx_get_stats_func = tcp_bridge_get_stats;
device->trx_reset_stats_func = tcp_bridge_reset_stats; device->trx_reset_stats_func = tcp_bridge_reset_stats;
device->trx_end_func = tcp_bridge_end; device->trx_end_func = tcp_bridge_end;
...@@ -313,25 +466,10 @@ int device_init(openair0_device* device, openair0_config_t *openair0_cfg) ...@@ -313,25 +466,10 @@ int device_init(openair0_device* device, openair0_config_t *openair0_cfg)
device->trx_set_freq_func = tcp_bridge_set_freq; device->trx_set_freq_func = tcp_bridge_set_freq;
device->trx_set_gains_func = tcp_bridge_set_gains; device->trx_set_gains_func = tcp_bridge_set_gains;
device->trx_write_func = tcp_bridge_write; device->trx_write_func = tcp_bridge_write;
if (tcp_bridge->is_enb) {
device->trx_read_func = tcp_bridge_read; device->trx_read_func = tcp_bridge_read;
} else {
device->trx_read_func = tcp_bridge_ue_first_read;
}
device->priv = tcp_bridge; 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 */ /* let's pretend to be a b2x0 */
device->type = USRP_B200_DEV; device->type = USRP_B200_DEV;
device->openair0_cfg=&openair0_cfg[0]; device->openair0_cfg=&openair0_cfg[0];
return 0; return 0;
} }
...@@ -783,11 +783,18 @@ static void *UE_thread_rxn_txnp4(void *arg) { ...@@ -783,11 +783,18 @@ static void *UE_thread_rxn_txnp4(void *arg) {
threadname); threadname);
while (!oai_exit) { while (!oai_exit) {
AssertFatal (pthread_mutex_lock(&proc->mutex_rxtx) == 0, "[SCHED][UE] error locking mutex for UE RXTX\n" ); if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
while (proc->instance_cnt_rxtx < 0) LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
exit_fun("nothing to add");
}
while (proc->instance_cnt_rxtx < 0) {
// most of the time, the thread is waiting here // most of the time, the thread is waiting here
pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" ); }
if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
exit_fun("nothing to add");
}
initRefTimes(t2); initRefTimes(t2);
initRefTimes(t3); initRefTimes(t3);
...@@ -861,12 +868,18 @@ static void *UE_thread_rxn_txnp4(void *arg) { ...@@ -861,12 +868,18 @@ static void *UE_thread_rxn_txnp4(void *arg) {
phy_procedures_UE_S_TX(UE,0,0); phy_procedures_UE_S_TX(UE,0,0);
updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)"); updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
AssertFatal (pthread_mutex_lock(&proc->mutex_rxtx) == 0, "[SCHED][UE] error locking mutex for UE RXTX\n" ); if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
exit_fun("noting to add");
}
proc->instance_cnt_rxtx--; proc->instance_cnt_rxtx--;
#if BASIC_SIMULATOR #if 1 //BASIC_SIMULATOR
AssertFatal (pthread_cond_signal(&proc->cond_rxtx) == 0, ""); if (pthread_cond_signal(&proc->cond_rxtx) != 0) abort();
#endif #endif
AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, "[SCHED][UE] error unlocking mutex for UE RXTX\n" ); if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
exit_fun("noting to add");
}
} }
// thread finished // thread finished
...@@ -981,6 +994,7 @@ static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) { ...@@ -981,6 +994,7 @@ static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) {
} }
while (phy_stub_ticking->ticking_var < 0) { while (phy_stub_ticking->ticking_var < 0) {
// most of the time, the thread is waiting here // most of the time, the thread is waiting here
//pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
LOG_D(MAC,"Waiting for ticking_var\n"); LOG_D(MAC,"Waiting for ticking_var\n");
pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking); pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
} }
...@@ -1265,6 +1279,7 @@ static void *UE_phy_stub_thread_rxn_txnp4(void *arg) { ...@@ -1265,6 +1279,7 @@ static void *UE_phy_stub_thread_rxn_txnp4(void *arg) {
} }
while (phy_stub_ticking->ticking_var < 0) { while (phy_stub_ticking->ticking_var < 0) {
// most of the time, the thread is waiting here // most of the time, the thread is waiting here
//pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
LOG_D(MAC,"Waiting for ticking_var\n"); LOG_D(MAC,"Waiting for ticking_var\n");
pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking); pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
} }
...@@ -1456,12 +1471,6 @@ void *UE_thread(void *arg) { ...@@ -1456,12 +1471,6 @@ void *UE_thread(void *arg) {
} }
while (!oai_exit) { while (!oai_exit) {
#if BASIC_SIMULATOR
while (!(UE->proc.instance_cnt_synch < 0)) {
printf("ue sync not ready\n");
usleep(500*1000);
}
#endif
AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
int instance_cnt_synch = UE->proc.instance_cnt_synch; int instance_cnt_synch = UE->proc.instance_cnt_synch;
...@@ -1591,7 +1600,7 @@ void *UE_thread(void *arg) { ...@@ -1591,7 +1600,7 @@ void *UE_thread(void *arg) {
// update thread index for received subframe // update thread index for received subframe
UE->current_thread_id[sub_frame] = thread_idx; UE->current_thread_id[sub_frame] = thread_idx;
#if BASIC_SIMULATOR #if 1 //BASIC_SIMULATOR
{ {
int t; int t;
for (t = 0; t < 2; t++) { for (t = 0; t < 2; t++) {
...@@ -1629,10 +1638,10 @@ void *UE_thread(void *arg) { ...@@ -1629,10 +1638,10 @@ void *UE_thread(void *arg) {
// compute TO compensation that should be applied for this frame // compute TO compensation that should be applied for this frame
if (UE->no_timing_correction == 0) { if (UE->no_timing_correction == 0) {
if ( getenv("RFSIMULATOR") != NULL && UE->rx_offset) { if (UE->rx_offset) {
//LOG_E(HW,"in simu, rx_offset is not null (impossible): %d\n", UE->rx_offset); //LOG_E(HW,"in simu, rx_offset is not null: %d\n", UE->rx_offset);
UE->rx_offset=0; UE->rx_offset=0;
} }
if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti && if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti &&
UE->rx_offset > 0 ) UE->rx_offset > 0 )
UE->rx_offset_diff = -1 ; UE->rx_offset_diff = -1 ;
...@@ -1704,6 +1713,7 @@ void *UE_thread(void *arg) { ...@@ -1704,6 +1713,7 @@ void *UE_thread(void *arg) {
proc->instance_cnt_rxtx++; proc->instance_cnt_rxtx++;
LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx); LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx);
if (proc->instance_cnt_rxtx != 0) { if (proc->instance_cnt_rxtx != 0) {
/*
if ( getenv("RFSIMULATOR") != NULL ) { if ( getenv("RFSIMULATOR") != NULL ) {
do { do {
AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, ""); AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, "");
...@@ -1711,7 +1721,7 @@ void *UE_thread(void *arg) { ...@@ -1711,7 +1721,7 @@ void *UE_thread(void *arg) {
AssertFatal (pthread_mutex_lock(&proc->mutex_rxtx) == 0, ""); AssertFatal (pthread_mutex_lock(&proc->mutex_rxtx) == 0, "");
} while ( proc->instance_cnt_rxtx >= 0); } while ( proc->instance_cnt_rxtx >= 0);
} else } else */
LOG_E( PHY, "[SCHED][UE %d] UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx); LOG_E( PHY, "[SCHED][UE %d] UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx);
if (proc->instance_cnt_rxtx > 2) if (proc->instance_cnt_rxtx > 2)
exit_fun("instance_cnt_rxtx > 2"); exit_fun("instance_cnt_rxtx > 2");
......
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