lte,enb,rlc: compute and forward to scheduler the number of bytes pending for retx and status pdu in RLC AM bearer

master
Francisco 3 years ago committed by Francisco Paisana
parent b14e75218d
commit 4a58c10f30

@ -375,6 +375,7 @@ private:
bool has_data();
uint32_t get_buffer_state();
void get_buffer_state(uint32_t& new_tx, uint32_t& prio_tx);
// Timeout callback interface
void timer_expired(uint32_t timeout_id);

@ -436,9 +436,18 @@ void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn)
uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
{
uint32_t newtx = 0, priotx = 0;
get_buffer_state(newtx, priotx);
return newtx + priotx;
}
void rlc_am_lte::rlc_am_lte_tx::get_buffer_state(uint32_t& n_bytes_newtx, uint32_t& n_bytes_prio)
{
n_bytes_newtx = 0;
n_bytes_prio = 0;
uint32_t n_sdus = 0;
std::lock_guard<std::mutex> lock(mutex);
uint32_t n_bytes = 0;
uint32_t n_sdus = 0;
logger.debug("%s Buffer state - do_status=%s, status_prohibit_running=%s (%d/%d)",
RB_NAME,
@ -449,8 +458,8 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
// Bytes needed for status report
if (do_status() && not status_prohibit_timer.is_running()) {
n_bytes += parent->rx.get_status_pdu_length();
logger.debug("%s Buffer state - total status report: %d bytes", RB_NAME, n_bytes);
n_bytes_prio += parent->rx.get_status_pdu_length();
logger.debug("%s Buffer state - total status report: %d bytes", RB_NAME, n_bytes_prio);
}
// Bytes needed for retx
@ -468,8 +477,8 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
logger.error("In get_buffer_state(): Removing retx.sn=%d from queue", retx.sn);
retx_queue.pop();
} else {
n_bytes += req_bytes;
logger.debug("Buffer state - retx: %d bytes", n_bytes);
n_bytes_prio += req_bytes;
logger.debug("Buffer state - retx: %d bytes", n_bytes_prio);
}
}
}
@ -477,25 +486,23 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
// Bytes needed for tx SDUs
if (tx_window.size() < 1024) {
n_sdus = tx_sdu_queue.get_n_sdus();
n_bytes += tx_sdu_queue.size_bytes();
n_bytes_newtx += tx_sdu_queue.size_bytes();
if (tx_sdu != NULL) {
n_sdus++;
n_bytes += tx_sdu->N_bytes;
n_bytes_newtx += tx_sdu->N_bytes;
}
}
// Room needed for header extensions? (integer rounding)
if (n_sdus > 1) {
n_bytes += ((n_sdus - 1) * 1.5) + 0.5;
n_bytes_newtx += ((n_sdus - 1) * 1.5) + 0.5;
}
// Room needed for fixed header of data PDUs
if (n_bytes > 0 && n_sdus > 0) {
n_bytes += 2; // Two bytes for fixed header with SN length = 10
logger.debug("%s Total buffer state - %d SDUs (%d B)", RB_NAME, n_sdus, n_bytes);
if (n_bytes_newtx > 0 && n_sdus > 0) {
n_bytes_newtx += 2; // Two bytes for fixed header with SN length = 10
logger.debug("%s Total buffer state - %d SDUs (%d B)", RB_NAME, n_sdus, n_bytes_newtx);
}
return n_bytes;
}
int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
@ -613,7 +620,9 @@ void rlc_am_lte::rlc_am_lte_tx::timer_expired(uint32_t timeout_id)
lock.unlock();
if (bsr_callback) {
bsr_callback(parent->lcid, get_buffer_state(), 0);
uint32_t newtx = 0, priotx = 0;
get_buffer_state(newtx, priotx);
bsr_callback(parent->lcid, newtx, priotx);
}
}

@ -43,7 +43,7 @@ public:
// Buffer Status update
void ul_bsr(uint32_t lcg_id, uint32_t val);
void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue);
void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue);
// Configuration getters
bool is_bearer_active(uint32_t lcid) const { return get_cfg(lcid).is_active(); }
@ -58,13 +58,13 @@ public:
/// DL newtx buffer status for given LCID (no RLC overhead included)
int get_dl_tx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_tx : 0; }
/// DL retx buffer status for given LCID (no RLC overhead included)
int get_dl_retx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_retx : 0; }
/// DL high prio tx buffer status for given LCID (no RLC overhead included)
int get_dl_prio_tx(uint32_t lcid) const { return is_bearer_dl(lcid) ? channels[lcid].buf_prio_tx : 0; }
/// Sum of DL RLC newtx and retx buffer status for given LCID (no RLC overhead included)
int get_dl_tx_total(uint32_t lcid) const { return get_dl_tx(lcid) + get_dl_retx(lcid); }
/// Sum of DL RLC newtx and high prio tx buffer status for given LCID (no RLC overhead included)
int get_dl_tx_total(uint32_t lcid) const { return get_dl_tx(lcid) + get_dl_prio_tx(lcid); }
/// Sum of DL RLC newtx and retx buffer status for all LCIDS
/// Sum of DL RLC newtx and high prio buffer status for all LCIDS
int get_dl_tx_total() const;
// UL BSR methods
@ -82,7 +82,7 @@ protected:
struct logical_channel {
mac_lc_ch_cfg_t cfg;
int buf_tx = 0;
int buf_retx = 0;
int buf_prio_tx = 0;
int Bj = 0;
int bucket_size = 0;
};

@ -53,7 +53,7 @@ public:
uint32_t get_ul_buffer(uint16_t rnti) final;
uint32_t get_dl_buffer(uint16_t rnti) final;
int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) final;
int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t prio_tx_queue) final;
int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code, uint32_t nof_cmds = 1) final;
int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) final;

@ -46,30 +46,30 @@ public:
} cell_cfg_sib_t;
struct sched_args_t {
std::string sched_policy = "time_pf";
std::string sched_policy_args = "2";
int pdsch_mcs = -1;
int pdsch_max_mcs = 28;
int pusch_mcs = -1;
int pusch_max_mcs = 28;
uint32_t min_nof_ctrl_symbols = 1;
uint32_t max_nof_ctrl_symbols = 3;
int min_aggr_level = 0;
int max_aggr_level = 3;
bool adaptive_aggr_level = false;
bool pucch_mux_enabled = false;
int pucch_harq_max_rb = 0;
float target_bler = 0.05;
float max_delta_dl_cqi = 5;
float max_delta_ul_snr = 5;
std::string sched_policy = "time_pf";
std::string sched_policy_args = "2";
int pdsch_mcs = -1;
int pdsch_max_mcs = 28;
int pusch_mcs = -1;
int pusch_max_mcs = 28;
uint32_t min_nof_ctrl_symbols = 1;
uint32_t max_nof_ctrl_symbols = 3;
int min_aggr_level = 0;
int max_aggr_level = 3;
bool adaptive_aggr_level = false;
bool pucch_mux_enabled = false;
int pucch_harq_max_rb = 0;
float target_bler = 0.05;
float max_delta_dl_cqi = 5;
float max_delta_ul_snr = 5;
float adaptive_dl_mcs_step_size = 0.001;
float adaptive_ul_mcs_step_size = 0.001;
uint32_t min_tpc_tti_interval = 1;
float ul_snr_avg_alpha = 0.05;
int init_ul_snr_value = 5;
int init_dl_cqi = 5;
float max_sib_coderate = 0.8;
int pdcch_cqi_offset = 0;
uint32_t min_tpc_tti_interval = 1;
float ul_snr_avg_alpha = 0.05;
int init_ul_snr_value = 5;
int init_dl_cqi = 5;
float max_sib_coderate = 0.8;
int pdcch_cqi_offset = 0;
};
struct cell_cfg_t {
@ -267,10 +267,10 @@ public:
* @param rnti user rnti
* @param lc_id logical channel id for which the buffer update is concerned
* @param tx_queue number of pending bytes for new DL RLC transmissions
* @param retx_queue number of pending bytes concerning RLC retransmissions
* @param prio_tx_queue number of pending bytes concerning RLC retransmissions and status PDUs
* @return error code
*/
virtual int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) = 0;
virtual int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t prio_tx_queue) = 0;
/**
* Enqueue MAC CEs for DL transmission

@ -35,7 +35,7 @@ public:
using base_type::dl_buffer_state;
using base_type::get_bsr;
using base_type::get_bsr_state;
using base_type::get_dl_retx;
using base_type::get_dl_prio_tx;
using base_type::get_dl_tx;
using base_type::get_dl_tx_total;
using base_type::is_bearer_active;
@ -51,7 +51,7 @@ public:
bool has_pending_dl_txs() const;
int get_dl_tx_total_with_overhead(uint32_t lcid) const;
int get_dl_tx_with_overhead(uint32_t lcid) const;
int get_dl_retx_with_overhead(uint32_t lcid) const;
int get_dl_prio_tx_with_overhead(uint32_t lcid) const;
int get_bsr_with_overhead(uint32_t lcid) const;
int get_max_prio_lcid() const;
@ -61,7 +61,7 @@ public:
srsran::deque<ce_cmd> pending_ces;
private:
int alloc_retx_bytes(uint8_t lcid, int rem_bytes);
int alloc_prio_tx_bytes(uint8_t lcid, int rem_bytes);
int alloc_tx_bytes(uint8_t lcid, int rem_bytes);
size_t prio_idx = 0;

@ -112,20 +112,20 @@ void ue_buffer_manager<isNR>::ul_bsr(uint32_t lcg_id, uint32_t val)
}
template <bool isNR>
void ue_buffer_manager<isNR>::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue)
void ue_buffer_manager<isNR>::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t prio_tx_queue)
{
if (not is_lcid_valid(lcid)) {
logger.warning("The provided lcid=%d is not valid", lcid);
return;
}
if (lcid <= MAX_SRB_LC_ID and
(channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_retx != (int)retx_queue)) {
logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue);
(channels[lcid].buf_tx != (int)tx_queue or channels[lcid].buf_prio_tx != (int)prio_tx_queue)) {
logger.info("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, prio_tx_queue);
} else {
logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, retx_queue);
logger.debug("SCHED: DL lcid=%d buffer_state=%d,%d", lcid, tx_queue, prio_tx_queue);
}
channels[lcid].buf_retx = retx_queue;
channels[lcid].buf_tx = tx_queue;
channels[lcid].buf_prio_tx = prio_tx_queue;
channels[lcid].buf_tx = tx_queue;
}
// Explicit instantiation

@ -165,9 +165,9 @@ uint32_t sched::get_ul_buffer(uint16_t rnti)
return ret;
}
int sched::dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue)
int sched::dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t prio_tx_queue)
{
return ue_db_access_locked(rnti, [&](sched_ue& ue) { ue.dl_buffer_state(lc_id, tx_queue, retx_queue); });
return ue_db_access_locked(rnti, [&](sched_ue& ue) { ue.dl_buffer_state(lc_id, tx_queue, prio_tx_queue); });
}
int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code, uint32_t nof_cmds)

@ -94,9 +94,9 @@ int lch_ue_manager::get_max_prio_lcid() const
{
int min_prio_val = std::numeric_limits<int>::max(), prio_lcid = -1;
// Prioritize retxs
// Prioritized Txs first (e.g. Retxs, status PDUs)
for (uint32_t lcid = 0; is_lcid_valid(lcid); ++lcid) {
if (get_dl_retx(lcid) > 0 and channels[lcid].cfg.priority < min_prio_val) {
if (get_dl_prio_tx(lcid) > 0 and channels[lcid].cfg.priority < min_prio_val) {
min_prio_val = channels[lcid].cfg.priority;
prio_lcid = lcid;
}
@ -147,10 +147,10 @@ int lch_ue_manager::alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* rlc_pdu, int
return alloc_bytes;
}
// try first to allocate retxs
alloc_bytes = alloc_retx_bytes(lcid, rem_bytes);
// try first to allocate high priority txs (e.g. retxs, status pdus)
alloc_bytes = alloc_prio_tx_bytes(lcid, rem_bytes);
// if no retx alloc, try newtx
// if no prio tx alloc, try newtx
if (alloc_bytes == 0) {
alloc_bytes = alloc_tx_bytes(lcid, rem_bytes);
}
@ -168,15 +168,15 @@ int lch_ue_manager::alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* rlc_pdu, int
return alloc_bytes;
}
int lch_ue_manager::alloc_retx_bytes(uint8_t lcid, int rem_bytes)
int lch_ue_manager::alloc_prio_tx_bytes(uint8_t lcid, int rem_bytes)
{
const int rlc_overhead = (lcid == 0) ? 0 : RLC_MAX_HEADER_SIZE_NO_LI;
if (rem_bytes <= rlc_overhead) {
return 0;
}
int rem_bytes_no_header = rem_bytes - rlc_overhead;
int alloc = std::min(rem_bytes_no_header, get_dl_retx(lcid));
channels[lcid].buf_retx -= alloc;
int alloc = std::min(rem_bytes_no_header, get_dl_prio_tx(lcid));
channels[lcid].buf_prio_tx -= alloc;
return alloc + (alloc > 0 ? rlc_overhead : 0);
}
@ -211,7 +211,7 @@ bool lch_ue_manager::has_pending_dl_txs() const
int lch_ue_manager::get_dl_tx_total_with_overhead(uint32_t lcid) const
{
return get_dl_retx_with_overhead(lcid) + get_dl_tx_with_overhead(lcid);
return get_dl_prio_tx_with_overhead(lcid) + get_dl_tx_with_overhead(lcid);
}
int lch_ue_manager::get_dl_tx_with_overhead(uint32_t lcid) const
@ -219,9 +219,9 @@ int lch_ue_manager::get_dl_tx_with_overhead(uint32_t lcid) const
return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_tx(lcid));
}
int lch_ue_manager::get_dl_retx_with_overhead(uint32_t lcid) const
int lch_ue_manager::get_dl_prio_tx_with_overhead(uint32_t lcid) const
{
return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_retx(lcid));
return get_dl_mac_sdu_size_with_overhead(lcid, get_dl_prio_tx(lcid));
}
int lch_ue_manager::get_bsr_with_overhead(uint32_t lcg) const

@ -44,7 +44,7 @@ int test_pdu_alloc_successful(srsenb::lch_ue_manager& lch_handler,
int test_retx_until_empty(srsenb::lch_ue_manager& lch_handler, int lcid, uint32_t rlc_payload_size)
{
int start_rlc_bytes = lch_handler.get_dl_retx(lcid);
int start_rlc_bytes = lch_handler.get_dl_prio_tx(lcid);
int nof_pdus = ceil(static_cast<float>(start_rlc_bytes) / static_cast<float>(rlc_payload_size));
int rem_rlc_bytes = start_rlc_bytes;
@ -53,7 +53,7 @@ int test_retx_until_empty(srsenb::lch_ue_manager& lch_handler, int lcid, uint32_
uint32_t expected_payload_size = std::min(rlc_payload_size, (uint32_t)rem_rlc_bytes);
TESTASSERT(test_pdu_alloc_successful(lch_handler, pdu, lcid, expected_payload_size) == SRSRAN_SUCCESS);
rem_rlc_bytes -= expected_payload_size;
TESTASSERT(lch_handler.get_dl_retx(lcid) == rem_rlc_bytes);
TESTASSERT(lch_handler.get_dl_prio_tx(lcid) == rem_rlc_bytes);
}
return start_rlc_bytes;
}
@ -97,15 +97,15 @@ int test_lc_ch_pbr_infinity()
lch_handler.dl_buffer_state(drb_to_lcid(lte_drb::drb2), 5000, 10000);
// TEST1 - retx of SRB1 is prioritized. Do not transmit other bearers until there are no SRB1 retxs
int nof_pending_bytes = lch_handler.get_dl_retx(srb_to_lcid(lte_srb::srb1));
int nof_pending_bytes = lch_handler.get_dl_prio_tx(srb_to_lcid(lte_srb::srb1));
TESTASSERT(test_retx_until_empty(lch_handler, srb_to_lcid(lte_srb::srb1), 500) == nof_pending_bytes);
// TEST2 - the DRB2 has lower prio level than SRB1, but has retxs
nof_pending_bytes = lch_handler.get_dl_retx(drb_to_lcid(lte_drb::drb2));
nof_pending_bytes = lch_handler.get_dl_prio_tx(drb_to_lcid(lte_drb::drb2));
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb2), 500) == nof_pending_bytes);
// TEST3 - the DRB1 has lower prio level, but has retxs
nof_pending_bytes = lch_handler.get_dl_retx(drb_to_lcid(lte_drb::drb1));
nof_pending_bytes = lch_handler.get_dl_prio_tx(drb_to_lcid(lte_drb::drb1));
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb1), 500) == nof_pending_bytes);
// TEST4 - The SRB1 newtx buffer is emptied before other bearers newtxs
@ -154,11 +154,11 @@ int test_lc_ch_pbr_finite()
lch_handler.dl_buffer_state(drb_to_lcid(lte_drb::drb2), 50000, 0);
// TEST1 - SRB1 retxs are emptied first
int nof_pending_bytes = lch_handler.get_dl_retx(srb_to_lcid(lte_srb::srb1));
int nof_pending_bytes = lch_handler.get_dl_prio_tx(srb_to_lcid(lte_srb::srb1));
TESTASSERT(test_retx_until_empty(lch_handler, srb_to_lcid(lte_srb::srb1), 500) == nof_pending_bytes);
// TEST2 - DRB1 retxs are emptied
nof_pending_bytes = lch_handler.get_dl_retx(drb_to_lcid(lte_drb::drb1));
nof_pending_bytes = lch_handler.get_dl_prio_tx(drb_to_lcid(lte_drb::drb1));
TESTASSERT(test_retx_until_empty(lch_handler, drb_to_lcid(lte_drb::drb1), 500) == nof_pending_bytes);
// TEST3 - SRB1 newtxs are emptied (PBR==infinity)

Loading…
Cancel
Save