addition of SCell Activation CE Cmd to scheduler and MAC

This commit is contained in:
Francisco Paisana 2020-02-13 17:15:41 +00:00
parent 838053e8f2
commit d831522692
13 changed files with 151 additions and 65 deletions

View File

@ -64,6 +64,19 @@ public:
}
}
void set(size_t pos, bool val) noexcept
{
if (pos >= size()) {
srslte::logmap::get("COMM")->error("ERROR: bitset out of bounds: %zd>=%zd\n", pos, size());
return;
}
if (val) {
set_(pos);
} else {
reset_(pos);
}
}
void set(size_t pos) noexcept
{
if (pos >= size()) {
@ -76,7 +89,7 @@ public:
void reset(size_t pos) noexcept
{
if (pos >= size()) {
printf("ERROR: bitset out of bounds: %zd>=%zd\n", pos, size());
srslte::logmap::get("COMM")->error("ERROR: bitset out of bounds: %zd>=%zd\n", pos, size());
return;
}
reset_(pos);
@ -92,7 +105,7 @@ public:
bool test(size_t pos) const noexcept
{
if (pos >= size()) {
printf("ERROR: bitset out of bounds: %zd>=%zd\n", pos, size());
srslte::logmap::get("COMM")->error("ERROR: bitset out of bounds: %zd>=%zd\n", pos, size());
return false;
}
return test_(pos);
@ -110,7 +123,8 @@ public:
bounded_bitset<N, reversed>& fill(size_t startpos, size_t endpos, bool value = true) noexcept
{
if (endpos > size() or startpos > endpos) {
printf("ERROR: bounds (%zd, %zd) are not valid for bitset of size: %zd\n", startpos, endpos, size());
srslte::logmap::get("COMM")->error(
"ERROR: bounds (%zd, %zd) are not valid for bitset of size: %zd\n", startpos, endpos, size());
return *this;
}
// NOTE: can be optimized
@ -154,7 +168,8 @@ public:
bool any(size_t start, size_t stop) const noexcept
{
if (start > stop or stop > size()) {
printf("ERROR: bounds (%zd, %zd) are not valid for bitset of size: %zd\n", start, stop, size());
srslte::logmap::get("COMM")->error(
"ERROR: bounds (%zd, %zd) are not valid for bitset of size: %zd\n", start, stop, size());
return false;
}
// NOTE: can be optimized
@ -174,8 +189,8 @@ public:
for (size_t i = 0; i < nof_words_(); i++) {
// result += __builtin_popcountl(buffer[i]);
word_t w = buffer[i];
for (; w; w >>= 1) {
result += (w & 1);
for (; w; w >>= 1u) {
result += (w & 1u);
}
}
return result;
@ -187,8 +202,9 @@ public:
return false;
}
for (uint32_t i = 0; i < nof_words_(); ++i) {
if (buffer[i] != other.buffer[i])
if (buffer[i] != other.buffer[i]) {
return false;
}
}
return true;
}
@ -198,7 +214,8 @@ public:
bounded_bitset<N, reversed>& operator|=(const bounded_bitset<N, reversed>& other) noexcept
{
if (other.size() != size()) {
printf("ERROR: operator|= called for bitsets of different sizes (%zd!=%zd)\n", size(), other.size());
srslte::logmap::get("COMM")->error(
"ERROR: operator|= called for bitsets of different sizes (%zd!=%zd)\n", size(), other.size());
return *this;
}
for (size_t i = 0; i < nof_words_(); ++i) {
@ -210,7 +227,8 @@ public:
bounded_bitset<N, reversed>& operator&=(const bounded_bitset<N, reversed>& other) noexcept
{
if (other.size() != size()) {
printf("ERROR: operator&= called for bitsets of different sizes (%zd!=%zd)\n", size(), other.size());
srslte::logmap::get("COMM")->error(
"ERROR: operator&= called for bitsets of different sizes (%zd!=%zd)\n", size(), other.size());
return *this;
}
for (size_t i = 0; i < nof_words_(); ++i) {
@ -249,7 +267,7 @@ public:
uint64_t to_uint64() const noexcept
{
if (nof_words_() > 1) {
printf("ERROR: cannot convert bitset of size %zd bits to uint64_t\n", size());
srslte::logmap::get("COMM")->error("ERROR: cannot convert bitset of size %zd bits to uint64_t\n", size());
return 0;
}
return get_word_(0);

View File

@ -22,6 +22,7 @@
#ifndef SRSLTE_PDU_H
#define SRSLTE_PDU_H
#include "srslte/common/bounded_bitset.h"
#include "srslte/common/interfaces_common.h"
#include "srslte/common/log.h"
#include <stdint.h>
@ -270,6 +271,7 @@ public:
bool set_bsr(uint32_t buff_size[4], sch_subh::cetype format);
bool set_con_res_id(uint64_t con_res_id);
bool set_ta_cmd(uint8_t ta_cmd);
bool set_scell_activation_cmd(srslte::bounded_bitset<32> active_cc_idxs);
bool set_phr(float phr);
void set_padding();
void set_padding(uint32_t padding_len);

View File

@ -128,9 +128,8 @@ public:
struct ue_cfg_t {
struct cc_cfg_t {
uint32_t enb_cc_idx = 0; ///< eNB CC index
uint32_t periodic_cqi_i = 0; ///< Periodic CQI configuration for this Scell
bool operator==(const cc_cfg_t& c) { return enb_cc_idx == c.enb_cc_idx; }
bool active = false;
uint32_t enb_cc_idx = 0; ///< eNB CC index
};
/* ue capabilities, etc */
uint32_t maxharq_tx = 5;
@ -276,7 +275,8 @@ public:
virtual int ul_sched(uint32_t tti, uint32_t cc_idx, ul_sched_res_t& sched_result) = 0;
/* Custom */
virtual void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0;
virtual void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0;
virtual const ue_cfg_t* get_ue_cfg(uint16_t rnti) = 0;
};
} // namespace srsenb

View File

@ -628,6 +628,24 @@ bool sch_subh::set_ta_cmd(uint8_t ta_cmd)
}
}
bool sch_subh::set_scell_activation_cmd(srslte::bounded_bitset<32> active_cc_idxs)
{
const uint32_t nof_octets = active_cc_idxs.size() <= 8 ? 1 : 4;
if (not((sch_pdu*)parent)->has_space_ce(nof_octets)) {
return false;
}
// first bit is reserved
active_cc_idxs.set(0, false);
uint32_t toencode = (uint32_t)active_cc_idxs.to_uint64();
for (uint32_t i = 0; i < nof_octets; ++i) {
w_payload_ce[i] = (uint8_t)((toencode >> (8u * i)) & 0xffu);
}
lcid = SCELL_ACTIVATION;
((sch_pdu*)parent)->update_space_ce(nof_octets);
nof_bytes = nof_octets;
return true;
}
bool sch_subh::set_next_mch_sched_info(uint8_t lcid_, uint16_t mtch_stop)
{
if (((sch_pdu*)parent)->has_space_ce(2, true)) {

View File

@ -80,8 +80,8 @@ public:
void reset() override;
/* Manages UE scheduling context */
int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg);
int ue_rem(uint16_t rnti);
int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override;
int ue_rem(uint16_t rnti) override;
// Indicates that the PHY config dedicated has been enabled or not
void phy_config_enabled(uint16_t rnti, bool enabled);

View File

@ -162,9 +162,10 @@ public:
/* Custom functions
*/
void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) final;
void tpc_inc(uint16_t rnti);
void tpc_dec(uint16_t rnti);
void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) final;
void tpc_inc(uint16_t rnti);
void tpc_dec(uint16_t rnti);
const ue_cfg_t* get_ue_cfg(uint16_t rnti) final;
// Static Methods
static uint32_t get_rvidx(uint32_t retx_idx)

View File

@ -44,7 +44,10 @@ struct sched_dci_cce_t {
struct sched_ue_carrier {
const static int SCHED_MAX_HARQ_PROC = SRSLTE_FDD_NOF_HARQ;
sched_ue_carrier(const sched_interface::ue_cfg_t& cfg_, const sched_cell_params_t& cell_cfg_, uint16_t rnti_);
sched_ue_carrier(const sched_interface::ue_cfg_t& cfg_,
const sched_cell_params_t& cell_cfg_,
uint16_t rnti_,
uint32_t ue_cc_idx);
void reset();
void set_cfg(const sched_interface::ue_cfg_t& cfg); ///< reconfigure ue carrier
@ -62,6 +65,8 @@ struct sched_ue_carrier {
int alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int* mcs);
uint32_t get_required_prb_ul(uint32_t req_bytes);
const sched_cell_params_t* get_cell_cfg() const { return cell_params; }
bool is_active() const { return active; }
uint32_t get_ue_cc_idx() const { return ue_cc_idx; }
std::array<dl_harq_proc, SCHED_MAX_HARQ_PROC> dl_harq = {};
std::array<ul_harq_proc, SCHED_MAX_HARQ_PROC> ul_harq = {};
@ -83,10 +88,15 @@ struct sched_ue_carrier {
std::array<std::array<sched_dci_cce_t, 10>, 3> dci_locations = {};
private:
// config
srslte::log* log_h = nullptr;
const sched_interface::ue_cfg_t* cfg = nullptr;
const sched_cell_params_t* cell_params = nullptr;
uint16_t rnti;
uint32_t ue_cc_idx = 0;
// state
bool active = false;
};
/** This class is designed to be thread-safe because it is called from workers through scheduler thread and from
@ -131,10 +141,11 @@ public:
void tpc_inc();
void tpc_dec();
dl_harq_proc* find_dl_harq(uint32_t tti_rx, uint32_t cc_idx);
dl_harq_proc* get_dl_harq(uint32_t idx, uint32_t cc_idx);
uint16_t get_rnti() const { return rnti; }
std::pair<bool, uint32_t> get_cell_index(uint32_t enb_cc_idx) const;
dl_harq_proc* find_dl_harq(uint32_t tti_rx, uint32_t cc_idx);
dl_harq_proc* get_dl_harq(uint32_t idx, uint32_t cc_idx);
uint16_t get_rnti() const { return rnti; }
std::pair<bool, uint32_t> get_cell_index(uint32_t enb_cc_idx) const;
const sched_interface::ue_cfg_t& get_ue_cfg() const { return cfg; }
/*******************************************************
* Functions used by scheduler metric objects

View File

@ -70,6 +70,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_)
rrc_cfg = rrc_cfg_;
// setup logging for each layer
srslte::logmap::get_instance()->set_default_logger(logger);
mac_log.init("MAC ", logger, true);
rlc_log.init("RLC ", logger);
pdcp_log.init("PDCP", logger);

View File

@ -195,31 +195,33 @@ void mac::phy_config_enabled(uint16_t rnti, bool enabled)
// Update UE configuration
int mac::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg)
{
int ret = -1;
srslte::rwlock_read_guard lock(rwlock);
if (ue_db.count(rnti) > 0) {
// Add RNTI to the PHY (pregerate signals) now instead of after PRACH
if (!ue_db[rnti]->is_phy_added) {
ue_db[rnti]->is_phy_added = true;
Info("Registering rnti=0x%x to PHY...\n", rnti);
// Register new user in PHY
if (phy_h->add_rnti(rnti, 0, false)) {
Error("Registering new ue rnti=0x%x to PHY\n", rnti);
}
Info("Done registering rnti=0x%x to PHY...\n", rnti);
}
// Update Scheduler configuration
if ((cfg != nullptr) ? (scheduler.ue_cfg(rnti, *cfg) != SRSLTE_SUCCESS) : false) {
Error("Registering new UE rnti=0x%x to SCHED\n", rnti);
} else {
ret = 0;
}
} else {
auto it = ue_db.find(rnti);
ue* ue_ptr = nullptr;
if (it == ue_db.end()) {
Error("User rnti=0x%x not found\n", rnti);
return SRSLTE_ERROR;
}
return ret;
ue_ptr = it->second;
// Add RNTI to the PHY (pregenerate signals) now instead of after PRACH
if (not ue_ptr->is_phy_added) {
ue_ptr->is_phy_added = true;
Info("Registering rnti=0x%x to PHY...\n", rnti);
// Register new user in PHY
if (phy_h->add_rnti(rnti, 0, false) == SRSLTE_ERROR) {
Error("Registering new ue rnti=0x%x to PHY\n", rnti);
}
Info("Done registering rnti=0x%x to PHY...\n", rnti);
}
// Update Scheduler configuration
if (cfg != nullptr and scheduler.ue_cfg(rnti, *cfg) == SRSLTE_ERROR) {
Error("Registering new UE rnti=0x%x to SCHED\n", rnti);
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
// Removes UE from DB
@ -446,10 +448,10 @@ int mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx,
// Add new user to the scheduler so that it can RX/TX SRB0
sched_interface::ue_cfg_t ue_cfg = {};
ue_cfg.supported_cc_list.emplace_back();
ue_cfg.supported_cc_list.back().enb_cc_idx = enb_cc_idx;
ue_cfg.supported_cc_list.back().periodic_cqi_i = 0;
ue_cfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
ue_cfg.dl_cfg.tm = SRSLTE_TM1;
ue_cfg.supported_cc_list.back().active = true;
ue_cfg.supported_cc_list.back().enb_cc_idx = enb_cc_idx;
ue_cfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
ue_cfg.dl_cfg.tm = SRSLTE_TM1;
if (scheduler.ue_cfg(rnti, ue_cfg) != SRSLTE_SUCCESS) {
Error("Registering new user rnti=0x%x to SCHED\n", rnti);
return -1;

View File

@ -366,6 +366,13 @@ void sched::tpc_dec(uint16_t rnti)
ue_db_access(rnti, [](sched_ue& ue) { ue.tpc_dec(); });
}
const sched::ue_cfg_t* sched::get_ue_cfg(uint16_t rnti)
{
const ue_cfg_t* cfg = nullptr;
ue_db_access(rnti, [&cfg](sched_ue& ue) { cfg = &ue.get_ue_cfg(); });
return cfg;
}
/*******************************************************
*
* Main sched functions

View File

@ -55,6 +55,11 @@ uint32_t get_tbs_bytes(uint32_t mcs, uint32_t nof_alloc_prb, bool is_ul)
} // namespace sched_utils
bool operator==(const sched_interface::ue_cfg_t::cc_cfg_t& lhs, const sched_interface::ue_cfg_t::cc_cfg_t& rhs)
{
return lhs.enb_cc_idx == rhs.enb_cc_idx and lhs.active == rhs.active;
}
/*******************************************************
*
* Initialization and configuration functions
@ -94,10 +99,6 @@ void sched_ue::set_cfg(const sched_interface::ue_cfg_t& cfg_)
cell = main_cc_params->cfg.cell;
max_msg3retx = main_cc_params->cfg.maxharq_msg3tx;
}
bool maxharq_tx_changed = cfg.maxharq_tx != cfg_.maxharq_tx;
bool cc_changed =
cfg.supported_cc_list.size() != cfg_.supported_cc_list.size() or
not std::equal(cfg.supported_cc_list.begin(), cfg.supported_cc_list.end(), cfg_.supported_cc_list.begin());
// update configuration
cfg = cfg_;
@ -108,21 +109,23 @@ void sched_ue::set_cfg(const sched_interface::ue_cfg_t& cfg_)
}
// either add a new carrier, or reconfigure existing one
bool scell_activation_state_changed = false;
for (auto& cc_cfg : cfg.supported_cc_list) {
sched_ue_carrier* c = get_ue_carrier(cc_cfg.enb_cc_idx);
if (c == nullptr) {
// add new carrier to sched_ue
carriers.emplace_back(cfg, (*cell_params_list)[cc_cfg.enb_cc_idx], rnti);
carriers.emplace_back(cfg, (*cell_params_list)[cc_cfg.enb_cc_idx], rnti, carriers.size());
scell_activation_state_changed |= carriers.size() > 1 and carriers.back().is_active();
} else {
// reconfiguration of carrier might be needed
if (maxharq_tx_changed) {
c->set_cfg(cfg);
}
// if SCell state changed
scell_activation_state_changed = c->is_active() != cc_cfg.active and c->get_ue_cc_idx() != 0;
// reconfiguration of carrier might be needed.
c->set_cfg(cfg);
}
}
if (cc_changed) {
pending_ces.push_back(ce_cmd{srslte::sch_subh::SCELL_ACTIVATION});
if (scell_activation_state_changed) {
pending_ces.emplace_back(srslte::sch_subh::SCELL_ACTIVATION);
log_h->info("SCHED: Scheduling SCell Activation CMD for rnti=0x%x\n", rnti);
}
}
}
@ -1058,10 +1061,12 @@ int sched_ue::cqi_to_tbs(uint32_t cqi,
sched_ue_carrier::sched_ue_carrier(const sched_interface::ue_cfg_t& cfg_,
const sched_cell_params_t& cell_cfg_,
uint16_t rnti_) :
uint16_t rnti_,
uint32_t ue_cc_idx_) :
cell_params(&cell_cfg_),
rnti(rnti_),
log_h(srslte::logmap::get("MAC "))
log_h(srslte::logmap::get("MAC ")),
ue_cc_idx(ue_cc_idx_)
{
// Init HARQ processes
for (uint32_t i = 0; i < dl_harq.size(); ++i) {
@ -1108,12 +1113,17 @@ void sched_ue_carrier::reset()
void sched_ue_carrier::set_cfg(const sched_interface::ue_cfg_t& cfg_)
{
if (cfg != nullptr and cfg->maxharq_tx == cfg_.maxharq_tx and active == cfg->supported_cc_list[ue_cc_idx].active) {
// nothing changed
return;
}
cfg = &cfg_;
// Config HARQ processes
for (uint32_t i = 0; i < dl_harq.size(); ++i) {
dl_harq[i].set_cfg(cfg->maxharq_tx);
ul_harq[i].set_cfg(cfg->maxharq_tx);
}
active = cfg->supported_cc_list[ue_cc_idx].active;
}
void sched_ue_carrier::reset_old_pending_pids(uint32_t tti_rx)

View File

@ -24,6 +24,7 @@
#include <string.h>
#include "srsenb/hdr/stack/mac/ue.h"
#include "srslte/common/bounded_bitset.h"
#include "srslte/interfaces/enb_interfaces.h"
#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__)
@ -424,6 +425,21 @@ void ue::allocate_ce(srslte::sch_pdu* pdu, uint32_t lcid)
Error("CE: Setting Contention Resolution ID CE. No space for a subheader\n");
}
break;
case srslte::sch_subh::SCELL_ACTIVATION:
if (pdu->new_subh()) {
const sched_interface::ue_cfg_t* sched_cfg = sched->get_ue_cfg(rnti);
srslte::bounded_bitset<32> active_cc_list(sched_cfg->supported_cc_list.size());
for (uint32_t i = 0; i < sched_cfg->supported_cc_list.size(); ++i) {
active_cc_list.set(i, sched_cfg->supported_cc_list[i].active);
}
if (pdu->get()->set_scell_activation_cmd(active_cc_list)) {
Info("CE: Added SCell Activation CE.\n");
} else {
Error("CE: Setting SCell Activation CE\n");
}
} else {
Error("CE: Setting SCell Activation CE. No space for a subheader\n");
}
default:
Error("CE: Allocating CE=0x%x. Not supported\n", lcid);
break;

View File

@ -1251,8 +1251,8 @@ void rrc::ue::handle_rrc_reconf_complete(rrc_conn_recfg_complete_s* msg, srslte:
auto it = std::find_if(list.begin(), list.end(), [i](const cc_cfg_t& u) { return u.enb_cc_idx == i; });
if (it == list.end()) {
list.emplace_back();
list.back().enb_cc_idx = i;
list.back().periodic_cqi_i = 0;
list.back().active = true;
list.back().enb_cc_idx = i;
}
}
parent->mac->ue_cfg(rnti, &current_sched_ue_cfg);