mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-20 16:10:29 +00:00
Compare commits
2 Commits
fr2_testin
...
nr-pdcp-dr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7ab1828d1 | ||
|
|
a63f1704fa |
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user