Commit 76aa112c authored by Chieh-Chun Chen's avatar Chieh-Chun Chen Committed by Robert Schmidt

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: default avatarTeodora Vladic <teodora.vladic@openairinterface.org>
parent 8a4df37e
......@@ -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);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment