sched,bugfix: The PHR handling scheme now considers the number of PRBs of the UL grant that carried the PHR. Before, it was assuming the most conservative scenario of Nprb=1

master
Francisco 4 years ago committed by Francisco Paisana
parent f7aef3ffc1
commit 486823e5de

@ -183,9 +183,15 @@ public:
* @param enb_cc_idx the eNb Cell/Carrier identifier
* @param nof_bytes the number of grants carrierd by the PUSCH message
* @param crc_res the CRC check, set to true if the message was decoded succesfully
* @param ul_nof_prbs Number of PRBs allocated to grant
* @return SRSRAN_SUCCESS if no error occurs, SRSRAN_ERROR* if an error occurs
*/
virtual int push_pdu(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc_res) = 0;
virtual int push_pdu(uint32_t tti_rx,
uint16_t rnti,
uint32_t enb_cc_idx,
uint32_t nof_bytes,
bool crc_res,
uint32_t ul_nof_prbs) = 0;
virtual int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) = 0;
virtual int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) = 0;

@ -295,7 +295,7 @@ public:
virtual int ul_crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, bool crc) = 0;
virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0;
virtual int ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) = 0;
virtual int ul_phr(uint16_t rnti, int phr) = 0;
virtual int ul_phr(uint16_t rnti, int phr, uint32_t ul_nof_prb) = 0;
virtual int ul_snr_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code) = 0;
/* Run Scheduler for this tti */

@ -30,7 +30,7 @@ public:
class process_callback
{
public:
virtual void process_pdu(uint8_t* buff, uint32_t len, channel_t channel) = 0;
virtual void process_pdu(uint8_t* buff, uint32_t len, channel_t channel, int ul_nof_prbs = -1) = 0;
};
pdu_queue(srslog::basic_logger& logger) : pool(DEFAULT_POOL_SIZE), callback(NULL), logger(logger) {}
@ -38,7 +38,7 @@ public:
uint8_t* request(uint32_t len);
void deallocate(const uint8_t* pdu);
void push(const uint8_t* ptr, uint32_t len, channel_t channel = DCH);
void push(const uint8_t* ptr, uint32_t len, channel_t channel = DCH, int ul_nof_prbs = -1);
bool process_pdus();
@ -52,6 +52,7 @@ private:
uint8_t ptr[MAX_PDU_LEN];
uint32_t len;
channel_t channel;
int grant_nof_prbs;
#ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED
char debug_name[128];
#endif

@ -53,12 +53,13 @@ void pdu_queue::deallocate(const uint8_t* pdu)
* This function enqueues the packet and returns quicly because ACK
* deadline is important here.
*/
void pdu_queue::push(const uint8_t* ptr, uint32_t len, channel_t channel)
void pdu_queue::push(const uint8_t* ptr, uint32_t len, channel_t channel, int grant_nof_prbs)
{
if (ptr) {
pdu_t* pdu = (pdu_t*)ptr;
pdu->len = len;
pdu->channel = channel;
pdu_t* pdu = (pdu_t*)ptr;
pdu->len = len;
pdu->channel = channel;
pdu->grant_nof_prbs = grant_nof_prbs;
if (!pdu_q.try_push(pdu)) {
logger.warning("Error pushing pdu: queue is full");
}
@ -74,7 +75,7 @@ bool pdu_queue::process_pdus()
pdu_t* pdu;
while (pdu_q.try_pop(pdu)) {
if (callback) {
callback->process_pdu(pdu->ptr, pdu->len, pdu->channel);
callback->process_pdu(pdu->ptr, pdu->len, pdu->channel, pdu->grant_nof_prbs);
}
cnt++;
have_data = true;

@ -77,9 +77,14 @@ public:
{
return mac.crc_info(tti, rnti, enb_cc_idx, nof_bytes, crc_res);
}
int push_pdu(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc_res) final
int push_pdu(uint32_t tti,
uint16_t rnti,
uint32_t enb_cc_idx,
uint32_t nof_bytes,
bool crc_res,
uint32_t grant_nof_prbs) final
{
return mac.push_pdu(tti, rnti, enb_cc_idx, nof_bytes, crc_res);
return mac.push_pdu(tti, rnti, enb_cc_idx, nof_bytes, crc_res, grant_nof_prbs);
}
int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) final { return mac.get_dl_sched(tti, dl_sched_res); }
int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) final

@ -59,7 +59,8 @@ public:
int ta_info(uint32_t tti, uint16_t rnti, float ta_us) override;
int ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) override;
int crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc_res) override;
int push_pdu(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc_res) override;
int push_pdu(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc_res, uint32_t ul_nof_prbs)
override;
int get_dl_sched(uint32_t tti_tx_dl, dl_sched_list_t& dl_sched_res) override;
int get_ul_sched(uint32_t tti_tx_ul, ul_sched_list_t& ul_sched_res) override;

@ -64,7 +64,7 @@ public:
int ul_crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, bool crc) final;
int ul_sr_info(uint32_t tti, uint16_t rnti) override;
int ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) final;
int ul_phr(uint16_t rnti, int phr) final;
int ul_phr(uint16_t rnti, int phr, uint32_t ul_nof_prb) final;
int ul_snr_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code) final;
int dl_sched(uint32_t tti, uint32_t enb_cc_idx, dl_sched_res_t& sched_result) final;

@ -53,7 +53,7 @@ public:
void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue);
void ul_buffer_state(uint8_t lcg_id, uint32_t bsr);
void ul_phr(int phr);
void ul_phr(int phr, uint32_t grant_nof_prb);
void mac_buffer_state(uint32_t ce_code, uint32_t nof_cmds);
void set_ul_snr(tti_point tti_rx, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code);

@ -35,13 +35,15 @@ public:
static constexpr uint32_t PUSCH_CODE = 0, PUCCH_CODE = 1;
static constexpr int PHR_NEG_NOF_PRB = 1;
explicit tpc(uint32_t cell_nof_prb,
explicit tpc(uint16_t rnti_,
uint32_t cell_nof_prb,
float target_pucch_snr_dB_ = -1.0,
float target_pusch_sn_dB_ = -1.0,
bool phr_handling_flag_ = false,
uint32_t min_tpc_tti_interval_ = 1,
float ul_snr_avg_alpha = 0.05,
int init_ul_snr_value = 5) :
rnti(rnti_),
nof_prb(cell_nof_prb),
target_pucch_snr_dB(target_pucch_snr_dB_),
target_pusch_snr_dB(target_pusch_sn_dB_),
@ -69,7 +71,7 @@ public:
snr_estim_list[ul_ch_code].pending_snr = snr;
}
}
void set_phr(int phr_)
void set_phr(int phr_, uint32_t grant_nof_prbs)
{
last_phr = phr_;
for (auto& ch_snr : snr_estim_list) {
@ -79,12 +81,18 @@ public:
// compute and cache the max nof UL PRBs that avoids overflowing PHR
if (phr_handling_flag) {
max_prbs_cached = PHR_NEG_NOF_PRB;
int phr_x_prb = std::roundf(last_phr + 10.0F * log10f(grant_nof_prbs)); // get what the PHR would be if Nprb=1
for (int n = nof_prb; n > PHR_NEG_NOF_PRB; --n) {
if (last_phr >= 10 * log10(n)) {
if (phr_x_prb >= 10 * log10f(n)) {
max_prbs_cached = n;
break;
}
}
logger.info("SCHED: rnti=0x%x received PHR=%d for UL Nprb=%d. Max UL Nprb is now=%d",
rnti,
phr_,
grant_nof_prbs,
max_prbs_cached);
}
}
@ -181,6 +189,7 @@ private:
return encode_tpc_delta(ch_snr.pending_delta);
}
uint16_t rnti;
uint32_t nof_prb;
uint32_t min_tpc_tti_interval = 1;
float target_pucch_snr_dB, target_pusch_snr_dB;

@ -67,7 +67,7 @@ public:
uint8_t* request_pdu(tti_point tti, uint32_t len);
bool push_pdu(tti_point tti, uint32_t len);
bool push_pdu(tti_point tti, uint32_t len, uint32_t grant_nof_prbs);
void clear_old_pdus(tti_point current_tti);
@ -161,10 +161,10 @@ public:
bool process_pdus();
uint8_t* request_buffer(uint32_t tti, uint32_t ue_cc_idx, const uint32_t len);
void process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel) override;
void push_pdu(uint32_t tti, uint32_t ue_cc_idx, uint32_t len);
void deallocate_pdu(uint32_t tti, uint32_t ue_cc_idx);
void clear_old_buffers(uint32_t tti);
void process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel, int grant_nof_prbs) override;
void push_pdu(uint32_t tti, uint32_t ue_cc_idx, uint32_t len, uint32_t grant_nof_prbs);
void deallocate_pdu(uint32_t tti, uint32_t ue_cc_idx);
void clear_old_buffers(uint32_t tti);
void metrics_read(mac_ue_metrics_t* metrics_);
void metrics_rx(bool crc, uint32_t tbs);
@ -179,7 +179,7 @@ public:
private:
void allocate_sdu(srsran::sch_pdu* pdu, uint32_t lcid, uint32_t sdu_len);
bool process_ce(srsran::sch_subh* subh);
bool process_ce(srsran::sch_subh* subh, int grant_nof_prbs);
void allocate_ce(srsran::sch_pdu* pdu, uint32_t lcid);
rlc_interface_mac* rlc = nullptr;

@ -365,7 +365,8 @@ void cc_worker::decode_pusch(stack_interface_phy_lte::ul_sched_grant_t* grants,
// Inform MAC about the CRC result
phy->stack->crc_info(tti_rx, rnti, cc_idx, ul_cfg.pusch.grant.tb.tbs / 8, pusch_res.crc);
// Push PDU buffer
phy->stack->push_pdu(tti_rx, rnti, cc_idx, ul_cfg.pusch.grant.tb.tbs / 8, pusch_res.crc);
phy->stack->push_pdu(
tti_rx, rnti, cc_idx, ul_cfg.pusch.grant.tb.tbs / 8, pusch_res.crc, ul_cfg.pusch.grant.L_prb);
// Logging
if (logger.info.enabled()) {
char str[512];

@ -341,7 +341,12 @@ int mac::crc_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t
return scheduler.ul_crc_info(tti_rx, rnti, enb_cc_idx, crc);
}
int mac::push_pdu(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc)
int mac::push_pdu(uint32_t tti_rx,
uint16_t rnti,
uint32_t enb_cc_idx,
uint32_t nof_bytes,
bool crc,
uint32_t ul_nof_prbs)
{
srsran::rwlock_read_guard lock(rwlock);
@ -359,7 +364,7 @@ int mac::push_pdu(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t
// push the pdu through the queue if received correctly
if (crc) {
logger.info("Pushing PDU rnti=0x%x, tti_rx=%d, nof_bytes=%d", rnti, tti_rx, nof_bytes);
ue_db[rnti]->push_pdu(tti_rx, ue_cc_idx, nof_bytes);
ue_db[rnti]->push_pdu(tti_rx, ue_cc_idx, nof_bytes, ul_nof_prbs);
stack_task_queue.push([this]() { process_pdus(); });
} else {
logger.debug("Discarting PDU rnti=0x%x, tti_rx=%d, nof_bytes=%d", rnti, tti_rx, nof_bytes);

@ -231,10 +231,10 @@ int sched::ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes)
return ue_db_access_locked(rnti, [lcid, bytes](sched_ue& ue) { ue.ul_buffer_add(lcid, bytes); });
}
int sched::ul_phr(uint16_t rnti, int phr)
int sched::ul_phr(uint16_t rnti, int phr, uint32_t ul_nof_prb)
{
return ue_db_access_locked(
rnti, [phr](sched_ue& ue) { ue.ul_phr(phr); }, __PRETTY_FUNCTION__);
rnti, [phr, ul_nof_prb](sched_ue& ue) { ue.ul_phr(phr, ul_nof_prb); }, __PRETTY_FUNCTION__);
}
int sched::ul_sr_info(uint32_t tti, uint16_t rnti)

@ -131,9 +131,9 @@ void sched_ue::ul_buffer_add(uint8_t lcid, uint32_t bytes)
lch_handler.ul_buffer_add(lcid, bytes);
}
void sched_ue::ul_phr(int phr)
void sched_ue::ul_phr(int phr, uint32_t grant_nof_prb)
{
cells[cfg.supported_cc_list[0].enb_cc_idx].tpc_fsm.set_phr(phr);
cells[cfg.supported_cc_list[0].enb_cc_idx].tpc_fsm.set_phr(phr, grant_nof_prb);
}
void sched_ue::dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue)

@ -35,7 +35,8 @@ sched_ue_cell::sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg
cell_cfg(&cell_cfg_),
dci_locations(generate_cce_location_table(rnti_, cell_cfg_)),
harq_ent(SCHED_MAX_HARQ_PROC, SCHED_MAX_HARQ_PROC),
tpc_fsm(cell_cfg->nof_prb(),
tpc_fsm(rnti_,
cell_cfg->nof_prb(),
cell_cfg->cfg.target_pucch_ul_sinr,
cell_cfg->cfg.target_pusch_ul_sinr,
cell_cfg->cfg.enable_phr_handling,

@ -71,14 +71,14 @@ cc_used_buffers_map::~cc_used_buffers_map()
clear();
}
bool cc_used_buffers_map::push_pdu(tti_point tti, uint32_t len)
bool cc_used_buffers_map::push_pdu(tti_point tti, uint32_t len, uint32_t grant_nof_prbs)
{
if (not has_tti(tti)) {
return false;
}
uint8_t* buffer = pdu_map[tti.to_uint()];
if (len > 0) {
shared_pdu_queue->push(buffer, len);
shared_pdu_queue->push(buffer, len, srsran::pdu_queue::DCH, grant_nof_prbs);
} else {
shared_pdu_queue->deallocate(buffer);
logger->error("Error pushing PDU: null length");
@ -329,7 +329,7 @@ uint32_t ue::set_ta(int ta_)
return nof_cmd;
}
void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel)
void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel, int grant_nof_prbs)
{
// Unpack ULSCH MAC PDU
mac_msg_ul.init_rx(nof_bytes, true);
@ -417,7 +417,7 @@ void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channe
assert(mac_msg_ul.get());
if (!mac_msg_ul.get()->is_sdu()) {
// Process MAC Control Element
bsr_received |= process_ce(mac_msg_ul.get());
bsr_received |= process_ce(mac_msg_ul.get(), grant_nof_prbs);
}
}
@ -440,15 +440,15 @@ void ue::deallocate_pdu(uint32_t tti, uint32_t ue_cc_idx)
}
}
void ue::push_pdu(uint32_t tti, uint32_t ue_cc_idx, uint32_t len)
void ue::push_pdu(uint32_t tti, uint32_t ue_cc_idx, uint32_t len, uint32_t grant_nof_prbs)
{
std::unique_lock<std::mutex> lock(rx_buffers_mutex);
if (not cc_buffers[ue_cc_idx].get_rx_used_buffers().push_pdu(tti_point(tti), len)) {
if (not cc_buffers[ue_cc_idx].get_rx_used_buffers().push_pdu(tti_point(tti), len, grant_nof_prbs)) {
logger.warning("UE buffers: Failed to push RX PDU for rnti=0x%x tti=%d cc_idx=%d", rnti, tti, ue_cc_idx);
}
}
bool ue::process_ce(srsran::sch_subh* subh)
bool ue::process_ce(srsran::sch_subh* subh, int grant_nof_prbs)
{
uint32_t buff_size_idx[4] = {};
uint32_t buff_size_bytes[4] = {};
@ -459,7 +459,8 @@ bool ue::process_ce(srsran::sch_subh* subh)
switch (subh->ul_sch_ce_type()) {
case srsran::ul_sch_lcid::PHR_REPORT:
phr = subh->get_phr();
sched->ul_phr(rnti, (int)phr);
srsran_assert(grant_nof_prbs > 0, "Invalid nof prbs=%d provided for PHR handling", grant_nof_prbs);
sched->ul_phr(rnti, (int)phr, grant_nof_prbs);
metrics_phr(phr);
break;
case srsran::ul_sch_lcid::CRNTI:

@ -26,7 +26,7 @@ int test_finite_target_snr()
const uint32_t nof_prbs = 50;
const int target_snr = 15;
tpc tpcfsm(nof_prbs, 15, 15, true);
tpc tpcfsm(0x46, nof_prbs, 15, 15, true);
// TEST: While UL SNR ~ target, no TPC commands are sent
for (uint32_t i = 0; i < 100 and tpcfsm.get_ul_snr_estim(0) < 14; ++i) {
@ -78,7 +78,7 @@ int test_undefined_target_snr()
{
const uint32_t nof_prbs = 50;
tpc tpcfsm(nof_prbs, -1, -1, true);
tpc tpcfsm(0x46, nof_prbs, -1, -1, true);
TESTASSERT(tpcfsm.max_ul_prbs() == 50);
// TEST: While the PHR is not updated, a limited number of TPC commands should be sent
@ -107,7 +107,7 @@ int test_undefined_target_snr()
// TEST: Check that high PHR allows full utilization of available PRBs, TPC remains at zero (no target SINR)
int phr = 30;
tpcfsm.set_phr(phr);
tpcfsm.set_phr(phr, 1);
TESTASSERT(tpcfsm.max_ul_prbs() == 50);
sum_pusch = 0;
sum_pucch = 0;
@ -120,7 +120,7 @@ int test_undefined_target_snr()
// TEST: PHR is too low to allow all PRBs to be allocated. This event should not affect TPC commands
phr = 5;
tpcfsm.set_phr(phr);
tpcfsm.set_phr(phr, 1);
TESTASSERT(tpcfsm.max_ul_prbs() < 50);
for (uint32_t i = 0; i < 100; ++i) {
tpcfsm.new_tti();
@ -130,7 +130,7 @@ int test_undefined_target_snr()
// TEST: PHR is negative. The TPC should slightly decrease Tx UL power until next PHR
phr = -1;
tpcfsm.set_phr(phr);
tpcfsm.set_phr(phr, 1);
TESTASSERT(tpcfsm.max_ul_prbs() == tpc::PHR_NEG_NOF_PRB);
sum_pusch = 0;
sum_pucch = 0;

@ -40,12 +40,12 @@ void test_neg_phr_scenario()
float snr = 0;
ue_cc.set_ul_snr(tti_point(0), snr, 0);
ue_cc.set_ul_snr(tti_point(0), snr, 1);
ue_cc.tpc_fsm.set_phr(-5);
ue_cc.tpc_fsm.set_phr(-5, 1);
ue_cc.new_tti(tti_point(0));
uint32_t req_bytes = 10000;
uint32_t pending_prbs = get_required_prb_ul(ue_cc, req_bytes);
TESTASSERT(pending_prbs < 10); // The PHR<0 is limiting the number of allocated PRBs
TESTASSERT(pending_prbs == 1); // The PHR<0 is limiting the number of allocated PRBs
uint32_t N_srs = 0;
uint32_t prb_grant_size = pending_prbs;

@ -505,7 +505,8 @@ public:
return 0;
}
int push_pdu(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc_res) override
int push_pdu(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc_res, uint32_t grant_nof_prbs)
override
{
logger.info("Received push_pdu tti=%d; rnti=0x%x; ack=%d;", tti, rnti, crc_res);
notify_push_pdu();

@ -56,7 +56,7 @@ public:
bool get_uecrid_successful();
void process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel);
void process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel, int ul_nof_prbs);
void mch_start_rx(uint32_t lcid);
private:

@ -147,7 +147,7 @@ bool demux::process_pdus()
return pdus.process_pdus();
}
void demux::process_pdu(uint8_t* mac_pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel)
void demux::process_pdu(uint8_t* mac_pdu, uint32_t nof_bytes, srsran::pdu_queue::channel_t channel, int ul_nof_prbs)
{
Debug("Processing MAC PDU channel %d", channel);
switch (channel) {

@ -104,7 +104,7 @@ public:
uint32_t get_tti();
void process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel);
void process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel, int ul_nof_prbs);
void set_cell_config(const ttcn3_helpers::timing_info_t timing, const cell_config_t cell);
void set_cell_config_impl(const cell_config_t cell);

@ -759,7 +759,7 @@ uint32_t ttcn3_syssim::get_tti()
return tti;
}
void ttcn3_syssim::process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel) {}
void ttcn3_syssim::process_pdu(uint8_t* buff, uint32_t len, pdu_queue::channel_t channel, int ul_nof_prbs) {}
void ttcn3_syssim::set_cell_config(const ttcn3_helpers::timing_info_t timing, const cell_config_t cell)
{

Loading…
Cancel
Save