Merge remote-tracking branch 'origin/sa_ue_rrc2' into feature_nr_sa_igm

master
Ismael Gomez 3 years ago
commit 15025f5d57

@ -135,7 +135,9 @@ public:
private:
// senders
void send_setup_request(srsran::nr_establishment_cause_t cause);
void send_ul_info_transfer(srsran::unique_byte_buffer_t nas_msg);
void send_ul_ccch_msg(const asn1::rrc_nr::ul_ccch_msg_s& msg);
srsran::task_sched_handle task_sched;
struct cmd_msg_t {
@ -162,6 +164,10 @@ private:
meas_cell_list<meas_cell_nr> meas_cells;
// PLMN
bool plmn_is_selected = false;
srsran::unique_byte_buffer_t dedicated_info_nas;
const uint32_t sim_measurement_timer_duration_ms = 250;
uint32_t sim_measurement_carrier_freq_r15;
srsran::timer_handler::unique_timer sim_measurement_timer;
@ -176,7 +182,7 @@ private:
const static char* rrc_nr_state_text[RRC_NR_STATE_N_ITEMS];
rrc_nr_state_t state = RRC_NR_STATE_IDLE;
// Stores the state of the PHy configuration setting
// Stores the state of the PHY configuration setting
enum {
PHY_CFG_STATE_NONE = 0,
PHY_CFG_STATE_APPLY_SP_CELL,
@ -222,9 +228,14 @@ 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 };
class cell_selection_proc;
class connection_reconf_no_ho_proc;
class setup_request_proc;
srsran::proc_t<connection_reconf_no_ho_proc> conn_recfg_proc;
srsran::proc_t<cell_selection_proc, cell_search_result_t> cell_selector;
srsran::proc_t<connection_reconf_no_ho_proc> conn_recfg_proc;
srsran::proc_t<setup_request_proc> setup_req_proc;
srsran::proc_manager_list_t callback_list;
};

@ -22,10 +22,65 @@ namespace srsue {
* Procedures
*******************************/
class rrc_nr::cell_selection_proc
{
public:
using cell_selection_complete_ev = srsran::proc_result_t<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 bool& event);
void then(const srsran::proc_result_t<cell_search_result_t>& proc_result) const;
private:
bool is_serv_cell_suitable() const;
srsran::proc_outcome_t set_proc_complete();
// consts
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;
};
class rrc_nr::setup_request_proc
{
public:
explicit setup_request_proc(rrc_nr& parent_);
srsran::proc_outcome_t init(srsran::nr_establishment_cause_t cause_,
srsran::unique_byte_buffer_t dedicated_info_nas_);
srsran::proc_outcome_t step();
void then(const srsran::proc_state_t& result);
srsran::proc_outcome_t react(const cell_selection_proc::cell_selection_complete_ev& e);
static const char* name() { return "Setup Request"; }
private:
// const
rrc_nr& rrc_handle;
srslog::basic_logger& logger;
// args
srsran::nr_establishment_cause_t cause;
srsran::unique_byte_buffer_t dedicated_info_nas;
// state variables
enum class state_t { cell_selection, config_serving_cell, wait_t300 } state;
cell_search_result_t cell_search_ret;
srsran::proc_future_t<void> serv_cfg_fut;
};
class rrc_nr::connection_reconf_no_ho_proc
{
public:
explicit connection_reconf_no_ho_proc(rrc_nr* parent_);
explicit connection_reconf_no_ho_proc(rrc_nr& parent_);
srsran::proc_outcome_t init(const reconf_initiator_t initiator_,
const bool endc_release_and_add_r15,
const bool nr_secondary_cell_group_cfg_r15_present,
@ -41,7 +96,7 @@ public:
private:
// const
rrc_nr* rrc_ptr = nullptr;
rrc_nr& rrc_handle;
reconf_initiator_t initiator;
asn1::rrc_nr::rrc_recfg_s rrc_recfg;
asn1::rrc_nr::cell_group_cfg_s cell_group_cfg;

@ -28,7 +28,12 @@ namespace srsue {
const char* rrc_nr::rrc_nr_state_text[] = {"IDLE", "CONNECTED", "CONNECTED-INACTIVE"};
rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) :
logger(srslog::fetch_basic_logger("RRC-NR")), task_sched(task_sched_), conn_recfg_proc(this), meas_cells(task_sched_)
logger(srslog::fetch_basic_logger("RRC-NR")),
task_sched(task_sched_),
conn_recfg_proc(*this),
setup_req_proc(*this),
cell_selector(*this),
meas_cells(task_sched_)
{}
rrc_nr::~rrc_nr() = default;
@ -54,6 +59,8 @@ int rrc_nr::init(phy_interface_rrc_nr* phy_,
stack = stack_;
args = args_;
plmn_is_selected = true; // short-cut SA test
running = true;
sim_measurement_timer = task_sched.get_unique_timer();
return SRSRAN_SUCCESS;
@ -222,8 +229,10 @@ bool rrc_nr::is_connected()
return false;
}
int rrc_nr::connection_request(srsran::nr_establishment_cause_t cause, srsran::unique_byte_buffer_t sdu)
int rrc_nr::connection_request(srsran::nr_establishment_cause_t cause, srsran::unique_byte_buffer_t dedicated_info_nas_)
{
// TODO:
// Assume cell has been found and SSB with MIB has been decoded
srsran::phy_cfg_nr_default_t::reference_cfg_t cfg = {};
cfg.carrier = srsran::phy_cfg_nr_default_t::reference_cfg_t::R_CARRIER_CUSTOM_10MHZ;
cfg.duplex = srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_FDD;
@ -234,17 +243,11 @@ int rrc_nr::connection_request(srsran::nr_establishment_cause_t cause, srsran::u
phy_cfg.carrier.dl_center_frequency_hz = 1842.5e6;
phy_cfg.carrier.ul_center_frequency_hz = 1747.5e6;
phy_interface_rrc_nr::cell_select_args_t cell_cfg = {};
cell_cfg.carrier = phy_cfg.carrier;
cell_cfg.ssb_cfg = phy_cfg.get_ssb_cfg();
phy->start_cell_select(cell_cfg);
sleep(1);
srsran::rach_nr_cfg_t rach_cfg = {};
mac->set_config(rach_cfg);
phy_cfg_state = PHY_CFG_STATE_APPLY_SP_CELL;
phy->set_config(phy_cfg);
if (not setup_req_proc.launch(cause, std::move(dedicated_info_nas_))) {
logger.error("Failed to initiate setup request procedure");
return SRSRAN_ERROR;
}
callback_list.add_proc(setup_req_proc);
return SRSRAN_SUCCESS;
}
@ -264,6 +267,58 @@ void rrc_nr::send_ul_info_transfer(unique_byte_buffer_t nas_msg)
logger.warning("%s not implemented yet.", __FUNCTION__);
}
void rrc_nr::send_setup_request(srsran::nr_establishment_cause_t cause)
{
logger.debug("Preparing RRC Setup Request");
// Prepare SetupRequest packet
ul_ccch_msg_s ul_ccch_msg;
rrc_setup_request_ies_s* rrc_setup_req = &ul_ccch_msg.msg.set_c1().set_rrc_setup_request().rrc_setup_request;
// TODO: implement ng_minus5_g_s_tmsi_part1
rrc_setup_req->ue_id.set_random_value();
// TODO use proper RNG
uint64_t random_id = 0;
for (uint i = 0; i < 5; i++) { // fill random ID bytewise, 40 bits = 5 bytes
random_id |= ((uint64_t)rand() & 0xFF) << i * 8;
}
rrc_setup_req->ue_id.random_value().from_number(random_id);
rrc_setup_req->establishment_cause = (establishment_cause_opts::options)cause;
send_ul_ccch_msg(ul_ccch_msg);
}
void rrc_nr::send_ul_ccch_msg(const asn1::rrc_nr::ul_ccch_msg_s& msg)
{
unique_byte_buffer_t pdu = srsran::make_byte_buffer();
if (pdu == nullptr) {
logger.error("Couldn't allocate PDU in %s().", __FUNCTION__);
return;
}
asn1::bit_ref bref(pdu->msg, pdu->get_tailroom());
msg.pack(bref);
bref.align_bytes_zero();
pdu->N_bytes = (uint32_t)bref.distance_bytes(pdu->msg);
pdu->set_timestamp();
// Set UE contention resolution ID in MAC
uint64_t uecri = 0;
uint8_t* ue_cri_ptr = (uint8_t*)&uecri;
uint32_t nbytes = 6;
for (uint32_t i = 0; i < nbytes; i++) {
ue_cri_ptr[nbytes - i - 1] = pdu->msg[i];
}
logger.debug("Setting UE contention resolution ID: %" PRIu64 "", uecri);
mac->set_contention_id(uecri);
uint32_t lcid = 0;
log_rrc_message(get_rb_name(lcid), Tx, pdu.get(), msg, msg.msg.c1().type().to_string());
rlc->write_sdu(lcid, std::move(pdu));
}
// EUTRA-RRC interface
int rrc_nr::get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps_pdu)
{
@ -1564,6 +1619,7 @@ bool rrc_nr::apply_radio_bearer_cfg(const radio_bearer_cfg_s& radio_bearer_cfg)
}
return true;
}
// RLC interface
void rrc_nr::max_retx_attempted() {}
void rrc_nr::protocol_failure() {}
@ -1575,6 +1631,7 @@ void rrc_nr::ra_completed()
phy->set_config(phy_cfg);
phy_cfg_state = PHY_CFG_STATE_RA_COMPLETED;
}
void rrc_nr::ra_problem()
{
rrc_eutra->nr_scg_failure_information(scg_failure_cause_t::random_access_problem);

@ -13,10 +13,10 @@
#include "srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h"
#include "srsran/common/standard_streams.h"
#define Error(fmt, ...) rrc_ptr->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define Warning(fmt, ...) rrc_ptr->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define Info(fmt, ...) rrc_ptr->logger.info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define Debug(fmt, ...) rrc_ptr->logger.debug("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define Error(fmt, ...) rrc_handle.logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define Warning(fmt, ...) rrc_handle.logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define Info(fmt, ...) rrc_handle.logger.info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define Debug(fmt, ...) rrc_handle.logger.debug("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
using namespace asn1::rrc_nr;
using namespace asn1;
@ -24,7 +24,8 @@ using namespace srsran;
namespace srsue {
rrc_nr::connection_reconf_no_ho_proc::connection_reconf_no_ho_proc(rrc_nr* parent_) : rrc_ptr(parent_), initiator(nr) {}
rrc_nr::connection_reconf_no_ho_proc::connection_reconf_no_ho_proc(rrc_nr& parent_) : rrc_handle(parent_), initiator(nr)
{}
proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator_t initiator_,
const bool endc_release_and_add_r15,
@ -55,6 +56,7 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator
rrc_ptr->log_rrc_message(
"RRC NR Reconfiguration", Rx, nr_secondary_cell_group_cfg_r15, rrc_recfg, "NR Secondary Cell Group Cfg R15");
#endif
if (rrc_recfg.crit_exts.type() != asn1::rrc_nr::rrc_recfg_s::crit_exts_c_::types::rrc_recfg) {
Error("Reconfiguration does not contain Secondary Cell Group Config");
return proc_outcome_t::error;
@ -83,14 +85,14 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator
#endif
Info("Applying Cell Group Cfg");
if (!rrc_ptr->apply_cell_group_cfg(cell_group_cfg)) {
if (!rrc_handle.apply_cell_group_cfg(cell_group_cfg)) {
return proc_outcome_t::error;
}
}
if (sk_counter_r15_present) {
Info("Applying Cell Group Cfg");
if (!rrc_ptr->configure_sk_counter((uint16_t)sk_counter_r15)) {
if (!rrc_handle.configure_sk_counter((uint16_t)sk_counter_r15)) {
return proc_outcome_t::error;
}
}
@ -110,7 +112,7 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator
#endif
Info("Applying Radio Bearer Cfg");
if (!rrc_ptr->apply_radio_bearer_cfg(radio_bearer_cfg)) {
if (!rrc_handle.apply_radio_bearer_cfg(radio_bearer_cfg)) {
return proc_outcome_t::error;
}
}
@ -140,12 +142,12 @@ void rrc_nr::connection_reconf_no_ho_proc::then(const srsran::proc_state_t& resu
if (result.is_success()) {
Info("Finished %s successfully", name());
srsran::console("RRC NR reconfiguration successful.\n");
rrc_ptr->rrc_eutra->nr_rrc_con_reconfig_complete(true);
rrc_handle.rrc_eutra->nr_rrc_con_reconfig_complete(true);
} else {
// 5.3.5.8.2 Inability to comply with RRCReconfiguration
switch (initiator) {
case reconf_initiator_t::mcg_srb1:
rrc_ptr->rrc_eutra->nr_notify_reconfiguration_failure();
rrc_handle.rrc_eutra->nr_notify_reconfiguration_failure();
break;
default:
Warning("Reconfiguration failure not implemented for initiator %d", initiator);
@ -157,4 +159,207 @@ void rrc_nr::connection_reconf_no_ho_proc::then(const srsran::proc_state_t& resu
return;
}
/**************************************
* RRC Setup Request Procedure
*************************************/
rrc_nr::setup_request_proc::setup_request_proc(rrc_nr& parent_) :
rrc_handle(parent_), logger(srslog::fetch_basic_logger("RRC"))
{}
proc_outcome_t rrc_nr::setup_request_proc::init(srsran::nr_establishment_cause_t cause_,
srsran::unique_byte_buffer_t dedicated_info_nas_)
{
cause = cause_;
dedicated_info_nas = std::move(dedicated_info_nas_);
if (!rrc_handle.plmn_is_selected) {
Error("Trying to connect but PLMN not selected.");
return proc_outcome_t::error;
}
if (rrc_handle.state != RRC_NR_STATE_IDLE) {
logger.warning("Requested RRC connection establishment while not in IDLE");
return proc_outcome_t::error;
}
// TODO: add T302 handling
Info("Initiation of Connection establishment procedure");
cell_search_ret = cell_search_result_t::no_cell;
state = state_t::cell_selection;
if (rrc_handle.cell_selector.is_idle()) {
// No one is running cell selection
if (not rrc_handle.cell_selector.launch()) {
Error("Failed to initiate cell selection procedure...");
return proc_outcome_t::error;
}
rrc_handle.callback_list.add_proc(rrc_handle.cell_selector);
} else {
Info("Cell selection proc already on-going. Wait for its result");
}
return proc_outcome_t::yield;
}
proc_outcome_t rrc_nr::setup_request_proc::step()
{
if (state == state_t::cell_selection) {
// NOTE: cell selection will signal back with an event trigger
return proc_outcome_t::yield;
}
if (state == state_t::config_serving_cell) {
// TODO: start serving cell config and start T300
srsran::rach_nr_cfg_t rach_cfg = {};
rrc_handle.mac->set_config(rach_cfg);
rrc_handle.phy_cfg_state = PHY_CFG_STATE_APPLY_SP_CELL;
rrc_handle.phy->set_config(rrc_handle.phy_cfg);
// Send setup request message to lower layers
rrc_handle.send_setup_request(cause);
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
}
return proc_outcome_t::error;
}
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");
dedicated_info_nas.reset();
rrc_handle.dedicated_info_nas.reset();
} else {
Info("Finished connection request procedure successfully.");
}
// TODO: signal back to NAS
// rrc_handle.nas->connection_request_completed(result.is_success());
}
srsran::proc_outcome_t rrc_nr::setup_request_proc::react(const cell_selection_proc::cell_selection_complete_ev& e)
{
if (state != state_t::cell_selection) {
// ignore if we are not expecting an cell selection result
return proc_outcome_t::yield;
}
if (e.is_error()) {
return proc_outcome_t::error;
}
cell_search_ret = *e.value();
// .. and SI acquisition
// TODO @ismagom use appropiate PHY interface
if (true /*rrc_handle.phy->cell_is_camping()*/) {
// TODO: Set default configurations
// rrc_handle.set_phy_default();
// rrc_handle.set_mac_default();
// CCCH configuration applied already at start
// timeAlignmentCommon applied in configure_serving_cell
Info("Configuring serving cell...");
state = state_t::config_serving_cell;
// 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;
}
}
/**************************************
* Basic Cell 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;
}
proc_outcome_t rrc_nr::cell_selection_proc::init()
{
init_serv_cell = meas_cells.serving_cell().phy_cell;
// Skip cell selection if serving cell is suitable and there are no stronger neighbours in same earfcn
if (is_serv_cell_suitable()) {
Debug("Skipping cell selection procedure as there are no stronger neighbours in same EARFCN.");
return set_proc_complete();
}
// TODO: add full cell selection
phy_interface_rrc_nr::cell_select_args_t cell_cfg = {};
cell_cfg.carrier = rrc_handle.phy_cfg.carrier;
cell_cfg.ssb_cfg = rrc_handle.phy_cfg.get_ssb_cfg();
rrc_handle.phy->start_cell_select(cell_cfg);
return set_proc_complete();
}
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();
return proc_outcome_t::yield;
}
return proc_outcome_t::error;
}
void rrc_nr::cell_selection_proc::then(const srsran::proc_result_t<cell_search_result_t>& proc_result) const
{
Info("Completed with %s.", proc_result.is_success() ? "success" : "failure");
// Inform Connection Request Procedure
rrc_handle.task_sched.defer_task([this, proc_result]() {
if (rrc_handle.setup_req_proc.is_busy()) {
rrc_handle.setup_req_proc.trigger(proc_result);
}
});
}
} // namespace srsue

@ -62,7 +62,15 @@ class dummy_rlc : public rlc_interface_rrc
bool has_bearer(uint32_t lcid) { return true; }
bool has_data(const uint32_t lcid) { return true; }
bool is_suspended(const uint32_t lcid) { return true; }
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {}
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu)
{
last_lcid = lcid;
last_sdu = std::move(sdu);
}
public:
uint32_t last_lcid = 99;
srsran::unique_byte_buffer_t last_sdu;
};
class dummy_pdcp : public pdcp_interface_rrc
@ -211,9 +219,53 @@ int rrc_nr_reconfig_test()
return SRSRAN_SUCCESS;
}
int rrc_nr_conn_setup_test()
{
srslog::init();
srslog::basic_logger& logger = srslog::fetch_basic_logger("RRC-NR");
logger.set_level(srslog::basic_levels::debug);
logger.set_hex_dump_max_size(-1);
srsran::task_scheduler task_sched{512, 100};
srsran::task_sched_handle task_sched_handle(&task_sched);
rrc_nr rrc_nr(task_sched_handle);
srsran::byte_buffer_t caps;
dummy_phy dummy_phy;
dummy_mac dummy_mac;
dummy_rlc dummy_rlc;
dummy_pdcp dummy_pdcp;
dummy_gw dummy_gw;
dummy_eutra dummy_eutra;
dummy_sim dummy_sim;
dummy_stack dummy_stack;
rrc_nr_args_t rrc_nr_args;
rrc_nr_args.supported_bands_nr.push_back(78);
TESTASSERT(rrc_nr.init(&dummy_phy,
&dummy_mac,
&dummy_rlc,
&dummy_pdcp,
&dummy_gw,
&dummy_eutra,
&dummy_sim,
task_sched.get_timer_handler(),
&dummy_stack,
rrc_nr_args) == SRSRAN_SUCCESS);
rrc_nr.connection_request(srsran::nr_establishment_cause_t::mt_Access, nullptr);
task_sched.run_pending_tasks();
TESTASSERT(dummy_rlc.last_lcid == 0); // SRB0 transmission
TESTASSERT(dummy_rlc.last_sdu->N_bytes == 6); // RRC Setup Request is 6 Bytes long
return SRSRAN_SUCCESS;
}
int main(int argc, char** argv)
{
TESTASSERT(rrc_nr_cap_request_test() == SRSRAN_SUCCESS);
TESTASSERT(rrc_nr_reconfig_test() == SRSRAN_SUCCESS);
TESTASSERT(rrc_nr_conn_setup_test() == SRSRAN_SUCCESS);
return SRSRAN_SUCCESS;
}

Loading…
Cancel
Save