From cb7f620254f65e59699e0207d5b75c5eb9f2839a Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Sat, 27 Jun 2020 16:05:20 +0100 Subject: [PATCH] created separate class to manage bearers buffers/status reports in the scheduler --- .../srslte/interfaces/sched_interface.h | 19 +- srsenb/hdr/stack/mac/scheduler.h | 4 +- srsenb/hdr/stack/mac/scheduler_ue.h | 60 ++-- srsenb/hdr/stack/mac/ue.h | 4 - srsenb/src/stack/mac/mac.cc | 2 - srsenb/src/stack/mac/scheduler.cc | 8 +- srsenb/src/stack/mac/scheduler_ue.cc | 286 +++++++++++------- srsenb/src/stack/mac/ue.cc | 27 +- srsenb/test/mac/scheduler_test_common.cc | 16 +- 9 files changed, 251 insertions(+), 175 deletions(-) diff --git a/lib/include/srslte/interfaces/sched_interface.h b/lib/include/srslte/interfaces/sched_interface.h index 9efb67b83..d53263494 100644 --- a/lib/include/srslte/interfaces/sched_interface.h +++ b/lib/include/srslte/interfaces/sched_interface.h @@ -40,6 +40,7 @@ public: const static int MAX_SIB_PAYLOAD_LEN = 2048; const static int MAX_SIBS = 16; const static int MAX_LC = 6; + const static int MAX_LC_GROUP = 4; const static int MAX_DATA_LIST = 32; const static int MAX_RAR_LIST = 8; const static int MAX_BC_LIST = 8; @@ -104,11 +105,11 @@ public: }; struct ue_bearer_cfg_t { - int priority = 0; - int bsd = 0; - int pbr = 0; - int group = 0; - enum { IDLE = 0, UL, DL, BOTH } direction = IDLE; + int priority = 0; + int bsd = 0; + int pbr = 0; + int group = 0; + enum direction_t { IDLE = 0, UL, DL, BOTH } direction = IDLE; }; struct ant_info_ded_t { @@ -286,8 +287,7 @@ public: /* UL information */ 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 lcid, uint32_t bsr, bool set_value = true) = 0; - virtual int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) = 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_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code) = 0; @@ -296,8 +296,9 @@ public: virtual int ul_sched(uint32_t tti, uint32_t enb_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 std::array get_enb_ue_cc_map(uint16_t rnti) = 0; + virtual void set_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0; + virtual std::array get_enb_ue_cc_map(uint16_t rnti) = 0; + virtual int ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/scheduler.h b/srsenb/hdr/stack/mac/scheduler.h index 4427ebe44..1ac14646a 100644 --- a/srsenb/hdr/stack/mac/scheduler.h +++ b/srsenb/hdr/stack/mac/scheduler.h @@ -120,8 +120,7 @@ public: int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) final; 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 lcid, uint32_t bsr, bool set_value = true) final; - int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) final; + 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_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code) final; @@ -134,6 +133,7 @@ public: void tpc_inc(uint16_t rnti); void tpc_dec(uint16_t rnti); std::array get_enb_ue_cc_map(uint16_t rnti) final; + int ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) final; class carrier_sched; diff --git a/srsenb/hdr/stack/mac/scheduler_ue.h b/srsenb/hdr/stack/mac/scheduler_ue.h index d70c302f7..af4cd31e6 100644 --- a/srsenb/hdr/stack/mac/scheduler_ue.h +++ b/srsenb/hdr/stack/mac/scheduler_ue.h @@ -82,6 +82,45 @@ private: bool active = false; }; +const char* to_string(sched_interface::ue_bearer_cfg_t::direction_t dir); + +class lch_manager +{ +public: + void set_cfg(const sched_interface::ue_cfg_t& cfg_); + void config_lcid(uint32_t lcg_id, const sched_interface::ue_bearer_cfg_t& bearer_cfg); + void ul_bsr(uint8_t lcg_id, uint32_t bsr); + void ul_buffer_add(uint8_t lcid, uint32_t bytes); + // void ul_recv(uint8_t lcg_id, uint32_t len); + void dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue); + + bool alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* lcid, int rem_bytes); + + bool is_bearer_active(uint32_t lcid) const; + bool is_bearer_ul(uint32_t lcid) const; + bool is_bearer_dl(uint32_t lcid) const; + + int get_dl_tx(uint32_t lcid) const; + int get_dl_retx(uint32_t lcid) const; + int get_bsr(uint32_t lcid) const; + + std::string get_bsr_text() const; + +private: + struct ue_bearer_t { + sched_interface::ue_bearer_cfg_t cfg = {}; + int buf_tx = 0; + int buf_retx = 0; + }; + + int alloc_retx_bytes(uint8_t lcid, uint32_t rem_bytes); + int alloc_tx_bytes(uint8_t lcid, uint32_t rem_bytes); + + srslte::log_ref log_h{"MAC"}; + std::array lch = {}; + std::array lcg_bsr = {}; +}; + /** This class is designed to be thread-safe because it is called from workers through scheduler thread and from * higher layers and mac threads. */ @@ -103,10 +142,9 @@ public: void rem_bearer(uint32_t lc_id); void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue); - void ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value = true); + void ul_buffer_state(uint8_t lcg_id, uint32_t bsr); void ul_phr(int phr); void mac_buffer_state(uint32_t ce_code, uint32_t nof_cmds); - void ul_recv_len(uint32_t lcid, uint32_t len); void set_ul_cqi(uint32_t tti, uint32_t enb_cc_idx, uint32_t cqi, uint32_t ul_ch_code); void set_dl_ri(uint32_t tti, uint32_t enb_cc_idx, uint32_t ri); @@ -127,6 +165,7 @@ public: std::pair get_cell_index(uint32_t enb_cc_idx) const; const sched_interface::ue_cfg_t& get_ue_cfg() const { return cfg; } uint32_t get_aggr_level(uint32_t ue_cc_idx, uint32_t nof_bits); + void ul_buffer_add(uint8_t lcid, uint32_t bytes); /******************************************************* * Functions used by scheduler metric objects @@ -191,18 +230,8 @@ public: uint32_t* mcs); private: - struct ue_bearer_t { - sched_interface::ue_bearer_cfg_t cfg = {}; - int buf_tx = 0; - int buf_retx = 0; - int bsr = 0; - }; - - void set_bearer_cfg_unlocked(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg_); - bool is_sr_triggered(); - int alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* mac_sdu, int rem_tbs); uint32_t allocate_mac_sdus(sched_interface::dl_sched_data_t* data, uint32_t total_tbs, uint32_t tbidx); uint32_t allocate_mac_ces(sched_interface::dl_sched_data_t* data, uint32_t total_tbs, uint32_t ue_cc_idx); std::pair allocate_new_dl_mac_pdu(sched_interface::dl_sched_data_t* data, @@ -220,9 +249,6 @@ private: uint32_t cfi, const srslte_dci_dl_t& dci); - static bool bearer_is_ul(const ue_bearer_t* lch); - static bool bearer_is_dl(const ue_bearer_t* lch); - uint32_t get_pending_ul_old_data_unlocked(uint32_t cc_idx); uint32_t get_pending_ul_new_data_unlocked(uint32_t tti); @@ -255,8 +281,8 @@ private: const sched_cell_params_t* main_cc_params = nullptr; /* Buffer states */ - bool sr = false; - std::array lch = {}; + bool sr = false; + lch_manager lch_handler; int power_headroom = 0; uint32_t cqi_request_tti = 0; diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index e8874f756..cbedc5e10 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -84,8 +84,6 @@ public: void push_pdu(const uint32_t ue_cc_idx, const uint32_t tti, uint32_t len); void deallocate_pdu(const uint32_t ue_cc_idx, const uint32_t tti); - void set_lcg(uint32_t lcid, uint32_t lcg); - void metrics_read(srsenb::mac_metrics_t* metrics); void metrics_rx(bool crc, uint32_t tbs); void metrics_tx(bool crc, uint32_t tbs); @@ -105,8 +103,6 @@ private: bool process_ce(srslte::sch_subh* subh); void allocate_ce(srslte::sch_pdu* pdu, uint32_t lcid); - std::vector lc_groups[4]; - uint32_t phr_counter = 0; uint32_t dl_cqi_counter = 0; uint32_t dl_ri_counter = 0; diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 9de4c39c3..28ac3f896 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -165,8 +165,6 @@ int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer int ret = -1; srslte::rwlock_read_guard lock(rwlock); if (ue_db.count(rnti)) { - // configure BSR group in UE - ue_db[rnti]->set_lcg(lc_id, (uint32_t)cfg->group); ret = scheduler.bearer_ue_cfg(rnti, lc_id, cfg); } else { Error("User rnti=0x%x not found\n", rnti); diff --git a/srsenb/src/stack/mac/scheduler.cc b/srsenb/src/stack/mac/scheduler.cc index e96c39354..9b4ab21ce 100644 --- a/srsenb/src/stack/mac/scheduler.cc +++ b/srsenb/src/stack/mac/scheduler.cc @@ -315,14 +315,14 @@ int sched::ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_ return ue_db_access(rnti, [&](sched_ue& ue) { ue.set_ul_cqi(tti, enb_cc_idx, cqi, ul_ch_code); }); } -int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value) +int sched::ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) { - return ue_db_access(rnti, [lcid, bsr, set_value](sched_ue& ue) { ue.ul_buffer_state(lcid, bsr, set_value); }); + return ue_db_access(rnti, [lcg_id, bsr](sched_ue& ue) { ue.ul_buffer_state(lcg_id, bsr); }); } -int sched::ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) +int sched::ul_buffer_add(uint16_t rnti, uint32_t lcid, uint32_t bytes) { - return ue_db_access(rnti, [lcid, len](sched_ue& ue) { ue.ul_recv_len(lcid, len); }, __PRETTY_FUNCTION__); + return ue_db_access(rnti, [lcid, bytes](sched_ue& ue) { ue.ul_buffer_add(lcid, bytes); }); } int sched::ul_phr(uint16_t rnti, int phr) diff --git a/srsenb/src/stack/mac/scheduler_ue.cc b/srsenb/src/stack/mac/scheduler_ue.cc index 78baaeef1..4165ad2e3 100644 --- a/srsenb/src/stack/mac/scheduler_ue.cc +++ b/srsenb/src/stack/mac/scheduler_ue.cc @@ -124,9 +124,7 @@ void sched_ue::set_cfg(const sched_interface::ue_cfg_t& cfg_) cfg = cfg_; // update bearer cfgs - for (uint32_t i = 0; i < sched_interface::MAX_LC; ++i) { - set_bearer_cfg_unlocked(i, cfg.ue_bearers[i]); - } + lch_handler.set_cfg(cfg_); // either add a new carrier, or reconfigure existing one bool scell_activation_state_changed = false; @@ -166,7 +164,7 @@ void sched_ue::reset() // erase all bearers for (uint32_t i = 0; i < cfg.ue_bearers.size(); ++i) { - set_bearer_cfg_unlocked(i, {}); + lch_handler.config_lcid(i, {}); } } @@ -179,13 +177,13 @@ void sched_ue::reset() void sched_ue::set_bearer_cfg(uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg_) { cfg.ue_bearers[lc_id] = *cfg_; - set_bearer_cfg_unlocked(lc_id, *cfg_); + lch_handler.config_lcid(lc_id, *cfg_); } void sched_ue::rem_bearer(uint32_t lc_id) { cfg.ue_bearers[lc_id] = sched_interface::ue_bearer_cfg_t{}; - set_bearer_cfg_unlocked(lc_id, sched_interface::ue_bearer_cfg_t{}); + lch_handler.config_lcid(lc_id, sched_interface::ue_bearer_cfg_t{}); } void sched_ue::phy_config_enabled(uint32_t tti, bool enabled) @@ -196,16 +194,14 @@ void sched_ue::phy_config_enabled(uint32_t tti, bool enabled) phy_config_dedicated_enabled = enabled; } -void sched_ue::ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value) +void sched_ue::ul_buffer_state(uint8_t lcg_id, uint32_t bsr) { - if (lc_id < sched_interface::MAX_LC) { - if (set_value) { - lch[lc_id].bsr = bsr; - } else { - lch[lc_id].bsr += bsr; - } - } - Debug("SCHED: bsr=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", bsr, lc_id, lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr); + lch_handler.ul_bsr(lcg_id, bsr); +} + +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) @@ -215,11 +211,7 @@ void sched_ue::ul_phr(int phr) void sched_ue::dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue) { - if (lc_id < sched_interface::MAX_LC) { - lch[lc_id].buf_retx = retx_queue; - lch[lc_id].buf_tx = tx_queue; - Debug("SCHED: DL lcid=%d buffer_state=%d,%d\n", lc_id, tx_queue, retx_queue); - } + lch_handler.dl_buffer_state(lc_id, tx_queue, retx_queue); } void sched_ue::mac_buffer_state(uint32_t ce_code, uint32_t nof_cmds) @@ -274,24 +266,6 @@ int sched_ue::set_ack_info(uint32_t tti_rx, uint32_t enb_cc_idx, uint32_t tb_idx return tbs_acked; } -void sched_ue::ul_recv_len(uint32_t lcid, uint32_t len) -{ - // Remove PDCP header?? - if (len > 4) { - len -= 4; - } - if (lcid < sched_interface::MAX_LC) { - if (bearer_is_ul(&lch[lcid])) { - if (lch[lcid].bsr > (int)len) { - lch[lcid].bsr -= len; - } else { - lch[lcid].bsr = 0; - } - } - } - Debug("SCHED: recv_len=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", len, lcid, lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr); -} - void sched_ue::set_ul_crc(srslte::tti_point tti_rx, uint32_t enb_cc_idx, bool crc_res) { auto p = get_cell_index(enb_cc_idx); @@ -388,7 +362,7 @@ uint32_t sched_ue::allocate_mac_sdus(sched_interface::dl_sched_data_t* data, uin // 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_rlc_pdu(&data->pdu[tbidx][data->nof_pdu_elems[tbidx]], max_sdu_bytes); + uint32_t alloc_sdu_bytes = lch_handler.alloc_rlc_pdu(&data->pdu[tbidx][data->nof_pdu_elems[tbidx]], max_sdu_bytes); if (alloc_sdu_bytes == 0) { break; } @@ -764,18 +738,6 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, * *******************************************************/ -bool sched_ue::bearer_is_ul(const ue_bearer_t* lch) -{ - return lch->cfg.direction == sched_interface::ue_bearer_cfg_t::UL || - lch->cfg.direction == sched_interface::ue_bearer_cfg_t::BOTH; -} - -bool sched_ue::bearer_is_dl(const ue_bearer_t* lch) -{ - return lch->cfg.direction == sched_interface::ue_bearer_cfg_t::DL || - lch->cfg.direction == sched_interface::ue_bearer_cfg_t::BOTH; -} - uint32_t sched_ue::get_max_retx() { return cfg.maxharq_tx; @@ -878,7 +840,7 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id /* Set Maximum boundary */ // Ensure there is space for ConRes and RRC Setup // SRB0 is a special case due to being RLC TM (no segmentation possible) - if (not bearer_is_dl(&lch[0])) { + if (not lch_handler.is_bearer_dl(0)) { log_h->error("SRB0 must always be activated for DL\n"); return {0, 0}; } @@ -889,9 +851,9 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id uint32_t max_data = 0, min_data = 0; uint32_t srb0_data = 0, rb_data = 0, sum_ce_data = 0; bool is_dci_format1 = get_dci_format() == SRSLTE_DCI_FORMAT1; - if (is_dci_format1 and (lch[0].buf_tx > 0 or lch[0].buf_retx > 0)) { - srb0_data = compute_sdu_total_bytes(0, lch[0].buf_retx); - srb0_data += compute_sdu_total_bytes(0, lch[0].buf_tx); + if (is_dci_format1) { + srb0_data += compute_sdu_total_bytes(0, lch_handler.get_dl_retx(0)); + srb0_data += compute_sdu_total_bytes(0, lch_handler.get_dl_tx(0)); } // Add pending CEs if (ue_cc_idx == 0) { @@ -905,9 +867,9 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id } // Add pending data in remaining RLC buffers for (int i = 1; i < sched_interface::MAX_LC; i++) { - if (bearer_is_dl(&lch[i])) { - rb_data += compute_sdu_total_bytes(i, lch[i].buf_retx); - rb_data += compute_sdu_total_bytes(i, lch[i].buf_tx); + if (lch_handler.is_bearer_dl(i)) { + rb_data += compute_sdu_total_bytes(i, lch_handler.get_dl_retx(i)); + rb_data += compute_sdu_total_bytes(i, lch_handler.get_dl_tx(i)); } } max_data = srb0_data + sum_ce_data + rb_data; @@ -940,8 +902,8 @@ uint32_t sched_ue::get_pending_dl_new_data() uint32_t pending_data = 0; for (int i = 0; i < sched_interface::MAX_LC; i++) { - if (bearer_is_dl(&lch[i])) { - pending_data += lch[i].buf_retx + lch[i].buf_tx; + if (lch_handler.is_bearer_dl(i)) { + pending_data += lch_handler.get_dl_tx(i) + lch_handler.get_dl_retx(i); } } for (auto& ce : pending_ces) { @@ -966,9 +928,9 @@ uint32_t sched_ue::get_pending_ul_new_data_unlocked(uint32_t tti) // Note: If there are no active bearers, scheduling requests are also ignored. uint32_t pending_data = 0; bool ul_bearers_found = false; - for (int i = 0; i < sched_interface::MAX_LC; i++) { - if (bearer_is_ul(&lch[i])) { - pending_data += lch[i].bsr; + for (int i = 0; i < sched_interface::MAX_LC_GROUP; i++) { + if (lch_handler.is_bearer_ul(i)) { + pending_data += lch_handler.get_bsr(i); ul_bearers_found = true; } } @@ -991,13 +953,10 @@ uint32_t sched_ue::get_pending_ul_new_data_unlocked(uint32_t tti) pending_data = (pending_data > pending_ul_data) ? pending_data - pending_ul_data : 0; if (pending_data > 0) { - Debug("SCHED: pending_data=%d, pending_ul_data=%d, bsr={%d,%d,%d,%d}\n", + Debug("SCHED: pending_data=%d, pending_ul_data=%d, bsr=%s\n", pending_data, pending_ul_data, - lch[0].bsr, - lch[1].bsr, - lch[2].bsr, - lch[3].bsr); + lch_handler.get_bsr_text().c_str()); } return pending_data; } @@ -1017,22 +976,6 @@ uint32_t sched_ue::get_required_prb_ul(uint32_t cc_idx, uint32_t req_bytes) return carriers[cc_idx].get_required_prb_ul(req_bytes); } -void sched_ue::set_bearer_cfg_unlocked(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& cfg_) -{ - if (lc_id < sched_interface::MAX_LC) { - bool is_idle = lch[lc_id].cfg.direction == sched_interface::ue_bearer_cfg_t::IDLE; - bool is_equal = memcmp(&cfg_, &lch[lc_id].cfg, sizeof(cfg_)) == 0; - lch[lc_id].cfg = cfg_; - if (lch[lc_id].cfg.direction != sched_interface::ue_bearer_cfg_t::IDLE) { - if (not is_equal) { - Info("SCHED: Set bearer config lc_id=%d, direction=%d\n", lc_id, (int)lch[lc_id].cfg.direction); - } - } else if (not is_idle) { - Info("SCHED: Removed bearer config lc_id=%d, direction=%d\n", lc_id, (int)lch[lc_id].cfg.direction); - } - } -} - bool sched_ue::is_sr_triggered() { return sr; @@ -1146,29 +1089,6 @@ cc_sched_ue* sched_ue::get_ue_carrier(uint32_t enb_cc_idx) return &carriers[p.second]; } -/* Allocates first available RLC PDU */ -int sched_ue::alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* mac_sdu, int rem_tbs) -{ - // TODO: Implement lcid priority (now lowest index is lowest priority) - 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 (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 alloc_bytes; -} - int sched_ue::cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, @@ -1411,4 +1331,156 @@ void cc_sched_ue::set_dl_cqi(uint32_t tti_tx_dl, uint32_t dl_cqi_) } } +/******************************************************* + * + * Logical Channel Management + * + *******************************************************/ + +const char* to_string(sched_interface::ue_bearer_cfg_t::direction_t dir) +{ + switch (dir) { + case sched_interface::ue_bearer_cfg_t::IDLE: + return "idle"; + case sched_interface::ue_bearer_cfg_t::BOTH: + return "bi-dir"; + case sched_interface::ue_bearer_cfg_t::DL: + return "DL"; + case sched_interface::ue_bearer_cfg_t::UL: + return "UL"; + default: + return "unrecognized direction"; + } +} + +void lch_manager::set_cfg(const sched_interface::ue_cfg_t& cfg) +{ + for (uint32_t lcid = 0; lcid < sched_interface::MAX_LC; lcid++) { + config_lcid(lcid, cfg.ue_bearers[lcid]); + } +} + +void lch_manager::config_lcid(uint32_t lc_id, const sched_interface::ue_bearer_cfg_t& bearer_cfg) +{ + if (lc_id >= sched_interface::MAX_LC) { + Warning("Adding bearer with invalid logical channel id=%d\n", lc_id); + return; + } + if (bearer_cfg.group >= sched_interface::MAX_LC_GROUP) { + Warning("Adding bearer with invalid logical channel group id=%d\n", bearer_cfg.group); + return; + } + + // update bearer config + bool is_equal = memcmp(&bearer_cfg, &lch[lc_id].cfg, sizeof(bearer_cfg)) == 0; + + if (not is_equal) { + lch[lc_id].cfg = bearer_cfg; + Info("SCHED: bearer configured: lc_id=%d, mode=%s, prio=%d\n", + lc_id, + to_string(lch[lc_id].cfg.direction), + lch[lc_id].cfg.priority); + } +} + +void lch_manager::ul_bsr(uint8_t lcg_id, uint32_t bsr) +{ + if (lcg_id >= sched_interface::MAX_LC_GROUP) { + Warning("The provided logical channel group id=%d is not valid\n", lcg_id); + return; + } + lcg_bsr[lcg_id] = bsr; + Debug("SCHED: bsr=%d, lcg_id=%d, bsr=%s\n", bsr, lcg_id, get_bsr_text().c_str()); +} + +void lch_manager::ul_buffer_add(uint8_t lcid, uint32_t bytes) +{ + if (lcid >= sched_interface::MAX_LC) { + Warning("The provided lcid=%d is not valid\n", lcid); + return; + } + lcg_bsr[lch[lcid].cfg.group] += bytes; + Debug("SCHED: UL buffer update=%d, lcg_id=%d, bsr=%s\n", bytes, lch[lcid].cfg.group, get_bsr_text().c_str()); +} + +void lch_manager::dl_buffer_state(uint8_t lcid, uint32_t tx_queue, uint32_t retx_queue) +{ + if (lcid >= sched_interface::MAX_LC) { + Warning("The provided lcid=%d is not valid\n", lcid); + return; + } + lch[lcid].buf_retx = retx_queue; + lch[lcid].buf_tx = tx_queue; + Debug("SCHED: DL lcid=%d buffer_state=%d,%d\n", lcid, tx_queue, retx_queue); +} + +/* Allocates first available RLC PDU */ +bool lch_manager::alloc_rlc_pdu(sched_interface::dl_sched_pdu_t* rlc_pdu, int rem_bytes) +{ + // TODO: Implement lcid priority (now lowest index is lowest priority) + int alloc_bytes = 0; + int i = 0; + for (i = 0; i < sched_interface::MAX_LC and alloc_bytes == 0; i++) { + alloc_bytes = alloc_retx_bytes(i, rem_bytes); + if (alloc_bytes == 0) { + alloc_bytes = alloc_tx_bytes(i, rem_bytes); + } + } + if (alloc_bytes > 0) { + rlc_pdu->nbytes = alloc_bytes; + rlc_pdu->lcid = i - 1; + Debug("SCHED: Allocated lcid=%d, nbytes=%d, tbs_bytes=%d\n", rlc_pdu->lcid, rlc_pdu->nbytes, rem_bytes); + } + return alloc_bytes > 0; +} + +int lch_manager::alloc_retx_bytes(uint8_t lcid, uint32_t rem_bytes) +{ + int alloc = std::min((int)rem_bytes, get_dl_retx(lcid)); + lch[lcid].buf_retx -= alloc; + return alloc; +} + +int lch_manager::alloc_tx_bytes(uint8_t lcid, uint32_t rem_bytes) +{ + int alloc = std::min((int)rem_bytes, get_dl_tx(lcid)); + lch[lcid].buf_tx -= alloc; + return alloc; +} + +bool lch_manager::is_bearer_active(uint32_t lcid) const +{ + return lch[lcid].cfg.direction != sched_interface::ue_bearer_cfg_t::IDLE; +} + +bool lch_manager::is_bearer_ul(uint32_t lcid) const +{ + return is_bearer_active(lcid) and lch[lcid].cfg.direction != sched_interface::ue_bearer_cfg_t::DL; +} + +bool lch_manager::is_bearer_dl(uint32_t lcid) const +{ + return is_bearer_active(lcid) and lch[lcid].cfg.direction != sched_interface::ue_bearer_cfg_t::UL; +} + +int lch_manager::get_dl_tx(uint32_t lcid) const +{ + return is_bearer_dl(lcid) ? lch[lcid].buf_tx : 0; +} +int lch_manager::get_dl_retx(uint32_t lcid) const +{ + return is_bearer_dl(lcid) ? lch[lcid].buf_retx : 0; +} +int lch_manager::get_bsr(uint32_t lcid) const +{ + return is_bearer_ul(lcid) ? lcg_bsr[lch[lcid].cfg.group] : 0; +} + +std::string lch_manager::get_bsr_text() const +{ + std::stringstream ss; + ss << "{" << lcg_bsr[0] << ", " << lcg_bsr[1] << ", " << lcg_bsr[2] << ", " << lcg_bsr[3] << "}"; + return ss.str(); +} + } // namespace srsenb diff --git a/srsenb/src/stack/mac/ue.cc b/srsenb/src/stack/mac/ue.cc index 5367fb6e3..493450daf 100644 --- a/srsenb/src/stack/mac/ue.cc +++ b/srsenb/src/stack/mac/ue.cc @@ -69,10 +69,6 @@ ue::ue(uint16_t rnti_, // Allocate buffer for PCell allocate_cc_buffers(); - - // Set LCID group for SRB0 and SRB1 - set_lcg(0, 0); - set_lcg(1, 0); } ue::~ue() @@ -158,15 +154,6 @@ void ue::start_pcap(srslte::mac_pcap* pcap_) pcap = pcap_; } -void ue::set_lcg(uint32_t lcid, uint32_t lcg) -{ - // find and remove if already exists - for (int i = 0; i < 4; i++) { - lc_groups[lcg].erase(std::remove(lc_groups[lcg].begin(), lc_groups[lcg].end(), lcid), lc_groups[lcg].end()); - } - lc_groups[lcg].push_back(lcid); -} - srslte_softbuffer_rx_t* ue::get_rx_softbuffer(const uint32_t ue_cc_idx, const uint32_t tti) { return &softbuffer_rx.at(ue_cc_idx).at(tti % nof_rx_harq_proc); @@ -315,7 +302,7 @@ void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srslte::pdu_queue::channe // If BSR is not received means that new data has arrived and there is no space for BSR transmission if (!bsr_received && lcid_most_data > 2) { // Add BSR to the LCID for which most data was received - sched->ul_bsr(rnti, lcid_most_data, 256, false); // false adds BSR instead of setting + sched->ul_buffer_add(rnti, lcid_most_data, 256); Debug("BSR not received. Giving extra dci\n"); } @@ -374,10 +361,8 @@ bool ue::process_ce(srslte::sch_subh* subh) Error("Invalid Index Passed to lc groups\n"); break; } - for (uint32_t i = 0; i < lc_groups[idx].size(); i++) { - // Indicate BSR to scheduler - sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]); - } + // Indicate BSR to scheduler + sched->ul_bsr(rnti, idx, buff_size[idx]); Info("CE: Received %s BSR rnti=0x%x, lcg=%d, value=%d\n", subh->ul_sch_ce_type() == srslte::ul_sch_lcid::SHORT_BSR ? "Short" : "Trunc", rnti, @@ -387,11 +372,7 @@ bool ue::process_ce(srslte::sch_subh* subh) break; case srslte::ul_sch_lcid::LONG_BSR: subh->get_bsr(buff_size); - for (idx = 0; idx < 4; idx++) { - for (uint32_t i = 0; i < lc_groups[idx].size(); i++) { - sched->ul_bsr(rnti, lc_groups[idx][i], buff_size[idx]); - } - } + sched->ul_bsr(rnti, idx, buff_size[idx]); is_bsr = true; Info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", rnti, diff --git a/srsenb/test/mac/scheduler_test_common.cc b/srsenb/test/mac/scheduler_test_common.cc index d3c98139c..6861c3667 100644 --- a/srsenb/test/mac/scheduler_test_common.cc +++ b/srsenb/test/mac/scheduler_test_common.cc @@ -21,6 +21,7 @@ #include "scheduler_test_common.h" #include "srsenb/hdr/stack/mac/scheduler.h" +#include "srsenb/hdr/stack/upper/common_enb.h" #include "srslte/mac/pdu.h" #include "srslte/common/test_common.h" @@ -981,7 +982,7 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) // Msg3 has been received but Msg4 has not been yet transmitted uint32_t pending_dl_new_data = ue_db[ue_ev.rnti].get_pending_dl_new_data(); if (pending_dl_new_data == 0) { - uint32_t lcid = 0; // Use SRB0 to schedule Msg4 + uint32_t lcid = RB_ID_SRB0; // Use SRB0 to schedule Msg4 dl_rlc_buffer_state(ue_ev.rnti, lcid, 50, 0); dl_mac_buffer_state(ue_ev.rnti, (uint32_t)srslte::dl_sch_lcid::CON_RES_ID); } else { @@ -994,16 +995,17 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) CONDERROR(user == nullptr, "TESTER ERROR: Trying to schedule data for user that does not exist\n"); if (ue_ev.buffer_ev->dl_data > 0 and user->msg4_tti.is_valid()) { // If Msg4 has already been tx and there DL data to transmit - uint32_t lcid = 2; + uint32_t lcid = RB_ID_DRB1; uint32_t pending_dl_new_data = ue_db[ue_ev.rnti].get_pending_dl_new_data(); if (user->drb_cfg_flag or pending_dl_new_data == 0) { // If RRCSetup finished if (not user->drb_cfg_flag) { - // setup lcid==2 bearer + // setup lcid==drb1 bearer sched::ue_bearer_cfg_t cfg = {}; cfg.direction = ue_bearer_cfg_t::BOTH; - ue_tester->bearer_cfg(ue_ev.rnti, 2, cfg); - bearer_ue_cfg(ue_ev.rnti, 2, &cfg); + cfg.group = 1; + ue_tester->bearer_cfg(ue_ev.rnti, lcid, cfg); + bearer_ue_cfg(ue_ev.rnti, lcid, &cfg); } // DRB is set. Update DL buffer uint32_t tot_dl_data = pending_dl_new_data + ue_ev.buffer_ev->dl_data; // TODO: derive pending based on rx @@ -1016,8 +1018,8 @@ int common_sched_tester::process_tti_events(const tti_ev& tti_ev) if (ue_ev.buffer_ev->sr_data > 0 and user->drb_cfg_flag) { uint32_t tot_ul_data = ue_db[ue_ev.rnti].get_pending_ul_new_data(tti_info.tti_params.tti_tx_ul) + ue_ev.buffer_ev->sr_data; - uint32_t lcid = 2; - ul_bsr(ue_ev.rnti, lcid, tot_ul_data, true); + uint32_t lcg = 1; + ul_bsr(ue_ev.rnti, lcg, tot_ul_data); } } }