ue,rrc: fix cell selection and RRC setup procedure

* fix event processing in RRC procedures
* add UE timer and constants
* parse SRB setup
This commit is contained in:
Andre Puschmann 2022-01-17 17:59:08 +01:00
parent c13797d287
commit e9252c731e
4 changed files with 192 additions and 129 deletions

View File

@ -189,6 +189,11 @@ private:
uint8_t transaction_id = 0;
// RRC constants and timers
uint32_t n310_cnt = 0, N310 = 0;
uint32_t n311_cnt = 0, N311 = 0;
srsran::timer_handler::unique_timer t300, t301, t302, t310, t311, t304;
// Stores the state of the PHY configuration setting
enum {
PHY_CFG_STATE_NONE = 0,
@ -228,6 +233,7 @@ private:
bool apply_sp_cell_ded_ul_pusch(const asn1::rrc_nr::pusch_cfg_s& pusch_cfg);
bool apply_csi_meas_cfg(const asn1::rrc_nr::csi_meas_cfg_s& csi_meas_cfg);
bool apply_res_csi_report_cfg(const asn1::rrc_nr::csi_report_cfg_s& csi_report_cfg);
bool apply_srb_add_mod(const asn1::rrc_nr::srb_to_add_mod_s& srb_cfg);
bool apply_drb_add_mod(const asn1::rrc_nr::drb_to_add_mod_s& drb_cfg);
bool apply_drb_release(const uint8_t drb);
bool apply_security_cfg(const asn1::rrc_nr::security_cfg_s& security_cfg);
@ -237,13 +243,13 @@ private:
typedef enum { mcg_srb1, en_dc_srb3, nr } reconf_initiator_t;
// RRC procedures
enum class cell_search_result_t { changed_cell, same_cell, no_cell };
enum class rrc_cell_search_result_t { changed_cell, same_cell, no_cell };
class cell_selection_proc;
class connection_setup_proc;
class connection_reconf_no_ho_proc;
class setup_request_proc;
srsran::proc_t<cell_selection_proc, cell_search_result_t> cell_selector;
srsran::proc_t<cell_selection_proc, rrc_cell_search_result_t> cell_selector;
srsran::proc_t<connection_setup_proc> conn_setup_proc;
srsran::proc_t<connection_reconf_no_ho_proc> conn_recfg_proc;
srsran::proc_t<setup_request_proc> setup_req_proc;

View File

@ -25,32 +25,30 @@ namespace srsue {
class rrc_nr::cell_selection_proc
{
public:
using cell_selection_complete_ev = srsran::proc_result_t<cell_search_result_t>;
enum class state_t { phy_cell_search, phy_cell_select };
using cell_selection_complete_ev = srsran::proc_result_t<rrc_cell_search_result_t>;
explicit cell_selection_proc(rrc_nr& parent_);
srsran::proc_outcome_t init();
srsran::proc_outcome_t step();
cell_search_result_t get_result() const { return cell_search_ret; }
static const char* name() { return "Cell Selection"; }
srsran::proc_outcome_t react(const rrc_interface_phy_nr::cell_search_result_t& result);
srsran::proc_outcome_t react(const rrc_interface_phy_nr::cell_select_result_t& result);
void then(const srsran::proc_result_t<cell_search_result_t>& proc_result) const;
srsran::proc_outcome_t react(const rrc_interface_phy_nr::cell_search_result_t& event);
srsran::proc_outcome_t react(const rrc_interface_phy_nr::cell_select_result_t& event);
void then(const cell_selection_complete_ev& proc_result) const;
rrc_cell_search_result_t get_result() const { return rrc_search_result; }
static const char* name() { return "Cell Selection"; }
private:
bool is_serv_cell_suitable() const;
srsran::proc_outcome_t set_proc_complete();
srsran::proc_outcome_t handle_cell_search_result(const rrc_interface_phy_nr::cell_search_result_t& result);
// consts
// conts
rrc_nr& rrc_handle;
meas_cell_list<meas_cell_nr>& meas_cells;
// state variables
enum class search_state_t { cell_selection, serv_cell_camp, cell_config, cell_search };
cell_search_result_t cell_search_ret;
search_state_t state;
srsran::proc_future_t<rrc_interface_phy_lte::cell_search_ret_t> cell_search_fut;
srsran::proc_future_t<void> serv_cell_cfg_fut;
phy_cell_t init_serv_cell;
// state vars
rrc_interface_phy_nr::cell_search_result_t phy_search_result = {};
rrc_cell_search_result_t rrc_search_result = {};
state_t state;
};
class rrc_nr::setup_request_proc
@ -74,7 +72,7 @@ private:
// state variables
enum class state_t { cell_selection, config_serving_cell, wait_t300 } state;
cell_search_result_t cell_search_ret;
rrc_cell_search_result_t cell_search_ret;
srsran::proc_future_t<void> serv_cfg_fut;
};

View File

@ -62,6 +62,8 @@ int rrc_nr::init(phy_interface_rrc_nr* phy_,
plmn_is_selected = true; // short-cut SA test
t300 = task_sched.get_unique_timer();
running = true;
sim_measurement_timer = task_sched.get_unique_timer();
return SRSRAN_SUCCESS;
@ -350,9 +352,25 @@ void rrc_nr::handle_sib1(const sib1_s& sib1)
// - uplinkConfigCommon.initialUplinkBWP.rach-ConfigCommon.restricted_set_cfg
// - uplinkConfigCommon.initialUplinkBWP.pusch-ConfigCommon.pusch-TimeDomainResourceAllocationList.p0-NominalWithGrant
// - ss-PBCH-BlockPower
// - ue-TimersAndConstants
// clang-format on
// ue-TimersAndConstants
auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); };
t300.set(sib1.ue_timers_and_consts.t300.to_number(), timer_expire_func);
t301.set(sib1.ue_timers_and_consts.t301.to_number(), timer_expire_func);
t310.set(sib1.ue_timers_and_consts.t310.to_number(), timer_expire_func);
t311.set(sib1.ue_timers_and_consts.t311.to_number(), timer_expire_func);
N310 = sib1.ue_timers_and_consts.n310.to_number();
N311 = sib1.ue_timers_and_consts.n311.to_number();
logger.info("Set Constants and Timers: N310=%d, N311=%d, t300=%d, t301=%d, t310=%d, t311=%d",
N310,
N311,
t300.duration(),
t301.duration(),
t310.duration(),
t311.duration());
// Apply RACH and timeAlginmentTimer configuration
mac_cfg_nr_t mac_cfg = {};
make_mac_rach_cfg(sib1.serving_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.setup(), &mac_cfg.rach_cfg);
@ -456,13 +474,9 @@ int rrc_nr::connection_request(srsran::nr_establishment_cause_t cause, srsran::u
harq_cfg.nof_procs = 8;
mac->set_config(harq_cfg);
// Setup SRB0, 1 and 2
for (int i = 0; i < 3; i++) {
logical_channel_config_t lch = {};
lch.lcid = i;
lch.priority = i + 1;
mac->setup_lcid(lch);
}
// Setup SRB0
logical_channel_config_t lch = {};
mac->setup_lcid(lch);
// Coreset0 configuration
// Get pointA and SSB absolute frequencies
@ -871,6 +885,8 @@ bool rrc_nr::apply_rlc_add_mod(const rlc_bearer_cfg_s& rlc_bearer_cfg)
drb_id = rlc_bearer_cfg.served_radio_bearer.drb_id();
add_lcid_drb(lc_ch_id, drb_id);
is_drb = true;
} else if (rlc_bearer_cfg.served_radio_bearer.type() == rlc_bearer_cfg_s::served_radio_bearer_c_::types::srb_id) {
srb_id = rlc_bearer_cfg.served_radio_bearer.srb_id();
}
} else {
logger.error("In RLC bearer cfg does not contain served radio bearer");
@ -1803,6 +1819,19 @@ bool rrc_nr::apply_drb_release(const uint8_t drb)
return true;
}
bool rrc_nr::apply_srb_add_mod(const srb_to_add_mod_s& srb_cfg)
{
if (srb_cfg.pdcp_cfg_present) {
logger.error("Cannot add SRB - only default configuration supported.");
return false;
}
srsran::pdcp_config_t pdcp_cfg = srsran::make_nr_srb_pdcp_config_t(srb_cfg.srb_id, true);
pdcp->add_bearer(srb_cfg.srb_id, pdcp_cfg);
return true;
}
bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg)
{
if (!drb_cfg.pdcp_cfg_present) {
@ -1900,20 +1929,23 @@ bool rrc_nr::apply_security_cfg(const security_cfg_s& security_cfg)
bool rrc_nr::apply_radio_bearer_cfg(const radio_bearer_cfg_s& radio_bearer_cfg)
{
if (radio_bearer_cfg.drb_to_add_mod_list.size() > 0) {
for (uint32_t i = 0; i < radio_bearer_cfg.drb_to_add_mod_list.size(); i++) {
if (apply_drb_add_mod(radio_bearer_cfg.drb_to_add_mod_list[i]) == false) {
return false;
}
for (const auto& srb : radio_bearer_cfg.srb_to_add_mod_list) {
if (apply_srb_add_mod(srb) == false) {
logger.error("Couldn't apply config for SRB%d.", srb.srb_id);
return false;
}
}
if (radio_bearer_cfg.drb_to_release_list.size() > 0) {
for (uint32_t i = 0; i < radio_bearer_cfg.drb_to_release_list.size(); i++) {
if (apply_drb_release(radio_bearer_cfg.drb_to_release_list[i]) == false) {
return false;
}
for (const auto& drb : radio_bearer_cfg.drb_to_add_mod_list) {
if (apply_drb_add_mod(drb) == false) {
return false;
}
}
for (const auto& drb : radio_bearer_cfg.drb_to_release_list) {
if (apply_drb_release(drb) == false) {
return false;
}
}
if (radio_bearer_cfg.security_cfg_present) {
if (apply_security_cfg(radio_bearer_cfg.security_cfg) == false) {
return false;
@ -1987,8 +2019,24 @@ void rrc_nr::cell_search_found_cell(const rrc_interface_phy_nr::cell_search_resu
cell_selector.trigger(result);
}
void rrc_nr::cell_select_completed(const rrc_interface_phy_nr::cell_select_result_t& result)
{
cell_selector.trigger(result);
}
void rrc_nr::set_phy_config_complete(bool status)
{
logger.info("set_phy_config_complete() status=%d", status);
// inform procedures if they are running
if (conn_setup_proc.is_busy()) {
conn_setup_proc.trigger(status);
}
if (conn_recfg_proc.is_busy()) {
conn_recfg_proc.trigger(status);
}
switch (phy_cfg_state) {
case PHY_CFG_STATE_NONE:
logger.warning("PHY configuration completed without a clear state.");
@ -2005,9 +2053,4 @@ void rrc_nr::set_phy_config_complete(bool status)
phy_cfg_state = PHY_CFG_STATE_NONE;
}
void rrc_nr::cell_select_completed(const rrc_interface_phy_nr::cell_select_result_t& result)
{
cell_selector.trigger(result);
}
} // namespace srsue

View File

@ -183,9 +183,9 @@ proc_outcome_t rrc_nr::setup_request_proc::init(srsran::nr_establishment_cause_t
// TODO: add T302 handling
Info("Initiation of Connection establishment procedure");
Info("Initiation of Setup request procedure");
cell_search_ret = cell_search_result_t::no_cell;
cell_search_ret = rrc_cell_search_result_t::no_cell;
state = state_t::cell_selection;
if (rrc_handle.cell_selector.is_idle()) {
@ -214,15 +214,39 @@ proc_outcome_t rrc_nr::setup_request_proc::step()
rrc_handle.phy_cfg_state = PHY_CFG_STATE_APPLY_SP_CELL;
rrc_handle.phy->set_config(rrc_handle.phy_cfg);
// start T300
rrc_handle.t300.run();
// Send setup request message to lower layers
rrc_handle.send_setup_request(cause);
// Save dedicatedInfoNAS SDU, if needed (TODO: this should be passed to procedure without temp storage)
if (dedicated_info_nas.get()) {
if (rrc_handle.dedicated_info_nas.get()) {
Warning("Received a new dedicatedInfoNAS SDU but there was one still in queue. Removing it.");
rrc_handle.dedicated_info_nas.reset();
}
Debug("Updating dedicatedInfoNAS in RRC");
rrc_handle.dedicated_info_nas = std::move(dedicated_info_nas);
} else {
Debug("dedicatedInfoNAS has already been provided to RRC.");
}
Info("Waiting for RRCSetup/Reject or expiry");
state = state_t::wait_t300;
return step();
} else if (state == state_t::wait_t300) {
// TODO: add T300 waiting
// Wait until t300 stops due to RRCConnectionSetup/Reject or expiry
if (rrc_handle.t300.is_running()) {
return proc_outcome_t::yield;
}
if (rrc_handle.state == RRC_NR_STATE_CONNECTED) {
// Received ConnectionSetup
return proc_outcome_t::success;
}
}
return proc_outcome_t::error;
@ -231,7 +255,7 @@ proc_outcome_t rrc_nr::setup_request_proc::step()
void rrc_nr::setup_request_proc::then(const srsran::proc_state_t& result)
{
if (result.is_error()) {
logger.warning("Could not establish connection. Deallocating dedicatedInfoNAS PDU");
logger.warning("Could not finish setup request. Deallocating dedicatedInfoNAS PDU");
dedicated_info_nas.reset();
rrc_handle.dedicated_info_nas.reset();
} else {
@ -266,18 +290,6 @@ srsran::proc_outcome_t rrc_nr::setup_request_proc::react(const cell_selection_pr
// Skip SI acquisition
return step();
} else {
switch (cell_search_ret) {
case cell_search_result_t::same_cell:
logger.warning("Did not reselect cell but serving cell is out-of-sync.");
break;
case cell_search_result_t::changed_cell:
logger.warning("Selected a new cell but could not camp on. Setting out-of-sync.");
break;
default:
logger.warning("Could not find any suitable cell to connect");
}
return proc_outcome_t::error;
}
}
@ -296,13 +308,16 @@ srsran::proc_outcome_t rrc_nr::connection_setup_proc::init(const asn1::rrc_nr::r
{
Info("Starting...");
// if (dedicated_info_nas_.get() == nullptr) {
// logger.error("Connection Setup Failed, no dedicatedInfoNAS available");
// return proc_outcome_t::error;
// }
if (dedicated_info_nas_.get() == nullptr) {
logger.error("Connection Setup Failed, no dedicatedInfoNAS available");
return proc_outcome_t::error;
}
dedicated_info_nas = std::move(dedicated_info_nas_);
// Stop T300
rrc_handle.t300.stop();
// Apply the Radio Bearer configuration
if (!rrc_handle.apply_radio_bearer_cfg(radio_bearer_cfg_)) {
return proc_outcome_t::error;
@ -336,35 +351,16 @@ void rrc_nr::connection_setup_proc::then(const srsran::proc_state_t& result)
}
/**************************************
* Basic Cell Selection Procedure
* Combined Cell Search/Selection Procedure
*************************************/
rrc_nr::cell_selection_proc::cell_selection_proc(rrc_nr& parent_) :
rrc_handle(parent_), meas_cells(rrc_handle.meas_cells)
{}
/// Verifies if serving cell passes selection criteria, UE is camping, and required SIBs were obtained
bool rrc_nr::cell_selection_proc::is_serv_cell_suitable() const
{
// TODO: add selection criteria
return true;
}
/// Called on procedure exit to set result
proc_outcome_t rrc_nr::cell_selection_proc::set_proc_complete()
{
if (is_serv_cell_suitable()) {
cell_search_ret = is_same_cell(init_serv_cell, meas_cells.serving_cell()) ? cell_search_result_t::same_cell
: cell_search_result_t::changed_cell;
return proc_outcome_t::success;
}
cell_search_ret = cell_search_result_t::no_cell;
return proc_outcome_t::error;
}
rrc_nr::cell_selection_proc::cell_selection_proc(rrc_nr& parent_) : rrc_handle(parent_) {}
// Starts PHY's cell search in the current ARFCN
proc_outcome_t rrc_nr::cell_selection_proc::init()
{
init_serv_cell = meas_cells.serving_cell().phy_cell;
Info("Starting...");
state = state_t::phy_cell_search;
// TODO: add full cell selection
// Start cell search
@ -375,42 +371,29 @@ proc_outcome_t rrc_nr::cell_selection_proc::init()
cs_args.ssb_pattern = rrc_handle.phy_cfg.ssb.pattern;
cs_args.duplex_mode = rrc_handle.phy_cfg.duplex.mode;
if (not rrc_handle.phy->start_cell_search(cs_args)) {
Error("Could not set start cell search.");
Error("Failed to initiate Cell Search.");
return proc_outcome_t::error;
}
state = search_state_t::cell_search;
return proc_outcome_t::yield;
}
// Skipping SI acquisition procedure
proc_outcome_t rrc_nr::cell_selection_proc::step()
{
switch (state) {
case search_state_t::cell_selection:
// this state waits for phy event
return proc_outcome_t::yield;
case search_state_t::serv_cell_camp:
// this state waits for phy event
return proc_outcome_t::yield;
case search_state_t::cell_config:
// return step_cell_config();
return proc_outcome_t::yield;
case search_state_t::cell_search:
// return step_cell_search();
case state_t::phy_cell_search:
case state_t::phy_cell_select:
// Waits for cell select/search to complete
return proc_outcome_t::yield;
}
return proc_outcome_t::error;
return proc_outcome_t::yield;
}
proc_outcome_t rrc_nr::cell_selection_proc::react(const rrc_interface_phy_nr::cell_search_result_t& result)
// Handles result of PHY's cell search and triggers PHY cell select when new cell was found
proc_outcome_t
rrc_nr::cell_selection_proc::handle_cell_search_result(const rrc_interface_phy_nr::cell_search_result_t& result)
{
if (state != search_state_t::cell_search) {
Error("Cell search result received in wrong state");
return proc_outcome_t::error;
}
// Print result only if the cell is found
if (result.cell_found) {
// Convert Cell measurement in Text
std::array<char, 512> csi_info_str = {};
@ -428,37 +411,70 @@ proc_outcome_t rrc_nr::cell_selection_proc::react(const rrc_interface_phy_nr::ce
}
// Logs the PCI, cell measurements and decoded MIB
Info("Cell search found PCI=%d %s %s", result.pci, csi_info_str.data(), mib_info_str.data());
Info("Cell search found ARFCN=%d PCI=%d %s %s",
result.ssb_arfcn,
result.pci,
csi_info_str.data(),
mib_info_str.data());
// Transition to cell selection ignoring the cell search result
state = state_t::phy_cell_select;
phy_interface_rrc_nr::cell_select_args_t cs_args = {};
cs_args.carrier = rrc_handle.phy_cfg.carrier;
cs_args.ssb_cfg = rrc_handle.phy_cfg.get_ssb_cfg();
// until cell selection is done, update PHY config to take the last found PCI
rrc_handle.phy_cfg.carrier.pci = result.pci;
if (not rrc_handle.phy->start_cell_select(cs_args)) {
Error("Could not set start cell search.");
return proc_outcome_t::error;
}
return proc_outcome_t::yield;
} else {
Info("Cell search did not find any cell");
Info("Cell search did not find any cell.");
}
// Transition to cell selection ignoring the cell search result
state = search_state_t::cell_selection;
phy_interface_rrc_nr::cell_select_args_t cs_args = {};
cs_args.carrier = rrc_handle.phy_cfg.carrier;
cs_args.ssb_cfg = rrc_handle.phy_cfg.get_ssb_cfg();
if (not rrc_handle.phy->start_cell_select(cs_args)) {
Error("Could not set start cell search.");
return proc_outcome_t::error;
}
return proc_outcome_t::yield;
return proc_outcome_t::error;
}
proc_outcome_t rrc_nr::cell_selection_proc::react(const rrc_interface_phy_nr::cell_select_result_t& result)
proc_outcome_t rrc_nr::cell_selection_proc::react(const rrc_interface_phy_nr::cell_select_result_t& event)
{
if (state != search_state_t::cell_selection) {
Error("Cell selection result received in wrong state");
if (state != state_t::phy_cell_select) {
Warning("Received unexpected cell search result");
return proc_outcome_t::yield;
}
if (event.status != rrc_interface_phy_nr::cell_select_result_t::SUCCESSFUL) {
Error("Couldn't select new serving cell");
phy_search_result.cell_found = false;
rrc_search_result = rrc_nr::rrc_cell_search_result_t::no_cell;
return proc_outcome_t::error;
}
return set_proc_complete();
rrc_search_result = rrc_nr::rrc_cell_search_result_t::same_cell;
// PHY is now camping on serving cell
Info("Cell search completed.");
return proc_outcome_t::success;
}
void rrc_nr::cell_selection_proc::then(const srsran::proc_result_t<cell_search_result_t>& proc_result) const
proc_outcome_t rrc_nr::cell_selection_proc::react(const rrc_interface_phy_nr::cell_search_result_t& event)
{
if (state != state_t::phy_cell_search) {
Error("Received unexpected cell search result");
return proc_outcome_t::error;
}
phy_search_result = event;
if (phy_search_result.cell_found) {
return handle_cell_search_result(phy_search_result);
}
return proc_outcome_t::error;
}
void rrc_nr::cell_selection_proc::then(const cell_selection_complete_ev& proc_result) const
{
Info("Completed with %s.", proc_result.is_success() ? "success" : "failure");
// Inform Connection Request Procedure