limit allocation of PDCP SDU+Timer buffer to DRB+RLC AM cases

master
Francisco 4 years ago committed by Francisco Paisana
parent 8dfa87c377
commit be7e78da53

@ -144,7 +144,7 @@ public:
pdcp_bearer_metrics_t get_metrics() override; pdcp_bearer_metrics_t get_metrics() override;
void reset_metrics() override; void reset_metrics() override;
size_t nof_discard_timers() const { return undelivered_sdus.nof_discard_timers(); } size_t nof_discard_timers() const { return undelivered_sdus != nullptr ? undelivered_sdus->nof_discard_timers() : 0; }
private: private:
srsue::rlc_interface_pdcp* rlc = nullptr; srsue::rlc_interface_pdcp* rlc = nullptr;
@ -168,7 +168,7 @@ private:
// TX Queue // TX Queue
uint32_t maximum_allocated_sns_window = 2048; uint32_t maximum_allocated_sns_window = 2048;
undelivered_sdus_queue undelivered_sdus; std::unique_ptr<undelivered_sdus_queue> undelivered_sdus;
}; };
// Discard callback (discardTimer) // Discard callback (discardTimer)

@ -30,7 +30,7 @@ pdcp_entity_lte::pdcp_entity_lte(srsue::rlc_interface_pdcp* rlc_,
srslog::basic_logger& logger, srslog::basic_logger& logger,
uint32_t lcid_, uint32_t lcid_,
pdcp_config_t cfg_) : pdcp_config_t cfg_) :
pdcp_entity_base(task_sched_, logger), rlc(rlc_), rrc(rrc_), gw(gw_), undelivered_sdus(task_sched_) pdcp_entity_base(task_sched_, logger), rlc(rlc_), rrc(rrc_), gw(gw_)
{ {
lcid = lcid_; lcid = lcid_;
cfg = cfg_; cfg = cfg_;
@ -49,7 +49,7 @@ pdcp_entity_lte::pdcp_entity_lte(srsue::rlc_interface_pdcp* rlc_,
st.tx_hfn = 0; st.tx_hfn = 0;
st.rx_hfn = 0; st.rx_hfn = 0;
st.next_pdcp_rx_sn = 0; st.next_pdcp_rx_sn = 0;
maximum_pdcp_sn = (1 << cfg.sn_len) - 1; maximum_pdcp_sn = (1u << cfg.sn_len) - 1u;
st.last_submitted_pdcp_rx_sn = maximum_pdcp_sn; st.last_submitted_pdcp_rx_sn = maximum_pdcp_sn;
if (is_drb() && not rlc->rb_is_um(lcid) && cfg.discard_timer == pdcp_discard_timer_t::infinity) { if (is_drb() && not rlc->rb_is_um(lcid) && cfg.discard_timer == pdcp_discard_timer_t::infinity) {
@ -60,7 +60,7 @@ pdcp_entity_lte::pdcp_entity_lte(srsue::rlc_interface_pdcp* rlc_,
} }
// Queue Helpers // Queue Helpers
maximum_allocated_sns_window = (1 << cfg.sn_len) / 2; maximum_allocated_sns_window = (1u << cfg.sn_len) / 2u;
logger.info("Init %s with bearer ID: %d", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id); logger.info("Init %s with bearer ID: %d", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id);
logger.info("SN len bits: %d, SN len bytes: %d, reordering window: %d, Maximum SN: %d, discard timer: %d ms", logger.info("SN len bits: %d, SN len bytes: %d, reordering window: %d, Maximum SN: %d, discard timer: %d ms",
@ -71,6 +71,10 @@ pdcp_entity_lte::pdcp_entity_lte(srsue::rlc_interface_pdcp* rlc_,
static_cast<uint32_t>(cfg.discard_timer)); static_cast<uint32_t>(cfg.discard_timer));
logger.info("Status Report Required: %s", cfg.status_report_required ? "True" : "False"); logger.info("Status Report Required: %s", cfg.status_report_required ? "True" : "False");
if (is_drb() and not rlc->rb_is_um(lcid)) {
undelivered_sdus = std::unique_ptr<undelivered_sdus_queue>(new undelivered_sdus_queue(task_sched));
}
// Check supported config // Check supported config
if (!check_valid_config()) { if (!check_valid_config()) {
srslte::console("Warning: Invalid PDCP config.\n"); srslte::console("Warning: Invalid PDCP config.\n");
@ -92,7 +96,6 @@ void pdcp_entity_lte::reestablish()
st.tx_hfn = 0; st.tx_hfn = 0;
st.rx_hfn = 0; st.rx_hfn = 0;
st.next_pdcp_rx_sn = 0; st.next_pdcp_rx_sn = 0;
undelivered_sdus.clear();
} else if (rlc->rb_is_um(lcid)) { } else if (rlc->rb_is_um(lcid)) {
// Only reset counter in RLC-UM // Only reset counter in RLC-UM
st.next_pdcp_tx_sn = 0; st.next_pdcp_tx_sn = 0;
@ -139,7 +142,7 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn)
if (!rlc->rb_is_um(lcid) and is_drb()) { if (!rlc->rb_is_um(lcid) and is_drb()) {
if (not store_sdu(used_sn, sdu)) { if (not store_sdu(used_sn, sdu)) {
// Could not store the SDU, discarding // Could not store the SDU, discarding
logger.error("Could not store SDU. Discarding %d\n", used_sn); logger.info("Could not store SDU. Discarding %d\n", used_sn);
return; return;
} }
} }
@ -425,14 +428,14 @@ void pdcp_entity_lte::send_status_report()
// Get First Missing Segment (FMS) // Get First Missing Segment (FMS)
uint32_t fms = 0; uint32_t fms = 0;
if (undelivered_sdus.empty()) { if (undelivered_sdus->empty()) {
fms = st.next_pdcp_tx_sn; fms = st.next_pdcp_tx_sn;
} else { } else {
fms = undelivered_sdus.get_fms(); fms = undelivered_sdus->get_fms();
} }
// Get Last Missing Segment // Get Last Missing Segment
uint32_t lms = undelivered_sdus.get_lms(); uint32_t lms = undelivered_sdus->get_lms();
// Allocate Status Report PDU // Allocate Status Report PDU
unique_byte_buffer_t pdu = make_byte_buffer(); unique_byte_buffer_t pdu = make_byte_buffer();
@ -464,7 +467,7 @@ void pdcp_entity_lte::send_status_report()
} }
// Add bitmap of missing PDUs, if necessary // Add bitmap of missing PDUs, if necessary
if (not undelivered_sdus.empty()) { if (not undelivered_sdus->empty()) {
// First check size of bitmap // First check size of bitmap
uint32_t bitmap_sz = std::ceil((float)(lms - (fms - 1)) / 8); uint32_t bitmap_sz = std::ceil((float)(lms - (fms - 1)) / 8);
memset(&pdu->msg[pdu->N_bytes], 0, bitmap_sz); memset(&pdu->msg[pdu->N_bytes], 0, bitmap_sz);
@ -474,7 +477,7 @@ void pdcp_entity_lte::send_status_report()
fms - 1, fms - 1,
bitmap_sz); bitmap_sz);
for (uint32_t sn = fms; sn <= lms; sn++) { for (uint32_t sn = fms; sn <= lms; sn++) {
if (undelivered_sdus.has_sdu(sn)) { if (undelivered_sdus->has_sdu(sn)) {
uint32_t offset = sn - fms; uint32_t offset = sn - fms;
uint32_t bit_offset = offset % 8; uint32_t bit_offset = offset % 8;
uint32_t byte_offset = offset / 8; uint32_t byte_offset = offset / 8;
@ -520,8 +523,8 @@ void pdcp_entity_lte::handle_status_report_pdu(unique_byte_buffer_t pdu)
// Remove all SDUs with SN smaller than FMS // Remove all SDUs with SN smaller than FMS
for (uint32_t sn = 0; sn < fms; sn++) { for (uint32_t sn = 0; sn < fms; sn++) {
if (sn < fms && undelivered_sdus.has_sdu(sn)) { if (sn < fms && undelivered_sdus->has_sdu(sn)) {
undelivered_sdus.clear_sdu(sn); undelivered_sdus->clear_sdu(sn);
} }
} }
@ -539,7 +542,7 @@ void pdcp_entity_lte::handle_status_report_pdu(unique_byte_buffer_t pdu)
// Discard ACK'ed SDUs // Discard ACK'ed SDUs
for (uint32_t sn : acked_sns) { for (uint32_t sn : acked_sns) {
logger.debug("Status report ACKed SN=%d.", sn); logger.debug("Status report ACKed SN=%d.", sn);
undelivered_sdus.clear_sdu(sn); undelivered_sdus->clear_sdu(sn);
} }
} }
/**************************************************************************** /****************************************************************************
@ -548,22 +551,22 @@ void pdcp_entity_lte::handle_status_report_pdu(unique_byte_buffer_t pdu)
bool pdcp_entity_lte::store_sdu(uint32_t sn, const unique_byte_buffer_t& sdu) bool pdcp_entity_lte::store_sdu(uint32_t sn, const unique_byte_buffer_t& sdu)
{ {
logger.debug("Storing SDU in undelivered SDUs queue. SN=%d, Queue size=%ld", sn, undelivered_sdus.size()); logger.debug("Storing SDU in undelivered SDUs queue. SN=%d, Queue size=%ld", sn, undelivered_sdus->size());
// Check wether PDU is already in the queue // Check wether PDU is already in the queue
if (undelivered_sdus.has_sdu(sn)) { if (undelivered_sdus->has_sdu(sn)) {
logger.error("PDU already exists in the queue. TX_COUNT=%d", sn); logger.error("PDU already exists in the queue. TX_COUNT=%d", sn);
return false; return false;
} }
if (undelivered_sdus.is_full()) { if (undelivered_sdus->is_full()) {
logger.error("Undelivered SDUs queue is full. TX_COUNT=%d", sn); logger.error("Undelivered SDUs queue is full. TX_COUNT=%d", sn);
return false; return false;
} }
// Make sure we don't associate more than half of the PDCP SN space of contiguous PDCP SDUs // Make sure we don't associate more than half of the PDCP SN space of contiguous PDCP SDUs
if (not undelivered_sdus.empty()) { if (not undelivered_sdus->empty()) {
uint32_t fms_sn = undelivered_sdus.get_fms(); uint32_t fms_sn = undelivered_sdus->get_fms();
int32_t diff = sn - fms_sn; int32_t diff = sn - fms_sn;
if (diff > (int32_t)maximum_allocated_sns_window) { if (diff > (int32_t)maximum_allocated_sns_window) {
// This SN is too large to assign, it may cause HFN de-synchronization. // This SN is too large to assign, it may cause HFN de-synchronization.
@ -572,7 +575,7 @@ bool pdcp_entity_lte::store_sdu(uint32_t sn, const unique_byte_buffer_t& sdu)
fms_sn, fms_sn,
diff, diff,
maximum_allocated_sns_window, maximum_allocated_sns_window,
undelivered_sdus.size()); undelivered_sdus->size());
return false; return false;
} }
if (diff < 0 && diff > -((int32_t)maximum_allocated_sns_window)) { if (diff < 0 && diff > -((int32_t)maximum_allocated_sns_window)) {
@ -582,7 +585,7 @@ bool pdcp_entity_lte::store_sdu(uint32_t sn, const unique_byte_buffer_t& sdu)
fms_sn, fms_sn,
diff, diff,
maximum_allocated_sns_window, maximum_allocated_sns_window,
undelivered_sdus.size()); undelivered_sdus->size());
return false; return false;
} }
} }
@ -590,7 +593,7 @@ bool pdcp_entity_lte::store_sdu(uint32_t sn, const unique_byte_buffer_t& sdu)
// Copy PDU contents into queue and start discard timer // Copy PDU contents into queue and start discard timer
uint32_t discard_timeout = static_cast<uint32_t>(cfg.discard_timer); uint32_t discard_timeout = static_cast<uint32_t>(cfg.discard_timer);
discard_callback discard_fnc(this, sn); discard_callback discard_fnc(this, sn);
bool ret = undelivered_sdus.add_sdu(sn, sdu, discard_timeout, discard_fnc); bool ret = undelivered_sdus->add_sdu(sn, sdu, discard_timeout, discard_fnc);
if (ret and discard_timeout > 0) { if (ret and discard_timeout > 0) {
logger.debug("Discard Timer set for SN %u. Timeout: %ums", sn, discard_timeout); logger.debug("Discard Timer set for SN %u. Timeout: %ums", sn, discard_timeout);
} }
@ -609,9 +612,9 @@ void pdcp_entity_lte::discard_callback::operator()(uint32_t timer_id)
parent->rlc->discard_sdu(parent->lcid, discard_sn); parent->rlc->discard_sdu(parent->lcid, discard_sn);
// Discard PDU if unacknowledged // Discard PDU if unacknowledged
if (parent->undelivered_sdus.has_sdu(discard_sn)) { if (parent->undelivered_sdus->has_sdu(discard_sn)) {
parent->logger.debug("Removed undelivered PDU with TX_COUNT=%d", discard_sn); parent->logger.debug("Removed undelivered PDU with TX_COUNT=%d", discard_sn);
parent->undelivered_sdus.clear_sdu(discard_sn); parent->undelivered_sdus->clear_sdu(discard_sn);
} else { } else {
parent->logger.debug("Could not find PDU to discard. TX_COUNT=%d", discard_sn); parent->logger.debug("Could not find PDU to discard. TX_COUNT=%d", discard_sn);
} }
@ -633,18 +636,19 @@ void pdcp_entity_lte::notify_delivery(const std::vector<uint32_t>& pdcp_sns)
continue; continue;
} }
// Find undelivered PDU info // Find undelivered PDU info
if (not undelivered_sdus.has_sdu(sn)) { if (not undelivered_sdus->has_sdu(sn)) {
logger.warning("Could not find PDU for delivery notification. Notified SN=%d", sn); logger.warning("Could not find PDU for delivery notification. Notified SN=%d", sn);
} else { } else {
// Metrics // Metrics
auto& sdu = (*undelivered_sdus)[sn];
tx_pdu_ack_latency_ms.push(std::chrono::duration_cast<std::chrono::milliseconds>( tx_pdu_ack_latency_ms.push(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - undelivered_sdus[sn]->get_timestamp()) std::chrono::high_resolution_clock::now() - sdu->get_timestamp())
.count()); .count());
metrics.num_tx_acked_bytes += undelivered_sdus[sn]->N_bytes; metrics.num_tx_acked_bytes += sdu->N_bytes;
metrics.num_tx_buffered_pdus_bytes -= undelivered_sdus[sn]->N_bytes; metrics.num_tx_buffered_pdus_bytes -= sdu->N_bytes;
// Remove PDU and disarm timer. // Remove PDU and disarm timer.
undelivered_sdus.clear_sdu(sn); undelivered_sdus->clear_sdu(sn);
} }
} }
} }
@ -663,11 +667,11 @@ void pdcp_entity_lte::notify_failure(const std::vector<uint32_t>& pdcp_sns)
continue; continue;
} }
// Find undelivered PDU info // Find undelivered PDU info
if (not undelivered_sdus.has_sdu(sn)) { if (not undelivered_sdus->has_sdu(sn)) {
logger.info("Could not find PDU for failure notification. Notified SN=%d", sn); logger.info("Could not find PDU for failure notification. Notified SN=%d", sn);
} else { } else {
// Remove PDU and disarm timer. // Remove PDU and disarm timer.
undelivered_sdus.clear_sdu(sn); undelivered_sdus->clear_sdu(sn);
} }
} }
} }
@ -711,8 +715,12 @@ void pdcp_entity_lte::set_bearer_state(const pdcp_lte_state_t& state)
std::map<uint32_t, srslte::unique_byte_buffer_t> pdcp_entity_lte::get_buffered_pdus() std::map<uint32_t, srslte::unique_byte_buffer_t> pdcp_entity_lte::get_buffered_pdus()
{ {
logger.info("Buffered PDUs requested, buffer_size=%d", undelivered_sdus.size()); if (undelivered_sdus == nullptr) {
return undelivered_sdus.get_buffered_sdus(); logger.error("Buffered PDUs being requested for non-AM DRB");
return std::map<uint32_t, srslte::unique_byte_buffer_t>{};
}
logger.info("Buffered PDUs requested, buffer_size=%d", undelivered_sdus->size());
return undelivered_sdus->get_buffered_sdus();
} }
/**************************************************************************** /****************************************************************************
@ -720,8 +728,10 @@ std::map<uint32_t, srslte::unique_byte_buffer_t> pdcp_entity_lte::get_buffered_p
***************************************************************************/ ***************************************************************************/
pdcp_bearer_metrics_t pdcp_entity_lte::get_metrics() pdcp_bearer_metrics_t pdcp_entity_lte::get_metrics()
{ {
metrics.num_tx_buffered_pdus = undelivered_sdus.size(); if (undelivered_sdus != nullptr) {
metrics.num_tx_buffered_pdus_bytes = undelivered_sdus.get_bytes(); //< Number of bytes of PDUs waiting for ACK metrics.num_tx_buffered_pdus = undelivered_sdus->size();
metrics.num_tx_buffered_pdus_bytes = undelivered_sdus->get_bytes(); //< Number of bytes of PDUs waiting for ACK
}
metrics.tx_notification_latency_ms = metrics.tx_notification_latency_ms =
tx_pdu_ack_latency_ms.value(); //< Average time in ms from PDU delivery to RLC to ACK notification from RLC tx_pdu_ack_latency_ms.value(); //< Average time in ms from PDU delivery to RLC to ACK notification from RLC
return metrics; return metrics;
@ -748,7 +758,6 @@ bool undelivered_sdus_queue::add_sdu(uint32_t sn,
uint32_t discard_timeout, uint32_t discard_timeout,
const std::function<void(uint32_t)>& callback) const std::function<void(uint32_t)>& callback)
{ {
assert(discard_timeout < capacity and "Invalid discard timeout value");
assert(not has_sdu(sn) && "Cannot add repeated SNs"); assert(not has_sdu(sn) && "Cannot add repeated SNs");
if (is_full()) { if (is_full()) {

Loading…
Cancel
Save