Compare commits

...

2 Commits

Author SHA1 Message Date
Cedric Roux
a7ab1828d1 nr rlc: don't drop packets if pdcp is in charge of dropping
Memory usage may grow in which case some warnings will be printed.
2023-08-14 10:48:39 +02:00
Cedric Roux
a63f1704fa nr pdcp: add --pdcp-drop option to drop packets in PDCP instead of RLC
This only works in monolithic. F1 split to be done later, it's a bit more
complicated.

And actually, the drop in RLC is still there, but it should not happen.
Or much less.

The logic around rlc_data_queue_occupancy() is not satisfying. It is
done globally for all the UEs so we may underestimate the real free
space in RLC for a given UE, and thus reject more packets than
necessary.
2023-08-14 10:48:39 +02:00
18 changed files with 294 additions and 67 deletions

View File

@@ -105,10 +105,11 @@ extern "C"
#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR 'MONOLITHIC', 'PNF', 'VNF','UE_STUB_PNF','UE_STUB_OFFNET','STANDALONE_PNF'\n"
#define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n"
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence\n"
#define CONFIG_HLP_SYNC_REF "Sync Reference in Sidelink\n"
#define CONFIG_HLP_NID1 "Set NID1 value in Sidelink\n"
#define CONFIG_HLP_NID2 "Set NID2 value in Sidelink\n"
#define CONFIG_HLP_PDCP_DROP "drop overloaded traffic at PDCP instead of RLC\n"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters common to eNodeB and UE */
@@ -145,6 +146,8 @@ extern "C"
#define NID2 softmodem_params.nid2
#define REORDER_THREAD_DISABLE softmodem_params.reorder_thread_disable
#define PDCP_DROP softmodem_params.pdcp_drop
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
extern int usrp_tx_thread;
@@ -190,6 +193,7 @@ extern int usrp_tx_thread;
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
{"nid1", CONFIG_HLP_NID1, 0, .iptr=&NID1, .defintval=10, TYPE_INT, 0}, \
{"nid2", CONFIG_HLP_NID2, 0, .iptr=&NID2, .defintval=1, TYPE_INT, 0}, \
{"pdcp-drop", CONFIG_HLP_PDCP_DROP, PARAMFLAG_BOOL, .iptr=&PDCP_DROP, .defintval=0, TYPE_INT, 0}, \
}
// clang-format on
@@ -238,6 +242,7 @@ extern int usrp_tx_thread;
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
// clang-format on
@@ -349,6 +354,7 @@ typedef struct {
int sync_ref;
int nid1;
int nid2;
int pdcp_drop;
} softmodem_params_t;
extern uint64_t get_softmodem_optmask(void);

View File

@@ -31,6 +31,7 @@
#include "nr_pdcp_sdu.h"
#include "LOG/log.h"
#include "executables/softmodem-common.h"
static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
char *_buffer, int size)
@@ -193,6 +194,27 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
entity->stats.rxsdu_pkts++;
entity->stats.rxsdu_bytes += size;
if (entity->sn_size == 12) {
header_size = 2;
} else {
header_size = 3;
}
/* SRBs always have MAC-I, even if integrity is not active */
if (entity->has_integrity || entity->type == NR_PDCP_SRB) {
integrity_size = 4;
} else {
integrity_size = 0;
}
/* if dropping is enabled, check if RLC has enough space to receive the PDU */
if (entity->do_drop) {
if (entity->type != NR_PDCP_SRB)
if (header_size + size + integrity_size > entity->rlc_tx_freesize)
return -1;
}
entity->rlc_tx_freesize -= size;
count = entity->tx_next;
sn = entity->tx_next & entity->sn_max;
@@ -207,19 +229,10 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity,
if (entity->sn_size == 12) {
buf[0] = dc_bit | ((sn >> 8) & 0xf);
buf[1] = sn & 0xff;
header_size = 2;
} else {
buf[0] = dc_bit | ((sn >> 16) & 0x3);
buf[1] = (sn >> 8) & 0xff;
buf[2] = sn & 0xff;
header_size = 3;
}
/* SRBs always have MAC-I, even if integrity is not active */
if (entity->has_integrity || entity->type == NR_PDCP_SRB) {
integrity_size = 4;
} else {
integrity_size = 0;
}
memcpy(buf + header_size, buffer, size);
@@ -362,11 +375,25 @@ static void check_t_reordering(nr_pdcp_entity_t *entity)
}
}
void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now)
static void log_dropped_packets(nr_pdcp_entity_t *entity)
{
/* log only every 2 seconds */
if (entity->t_current < entity->dropped_lastlog_time + 2000)
return;
if (entity->dropped_sdus == 0)
return;
LOG_W(PDCP, "%"PRIu64" SDUs (%"PRIu64" bytes) dropped\n", entity->dropped_sdus, entity->dropped_bytes);
entity->dropped_sdus = 0;
entity->dropped_bytes = 0;
entity->dropped_lastlog_time = entity->t_current;
}
void nr_pdcp_entity_set_time(nr_pdcp_entity_t *entity, uint64_t now)
{
entity->t_current = now;
check_t_reordering(entity);
log_dropped_packets(entity);
}
void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity)
@@ -449,9 +476,18 @@ nr_pdcp_entity_t *new_nr_pdcp_entity(
ret->is_gnb = is_gnb;
ret->rlc_rnti = -1;
ret->do_drop = get_softmodem_params()->pdcp_drop;
nr_pdcp_entity_set_security(ret,
integrity_algorithm, (char *)integrity_key,
ciphering_algorithm, (char *)ciphering_key);
return ret;
}
void nr_pdcp_entity_set_rlc_ids(nr_pdcp_entity_t *entity, int rlc_rnti, int rlc_channel_id)
{
entity->rlc_rnti = rlc_rnti;
entity->rlc_channel_id = rlc_channel_id;
}

View File

@@ -152,6 +152,16 @@ typedef struct nr_pdcp_entity_t {
int rx_maxsize;
nr_pdcp_statistics_t stats;
/* RLC TX buffer size estimation */
bool do_drop; /* dropping is optional */
/* PDCP entity drops a packet if its size is > rlc_tx_freesize */
int rlc_tx_freesize;
int rlc_rnti; /* set to -1 if unknown (think CU entity) */
int rlc_channel_id;
uint64_t dropped_sdus;
uint64_t dropped_bytes;
uint64_t dropped_lastlog_time;
// WARNING: This is a hack!
// 3GPP TS 38.331 (RRC) version 15.3
// Section 5.3.4.3 Reception of the SecurityModeCommand by the UE
@@ -187,4 +197,6 @@ nr_pdcp_entity_t *new_nr_pdcp_entity(
unsigned char *ciphering_key,
unsigned char *integrity_key);
void nr_pdcp_entity_set_rlc_ids(nr_pdcp_entity_t *entity, int rlc_rnti, int rlc_channel_id);
#endif /* _NR_PDCP_ENTITY_H_ */

View File

@@ -103,6 +103,7 @@ typedef struct {
volatile int length;
pthread_mutex_t m;
pthread_cond_t c;
int bytes_stored;
} rlc_data_req_queue;
static rlc_data_req_queue q;
@@ -135,6 +136,8 @@ static void *rlc_data_req_thread(void *_)
q.length--;
q.start = (q.start + 1) % RLC_DATA_REQ_QUEUE_SIZE;
q.bytes_stored -= q.q[i].sdu_sizeP;
if (pthread_cond_signal(&q.c) != 0) abort();
if (pthread_mutex_unlock(&q.m) != 0) abort();
}
@@ -177,6 +180,8 @@ static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
i = (q.start + q.length) % RLC_DATA_REQ_QUEUE_SIZE;
q.length++;
q.bytes_stored += sdu_sizeP;
q.q[i].ctxt_pP = *ctxt_pP;
q.q[i].srb_flagP = srb_flagP;
q.q[i].MBMS_flagP = MBMS_flagP;
@@ -208,6 +213,21 @@ void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP,
sdu_pP);
}
static int rlc_data_queue_occupancy(void)
{
int ret;
/* no queue for CU */
if (NODE_IS_CU(node_type))
return 0;
if (pthread_mutex_lock(&q.m) != 0) abort();
ret = q.bytes_stored;
if (pthread_mutex_unlock(&q.m) != 0) abort();
return ret;
}
/****************************************************************************/
/* rlc_data_req queue - end */
/****************************************************************************/
@@ -1033,7 +1053,12 @@ bool nr_pdcp_data_req_srb(ue_id_t ue_id,
LOG_D(PDCP, "%s() called, size %d\n", __func__, sdu_buffer_size);
nr_pdcp_ue_t *ue;
nr_pdcp_entity_t *rb;
int rlc_rnti;
int rlc_channel_id;
int rlc_tx_freesize = -1;
bool rlc_tx_freesize_updated = false;
try_to_process_again:
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
@@ -1051,12 +1076,40 @@ bool nr_pdcp_data_req_srb(ue_id_t ue_id,
int max_size = sdu_buffer_size + 3 + 4; // 3: max header, 4: max integrity
char pdu_buf[max_size];
if (rlc_tx_freesize != -1)
rb->rlc_tx_freesize = rlc_tx_freesize;
int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size);
rlc_rnti = rb->rlc_rnti;
rlc_channel_id = rb->rlc_channel_id;
AssertFatal(rb->deliver_pdu == NULL, "SRB callback should be NULL, to be provided on every invocation\n");
if (pdu_size == -1 && rlc_tx_freesize_updated) {
/* update stats of dropped SDUs */
rb->dropped_sdus++;
rb->dropped_bytes += sdu_buffer_size;
}
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
deliver_pdu_cb(data, ue_id, rb_id, pdu_buf, pdu_size, muiP);
/* nr_rlc_get_available_tx_space() should be called by rb->process_sdu()
* but because the RLC lock must not be acquired when the PDCP lock is acquired,
* we need to call it here and have this logic of calling rb->process_sdu()
* a second time if the first call failed.
* If the locking logic changes, this may need to be changed.
* (And the update of stats of dropped SDUs will then need to be changed
* too, not done here anymore.)
*/
if (pdu_size == -1 && !rlc_tx_freesize_updated && rlc_rnti != -1) {
rlc_tx_freesize = nr_rlc_get_available_tx_space(rlc_rnti, rlc_channel_id)
- rlc_data_queue_occupancy();
if (rlc_tx_freesize < 0)
rlc_tx_freesize = 0;
rlc_tx_freesize_updated = true;
goto try_to_process_again;
}
if (pdu_size != -1)
deliver_pdu_cb(data, ue_id, rb_id, pdu_buf, pdu_size, muiP);
return 1;
}
@@ -1111,6 +1164,10 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP,
nr_pdcp_ue_t *ue;
nr_pdcp_entity_t *rb;
ue_id_t ue_id = ctxt_pP->rntiMaybeUEid;
int rlc_rnti;
int rlc_channel_id;
int rlc_tx_freesize = -1;
bool rlc_tx_freesize_updated = false;
if (ctxt_pP->module_id != 0 ||
//ctxt_pP->enb_flag != 1 ||
@@ -1122,6 +1179,7 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP,
exit(1);
}
try_to_process_again:
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
@@ -1139,12 +1197,40 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP,
int max_size = sdu_buffer_size + 3 + 4; // 3: max header, 4: max integrity
char pdu_buf[max_size];
if (rlc_tx_freesize != -1)
rb->rlc_tx_freesize = rlc_tx_freesize;
int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size);
rlc_rnti = rb->rlc_rnti;
rlc_channel_id = rb->rlc_channel_id;
deliver_pdu deliver_pdu_cb = rb->deliver_pdu;
if (pdu_size == -1 && rlc_tx_freesize_updated) {
/* update stats of dropped SDUs */
rb->dropped_sdus++;
rb->dropped_bytes += sdu_buffer_size;
}
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
deliver_pdu_cb(NULL, ue_id, rb_id, pdu_buf, pdu_size, muiP);
/* nr_rlc_get_available_tx_space() should be called by rb->process_sdu()
* but because the RLC lock must not be acquired when then PDCP lock is acquired,
* we need to call it here and have this logic of calling rb->process_sdu()
* a second time if the first call failed.
* If the locking logic changes, this may need to be changed.
* (And the update of stats of dropped SDUs will then need to be changed
* too, not done here anymore.)
*/
if (pdu_size == -1 && !rlc_tx_freesize_updated && rlc_rnti != -1) {
rlc_tx_freesize = nr_rlc_get_available_tx_space(rlc_rnti, rlc_channel_id)
- rlc_data_queue_occupancy();
if (rlc_tx_freesize < 0)
rlc_tx_freesize = 0;
rlc_tx_freesize_updated = true;
goto try_to_process_again;
}
if (pdu_size != -1)
deliver_pdu_cb(NULL, ue_id, rb_id, pdu_buf, pdu_size, muiP);
return 1;
}
@@ -1258,3 +1344,32 @@ const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdc
return ret;
}
void nr_pdcp_set_rlc_ids(ue_id_t ue_id, bool srb_flag, int rb_id, int rlc_rnti, int rlc_channel_id)
{
nr_pdcp_ue_t *ue;
nr_pdcp_entity_t *rb;
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
if (srb_flag) {
if (rb_id < 1 || rb_id > 2)
rb = NULL;
else
rb = ue->srb[rb_id - 1];
} else {
if (rb_id < 1 || rb_id > 5)
rb = NULL;
else
rb = ue->drb[rb_id - 1];
}
if (rb != NULL) {
nr_pdcp_entity_set_rlc_ids(rb, rlc_rnti, rlc_channel_id);
} else {
LOG_E(PDCP, "ue %"PRIx64" not found\n", ue_id);
}
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}

View File

@@ -105,4 +105,6 @@ nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager();
const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out);
void nr_pdcp_set_rlc_ids(ue_id_t ue_id, bool srb_flag, int rb_id, int rlc_rnti, int rlc_channel_id);
#endif /* NR_PDCP_OAI_API_H */

View File

@@ -63,7 +63,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
int poll_pdu,
int poll_byte,
int max_retx_threshold,
int sn_field_length)
int sn_field_length,
bool do_drop)
{
nr_rlc_entity_am_t *ret;
@@ -117,6 +118,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
ret->common.do_drop = do_drop;
return (nr_rlc_entity_t *)ret;
}
@@ -127,7 +130,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_um(
char *buf, int size),
void *deliver_sdu_data,
int t_reassembly,
int sn_field_length)
int sn_field_length,
bool do_drop)
{
nr_rlc_entity_um_t *ret;
@@ -172,6 +176,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_um(
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
ret->common.do_drop = do_drop;
return (nr_rlc_entity_t *)ret;
}
@@ -179,7 +185,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_tm(
int tx_maxsize,
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
char *buf, int size),
void *deliver_sdu_data)
void *deliver_sdu_data,
bool do_drop)
{
nr_rlc_entity_tm_t *ret;
@@ -212,5 +219,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_tm(
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
ret->common.do_drop = do_drop;
return (nr_rlc_entity_t *)ret;
}

View File

@@ -23,6 +23,7 @@
#define _NR_RLC_ENTITY_H_
#include <stdint.h>
#include <stdbool.h>
#include "common/utils/time_stat.h"
@@ -144,6 +145,8 @@ typedef struct nr_rlc_entity_t {
nr_rlc_statistics_t stats;
time_average_t *txsdu_avg_time_to_tx;
int avg_time_is_on;
bool do_drop;
} nr_rlc_entity_t;
nr_rlc_entity_t *new_nr_rlc_entity_am(
@@ -165,7 +168,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
int poll_pdu,
int poll_byte,
int max_retx_threshold,
int sn_field_length);
int sn_field_length,
bool do_drop);
nr_rlc_entity_t *new_nr_rlc_entity_um(
int rx_maxsize,
@@ -174,12 +178,14 @@ nr_rlc_entity_t *new_nr_rlc_entity_um(
char *buf, int size),
void *deliver_sdu_data,
int t_reassembly,
int sn_field_length);
int sn_field_length,
bool do_drop);
nr_rlc_entity_t *new_nr_rlc_entity_tm(
int tx_maxsize,
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
char *buf, int size),
void *deliver_sdu_data);
void *deliver_sdu_data,
bool do_drop);
#endif /* _NR_RLC_ENTITY_H_ */

View File

@@ -1699,13 +1699,26 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
entity->t_log_buffer_full = entity->t_current;
}
if (entity->tx_size + size > entity->tx_maxsize) {
if (entity->common.do_drop && entity->tx_size + size > entity->tx_maxsize) {
entity->sdu_rejected++;
return;
}
entity->tx_size += size;
/* warn about excessive memory usage every tx_maxsize MB
* (might happen when RLC doesn't drop packets but PDCP does)
*/
if (entity->tx_size > entity->tx_last_warning_size &&
entity->tx_size - entity->tx_last_warning_size > entity->tx_maxsize) {
entity->tx_last_warning_size += entity->tx_maxsize;
LOG_W(RLC, "TX list memory usage is over %dMB\n",
entity->tx_last_warning_size / 1000000);
} else if (entity->tx_size < entity->tx_last_warning_size &&
entity->tx_last_warning_size - entity->tx_size > entity->tx_maxsize) {
entity->tx_last_warning_size = (entity->tx_size / entity->tx_maxsize) * entity->tx_maxsize;
}
sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
LOG_D(RLC, "Created new RLC SDU and append it to the RLC list \n");
@@ -1966,5 +1979,5 @@ void nr_rlc_entity_am_delete(nr_rlc_entity_t *_entity)
int nr_rlc_entity_am_available_tx_space(nr_rlc_entity_t *_entity)
{
nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
return entity->tx_maxsize - entity->tx_size;
return entity->tx_size > entity->tx_maxsize ? 0 : entity->tx_maxsize - entity->tx_size;
}

View File

@@ -79,6 +79,7 @@ typedef struct {
nr_rlc_sdu_segment_t *tx_end;
int tx_size;
int tx_maxsize;
int tx_last_warning_size;
nr_rlc_sdu_segment_t *wait_list;
nr_rlc_sdu_segment_t *wait_end;

View File

@@ -136,7 +136,7 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity,
exit(1);
}
if (entity->tx_size + size > entity->tx_maxsize) {
if (entity->common.do_drop && entity->tx_size + size > entity->tx_maxsize) {
LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
__FILE__, __LINE__, __FUNCTION__);
@@ -148,6 +148,19 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity,
entity->tx_size += size;
/* warn about excessive memory usage every tx_maxsize MB
* (might happen when RLC doesn't drop packets but PDCP does)
*/
if (entity->tx_size > entity->tx_last_warning_size &&
entity->tx_size - entity->tx_last_warning_size > entity->tx_maxsize) {
entity->tx_last_warning_size += entity->tx_maxsize;
LOG_W(RLC, "TX list memory usage is over %dMB\n",
entity->tx_last_warning_size / 1000000);
} else if (entity->tx_size < entity->tx_last_warning_size &&
entity->tx_last_warning_size - entity->tx_size > entity->tx_maxsize) {
entity->tx_last_warning_size = (entity->tx_size / entity->tx_maxsize) * entity->tx_maxsize;
}
sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
@@ -207,5 +220,5 @@ void nr_rlc_entity_tm_delete(nr_rlc_entity_t *_entity)
int nr_rlc_entity_tm_available_tx_space(nr_rlc_entity_t *_entity)
{
nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
return entity->tx_maxsize - entity->tx_size;
return entity->tx_size > entity->tx_maxsize ? 0 : entity->tx_maxsize - entity->tx_size;
}

View File

@@ -36,6 +36,7 @@ typedef struct {
nr_rlc_sdu_segment_t *tx_end;
int tx_size;
int tx_maxsize;
int tx_last_warning_size;
} nr_rlc_entity_tm_t;
void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *entity,

View File

@@ -575,7 +575,7 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
exit(1);
}
if (entity->tx_size + size > entity->tx_maxsize) {
if (entity->common.do_drop && entity->tx_size + size > entity->tx_maxsize) {
LOG_W(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
__FILE__, __LINE__, __FUNCTION__);
@@ -587,6 +587,19 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
entity->tx_size += size;
/* warn about excessive memory usage every tx_maxsize MB
* (might happen when RLC doesn't drop packets but PDCP does)
*/
if (entity->tx_size > entity->tx_last_warning_size &&
entity->tx_size - entity->tx_last_warning_size > entity->tx_maxsize) {
entity->tx_last_warning_size += entity->tx_maxsize;
LOG_W(RLC, "TX list memory usage is over %dMB\n",
entity->tx_last_warning_size / 1000000);
} else if (entity->tx_size < entity->tx_last_warning_size &&
entity->tx_last_warning_size - entity->tx_size > entity->tx_maxsize) {
entity->tx_last_warning_size = (entity->tx_size / entity->tx_maxsize) * entity->tx_maxsize;
}
sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
@@ -754,5 +767,5 @@ void nr_rlc_entity_um_delete(nr_rlc_entity_t *_entity)
int nr_rlc_entity_um_available_tx_space(nr_rlc_entity_t *_entity)
{
nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
return entity->tx_maxsize - entity->tx_size;
return entity->tx_size > entity->tx_maxsize ? 0 : entity->tx_maxsize - entity->tx_size;
}

View File

@@ -60,6 +60,7 @@ typedef struct {
nr_rlc_sdu_segment_t *tx_end;
int tx_size;
int tx_maxsize;
int tx_last_warning_size;
} nr_rlc_entity_um_t;
void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *entity,

View File

@@ -697,7 +697,9 @@ void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_Beare
t_poll_retransmit,
t_reassembly, t_status_prohibit,
poll_pdu, poll_byte, max_retx_threshold,
sn_field_length);
sn_field_length,
/* we drop in RLC if we don't drop in PDCP */
!get_softmodem_params()->pdcp_drop);
nr_rlc_ue_add_srb_rlc_entity(ue, srb_id, nr_rlc_am);
LOG_I(RLC, "%s:%d:%s: added srb %d to UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
@@ -778,7 +780,9 @@ static void add_drb_am(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Be
t_poll_retransmit,
t_reassembly, t_status_prohibit,
poll_pdu, poll_byte, max_retx_threshold,
sn_field_length);
sn_field_length,
/* we drop in RLC if we don't drop in PDCP */
!get_softmodem_params()->pdcp_drop);
nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_am);
LOG_I(RLC, "%s:%d:%s: added drb %d to UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
@@ -845,7 +849,9 @@ static void add_drb_um(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Be
RLC_TX_MAXSIZE,
deliver_sdu, ue,
t_reassembly,
sn_field_length);
sn_field_length,
/* we drop in RLC if we don't drop in PDCP */
!get_softmodem_params()->pdcp_drop);
nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_um);
LOG_D(RLC, "%s:%d:%s: added drb %d to UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
@@ -931,7 +937,9 @@ void nr_rlc_activate_srb0(int rnti, struct gNB_MAC_INST_s *mac, void *rawUE,
}
nr_rlc_tm = new_nr_rlc_entity_tm(10000,
deliver_sdu_srb0, srb0_data);
deliver_sdu_srb0, srb0_data,
/* we drop in RLC if we don't drop in PDCP */
!get_softmodem_params()->pdcp_drop);
nr_rlc_ue_add_srb_rlc_entity(ue, 0, nr_rlc_tm);
LOG_I(RLC, "activated srb0 for UE with RNTI 0x%x\n", rnti);

View File

@@ -1,32 +0,0 @@
#include "nr_rlc_entity.h"
#include <stdio.h>
int main(void)
{
char out[32768];
nr_rlc_entity_t *am;
int sdu_id = 0;
int size;
int i;
am = new_nr_rlc_entity_am(100000, 100000,
0, 0,
0, 0,
0, 0,
45, 35, 0,
-1, -1, 8,
12);
char data[8] = { 1, 2, 3, 4, 8, 7, 6, 5 };
am->recv_sdu(am, data, sizeof(data), sdu_id++);
size = am->generate_pdu(am, out, 32768);
printf("generate_pdu[%d]:", size);
for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)out[i]);
printf("\n");
return 0;
}

View File

@@ -262,7 +262,8 @@ int test_main(void)
max_retx_reached_gnb, NULL,
test[pos+3], test[pos+4], test[pos+5],
test[pos+6], test[pos+7], test[pos+8],
test[pos+9]);
test[pos+9],
true);
pos += 10;
break;
case UE_AM:
@@ -272,27 +273,30 @@ int test_main(void)
max_retx_reached_ue, NULL,
test[pos+3], test[pos+4], test[pos+5],
test[pos+6], test[pos+7], test[pos+8],
test[pos+9]);
test[pos+9],
true);
pos += 10;
break;
case GNB_UM:
gnb = new_nr_rlc_entity_um(test[pos+1], test[pos+2],
deliver_sdu_gnb_um, NULL,
test[pos+3], test[pos+4]);
test[pos+3], test[pos+4],
true);
pos += 5;
break;
case UE_UM:
ue = new_nr_rlc_entity_um(test[pos+1], test[pos+2],
deliver_sdu_ue_um, NULL,
test[pos+3], test[pos+4]);
test[pos+3], test[pos+4],
true);
pos += 5;
break;
case GNB_TM:
gnb = new_nr_rlc_entity_tm(test[pos+1], deliver_sdu_gnb_tm, NULL);
gnb = new_nr_rlc_entity_tm(test[pos+1], deliver_sdu_gnb_tm, NULL, true);
pos += 2;
break;
case UE_TM:
ue = new_nr_rlc_entity_tm(test[pos+1], deliver_sdu_ue_tm, NULL);
ue = new_nr_rlc_entity_tm(test[pos+1], deliver_sdu_ue_tm, NULL, true);
pos += 2;
break;
case GNB_SDU:

View File

@@ -189,6 +189,17 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
// the code is very badly organized, it is not possible here to call freeDRBlist()
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList,DRB_configList );
if (NODE_IS_MONOLITHIC(RC.nrrrc[ctxt.module_id]->node_type)) {
for (int i = 0; i < MAX_DRBS_PER_UE; i++) {
if (UE->established_drbs[i].status != DRB_INACTIVE) {
int rlc_rnti = UE->rnti;
int drb_id = UE->established_drbs[i].drb_id;
int rlc_channel_id = drb_id + 3;
nr_pdcp_set_rlc_ids(UE->rnti, false, drb_id, rlc_rnti, rlc_channel_id);
}
}
}
// Used to store teids: if monolithic, will simply be NULL
if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) {
// intentionally empty

View File

@@ -1680,6 +1680,14 @@ int32_t nr_rrc_ue_establish_drb(module_id_t ue_mod_idP,
kUPenc,
kUPint,
ue_rrc->cell_group_config->rlc_BearerToAddModList);
for (int i = 0; i < radioBearerConfig->drb_ToAddModList->list.count; i++) {
NR_DRB_ToAddMod_t *drb = radioBearerConfig->drb_ToAddModList->list.array[i];
int rlc_rnti = ctxt_pP->rntiMaybeUEid;
int rlc_channel_id = drb->drb_Identity + 3;
nr_pdcp_set_rlc_ids(ctxt_pP->rntiMaybeUEid, false, drb->drb_Identity, rlc_rnti, rlc_channel_id);
}
// Refresh DRBs
nr_rrc_addmod_drbs(ctxt_pP->rntiMaybeUEid,
radioBearerConfig->drb_ToAddModList,