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)
|
nr_rlc_statistics_t *out)
|
||||||
{
|
{
|
||||||
// printf("Stats from the RLC entity asked\n");
|
// printf("Stats from the RLC entity asked\n");
|
||||||
|
uint64_t time_now = time_average_now();
|
||||||
*out = entity->stats;
|
*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)
|
if (entity->avg_time_is_on)
|
||||||
out->txsdu_avg_time_to_tx = time_average_get_average(entity->txsdu_avg_time_to_tx,
|
out->txsdu_avg_time_to_tx = time_average_get_average(entity->txsdu_avg_time_to_tx, time_now);
|
||||||
time_average_now());
|
|
||||||
else
|
else
|
||||||
out->txsdu_avg_time_to_tx = 0;
|
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.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
|
/* 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);
|
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ typedef struct {
|
|||||||
/* TX */
|
/* TX */
|
||||||
uint32_t txpdu_pkts; /* aggregated number of transmitted RLC PDUs */
|
uint32_t txpdu_pkts; /* aggregated number of transmitted RLC PDUs */
|
||||||
uint32_t txpdu_bytes; /* aggregated amount of transmitted bytes in RLC PDUs */
|
uint32_t txpdu_bytes; /* aggregated amount of transmitted bytes in RLC PDUs */
|
||||||
/* TODO? */
|
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_wt_ms; /* 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_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_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) */
|
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_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_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) */
|
uint32_t txpdu_status_bytes; /* aggregated amount of tx status bytes (only applicable to RLC AM) */
|
||||||
/* TODO? */
|
uint32_t txbuf_occ_bytes; /* (IMPLEMENTED) transmitting bytes currently in buffer */
|
||||||
uint32_t txbuf_occ_bytes; /* current tx buffer occupancy in terms of amount of bytes (average: NOT IMPLEMENTED) */
|
uint32_t txbuf_occ_pkts; /* TODO: current tx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||||
/* TODO? */
|
|
||||||
uint32_t txbuf_occ_pkts; /* 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 */
|
/* txbuf_wd_ms: the time window for which the txbuf occupancy value is obtained - NOT IMPLEMENTED */
|
||||||
|
|
||||||
/* RX */
|
/* RX */
|
||||||
@@ -70,31 +67,28 @@ typedef struct {
|
|||||||
/* rxpdu_rotout_ms: flag indicating rx reordering timeout in ms - NOT IMPLEMENTED */
|
/* 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_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 */
|
/* rxpdu_sptout_ms: flag indicating status prohibit timeout in ms - NOT IMPLEMENTED */
|
||||||
/* TODO? */
|
uint32_t rxbuf_occ_bytes; /* (IMPLEMENTED) received bytes currently in buffer */
|
||||||
uint32_t rxbuf_occ_bytes; /* current rx buffer occupancy in terms of amount of bytes (average: NOT IMPLEMENTED) */
|
uint32_t rxbuf_occ_pkts; /* TODO: current rx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||||
/* TODO? */
|
|
||||||
uint32_t rxbuf_occ_pkts; /* current rx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
|
||||||
|
|
||||||
/* SDU stats */
|
/* SDU stats */
|
||||||
/* TX */
|
/* TX */
|
||||||
uint32_t txsdu_pkts; /* number of SDUs delivered */
|
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 */
|
/* RX */
|
||||||
uint32_t rxsdu_pkts; /* number of SDUs received */
|
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_pkts; /* number of dropped or discarded SDUs */
|
||||||
uint32_t rxsdu_dd_bytes; /* number of bytes of SDUs dropped or discarded */
|
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;
|
} nr_rlc_statistics_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -224,7 +224,8 @@ static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn)
|
|||||||
sdu, so);
|
sdu, so);
|
||||||
|
|
||||||
entity->common.stats.txsdu_pkts++;
|
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)
|
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;
|
end_wait_list = prev_wait_list;
|
||||||
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
||||||
entity->tx_size -= sdu_size;
|
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(
|
||||||
entity->common.sdu_successful_delivery_data,
|
entity->common.sdu_successful_delivery_data,
|
||||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||||
@@ -546,6 +549,8 @@ process_retransmit_list_head:
|
|||||||
+ cur->size;
|
+ cur->size;
|
||||||
if (nr_rlc_free_sdu_segment(cur)) {
|
if (nr_rlc_free_sdu_segment(cur)) {
|
||||||
entity->tx_size -= sdu_size;
|
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(
|
||||||
entity->common.sdu_successful_delivery_data,
|
entity->common.sdu_successful_delivery_data,
|
||||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||||
@@ -604,6 +609,8 @@ nacks_done:
|
|||||||
end_wait_list = prev_wait_list;
|
end_wait_list = prev_wait_list;
|
||||||
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
||||||
entity->tx_size -= sdu_size;
|
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(
|
||||||
entity->common.sdu_successful_delivery_data,
|
entity->common.sdu_successful_delivery_data,
|
||||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||||
@@ -625,6 +632,8 @@ nacks_done:
|
|||||||
+ cur->size;
|
+ cur->size;
|
||||||
if (nr_rlc_free_sdu_segment(cur)) {
|
if (nr_rlc_free_sdu_segment(cur)) {
|
||||||
entity->tx_size -= sdu_size;
|
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(
|
||||||
entity->common.sdu_successful_delivery_data,
|
entity->common.sdu_successful_delivery_data,
|
||||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
(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_pkts++;
|
||||||
entity->common.stats.txpdu_bytes += ret_size;
|
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 time_now = time_average_now();
|
||||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
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);
|
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;
|
nr_rlc_sdu_segment_t *sdu;
|
||||||
|
|
||||||
entity->common.stats.rxsdu_pkts++;
|
entity->common.stats.rxsdu_pkts++;
|
||||||
entity->common.stats.rxsdu_bytes += size;
|
|
||||||
|
|
||||||
if (size > NR_SDU_MAX) {
|
if (size > NR_SDU_MAX) {
|
||||||
LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
|
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;
|
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);
|
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;
|
+ cur->size;
|
||||||
|
|
||||||
entity->tx_size -= cur->sdu->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);
|
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_pkts++;
|
||||||
entity->common.stats.txpdu_bytes += size;
|
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 time_now = time_average_now();
|
||||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
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);
|
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_pkts++;
|
||||||
entity->common.stats.txpdu_bytes += size;
|
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 time_now = time_average_now();
|
||||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
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);
|
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) {
|
if (rb != NULL) {
|
||||||
rb->get_stats(rb, out);
|
rb->get_stats(rb, out);
|
||||||
ret = true;
|
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 {
|
} else {
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
#include "NR_RadioBearerConfig.h"
|
#include "NR_RadioBearerConfig.h"
|
||||||
#include "NR_CellGroupConfig.h"
|
#include "NR_CellGroupConfig.h"
|
||||||
#include "openair2/RRC/NR/nr_rrc_proto.h"
|
#include "openair2/RRC/NR/nr_rrc_proto.h"
|
||||||
|
#include "nr_rlc_ue_manager.h"
|
||||||
|
|
||||||
|
|
||||||
struct NR_RLC_Config;
|
struct NR_RLC_Config;
|
||||||
struct NR_LogicalChannelConfig;
|
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,
|
const uint8_t *sdu,
|
||||||
sdu_size_t sdu_len,
|
sdu_size_t sdu_len,
|
||||||
void *rawUE));
|
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