rlc: extend RLC metrics

extend RLC metrics to count Rx/Tx PDUs/SDUs bytes/#
master
Andre Puschmann 5 years ago
parent 48db31c5cf
commit df50dd7d3c

@ -118,6 +118,8 @@ private:
void update_bsr_mch(uint32_t lcid); void update_bsr_mch(uint32_t lcid);
}; };
void rlc_bearer_metrics_print(const rlc_bearer_metrics_t& metrics);
} // namespace srslte } // namespace srslte
#endif // SRSLTE_RLC_H #endif // SRSLTE_RLC_H

@ -23,19 +23,24 @@
#define SRSLTE_RLC_METRICS_H #define SRSLTE_RLC_METRICS_H
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include <iostream>
namespace srslte { namespace srslte {
typedef struct { typedef struct {
// SDU metrics
uint32_t num_tx_sdus; uint32_t num_tx_sdus;
uint32_t num_rx_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_tx_pdus;
uint32_t num_rx_pdus; uint32_t num_rx_pdus;
uint64_t num_tx_bytes; uint64_t num_tx_pdu_bytes;
uint64_t num_rx_bytes; uint64_t num_rx_pdu_bytes;
uint32_t num_lost_pdus; //< Lost PDUs registered at Rx 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; } rlc_bearer_metrics_t;
typedef struct { typedef struct {

@ -113,8 +113,8 @@ void rlc::get_metrics(rlc_metrics_t& m)
rlc_bearer_metrics_t metrics = it->second->get_metrics(); 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", rlc_log->info("LCID=%d, RX throughput: %4.6f Mbps. TX throughput: %4.6f Mbps.\n",
it->first, it->first,
(metrics.num_rx_bytes * 8 / static_cast<double>(1e6)) / secs, (metrics.num_rx_pdu_bytes * 8 / static_cast<double>(1e6)) / secs,
(metrics.num_tx_bytes * 8 / static_cast<double>(1e6)) / secs); (metrics.num_tx_pdu_bytes * 8 / static_cast<double>(1e6)) / secs);
m.bearer[it->first] = metrics; 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_bearer_metrics_t metrics = it->second->get_metrics();
rlc_log->info("MCH_LCID=%d, RX throughput: %4.6f Mbps\n", rlc_log->info("MCH_LCID=%d, RX throughput: %4.6f Mbps\n",
it->first, it->first,
(metrics.num_rx_bytes * 8 / static_cast<double>(1e6)) / secs); (metrics.num_rx_pdu_bytes * 8 / static_cast<double>(1e6)) / secs);
m.bearer[it->first] = metrics; 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 } // namespace srslte

@ -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) void rlc_am_lte::discard_sdu(uint32_t discard_sn)
{ {
tx.discard_sdu(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) 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) void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes)
{ {
rx.write_pdu(payload, 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); 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(); rx_sdu->set_timestamp();
parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu));
parent->metrics.num_rx_sdus++;
rx_sdu = allocate_unique_buffer(*pool, true); rx_sdu = allocate_unique_buffer(*pool, true);
if (rx_sdu == nullptr) { 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); 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(); rx_sdu->set_timestamp();
parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu));
parent->metrics.num_rx_sdus++;
rx_sdu = allocate_unique_buffer(*pool, true); rx_sdu = allocate_unique_buffer(*pool, true);
if (rx_sdu == NULL) { if (rx_sdu == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG

@ -173,7 +173,7 @@ int rlc_tm::read_pdu(uint8_t* payload, uint32_t nof_bytes)
ul_queue.size(), ul_queue.size(),
ul_queue.size_bytes()); ul_queue.size_bytes());
metrics.num_tx_bytes += pdu_size; metrics.num_tx_pdu_bytes += pdu_size;
return pdu_size; return pdu_size;
} else { } else {
log->warning("Queue empty while trying to read\n"); 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); memcpy(buf->msg, payload, nof_bytes);
buf->N_bytes = nof_bytes; buf->N_bytes = nof_bytes;
buf->set_timestamp(); 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") { if (rrc->get_rb_name(lcid) == "SRB0") {
rrc->write_pdu(lcid, std::move(buf)); rrc->write_pdu(lcid, std::move(buf));
} else { } else {

@ -95,15 +95,18 @@ void rlc_um_base::write_sdu(unique_byte_buffer_t sdu, bool blocking)
{ {
if (not tx_enabled || not tx) { if (not tx_enabled || not tx) {
log->debug("%s is currently deactivated. Dropping SDU (%d B)\n", rb_name.c_str(), sdu->N_bytes); 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; return;
} }
if (blocking) { if (blocking) {
metrics.num_tx_sdus++;
metrics.num_tx_sdu_bytes += sdu->N_bytes;
tx->write_sdu(std::move(sdu)); tx->write_sdu(std::move(sdu));
} else { } else {
if (tx->try_write_sdu(std::move(sdu)) != SRSLTE_SUCCESS) { 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) { if (not tx_enabled || not tx) {
log->debug("%s is currently deactivated. Ignoring SDU discard (SN %u)\n", rb_name.c_str(), discard_sn); log->debug("%s is currently deactivated. Ignoring SDU discard (SN %u)\n", rb_name.c_str(), discard_sn);
metrics.num_dropped_sdus++;
return; return;
} }
tx->discard_sdu(discard_sn); tx->discard_sdu(discard_sn);
metrics.num_lost_sdus++;
} }
/**************************************************************************** /****************************************************************************
* MAC interface * MAC interface
@ -142,7 +145,7 @@ int rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes)
if (tx && tx_enabled) { if (tx && tx_enabled) {
uint32_t len = tx->build_data_pdu(payload, nof_bytes); uint32_t len = tx->build_data_pdu(payload, nof_bytes);
if (len > 0) { if (len > 0) {
metrics.num_tx_bytes += len; metrics.num_tx_pdu_bytes += len;
metrics.num_tx_pdus++; metrics.num_tx_pdus++;
} }
return len; return len;
@ -154,7 +157,7 @@ void rlc_um_base::write_pdu(uint8_t* payload, uint32_t nof_bytes)
{ {
if (rx && rx_enabled) { if (rx && rx_enabled) {
metrics.num_rx_pdus++; metrics.num_rx_pdus++;
metrics.num_rx_bytes += nof_bytes; metrics.num_rx_pdu_bytes += nof_bytes;
rx->handle_data_pdu(payload, nof_bytes); rx->handle_data_pdu(payload, nof_bytes);
} }
} }

@ -402,6 +402,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
vr_ur, vr_ur,
i); i);
rx_sdu->set_timestamp(); rx_sdu->set_timestamp();
metrics.num_rx_sdus++;
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
if (cfg.um.is_mrb) { if (cfg.um.is_mrb) {
pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); pdcp->write_pdu_mch(lcid, std::move(rx_sdu));
} else { } else {
@ -435,6 +437,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
log->info_hex( 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->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(); rx_sdu->set_timestamp();
metrics.num_rx_sdus++;
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
if (cfg.um.is_mrb) { if (cfg.um.is_mrb) {
pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); pdcp->write_pdu_mch(lcid, std::move(rx_sdu));
} else { } else {
@ -544,6 +548,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
vr_ur, vr_ur,
i); i);
rx_sdu->set_timestamp(); rx_sdu->set_timestamp();
metrics.num_rx_sdus++;
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
if (cfg.um.is_mrb) { if (cfg.um.is_mrb) {
pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); pdcp->write_pdu_mch(lcid, std::move(rx_sdu));
} else { } else {
@ -604,6 +610,8 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
log->info_hex( 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->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(); rx_sdu->set_timestamp();
metrics.num_rx_sdus++;
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
if (cfg.um.is_mrb) { if (cfg.um.is_mrb) {
pdcp->write_pdu_mch(lcid, std::move(rx_sdu)); pdcp->write_pdu_mch(lcid, std::move(rx_sdu));
} else { } else {

@ -22,6 +22,7 @@
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
#include "srslte/common/logger_stdout.h" #include "srslte/common/logger_stdout.h"
#include "srslte/common/rlc_pcap.h" #include "srslte/common/rlc_pcap.h"
#include "srslte/common/test_common.h"
#include "srslte/common/threads.h" #include "srslte/common/threads.h"
#include "srslte/upper/rlc_am_lte.h" #include "srslte/upper/rlc_am_lte.h"
#include <assert.h> #include <assert.h>
@ -36,6 +37,18 @@ using namespace srslte;
srslte::log_ref rrc_log1("RLC_AM_1"); srslte::log_ref rrc_log1("RLC_AM_1");
srslte::log_ref rrc_log2("RLC_AM_2"); 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 class rlc_am_tester : public pdcp_interface_rlc, public rrc_interface_rlc
{ {
public: public:
@ -178,18 +191,9 @@ bool meas_obj_test()
} }
// Check statistics // Check statistics
rlc_bearer_metrics_t rlc1_metrics = rlc1.get_metrics(); TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics()));
rlc_bearer_metrics_t rlc2_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 SRSLTE_SUCCESS;
return -1;
}
return 0;
} }
bool concat_test() bool concat_test()
@ -239,18 +243,9 @@ bool concat_test()
} }
// Check statistics // Check statistics
rlc_bearer_metrics_t rlc1_metrics = rlc1.get_metrics(); TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics()));
rlc_bearer_metrics_t rlc2_metrics = rlc2.get_metrics();
if (rlc1_metrics.num_tx_bytes != rlc2_metrics.num_rx_bytes) { return SRSLTE_SUCCESS;
return -1;
}
if (rlc2_metrics.num_tx_bytes != rlc1_metrics.num_rx_bytes) {
return -1;
}
return 0;
} }
bool segment_test(bool in_seq_rx) bool segment_test(bool in_seq_rx)
@ -330,18 +325,9 @@ bool segment_test(bool in_seq_rx)
} }
// Check statistics // Check statistics
rlc_bearer_metrics_t rlc1_metrics = rlc1.get_metrics(); TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics()));
rlc_bearer_metrics_t rlc2_metrics = rlc2.get_metrics();
if (rlc1_metrics.num_tx_bytes != rlc2_metrics.num_rx_bytes) { return SRSLTE_SUCCESS;
return -1;
}
if (rlc2_metrics.num_tx_bytes != rlc1_metrics.num_rx_bytes) {
return -1;
}
return 0;
} }
bool retx_test() bool retx_test()

@ -533,18 +533,18 @@ void stress_test(stress_test_args_t args)
tester1.get_nof_rx_pdus(), tester1.get_nof_rx_pdus(),
args.test_duration_sec, args.test_duration_sec,
static_cast<double>(tester1.get_nof_rx_pdus() / args.test_duration_sec), static_cast<double>(tester1.get_nof_rx_pdus() / args.test_duration_sec),
metrics.bearer[lcid].num_tx_bytes, metrics.bearer[lcid].num_tx_pdu_bytes,
metrics.bearer[lcid].num_rx_bytes); metrics.bearer[lcid].num_rx_pdu_bytes);
printf("rlc1_num_lost=%d\n", metrics.bearer[lcid].num_lost_pdus); rlc_bearer_metrics_print(metrics.bearer[lcid]);
rlc2.get_metrics(metrics); rlc2.get_metrics(metrics);
printf("RLC2 received %d SDUs in %ds (%.2f/s), Tx=%" PRIu64 " B, Rx=%" PRIu64 " B\n", printf("RLC2 received %d SDUs in %ds (%.2f/s), Tx=%" PRIu64 " B, Rx=%" PRIu64 " B\n",
tester2.get_nof_rx_pdus(), tester2.get_nof_rx_pdus(),
args.test_duration_sec, args.test_duration_sec,
static_cast<double>(tester2.get_nof_rx_pdus() / args.test_duration_sec), static_cast<double>(tester2.get_nof_rx_pdus() / args.test_duration_sec),
metrics.bearer[lcid].num_tx_bytes, metrics.bearer[lcid].num_tx_pdu_bytes,
metrics.bearer[lcid].num_rx_bytes); metrics.bearer[lcid].num_rx_pdu_bytes);
printf("rlc2_num_lost=%d\n", metrics.bearer[lcid].num_lost_pdus); rlc_bearer_metrics_print(metrics.bearer[lcid]);
} }
int main(int argc, char** argv) int main(int argc, char** argv)

Loading…
Cancel
Save