diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 69724177c..de58bebee 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -14,6 +14,7 @@ #define SRSUE_RRC_NR_H #include "srslte/asn1/rrc_nr.h" +#include "srslte/asn1/rrc_nr_utils.h" #include "srslte/common/block_queue.h" #include "srslte/common/buffer_pool.h" #include "srslte/interfaces/nr_common_interface_types.h" @@ -154,6 +155,29 @@ private: std::string get_rb_name(uint32_t lcid) final { return srslte::to_string((srslte::rb_id_nr_t)lcid); } + typedef enum { Srb = 0, Drb } rb_type_t; + typedef struct { + uint32_t rb_id; + rb_type_t rb_type; + } rb_t; + + bool add_lcid_rb(uint32_t lcid, rb_type_t rb_type, uint32_t rbid); + uint32_t get_lcid_for_rbid(uint32_t rdid); + + std::map lcid_rb; // Map of lcid to radio bearer (type and rb id) + + std::map drb_eps_bearer_id; // Map of drb id to eps_bearer_id + + bool apply_cell_group_cfg(const asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg); + bool apply_radio_bearer_cfg(const asn1::rrc_nr::radio_bearer_cfg_s& radio_bearer_cfg); + bool apply_rlc_add_mod(const asn1::rrc_nr::rlc_bearer_cfg_s& rlc_bearer_cfg); + bool apply_mac_cell_group(const asn1::rrc_nr::mac_cell_group_cfg_s& mac_cell_group_cfg); + bool apply_sp_cell_cfg(const asn1::rrc_nr::sp_cell_cfg_s& sp_cell_cfg); + bool apply_drb_add_mod(const asn1::rrc_nr::drb_to_add_mod_s& drb_cfg); + bool apply_security_cfg(const asn1::rrc_nr::security_cfg_s& security_cfg); + + srslte::as_security_config_t sec_cfg; + class connection_reconf_no_ho_proc { public: diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index cf76872c8..977f57b33 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -11,6 +11,7 @@ */ #include "srsue/hdr/stack/rrc/rrc_nr.h" +#include "srslte/common/security.h" #define Error(fmt, ...) rrc_ptr->log_h->error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define Warning(fmt, ...) rrc_ptr->log_h->warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) @@ -146,6 +147,30 @@ void rrc_nr::log_rrc_message(const std::string& source, } } +bool rrc_nr::add_lcid_rb(uint32_t lcid, rb_type_t rb_type, uint32_t rbid) +{ + if (lcid_rb.find(lcid) != lcid_rb.end()) { + log_h->error("Couldn't add RB to LCID. RB %d does exist.\n", rbid); + return false; + } else { + log_h->info("Adding lcid %d and radio bearer ID %d with type %s \n", lcid, rbid, (rb_type == Srb) ? "SRB" : "DRB"); + lcid_rb[lcid].rb_id = rbid; + lcid_rb[lcid].rb_type = rb_type; + } + return true; +} + +uint32_t rrc_nr::get_lcid_for_rbid(uint32_t rb_id) +{ + for (auto& rb : lcid_rb) { + if (rb.second.rb_id == rb_id) { + return rb.first; + } + } + log_h->error("Couldn't find LCID for rb LCID. RB %d does exist.\n", rb_id); + return 0; +} + // PHY interface void rrc_nr::in_sync() {} void rrc_nr::out_of_sync() {} @@ -418,6 +443,194 @@ bool rrc_nr::is_config_pending() return false; } +bool rrc_nr::apply_rlc_add_mod(const rlc_bearer_cfg_s& rlc_bearer_cfg) +{ + uint32_t lc_ch_id = 0; + uint32_t drb_id = 0; + uint32_t srb_id = 0; + rlc_config_t rlc_cfg; + + lc_ch_id = rlc_bearer_cfg.lc_ch_id; + if (rlc_bearer_cfg.served_radio_bearer_present == true) { + if (rlc_bearer_cfg.served_radio_bearer.type() == rlc_bearer_cfg_s::served_radio_bearer_c_::types::drb_id) { + drb_id = rlc_bearer_cfg.served_radio_bearer.drb_id(); + add_lcid_rb(lc_ch_id, Drb, drb_id); + } else { + srb_id = rlc_bearer_cfg.served_radio_bearer.srb_id(); + add_lcid_rb(lc_ch_id, Srb, srb_id); + } + } else { + log_h->warning("In RLC bearer cfg does not contain served radio bearer\n"); + return false; + } + + if (rlc_bearer_cfg.rlc_cfg_present == true) { + rlc_cfg = srslte::make_rlc_config_t(rlc_bearer_cfg.rlc_cfg); + if (rlc_bearer_cfg.rlc_cfg.type() == asn1::rrc_nr::rlc_cfg_c::types::um_bi_dir) { + if (rlc_bearer_cfg.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present && + rlc_bearer_cfg.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present && + rlc_bearer_cfg.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len != + rlc_bearer_cfg.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len) { + log_h->warning("NR RLC sequence number length is not the same in uplink and downlink\n"); + } + } else { + log_h->warning("NR RLC type is not unacknowledged mode bidirectional\n"); + } + } else { + log_h->warning("In RLC bearer cfg does not contain rlc cfg\n"); + return false; + } + + // Setup RLC + rlc->add_bearer(lc_ch_id, rlc_cfg); + + uint8_t log_chan_group = 0; + uint8_t priority = 1; + int prioritized_bit_rate = -1; + int bucket_size_duration = -1; + + if (rlc_bearer_cfg.mac_lc_ch_cfg_present == true && rlc_bearer_cfg.mac_lc_ch_cfg.ul_specific_params_present) { + lc_ch_cfg_s::ul_specific_params_s_ ul_specific_params = rlc_bearer_cfg.mac_lc_ch_cfg.ul_specific_params; + + if (ul_specific_params.lc_ch_group_present) { + log_chan_group = ul_specific_params.lc_ch_group; + } else { + log_h->warning("LCG not present, setting to 0\n"); + } + priority = ul_specific_params.prio; + prioritized_bit_rate = ul_specific_params.prioritised_bit_rate.to_number(); + bucket_size_duration = ul_specific_params.bucket_size_dur.to_number(); + // TODO Setup MAC @andre + // mac->setup_lcid(lc_ch_id, log_chan_group, priority, prioritized_bit_rate, bucket_size_duration); + } + return true; +} +bool rrc_nr::apply_mac_cell_group(const mac_cell_group_cfg_s& mac_cell_group_cfg) +{ + return true; +} + +bool rrc_nr::apply_cell_group_cfg(const cell_group_cfg_s& cell_group_cfg) +{ + if (cell_group_cfg.rlc_bearer_to_add_mod_list_present == true) { + for (uint32_t i = 0; i < cell_group_cfg.rlc_bearer_to_add_mod_list.size(); i++) { + apply_rlc_add_mod(cell_group_cfg.rlc_bearer_to_add_mod_list[i]); + } + } + if (cell_group_cfg.mac_cell_group_cfg_present == true) { + apply_mac_cell_group(cell_group_cfg.mac_cell_group_cfg); + } + if (cell_group_cfg.sp_cell_cfg_present) { + // apply_sp_cell_cfg(cell_group_cfg.sp_cell_cfg); + } + return true; +} + +bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) +{ + if (!drb_cfg.pdcp_cfg_present) { + log_h->error("Cannot add DRB - incomplete configuration\n"); + return false; + } + + uint32_t lcid = get_lcid_for_rbid(drb_cfg.drb_id); + + // Setup PDCP + if (!(drb_cfg.pdcp_cfg.drb_present == true)) { + log_h->error("PDCP config does not contain DRB config\n"); + return false; + } + + if (!(drb_cfg.cn_assoc_present == true)) { + log_h->error("DRB config does not contain an associated cn\n"); + return false; + } + + if (!(drb_cfg.cn_assoc.type() == drb_to_add_mod_s::cn_assoc_c_::types_opts::eps_bearer_id)) { + log_h->error("CN associtaion type not supported %s \n", drb_cfg.cn_assoc.type().to_string().c_str()); + return false; + } + + drb_eps_bearer_id[drb_cfg.drb_id] = drb_cfg.cn_assoc.eps_bearer_id(); + + if (drb_cfg.pdcp_cfg.drb.pdcp_sn_size_dl_present && drb_cfg.pdcp_cfg.drb.pdcp_sn_size_ul_present && + (drb_cfg.pdcp_cfg.drb.pdcp_sn_size_ul.to_number() != drb_cfg.pdcp_cfg.drb.pdcp_sn_size_dl.to_number())) { + log_h->warning("PDCP SN size in UL and DL are not the same. make_drb_pdcp_config_t will use the DL SN size %d \n", + drb_cfg.pdcp_cfg.drb.pdcp_sn_size_dl.to_number()); + } + + srslte::pdcp_config_t pdcp_cfg = make_drb_pdcp_config_t(drb_cfg.drb_id, true, drb_cfg.pdcp_cfg); + pdcp->add_bearer(lcid, pdcp_cfg); + + return true; +} + +bool rrc_nr::apply_security_cfg(const security_cfg_s& security_cfg) +{ + if (security_cfg.security_algorithm_cfg_present) { + switch (security_cfg.security_algorithm_cfg.ciphering_algorithm) { + case ciphering_algorithm_e::nea0: + sec_cfg.cipher_algo = CIPHERING_ALGORITHM_ID_EEA0; + break; + case ciphering_algorithm_e::nea1: + sec_cfg.cipher_algo = CIPHERING_ALGORITHM_ID_128_EEA1; + break; + case ciphering_algorithm_e::nea2: + sec_cfg.cipher_algo = CIPHERING_ALGORITHM_ID_128_EEA2; + break; + case ciphering_algorithm_e::nea3: + sec_cfg.cipher_algo = CIPHERING_ALGORITHM_ID_128_EEA3; + break; + default: + log_h->warning("Unsupported algorithm\n"); + break; + } + + if (security_cfg.security_algorithm_cfg.integrity_prot_algorithm_present) { + switch (security_cfg.security_algorithm_cfg.integrity_prot_algorithm) { + case integrity_prot_algorithm_e::nia0: + sec_cfg.integ_algo = INTEGRITY_ALGORITHM_ID_EIA0; + break; + case integrity_prot_algorithm_e::nia1: + sec_cfg.integ_algo = INTEGRITY_ALGORITHM_ID_128_EIA1; + break; + case integrity_prot_algorithm_e::nia2: + sec_cfg.integ_algo = INTEGRITY_ALGORITHM_ID_128_EIA2; + break; + case integrity_prot_algorithm_e::nia3: + sec_cfg.integ_algo = INTEGRITY_ALGORITHM_ID_128_EIA3; + break; + default: + log_h->warning("Unsupported algorithm\n"); + break; + } + } + } + // TODO derive correct keys + if (security_cfg.key_to_use_present) { + } + // TODO derive correct keys + + // Apply security config for all known NR lcids + for (auto& lcid : lcid_rb) { + pdcp->config_security(lcid.first, sec_cfg); + pdcp->enable_encryption(lcid.first); + } + return true; +} + +bool rrc_nr::apply_radio_bearer_cfg(const radio_bearer_cfg_s& radio_bearer_cfg) +{ + if (radio_bearer_cfg.drb_to_add_mod_list_present) { + for (uint32_t i = 0; i < radio_bearer_cfg.drb_to_add_mod_list.size(); i++) { + apply_drb_add_mod(radio_bearer_cfg.drb_to_add_mod_list[i]); + } + } + if (radio_bearer_cfg.security_cfg_present) { + apply_security_cfg(radio_bearer_cfg.security_cfg); + } + return true; +} // RLC interface void rrc_nr::max_retx_attempted() {} @@ -436,6 +649,15 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const bool { Info("Starting...\n"); + Info("Applying Cell Group Cfg\n"); + if (!rrc_ptr->apply_cell_group_cfg(cell_group_cfg)) { + return proc_outcome_t::error; + } + + Info("Applying Radio Bearer Cfg\n"); + if (!rrc_ptr->apply_radio_bearer_cfg(radio_bearer_cfg)) { + return proc_outcome_t::error; + } return proc_outcome_t::success; } @@ -456,6 +678,7 @@ void rrc_nr::connection_reconf_no_ho_proc::then(const srslte::proc_state_t& resu { if (result.is_success()) { Info("Finished %s successfully\n", name()); + srslte::console("RRC NR reconfiguration successful.\n"); return; } diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 0df20c75e..6c2ca0888 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -122,7 +122,7 @@ int ue_stack_lte::init(const stack_args_t& args_, srslte::logger* logger_) pdcp.init(&rlc, &rrc, gw); nas.init(usim.get(), &rrc, gw, args.nas); #ifdef HAVE_5GNR - rrc_nr.init(nullptr, nullptr, nullptr, nullptr, gw, &rrc, task_sched.get_timer_handler(), nullptr, args.rrc_nr); + rrc_nr.init(nullptr, nullptr, &rlc, &pdcp, gw, &rrc, task_sched.get_timer_handler(), nullptr, args.rrc_nr); rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, &rrc_nr, args.rrc); #else rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, args.rrc);