Add more RLC stats and correct RLC stats
- Add GOL-delay and AVG-soujour - Correct the types of/measurement the tx/rxsdu_bytes and tx/rxsdu_occ_bytes - Update txsdu_avg_time_to_tx value only when measurements activated Co-authored-by: Teodora Vladic <teodora.vladic@openairinterface.org>
This commit is contained in:
committed by
Robert Schmidt
co-authored by
Teodora Vladic
parent
8a4df37e83
commit
76aa112cec
@@ -36,10 +36,36 @@ static void nr_rlc_entity_get_stats(
|
||||
nr_rlc_statistics_t *out)
|
||||
{
|
||||
// printf("Stats from the RLC entity asked\n");
|
||||
uint64_t time_now = time_average_now();
|
||||
*out = entity->stats;
|
||||
|
||||
// Get the correct HOL RLC-SDU
|
||||
nr_rlc_sdu_segment_t* sdu;
|
||||
if (entity->stats.mode == NR_RLC_AM) {
|
||||
nr_rlc_entity_am_t* am_entity = (nr_rlc_entity_am_t *) entity;
|
||||
if (am_entity->retransmit_list != NULL) {
|
||||
sdu = am_entity->retransmit_list;
|
||||
} else {
|
||||
sdu = am_entity->tx_list;
|
||||
}
|
||||
} else if (entity->stats.mode == NR_RLC_UM) {
|
||||
nr_rlc_entity_um_t* um_entity = (nr_rlc_entity_um_t *) entity;
|
||||
sdu = um_entity->tx_list;
|
||||
} else {
|
||||
nr_rlc_entity_tm_t* tm_entity = (nr_rlc_entity_tm_t *) entity;
|
||||
sdu = tm_entity->tx_list;
|
||||
}
|
||||
|
||||
// Compute HOL waittime, make sure that segmented packets don't have 'zero' time-of-arrival
|
||||
if (sdu != NULL) {
|
||||
out->txsdu_wt_us = time_now - sdu->sdu->time_of_arrival;
|
||||
} else {
|
||||
// No HOL packets --> wait-time == 0
|
||||
out->txsdu_wt_us = 0;
|
||||
}
|
||||
|
||||
if (entity->avg_time_is_on)
|
||||
out->txsdu_avg_time_to_tx = time_average_get_average(entity->txsdu_avg_time_to_tx,
|
||||
time_average_now());
|
||||
out->txsdu_avg_time_to_tx = time_average_get_average(entity->txsdu_avg_time_to_tx, time_now);
|
||||
else
|
||||
out->txsdu_avg_time_to_tx = 0;
|
||||
}
|
||||
@@ -112,8 +138,11 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
|
||||
|
||||
ret->common.stats.mode = NR_RLC_AM;
|
||||
|
||||
ret->common.stats.rxsdu_bytes = 0; // init default arrivals (SDU) counter
|
||||
ret->common.stats.txsdu_bytes = 0; // init default transmits (SDU) counter
|
||||
|
||||
/* let's take average over the last 100 milliseconds
|
||||
* initial_size of 1024 is arbitrary
|
||||
* initial_size of 1024 (packets) is arbitrary
|
||||
*/
|
||||
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@ typedef struct {
|
||||
/* TX */
|
||||
uint32_t txpdu_pkts; /* aggregated number of transmitted RLC PDUs */
|
||||
uint32_t txpdu_bytes; /* aggregated amount of transmitted bytes in RLC PDUs */
|
||||
/* TODO? */
|
||||
uint32_t txpdu_wt_ms; /* aggregated head-of-line tx packet waiting time to be transmitted (i.e. send to the MAC layer) */
|
||||
uint32_t txpdu_wt_ms; /* TODO: aggregated head-of-line tx packet waiting time to be transmitted (i.e. send to the MAC layer) */
|
||||
uint32_t txpdu_dd_pkts; /* aggregated number of dropped or discarded tx packets by RLC */
|
||||
uint32_t txpdu_dd_bytes; /* aggregated amount of bytes dropped or discarded tx packets by RLC */
|
||||
uint32_t txpdu_retx_pkts; /* aggregated number of tx pdus/pkts to be re-transmitted (only applicable to RLC AM) */
|
||||
@@ -50,10 +49,8 @@ typedef struct {
|
||||
uint32_t txpdu_segmented; /* aggregated number of segmentations */
|
||||
uint32_t txpdu_status_pkts; /* aggregated number of tx status pdus/pkts (only applicable to RLC AM) */
|
||||
uint32_t txpdu_status_bytes; /* aggregated amount of tx status bytes (only applicable to RLC AM) */
|
||||
/* TODO? */
|
||||
uint32_t txbuf_occ_bytes; /* current tx buffer occupancy in terms of amount of bytes (average: NOT IMPLEMENTED) */
|
||||
/* TODO? */
|
||||
uint32_t txbuf_occ_pkts; /* current tx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
uint32_t txbuf_occ_bytes; /* (IMPLEMENTED) transmitting bytes currently in buffer */
|
||||
uint32_t txbuf_occ_pkts; /* TODO: current tx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
/* txbuf_wd_ms: the time window for which the txbuf occupancy value is obtained - NOT IMPLEMENTED */
|
||||
|
||||
/* RX */
|
||||
@@ -70,31 +67,28 @@ typedef struct {
|
||||
/* rxpdu_rotout_ms: flag indicating rx reordering timeout in ms - NOT IMPLEMENTED */
|
||||
/* rxpdu_potout_ms: flag indicating the poll retransmit time out in ms - NOT IMPLEMENTED */
|
||||
/* rxpdu_sptout_ms: flag indicating status prohibit timeout in ms - NOT IMPLEMENTED */
|
||||
/* TODO? */
|
||||
uint32_t rxbuf_occ_bytes; /* current rx buffer occupancy in terms of amount of bytes (average: NOT IMPLEMENTED) */
|
||||
/* TODO? */
|
||||
uint32_t rxbuf_occ_pkts; /* current rx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
uint32_t rxbuf_occ_bytes; /* (IMPLEMENTED) received bytes currently in buffer */
|
||||
uint32_t rxbuf_occ_pkts; /* TODO: current rx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
|
||||
/* SDU stats */
|
||||
/* TX */
|
||||
uint32_t txsdu_pkts; /* number of SDUs delivered */
|
||||
uint32_t txsdu_bytes; /* number of bytes of SDUs delivered */
|
||||
uint64_t txsdu_bytes; /* (UPDATED) number of SDUs bytes successfully transmitted so far (counter) */
|
||||
/* Average time for an SDU to be passed to MAC:
|
||||
* Actually measures the time it takes for THE FULL SDU to be passed to MAC FOR THE FIRST TIME.
|
||||
* Since the MAC schedules in advance, it does not measure the time of
|
||||
* transmission over the air, just the time to reach the MAC layer.
|
||||
* => to control it, 'txsdu_wt_us' that measures the current HOL-delay is added.
|
||||
*/
|
||||
double txsdu_avg_time_to_tx; /* (100ms-windowed) per-packet sojourn (SDU to PDU) in microseconds */
|
||||
uint32_t txsdu_wt_us; /* HOL delay of the current radio bearer, in microseconds */
|
||||
|
||||
/* RX */
|
||||
uint32_t rxsdu_pkts; /* number of SDUs received */
|
||||
uint32_t rxsdu_bytes; /* number of bytes of SDUs received */
|
||||
uint64_t rxsdu_bytes; /* (UPDATED) number of SDUs bytes arrived so far (counter) */
|
||||
uint32_t rxsdu_dd_pkts; /* number of dropped or discarded SDUs */
|
||||
uint32_t rxsdu_dd_bytes; /* number of bytes of SDUs dropped or discarded */
|
||||
|
||||
/* Average time for an SDU to be passed to MAC.
|
||||
* Actually measures the time it takes for any part of an SDU to be
|
||||
* passed to MAC for the first time, that is: the first TX of (part of) the
|
||||
* SDU.
|
||||
* Since the MAC schedules in advance, it does not measure the time of
|
||||
* transmission over the air, just the time to reach the MAC layer.
|
||||
*/
|
||||
double txsdu_avg_time_to_tx;
|
||||
|
||||
} nr_rlc_statistics_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -224,7 +224,8 @@ static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn)
|
||||
sdu, so);
|
||||
|
||||
entity->common.stats.txsdu_pkts++;
|
||||
entity->common.stats.txsdu_bytes += so;
|
||||
/* AM 'txsdu_bytes' now only count successfully transmitted bytes */
|
||||
// entity->common.stats.txsdu_bytes += so;
|
||||
}
|
||||
|
||||
static void reception_actions(nr_rlc_entity_am_t *entity, nr_rlc_pdu_t *pdu)
|
||||
@@ -484,6 +485,8 @@ process_wait_list_head:
|
||||
end_wait_list = prev_wait_list;
|
||||
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Wait-ACK: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -546,6 +549,8 @@ process_retransmit_list_head:
|
||||
+ cur->size;
|
||||
if (nr_rlc_free_sdu_segment(cur)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Retransmit-ACK: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -604,6 +609,8 @@ nacks_done:
|
||||
end_wait_list = prev_wait_list;
|
||||
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Wait-NACK done: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -625,6 +632,8 @@ nacks_done:
|
||||
+ cur->size;
|
||||
if (nr_rlc_free_sdu_segment(cur)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Retransmit-NACK done: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -1619,11 +1628,11 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += ret_size;
|
||||
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
if (entity->common.avg_time_is_on) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
/* set time_of_arrival to 0 so as to update stats only once */
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
|
||||
@@ -1681,7 +1690,6 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
nr_rlc_sdu_segment_t *sdu;
|
||||
|
||||
entity->common.stats.rxsdu_pkts++;
|
||||
entity->common.stats.rxsdu_bytes += size;
|
||||
|
||||
if (size > NR_SDU_MAX) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
|
||||
@@ -1705,6 +1713,8 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
}
|
||||
|
||||
entity->tx_size += size;
|
||||
// SDU received: Count as arrival bytes
|
||||
entity->common.stats.rxsdu_bytes += size;
|
||||
|
||||
sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
|
||||
|
||||
@@ -1899,6 +1909,10 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
|
||||
+ cur->size;
|
||||
|
||||
entity->tx_size -= cur->sdu->size;
|
||||
|
||||
/* Uncomment to assert if SDU are ever discarded */
|
||||
// assert(0 != 0 && "[RLC-TRAP] SDU discard should never be reached!");
|
||||
|
||||
nr_rlc_free_sdu_segment(cur);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,11 +79,11 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size)
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += size;
|
||||
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
if (entity->common.avg_time_is_on) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
/* set time_of_arrival to 0 so as to update stats only once */
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
|
||||
|
||||
@@ -521,11 +521,11 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += size;
|
||||
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
if (entity->common.avg_time_is_on) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
/* set time_of_arrival to 0 so as to update stats only once */
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
|
||||
|
||||
@@ -1070,6 +1070,12 @@ const bool nr_rlc_get_statistics(
|
||||
if (rb != NULL) {
|
||||
rb->get_stats(rb, out);
|
||||
ret = true;
|
||||
|
||||
// Patch buffer status using OAI results (no need to change anything in the RB)
|
||||
// rb->set_time(rb, nr_rlc_current_time);
|
||||
nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 1000*1000);
|
||||
out->rxbuf_occ_bytes = oai_stat.status_size;
|
||||
out->txbuf_occ_bytes = oai_stat.tx_size + oai_stat.retx_size;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "NR_RadioBearerConfig.h"
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_proto.h"
|
||||
#include "nr_rlc_ue_manager.h"
|
||||
|
||||
|
||||
struct NR_RLC_Config;
|
||||
struct NR_LogicalChannelConfig;
|
||||
@@ -67,3 +69,5 @@ void nr_rlc_activate_srb0(int rnti, struct gNB_MAC_INST_s *mac, void *rawUE,
|
||||
const uint8_t *sdu,
|
||||
sdu_size_t sdu_len,
|
||||
void *rawUE));
|
||||
|
||||
const bool nr_rlc_get_statistics(int rnti, int srb_flag, int rb_id, nr_rlc_statistics_t *out);
|
||||
|
||||
Reference in New Issue
Block a user