From d3537fc34090ee1c2af6601661b628e027d6ced7 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 22 Jan 2020 16:27:45 +0100 Subject: [PATCH] srsLTE: expanded RLC stress test with the addition of multiple PDU per TTI in reverse order --- lib/test/upper/rlc_stress_test.cc | 144 +++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 40 deletions(-) diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index c03ea9422..3155d5114 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -78,6 +78,7 @@ typedef struct { uint32_t test_duration_sec; float pdu_drop_rate; float pdu_cut_rate; + float pdu_duplicate_rate; uint32_t sdu_gen_delay_usec; uint32_t pdu_tx_delay_usec; bool reestablish; @@ -88,6 +89,7 @@ typedef struct { bool random_opp; bool zero_seed; bool pedantic_sdu_check; + uint32_t nof_pdu_tti; } stress_test_args_t; void parse_args(stress_test_args_t* args, int argc, char* argv[]) @@ -103,22 +105,24 @@ void parse_args(stress_test_args_t* args, int argc, char* argv[]) // Command line or config file options bpo::options_description common("Configuration options"); common.add_options() - ("rat", bpo::value(&args->rat)->default_value("LTE"), "The RLC version to use (LTE/NR)") - ("mode", bpo::value(&args->mode)->default_value("AM"), "Whether to test RLC acknowledged or unacknowledged mode (AM/UM)") - ("duration", bpo::value(&args->test_duration_sec)->default_value(5), "Duration (sec)") - ("sdu_size", bpo::value(&args->sdu_size)->default_value(1500), "Size of SDUs") - ("avg_opp_size", bpo::value(&args->avg_opp_size)->default_value(1505), "Size of the MAC opportunity (if not random)") - ("random_opp", bpo::value(&args->random_opp)->default_value(true), "Whether to generate random MAC opportunities") - ("sdu_gen_delay", bpo::value(&args->sdu_gen_delay_usec)->default_value(0), "SDU generation delay (usec)") - ("pdu_tx_delay", bpo::value(&args->pdu_tx_delay_usec)->default_value(0), "Delay in MAC for transfering PDU from tx'ing RLC to rx'ing RLC (usec)") - ("pdu_drop_rate", bpo::value(&args->pdu_drop_rate)->default_value(0.1), "Rate at which RLC PDUs are dropped") - ("pdu_cut_rate", bpo::value(&args->pdu_cut_rate)->default_value(0.0), "Rate at which RLC PDUs are chopped in length") - ("reestablish", bpo::value(&args->reestablish)->default_value(false), "Mimic RLC reestablish during execution") - ("loglevel", bpo::value(&args->log_level)->default_value(srslte::LOG_LEVEL_DEBUG), "Log level (1=Error,2=Warning,3=Info,4=Debug)") - ("singletx", bpo::value(&args->single_tx)->default_value(false), "If set to true, only one node is generating data") - ("pcap", bpo::value(&args->write_pcap)->default_value(false), "Whether to write all RLC PDU to PCAP file") - ("zeroseed", bpo::value(&args->zero_seed)->default_value(false), "Whether to initialize random seed to zero") - ("pedantic", bpo::value(&args->pedantic_sdu_check)->default_value(false), "Whether to check SDU length and exit on error"); + ("rat", bpo::value(&args->rat)->default_value("LTE"), "The RLC version to use (LTE/NR)") + ("mode", bpo::value(&args->mode)->default_value("AM"), "Whether to test RLC acknowledged or unacknowledged mode (AM/UM)") + ("duration", bpo::value(&args->test_duration_sec)->default_value(5), "Duration (sec)") + ("sdu_size", bpo::value(&args->sdu_size)->default_value(1500), "Size of SDUs") + ("avg_opp_size", bpo::value(&args->avg_opp_size)->default_value(1505), "Size of the MAC opportunity (if not random)") + ("random_opp", bpo::value(&args->random_opp)->default_value(true), "Whether to generate random MAC opportunities") + ("sdu_gen_delay", bpo::value(&args->sdu_gen_delay_usec)->default_value(0), "SDU generation delay (usec)") + ("pdu_tx_delay", bpo::value(&args->pdu_tx_delay_usec)->default_value(0), "Delay in MAC for transfering PDU from tx'ing RLC to rx'ing RLC (usec)") + ("pdu_drop_rate", bpo::value(&args->pdu_drop_rate)->default_value(0.1), "Rate at which RLC PDUs are dropped") + ("pdu_cut_rate", bpo::value(&args->pdu_cut_rate)->default_value(0.0), "Rate at which RLC PDUs are chopped in length") + ("pdu_duplicate_rate", bpo::value(&args->pdu_duplicate_rate)->default_value(0.0), "Rate at which RLC PDUs are duplicated") + ("reestablish", bpo::value(&args->reestablish)->default_value(false), "Mimic RLC reestablish during execution") + ("loglevel", bpo::value(&args->log_level)->default_value(srslte::LOG_LEVEL_DEBUG), "Log level (1=Error,2=Warning,3=Info,4=Debug)") + ("singletx", bpo::value(&args->single_tx)->default_value(false), "If set to true, only one node is generating data") + ("pcap", bpo::value(&args->write_pcap)->default_value(false), "Whether to write all RLC PDU to PCAP file") + ("zeroseed", bpo::value(&args->zero_seed)->default_value(false), "Whether to initialize random seed to zero") + ("pedantic", bpo::value(&args->pedantic_sdu_check)->default_value(false), "Whether to check SDU length and exit on error") + ("nof_pdu_tti", bpo::value(&args->nof_pdu_tti)->default_value(1), "Number of PDUs processed in a TTI"); // clang-format on // these options are allowed on the command line @@ -161,7 +165,8 @@ public: timers(timers_), log("MAC "), thread("MAC_DUMMY"), - real_dist(0.0, 1.0) + real_dist(0.0, 1.0), + mt19937(1234) { log.set_level(static_cast(args.log_level)); log.set_hex_limit(LOG_HEX_LIMIT); @@ -174,37 +179,72 @@ public: } private: - void run_tti(rlc_interface_mac* tx_rlc, rlc_interface_mac* rx_rlc, bool is_dl) + void run_tx_tti(rlc_interface_mac* tx_rlc, rlc_interface_mac* rx_rlc, std::vector& pdu_list) { - byte_buffer_pool* pool = byte_buffer_pool::get_instance(); - unique_byte_buffer_t pdu = srslte::allocate_unique_buffer(*pool, __PRETTY_FUNCTION__, true); - if (!pdu) { - printf("Fatal Error: Could not allocate PDU in mac_reader::run_thread\n"); - exit(-1); + // Generate A number of MAC PDUs + for (uint32_t i = 0; i < args.nof_pdu_tti; i++) { + // Get PDU pool + byte_buffer_pool* pool = byte_buffer_pool::get_instance(); + + // Create PDU unique buffer + unique_byte_buffer_t pdu = srslte::allocate_unique_buffer(*pool, __PRETTY_FUNCTION__, true); + if (!pdu) { + printf("Fatal Error: Could not allocate PDU in mac_reader::run_thread\n"); + exit(-1); + } + + // Get MAC PDU size + float factor = 1.0f; + if (args.random_opp) { + factor = 0.5f + real_dist(mt19937); + } + int opp_size = static_cast(args.avg_opp_size * factor); + + // Request data to transmit + uint32_t buf_state = tx_rlc->get_buffer_state(lcid); + if (buf_state > 0) { + int read = tx_rlc->read_pdu(lcid, pdu->msg, opp_size); + pdu->N_bytes = read; + + // Push PDU in the list + pdu_list.push_back(std::move(pdu)); + } } + } - float factor = 1.0; - if (args.random_opp) { - factor = 0.5 + real_dist(mt19937); + void run_rx_tti(rlc_interface_mac* tx_rlc, + rlc_interface_mac* rx_rlc, + bool is_dl, + std::vector& pdu_list) + { + // Sleep if necessary + if (args.pdu_tx_delay_usec > 0) { + usleep(args.pdu_tx_delay_usec); } - int opp_size = args.avg_opp_size * factor; - uint32_t buf_state = tx_rlc->get_buffer_state(lcid); - if (buf_state > 0) { - int read = tx_rlc->read_pdu(lcid, pdu->msg, opp_size); - pdu->N_bytes = read; - if (args.pdu_tx_delay_usec > 0) { - usleep(args.pdu_tx_delay_usec); - } - if ((real_dist(mt19937) > args.pdu_drop_rate) && read > 0) { + + auto it = pdu_list.begin(); // PDU iterator + bool skip_action = false; // Avoid discarding a duplicated or duplicating a discarded + + while (it != pdu_list.end()) { + // Get PDU unique buffer + unique_byte_buffer_t& pdu = *it; + + // Drop + if (((real_dist(mt19937) > args.pdu_drop_rate) || skip_action) && pdu->N_bytes > 0) { uint32_t pdu_len = pdu->N_bytes; - if ((real_dist(mt19937) > 0.1) && args.pdu_cut_rate) { - int cut_pdu_len = pdu_len * real_dist(mt19937); - log.info("Cutting MAC PDU len (%d B > %d B)\n", pdu_len, cut_pdu_len); + + // Cut + if ((real_dist(mt19937) < args.pdu_cut_rate)) { + int cut_pdu_len = static_cast(pdu_len * real_dist(mt19937)); + log.info("Cutting MAC PDU len (%d B -> %d B)\n", pdu_len, cut_pdu_len); pdu_len = cut_pdu_len; } + + // Write PDU in RX rx_rlc->write_pdu(lcid, pdu->msg, pdu_len); - write_pdu_to_pcap(is_dl, 4, pdu->msg, pdu_len); + // Write PCAP + write_pdu_to_pcap(is_dl, 4, pdu->msg, pdu_len); if (is_dl) { pcap->write_dl_am_ccch(pdu->msg, pdu_len); } else { @@ -212,11 +252,35 @@ private: } } else { log.warning_hex(pdu->msg, pdu->N_bytes, "Dropping RLC PDU (%d B)\n", pdu->N_bytes); + skip_action = true; // Avoid drop duplicating this PDU + } + + // Duplicate + if (real_dist(mt19937) > args.pdu_duplicate_rate || skip_action) { + it++; + skip_action = false; // Allow action on the next PDU + } else { + log.warning_hex(pdu->msg, pdu->N_bytes, "Duplicating RLC PDU (%d B)\n", pdu->N_bytes); + skip_action = true; // Avoid drop of this PDU } } } - void run_thread() + void run_tti(rlc_interface_mac* tx_rlc, rlc_interface_mac* rx_rlc, bool is_dl) + { + std::vector pdu_list; + + // Run Tx + run_tx_tti(tx_rlc, rx_rlc, pdu_list); + + // Reverse PDUs + std::reverse(pdu_list.begin(), pdu_list.end()); + + // Run Rx + run_rx_tti(tx_rlc, rx_rlc, is_dl, pdu_list); + } + + void run_thread() override { while (run_enable) { // Downlink direction first (RLC1->RLC2)