Files
openairinterface5g/openair2/LAYER2/nr_rlc/nr_rlc_entity.c
T
2026-09-19 23:28:08 +09:00

250 lines
9.6 KiB
C

/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
#include "nr_rlc_entity.h"
#include <stdlib.h>
#include "nr_rlc_entity_am.h"
#include "nr_rlc_entity_um.h"
#include "nr_rlc_entity_tm.h"
#include "LOG/log.h"
#include "common/utils/time_stat.h"
#include "common/utils/assertions.h"
static void nr_rlc_entity_get_stats(
nr_rlc_entity_t *entity,
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_now);
else
out->txsdu_avg_time_to_tx = 0;
}
nr_rlc_entity_t *new_nr_rlc_entity_am(int rx_maxsize,
int tx_maxsize,
void (*deliver_sdu)(void *deliver_sdu_data, nr_rlc_entity_t *entity, char *buf, int size),
void *deliver_sdu_data,
void (*sdu_successful_delivery)(void *sdu_successful_delivery_data,
nr_rlc_entity_t *entity,
int sdu_id),
void *sdu_successful_delivery_data,
void (*max_retx_reached)(void *max_retx_reached_data, nr_rlc_entity_t *entity),
void *max_retx_reached_data,
int t_poll_retransmit,
int t_reassembly,
int t_status_prohibit,
int poll_pdu,
int poll_byte,
int max_retx_threshold,
int sn_field_length)
{
nr_rlc_entity_am_t *ret;
ret = calloc(1, sizeof(nr_rlc_entity_am_t));
if (ret == NULL) {
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
ret->tx_maxsize = tx_maxsize * 5;
ret->rx_maxsize = rx_maxsize * 5;
ret->t_poll_retransmit = t_poll_retransmit;
ret->t_reassembly = t_reassembly;
ret->t_status_prohibit = t_status_prohibit;
ret->poll_pdu = poll_pdu;
ret->poll_byte = poll_byte;
ret->max_retx_threshold = max_retx_threshold;
ret->sn_field_length = sn_field_length;
AssertFatal(sn_field_length == 12 || sn_field_length == 18, "Wrong SN field_length (%d), must be 12 or 18\n", sn_field_length);
ret->sn_modulus = 1 << ret->sn_field_length;
ret->window_size = ret->sn_modulus / 2;
ret->common.recv_pdu = nr_rlc_entity_am_recv_pdu;
ret->common.buffer_status = nr_rlc_entity_am_buffer_status;
ret->common.generate_pdu = nr_rlc_entity_am_generate_pdu;
ret->common.recv_sdu = nr_rlc_entity_am_recv_sdu;
ret->common.set_time = nr_rlc_entity_am_set_time;
ret->common.discard_sdu = nr_rlc_entity_am_discard_sdu;
ret->common.reestablishment = nr_rlc_entity_am_reestablishment;
ret->common.delete_entity = nr_rlc_entity_am_delete;
ret->common.available_tx_space = nr_rlc_entity_am_available_tx_space;
ret->common.tx_list_occupancy = nr_rlc_entity_am_tx_list_occupancy;
ret->common.get_stats = nr_rlc_entity_get_stats;
ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data;
ret->common.sdu_successful_delivery = sdu_successful_delivery;
ret->common.sdu_successful_delivery_data = sdu_successful_delivery_data;
ret->common.max_retx_reached = max_retx_reached;
ret->common.max_retx_reached_data = max_retx_reached_data;
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 (packets) is arbitrary
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(1000 * 1000, 1024);
ret->rx = nr_rlc_new_rx_manager(1 << (sn_field_length - 1));
return (nr_rlc_entity_t *)ret;
}
nr_rlc_entity_t *new_nr_rlc_entity_um(int rx_maxsize,
int tx_maxsize,
void (*deliver_sdu)(void *deliver_sdu_data, nr_rlc_entity_t *entity, char *buf, int size),
void *deliver_sdu_data,
int t_reassembly,
int sn_field_length)
{
nr_rlc_entity_um_t *ret;
ret = calloc(1, sizeof(nr_rlc_entity_um_t));
if (ret == NULL) {
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
ret->tx_maxsize = tx_maxsize;
ret->rx_maxsize = rx_maxsize;
ret->t_reassembly = t_reassembly;
ret->sn_field_length = sn_field_length;
AssertFatal(sn_field_length == 6 || sn_field_length == 12, "Wrong SN field_length (%d), must be 6 or 12\n", sn_field_length);
ret->sn_modulus = 1 << ret->sn_field_length;
ret->window_size = ret->sn_modulus / 2;
ret->common.recv_pdu = nr_rlc_entity_um_recv_pdu;
ret->common.buffer_status = nr_rlc_entity_um_buffer_status;
ret->common.generate_pdu = nr_rlc_entity_um_generate_pdu;
ret->common.recv_sdu = nr_rlc_entity_um_recv_sdu;
ret->common.set_time = nr_rlc_entity_um_set_time;
ret->common.discard_sdu = nr_rlc_entity_um_discard_sdu;
ret->common.reestablishment = nr_rlc_entity_um_reestablishment;
ret->common.delete_entity = nr_rlc_entity_um_delete;
ret->common.available_tx_space = nr_rlc_entity_um_available_tx_space;
ret->common.tx_list_occupancy = nr_rlc_entity_um_tx_list_occupancy;
ret->common.get_stats = nr_rlc_entity_get_stats;
ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data;
ret->common.stats.mode = NR_RLC_UM;
/* let's take average over the last 100 milliseconds
* initial_size of 1024 is arbitrary
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(1000 * 1000, 1024);
return (nr_rlc_entity_t *)ret;
}
nr_rlc_entity_t *new_nr_rlc_entity_tm(int tx_maxsize,
void (*deliver_sdu)(void *deliver_sdu_data, nr_rlc_entity_t *entity, char *buf, int size),
void *deliver_sdu_data)
{
nr_rlc_entity_tm_t *ret;
ret = calloc(1, sizeof(nr_rlc_entity_tm_t));
if (ret == NULL) {
LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
ret->tx_maxsize = tx_maxsize;
ret->common.recv_pdu = nr_rlc_entity_tm_recv_pdu;
ret->common.buffer_status = nr_rlc_entity_tm_buffer_status;
ret->common.generate_pdu = nr_rlc_entity_tm_generate_pdu;
ret->common.recv_sdu = nr_rlc_entity_tm_recv_sdu;
ret->common.set_time = nr_rlc_entity_tm_set_time;
ret->common.discard_sdu = nr_rlc_entity_tm_discard_sdu;
ret->common.reestablishment = nr_rlc_entity_tm_reestablishment;
ret->common.delete_entity = nr_rlc_entity_tm_delete;
ret->common.available_tx_space = nr_rlc_entity_tm_available_tx_space;
ret->common.tx_list_occupancy = nr_rlc_entity_tm_tx_list_occupancy;
ret->common.get_stats = nr_rlc_entity_get_stats;
ret->common.deliver_sdu = deliver_sdu;
ret->common.deliver_sdu_data = deliver_sdu_data;
ret->common.stats.mode = NR_RLC_TM;
/* let's take average over the last 100 milliseconds
* initial_size of 1024 is arbitrary
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(1000 * 1000, 1024);
return (nr_rlc_entity_t *)ret;
}
void nr_rlc_entity_um_reconfigure(nr_rlc_entity_t *_entity, int t_reassembly, int *sn_field_length)
{
nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
entity->t_reassembly = t_reassembly;
if (sn_field_length)
entity->sn_field_length = *sn_field_length;
}
void nr_rlc_entity_am_reconfigure(nr_rlc_entity_t *_entity,
int t_poll_retransmit,
int t_reassembly,
int t_status_prohibit,
int poll_pdu,
int poll_byte,
int max_retx_threshold,
int *sn_field_length)
{
nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
entity->t_poll_retransmit = t_poll_retransmit;
entity->t_reassembly = t_reassembly;
entity->t_status_prohibit = t_status_prohibit;
entity->poll_pdu = poll_pdu;
entity->poll_byte = poll_byte;
entity->max_retx_threshold = max_retx_threshold;
if (sn_field_length)
entity->sn_field_length = *sn_field_length;
}