@ -30,10 +30,14 @@
# include "srslte/common/log_filter.h"
# include "srslte/common/logger_stdout.h"
# include "srslte/common/threads.h"
# include "srslte/common/rlc_pcap.h"
# include "srslte/upper/rlc.h"
# include <boost/program_options.hpp>
# include <boost/program_options/parsers.hpp>
# include <assert.h>
# include <boost/thread.hpp>
# define SDU_SIZE 1500
using namespace std ;
using namespace srsue ;
@ -47,8 +51,13 @@ typedef struct {
uint32_t pdu_tx_delay_usec ;
bool reestablish ;
uint32_t log_level ;
bool single_tx ;
bool write_pcap ;
float opp_sdu_ratio ;
} stress_test_args_t ;
boost : : mutex mutex ;
void parse_args ( stress_test_args_t * args , int argc , char * argv [ ] ) {
// Command line only options
@ -65,8 +74,11 @@ void parse_args(stress_test_args_t *args, int argc, char *argv[]) {
( " sdu_gen_delay " , bpo : : value < uint32_t > ( & args - > sdu_gen_delay_usec ) - > default_value ( 10 ) , " SDU generation delay (usec) " )
( " pdu_tx_delay " , bpo : : value < uint32_t > ( & args - > pdu_tx_delay_usec ) - > default_value ( 10 ) , " Delay in MAC for transfering PDU from tx'ing RLC to rx'ing RLC (usec) " )
( " error_rate " , bpo : : value < float > ( & args - > error_rate ) - > default_value ( 0.1 ) , " Rate at which RLC PDUs are dropped " )
( " opp_sdu_ratio " , bpo : : value < float > ( & args - > opp_sdu_ratio ) - > default_value ( 0.0 ) , " Ratio between MAC opportunity and SDU size (0==random) " )
( " reestablish " , bpo : : value < bool > ( & args - > reestablish ) - > default_value ( false ) , " Mimic RLC reestablish during execution " )
( " loglevel " , bpo : : value < uint32_t > ( & args - > log_level ) - > default_value ( srslte : : LOG_LEVEL_DEBUG ) , " Log level (1=Error,2=Warning,3=Info,4=Debug " ) ;
( " loglevel " , bpo : : value < uint32_t > ( & args - > log_level ) - > default_value ( srslte : : LOG_LEVEL_DEBUG ) , " Log level (1=Error,2=Warning,3=Info,4=Debug) " )
( " singletx " , bpo : : value < bool > ( & args - > single_tx ) - > default_value ( false ) , " If set to true, only one node is generating data " )
( " pcap " , bpo : : value < bool > ( & args - > write_pcap ) - > default_value ( false ) , " Whether to write all RLC PDU to PCAP file " ) ;
// these options are allowed on the command line
bpo : : options_description cmdline_options ;
@ -94,14 +106,17 @@ class mac_reader
: public thread
{
public :
mac_reader ( rlc_interface_mac * rlc1_ , rlc_interface_mac * rlc2_ , float fail_rate_ , uint32_t pdu_tx_delay_usec_ )
mac_reader ( rlc_interface_mac * rlc1_ , rlc_interface_mac * rlc2_ , float fail_rate_ , float opp_sdu_ratio_ , uint32_t pdu_tx_delay_usec_ , rlc_pcap * pcap_ , bool is_dl_ = true )
{
rlc1 = rlc1_ ;
rlc2 = rlc2_ ;
fail_rate = fail_rate_ ;
opp_sdu_ratio = opp_sdu_ratio_ ;
run_enable = true ;
running = false ;
pdu_tx_delay_usec = pdu_tx_delay_usec_ ;
pcap = pcap_ ;
is_dl = is_dl_ ;
}
void stop ( )
@ -129,14 +144,25 @@ private:
}
while ( run_enable ) {
float r = ( float ) rand ( ) / RAND_MAX ;
int opp_size = r * 1500 ;
rlc1 - > get_buffer_state ( 1 ) ;
int read = rlc1 - > read_pdu ( 1 , pdu - > msg , opp_size ) ;
if ( ( ( float ) rand ( ) / RAND_MAX > fail_rate ) & & read > 0 ) {
rlc2 - > write_pdu ( 1 , pdu - > msg , opp_size ) ;
// generate MAC opportunities of random size or with fixed ratio
float r = opp_sdu_ratio ? opp_sdu_ratio : ( float ) rand ( ) / RAND_MAX ;
int opp_size = r * SDU_SIZE ;
mutex . lock ( ) ;
uint32_t buf_state = rlc1 - > get_buffer_state ( 1 ) ;
if ( buf_state ) {
int read = rlc1 - > read_pdu ( 1 , pdu - > msg , opp_size ) ;
usleep ( pdu_tx_delay_usec ) ;
if ( ( ( float ) rand ( ) / RAND_MAX > fail_rate ) & & read > 0 ) {
pdu - > N_bytes = read ;
rlc2 - > write_pdu ( 1 , pdu - > msg , pdu - > N_bytes ) ;
if ( is_dl ) {
pcap - > write_dl_am_ccch ( pdu - > msg , pdu - > N_bytes ) ;
} else {
pcap - > write_ul_am_ccch ( pdu - > msg , pdu - > N_bytes ) ;
}
}
}
usleep ( pdu_tx_delay_usec ) ;
mutex. unlock ( ) ;
}
running = false ;
byte_buffer_pool : : get_instance ( ) - > deallocate ( pdu ) ;
@ -145,7 +171,10 @@ private:
rlc_interface_mac * rlc1 ;
rlc_interface_mac * rlc2 ;
float fail_rate ;
float opp_sdu_ratio ;
uint32_t pdu_tx_delay_usec ;
rlc_pcap * pcap ;
bool is_dl ;
bool run_enable ;
bool running ;
@ -155,9 +184,9 @@ class mac_dummy
: public srslte : : mac_interface_timers
{
public :
mac_dummy ( rlc_interface_mac * rlc1_ , rlc_interface_mac * rlc2_ , float fail_rate_ , uint32_t pdu_tx_delay )
: r1 ( rlc1_ , rlc2_ , fail_rate_ , pdu_tx_delay)
, r2 ( rlc2_ , rlc1_ , fail_rate_ , pdu_tx_delay)
mac_dummy ( rlc_interface_mac * rlc1_ , rlc_interface_mac * rlc2_ , float fail_rate_ , float opp_sd u_ratio_, int32_t pdu_tx_delay , rlc_pcap * pcap = NULL )
: r1 ( rlc1_ , rlc2_ , fail_rate_ , opp_sdu_ratio_, pdu_tx_delay, pcap , true )
, r2 ( rlc2_ , rlc1_ , fail_rate_ , opp_sdu_ratio_, pdu_tx_delay, pcap , false )
{
}
@ -222,6 +251,7 @@ public:
void write_pdu ( uint32_t lcid , byte_buffer_t * sdu )
{
assert ( lcid = = 1 ) ;
assert ( sdu - > N_bytes = = SDU_SIZE ) ;
byte_buffer_pool : : get_instance ( ) - > deallocate ( sdu ) ;
std : : cout < < " rlc_am_tester " < < name < < " received " < < rx_pdus + + < < " PDUs " < < std : : endl ;
}
@ -244,8 +274,11 @@ private:
printf ( " Fatal Error: Could not allocate PDU in rlc_am_tester::run_thread \n " ) ;
exit ( - 1 ) ;
}
pdu - > N_bytes = 1500 ;
pdu - > msg [ 0 ] = sn + + ;
for ( uint32_t i = 0 ; i < SDU_SIZE ; i + + ) {
pdu - > msg [ i ] = sn ;
}
sn + + ;
pdu - > N_bytes = SDU_SIZE ;
rlc - > write_sdu ( 1 , pdu ) ;
usleep ( sdu_gen_delay_usec ) ;
}
@ -271,13 +304,18 @@ void stress_test(stress_test_args_t args)
log2 . set_level ( ( LOG_LEVEL_ENUM ) args . log_level ) ;
log1 . set_hex_limit ( - 1 ) ;
log2 . set_hex_limit ( - 1 ) ;
rlc_pcap pcap ;
if ( args . write_pcap ) {
pcap . open ( " rlc_stress_test.pcap " , 0 ) ;
}
rlc rlc1 ;
rlc rlc2 ;
rlc_am_tester tester1 ( & rlc1 , " tester1 " , args . sdu_gen_delay_usec ) ;
rlc_am_tester tester2 ( & rlc2 , " tester2 " , args . sdu_gen_delay_usec ) ;
mac_dummy mac ( & rlc1 , & rlc2 , args . error_rate , args . pdu_tx_delay_usec) ;
mac_dummy mac ( & rlc1 , & rlc2 , args . error_rate , args . opp_sdu_ratio, args . pdu_tx_delay_usec, & pcap ) ;
ue_interface ue ;
rlc1 . init ( & tester1 , & tester1 , & ue , & log1 , & mac , 0 ) ;
@ -298,14 +336,21 @@ void stress_test(stress_test_args_t args)
rlc2 . add_bearer ( 1 , cnfg_ ) ;
tester1 . start ( 7 ) ;
tester2 . start ( 7 ) ;
if ( ! args . single_tx ) {
tester2 . start ( 7 ) ;
}
mac . start ( ) ;
for ( uint32_t i = 0 ; i < args . test_duration_sec ; i + + ) {
// if enabled, mimic reestablishment every second
if ( args . reestablish ) {
// lock mutex during reestablish to prevent a RLC PDU that is already been transmitted before
// resetting the tx'ing RLC entity, but not yet received before resetting the
// rx'ing RLC entity to screw the test
mutex . lock ( ) ;
rlc1 . reestablish ( ) ;
rlc2 . reestablish ( ) ;
mutex . unlock ( ) ;
}
usleep ( 1e6 ) ;
}
@ -313,6 +358,9 @@ void stress_test(stress_test_args_t args)
tester1 . stop ( ) ;
tester2 . stop ( ) ;
mac . stop ( ) ;
if ( args . write_pcap ) {
pcap . close ( ) ;
}
}