fixed the building of MAC SDUs in the scheduler. Now, we ensure there is always space for the MAC subheader and RLC header. The MAC subheader is correctly discounted from the remaining bytes in a TB.

This commit is contained in:
Francisco Paisana 2020-02-07 18:36:41 +00:00
parent 089f72d573
commit 87038375d5
3 changed files with 63 additions and 52 deletions

View File

@ -222,9 +222,10 @@ private:
void set_bearer_cfg_unlocked(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg_);
bool is_sr_triggered();
int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu);
uint32_t format1_count_prb(const rbgmask_t& bitmask, uint32_t cc_idx);
int alloc_mac_sdu(sched_interface::dl_sched_pdu_t* pdu, int rem_tbs);
uint32_t allocate_mac_sdus(sched_interface::dl_sched_data_t* data, uint32_t total_tbs);
static bool bearer_is_ul(ue_bearer_t* lch);
static bool bearer_is_dl(const ue_bearer_t* lch);

View File

@ -33,7 +33,6 @@
#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__)
#define MCS_FIRST_DL 4
#define MIN_DATA_TBS 4
/******************************************************
* UE class *
@ -43,6 +42,19 @@ namespace srsenb {
constexpr uint32_t conres_ce_size = 6;
/******************************************************
* Helper Functions *
******************************************************/
namespace sched_utils {
uint32_t get_tbs_bytes(uint32_t mcs, uint32_t nof_alloc_prb, bool is_ul)
{
return srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, is_ul), nof_alloc_prb);
}
} // namespace sched_utils
/*******************************************************
*
* Initialization and configuration functions
@ -349,8 +361,28 @@ void sched_ue::tpc_dec()
*
*******************************************************/
uint32_t sched_ue::allocate_mac_sdus(sched_interface::dl_sched_data_t* data, uint32_t total_tbs)
{
auto compute_subheader_size = [](uint32_t sdu_size) { return sdu_size > 128 ? 3 : 2; };
constexpr uint32_t min_mac_sdu_size = 5; // accounts for MAC SDU subheader and RLC header
uint32_t rem_tbs = total_tbs;
// if we do not have enough bytes to fit MAC subheader and RLC header, skip MAC SDU allocation
while (rem_tbs >= min_mac_sdu_size) {
uint32_t max_sdu_bytes = rem_tbs - compute_subheader_size(rem_tbs - 2);
uint32_t alloc_sdu_bytes = alloc_mac_sdu(&data->pdu[0][data->nof_pdu_elems[0]], max_sdu_bytes);
if (alloc_sdu_bytes == 0) {
break;
}
rem_tbs -= (alloc_sdu_bytes + compute_subheader_size(alloc_sdu_bytes)); // account for MAC sub-header
data->nof_pdu_elems[0]++;
}
return total_tbs - rem_tbs;
}
// Generates a Format1 dci
// > return 0 if TBS<MIN_DATA_TBS
// > return 0 if allocation is invalid
int sched_ue::generate_format1(dl_harq_proc* h,
sched_interface::dl_sched_data_t* data,
uint32_t tti_tx_dl,
@ -391,25 +423,14 @@ int sched_ue::generate_format1(dl_harq_proc* h,
if (mcs0 < 0) { // dynamic MCS
tbs = carriers[cc_idx].alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs);
} else {
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs0, false), nof_prb) / 8;
mcs = mcs0;
}
// Ensure tbs >= MIN_DATA_TBS
while (tbs < MIN_DATA_TBS and mcs != carriers[cc_idx].max_mcs_dl) {
mcs++;
tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false), nof_prb) / 8;
}
if (tbs < MIN_DATA_TBS) {
log_h->warning("SCHED: Allocation of TBS=%d that does not account header\n", tbs);
return 0;
tbs = sched_utils::get_tbs_bytes(mcs, nof_prb, false);
}
// Allocate DL Harq
h->new_tx(user_mask, 0, tti_tx_dl, mcs, tbs, data->dci.location.ncce);
int rem_tbs = tbs;
int x = 0;
// Allocate MAC ConRes CE
if (need_conres_ce) {
@ -426,14 +447,8 @@ int sched_ue::generate_format1(dl_harq_proc* h,
rem_tbs -= 2;
}
// Allocate PDUs
do {
x = alloc_pdu(rem_tbs, &data->pdu[0][data->nof_pdu_elems[0]]);
if (x) {
rem_tbs -= x + 2; // count 2-byte header
data->nof_pdu_elems[0]++;
}
} while (rem_tbs >= MIN_DATA_TBS && x > 0);
// Allocate MAC SDU and respective subheaders
allocate_mac_sdus(data, rem_tbs);
Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
} else {
@ -538,17 +553,10 @@ int sched_ue::generate_format2a_unlocked(dl_harq_proc* h,
8;
mcs = carriers[cc_idx].fixed_mcs_dl;
}
h->new_tx(user_mask, tb, tti, mcs, tbs, data->dci.location.ncce);
int rem_tbs = tbs;
int x = 0;
do {
x = alloc_pdu(rem_tbs, &data->pdu[tb][data->nof_pdu_elems[tb]]);
rem_tbs -= x;
if (x) {
data->nof_pdu_elems[tb]++;
}
} while (rem_tbs >= MIN_DATA_TBS && x > 0);
allocate_mac_sdus(data, tbs);
Debug("SCHED: Alloc format2/2a new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes);
}
@ -1006,26 +1014,26 @@ sched_ue_carrier* sched_ue::get_ue_carrier(uint32_t enb_cc_idx)
}
/* Allocates first available RLC PDU */
int sched_ue::alloc_pdu(int tbs_bytes, sched_interface::dl_sched_pdu_t* pdu)
int sched_ue::alloc_mac_sdu(sched_interface::dl_sched_pdu_t* mac_sdu, int rem_tbs)
{
// TODO: Implement lcid priority (now lowest index is lowest priority)
int x = 0;
int i = 0;
for (i = 0; i < sched_interface::MAX_LC && !x; i++) {
if (lch[i].buf_retx) {
x = SRSLTE_MIN(lch[i].buf_retx, tbs_bytes);
lch[i].buf_retx -= x;
} else if (lch[i].buf_tx) {
x = SRSLTE_MIN(lch[i].buf_tx, tbs_bytes);
lch[i].buf_tx -= x;
int alloc_bytes = 0;
int i = 0;
for (i = 0; i < sched_interface::MAX_LC and alloc_bytes == 0; i++) {
if (lch[i].buf_retx > 0) {
alloc_bytes = SRSLTE_MIN(lch[i].buf_retx, rem_tbs);
lch[i].buf_retx -= alloc_bytes;
} else if (lch[i].buf_tx > 0) {
alloc_bytes = SRSLTE_MIN(lch[i].buf_tx, rem_tbs);
lch[i].buf_tx -= alloc_bytes;
}
}
if (x) {
pdu->lcid = i - 1;
pdu->nbytes = x;
Debug("SCHED: Allocated lcid=%d, nbytes=%d, tbs_bytes=%d\n", pdu->lcid, pdu->nbytes, tbs_bytes);
if (alloc_bytes > 0) {
mac_sdu->lcid = i - 1;
mac_sdu->nbytes = alloc_bytes;
Debug("SCHED: Allocated lcid=%d, nbytes=%d, tbs_bytes=%d\n", mac_sdu->lcid, mac_sdu->nbytes, rem_tbs);
}
return x;
return alloc_bytes;
}
uint32_t sched_ue::format1_count_prb(const rbgmask_t& bitmask, uint32_t cc_idx)

View File

@ -23,6 +23,7 @@
#include "srsenb/hdr/stack/mac/scheduler_carrier.h"
#include "srsenb/hdr/stack/mac/scheduler_ue.h"
#include <algorithm>
#include <chrono>
#include <random>
#include <set>
#include <srslte/srslte.h>
@ -70,8 +71,8 @@
/***************************
* Setup Random generators
**************************/
uint32_t const seed = time(nullptr);
// uint32_t const seed = 2452071795; // [{3054, 1656}, {5970, 1595}, ... {204, 3}]
uint32_t const seed = std::chrono::system_clock::now().time_since_epoch().count();
// uint32_t const seed = 2452071795;
// uint32_t const seed = 1581009287; // prb==25
std::default_random_engine rand_gen(seed);
std::uniform_real_distribution<float> unif_dist(0, 1.0);
@ -910,16 +911,17 @@ int sched_tester::ack_txs()
srsenb::sched_interface::cell_cfg_t generate_cell_cfg()
{
srsenb::sched_interface::cell_cfg_t cell_cfg;
srsenb::sched_interface::cell_cfg_t cell_cfg = {};
srslte_cell_t& cell_cfg_phy = cell_cfg.cell;
bzero(&cell_cfg, sizeof(srsenb::sched_interface::cell_cfg_t));
std::uniform_int_distribution<uint32_t> dist_prb_idx(0, 5);
uint32_t prb_idx = dist_prb_idx(rand_gen);
/* Set PHY cell configuration */
cell_cfg_phy.id = 1;
cell_cfg_phy.cp = SRSLTE_CP_NORM;
cell_cfg_phy.nof_ports = 1;
cell_cfg_phy.nof_prb = 6;
cell_cfg_phy.nof_prb = std::array<uint32_t, 6>({6, 15, 25, 50, 75, 100})[prb_idx];
cell_cfg_phy.phich_length = SRSLTE_PHICH_NORM;
cell_cfg_phy.phich_resources = SRSLTE_PHICH_R_1;