diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index ceee7fea4..acb12679f 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -382,7 +382,7 @@ public: virtual bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) = 0; ///< Provide packed SIB to MAC (buffer is managed by RRC) - virtual uint8_t* read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index) = 0; + virtual uint8_t* read_pdu_bcch_dlsch(const uint8_t enb_cc_idx, const uint32_t sib_index) = 0; }; // SCell configuration diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index 617de5b95..c1cf15304 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -54,15 +54,15 @@ public: /******** Interface from PHY (PHY -> MAC) ****************/ int sr_detected(uint32_t tti, uint16_t rnti) final; - void rach_detected(uint32_t tti, uint32_t primary_cc_idx, uint32_t preamble_idx, uint32_t time_adv) final; + void rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx, uint32_t time_adv) final; - int ri_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t ri_value) override; - int pmi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t pmi_value) override; - int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) override; - int snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr) override; + int ri_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ri_value) override; + int pmi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t pmi_value) override; + int cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) override; + int snr_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, float snr) override; int ta_info(uint32_t tti, uint16_t rnti, float ta_us) override; - int ack_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t tb_idx, bool ack) override; - int crc_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc_res) 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 get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override; int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override; diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 89ec74492..170e000b6 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -70,14 +70,14 @@ public: uint8_t* generate_mch_pdu(uint32_t harq_pid, sched_interface::dl_pdu_mch_t sched, uint32_t nof_pdu_elems, uint32_t grant_size); - srslte_softbuffer_tx_t* get_tx_softbuffer(uint32_t harq_process, uint32_t tb_idx); - srslte_softbuffer_rx_t* get_rx_softbuffer(uint32_t tti); + srslte_softbuffer_tx_t* get_tx_softbuffer(const uint32_t cc_idx, const uint32_t harq_process, const uint32_t tb_idx); + srslte_softbuffer_rx_t* get_rx_softbuffer(const uint32_t cc_idx, const uint32_t tti); bool process_pdus(); - uint8_t* request_buffer(uint32_t tti, uint32_t len); + uint8_t* request_buffer(const uint32_t ue_cc_idx, const uint32_t tti, const uint32_t len); void process_pdu(uint8_t* pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel); - void push_pdu(uint32_t tti, uint32_t len); - void deallocate_pdu(uint32_t tti); + 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); uint32_t rl_failure(); void rl_failure_reset(); @@ -96,6 +96,8 @@ public: int read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes); private: + uint32_t allocate_cc_buffers(const uint32_t num_cc = 1); ///< Add and initialize softbuffers for CC + void allocate_sdu(srslte::sch_pdu* pdu, uint32_t lcid, uint32_t sdu_len); bool process_ce(srslte::sch_subh* subh); void allocate_ce(srslte::sch_pdu* pdu, uint32_t lcid); @@ -106,29 +108,33 @@ private: uint32_t dl_cqi_counter = 0; uint32_t dl_ri_counter = 0; uint32_t dl_pmi_counter = 0; - mac_metrics_t metrics; + mac_metrics_t metrics = {}; - srslte::mac_pcap* pcap = nullptr; + srslte::mac_pcap* pcap = nullptr; + uint64_t conres_id = 0; + uint16_t rnti = 0; + uint32_t nof_prb = 0; + uint32_t last_tti = 0; + uint32_t nof_failures = 0; + int nof_rx_harq_proc = 0; + int nof_tx_harq_proc = 0; - uint64_t conres_id = 0; + typedef std::vector + cc_softbuffer_tx_list_t; ///< List of Tx softbuffers for all HARQ processes of one carrier + std::vector softbuffer_tx; ///< List of softbuffer lists for Tx - uint16_t rnti = 0; + typedef std::vector + cc_softbuffer_rx_list_t; ///< List of Rx softbuffers for all HARQ processes of one carrier + std::vector softbuffer_rx; ///< List of softbuffer lists for Rx - uint32_t last_tti = 0; - - uint32_t nof_failures = 0; - - srslte::block_queue pending_ta_commands; - - int nof_rx_harq_proc = 0; - int nof_tx_harq_proc = 0; - std::vector softbuffer_tx; - std::vector softbuffer_rx; - std::vector pending_buffers; + typedef std::vector cc_buffer_ptr_t; ///< List of buffer pointers for RX HARQ processes of one carrier + std::vector pending_buffers; ///< List of buffer pointer list for Rx // For DL there are two buffers, one for each Transport block srslte::byte_buffer_t tx_payload_buffer[SRSLTE_FDD_NOF_HARQ][SRSLTE_MAX_TB]; + srslte::block_queue pending_ta_commands; + // For UL there are multiple buffers per PID and are managed by pdu_queue srslte::pdu_queue pdus; srslte::sch_pdu mac_msg_dl, mac_msg_ul; @@ -142,7 +148,7 @@ private: bool conres_id_available = false; // Mutexes - pthread_mutex_t mutex; + std::mutex mutex; const uint8_t UL_CC_IDX = 0; ///< Passed to write CC index in PCAP (TODO: use actual CC idx) }; diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 6e07cdf45..58c8f2100 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -295,106 +295,118 @@ void mac::rl_ok(uint16_t rnti) } } -int mac::ack_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t tb_idx, bool ack) +int mac::ack_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) { srslte::rwlock_read_guard lock(rwlock); log_h->step(tti); - uint32_t nof_bytes = scheduler.dl_ack_info(tti, rnti, cc_idx, tb_idx, ack); - ue_db[rnti]->metrics_tx(ack, nof_bytes); + if (ue_db.count(rnti)) { + uint32_t nof_bytes = scheduler.dl_ack_info(tti, rnti, enb_cc_idx, tb_idx, ack); + ue_db[rnti]->metrics_tx(ack, nof_bytes); - if (ack) { - if (nof_bytes > 64) { // do not count RLC status messages only - rrc_h->set_activity_user(rnti); - log_h->debug("DL activity rnti=0x%x, n_bytes=%d\n", rnti, nof_bytes); + if (ack) { + if (nof_bytes > 64) { // do not count RLC status messages only + rrc_h->set_activity_user(rnti); + log_h->debug("DL activity rnti=0x%x, n_bytes=%d\n", rnti, nof_bytes); + } } } - return 0; + return SRSLTE_SUCCESS; } -int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc) +int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t nof_bytes, bool crc) { + int ret = SRSLTE_ERROR; log_h->step(tti); - int ret = -1; srslte::rwlock_read_guard lock(rwlock); + if (ue_db.count(rnti)) { ue_db[rnti]->set_tti(tti); - ue_db[rnti]->metrics_rx(crc, nof_bytes); + uint32_t ue_cc_idx = 0; // FIXME: mapping between eNB->UE CC idx + // push the pdu through the queue if received correctly if (crc) { Info("Pushing PDU rnti=%d, tti=%d, nof_bytes=%d\n", rnti, tti, nof_bytes); - ue_db[rnti]->push_pdu(tti, nof_bytes); + ue_db[rnti]->push_pdu(ue_cc_idx, tti, nof_bytes); stack_task_queue.push([this]() { process_pdus(); }); } else { - ue_db[rnti]->deallocate_pdu(tti); + ue_db[rnti]->deallocate_pdu(ue_cc_idx, tti); } - ret = scheduler.ul_crc_info(tti, rnti, cc_idx, crc); + ret = scheduler.ul_crc_info(tti, rnti, ue_cc_idx, crc); } else { Error("User rnti=0x%x not found\n", rnti); } + return ret; } -int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t ri_value) +int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ri_value) { + int ret = SRSLTE_ERROR; log_h->step(tti); - int ret = -1; srslte::rwlock_read_guard lock(rwlock); + if (ue_db.count(rnti)) { - scheduler.dl_ri_info(tti, rnti, cc_idx, ri_value); + scheduler.dl_ri_info(tti, rnti, enb_cc_idx, ri_value); ue_db[rnti]->metrics_dl_ri(ri_value); - ret = 0; + ret = SRSLTE_SUCCESS; } else { Error("User rnti=0x%x not found\n", rnti); } + return ret; } -int mac::pmi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t pmi_value) +int mac::pmi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t pmi_value) { + int ret = SRSLTE_ERROR; log_h->step(tti); srslte::rwlock_read_guard lock(rwlock); - int ret = -1; + if (ue_db.count(rnti)) { - scheduler.dl_pmi_info(tti, rnti, cc_idx, pmi_value); + scheduler.dl_pmi_info(tti, rnti, enb_cc_idx, pmi_value); ue_db[rnti]->metrics_dl_pmi(pmi_value); - ret = 0; + ret = SRSLTE_SUCCESS; } else { Error("User rnti=0x%x not found\n", rnti); } + return ret; } -int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) +int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi_value) { + int ret = SRSLTE_ERROR; log_h->step(tti); - int ret = -1; - srslte::rwlock_read_guard lock(rwlock); + if (ue_db.count(rnti)) { - scheduler.dl_cqi_info(tti, rnti, cc_idx, cqi_value); + scheduler.dl_cqi_info(tti, rnti, enb_cc_idx, cqi_value); ue_db[rnti]->metrics_dl_cqi(cqi_value); - ret = 0; + ret = SRSLTE_SUCCESS; } else { Error("User rnti=0x%x not found\n", rnti); } + return ret; } -int mac::snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr) +int mac::snr_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, float snr) { + int ret = SRSLTE_ERROR; log_h->step(tti); - int ret = -1; srslte::rwlock_read_guard lock(rwlock); + if (ue_db.count(rnti)) { uint32_t cqi = srslte_cqi_from_snr(snr); - scheduler.ul_cqi_info(tti, rnti, cc_idx, cqi, 0); - ret = 0; + scheduler.ul_cqi_info(tti, rnti, enb_cc_idx, cqi, 0); + ret = SRSLTE_SUCCESS; } else { Error("User rnti=0x%x not found\n", rnti); } + return ret; } @@ -491,7 +503,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res_list) log_h->step(tti); - for (uint32_t enb_cc_idx = 0; enb_cc_idx <= cell_config.size(); enb_cc_idx++) { + for (uint32_t enb_cc_idx = 0; enb_cc_idx < cell_config.size(); enb_cc_idx++) { // Run scheduler with current info sched_interface::dl_sched_res_t sched_result = {}; if (scheduler.dl_sched(tti, enb_cc_idx, sched_result) < 0) { @@ -516,7 +528,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res_list) dl_sched_res->pdsch[n].dci = sched_result.data[i].dci; for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - dl_sched_res->pdsch[n].softbuffer_tx[tb] = ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.pid, tb); + dl_sched_res->pdsch[n].softbuffer_tx[tb] = ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.ue_cc_idx, sched_result.data[i].dci.pid, tb); if (sched_result.data[i].nof_pdu_elems[tb] > 0) { /* Get PDU if it's a new transmission */ @@ -739,9 +751,9 @@ uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, } } -uint8_t* mac::assemble_si(const uint8_t cc_idx, const uint32_t sib_index) +uint8_t* mac::assemble_si(const uint8_t enb_cc_idx, const uint32_t sib_index) { - uint8_t* sib_payload = rrc_h->read_pdu_bcch_dlsch(cc_idx, sib_index); + uint8_t* sib_payload = rrc_h->read_pdu_bcch_dlsch(enb_cc_idx, sib_index); if (sib_payload == nullptr) { // return MAC managed dummy buffer in this case sib_payload = bcch_dlsch_payload; @@ -751,63 +763,67 @@ uint8_t* mac::assemble_si(const uint8_t cc_idx, const uint32_t sib_index) int mac::get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res_list) { - ul_sched_t* ul_sched_res = &ul_sched_res_list[0]; log_h->step(tti); if (!started) { - return 0; + return SRSLTE_SUCCESS; } - // Run scheduler with current info - sched_interface::ul_sched_res_t sched_result = {}; - if (scheduler.ul_sched(tti, 0, sched_result) < 0) { - Error("Running scheduler\n"); - return SRSLTE_ERROR; - } + for (uint32_t enb_cc_idx = 0; enb_cc_idx < cell_config.size(); enb_cc_idx++) { + ul_sched_t* phy_ul_sched_res = &ul_sched_res_list[enb_cc_idx]; - { - srslte::rwlock_read_guard lock(rwlock); - - // Copy DCI grants - ul_sched_res->nof_grants = 0; - int n = 0; - for (uint32_t i = 0; i < sched_result.nof_dci_elems; i++) { - - if (sched_result.pusch[i].tbs > 0) { - // Get UE - uint16_t rnti = sched_result.pusch[i].dci.rnti; - - if (ue_db.count(rnti)) { - // Copy grant info - ul_sched_res->pusch[n].current_tx_nb = sched_result.pusch[i].current_tx_nb; - ul_sched_res->pusch[n].needs_pdcch = sched_result.pusch[i].needs_pdcch; - ul_sched_res->pusch[n].dci = sched_result.pusch[i].dci; - ul_sched_res->pusch[n].softbuffer_rx = ue_db[rnti]->get_rx_softbuffer(tti); - - if (sched_result.pusch[n].current_tx_nb == 0) { - srslte_softbuffer_rx_reset_tbs(ul_sched_res->pusch[n].softbuffer_rx, sched_result.pusch[i].tbs * 8); - } - ul_sched_res->pusch[n].data = ue_db[rnti]->request_buffer(tti, sched_result.pusch[i].tbs); - ul_sched_res->nof_grants++; - n++; - } else { - Warning("Invalid UL scheduling result. User 0x%x does not exist\n", rnti); - } - - } else { - Warning("Grant %d for rnti=0x%x has zero TBS\n", i, sched_result.pusch[i].dci.rnti); - } + // Run scheduler with current info + sched_interface::ul_sched_res_t sched_result = {}; + if (scheduler.ul_sched(tti, enb_cc_idx, sched_result) < 0) { + Error("Running scheduler\n"); + return SRSLTE_ERROR; } - // No more uses of ue_db beyond here - } + { + srslte::rwlock_read_guard lock(rwlock); - // Copy PHICH actions - for (uint32_t i = 0; i < sched_result.nof_phich_elems; i++) { - ul_sched_res->phich[i].ack = sched_result.phich[i].phich == sched_interface::ul_sched_phich_t::ACK; - ul_sched_res->phich[i].rnti = sched_result.phich[i].rnti; + // Copy DCI grants + phy_ul_sched_res->nof_grants = 0; + int n = 0; + for (uint32_t i = 0; i < sched_result.nof_dci_elems; i++) { + + if (sched_result.pusch[i].tbs > 0) { + // Get UE + uint16_t rnti = sched_result.pusch[i].dci.rnti; + + if (ue_db.count(rnti)) { + // Copy grant info + phy_ul_sched_res->pusch[n].current_tx_nb = sched_result.pusch[i].current_tx_nb; + phy_ul_sched_res->pusch[n].needs_pdcch = sched_result.pusch[i].needs_pdcch; + phy_ul_sched_res->pusch[n].dci = sched_result.pusch[i].dci; + phy_ul_sched_res->pusch[n].softbuffer_rx = + ue_db[rnti]->get_rx_softbuffer(sched_result.pusch[i].dci.ue_cc_idx, tti); + if (sched_result.pusch[n].current_tx_nb == 0) { + srslte_softbuffer_rx_reset_tbs(phy_ul_sched_res->pusch[n].softbuffer_rx, sched_result.pusch[i].tbs * 8); + } + phy_ul_sched_res->pusch[n].data = + ue_db[rnti]->request_buffer(sched_result.pusch[i].dci.ue_cc_idx, tti, sched_result.pusch[i].tbs); + phy_ul_sched_res->nof_grants++; + n++; + } else { + Warning("Invalid UL scheduling result. User 0x%x does not exist\n", rnti); + } + + } else { + Warning("Grant %d for rnti=0x%x has zero TBS\n", i, sched_result.pusch[i].dci.rnti); + } + } + + // No more uses of ue_db beyond here + } + + // Copy PHICH actions + for (uint32_t i = 0; i < sched_result.nof_phich_elems; i++) { + phy_ul_sched_res->phich[i].ack = sched_result.phich[i].phich == sched_interface::ul_sched_phich_t::ACK; + phy_ul_sched_res->phich[i].rnti = sched_result.phich[i].rnti; + } + phy_ul_sched_res->nof_phich = sched_result.nof_phich_elems; } - ul_sched_res->nof_phich = sched_result.nof_phich_elems; return SRSLTE_SUCCESS; } diff --git a/srsenb/src/stack/mac/ue.cc b/srsenb/src/stack/mac/ue.cc index 602f0bd33..e2713d91d 100644 --- a/srsenb/src/stack/mac/ue.cc +++ b/srsenb/src/stack/mac/ue.cc @@ -35,7 +35,7 @@ namespace srsenb { ue::ue(uint16_t rnti_, - uint32_t nof_prb, + uint32_t nof_prb_, sched_interface* sched_, rrc_interface_mac* rrc_, rlc_interface_mac* rlc_, @@ -43,6 +43,7 @@ ue::ue(uint16_t rnti_, uint32_t nof_rx_harq_proc_, uint32_t nof_tx_harq_proc_) : rnti(rnti_), + nof_prb(nof_prb_), sched(sched_), rrc(rrc_), rlc(rlc_), @@ -54,24 +55,10 @@ ue::ue(uint16_t rnti_, nof_rx_harq_proc(nof_rx_harq_proc_), nof_tx_harq_proc(nof_tx_harq_proc_) { - bzero(&metrics, sizeof(mac_metrics_t)); - bzero(&mutex, sizeof(pthread_mutex_t)); - pthread_mutex_init(&mutex, NULL); - pdus.init(this, log_h); - softbuffer_tx.reserve(nof_tx_harq_proc); - softbuffer_rx.reserve(nof_rx_harq_proc); - pending_buffers.reserve(nof_rx_harq_proc); - - for (int i = 0; i < nof_rx_harq_proc; i++) { - srslte_softbuffer_rx_init(&softbuffer_rx[i], nof_prb); - pending_buffers[i] = nullptr; - } - for (int i = 0; i < nof_tx_harq_proc; i++) { - srslte_softbuffer_tx_init(&softbuffer_tx[i], nof_prb); - } - // don't need to reset because just initiated the buffers + // Allocate buffer for PCell + allocate_cc_buffers(); // Set LCID group for SRB0 and SRB1 set_lcg(0, 0); @@ -80,28 +67,73 @@ ue::ue(uint16_t rnti_, ue::~ue() { - for (int i = 0; i < nof_rx_harq_proc; i++) { - srslte_softbuffer_rx_free(&softbuffer_rx[i]); + // Free up all softbuffers for all CCs + for (auto cc : softbuffer_rx) { + for (auto buffer : cc) { + srslte_softbuffer_rx_free(&buffer); + } } - for (int i = 0; i < nof_tx_harq_proc; i++) { - srslte_softbuffer_tx_free(&softbuffer_tx[i]); + + for (auto cc : softbuffer_tx) { + for (auto buffer : cc) { + srslte_softbuffer_tx_free(&buffer); + } } - pthread_mutex_destroy(&mutex); } void ue::reset() { - bzero(&metrics, sizeof(mac_metrics_t)); - + metrics = {}; nof_failures = 0; - for (int i = 0; i < nof_rx_harq_proc; i++) { - srslte_softbuffer_rx_reset(&softbuffer_rx[i]); + + for (auto cc : softbuffer_rx) { + for (auto buffer : cc) { + srslte_softbuffer_rx_reset(&buffer); + } } - for (int i = 0; i < nof_tx_harq_proc; i++) { - srslte_softbuffer_tx_reset(&softbuffer_tx[i]); + + for (auto cc : softbuffer_tx) { + for (auto buffer : cc) { + srslte_softbuffer_tx_reset(&buffer); + } } } +/** + * Allocate and initialize softbuffers for Tx and Rx and + * append to current list of CC buffers. It uses the configured + * number of HARQ processes and cell width. + * + * @param num_cc Number of carriers to add buffers for (default 1) + * @return number of carriers + */ +uint32_t ue::allocate_cc_buffers(const uint32_t num_cc) +{ + for (uint32_t i = 0; i < num_cc; ++i) { + // create and init Rx buffers for Pcell + softbuffer_rx.emplace_back(); + softbuffer_rx.back().resize(nof_rx_harq_proc); + for (auto& buffer : softbuffer_rx.back()) { + srslte_softbuffer_rx_init(&buffer, nof_prb); + } + + pending_buffers.emplace_back(); + pending_buffers.back().resize(nof_rx_harq_proc); + for (auto& buffer : pending_buffers.back()) { + buffer = nullptr; + } + + // Create and init Tx buffers for Pcell + softbuffer_tx.emplace_back(); + softbuffer_tx.back().resize(nof_tx_harq_proc); + for (auto& buffer : softbuffer_tx.back()) { + srslte_softbuffer_tx_init(&buffer, nof_prb); + } + // don't need to reset because just initiated the buffers + } + return softbuffer_tx.size(); +} + void ue::start_pcap(srslte::mac_pcap* pcap_) { pcap = pcap_; @@ -127,23 +159,23 @@ void ue::set_lcg(uint32_t lcid, uint32_t lcg) lc_groups[lcg].push_back(lcid); } -srslte_softbuffer_rx_t* ue::get_rx_softbuffer(uint32_t tti) +srslte_softbuffer_rx_t* ue::get_rx_softbuffer(const uint32_t cc_idx, const uint32_t tti) { - return &softbuffer_rx[tti % nof_rx_harq_proc]; + return &softbuffer_rx.at(cc_idx).at(tti % nof_rx_harq_proc); } -srslte_softbuffer_tx_t* ue::get_tx_softbuffer(uint32_t harq_process, uint32_t tb_idx) +srslte_softbuffer_tx_t* ue::get_tx_softbuffer(const uint32_t cc_idx, const uint32_t harq_process, const uint32_t tb_idx) { - return &softbuffer_tx[(harq_process * SRSLTE_MAX_TB + tb_idx) % nof_tx_harq_proc]; + return &softbuffer_tx.at(cc_idx).at((harq_process * SRSLTE_MAX_TB + tb_idx) % nof_tx_harq_proc); } -uint8_t* ue::request_buffer(uint32_t tti, uint32_t len) +uint8_t* ue::request_buffer(const uint32_t ue_cc_idx, const uint32_t tti, const uint32_t len) { - uint8_t* ret = NULL; + uint8_t* ret = nullptr; if (len > 0) { - if (!pending_buffers[tti % nof_rx_harq_proc]) { + if (!pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc)) { ret = pdus.request(len); - pending_buffers[tti % nof_rx_harq_proc] = ret; + pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc) = ret; } else { log_h->console("Error requesting buffer for pid %d, not pushed yet\n", tti % nof_rx_harq_proc); log_h->error("Requesting buffer for pid %d, not pushed yet\n", tti % nof_rx_harq_proc); @@ -282,23 +314,24 @@ void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srslte::pdu_queue::channe Debug("MAC PDU processed\n"); } -void ue::deallocate_pdu(uint32_t tti) +void ue::deallocate_pdu(const uint32_t ue_cc_idx, const uint32_t tti) { - if (pending_buffers[tti % nof_rx_harq_proc]) { - pdus.deallocate(pending_buffers[tti % nof_rx_harq_proc]); - pending_buffers[tti % nof_rx_harq_proc] = NULL; + if (pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc)) { + pdus.deallocate(pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc)); + pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc) = nullptr; } else { - log_h->console("Error deallocating buffer for pid=%d. Not requested\n", tti % nof_rx_harq_proc); + log_h->console( + "Error deallocating buffer for ue_cc_idx=%d, pid=%d. Not requested\n", ue_cc_idx, tti % nof_rx_harq_proc); } } -void ue::push_pdu(uint32_t tti, uint32_t len) +void ue::push_pdu(const uint32_t ue_cc_idx, const uint32_t tti, uint32_t len) { - if (pending_buffers[tti % nof_rx_harq_proc]) { - pdus.push(pending_buffers[tti % nof_rx_harq_proc], len); - pending_buffers[tti % nof_rx_harq_proc] = NULL; + if (pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc)) { + pdus.push(pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc), len); + pending_buffers.at(ue_cc_idx).at(tti % nof_rx_harq_proc) = nullptr; } else { - log_h->console("Error pushing buffer for pid=%d. Not requested\n", tti % nof_rx_harq_proc); + log_h->console("Error pushing buffer for ue_cc_idx=%d, pid=%d. Not requested\n", ue_cc_idx, tti % nof_rx_harq_proc); } } @@ -435,6 +468,8 @@ void ue::allocate_ce(srslte::sch_pdu* pdu, uint32_t lcid) } if (pdu->get()->set_scell_activation_cmd(active_cc_list)) { Info("CE: Added SCell Activation CE.\n"); + // Allocate and initialize Rx/Tx softbuffers for new carriers (exclude PCell) + allocate_cc_buffers(active_cc_list.size() - 1); } else { Error("CE: Setting SCell Activation CE\n"); } @@ -457,8 +492,8 @@ uint8_t* ue::generate_pdu(uint32_t harq_pid, uint32_t nof_pdu_elems, uint32_t grant_size) { - uint8_t* ret = NULL; - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); + uint8_t* ret = nullptr; if (rlc) { tx_payload_buffer[harq_pid][tb_idx].clear(); mac_msg_dl.init_tx(&tx_payload_buffer[harq_pid][tb_idx], grant_size, false); @@ -469,14 +504,10 @@ uint8_t* ue::generate_pdu(uint32_t harq_pid, allocate_ce(&mac_msg_dl, pdu[i].lcid); } } - ret = mac_msg_dl.write_packet(log_h); - } else { std::cout << "Error ue not configured (must call config() first" << std::endl; } - - pthread_mutex_unlock(&mutex); return ret; } @@ -485,8 +516,8 @@ uint8_t* ue::generate_mch_pdu(uint32_t harq_pid, uint32_t nof_pdu_elems, uint32_t grant_size) { - uint8_t* ret = NULL; - pthread_mutex_lock(&mutex); + std::lock_guard lock(mutex); + uint8_t* ret = nullptr; tx_payload_buffer[harq_pid][0].clear(); mch_mac_msg_dl.init_tx(&tx_payload_buffer[harq_pid][0], grant_size); @@ -504,7 +535,6 @@ uint8_t* ue::generate_mch_pdu(uint32_t harq_pid, } ret = mch_mac_msg_dl.write_packet(log_h); - pthread_mutex_unlock(&mutex); return ret; } @@ -519,7 +549,7 @@ void ue::metrics_read(mac_metrics_t* metrics_) phr_counter = 0; dl_cqi_counter = 0; - bzero(&metrics, sizeof(mac_metrics_t)); + metrics = {}; } void ue::metrics_phr(float phr)