Added mac prach nr proc error handling

This commit is contained in:
David Rupprecht 2021-03-26 18:44:15 +01:00 committed by Andre Puschmann
parent f9ea02b6bf
commit 7a481c40ab
9 changed files with 128 additions and 21 deletions

View File

@ -121,6 +121,11 @@ void mac_rar_subpdu_nr::set_backoff(const uint8_t backoff_indicator_)
backoff_indicator = backoff_indicator_; backoff_indicator = backoff_indicator_;
} }
uint8_t mac_rar_subpdu_nr::get_backoff() const
{
return backoff_indicator;
}
std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> mac_rar_subpdu_nr::get_ul_grant() const std::array<uint8_t, mac_rar_subpdu_nr::UL_GRANT_NBITS> mac_rar_subpdu_nr::get_ul_grant() const
{ {
return ul_grant; return ul_grant;

View File

@ -87,6 +87,9 @@ public:
bool msg3_is_pending() { return mux.msg3_is_pending(); } bool msg3_is_pending() { return mux.msg3_is_pending(); }
bool msg3_is_empty() { return mux.msg3_is_empty(); } bool msg3_is_empty() { return mux.msg3_is_empty(); }
/// RRC
void rrc_ra_problem() { rrc->ra_problem(); }
/// stack interface /// stack interface
void process_pdus(); void process_pdus();

View File

@ -32,6 +32,9 @@ public:
virtual void msg3_flush() = 0; virtual void msg3_flush() = 0;
virtual void msg3_prepare() = 0; virtual void msg3_prepare() = 0;
virtual bool msg3_is_empty() = 0; virtual bool msg3_is_empty() = 0;
// RRC functions
virtual void rrc_ra_problem() = 0;
}; };
/** /**

View File

@ -82,10 +82,12 @@ private:
srsran::timer_handler::unique_timer prach_send_timer; srsran::timer_handler::unique_timer prach_send_timer;
srsran::timer_handler::unique_timer rar_timeout_timer; srsran::timer_handler::unique_timer rar_timeout_timer;
srsran::timer_handler::unique_timer contention_resolution_timer; srsran::timer_handler::unique_timer contention_resolution_timer;
srsran::timer_handler::unique_timer backoff_timer;
// 38.321 5.1.1 Variables // 38.321 5.1.1 Variables
uint32_t preamble_index = 0; uint32_t preamble_index = 0;
uint32_t preamble_transmission_counter = 0; uint32_t preamble_transmission_counter = 0;
uint32_t preamble_backoff = 0; // in ms
uint32_t preamble_power_ramping_step = 0; uint32_t preamble_power_ramping_step = 0;
int preamble_received_target_power = 0; int preamble_received_target_power = 0;
uint32_t scaling_factor_bi = 0; uint32_t scaling_factor_bi = 0;

View File

@ -96,13 +96,12 @@ public:
void in_sync() final; void in_sync() final;
void out_of_sync() final; void out_of_sync() final;
// MAC interface
void run_tti(uint32_t tti) final;
// RLC interface // RLC interface
void max_retx_attempted() final; void max_retx_attempted() final;
// MAC interface // MAC interface
void run_tti(uint32_t tti) final;
void ra_completed() final; void ra_completed() final;
void ra_problem() final; void ra_problem() final;
void release_pucch_srs() final; void release_pucch_srs() final;

View File

@ -322,7 +322,7 @@ bool mac_nr::set_crnti(const uint16_t c_rnti_)
void mac_nr::start_ra_procedure() void mac_nr::start_ra_procedure()
{ {
proc_ra.start_by_rrc(); stack_task_dispatch_queue.push([this]() {proc_ra.start_by_rrc();});
} }
bool mac_nr::is_valid_crnti(const uint16_t crnti) bool mac_nr::is_valid_crnti(const uint16_t crnti)

View File

@ -40,6 +40,7 @@ void proc_ra_nr::init(phy_interface_mac_nr* phy_, srsran::ext_task_sched_handle*
prach_send_timer = task_sched->get_unique_timer(); prach_send_timer = task_sched->get_unique_timer();
rar_timeout_timer = task_sched->get_unique_timer(); rar_timeout_timer = task_sched->get_unique_timer();
contention_resolution_timer = task_sched->get_unique_timer(); contention_resolution_timer = task_sched->get_unique_timer();
backoff_timer = task_sched->get_unique_timer();
} }
/* Sets a new configuration. The configuration is applied by initialization() function */ /* Sets a new configuration. The configuration is applied by initialization() function */
@ -124,15 +125,18 @@ uint16_t proc_ra_nr::get_temp_rnti()
void proc_ra_nr::timer_expired(uint32_t timer_id) void proc_ra_nr::timer_expired(uint32_t timer_id)
{ {
if (prach_send_timer.id() == timer_id) { if (prach_send_timer.id() == timer_id) {
logger.error("PRACH Send timer expired. PRACH was not transmitted within %d ttis by phy. (TODO)", logger.warning("PRACH Send timer expired. PRACH was not transmitted within %d ttis by phy. (TODO)",
prach_send_timer.duration()); prach_send_timer.duration());
ra_error(); ra_error();
} else if (rar_timeout_timer.id() == timer_id) { } else if (rar_timeout_timer.id() == timer_id) {
logger.error("RAR Timer expired. RA response not received within the response window Response Error (TODO)"); logger.warning("RAR Timer expired. RA response not received within the response window");
ra_error(); ra_error();
} else if (contention_resolution_timer.id() == timer_id) { } else if (contention_resolution_timer.id() == timer_id) {
logger.error("Contention Resolution Timer expired. Stopping PDCCH Search and going to Response Error (TODO)"); logger.warning("Contention Resolution Timer expired. Stopping PDCCH Search and going to Response Error (TODO)");
ra_error(); ra_error();
} else if (backoff_timer.id() == timer_id) {
logger.info("Transmitting new preamble (%d/%d)", preamble_transmission_counter, rach_cfg.preambleTransMax);
ra_resource_selection();
} else { } else {
logger.error("Timer not implemented"); logger.error("Timer not implemented");
} }
@ -142,8 +146,10 @@ void proc_ra_nr::timer_expired(uint32_t timer_id)
void proc_ra_nr::ra_procedure_initialization() void proc_ra_nr::ra_procedure_initialization()
{ {
mac.msg3_flush(); mac.msg3_flush();
preamble_transmission_counter = 1;
preamble_power_ramping_step = rach_cfg.powerRampingStep; preamble_power_ramping_step = rach_cfg.powerRampingStep;
scaling_factor_bi = 1; scaling_factor_bi = 1;
preamble_backoff = 0;
preambleTransMax = rach_cfg.preambleTransMax; preambleTransMax = rach_cfg.preambleTransMax;
ra_resource_selection(); ra_resource_selection();
} }
@ -205,6 +211,13 @@ void proc_ra_nr::ra_response_reception(const mac_interface_phy_nr::mac_nr_grant_
rar_rnti = SRSRAN_INVALID_RNTI; rar_rnti = SRSRAN_INVALID_RNTI;
mac.msg3_prepare(); mac.msg3_prepare();
current_ta = subpdu.get_ta(); current_ta = subpdu.get_ta();
// Set Backoff parameter
if (subpdu.has_backoff()) {
preamble_backoff = backoff_table_nr[subpdu.get_backoff() % 16]; // TODO multiplied with SCALING_FACTOR_BI.
} else {
preamble_backoff = 0;
}
} }
} }
} }
@ -265,7 +278,31 @@ void proc_ra_nr::ra_completion()
void proc_ra_nr::ra_error() void proc_ra_nr::ra_error()
{ {
logger.error("NR random access procedure error recovery not implemented yet"); temp_rnti = 0;
preamble_transmission_counter++;
contention_resolution_timer.stop();
uint32_t backoff_wait;
bool ra_procedure_completed = false; // true = (unsuccessfully) completed, false = uncompleted
if (preamble_transmission_counter >= rach_cfg.preambleTransMax + 1) {
logger.warning("Maximum number of transmissions reached (%d)", rach_cfg.preambleTransMax);
// if the Random Access Preamble is transmitted on the SpCell assumption (TODO)
mac.rrc_ra_problem(); // indicate a Random Access problem to upper layers;
if (started_by == initiators_t::MAC) { // if this Random Access procedure was triggered for SI request
ra_procedure_completed = true; // consider the Random Access procedure unsuccessfully completed.
reset();
}
} else {
// if the Random Access procedure is not completed
if (preamble_backoff) {
backoff_wait = rand() % preamble_backoff;
} else {
backoff_wait = 0;
}
logger.warning("Backoff wait interval %d", backoff_wait);
backoff_timer.set(backoff_wait, [this](uint32_t tid) { timer_expired(tid); });
backoff_timer.run();
}
} }
// Is called by PHY once it has transmitted the prach transmitted, than configure RA-RNTI and wait for RAR reception // Is called by PHY once it has transmitted the prach transmitted, than configure RA-RNTI and wait for RAR reception
@ -297,7 +334,7 @@ void proc_ra_nr::prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t
tti); tti);
uint32_t rar_window_st = TTI_ADD(tti, 3); uint32_t rar_window_st = TTI_ADD(tti, 3);
// TODO check ra_response window (delayed start)? // last 3 check if needed when we have a delayed start // TODO check ra_response window (delayed start)? // last 3 check if needed when we have a delayed start
rar_timeout_timer.set(rach_cfg.ra_responseWindow + 3 + 3, [this](uint32_t tid) { timer_expired(tid); }); rar_timeout_timer.set(rach_cfg.ra_responseWindow + 3 + 10, [this](uint32_t tid) { timer_expired(tid); });
rar_timeout_timer.run(); rar_timeout_timer.run();
// Wait for RAR reception // Wait for RAR reception
ra_window_length = rach_cfg.ra_responseWindow; ra_window_length = rach_cfg.ra_responseWindow;

View File

@ -1190,7 +1190,11 @@ void rrc_nr::max_retx_attempted() {}
// MAC interface // MAC interface
void rrc_nr::ra_completed() {} void rrc_nr::ra_completed() {}
void rrc_nr::ra_problem() {} void rrc_nr::ra_problem()
{
rrc_eutra->nr_scg_failure_information(scg_failure_cause_t::random_access_problem);
}
void rrc_nr::release_pucch_srs() {} void rrc_nr::release_pucch_srs() {}
// STACK interface // STACK interface
@ -1245,7 +1249,7 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator
return proc_outcome_t::error; return proc_outcome_t::error;
} }
rrc_ptr->log_rrc_message("RRC NR Reconfiguration", rrc_ptr->log_rrc_message("RRC NRf Reconfiguration",
Rx, Rx,
rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group, rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group,
cell_group_cfg, cell_group_cfg,

View File

@ -53,6 +53,7 @@ private:
class dummy_mac : public mac_interface_proc_ra_nr class dummy_mac : public mac_interface_proc_ra_nr
{ {
public: public:
dummy_mac() : logger(srslog::fetch_basic_logger("MAC")) {}
uint64_t get_contention_id() { return 0xdeadbeaf; } uint64_t get_contention_id() { return 0xdeadbeaf; }
uint16_t get_crnti() { return crnti; } uint16_t get_crnti() { return crnti; }
bool set_crnti(uint16_t c_rnti) bool set_crnti(uint16_t c_rnti)
@ -67,26 +68,24 @@ public:
bool msg3_is_empty() { return true; } bool msg3_is_empty() { return true; }
void msga_flush(){}; void msga_flush(){};
// RRC RA problem
void rrc_ra_problem() { logger.warning("Dummy MAC RRC ra problem"); }
private: private:
uint16_t crnti = SRSRAN_INVALID_RNTI; uint16_t crnti = SRSRAN_INVALID_RNTI;
srslog::basic_logger& logger;
}; };
int main() int proc_ra_normal_test()
{ {
srslog::init();
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.set_level(srslog::basic_levels::debug);
mac_logger.set_hex_dump_max_size(-1);
dummy_phy dummy_phy; dummy_phy dummy_phy;
dummy_mac dummy_mac; dummy_mac dummy_mac;
srsran::task_scheduler task_sched{5, 2}; srsran::task_scheduler task_sched{5, 2};
srsran::ext_task_sched_handle ext_task_sched_h(&task_sched); srsran::ext_task_sched_handle ext_task_sched_h(&task_sched);
proc_ra_nr proc_ra_nr(dummy_mac, mac_logger); proc_ra_nr proc_ra_nr(dummy_mac, srslog::fetch_basic_logger("MAC"));
proc_ra_nr.init(&dummy_phy, &ext_task_sched_h); proc_ra_nr.init(&dummy_phy, &ext_task_sched_h);
TESTASSERT(proc_ra_nr.is_rar_opportunity(1) == false); TESTASSERT(proc_ra_nr.is_rar_opportunity(1) == false);
srsran::rach_nr_cfg_t rach_cfg; srsran::rach_nr_cfg_t rach_cfg;
rach_cfg.powerRampingStep = 4; rach_cfg.powerRampingStep = 4;
@ -105,7 +104,7 @@ int main()
dummy_phy.get_last_send_prach(&prach_occasion, &preamble_index, &preamble_received_target_power); dummy_phy.get_last_send_prach(&prach_occasion, &preamble_index, &preamble_received_target_power);
TESTASSERT(prach_occasion == 0); TESTASSERT(prach_occasion == 0);
TESTASSERT(preamble_index == 0); TESTASSERT(preamble_index == 0);
TESTASSERT(preamble_received_target_power == -114); TESTASSERT(preamble_received_target_power == -110);
// Simulate PHY and call prach_sent (random values) // Simulate PHY and call prach_sent (random values)
uint32_t tti_start = 0; uint32_t tti_start = 0;
proc_ra_nr.prach_sent(tti_start, 7, 1, 0, 0); proc_ra_nr.prach_sent(tti_start, 7, 1, 0, 0);
@ -135,9 +134,64 @@ int main()
task_sched.tic(); task_sched.tic();
task_sched.run_pending_tasks(); task_sched.run_pending_tasks();
proc_ra_nr.pdcch_to_crnti(); return SRSRAN_SUCCESS;
}
int proc_ra_timeout_test()
{
dummy_phy dummy_phy;
dummy_mac dummy_mac;
srsran::task_scheduler task_sched{5, 2};
srsran::ext_task_sched_handle ext_task_sched_h(&task_sched);
proc_ra_nr proc_ra_nr(dummy_mac, srslog::fetch_basic_logger("MAC"));
proc_ra_nr.init(&dummy_phy, &ext_task_sched_h);
TESTASSERT(proc_ra_nr.is_rar_opportunity(1) == false);
srsran::rach_nr_cfg_t rach_cfg;
rach_cfg.powerRampingStep = 4;
rach_cfg.prach_ConfigurationIndex = 16;
rach_cfg.PreambleReceivedTargetPower = -110;
rach_cfg.preambleTransMax = 7;
rach_cfg.ra_ContentionResolutionTimer = 64;
rach_cfg.ra_responseWindow = 10;
proc_ra_nr.set_config(rach_cfg);
proc_ra_nr.start_by_rrc();
// Test send prach parameters
uint32_t prach_occasion = 0;
uint32_t preamble_index = 0;
int preamble_received_target_power = 0;
dummy_phy.get_last_send_prach(&prach_occasion, &preamble_index, &preamble_received_target_power);
TESTASSERT(prach_occasion == 0);
TESTASSERT(preamble_index == 0);
TESTASSERT(preamble_received_target_power == -110);
// Simulate PHY and call prach_sent (random values)
uint32_t tti = 0;
for (uint32_t j = 0; j < rach_cfg.preambleTransMax; j++) {
proc_ra_nr.prach_sent(tti, 7, 1, 0, 0);
uint32_t i = 0;
for (i = tti; i < tti + rach_cfg.ra_responseWindow + 100; i++) {
// update clock and run internal tasks
task_sched.tic();
task_sched.run_pending_tasks();
}
tti = i;
}
task_sched.tic(); task_sched.tic();
task_sched.run_pending_tasks(); task_sched.run_pending_tasks();
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
int main()
{
srslog::init();
auto& mac_logger = srslog::fetch_basic_logger("MAC");
mac_logger.set_level(srslog::basic_levels::debug);
mac_logger.set_hex_dump_max_size(-1);
// TESTASSERT(proc_ra_normal_test() == SRSRAN_SUCCESS);
TESTASSERT(proc_ra_timeout_test() == SRSRAN_SUCCESS);
return SRSRAN_SUCCESS;
}