diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 757770ead..de4c521b0 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -118,6 +118,8 @@ private: void update_bsr_mch(uint32_t lcid); }; +void rlc_bearer_metrics_print(const rlc_bearer_metrics_t& metrics); + } // namespace srslte #endif // SRSLTE_RLC_H diff --git a/lib/include/srslte/upper/rlc_metrics.h b/lib/include/srslte/upper/rlc_metrics.h index ab12cb9a8..4325ca774 100644 --- a/lib/include/srslte/upper/rlc_metrics.h +++ b/lib/include/srslte/upper/rlc_metrics.h @@ -23,19 +23,24 @@ #define SRSLTE_RLC_METRICS_H #include "srslte/common/common.h" +#include namespace srslte { typedef struct { + // SDU metrics uint32_t num_tx_sdus; uint32_t num_rx_sdus; + uint64_t num_tx_sdu_bytes; + uint64_t num_rx_sdu_bytes; + uint32_t num_lost_sdus; //< Count dropped SDUs at Tx due to bearer inactivity or empty buffer + + // PDU metrics uint32_t num_tx_pdus; uint32_t num_rx_pdus; - uint64_t num_tx_bytes; - uint64_t num_rx_bytes; - + uint64_t num_tx_pdu_bytes; + uint64_t num_rx_pdu_bytes; uint32_t num_lost_pdus; //< Lost PDUs registered at Rx - uint32_t num_dropped_sdus; //< Count dropped SDUs at Tx due to bearer inactivity or empty buffer } rlc_bearer_metrics_t; typedef struct { diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 217f28b8c..9cecb5bb0 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -113,8 +113,8 @@ void rlc::get_metrics(rlc_metrics_t& m) rlc_bearer_metrics_t metrics = it->second->get_metrics(); rlc_log->info("LCID=%d, RX throughput: %4.6f Mbps. TX throughput: %4.6f Mbps.\n", it->first, - (metrics.num_rx_bytes * 8 / static_cast(1e6)) / secs, - (metrics.num_tx_bytes * 8 / static_cast(1e6)) / secs); + (metrics.num_rx_pdu_bytes * 8 / static_cast(1e6)) / secs, + (metrics.num_tx_pdu_bytes * 8 / static_cast(1e6)) / secs); m.bearer[it->first] = metrics; } @@ -123,7 +123,7 @@ void rlc::get_metrics(rlc_metrics_t& m) rlc_bearer_metrics_t metrics = it->second->get_metrics(); rlc_log->info("MCH_LCID=%d, RX throughput: %4.6f Mbps\n", it->first, - (metrics.num_rx_bytes * 8 / static_cast(1e6)) / secs); + (metrics.num_rx_pdu_bytes * 8 / static_cast(1e6)) / secs); m.bearer[it->first] = metrics; } @@ -607,4 +607,18 @@ void rlc::update_bsr_mch(uint32_t lcid) } } +void rlc_bearer_metrics_print(const rlc_bearer_metrics_t& metrics) +{ + std::cout << "num_tx_sdus=" << metrics.num_tx_sdus << "\n"; + std::cout << "num_rx_sdus=" << metrics.num_rx_sdus << "\n"; + std::cout << "num_tx_sdu_bytes=" << metrics.num_tx_sdu_bytes << "\n"; + std::cout << "num_rx_sdu_bytes=" << metrics.num_rx_sdu_bytes << "\n"; + std::cout << "num_tx_pdus=" << metrics.num_tx_pdus << "\n"; + std::cout << "num_rx_pdus=" << metrics.num_rx_pdus << "\n"; + std::cout << "num_tx_pdu_bytes=" << metrics.num_tx_pdu_bytes << "\n"; + std::cout << "num_rx_pdu_bytes=" << metrics.num_rx_pdu_bytes << "\n"; + std::cout << "num_lost_pdus=" << metrics.num_lost_pdus << "\n"; + std::cout << "num_lost_sdus=" << metrics.num_lost_sdus << "\n"; +} + } // namespace srslte diff --git a/lib/src/upper/rlc_am_lte.cc b/lib/src/upper/rlc_am_lte.cc index bb3cfd9f6..bface4ad9 100644 --- a/lib/src/upper/rlc_am_lte.cc +++ b/lib/src/upper/rlc_am_lte.cc @@ -137,6 +137,7 @@ void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking) void rlc_am_lte::discard_sdu(uint32_t discard_sn) { tx.discard_sdu(discard_sn); + metrics.num_lost_sdus++; } /**************************************************************************** @@ -155,12 +156,17 @@ uint32_t rlc_am_lte::get_buffer_state() int rlc_am_lte::read_pdu(uint8_t* payload, uint32_t nof_bytes) { - return tx.read_pdu(payload, nof_bytes); + int read_bytes = tx.read_pdu(payload, nof_bytes); + metrics.num_tx_pdus++; + metrics.num_tx_pdu_bytes += read_bytes; + return read_bytes; } void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes) { rx.write_pdu(payload, nof_bytes); + metrics.num_rx_pdus++; + metrics.num_rx_pdu_bytes += nof_bytes; } /**************************************************************************** @@ -1470,6 +1476,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes); rx_sdu->set_timestamp(); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); + parent->metrics.num_rx_sdus++; rx_sdu = allocate_unique_buffer(*pool, true); if (rx_sdu == nullptr) { @@ -1513,6 +1520,8 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes); rx_sdu->set_timestamp(); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); + parent->metrics.num_rx_sdus++; + rx_sdu = allocate_unique_buffer(*pool, true); if (rx_sdu == NULL) { #ifdef RLC_AM_BUFFER_DEBUG diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index b711f64f2..05cbb5975 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -173,7 +173,7 @@ int rlc_tm::read_pdu(uint8_t* payload, uint32_t nof_bytes) ul_queue.size(), ul_queue.size_bytes()); - metrics.num_tx_bytes += pdu_size; + metrics.num_tx_pdu_bytes += pdu_size; return pdu_size; } else { log->warning("Queue empty while trying to read\n"); @@ -192,7 +192,8 @@ void rlc_tm::write_pdu(uint8_t* payload, uint32_t nof_bytes) memcpy(buf->msg, payload, nof_bytes); buf->N_bytes = nof_bytes; buf->set_timestamp(); - metrics.num_rx_bytes += nof_bytes; + metrics.num_rx_pdu_bytes += nof_bytes; + metrics.num_rx_pdus++; if (rrc->get_rb_name(lcid) == "SRB0") { rrc->write_pdu(lcid, std::move(buf)); } else { diff --git a/lib/src/upper/rlc_um_base.cc b/lib/src/upper/rlc_um_base.cc index e820c4539..8f136dc83 100644 --- a/lib/src/upper/rlc_um_base.cc +++ b/lib/src/upper/rlc_um_base.cc @@ -95,15 +95,18 @@ void rlc_um_base::write_sdu(unique_byte_buffer_t sdu, bool blocking) { if (not tx_enabled || not tx) { log->debug("%s is currently deactivated. Dropping SDU (%d B)\n", rb_name.c_str(), sdu->N_bytes); - metrics.num_dropped_sdus++; + metrics.num_lost_sdus++; return; } if (blocking) { + metrics.num_tx_sdus++; + metrics.num_tx_sdu_bytes += sdu->N_bytes; tx->write_sdu(std::move(sdu)); + } else { if (tx->try_write_sdu(std::move(sdu)) != SRSLTE_SUCCESS) { - metrics.num_dropped_sdus++; + metrics.num_lost_sdus++; } } } @@ -112,10 +115,10 @@ void rlc_um_base::discard_sdu(uint32_t discard_sn) { if (not tx_enabled || not tx) { log->debug("%s is currently deactivated. Ignoring SDU discard (SN %u)\n", rb_name.c_str(), discard_sn); - metrics.num_dropped_sdus++; return; } tx->discard_sdu(discard_sn); + metrics.num_lost_sdus++; } /**************************************************************************** * MAC interface @@ -142,7 +145,7 @@ int rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes) if (tx && tx_enabled) { uint32_t len = tx->build_data_pdu(payload, nof_bytes); if (len > 0) { - metrics.num_tx_bytes += len; + metrics.num_tx_pdu_bytes += len; metrics.num_tx_pdus++; } return len; @@ -154,7 +157,7 @@ void rlc_um_base::write_pdu(uint8_t* payload, uint32_t nof_bytes) { if (rx && rx_enabled) { metrics.num_rx_pdus++; - metrics.num_rx_bytes += nof_bytes; + metrics.num_rx_pdu_bytes += nof_bytes; rx->handle_data_pdu(payload, nof_bytes); } } diff --git a/lib/src/upper/rlc_um_lte.cc b/lib/src/upper/rlc_um_lte.cc index f7482ed75..9d6b78596 100644 --- a/lib/src/upper/rlc_um_lte.cc +++ b/lib/src/upper/rlc_um_lte.cc @@ -402,6 +402,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus() vr_ur, i); rx_sdu->set_timestamp(); + metrics.num_rx_sdus++; + metrics.num_rx_sdu_bytes += rx_sdu->N_bytes; if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { @@ -435,6 +437,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus() log->info_hex( rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rb_name.c_str(), vr_ur); rx_sdu->set_timestamp(); + metrics.num_rx_sdus++; + metrics.num_rx_sdu_bytes += rx_sdu->N_bytes; if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { @@ -544,6 +548,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus() vr_ur, i); rx_sdu->set_timestamp(); + metrics.num_rx_sdus++; + metrics.num_rx_sdu_bytes += rx_sdu->N_bytes; if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { @@ -604,6 +610,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus() log->info_hex( rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", rb_name.c_str(), vr_ur); rx_sdu->set_timestamp(); + metrics.num_rx_sdus++; + metrics.num_rx_sdu_bytes += rx_sdu->N_bytes; if (cfg.um.is_mrb) { pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); } else { diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index a96299cf8..a7fa2f3aa 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -22,6 +22,7 @@ #include "srslte/common/log_filter.h" #include "srslte/common/logger_stdout.h" #include "srslte/common/rlc_pcap.h" +#include "srslte/common/test_common.h" #include "srslte/common/threads.h" #include "srslte/upper/rlc_am_lte.h" #include @@ -36,6 +37,18 @@ using namespace srslte; srslte::log_ref rrc_log1("RLC_AM_1"); srslte::log_ref rrc_log2("RLC_AM_2"); +bool rx_is_tx(const rlc_bearer_metrics_t& rlc1_metrics, const rlc_bearer_metrics_t& rlc2_metrics) +{ + if (rlc1_metrics.num_tx_pdu_bytes != rlc2_metrics.num_rx_pdu_bytes) { + return false; + } + + if (rlc2_metrics.num_tx_pdu_bytes != rlc1_metrics.num_rx_pdu_bytes) { + return false; + } + return true; +} + class rlc_am_tester : public pdcp_interface_rlc, public rrc_interface_rlc { public: @@ -178,18 +191,9 @@ bool meas_obj_test() } // Check statistics - rlc_bearer_metrics_t rlc1_metrics = rlc1.get_metrics(); - rlc_bearer_metrics_t rlc2_metrics = rlc2.get_metrics(); - - if (rlc1_metrics.num_tx_bytes != rlc2_metrics.num_rx_bytes) { - return -1; - } + TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics())); - if (rlc2_metrics.num_tx_bytes != rlc1_metrics.num_rx_bytes) { - return -1; - } - - return 0; + return SRSLTE_SUCCESS; } bool concat_test() @@ -239,18 +243,9 @@ bool concat_test() } // Check statistics - rlc_bearer_metrics_t rlc1_metrics = rlc1.get_metrics(); - rlc_bearer_metrics_t rlc2_metrics = rlc2.get_metrics(); + TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics())); - if (rlc1_metrics.num_tx_bytes != rlc2_metrics.num_rx_bytes) { - return -1; - } - - if (rlc2_metrics.num_tx_bytes != rlc1_metrics.num_rx_bytes) { - return -1; - } - - return 0; + return SRSLTE_SUCCESS; } bool segment_test(bool in_seq_rx) @@ -330,18 +325,9 @@ bool segment_test(bool in_seq_rx) } // Check statistics - rlc_bearer_metrics_t rlc1_metrics = rlc1.get_metrics(); - rlc_bearer_metrics_t rlc2_metrics = rlc2.get_metrics(); + TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics())); - if (rlc1_metrics.num_tx_bytes != rlc2_metrics.num_rx_bytes) { - return -1; - } - - if (rlc2_metrics.num_tx_bytes != rlc1_metrics.num_rx_bytes) { - return -1; - } - - return 0; + return SRSLTE_SUCCESS; } bool retx_test() diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index 0262c6839..ba4fef745 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -533,18 +533,18 @@ void stress_test(stress_test_args_t args) tester1.get_nof_rx_pdus(), args.test_duration_sec, static_cast(tester1.get_nof_rx_pdus() / args.test_duration_sec), - metrics.bearer[lcid].num_tx_bytes, - metrics.bearer[lcid].num_rx_bytes); - printf("rlc1_num_lost=%d\n", metrics.bearer[lcid].num_lost_pdus); + metrics.bearer[lcid].num_tx_pdu_bytes, + metrics.bearer[lcid].num_rx_pdu_bytes); + rlc_bearer_metrics_print(metrics.bearer[lcid]); rlc2.get_metrics(metrics); printf("RLC2 received %d SDUs in %ds (%.2f/s), Tx=%" PRIu64 " B, Rx=%" PRIu64 " B\n", tester2.get_nof_rx_pdus(), args.test_duration_sec, static_cast(tester2.get_nof_rx_pdus() / args.test_duration_sec), - metrics.bearer[lcid].num_tx_bytes, - metrics.bearer[lcid].num_rx_bytes); - printf("rlc2_num_lost=%d\n", metrics.bearer[lcid].num_lost_pdus); + metrics.bearer[lcid].num_tx_pdu_bytes, + metrics.bearer[lcid].num_rx_pdu_bytes); + rlc_bearer_metrics_print(metrics.bearer[lcid]); } int main(int argc, char** argv)