pdcp,rlc: refactor SDU queueing policy

this patch refactors the SDU queuing and dropping policy of the RLC and PDCP layer.
the previous design had issues when packets have been generated at a higher
rate above the PDCP than they could be consumed below the RLC.

When the RLC SDU queues were full, we allowed two policies, one to block on the write
and the other to drop the SDU. Both options are not ideal because they either
lead to a blocking stack thread or to lost PDCP PDUs.

To avoid this, this patch makes the following changes:

* PDCP monitors RLC's SDU queue and drops packets on its north-bound SAP if queues are full
  * a new method sdu_queue_is_full() has been added to the RLC interface for PDCP
* remove blocking write from pdcp and rlc write_sdu() interface
  * all writes into queues need to be non-blocking
  * if Tx queues are overflowing, SDUs are dropped above PDCP, not RLC
* log warning if RLC still needs to drop SDUs
  * this case should be avoided with the monitoring mechanism
master
Andre Puschmann 5 years ago
parent 7a66a00e15
commit a7911f0dab

@ -341,6 +341,7 @@ public:
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void discard_sdu(uint16_t rnti, uint32_t lcid, uint32_t sn) = 0;
virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0;
virtual bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid) = 0;
};
// RLC interface for RRC

@ -69,6 +69,7 @@ public:
* RLC PDUs according to TB size. */
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0;
virtual bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid) = 0;
};
class rlc_interface_rrc_nr
{

@ -233,7 +233,7 @@ public:
virtual void reestablish() = 0;
virtual void reestablish(uint32_t lcid) = 0;
virtual void reset() = 0;
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) = 0;
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void add_bearer(uint32_t lcid, srslte::pdcp_config_t cnfg) = 0;
virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0;
virtual void config_security(uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0;
@ -258,7 +258,7 @@ public:
class pdcp_interface_gw
{
public:
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) = 0;
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual bool is_lcid_enabled(uint32_t lcid) = 0;
};
@ -278,18 +278,25 @@ public:
virtual bool has_bearer(uint32_t lcid) = 0;
virtual bool has_data(const uint32_t lcid) = 0;
virtual bool is_suspended(const uint32_t lcid) = 0;
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true) = 0;
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
};
// RLC interface for PDCP
class rlc_interface_pdcp
{
public:
/* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls
* RLC PDUs according to TB size. */
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true) = 0;
///< PDCP calls RLC to push an RLC SDU. SDU gets placed into the buffer
///< MAC pulls RLC PDUs according to TB size
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
///< Indicate RLC that a certain SN can be discarded
virtual void discard_sdu(uint32_t lcid, uint32_t discard_sn) = 0;
///< Helper to query RLC mode
virtual bool rb_is_um(uint32_t lcid) = 0;
///< Allow PDCP to query SDU queue status
virtual bool sdu_queue_is_full(uint32_t lcid) = 0;
};
// RLC interface for MAC

@ -45,7 +45,7 @@ public:
void reestablish() override;
void reestablish(uint32_t lcid) override;
void reset() override;
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking) override;
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu) override;
void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu);
void add_bearer(uint32_t lcid, pdcp_config_t cnfg) override;
void add_bearer_mrb(uint32_t lcid, pdcp_config_t cnfg);

@ -115,7 +115,7 @@ public:
void config_security(as_security_config_t sec_cfg_);
// GW/SDAP/RRC interface
virtual void write_sdu(unique_byte_buffer_t sdu, bool blocking) = 0;
virtual void write_sdu(unique_byte_buffer_t sdu) = 0;
// RLC interface
virtual void write_pdu(unique_byte_buffer_t pdu) = 0;

@ -58,7 +58,7 @@ public:
void reestablish() override;
// GW/RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking) override;
void write_sdu(unique_byte_buffer_t sdu) override;
// RLC interface
void write_pdu(unique_byte_buffer_t pdu) override;

@ -54,7 +54,7 @@ public:
void reestablish() final;
// RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking) final;
void write_sdu(unique_byte_buffer_t sdu) final;
// RLC interface
void write_pdu(unique_byte_buffer_t pdu) final;

@ -56,10 +56,11 @@ public:
void get_metrics(rlc_metrics_t& m);
// PDCP interface
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true);
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu);
void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu);
bool rb_is_um(uint32_t lcid);
void discard_sdu(uint32_t lcid, uint32_t discard_sn);
bool sdu_queue_is_full(uint32_t lcid);
// MAC interface
bool has_data(const uint32_t lcid);

@ -79,8 +79,9 @@ public:
uint32_t get_bearer();
// PDCP interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking = true);
void write_sdu(unique_byte_buffer_t sdu);
void discard_sdu(uint32_t pdcp_sn);
bool sdu_queue_is_full();
// MAC interface
bool has_data();
@ -107,9 +108,10 @@ private:
void reestablish();
void stop();
int write_sdu(unique_byte_buffer_t sdu, bool blocking);
int write_sdu(unique_byte_buffer_t sdu);
int read_pdu(uint8_t* payload, uint32_t nof_bytes);
void discard_sdu(uint32_t discard_sn);
bool sdu_queue_is_full();
bool has_data();
uint32_t get_buffer_state();

@ -237,7 +237,7 @@ public:
unique_byte_buffer_t s;
while (tx_sdu_resume_queue.try_pop(&s)) {
write_sdu(std::move(s), false);
write_sdu(std::move(s));
}
suspended = false;
return true;
@ -252,12 +252,12 @@ public:
}
}
void write_sdu_s(unique_byte_buffer_t sdu, bool blocking)
void write_sdu_s(unique_byte_buffer_t sdu)
{
if (suspended) {
queue_tx_sdu(std::move(sdu));
} else {
write_sdu(std::move(sdu), blocking);
write_sdu(std::move(sdu));
}
}
@ -268,8 +268,9 @@ public:
virtual void reset_metrics() = 0;
// PDCP interface
virtual void write_sdu(unique_byte_buffer_t sdu, bool blocking) = 0;
virtual void write_sdu(unique_byte_buffer_t sdu) = 0;
virtual void discard_sdu(uint32_t discard_sn) = 0;
virtual bool sdu_queue_is_full() = 0;
// MAC interface
virtual bool has_data() = 0;

@ -53,8 +53,9 @@ public:
void reset_metrics() override;
// PDCP interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking) override;
void write_sdu(unique_byte_buffer_t sdu) override;
void discard_sdu(uint32_t discard_sn) override;
bool sdu_queue_is_full() override;
// MAC interface
bool has_data() override;

@ -86,6 +86,8 @@ public:
bool is_empty() { return queue.empty(); }
bool is_full() { return queue.full(); }
private:
block_queue<unique_byte_buffer_t> queue;
uint32_t unread_bytes;

@ -53,8 +53,9 @@ public:
uint32_t get_bearer();
// PDCP interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking = true);
void write_sdu(unique_byte_buffer_t sdu);
void discard_sdu(uint32_t discard_sn);
bool sdu_queue_is_full();
// MAC interface
bool has_data();
@ -82,6 +83,7 @@ protected:
void empty_queue();
void write_sdu(unique_byte_buffer_t sdu);
void discard_sdu(uint32_t discard_sn);
bool sdu_queue_is_full();
int try_write_sdu(unique_byte_buffer_t sdu);
void reset_metrics();
bool has_data();

@ -61,6 +61,7 @@ private:
bool configure(const rlc_config_t& cfg, std::string rb_name);
int build_data_pdu(unique_byte_buffer_t pdu, uint8_t* payload, uint32_t nof_bytes);
uint32_t get_buffer_state();
bool sdu_queue_is_full();
private:
void reset();

@ -83,10 +83,10 @@ bool pdcp::is_lcid_enabled(uint32_t lcid)
return valid_lcids_cached.count(lcid) > 0;
}
void pdcp::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking)
void pdcp::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu)
{
if (valid_lcid(lcid)) {
pdcp_array.at(lcid)->write_sdu(std::move(sdu), blocking);
pdcp_array.at(lcid)->write_sdu(std::move(sdu));
} else {
pdcp_log->warning("Writing sdu: lcid=%d. Deallocating sdu\n", lcid);
}
@ -95,7 +95,7 @@ void pdcp::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking)
void pdcp::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu)
{
if (valid_mch_lcid(lcid)) {
pdcp_array_mrb.at(lcid)->write_sdu(std::move(sdu), true);
pdcp_array_mrb.at(lcid)->write_sdu(std::move(sdu));
}
}

@ -104,8 +104,13 @@ void pdcp_entity_lte::reset()
}
// GW/RRC interface
void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking)
void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu)
{
if (rlc->sdu_queue_is_full(lcid)) {
log->info_hex(sdu->msg, sdu->N_bytes, "Dropping %s SDU due to full queue", rrc->get_rb_name(lcid).c_str());
return;
}
// Get COUNT to be used with this packet
uint32_t tx_count = COUNT(st.tx_hfn, st.next_pdcp_tx_sn);
@ -149,7 +154,7 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking)
st.next_pdcp_tx_sn = 0;
}
rlc->write_sdu(lcid, std::move(sdu), blocking);
rlc->write_sdu(lcid, std::move(sdu));
}
// RLC interface

@ -71,7 +71,7 @@ void pdcp_entity_nr::reset()
}
// SDAP/RRC interface
void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu, bool blocking)
void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu)
{
// Log SDU
log->info_hex(sdu->msg,
@ -120,7 +120,7 @@ void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu, bool blocking)
// Check if PDCP is associated with more than on RLC entity TODO
// Write to lower layers
rlc->write_sdu(lcid, std::move(sdu), blocking);
rlc->write_sdu(lcid, std::move(sdu));
}
// RLC interface

@ -185,7 +185,7 @@ void rlc::empty_queue()
PDCP interface
*******************************************************************************/
void rlc::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking)
void rlc::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu)
{
// TODO: rework build PDU logic to allow large SDUs (without concatenation)
if (sdu->N_bytes > RLC_MAX_SDU_SIZE) {
@ -194,7 +194,7 @@ void rlc::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking)
}
if (valid_lcid(lcid)) {
rlc_array.at(lcid)->write_sdu_s(std::move(sdu), blocking);
rlc_array.at(lcid)->write_sdu_s(std::move(sdu));
update_bsr(lcid);
} else {
rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid);
@ -204,7 +204,7 @@ void rlc::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking)
void rlc::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu)
{
if (valid_lcid_mrb(lcid)) {
rlc_array_mrb.at(lcid)->write_sdu(std::move(sdu), false); // write in non-blocking mode by default
rlc_array_mrb.at(lcid)->write_sdu(std::move(sdu));
update_bsr_mch(lcid);
} else {
rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid);
@ -234,6 +234,15 @@ void rlc::discard_sdu(uint32_t lcid, uint32_t discard_sn)
}
}
bool rlc::sdu_queue_is_full(uint32_t lcid)
{
if (valid_lcid(lcid)) {
return rlc_array.at(lcid)->sdu_queue_is_full();
}
rlc_log->warning("RLC LCID %d doesn't exist. Ignoring queue check\n", lcid);
return false;
}
/*******************************************************************************
MAC interface
*******************************************************************************/

@ -127,9 +127,9 @@ void rlc_am_lte::reset_metrics()
* PDCP interface
***************************************************************************/
void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking)
void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu)
{
if (tx.write_sdu(std::move(sdu), blocking) == SRSLTE_SUCCESS) {
if (tx.write_sdu(std::move(sdu)) == SRSLTE_SUCCESS) {
metrics.num_tx_sdus++;
}
}
@ -140,6 +140,11 @@ void rlc_am_lte::discard_sdu(uint32_t discard_sn)
metrics.num_lost_sdus++;
}
bool rlc_am_lte::sdu_queue_is_full()
{
return tx.sdu_queue_is_full();
}
/****************************************************************************
* MAC interface
***************************************************************************/
@ -353,7 +358,7 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
return n_bytes;
}
int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu, bool blocking)
int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
{
if (!tx_enabled) {
return SRSLTE_ERROR;
@ -364,13 +369,6 @@ int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu, bool blocking
return SRSLTE_ERROR;
}
if (blocking) {
// block on write to queue
log->info_hex(
sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)\n", RB_NAME, sdu->N_bytes, tx_sdu_queue.size());
tx_sdu_queue.write(std::move(sdu));
} else {
// non-blocking write
uint8_t* msg_ptr = sdu->msg;
uint32_t nof_bytes = sdu->N_bytes;
srslte::error_type<unique_byte_buffer_t> ret = tx_sdu_queue.try_write(std::move(sdu));
@ -379,15 +377,15 @@ int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu, bool blocking
msg_ptr, nof_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)\n", RB_NAME, nof_bytes, tx_sdu_queue.size());
} else {
// in case of fail, the try_write returns back the sdu
log->info_hex(ret.error()->msg,
log->warning_hex(ret.error()->msg,
ret.error()->N_bytes,
"[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)\n",
RB_NAME,
ret.error()->N_bytes,
tx_sdu_queue.size());
}
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
@ -399,6 +397,11 @@ void rlc_am_lte::rlc_am_lte_tx::discard_sdu(uint32_t discard_sn)
log->warning("Discard SDU not implemented yet\n");
}
bool rlc_am_lte::rlc_am_lte_tx::sdu_queue_is_full()
{
return tx_sdu_queue.is_full();
}
int rlc_am_lte::rlc_am_lte_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
{
pthread_mutex_lock(&mutex);

@ -82,21 +82,12 @@ uint32_t rlc_tm::get_bearer()
}
// PDCP interface
void rlc_tm::write_sdu(unique_byte_buffer_t sdu, bool blocking)
void rlc_tm::write_sdu(unique_byte_buffer_t sdu)
{
if (!tx_enabled) {
return;
}
if (sdu) {
if (blocking) {
log->info_hex(sdu->msg,
sdu->N_bytes,
"%s Tx SDU, queue size=%d, bytes=%d",
rrc->get_rb_name(lcid).c_str(),
ul_queue.size(),
ul_queue.size_bytes());
ul_queue.write(std::move(sdu));
} else {
if (sdu != nullptr) {
uint8_t* msg_ptr = sdu->msg;
uint32_t nof_bytes = sdu->N_bytes;
srslte::error_type<unique_byte_buffer_t> ret = ul_queue.try_write(std::move(sdu));
@ -108,14 +99,14 @@ void rlc_tm::write_sdu(unique_byte_buffer_t sdu, bool blocking)
ul_queue.size(),
ul_queue.size_bytes());
} else {
log->info_hex(ret.error()->msg,
log->warning_hex(ret.error()->msg,
ret.error()->N_bytes,
"[Dropped SDU] %s Tx SDU, queue size=%d, bytes=%d",
rrc->get_rb_name(lcid).c_str(),
ul_queue.size(),
ul_queue.size_bytes());
}
}
} else {
log->warning("NULL SDU pointer in write_sdu()\n");
}
@ -129,6 +120,11 @@ void rlc_tm::discard_sdu(uint32_t discard_sn)
log->warning("SDU discard not implemented on RLC TM\n");
}
bool rlc_tm::sdu_queue_is_full()
{
return ul_queue.is_full();
}
// MAC interface
bool rlc_tm::has_data()
{

@ -91,7 +91,7 @@ void rlc_um_base::empty_queue()
/****************************************************************************
* PDCP interface
***************************************************************************/
void rlc_um_base::write_sdu(unique_byte_buffer_t sdu, bool blocking)
void rlc_um_base::write_sdu(unique_byte_buffer_t sdu)
{
if (not tx_enabled || not tx) {
log->debug("%s is currently deactivated. Dropping SDU (%d B)\n", rb_name.c_str(), sdu->N_bytes);
@ -99,16 +99,13 @@ void rlc_um_base::write_sdu(unique_byte_buffer_t sdu, bool blocking)
return;
}
if (blocking) {
int sdu_bytes = sdu->N_bytes; //< Store SDU length for book-keeping
if (tx->try_write_sdu(std::move(sdu)) == SRSLTE_SUCCESS) {
metrics.num_tx_sdus++;
metrics.num_tx_sdu_bytes += sdu->N_bytes;
tx->write_sdu(std::move(sdu));
metrics.num_tx_sdu_bytes += sdu_bytes;
} else {
if (tx->try_write_sdu(std::move(sdu)) != SRSLTE_SUCCESS) {
metrics.num_lost_sdus++;
}
}
}
void rlc_um_base::discard_sdu(uint32_t discard_sn)
@ -120,6 +117,12 @@ void rlc_um_base::discard_sdu(uint32_t discard_sn)
tx->discard_sdu(discard_sn);
metrics.num_lost_sdus++;
}
bool rlc_um_base::sdu_queue_is_full()
{
return tx->sdu_queue_is_full();
}
/****************************************************************************
* MAC interface
***************************************************************************/
@ -268,7 +271,7 @@ int rlc_um_base::rlc_um_base_tx::try_write_sdu(unique_byte_buffer_t sdu)
msg_ptr, nof_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rb_name.c_str(), nof_bytes, tx_sdu_queue.size());
return SRSLTE_SUCCESS;
} else {
log->info_hex(ret.error()->msg,
log->warning_hex(ret.error()->msg,
ret.error()->N_bytes,
"[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)",
rb_name.c_str(),
@ -286,6 +289,11 @@ void rlc_um_base::rlc_um_base_tx::discard_sdu(uint32_t discard_sn)
log->warning("RLC UM: Discard SDU not implemented yet.\n");
}
bool rlc_um_base::rlc_um_base_tx::sdu_queue_is_full()
{
return tx_sdu_queue.is_full();
}
int rlc_um_base::rlc_um_base_tx::build_data_pdu(uint8_t* payload, uint32_t nof_bytes)
{
unique_byte_buffer_t pdu;

@ -51,7 +51,7 @@ public:
pdu->N_bytes = last_pdcp_pdu->N_bytes;
return;
}
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = true)
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
log->info_hex(sdu->msg, sdu->N_bytes, "RLC SDU");
last_pdcp_pdu.swap(sdu);
@ -72,6 +72,7 @@ private:
srslte::unique_byte_buffer_t last_pdcp_pdu;
bool rb_is_um(uint32_t lcid) { return false; }
bool sdu_queue_is_full(uint32_t lcid) { return false; };
};
class rrc_dummy : public srsue::rrc_interface_pdcp

@ -116,7 +116,7 @@ srslte::unique_byte_buffer_t gen_expected_pdu(const srslte::unique_byte_buffer_t
srslte::unique_byte_buffer_t sdu = srslte::allocate_unique_buffer(*pool);
*sdu = *in_sdu;
pdcp->write_sdu(std::move(sdu), true);
pdcp->write_sdu(std::move(sdu));
srslte::unique_byte_buffer_t out_pdu = srslte::allocate_unique_buffer(*pool);
rlc->get_last_sdu(out_pdu);
@ -128,14 +128,14 @@ std::vector<pdcp_test_event_t> gen_expected_pdus_vector(const srslte::unique_byt
const std::vector<uint32_t>& tx_nexts,
uint8_t pdcp_sn_len,
srslte::pdcp_rb_type_t rb_type,
srslte::as_security_config_t sec_cfg,
srslte::as_security_config_t sec_cfg_,
srslte::byte_buffer_pool* pool,
srslte::log_ref log)
{
std::vector<pdcp_test_event_t> pdu_vec;
for (uint32_t tx_next : tx_nexts) {
pdcp_test_event_t event;
event.pkt = gen_expected_pdu(in_sdu, tx_next, pdcp_sn_len, rb_type, sec_cfg, pool, log);
event.pkt = gen_expected_pdu(in_sdu, tx_next, pdcp_sn_len, rb_type, sec_cfg_, pool, log);
event.ticks = 0;
pdu_vec.push_back(std::move(event));
}

@ -148,7 +148,7 @@ srslte::unique_byte_buffer_t gen_expected_pdu(const srslte::unique_byte_buffer_t
srslte::unique_byte_buffer_t sdu = srslte::allocate_unique_buffer(*pool);
*sdu = *in_sdu;
pdcp->write_sdu(std::move(sdu), true);
pdcp->write_sdu(std::move(sdu));
srslte::unique_byte_buffer_t out_pdu = srslte::allocate_unique_buffer(*pool);
rlc->get_last_sdu(out_pdu);
@ -159,14 +159,14 @@ srslte::unique_byte_buffer_t gen_expected_pdu(const srslte::unique_byte_buffer_t
std::vector<pdcp_test_event_t> gen_expected_pdus_vector(const srslte::unique_byte_buffer_t& in_sdu,
const std::vector<uint32_t>& tx_nexts,
uint8_t pdcp_sn_len,
srslte::as_security_config_t sec_cfg,
srslte::as_security_config_t sec_cfg_,
srslte::byte_buffer_pool* pool,
srslte::log_ref log)
{
std::vector<pdcp_test_event_t> pdu_vec;
for (uint32_t tx_next : tx_nexts) {
pdcp_test_event_t event;
event.pkt = gen_expected_pdu(in_sdu, tx_next, pdcp_sn_len, sec_cfg, pool, log);
event.pkt = gen_expected_pdu(in_sdu, tx_next, pdcp_sn_len, sec_cfg_, pool, log);
event.ticks = 0;
pdu_vec.push_back(std::move(event));
}

@ -48,7 +48,7 @@ int test_tx_sdu_discard(const pdcp_initial_state& init_state,
// Test SDU
srslte::unique_byte_buffer_t sdu = allocate_unique_buffer(*pool);
sdu->append_bytes(sdu1, sizeof(sdu1));
pdcp->write_sdu(std::move(sdu), true);
pdcp->write_sdu(std::move(sdu));
for (uint32_t i = 0; i < static_cast<uint32_t>(cfg.discard_timer) - 1; ++i) {
stack->run_tti();

@ -51,7 +51,7 @@ int test_tx(uint32_t n_packets,
// Test SDU
srslte::unique_byte_buffer_t sdu = allocate_unique_buffer(*pool);
sdu->append_bytes(sdu1, sizeof(sdu1));
pdcp->write_sdu(std::move(sdu), true);
pdcp->write_sdu(std::move(sdu));
}
srslte::unique_byte_buffer_t pdu_act = allocate_unique_buffer(*pool);

@ -70,7 +70,7 @@ public:
int rx_data_indication(rx_data_ind_t& grant);
// Temporary GW interface
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking);
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu);
bool is_lcid_enabled(uint32_t lcid);
bool switch_on();
void run_tti(uint32_t tti);

@ -62,9 +62,10 @@ private:
uint16_t rnti;
srsenb::rlc_interface_pdcp* rlc;
// rlc_interface_pdcp
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking);
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu);
void discard_sdu(uint32_t lcid, uint32_t discard_sn);
bool rb_is_um(uint32_t lcid);
bool sdu_queue_is_full(uint32_t lcid);
};
class user_interface_gtpu : public srsue::gw_interface_pdcp

@ -68,9 +68,10 @@ private:
uint16_t rnti;
srsenb::rlc_interface_pdcp_nr* rlc;
// rlc_interface_pdcp_nr
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) final;
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) final;
void discard_sdu(uint32_t lcid, uint32_t discard_sn) final;
bool rb_is_um(uint32_t lcid) final;
bool sdu_queue_is_full(uint32_t lcid) final;
};
class user_interface_sdap : public srsue::gw_interface_pdcp

@ -63,6 +63,7 @@ public:
void discard_sdu(uint16_t rnti, uint32_t lcid, uint32_t discard_sn);
bool rb_is_um(uint16_t rnti, uint32_t lcid);
std::string get_rb_name(uint32_t lcid);
bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid);
// rlc_interface_mac
int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes);

@ -58,6 +58,7 @@ public:
// rlc_interface_pdcp_nr
void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu);
bool rb_is_um(uint16_t rnti, uint32_t lcid);
bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid);
std::string get_rb_name(uint32_t lcid);
// rlc_interface_mac_nr

@ -182,7 +182,7 @@ int gnb_stack_nr::rx_data_indication(rx_data_ind_t& grant)
}
// Temporary GW interface
void gnb_stack_nr::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking)
void gnb_stack_nr::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
m_pdcp->write_sdu(args.coreless.rnti, lcid, std::move(sdu));
}

@ -146,8 +146,7 @@ void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t
{
if (users.count(rnti)) {
if (rnti != SRSLTE_MRNTI) {
// TODO: expose blocking mode as function param
users[rnti].pdcp->write_sdu(lcid, std::move(sdu), false);
users[rnti].pdcp->write_sdu(lcid, std::move(sdu));
} else {
users[rnti].pdcp->write_sdu_mch(lcid, std::move(sdu));
}
@ -159,7 +158,7 @@ void pdcp::user_interface_gtpu::write_pdu(uint32_t lcid, srslte::unique_byte_buf
gtpu->write_pdu(rnti, lcid, std::move(pdu));
}
void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking)
void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
rlc->write_sdu(rnti, lcid, std::move(sdu));
}
@ -174,6 +173,11 @@ bool pdcp::user_interface_rlc::rb_is_um(uint32_t lcid)
return rlc->rb_is_um(rnti, lcid);
}
bool pdcp::user_interface_rlc::sdu_queue_is_full(uint32_t lcid)
{
return rlc->sdu_queue_is_full(rnti, lcid);
}
void pdcp::user_interface_rrc::write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu)
{
rrc->write_pdu(rnti, lcid, std::move(pdu));

@ -114,7 +114,7 @@ void pdcp_nr::write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer
void pdcp_nr::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
if (users.count(rnti)) {
users[rnti].pdcp->write_sdu(lcid, std::move(sdu), false);
users[rnti].pdcp->write_sdu(lcid, std::move(sdu));
} else {
m_log->error("Can't write SDU. RNTI=0x%X doesn't exist.\n", rnti);
}
@ -125,7 +125,7 @@ void pdcp_nr::user_interface_sdap::write_pdu(uint32_t lcid, srslte::unique_byte_
sdap->write_pdu(rnti, lcid, std::move(pdu));
}
void pdcp_nr::user_interface_rlc::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking)
void pdcp_nr::user_interface_rlc::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
rlc->write_sdu(rnti, lcid, std::move(sdu));
}
@ -140,6 +140,11 @@ bool pdcp_nr::user_interface_rlc::rb_is_um(uint32_t lcid)
return rlc->rb_is_um(rnti, lcid);
}
bool pdcp_nr::user_interface_rlc::sdu_queue_is_full(uint32_t lcid)
{
return rlc->sdu_queue_is_full(rnti, lcid);
}
void pdcp_nr::user_interface_rrc::write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu)
{
rrc->write_pdu(rnti, lcid, std::move(pdu));

@ -214,7 +214,7 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t s
pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti)) {
if (rnti != SRSLTE_MRNTI) {
users[rnti].rlc->write_sdu(lcid, std::move(sdu), false);
users[rnti].rlc->write_sdu(lcid, std::move(sdu));
} else {
users[rnti].rlc->write_sdu_mch(lcid, std::move(sdu));
}
@ -242,6 +242,17 @@ bool rlc::rb_is_um(uint16_t rnti, uint32_t lcid)
return ret;
}
bool rlc::sdu_queue_is_full(uint16_t rnti, uint32_t lcid)
{
bool ret = false;
pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti)) {
ret = users[rnti].rlc->sdu_queue_is_full(lcid);
}
pthread_rwlock_unlock(&rwlock);
return ret;
}
void rlc::user_interface::max_retx_attempted()
{
rrc->max_retx_attempted(rnti);

@ -150,7 +150,7 @@ void rlc_nr::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_
if (users.count(rnti)) {
if (rnti != SRSLTE_MRNTI) {
users[rnti].m_rlc->write_sdu(lcid, std::move(sdu), false);
users[rnti].m_rlc->write_sdu(lcid, std::move(sdu));
tx_queue = users[rnti].m_rlc->get_buffer_state(lcid);
} else {
users[rnti].m_rlc->write_sdu_mch(lcid, std::move(sdu));
@ -174,6 +174,14 @@ bool rlc_nr::rb_is_um(uint16_t rnti, uint32_t lcid)
return ret;
}
bool rlc_nr::sdu_queue_is_full(uint16_t rnti, uint32_t lcid)
{
bool ret = false;
if (users.count(rnti)) {
ret = users[rnti].m_rlc->sdu_queue_is_full(lcid);
}
return ret;
}
void rlc_nr::user_interface::max_retx_attempted()
{
m_rrc->max_retx_attempted(rnti);

@ -116,7 +116,7 @@ public:
void run_tti(uint32_t tti, uint32_t tti_jump) final;
// Interface for GW
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) final;
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) final;
bool is_lcid_enabled(uint32_t lcid) final { return pdcp.is_lcid_enabled(lcid); }

@ -88,7 +88,7 @@ public:
void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant) final { mac->new_grant_ul(cc_idx, grant); }
// Interface for GW
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) final;
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) final;
bool is_lcid_enabled(uint32_t lcid) final { return pdcp->is_lcid_enabled(lcid); }
// Interface for RRC

@ -1443,7 +1443,7 @@ void rrc::send_ul_dcch_msg(uint32_t lcid, const ul_dcch_msg_s& msg)
log_rrc_message(get_rb_name(lcid).c_str(), Tx, pdcp_buf.get(), msg, msg.msg.c1().type().to_string());
pdcp->write_sdu(lcid, std::move(pdcp_buf), true);
pdcp->write_sdu(lcid, std::move(pdcp_buf));
}
void rrc::write_sdu(srslte::unique_byte_buffer_t sdu)

@ -241,11 +241,9 @@ void ue_stack_lte::run_thread()
* @param sdu
* @param blocking
*/
void ue_stack_lte::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking)
void ue_stack_lte::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
auto task = [this, lcid, blocking](srslte::unique_byte_buffer_t& sdu) {
pdcp.write_sdu(lcid, std::move(sdu), blocking);
};
auto task = [this, lcid](srslte::unique_byte_buffer_t& sdu) { pdcp.write_sdu(lcid, std::move(sdu)); };
bool ret = gw_queue_id.try_push(std::bind(task, std::move(sdu))).first;
if (not ret) {
pdcp_log->warning("GW SDU with lcid=%d was discarded.\n", lcid);

@ -167,12 +167,11 @@ void ue_stack_nr::run_thread()
* @param sdu
* @param blocking
*/
void ue_stack_nr::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking)
void ue_stack_nr::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
if (pdcp != nullptr) {
std::pair<bool, move_task_t> ret = gw_task_queue.try_push(std::bind(
[this, lcid, blocking](srslte::unique_byte_buffer_t& sdu) { pdcp->write_sdu(lcid, std::move(sdu), blocking); },
std::move(sdu)));
[this, lcid](srslte::unique_byte_buffer_t& sdu) { pdcp->write_sdu(lcid, std::move(sdu)); }, std::move(sdu)));
if (not ret.first) {
pdcp_log->warning("GW SDU with lcid=%d was discarded.\n", lcid);
}

@ -278,7 +278,7 @@ void gw::run_thread()
if (stack->is_lcid_enabled(lcid)) {
pdu->set_timestamp();
ul_tput_bytes += pdu->N_bytes;
stack->write_sdu(lcid, std::move(pdu), false);
stack->write_sdu(lcid, std::move(pdu));
do {
pdu = srslte::allocate_unique_buffer(*pool);
if (!pdu) {

@ -177,12 +177,14 @@ public:
std::string get_rb_name(uint32_t lcid);
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking = true);
void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu);
void discard_sdu(uint32_t lcid, uint32_t sn);
bool rb_is_um(uint32_t lcid);
bool sdu_queue_is_full(uint32_t lcid);
void set_as_security(const ttcn3_helpers::timing_info_t timing,
std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_,

@ -902,7 +902,7 @@ void ttcn3_syssim::add_dcch_pdu_impl(uint32_t lcid, unique_byte_buffer_t pdu, bo
{
// push to PDCP and create DL grant for it
log->info("Writing PDU (%d B) to LCID=%d\n", pdu->N_bytes, lcid);
pdcp.write_sdu(lcid, std::move(pdu), true);
pdcp.write_sdu(lcid, std::move(pdu));
bearer_follow_on_map[lcid] = follow_on_flag;
}
@ -1063,12 +1063,11 @@ std::string ttcn3_syssim::get_rb_name(uint32_t lcid)
return std::string("RB");
};
void ttcn3_syssim::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking)
void ttcn3_syssim::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu)
{
log->info_hex(sdu->msg, sdu->N_bytes, "Received SDU on LCID=%d\n", lcid);
uint8_t* mac_pdu_ptr;
mac_pdu_ptr = mac_msg_dl.write_packet(log);
uint8_t* mac_pdu_ptr = mac_msg_dl.write_packet(log);
log->info_hex(mac_pdu_ptr, mac_msg_dl.get_pdu_len(), "DL MAC PDU:\n");
// Prepare MAC grant for CCCH
@ -1091,6 +1090,11 @@ bool ttcn3_syssim::rb_is_um(uint32_t lcid)
return false;
}
bool ttcn3_syssim::sdu_queue_is_full(uint32_t lcid)
{
return false;
}
void ttcn3_syssim::set_as_security(const ttcn3_helpers::timing_info_t timing,
std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_,

@ -253,5 +253,5 @@ void ttcn3_ue::send_queued_data()
void ttcn3_ue::loop_back_pdu_with_tft(uint32_t input_lcid, srslte::unique_byte_buffer_t pdu)
{
log.info_hex(pdu->msg, pdu->N_bytes, "Rx PDU (%d B) on lcid=%d, looping back\n", pdu->N_bytes, input_lcid);
stack->write_sdu(input_lcid, std::move(pdu), true);
stack->write_sdu(input_lcid, std::move(pdu));
}

@ -87,7 +87,7 @@ public:
void write_pdu_pcch(unique_byte_buffer_t pdu) {}
void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) {}
std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); }
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) {}
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) {}
bool is_lcid_enabled(uint32_t lcid) { return false; }
};
@ -159,10 +159,7 @@ public:
}
return proc_result.is_success();
}
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking)
{
pdcp->write_sdu(lcid, std::move(sdu), blocking);
}
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) { pdcp->write_sdu(lcid, std::move(sdu)); }
bool is_lcid_enabled(uint32_t lcid) { return pdcp->is_lcid_enabled(lcid); }
void run_thread()
{

@ -121,7 +121,7 @@ class pdcp_test : public srslte::pdcp
{
public:
pdcp_test(const char* logname, srslte::task_sched_handle t) : srslte::pdcp(t, logname) {}
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking = false) override
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) override
{
ul_dcch_msg_s ul_dcch_msg;
asn1::cbit_ref bref(sdu->msg, sdu->N_bytes);

Loading…
Cancel
Save