Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
常顺宇
OpenXG-RAN
Commits
11fd202d
Commit
11fd202d
authored
Jan 19, 2019
by
laurent
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix compilation, attach complete
parent
c17f65f1
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
418 additions
and
265 deletions
+418
-265
openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
+1
-1
openair2/RRC/LTE/rrc_UE.c
openair2/RRC/LTE/rrc_UE.c
+3
-0
targets/ARCH/rfsimulator/simulator.c
targets/ARCH/rfsimulator/simulator.c
+3
-1
targets/ARCH/tcp_bridge/tcp_bridge_oai.c
targets/ARCH/tcp_bridge/tcp_bridge_oai.c
+382
-244
targets/RT/USER/lte-ue.c
targets/RT/USER/lte-ue.c
+29
-19
No files found.
openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
View file @
11fd202d
...
...
@@ -63,7 +63,7 @@ struct msghdr nas_msg_tx;
struct
msghdr
nas_msg_rx
;
#define GRAAL_NETLINK_ID 31
#ifdef UE_NAS_USE_TUN
static
int
tun_alloc
(
char
*
dev
)
...
...
openair2/RRC/LTE/rrc_UE.c
View file @
11fd202d
...
...
@@ -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
);
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
...
...
@@ -5111,6 +5112,7 @@ void *rrc_ue_task( void *args_p )
break
;
// PHY_FIND_CELL_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
;
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 )
}
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
);
break
;
...
...
targets/ARCH/rfsimulator/simulator.c
View file @
11fd202d
...
...
@@ -280,7 +280,7 @@ bool flushInput(tcp_bridge_state_t *t) {
else
blockSz
=
b
->
transferPtr
+
b
->
remainToTransfer
<
b
->
circularBufEnd
?
b
->
remainToTransfer
:
b
->
circularBufEnd
-
b
->
transferPtr
;
b
->
circularBufEnd
-
1
-
b
->
transferPtr
;
int
sz
=
recv
(
fd
,
b
->
transferPtr
,
blockSz
,
MSG_DONTWAIT
);
...
...
@@ -294,6 +294,8 @@ bool flushInput(tcp_bridge_state_t *t) {
AssertFatal
((
b
->
remainToTransfer
-=
sz
)
>=
0
,
""
);
b
->
transferPtr
+=
sz
;
if
(
b
->
transferPtr
==
b
->
circularBufEnd
-
1
)
b
->
transferPtr
=
(
char
*
)
b
->
circularBuf
;
// check the header and start block transfer
if
(
b
->
headerMode
==
true
&&
b
->
remainToTransfer
==
0
)
{
...
...
targets/ARCH/tcp_bridge/tcp_bridge_oai.c
View file @
11fd202d
...
...
@@ -6,296 +6,447 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/epoll.h>
#include <string.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
;
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include "common_lib.h"
#include <openair1/PHY/defs_eNB.h>
#include "openair1/PHY/defs_UE.h"
#define PORT 4043 //TCP port for this simulator
#define CirSize 3072000 // 100ms is enough
#define sample_t uint32_t // 2*16 bits complex number
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
#define MAGICeNB 0xA5A5A5A5A5A5A5A5
#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
,
""
);
}
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
;
}
int
fullwrite
(
int
fd
,
void
*
_buf
,
int
count
)
{
#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
;
int
ret
=
0
;
int
l
;
while
(
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
;
buf
+=
l
;
ret
+=
l
;
}
return
ret
;
}
#include "common_lib.h"
typedef
struct
{
int
sock
;
int
samples_per_subframe
;
uint64_t
timestamp
;
uint64_t
next_tx_timestamp
;
int
is_enb
;
}
tcp_bridge_state_t
;
void
verify_connection
(
int
fd
,
int
is_enb
)
{
char
c
=
is_enb
;
if
(
fullwrite
(
fd
,
&
c
,
1
)
!=
1
)
exit
(
1
);
if
(
fullread
(
fd
,
&
c
,
1
)
!=
1
)
exit
(
1
);
if
(
c
==
is_enb
)
{
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
);
}
return
ret
;
}
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
);
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
);
}
enum
blocking_t
{
blocking
,
notBlocking
};
struct
sockaddr_in
addr
=
{
sin_family:
AF_INET
,
sin_port:
htons
(
port
),
sin_addr:
{
s_addr
:
INADDR_ANY
}
};
void
setblocking
(
int
sock
,
enum
blocking_t
active
)
{
int
opts
;
AssertFatal
(
(
opts
=
fcntl
(
sock
,
F_GETFL
))
>=
0
,
""
);
if
(
bind
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
)))
{
if
(
errno
==
EADDRINUSE
)
goto
client_mode
;
{
perror
(
"tcp_bridge: bind"
);
exit
(
1
);
}
}
if
(
active
==
blocking
)
opts
=
opts
&
~
O_NONBLOCK
;
else
opts
=
opts
|
O_NONBLOCK
;
if
(
listen
(
sock
,
5
))
{
perror
(
"tcp_bridge: listen"
);
exit
(
1
);
}
printf
(
"tcp_bridge: wait for connection on port %d
\n
"
,
port
);
AssertFatal
(
fcntl
(
sock
,
F_SETFL
,
opts
)
>=
0
,
""
);
}
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_state_t
*
init_bridge
(
openair0_device
*
device
)
{
tcp_bridge_state_t
*
tcp_bridge
;
tcp_bridge
->
sock
=
sock2
;
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
,
""
);
printf
(
"tcp_bridge: connection established
\n
"
);
for
(
int
i
=
0
;
i
<
FD_SETSIZE
;
i
++
)
tcp_bridge
->
buf
[
i
].
conn_sock
=-
1
;
verify_connection
(
sock2
,
tcp_bridge
->
is_enb
);
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
;
AssertFatal
(
setsockopt
(
t
->
listen_sock
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
enable
,
sizeof
(
int
))
==
0
,
""
);
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
;
}
client_mode:
addr
.
sin_addr
.
s_addr
=
inet_addr
(
"127.0.0.1"
);
for
(
try
=
0
;
try
<
max_try
;
try
++
)
{
if
(
try
!=
0
)
sleep
(
1
);
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
=
{
sin_family:
AF_INET
,
sin_port:
htons
(
PORT
),
sin_addr:
{
s_addr
:
INADDR_ANY
}
};
addr
.
sin_addr
.
s_addr
=
inet_addr
(
t
->
ip
);
bool
connected
=
false
;
printf
(
"tcp_bridge: trying to connect to 127.0.0.1:%d (attempt %d/%d)
\n
"
,
port
,
try
+
1
,
max_try
);
while
(
!
connected
)
{
printf
(
"tcp_bridge: trying to connect to %s:%d
\n
"
,
t
->
ip
,
PORT
);
if
(
connect
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
))
==
0
)
{
printf
(
"tcp_bridge: connection established
\n
"
);
tcp_bridge
->
sock
=
sock
;
verify_connection
(
sock
,
tcp_bridge
->
is_enb
);
return
0
;
connected
=
true
;
}
perror
(
"tcp_bridge"
);
sleep
(
1
);
}
printf
(
"tcp_bridge: connection failed
\n
"
);
exit
(
1
);
setblocking
(
sock
,
notBlocking
);
allocCirBuf
(
t
,
sock
);
t
->
buf
[
sock
].
alreadyWrote
=
true
;
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
)
{
if
(
cc
!=
1
)
{
printf
(
"tcp_bridge: only 1 antenna supported
\n
"
);
exit
(
1
);
}
int
tcp_bridge_write
(
openair0_device
*
device
,
openair0_timestamp
timestamp
,
void
**
samplesVoid
,
int
nsamps
,
int
nbAnt
,
int
flags
)
{
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
));
for
(
int
i
=
0
;
i
<
FD_SETSIZE
;
i
++
)
{
buffer_t
*
ptr
=&
t
->
buf
[
i
];
if
(
ptr
->
conn_sock
>=
0
)
{
setblocking
(
ptr
->
conn_sock
,
blocking
);
transferHeader
header
=
{
t
->
typeStamp
,
nsamps
,
nbAnt
,
timestamp
};
int
n
=-
1
;
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
));
if
(
n
!=
sampleToByte
(
nsamps
,
nbAnt
)
)
{
printf
(
"tcp_bridge: write error ret %d (wanted %ld) error %s
\n
"
,
n
,
sampleToByte
(
nsamps
,
nbAnt
),
strerror
(
errno
));
abort
();
}
to_send
-=
len
;
ptr
->
alreadyWrote
=
true
;
setblocking
(
ptr
->
conn_sock
,
notBlocking
);
}
}
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
;
LOG_D
(
HW
,
"sent %d samples at time: %ld->%ld, energy in first antenna: %d
\n
"
,
nsamps
,
timestamp
,
timestamp
+
nsamps
,
signal_energy
(
samplesVoid
[
0
],
nsamps
)
);
return
nsamps
;
}
int
tcp_bridge_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
;
int
n
=
fullread
(
t
->
sock
,
buff
[
0
],
nsamps
*
4
);
if
(
n
!=
nsamps
*
4
)
{
printf
(
"tcp_bridge: read error ret %d nsamps*4 %d error %s
\n
"
,
n
,
nsamps
*
4
,
strerror
(
errno
));
abort
();
bool
flushInput
(
tcp_bridge_state_t
*
t
)
{
// 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
"
);
}
//printf("waited iter=%d, res %d, waiting fd %d\n", iterations, nfds, nfds>=1? events[0].data.fd:-1);
for
(
int
nbEv
=
0
;
nbEv
<
nfds
;
++
nbEv
)
{
int
fd
=
events
[
nbEv
].
data
.
fd
;
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
;
}
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
;
}
int
blockSz
;
if
(
b
->
headerMode
)
blockSz
=
b
->
remainToTransfer
;
else
blockSz
=
b
->
transferPtr
+
b
->
remainToTransfer
<
b
->
circularBufEnd
?
b
->
remainToTransfer
:
b
->
circularBufEnd
-
b
->
transferPtr
;
int
sz
=
recv
(
fd
,
b
->
transferPtr
,
blockSz
,
MSG_DONTWAIT
);
if
(
sz
<
0
)
{
if
(
errno
!=
EAGAIN
)
{
LOG_E
(
HW
,
"socket failed %s
\n
"
,
strerror
(
errno
));
abort
();
}
}
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
;
}
}
}
}
}
*
timestamp
=
t
->
timestamp
;
t
->
timestamp
+=
nsamps
;
return
nsamps
;
return
completedABuffer
;
}
int
tcp_bridge_read
_ue
(
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
);
}
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
);
}
tcp_bridge_state_t
*
t
=
device
->
priv
;
int
n
;
/* In synch mode, UE does not write, but we need to
* send something to the eNodeB.
* We know that UE is in synch mode when it reads
* 10 subframes at a time.
*/
if
(
nsamps
==
t
->
samples_per_subframe
*
10
)
{
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
();
// deliver data from received data
// check if a UE is connected
int
first_sock
;
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
;
}
*
ptimestamp
=
t
->
nextTimestamp
-
nsamps
;
return
nsamps
;
}
}
else
{
bool
have_to_wait
;
do
{
have_to_wait
=
false
;
for
(
int
sock
=
0
;
sock
<
FD_SETSIZE
;
sock
++
)
if
(
t
->
buf
[
sock
].
circularBuf
&&
t
->
buf
[
sock
].
alreadyWrote
&&
(
t
->
nextTimestamp
+
nsamps
)
>
t
->
buf
[
sock
].
lastReceivedTS
)
{
have_to_wait
=
true
;
break
;
}
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,
* we need to understand that:
* - eNodeB starts reading subframe 0
* - 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
;
// Add all input signal in the output buffer
for
(
int
sock
=
0
;
sock
<
FD_SETSIZE
;
sock
++
)
{
buffer_t
*
ptr
=&
t
->
buf
[
sock
];
uint32_t
b
[
t
->
samples_per_subframe
*
12
];
memset
(
b
,
0
,
t
->
samples_per_subframe
*
12
*
4
);
int
n
=
fullwrite
(
t
->
sock
,
b
,
t
->
samples_per_subframe
*
12
*
4
);
if
(
n
!=
t
->
samples_per_subframe
*
12
*
4
)
{
printf
(
"tcp_bridge: write error ret %d error %s
\n
"
,
n
,
strerror
(
errno
));
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
();
if
(
ptr
->
circularBuf
&&
ptr
->
alreadyWrote
)
{
for
(
int
a
=
0
;
a
<
nbAnt
;
a
++
)
{
sample_t
*
out
=
(
sample_t
*
)
samplesVoid
[
a
];
for
(
int
i
=
0
;
i
<
nsamps
;
i
++
)
out
[
i
]
+=
ptr
->
circularBuf
[(
t
->
nextTimestamp
+
(
a
*
nbAnt
+
i
))
%
CirSize
]
<<
1
;
}
}
}
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"
)))
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
));
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
*
)
calloc
(
sizeof
(
tcp_bridge_state_t
),
1
);
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 */
if
(
openair0_cfg
[
0
].
sample_rate
!=
30720000
&&
...
...
@@ -305,7 +456,9 @@ int device_init(openair0_device* device, openair0_config_t *openair0_cfg)
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_reset_stats_func
=
tcp_bridge_reset_stats
;
device
->
trx_end_func
=
tcp_bridge_end
;
...
...
@@ -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_gains_func
=
tcp_bridge_set_gains
;
device
->
trx_write_func
=
tcp_bridge_write
;
if
(
tcp_bridge
->
is_enb
)
{
device
->
trx_read_func
=
tcp_bridge_read
;
}
else
{
device
->
trx_read_func
=
tcp_bridge_ue_first_read
;
}
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
;
}
targets/RT/USER/lte-ue.c
View file @
11fd202d
...
...
@@ -783,11 +783,18 @@ static void *UE_thread_rxn_txnp4(void *arg) {
threadname
);
while
(
!
oai_exit
)
{
AssertFatal
(
pthread_mutex_lock
(
&
proc
->
mutex_rxtx
)
==
0
,
"[SCHED][UE] error locking mutex for UE RXTX
\n
"
);
while
(
proc
->
instance_cnt_rxtx
<
0
)
if
(
pthread_mutex_lock
(
&
proc
->
mutex_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
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
(
t3
);
...
...
@@ -861,12 +868,18 @@ static void *UE_thread_rxn_txnp4(void *arg) {
phy_procedures_UE_S_TX
(
UE
,
0
,
0
);
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
--
;
#if BASIC_SIMULATOR
AssertFatal
(
pthread_cond_signal
(
&
proc
->
cond_rxtx
)
==
0
,
""
);
#if
1 //
BASIC_SIMULATOR
if
(
pthread_cond_signal
(
&
proc
->
cond_rxtx
)
!=
0
)
abort
(
);
#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
...
...
@@ -981,6 +994,7 @@ static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) {
}
while
(
phy_stub_ticking
->
ticking_var
<
0
)
{
// 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
"
);
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) {
}
while
(
phy_stub_ticking
->
ticking_var
<
0
)
{
// 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
"
);
pthread_cond_wait
(
&
phy_stub_ticking
->
cond_ticking
,
&
phy_stub_ticking
->
mutex_ticking
);
}
...
...
@@ -1456,12 +1471,6 @@ void *UE_thread(void *arg) {
}
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
),
""
);
int
instance_cnt_synch
=
UE
->
proc
.
instance_cnt_synch
;
...
...
@@ -1591,7 +1600,7 @@ void *UE_thread(void *arg) {
// update thread index for received subframe
UE
->
current_thread_id
[
sub_frame
]
=
thread_idx
;
#if BASIC_SIMULATOR
#if
1 //
BASIC_SIMULATOR
{
int
t
;
for
(
t
=
0
;
t
<
2
;
t
++
)
{
...
...
@@ -1629,10 +1638,10 @@ void *UE_thread(void *arg) {
// compute TO compensation that should be applied for this frame
if
(
UE
->
no_timing_correction
==
0
)
{
if
(
getenv
(
"RFSIMULATOR"
)
!=
NULL
&&
UE
->
rx_offset
)
{
//LOG_E(HW,"in simu, rx_offset is not null (impossible)
: %d\n", UE->rx_offset);
UE
->
rx_offset
=
0
;
}
if
(
UE
->
rx_offset
)
{
//LOG_E(HW,"in simu, rx_offset is not null
: %d\n", UE->rx_offset);
UE
->
rx_offset
=
0
;
}
if
(
UE
->
rx_offset
<
5
*
UE
->
frame_parms
.
samples_per_tti
&&
UE
->
rx_offset
>
0
)
UE
->
rx_offset_diff
=
-
1
;
...
...
@@ -1704,6 +1713,7 @@ void *UE_thread(void *arg) {
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
);
if
(
proc
->
instance_cnt_rxtx
!=
0
)
{
/*
if ( getenv("RFSIMULATOR") != NULL ) {
do {
AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, "");
...
...
@@ -1711,7 +1721,7 @@ void *UE_thread(void *arg) {
AssertFatal (pthread_mutex_lock(&proc->mutex_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
);
if
(
proc
->
instance_cnt_rxtx
>
2
)
exit_fun
(
"instance_cnt_rxtx > 2"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment