mirror of https://github.com/PentHertz/srsLTE.git
mac_nr: add UL HARQ
this patch adds a basic UL HARQ entity for NR. The patch also updates some interfaces between MAC/RA/HARQ, i.e. get_temp_crnti(). It also adds a Msg3 unit test.
This commit is contained in:
parent
b7146c41b2
commit
44baea6666
|
@ -120,6 +120,21 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SRSRAN_MAX_NOF_DL_DATA_TO_UL 8
|
#define SRSRAN_MAX_NOF_DL_DATA_TO_UL 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of HARQ processes in the DL, signaled through RRC (PDSCH-ServingCellConfig)
|
||||||
|
*/
|
||||||
|
#define SRSRAN_MAX_HARQ_PROC_DL_NR 16 // 3GPP TS 38.214 version 15.3.0 Sec. 5.1 or nrofHARQ-ProcessesForPDSCH
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default number of HARQ processes in the DL, if config is absent.
|
||||||
|
*/
|
||||||
|
#define SRSRAN_DEFAULT_HARQ_PROC_DL_NR 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of HARQ processes in the UL, signaled through RRC (ConfiguredGrantConfig)
|
||||||
|
*/
|
||||||
|
#define SRSRAN_MAX_HARQ_PROC_UL_NR 16 // 3GPP TS 38.214 version 15.3.0 Sec. 6.1
|
||||||
|
|
||||||
typedef enum SRSRAN_API {
|
typedef enum SRSRAN_API {
|
||||||
srsran_coreset_mapping_type_non_interleaved = 0,
|
srsran_coreset_mapping_type_non_interleaved = 0,
|
||||||
srsran_coreset_mapping_type_interleaved,
|
srsran_coreset_mapping_type_interleaved,
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "srsue/hdr/stack/mac_common/mac_common.h"
|
#include "srsue/hdr/stack/mac_common/mac_common.h"
|
||||||
#include "srsue/hdr/stack/mac_nr/mux_nr.h"
|
#include "srsue/hdr/stack/mac_nr/mux_nr.h"
|
||||||
#include "srsue/hdr/stack/ue_stack_base.h"
|
#include "srsue/hdr/stack/ue_stack_base.h"
|
||||||
|
#include "ul_harq_nr.h"
|
||||||
|
|
||||||
namespace srsue {
|
namespace srsue {
|
||||||
|
|
||||||
|
@ -36,7 +37,8 @@ class mac_nr final : public mac_interface_phy_nr,
|
||||||
public mac_interface_rrc_nr,
|
public mac_interface_rrc_nr,
|
||||||
public mac_interface_proc_ra_nr,
|
public mac_interface_proc_ra_nr,
|
||||||
public mac_interface_sr_nr,
|
public mac_interface_sr_nr,
|
||||||
public mac_interface_mux_nr
|
public mac_interface_mux_nr,
|
||||||
|
public mac_interface_harq_nr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
mac_nr(srsran::ext_task_sched_handle task_sched_);
|
mac_nr(srsran::ext_task_sched_handle task_sched_);
|
||||||
|
@ -82,9 +84,11 @@ public:
|
||||||
int remove_tag_config(const uint32_t tag_id);
|
int remove_tag_config(const uint32_t tag_id);
|
||||||
void start_ra_procedure();
|
void start_ra_procedure();
|
||||||
|
|
||||||
/// procedure ra nr interface + mux
|
/// Interface for internal procedures (RA, MUX, HARQ)
|
||||||
uint64_t get_contention_id();
|
uint64_t get_contention_id();
|
||||||
uint16_t get_crnti();
|
uint16_t get_crnti();
|
||||||
|
uint16_t get_temp_crnti();
|
||||||
|
uint16_t get_csrnti() { return SRSRAN_INVALID_RNTI; }; // SPS not supported
|
||||||
|
|
||||||
/// procedure sr nr interface
|
/// procedure sr nr interface
|
||||||
void start_ra() { proc_ra.start_by_mac(); }
|
void start_ra() { proc_ra.start_by_mac(); }
|
||||||
|
@ -136,7 +140,7 @@ private:
|
||||||
srslog::basic_logger& logger;
|
srslog::basic_logger& logger;
|
||||||
mac_nr_args_t args = {};
|
mac_nr_args_t args = {};
|
||||||
|
|
||||||
bool started = false;
|
std::atomic<bool> started = {false};
|
||||||
|
|
||||||
uint16_t c_rnti = SRSRAN_INVALID_RNTI;
|
uint16_t c_rnti = SRSRAN_INVALID_RNTI;
|
||||||
uint64_t contention_id = 0;
|
uint64_t contention_id = 0;
|
||||||
|
@ -149,11 +153,6 @@ private:
|
||||||
/// Rx buffer
|
/// Rx buffer
|
||||||
srsran::mac_sch_pdu_nr rx_pdu;
|
srsran::mac_sch_pdu_nr rx_pdu;
|
||||||
|
|
||||||
/// Tx buffer
|
|
||||||
srsran::unique_byte_buffer_t ul_harq_buffer = nullptr; // store PDU generated from MUX
|
|
||||||
srsran::unique_byte_buffer_t rlc_buffer = nullptr;
|
|
||||||
srsran_softbuffer_tx_t softbuffer_tx = {}; /// UL HARQ (temporal)
|
|
||||||
|
|
||||||
srsran::task_multiqueue::queue_handle stack_task_dispatch_queue;
|
srsran::task_multiqueue::queue_handle stack_task_dispatch_queue;
|
||||||
|
|
||||||
// MAC Uplink-related procedures
|
// MAC Uplink-related procedures
|
||||||
|
@ -161,6 +160,12 @@ private:
|
||||||
proc_sr_nr proc_sr;
|
proc_sr_nr proc_sr;
|
||||||
proc_bsr_nr proc_bsr;
|
proc_bsr_nr proc_bsr;
|
||||||
mux_nr mux;
|
mux_nr mux;
|
||||||
|
|
||||||
|
// UL HARQ
|
||||||
|
ul_harq_entity_nr_vector ul_harq = {};
|
||||||
|
ul_harq_cfg_t ul_harq_cfg;
|
||||||
|
|
||||||
|
const uint8_t PCELL_CC_IDX = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace srsue
|
} // namespace srsue
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
class mac_interface_sr_nr
|
class mac_interface_sr_nr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// MUX can query MAC for current C-RNTI for Msg3 transmission
|
// SR can query MAC (as proxy for RA) to start RA procedure
|
||||||
virtual void start_ra() = 0;
|
virtual void start_ra() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,6 +61,22 @@ public:
|
||||||
virtual srsran::mac_sch_subpdu_nr::lcg_bsr_t generate_sbsr() = 0;
|
virtual srsran::mac_sch_subpdu_nr::lcg_bsr_t generate_sbsr() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface from MAC NR parent class to HARQ subclass
|
||||||
|
*/
|
||||||
|
class mac_interface_harq_nr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// HARQ can query MAC for current C-RNTI
|
||||||
|
virtual uint16_t get_crnti() = 0;
|
||||||
|
|
||||||
|
// MAC also provides Temp C-RNTI (through RA proc)
|
||||||
|
virtual uint16_t get_temp_crnti() = 0;
|
||||||
|
|
||||||
|
// MAC provides the Currently Scheduled RNTI (for SPS)
|
||||||
|
virtual uint16_t get_csrnti() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace srsue
|
} // namespace srsue
|
||||||
|
|
||||||
#endif // SRSUE_MAC_NR_INTERFACES_H
|
#endif // SRSUE_MAC_NR_INTERFACES_H
|
|
@ -38,8 +38,8 @@ public:
|
||||||
bool is_rar_opportunity(uint32_t tti);
|
bool is_rar_opportunity(uint32_t tti);
|
||||||
bool has_rar_rnti();
|
bool has_rar_rnti();
|
||||||
uint16_t get_rar_rnti();
|
uint16_t get_rar_rnti();
|
||||||
bool has_temp_rnti();
|
bool has_temp_crnti();
|
||||||
uint16_t get_temp_rnti();
|
uint16_t get_temp_crnti();
|
||||||
|
|
||||||
// PHY interfaces
|
// PHY interfaces
|
||||||
void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id);
|
void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id);
|
||||||
|
@ -59,7 +59,7 @@ private:
|
||||||
|
|
||||||
int ra_window_length = -1, ra_window_start = -1;
|
int ra_window_length = -1, ra_window_start = -1;
|
||||||
uint16_t rar_rnti = SRSRAN_INVALID_RNTI;
|
uint16_t rar_rnti = SRSRAN_INVALID_RNTI;
|
||||||
uint16_t temp_rnti = SRSRAN_INVALID_RNTI;
|
uint16_t temp_crnti = SRSRAN_INVALID_RNTI;
|
||||||
|
|
||||||
srsran::rach_nr_cfg_t rach_cfg = {};
|
srsran::rach_nr_cfg_t rach_cfg = {};
|
||||||
bool configured = false;
|
bool configured = false;
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSUE_UL_HARQ_NR_H
|
||||||
|
#define SRSUE_UL_HARQ_NR_H
|
||||||
|
|
||||||
|
#include "mux_nr.h"
|
||||||
|
#include "proc_ra_nr.h"
|
||||||
|
#include "srsran/common/interfaces_common.h"
|
||||||
|
#include "srsran/common/timers.h"
|
||||||
|
#include "srsran/interfaces/ue_nr_interfaces.h"
|
||||||
|
|
||||||
|
using namespace srsran;
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
class ul_harq_entity_nr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ul_harq_entity_nr(const uint8_t cc_idx_, mac_interface_harq_nr* mac_, proc_ra_nr* ra_proc__, mux_nr* mux_);
|
||||||
|
|
||||||
|
int init();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void reset_ndi();
|
||||||
|
void set_config(srsran::ul_harq_cfg_t& harq_cfg);
|
||||||
|
|
||||||
|
/***************** PHY->MAC interface for UL processes **************************/
|
||||||
|
void new_grant_ul(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant, mac_interface_phy_nr::tb_action_ul_t* action);
|
||||||
|
|
||||||
|
int get_current_tbs(uint32_t pid);
|
||||||
|
float get_average_retx();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ul_harq_process_nr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ul_harq_process_nr();
|
||||||
|
~ul_harq_process_nr();
|
||||||
|
|
||||||
|
bool init(uint32_t pid_, ul_harq_entity_nr* entity_);
|
||||||
|
void reset();
|
||||||
|
void reset_ndi();
|
||||||
|
uint8_t get_ndi();
|
||||||
|
bool has_grant();
|
||||||
|
|
||||||
|
uint32_t get_nof_retx();
|
||||||
|
int get_current_tbs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Section 5.4.2.1
|
||||||
|
*
|
||||||
|
* @param grant The unmodified grant as received from PHY
|
||||||
|
* @param ndi_toggled The NDI toggled state determined by the entity
|
||||||
|
* @param action The resulting UL action structure to be filled.
|
||||||
|
*/
|
||||||
|
void new_grant_ul(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
|
const bool& ndi_toggled,
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t* action);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mac_interface_phy_nr::mac_nr_grant_ul_t current_grant = {};
|
||||||
|
bool grant_configured = false;
|
||||||
|
|
||||||
|
uint32_t pid = 0;
|
||||||
|
uint32_t nof_retx = 0;
|
||||||
|
bool is_initiated = false;
|
||||||
|
|
||||||
|
srslog::basic_logger& logger;
|
||||||
|
ul_harq_entity_nr* harq_entity = nullptr;
|
||||||
|
srsran_softbuffer_tx_t softbuffer;
|
||||||
|
|
||||||
|
std::unique_ptr<byte_buffer_t> harq_buffer = nullptr;
|
||||||
|
|
||||||
|
void generate_tx(mac_interface_phy_nr::tb_action_ul_t* action);
|
||||||
|
void generate_new_tx(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t* action);
|
||||||
|
void generate_retx(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t* action);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<ul_harq_process_nr, SRSRAN_MAX_HARQ_PROC_UL_NR> harq_procs;
|
||||||
|
|
||||||
|
mac_interface_harq_nr* mac = nullptr;
|
||||||
|
mux_nr* mux = nullptr;
|
||||||
|
srslog::basic_logger& logger;
|
||||||
|
|
||||||
|
srsran::ul_harq_cfg_t harq_cfg = {};
|
||||||
|
|
||||||
|
float average_retx = 0.0;
|
||||||
|
uint64_t nof_pkts = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::unique_ptr<ul_harq_entity_nr> ul_harq_entity_nr_ptr;
|
||||||
|
typedef std::array<ul_harq_entity_nr_ptr, SRSRAN_MAX_CARRIERS> ul_harq_entity_nr_vector;
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSUE_UL_HARQ_NR_H
|
|
@ -371,6 +371,12 @@ bool cc_worker::work_ul()
|
||||||
mac_ul_grant.rv = pusch_cfg.grant.tb[0].rv;
|
mac_ul_grant.rv = pusch_cfg.grant.tb[0].rv;
|
||||||
phy->stack->new_grant_ul(0, mac_ul_grant, &ul_action);
|
phy->stack->new_grant_ul(0, mac_ul_grant, &ul_action);
|
||||||
|
|
||||||
|
// Don't process further if MAC can't provide PDU
|
||||||
|
if (not ul_action.tb.enabled) {
|
||||||
|
ERROR("No MAC PDU provided by MAC");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Set UCI configuration following procedures
|
// Set UCI configuration following procedures
|
||||||
srsran_ra_ul_set_grant_uci_nr(&phy->cfg.pusch, &uci_data.cfg, &pusch_cfg);
|
srsran_ra_ul_set_grant_uci_nr(&phy->cfg.pusch, &uci_data.cfg, &pusch_cfg);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# the distribution.
|
# the distribution.
|
||||||
#
|
#
|
||||||
|
|
||||||
set(SOURCES mac_nr.cc proc_ra_nr.cc proc_bsr_nr.cc proc_sr_nr.cc mux_nr.cc)
|
set(SOURCES mac_nr.cc proc_ra_nr.cc proc_bsr_nr.cc proc_sr_nr.cc mux_nr.cc ul_harq_nr.cc)
|
||||||
add_library(srsue_mac_nr STATIC ${SOURCES})
|
add_library(srsue_mac_nr STATIC ${SOURCES})
|
||||||
target_link_libraries(srsue_mac_nr srsue_mac_common srsran_mac)
|
target_link_libraries(srsue_mac_nr srsue_mac_common srsran_mac)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,10 @@ mac_nr::mac_nr(srsran::ext_task_sched_handle task_sched_) :
|
||||||
proc_bsr(logger),
|
proc_bsr(logger),
|
||||||
mux(*this, logger),
|
mux(*this, logger),
|
||||||
pcap(nullptr)
|
pcap(nullptr)
|
||||||
{}
|
{
|
||||||
|
// Create PCell HARQ entities
|
||||||
|
ul_harq.at(PCELL_CC_IDX) = ul_harq_entity_nr_ptr(new ul_harq_entity_nr(PCELL_CC_IDX, this, &proc_ra, &mux));
|
||||||
|
}
|
||||||
|
|
||||||
mac_nr::~mac_nr()
|
mac_nr::~mac_nr()
|
||||||
{
|
{
|
||||||
|
@ -59,14 +62,9 @@ int mac_nr::init(const mac_nr_args_t& args_,
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srsran_softbuffer_tx_init_guru(&softbuffer_tx, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) <
|
// Configure PCell HARQ entities
|
||||||
SRSRAN_SUCCESS) {
|
if (ul_harq.at(PCELL_CC_IDX)->init() != SRSRAN_SUCCESS) {
|
||||||
ERROR("Error init soft-buffer");
|
logger.error("Couldn't initialize UL HARQ entity.");
|
||||||
return SRSRAN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul_harq_buffer = srsran::make_byte_buffer();
|
|
||||||
if (ul_harq_buffer == nullptr) {
|
|
||||||
return SRSRAN_ERROR;
|
return SRSRAN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +83,6 @@ void mac_nr::stop()
|
||||||
if (started) {
|
if (started) {
|
||||||
started = false;
|
started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
srsran_softbuffer_tx_free(&softbuffer_tx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement Section 5.9
|
// Implement Section 5.9
|
||||||
|
@ -167,9 +163,9 @@ mac_interface_phy_nr::sched_rnti_t mac_nr::get_dl_sched_rnti_nr(const uint32_t t
|
||||||
return {proc_ra.get_rar_rnti(), srsran_rnti_type_ra};
|
return {proc_ra.get_rar_rnti(), srsran_rnti_type_ra};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc_ra.has_temp_rnti() && has_crnti() == false) {
|
if (proc_ra.has_temp_crnti() && has_crnti() == false) {
|
||||||
logger.debug("SCHED: Searching temp C-RNTI=0x%x (proc_ra)", proc_ra.get_temp_rnti());
|
logger.debug("SCHED: Searching temp C-RNTI=0x%x (proc_ra)", proc_ra.get_temp_crnti());
|
||||||
return {proc_ra.get_temp_rnti(), srsran_rnti_type_c};
|
return {proc_ra.get_temp_crnti(), srsran_rnti_type_c};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_crnti()) {
|
if (has_crnti()) {
|
||||||
|
@ -191,6 +187,11 @@ uint16_t mac_nr::get_crnti()
|
||||||
return c_rnti;
|
return c_rnti;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t mac_nr::get_temp_crnti()
|
||||||
|
{
|
||||||
|
return proc_ra.get_temp_crnti();
|
||||||
|
}
|
||||||
|
|
||||||
srsran::mac_sch_subpdu_nr::lcg_bsr_t mac_nr::generate_sbsr()
|
srsran::mac_sch_subpdu_nr::lcg_bsr_t mac_nr::generate_sbsr()
|
||||||
{
|
{
|
||||||
return proc_bsr.generate_sbsr();
|
return proc_bsr.generate_sbsr();
|
||||||
|
@ -274,6 +275,19 @@ void mac_nr::tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant)
|
||||||
|
|
||||||
void mac_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action)
|
void mac_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, tb_action_ul_t* action)
|
||||||
{
|
{
|
||||||
|
logger.debug("new_grant_ul(): cc_idx=%d, tti=%d, rnti=%d, pid=%d, tbs=%d, ndi=%d, rv=%d, is_rar=%d",
|
||||||
|
cc_idx,
|
||||||
|
grant.tti,
|
||||||
|
grant.rnti,
|
||||||
|
grant.pid,
|
||||||
|
grant.tbs,
|
||||||
|
grant.ndi,
|
||||||
|
grant.rv,
|
||||||
|
grant.is_rar_grant);
|
||||||
|
|
||||||
|
// Clear UL action
|
||||||
|
*action = {};
|
||||||
|
|
||||||
// if proc ra is in contention resolution and c_rnti == grant.c_rnti resolve contention resolution
|
// if proc ra is in contention resolution and c_rnti == grant.c_rnti resolve contention resolution
|
||||||
if (proc_ra.is_contention_resolution() && grant.rnti == c_rnti) {
|
if (proc_ra.is_contention_resolution() && grant.rnti == c_rnti) {
|
||||||
proc_ra.pdcch_to_crnti();
|
proc_ra.pdcch_to_crnti();
|
||||||
|
@ -282,28 +296,20 @@ void mac_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant,
|
||||||
// Let BSR know there is a new grant, might have to send a BSR
|
// Let BSR know there is a new grant, might have to send a BSR
|
||||||
proc_bsr.new_grant_ul(grant.tbs);
|
proc_bsr.new_grant_ul(grant.tbs);
|
||||||
|
|
||||||
// TODO: add proper UL-HARQ
|
// Assert UL HARQ entity
|
||||||
// The code below assumes a single HARQ entity, no retx, every Tx is always a new transmission
|
if (ul_harq.at(cc_idx) == nullptr) {
|
||||||
ul_harq_buffer = mux.get_pdu(grant.tbs);
|
logger.error("HARQ entity %d has not been created", cc_idx);
|
||||||
|
return;
|
||||||
// fill TB action (goes into UL harq eventually)
|
|
||||||
if (ul_harq_buffer != nullptr) {
|
|
||||||
action->tb.payload = ul_harq_buffer.get(); // pass handle to PDU to PHY
|
|
||||||
action->tb.enabled = true;
|
|
||||||
action->tb.rv = 0;
|
|
||||||
action->tb.softbuffer = &softbuffer_tx;
|
|
||||||
srsran_softbuffer_tx_reset(&softbuffer_tx);
|
|
||||||
} else {
|
|
||||||
action->tb.enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul_harq.at(cc_idx)->new_grant_ul(grant, action);
|
||||||
|
metrics[cc_idx].tx_pkts++;
|
||||||
|
metrics[cc_idx].tx_brate += grant.tbs * 8;
|
||||||
|
|
||||||
// store PCAP
|
// store PCAP
|
||||||
if (pcap) {
|
if (action->tb.enabled && pcap) {
|
||||||
pcap->write_ul_crnti_nr(ul_harq_buffer->msg, ul_harq_buffer->N_bytes, grant.rnti, grant.pid, grant.tti);
|
pcap->write_ul_crnti_nr(action->tb.payload->msg, action->tb.payload->N_bytes, grant.rnti, grant.pid, grant.tti);
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics[cc_idx].tx_brate += grant.tbs * 8;
|
|
||||||
metrics[cc_idx].tx_pkts++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mac_nr::timer_expired(uint32_t timer_id)
|
void mac_nr::timer_expired(uint32_t timer_id)
|
||||||
|
|
|
@ -62,14 +62,10 @@ srsran::unique_byte_buffer_t mux_nr::get_pdu(uint32_t max_pdu_len)
|
||||||
tx_pdu.init_tx(phy_tx_pdu.get(), max_pdu_len, true);
|
tx_pdu.init_tx(phy_tx_pdu.get(), max_pdu_len, true);
|
||||||
|
|
||||||
if (msg3_is_pending()) {
|
if (msg3_is_pending()) {
|
||||||
// If message 3 is pending pack message 3 for uplink transmission
|
// If Msg3 is pending, pack it
|
||||||
// Use the CRNTI which is provided in the RRC reconfiguration (only for DC mode maybe other)
|
// Use the CRNTI which is provided in the RRC reconfiguration (only for DC mode maybe other)
|
||||||
tx_pdu.add_crnti_ce(mac.get_crnti());
|
tx_pdu.add_crnti_ce(mac.get_crnti());
|
||||||
srsran::mac_sch_subpdu_nr::lcg_bsr_t sbsr = {};
|
tx_pdu.add_sbsr_ce(mac.generate_sbsr());
|
||||||
sbsr.lcg_id = 0;
|
|
||||||
sbsr.buffer_size = 1;
|
|
||||||
tx_pdu.add_sbsr_ce(sbsr);
|
|
||||||
logger.info("Generated msg3 with RNTI 0x%x", mac.get_crnti());
|
|
||||||
msg3_transmitted();
|
msg3_transmitted();
|
||||||
} else {
|
} else {
|
||||||
// Pack normal UL data PDU
|
// Pack normal UL data PDU
|
||||||
|
|
|
@ -112,14 +112,14 @@ bool proc_ra_nr::has_rar_rnti()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool proc_ra_nr::has_temp_rnti()
|
bool proc_ra_nr::has_temp_crnti()
|
||||||
{
|
{
|
||||||
return temp_rnti != SRSRAN_INVALID_RNTI;
|
return temp_crnti != SRSRAN_INVALID_RNTI;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t proc_ra_nr::get_temp_rnti()
|
uint16_t proc_ra_nr::get_temp_crnti()
|
||||||
{
|
{
|
||||||
return temp_rnti;
|
return temp_crnti;
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc_ra_nr::timer_expired(uint32_t timer_id)
|
void proc_ra_nr::timer_expired(uint32_t timer_id)
|
||||||
|
@ -201,11 +201,11 @@ void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_
|
||||||
|
|
||||||
for (auto& subpdu : pdu.get_subpdus()) {
|
for (auto& subpdu : pdu.get_subpdus()) {
|
||||||
if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) {
|
if (subpdu.has_rapid() && subpdu.get_rapid() == preamble_index) {
|
||||||
logger.info("PROC RA NR: Setting ul grant and prepare msg3");
|
logger.debug("PROC RA NR: Setting UL grant and prepare Msg3");
|
||||||
temp_rnti = subpdu.get_temp_crnti();
|
temp_crnti = subpdu.get_temp_crnti();
|
||||||
|
|
||||||
// Set Temporary-C-RNTI if provided, otherwise C-RNTI is ok
|
// Set Temporary-C-RNTI if provided, otherwise C-RNTI is ok
|
||||||
phy->set_ul_grant(subpdu.get_ul_grant(), temp_rnti, srsran_rnti_type_c);
|
phy->set_ul_grant(subpdu.get_ul_grant(), temp_crnti, srsran_rnti_type_c);
|
||||||
|
|
||||||
// reset all parameters that are used before rar
|
// reset all parameters that are used before rar
|
||||||
rar_rnti = SRSRAN_INVALID_RNTI;
|
rar_rnti = SRSRAN_INVALID_RNTI;
|
||||||
|
@ -272,13 +272,13 @@ void proc_ra_nr::ra_completion()
|
||||||
}
|
}
|
||||||
srsran::console("Random Access Complete. c-rnti=0x%x, ta=%d\n", mac.get_crnti(), current_ta);
|
srsran::console("Random Access Complete. c-rnti=0x%x, ta=%d\n", mac.get_crnti(), current_ta);
|
||||||
logger.info("Random Access Complete. c-rnti=0x%x, ta=%d", mac.get_crnti(), current_ta);
|
logger.info("Random Access Complete. c-rnti=0x%x, ta=%d", mac.get_crnti(), current_ta);
|
||||||
temp_rnti = SRSRAN_INVALID_RNTI;
|
temp_crnti = SRSRAN_INVALID_RNTI;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc_ra_nr::ra_error()
|
void proc_ra_nr::ra_error()
|
||||||
{
|
{
|
||||||
temp_rnti = 0;
|
temp_crnti = SRSRAN_INVALID_RNTI;
|
||||||
preamble_transmission_counter++;
|
preamble_transmission_counter++;
|
||||||
contention_resolution_timer.stop();
|
contention_resolution_timer.stop();
|
||||||
uint32_t backoff_wait;
|
uint32_t backoff_wait;
|
||||||
|
|
|
@ -141,9 +141,61 @@ private:
|
||||||
std::map<uint32_t, uint32_t> ul_queues;
|
std::map<uint32_t, uint32_t> ul_queues;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Add test
|
|
||||||
int msg3_test()
|
int msg3_test()
|
||||||
{
|
{
|
||||||
|
// UL-SCH PDU for Msg3 with C-RNTI CE and SBSR
|
||||||
|
const uint8_t tv[] = {0x3a, 0x10, 0x01, 0x3d, 0x00, 0x3f, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
|
// dummy layers
|
||||||
|
dummy_phy phy;
|
||||||
|
rlc_dummy rlc;
|
||||||
|
rrc_dummy rrc;
|
||||||
|
stack_dummy stack;
|
||||||
|
|
||||||
|
// the actual MAC
|
||||||
|
mac_nr mac(&stack.task_sched);
|
||||||
|
|
||||||
|
mac_nr_args_t args = {};
|
||||||
|
mac.init(args, &phy, &rlc, &rrc);
|
||||||
|
const uint16_t crnti = 0x1001;
|
||||||
|
|
||||||
|
// set C-RNTI and tell MAC to prepare Msg3 transmission
|
||||||
|
mac.set_crnti(crnti);
|
||||||
|
mac.msg3_prepare();
|
||||||
|
|
||||||
|
stack.init(&mac, &phy);
|
||||||
|
|
||||||
|
// create UL action and grant and read MAC PDU
|
||||||
|
{
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t ul_action = {};
|
||||||
|
mac_interface_phy_nr::mac_nr_grant_ul_t mac_grant = {};
|
||||||
|
|
||||||
|
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
||||||
|
mac_grant.pid = 0;
|
||||||
|
mac_grant.tti = 0;
|
||||||
|
mac_grant.tbs = 9;
|
||||||
|
int cc_idx = 0;
|
||||||
|
|
||||||
|
// Send grant to MAC and get action for this TB, 0x
|
||||||
|
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
||||||
|
|
||||||
|
TESTASSERT(ul_action.tb.enabled == true);
|
||||||
|
|
||||||
|
// print generated PDU
|
||||||
|
srslog::fetch_basic_logger("MAC").info(
|
||||||
|
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
||||||
|
#if HAVE_PCAP
|
||||||
|
pcap_handle->write_ul_crnti_nr(
|
||||||
|
ul_action.tb.payload->msg, mac_grant.tbs, mac_grant.rnti, UE_ID, mac_grant.pid, mac_grant.tti);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TESTASSERT(memcmp(ul_action.tb.payload->msg, tv, sizeof(tv)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure MAC PDU thread picks up before stopping
|
||||||
|
stack.run_tti(0);
|
||||||
|
mac.stop();
|
||||||
|
|
||||||
return SRSRAN_SUCCESS;
|
return SRSRAN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +224,7 @@ int mac_nr_ul_logical_channel_prioritization_test1()
|
||||||
|
|
||||||
stack.init(&mac, &phy);
|
stack.init(&mac, &phy);
|
||||||
const uint16_t crnti = 0x1001;
|
const uint16_t crnti = 0x1001;
|
||||||
|
mac.set_crnti(crnti);
|
||||||
|
|
||||||
// generate config (default DRB2 config for EN-DC)
|
// generate config (default DRB2 config for EN-DC)
|
||||||
std::vector<srsran::logical_channel_config_t> lcids;
|
std::vector<srsran::logical_channel_config_t> lcids;
|
||||||
|
@ -202,14 +255,46 @@ int mac_nr_ul_logical_channel_prioritization_test1()
|
||||||
|
|
||||||
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
||||||
mac_grant.pid = 0;
|
mac_grant.pid = 0;
|
||||||
mac_grant.rnti = 0x1001;
|
|
||||||
mac_grant.tti = 0;
|
mac_grant.tti = 0;
|
||||||
mac_grant.tbs = 20;
|
mac_grant.tbs = 20;
|
||||||
|
mac_grant.ndi = 0;
|
||||||
int cc_idx = 0;
|
int cc_idx = 0;
|
||||||
|
|
||||||
// Send grant to MAC and get action for this TB, 0x
|
// Send grant to MAC and get action for this TB, 0x
|
||||||
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
||||||
|
|
||||||
|
TESTASSERT(ul_action.tb.enabled == true);
|
||||||
|
|
||||||
|
// print generated PDU
|
||||||
|
srslog::fetch_basic_logger("MAC").info(
|
||||||
|
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
||||||
|
#if HAVE_PCAP
|
||||||
|
pcap_handle->write_ul_crnti_nr(
|
||||||
|
ul_action.tb.payload->msg, mac_grant.tbs, mac_grant.rnti, UE_ID, mac_grant.pid, mac_grant.tti);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TESTASSERT(memcmp(ul_action.tb.payload->msg, tv, sizeof(tv)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.run_tti(0);
|
||||||
|
|
||||||
|
// create new grant that indicates/requests a retx of the previous PDU
|
||||||
|
{
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t ul_action = {};
|
||||||
|
mac_interface_phy_nr::mac_nr_grant_ul_t mac_grant = {};
|
||||||
|
|
||||||
|
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
||||||
|
mac_grant.pid = 0; // same PID as above
|
||||||
|
mac_grant.tbs = 20;
|
||||||
|
mac_grant.rv = 1; // this is RV=1
|
||||||
|
mac_grant.ndi = 0; // NDI keeps zero to request retx
|
||||||
|
int cc_idx = 0;
|
||||||
|
|
||||||
|
// Send grant to MAC and get action for this TB, 0x
|
||||||
|
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
||||||
|
|
||||||
|
TESTASSERT(ul_action.tb.enabled == true);
|
||||||
|
|
||||||
// print generated PDU
|
// print generated PDU
|
||||||
srslog::fetch_basic_logger("MAC").info(
|
srslog::fetch_basic_logger("MAC").info(
|
||||||
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
||||||
|
@ -260,11 +345,12 @@ int mac_nr_ul_logical_channel_prioritization_test2()
|
||||||
// the actual MAC
|
// the actual MAC
|
||||||
mac_nr mac(&stack.task_sched);
|
mac_nr mac(&stack.task_sched);
|
||||||
|
|
||||||
|
const uint16_t crnti = 0x1001;
|
||||||
mac_nr_args_t args = {};
|
mac_nr_args_t args = {};
|
||||||
mac.init(args, &phy, &rlc, &rrc);
|
mac.init(args, &phy, &rlc, &rrc);
|
||||||
|
mac.set_crnti(crnti);
|
||||||
|
|
||||||
stack.init(&mac, &phy);
|
stack.init(&mac, &phy);
|
||||||
const uint16_t crnti = 0x1001;
|
|
||||||
|
|
||||||
// generate config (default DRB2 config for EN-DC)
|
// generate config (default DRB2 config for EN-DC)
|
||||||
std::vector<srsran::logical_channel_config_t> lcids;
|
std::vector<srsran::logical_channel_config_t> lcids;
|
||||||
|
@ -295,7 +381,6 @@ int mac_nr_ul_logical_channel_prioritization_test2()
|
||||||
|
|
||||||
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
||||||
mac_grant.pid = 0;
|
mac_grant.pid = 0;
|
||||||
mac_grant.rnti = 0x1001;
|
|
||||||
mac_grant.tti = 0;
|
mac_grant.tti = 0;
|
||||||
mac_grant.tbs = 260;
|
mac_grant.tbs = 260;
|
||||||
int cc_idx = 0;
|
int cc_idx = 0;
|
||||||
|
@ -343,10 +428,11 @@ int mac_nr_ul_periodic_bsr_test()
|
||||||
mac_nr mac(&stack.task_sched);
|
mac_nr mac(&stack.task_sched);
|
||||||
|
|
||||||
mac_nr_args_t args = {};
|
mac_nr_args_t args = {};
|
||||||
|
const uint16_t crnti = 0x1001;
|
||||||
mac.init(args, &phy, &rlc, &rrc);
|
mac.init(args, &phy, &rlc, &rrc);
|
||||||
|
mac.set_crnti(crnti);
|
||||||
|
|
||||||
stack.init(&mac, &phy);
|
stack.init(&mac, &phy);
|
||||||
const uint16_t crnti = 0x1001;
|
|
||||||
|
|
||||||
// generate config (default DRB2 config for EN-DC)
|
// generate config (default DRB2 config for EN-DC)
|
||||||
std::vector<srsran::logical_channel_config_t> lcids;
|
std::vector<srsran::logical_channel_config_t> lcids;
|
||||||
|
@ -379,6 +465,8 @@ int mac_nr_ul_periodic_bsr_test()
|
||||||
stack.run_tti(tti++);
|
stack.run_tti(tti++);
|
||||||
usleep(100);
|
usleep(100);
|
||||||
|
|
||||||
|
int ul_ndi = 0;
|
||||||
|
|
||||||
// create UL action and grant and read MAC PDU
|
// create UL action and grant and read MAC PDU
|
||||||
{
|
{
|
||||||
mac_interface_phy_nr::tb_action_ul_t ul_action = {};
|
mac_interface_phy_nr::tb_action_ul_t ul_action = {};
|
||||||
|
@ -386,14 +474,16 @@ int mac_nr_ul_periodic_bsr_test()
|
||||||
|
|
||||||
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
||||||
mac_grant.pid = 0;
|
mac_grant.pid = 0;
|
||||||
mac_grant.rnti = 0x1001;
|
|
||||||
mac_grant.tti = 0;
|
mac_grant.tti = 0;
|
||||||
mac_grant.tbs = 10;
|
mac_grant.tbs = 10;
|
||||||
|
mac_grant.ndi = (ul_ndi++) % 2;
|
||||||
int cc_idx = 0;
|
int cc_idx = 0;
|
||||||
|
|
||||||
// Send grant to MAC and get action for this TB
|
// Send grant to MAC and get action for this TB
|
||||||
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
||||||
|
|
||||||
|
TESTASSERT(ul_action.tb.enabled == true);
|
||||||
|
|
||||||
// print generated PDU
|
// print generated PDU
|
||||||
srslog::fetch_basic_logger("MAC").info(
|
srslog::fetch_basic_logger("MAC").info(
|
||||||
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
||||||
|
@ -417,14 +507,16 @@ int mac_nr_ul_periodic_bsr_test()
|
||||||
|
|
||||||
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
||||||
mac_grant.pid = 0;
|
mac_grant.pid = 0;
|
||||||
mac_grant.rnti = 0x1001;
|
|
||||||
mac_grant.tti = 0;
|
mac_grant.tti = 0;
|
||||||
mac_grant.tbs = 10;
|
mac_grant.tbs = 10;
|
||||||
|
mac_grant.ndi = (ul_ndi++) % 2;
|
||||||
int cc_idx = 0;
|
int cc_idx = 0;
|
||||||
|
|
||||||
// Send grant to MAC and get action for this TB
|
// Send grant to MAC and get action for this TB
|
||||||
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
||||||
|
|
||||||
|
TESTASSERT(ul_action.tb.enabled == true);
|
||||||
|
|
||||||
// print generated PDU
|
// print generated PDU
|
||||||
srslog::fetch_basic_logger("MAC").info(
|
srslog::fetch_basic_logger("MAC").info(
|
||||||
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
||||||
|
@ -448,7 +540,6 @@ int mac_nr_ul_periodic_bsr_test()
|
||||||
|
|
||||||
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
mac_grant.rnti = crnti; // make sure MAC picks it up as valid UL grant
|
||||||
mac_grant.pid = 0;
|
mac_grant.pid = 0;
|
||||||
mac_grant.rnti = 0x1001;
|
|
||||||
mac_grant.tti = 0;
|
mac_grant.tti = 0;
|
||||||
mac_grant.tbs = 10;
|
mac_grant.tbs = 10;
|
||||||
int cc_idx = 0;
|
int cc_idx = 0;
|
||||||
|
@ -456,6 +547,8 @@ int mac_nr_ul_periodic_bsr_test()
|
||||||
// Send grant to MAC and get action for this TB
|
// Send grant to MAC and get action for this TB
|
||||||
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
mac.new_grant_ul(cc_idx, mac_grant, &ul_action);
|
||||||
|
|
||||||
|
TESTASSERT(ul_action.tb.enabled == true);
|
||||||
|
|
||||||
// print generated PDU
|
// print generated PDU
|
||||||
srslog::fetch_basic_logger("MAC").info(
|
srslog::fetch_basic_logger("MAC").info(
|
||||||
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
ul_action.tb.payload->msg, mac_grant.tbs, "Generated PDU (%d B)", mac_grant.tbs);
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srsue/hdr/stack/mac_nr/ul_harq_nr.h"
|
||||||
|
#include "srsran/common/buffer_pool.h"
|
||||||
|
#include "srsran/common/interfaces_common.h"
|
||||||
|
#include "srsran/common/timers.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
ul_harq_entity_nr::ul_harq_entity_nr(const uint8_t cc_idx_,
|
||||||
|
mac_interface_harq_nr* mac_,
|
||||||
|
proc_ra_nr* ra_proc_,
|
||||||
|
mux_nr* mux_) :
|
||||||
|
mac(mac_), mux(mux_), logger(srslog::fetch_basic_logger("MAC"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
int ul_harq_entity_nr::init()
|
||||||
|
{
|
||||||
|
uint32_t proc_count = 0;
|
||||||
|
for (auto& proc : harq_procs) {
|
||||||
|
if (not proc.init(proc_count++, this)) {
|
||||||
|
logger.error("Couldn't initialize HARQ procedure");
|
||||||
|
return SRSRAN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_harq_entity_nr::reset()
|
||||||
|
{
|
||||||
|
for (auto& proc : harq_procs) {
|
||||||
|
proc.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_harq_entity_nr::reset_ndi()
|
||||||
|
{
|
||||||
|
for (auto& proc : harq_procs) {
|
||||||
|
proc.reset_ndi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_harq_entity_nr::set_config(srsran::ul_harq_cfg_t& harq_cfg_)
|
||||||
|
{
|
||||||
|
harq_cfg = harq_cfg_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************** PHY->MAC interface for UL processes **************************/
|
||||||
|
void ul_harq_entity_nr::new_grant_ul(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t* action)
|
||||||
|
{
|
||||||
|
if (grant.pid >= harq_procs.size()) {
|
||||||
|
logger.error("Invalid PID: %d", grant.pid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine whether the NDI has been toggled for this process
|
||||||
|
bool ndi_toggled = (grant.ndi != harq_procs.at(grant.pid).get_ndi());
|
||||||
|
|
||||||
|
// 1> if UL MAC entity's C-RNTI or Temporary C-RNTI; or Received in RAR;
|
||||||
|
if (mac->get_crnti() == grant.rnti || mac->get_temp_crnti() == grant.rnti || grant.is_rar_grant) {
|
||||||
|
// 2> if UL grant for C-RNTI and if the previous grant delivered to the HARQ entity
|
||||||
|
// for the same HARQ process was either an uplink grant received for the MAC entity's CS-RNTI or a
|
||||||
|
// configured uplink grant:
|
||||||
|
if (mac->get_crnti() == grant.rnti && harq_procs.at(grant.pid).has_grant()) {
|
||||||
|
// 3> consider the NDI to have been toggled regardless of the value of the NDI.
|
||||||
|
ndi_toggled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2> if the UL grant is for MAC entity's C-RNTI, and the HARQ process is configured for a configured uplink grant:
|
||||||
|
if (mac->get_crnti() == grant.rnti && harq_procs.at(grant.pid).has_grant()) {
|
||||||
|
// TODO: add handling for configuredGrantTimer
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2> deliver the uplink grant and the associated HARQ information to the HARQ entity
|
||||||
|
harq_procs.at(grant.pid).new_grant_ul(grant, ndi_toggled, action);
|
||||||
|
} else if (mac->get_csrnti() == grant.rnti) {
|
||||||
|
// SPS not supported
|
||||||
|
logger.warning("Ignoring grant for CS-RNTI=0x%x", grant.rnti);
|
||||||
|
} else {
|
||||||
|
logger.warning("Received grant for unknown rnti=0x%x", grant.rnti);
|
||||||
|
printf("Received grant for unknown rnti=0x%x\n", grant.rnti);
|
||||||
|
}
|
||||||
|
|
||||||
|
srsran_expect(action->tb.enabled ? action->tb.payload != nullptr : true,
|
||||||
|
"UL action enabled but no HARQ buffer provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ul_harq_entity_nr::get_current_tbs(uint32_t pid)
|
||||||
|
{
|
||||||
|
if (pid >= harq_procs.size()) {
|
||||||
|
logger.error("Invalid PID: %d", pid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return harq_procs.at(pid).get_current_tbs();
|
||||||
|
}
|
||||||
|
|
||||||
|
float ul_harq_entity_nr::get_average_retx()
|
||||||
|
{
|
||||||
|
return average_retx;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul_harq_entity_nr::ul_harq_process_nr::ul_harq_process_nr() : logger(srslog::fetch_basic_logger("MAC")) {}
|
||||||
|
|
||||||
|
ul_harq_entity_nr::ul_harq_process_nr::~ul_harq_process_nr()
|
||||||
|
{
|
||||||
|
if (is_initiated) {
|
||||||
|
srsran_softbuffer_tx_free(&softbuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ul_harq_entity_nr::ul_harq_process_nr::init(uint32_t pid_, ul_harq_entity_nr* entity_)
|
||||||
|
{
|
||||||
|
if (srsran_softbuffer_tx_init_guru(&softbuffer, SRSRAN_SCH_NR_MAX_NOF_CB_LDPC, SRSRAN_LDPC_MAX_LEN_ENCODED_CB) <
|
||||||
|
SRSRAN_SUCCESS) {
|
||||||
|
logger.error("Couldn't initialize softbuffer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = pid_;
|
||||||
|
harq_entity = entity_;
|
||||||
|
|
||||||
|
is_initiated = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_harq_entity_nr::ul_harq_process_nr::reset()
|
||||||
|
{
|
||||||
|
nof_retx = 0;
|
||||||
|
harq_buffer = nullptr;
|
||||||
|
current_grant = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_harq_entity_nr::ul_harq_process_nr::reset_ndi()
|
||||||
|
{
|
||||||
|
current_grant.ndi = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ul_harq_entity_nr::ul_harq_process_nr::get_ndi()
|
||||||
|
{
|
||||||
|
return current_grant.ndi;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ul_harq_entity_nr::ul_harq_process_nr::has_grant()
|
||||||
|
{
|
||||||
|
return grant_configured;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic handling of new grant
|
||||||
|
void ul_harq_entity_nr::ul_harq_process_nr::new_grant_ul(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
|
const bool& ndi_toggled,
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t* action)
|
||||||
|
{
|
||||||
|
// Get maximum retransmissions
|
||||||
|
uint32_t max_retx = harq_entity->harq_cfg.max_harq_tx;
|
||||||
|
|
||||||
|
// Check maximum retransmissions, do not consider last retx ACK
|
||||||
|
if (nof_retx >= max_retx) {
|
||||||
|
logger.info("UL %d: Maximum number of ReTX reached (%d). Discarding TB.", pid, max_retx);
|
||||||
|
if (grant.rnti == harq_entity->mac->get_temp_crnti()) {
|
||||||
|
// FIXME: signal maxRetx to RA?
|
||||||
|
// harq_entity->ra_proc->harq_max_retx();
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks in 5.4.2.1
|
||||||
|
if ((grant.rnti != harq_entity->mac->get_temp_crnti() &&
|
||||||
|
ndi_toggled) || // If not addressed to T-CRNTI and NDI toggled
|
||||||
|
(grant.rnti == harq_entity->mac->get_crnti() &&
|
||||||
|
harq_buffer == nullptr) || // If addressed to C-RNTI and buffer is empty
|
||||||
|
(grant.is_rar_grant) // Grant received in a RAR
|
||||||
|
) {
|
||||||
|
// new transmission
|
||||||
|
|
||||||
|
// generate new PDU (Msg3 or normal UL)
|
||||||
|
harq_buffer = harq_entity->mux->get_pdu(grant.tbs);
|
||||||
|
|
||||||
|
// 3> if a MAC PDU to transmit has been obtained
|
||||||
|
if (harq_buffer != nullptr) {
|
||||||
|
// 4> deliver the MAC PDU
|
||||||
|
// 4> instruct the identified HARQ process to trigger a new transmission;
|
||||||
|
generate_new_tx(grant, action);
|
||||||
|
|
||||||
|
// TODO: add handling of configuredGrantTimer
|
||||||
|
} else {
|
||||||
|
// HARQ buffer is automatically flushed
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// retransmission
|
||||||
|
if (harq_buffer == nullptr) {
|
||||||
|
// ignore the UL grant
|
||||||
|
logger.info("UL %d: HARQ buffer empty. Ignoring grant.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4> instruct the identified HARQ process to trigger a retransmission;
|
||||||
|
generate_retx(grant, action);
|
||||||
|
|
||||||
|
// TODO: add handling of configuredGrantTimer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ul_harq_entity_nr::ul_harq_process_nr::get_nof_retx()
|
||||||
|
{
|
||||||
|
return nof_retx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ul_harq_entity_nr::ul_harq_process_nr::get_current_tbs()
|
||||||
|
{
|
||||||
|
return current_grant.tbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New transmission (Section 5.4.2.2)
|
||||||
|
void ul_harq_entity_nr::ul_harq_process_nr::generate_new_tx(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t* action)
|
||||||
|
{
|
||||||
|
// Compute average number of retransmissions per packet considering previous packet
|
||||||
|
harq_entity->average_retx = SRSRAN_VEC_CMA((float)nof_retx, harq_entity->average_retx, harq_entity->nof_pkts++);
|
||||||
|
current_grant = grant;
|
||||||
|
nof_retx = 0;
|
||||||
|
|
||||||
|
logger.info("UL %d: New TX%s, rv=%d, tbs=%d",
|
||||||
|
pid,
|
||||||
|
grant.rnti == harq_entity->mac->get_temp_crnti() ? " for Msg3" : "",
|
||||||
|
grant.rv,
|
||||||
|
grant.tbs);
|
||||||
|
|
||||||
|
generate_tx(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retransmission (Section 5.4.2.2)
|
||||||
|
void ul_harq_entity_nr::ul_harq_process_nr::generate_retx(const mac_interface_phy_nr::mac_nr_grant_ul_t& grant,
|
||||||
|
mac_interface_phy_nr::tb_action_ul_t* action)
|
||||||
|
{
|
||||||
|
logger.info("UL %d: Retx=%d, rv=%d, tbs=%d", pid, nof_retx, grant.rv, grant.tbs);
|
||||||
|
|
||||||
|
// overwrite original grant
|
||||||
|
current_grant = grant;
|
||||||
|
|
||||||
|
generate_tx(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transmission of pending frame (Section 5.4.2.2)
|
||||||
|
void ul_harq_entity_nr::ul_harq_process_nr::generate_tx(mac_interface_phy_nr::tb_action_ul_t* action)
|
||||||
|
{
|
||||||
|
nof_retx++;
|
||||||
|
|
||||||
|
action->tb.rv = current_grant.rv;
|
||||||
|
action->tb.enabled = true;
|
||||||
|
action->tb.payload = harq_buffer.get();
|
||||||
|
action->tb.softbuffer = &softbuffer;
|
||||||
|
|
||||||
|
srsran_softbuffer_tx_reset(&softbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srsue
|
Loading…
Reference in New Issue