diff --git a/lib/include/srsran/adt/choice_type.h b/lib/include/srsran/adt/choice_type.h index 39e786a27..3ee27d425 100644 --- a/lib/include/srsran/adt/choice_type.h +++ b/lib/include/srsran/adt/choice_type.h @@ -64,7 +64,7 @@ struct choice_storage_t { } template - void destroy_unsafe() + void destroy_unchecked() { get_unchecked().~U(); }; @@ -80,7 +80,7 @@ struct CopyCtorVisitor { template void operator()(const T& t) { - c->construct_unsafe(t); + c->construct_unchecked(t); } C* c; }; @@ -91,18 +91,18 @@ struct MoveCtorVisitor { template void operator()(T&& t) { - c->construct_unsafe(std::move(t)); + c->construct_unchecked(std::move(t)); } C* c; }; template -struct DtorUnsafeVisitor { - explicit DtorUnsafeVisitor(C* c_) : c(c_) {} +struct DtorUncheckVisitor { + explicit DtorUncheckVisitor(C* c_) : c(c_) {} template void operator()(T& t) { - c->template destroy_unsafe(); + c->template destroy_unchecked(); } C* c; }; @@ -119,12 +119,12 @@ struct tagged_union_t std::size_t type_id; - using base_t::destroy_unsafe; + using base_t::destroy_unchecked; using base_t::get_buffer; using base_t::get_unchecked; template - void construct_emplace_unsafe(Args2&&... args) + void construct_emplace_unchecked(Args2&&... args) { using U2 = typename std::decay::type; static_assert(type_list_contains(), @@ -134,7 +134,7 @@ struct tagged_union_t } template - void construct_unsafe(U&& u) + void construct_unchecked(U&& u) { using U2 = typename std::decay::type; static_assert(type_list_contains(), @@ -143,11 +143,11 @@ struct tagged_union_t new (get_buffer()) U2(std::forward(u)); } - void copy_unsafe(const this_type& other) { visit(CopyCtorVisitor{this}, other); } + void copy_unchecked(const this_type& other) { visit(CopyCtorVisitor{this}, other); } - void move_unsafe(this_type&& other) { visit(MoveCtorVisitor{this}, other); } + void move_unchecked(this_type&& other) { visit(MoveCtorVisitor{this}, other); } - void dtor_unsafe() { visit(choice_details::DtorUnsafeVisitor{this}, *this); } + void dtor_unchecked() { visit(choice_details::DtorUncheckVisitor{this}, *this); } size_t get_type_idx() const { return type_id; } @@ -189,51 +189,51 @@ public: typename = typename std::enable_if::value>::type> explicit choice_t(Args2&&... args) noexcept { - base_t::template construct_emplace_unsafe(std::forward(args)...); + base_t::template construct_emplace_unchecked(std::forward(args)...); } - choice_t(const choice_t& other) noexcept { base_t::copy_unsafe(other); } + choice_t(const choice_t& other) noexcept { base_t::copy_unchecked(other); } - choice_t(choice_t&& other) noexcept { base_t::move_unsafe(std::move(other)); } + choice_t(choice_t&& other) noexcept { base_t::move_unchecked(std::move(other)); } template > choice_t(U&& u) noexcept { - base_t::construct_unsafe(std::forward(u)); + base_t::construct_unchecked(std::forward(u)); } - ~choice_t() { base_t::dtor_unsafe(); } + ~choice_t() { base_t::dtor_unchecked(); } template > choice_t& operator=(U&& u) noexcept { if (not base_t::template is()) { - base_t::dtor_unsafe(); + base_t::dtor_unchecked(); } - base_t::construct_unsafe(std::forward(u)); + base_t::construct_unchecked(std::forward(u)); return *this; } template void emplace(Args2&&... args) noexcept { - base_t::dtor_unsafe(); - base_t::template construct_emplace_unsafe(std::forward(args)...); + base_t::dtor_unchecked(); + base_t::template construct_emplace_unchecked(std::forward(args)...); } choice_t& operator=(const choice_t& other) noexcept { if (this != &other) { - base_t::dtor_unsafe(); - base_t::copy_unsafe(other); + base_t::dtor_unchecked(); + base_t::copy_unchecked(other); } return *this; } choice_t& operator=(choice_t&& other) noexcept { - base_t::dtor_unsafe(); - base_t::move_unsafe(std::move(other)); + base_t::dtor_unchecked(); + base_t::move_unchecked(std::move(other)); return *this; } diff --git a/lib/include/srsran/adt/circular_map.h b/lib/include/srsran/adt/circular_map.h index 069fc94e7..eee22a67d 100644 --- a/lib/include/srsran/adt/circular_map.h +++ b/lib/include/srsran/adt/circular_map.h @@ -99,7 +99,12 @@ public: { public: const_iterator() = default; - const_iterator(const static_circular_map* map, size_t idx_) : ptr(map), idx(idx_) {} + const_iterator(const static_circular_map* map, size_t idx_) : ptr(map), idx(idx_) + { + if (idx < ptr->capacity() and not ptr->present[idx]) { + ++(*this); + } + } const_iterator& operator++() { diff --git a/lib/include/srsran/adt/pool/batch_mem_pool.h b/lib/include/srsran/adt/pool/batch_mem_pool.h index 76add9095..7d3a4eee8 100644 --- a/lib/include/srsran/adt/pool/batch_mem_pool.h +++ b/lib/include/srsran/adt/pool/batch_mem_pool.h @@ -130,7 +130,7 @@ public: void* node = grow_pool.allocate_node(); if (grow_pool.size() < batch_threshold) { - allocate_batch_in_background_unlocked(); + allocate_batch_in_background_nolock(); } return node; } @@ -155,7 +155,7 @@ public: } private: - void allocate_batch_in_background_unlocked() + void allocate_batch_in_background_nolock() { if (state->dispatched) { // new batch allocation already ongoing diff --git a/lib/include/srsran/asn1/nas_5g_ies.h b/lib/include/srsran/asn1/nas_5g_ies.h index d5c909317..cd83afcb3 100644 --- a/lib/include/srsran/asn1/nas_5g_ies.h +++ b/lib/include/srsran/asn1/nas_5g_ies.h @@ -64,8 +64,8 @@ public: }; typedef nas_enumerated follow_on_request_bit_type; - follow_on_request_bit_type follow_on_request_bit; - registration_type_type registration_type; + follow_on_request_bit_type follow_on_request_bit = follow_on_request_bit_type_::options::no_follow_on_request_pending; + registration_type_type registration_type = registration_type_type_::options::initial_registration; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -96,8 +96,9 @@ public: }; typedef nas_enumerated nas_key_set_identifier_type; - security_context_flag_type security_context_flag; - nas_key_set_identifier_type nas_key_set_identifier; + security_context_flag_type security_context_flag = security_context_flag_type_::options::native_security_context; + nas_key_set_identifier_type nas_key_set_identifier = + nas_key_set_identifier_type_::options::no_key_is_available_or_reserved; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -283,42 +284,42 @@ public: guti_5g_s& set_guti_5g() { - set(identity_types::guti_5g); + set(identity_types::guti_5g); choice_container = srslog::detail::any{guti_5g_s()}; return *srslog::detail::any_cast(&choice_container); } imei_s& set_imei() { - set(identity_types::imei); + set(identity_types::imei); choice_container = srslog::detail::any{imei_s()}; return *srslog::detail::any_cast(&choice_container); } s_tmsi_5g_s& set_s_tmsi_5g() { - set(identity_types::s_tmsi_5g); + set(identity_types::s_tmsi_5g); choice_container = srslog::detail::any{s_tmsi_5g_s()}; return *srslog::detail::any_cast(&choice_container); } imeisv_s& set_imeisv() { - set(identity_types::imeisv); + set(identity_types::imeisv); choice_container = srslog::detail::any{imeisv_s()}; return *srslog::detail::any_cast(&choice_container); } mac_address_s& set_mac_address() { - set(identity_types::mac_address); + set(identity_types::mac_address); choice_container = srslog::detail::any{mac_address_s()}; return *srslog::detail::any_cast(&choice_container); } eui_64_s& set_eui_64() { - set(identity_types::eui_64); + set(identity_types::eui_64); choice_container = srslog::detail::any{eui_64_s()}; return *srslog::detail::any_cast(&choice_container); } @@ -327,7 +328,7 @@ public: SRSASN_CODE unpack(asn1::cbit_ref& bref); private: - identity_types type_; + identity_types type_ = identity_types_::options::no_identity; srslog::detail::any choice_container; }; // mobile_identity_5gs_t @@ -337,26 +338,26 @@ private: class capability_5gmm_t { public: - bool sgc; - bool iphc_cp_c_io_t_5g; - bool n3_data; - bool cp_c_io_t_5g; - bool restrict_ec; - bool lpp; - bool ho_attach; - bool s1_mode; - bool racs; - bool nssaa; - bool lcs_5g; - bool v2_xcnpc5; - bool v2_xcepc5; - bool v2_x; - bool up_c_io_t_5g; - bool srvcc_5g; - bool ehc_cp_c_io_t_5g; - bool multiple_up; - bool wusa; - bool cag; + bool sgc = false; + bool iphc_cp_c_io_t_5g = false; + bool n3_data = false; + bool cp_c_io_t_5g = false; + bool restrict_ec = false; + bool lpp = false; + bool ho_attach = false; + bool s1_mode = false; + bool racs = false; + bool nssaa = false; + bool lcs_5g = false; + bool v2_xcnpc5 = false; + bool v2_xcepc5 = false; + bool v2_x = false; + bool up_c_io_t_5g = false; + bool srvcc_5g = false; + bool ehc_cp_c_io_t_5g = false; + bool multiple_up = false; + bool wusa = false; + bool cag = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -368,39 +369,39 @@ public: class ue_security_capability_t { public: - bool ea0_5g_supported; - bool ea1_128_5g_supported; - bool ea2_128_5g_supported; - bool ea3_128_5g_supported; - bool ea4_5g_supported; - bool ea5_5g_supported; - bool ea6_5g_supported; - bool ea7_5g_supported; - bool ia0_5g_supported; - bool ia1_128_5g_supported; - bool ia2_128_5g_supported; - bool ia3_128_5g_supported; - bool ia4_5g_supported; - bool ia5_5g_supported; - bool ia6_5g_supported; - bool ia7_5g_supported; - bool eps_caps_present; - bool eea0_supported; - bool eea1_128_supported; - bool eea2_128_supported; - bool eea3_128_supported; - bool eea4_supported; - bool eea5_supported; - bool eea6_supported; - bool eea7_supported; - bool eia0_supported; - bool eia1_128_supported; - bool eia2_128_supported; - bool eia3_128_supported; - bool eia4_supported; - bool eia5_supported; - bool eia6_supported; - bool eia7_supported; + bool ea0_5g_supported = false; + bool ea1_128_5g_supported = false; + bool ea2_128_5g_supported = false; + bool ea3_128_5g_supported = false; + bool ea4_5g_supported = false; + bool ea5_5g_supported = false; + bool ea6_5g_supported = false; + bool ea7_5g_supported = false; + bool ia0_5g_supported = false; + bool ia1_128_5g_supported = false; + bool ia2_128_5g_supported = false; + bool ia3_128_5g_supported = false; + bool ia4_5g_supported = false; + bool ia5_5g_supported = false; + bool ia6_5g_supported = false; + bool ia7_5g_supported = false; + bool eps_caps_present = false; + bool eea0_supported = false; + bool eea1_128_supported = false; + bool eea2_128_supported = false; + bool eea3_128_supported = false; + bool eea4_supported = false; + bool eea5_supported = false; + bool eea6_supported = false; + bool eea7_supported = false; + bool eia0_supported = false; + bool eia1_128_supported = false; + bool eia2_128_supported = false; + bool eia3_128_supported = false; + bool eia4_supported = false; + bool eia5_supported = false; + bool eia6_supported = false; + bool eia7_supported = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -438,6 +439,8 @@ public: }; // s_nssai_t + + // IE: NSSAI // Reference: 9.11.3.37 class nssai_t @@ -469,67 +472,67 @@ public: class s1_ue_network_capability_t { public: - bool eea0_supported; - bool eea1_128_supported; - bool eea2_128_supported; - bool eea3_128_supported; - bool eea4_supported; - bool eea5_supported; - bool eea6_supported; - bool eea7_supported; - bool eia0_supported; - bool eia1_128_supported; - bool eia2_128_supported; - bool eia3_128_supported; - bool eia4_supported; - bool eia5_supported; - bool eia6_supported; - bool eia7_supported; - bool uea0_supported; - bool uea1_128_supported; - bool uea2_128_supported; - bool uea3_128_supported; - bool uea4_supported; - bool uea5_supported; - bool uea6_supported; - bool uea7_supported; - bool ucs2_support; - bool uia1_128_supported; - bool uia2_128_supported; - bool uia3_128_supported; - bool uia4_supported; - bool uia5_supported; - bool uia6_supported; - bool uia7_supported; - bool pro_se_dd_supported; - bool pro_se_supported; - bool h245_ash_supported; - bool acc_csfb_supported; - bool llp_supported; - bool lcs_supported; - bool srvcc_capability_supported; - bool nf_capability_supported; - bool e_pco_supported; - bool hc_cp_c_io_t_supported; - bool e_rw_o_pdn_supported; - bool s1_u_data_supported; - bool up_c_io_t_supported; - bool cp_c_io_t_supported; - bool pro_se_relay_supported; - bool pro_se_dc_supported; - bool max_15_eps_bearer_supported; - bool sgc_supported; - bool n1mode_supported; - bool dcnr_supported; - bool cp_backoff_supported; - bool restrict_ec_supported; - bool v2_x_pc5_supported; - bool multiple_drb_supported; - bool nr_pc5_supported; - bool up_mt_edt_supported; - bool cp_mt_edt_supported; - bool wus_supported; - bool racs_supported; + bool eea0_supported = false; + bool eea1_128_supported = false; + bool eea2_128_supported = false; + bool eea3_128_supported = false; + bool eea4_supported = false; + bool eea5_supported = false; + bool eea6_supported = false; + bool eea7_supported = false; + bool eia0_supported = false; + bool eia1_128_supported = false; + bool eia2_128_supported = false; + bool eia3_128_supported = false; + bool eia4_supported = false; + bool eia5_supported = false; + bool eia6_supported = false; + bool eia7_supported = false; + bool uea0_supported = false; + bool uea1_128_supported = false; + bool uea2_128_supported = false; + bool uea3_128_supported = false; + bool uea4_supported = false; + bool uea5_supported = false; + bool uea6_supported = false; + bool uea7_supported = false; + bool ucs2_support = false; + bool uia1_128_supported = false; + bool uia2_128_supported = false; + bool uia3_128_supported = false; + bool uia4_supported = false; + bool uia5_supported = false; + bool uia6_supported = false; + bool uia7_supported = false; + bool pro_se_dd_supported = false; + bool pro_se_supported = false; + bool h245_ash_supported = false; + bool acc_csfb_supported = false; + bool llp_supported = false; + bool lcs_supported = false; + bool srvcc_capability_supported = false; + bool nf_capability_supported = false; + bool e_pco_supported = false; + bool hc_cp_c_io_t_supported = false; + bool e_rw_o_pdn_supported = false; + bool s1_u_data_supported = false; + bool up_c_io_t_supported = false; + bool cp_c_io_t_supported = false; + bool pro_se_relay_supported = false; + bool pro_se_dc_supported = false; + bool max_15_eps_bearer_supported = false; + bool sgc_supported = false; + bool n1mode_supported = false; + bool dcnr_supported = false; + bool cp_backoff_supported = false; + bool restrict_ec_supported = false; + bool v2_x_pc5_supported = false; + bool multiple_drb_supported = false; + bool nr_pc5_supported = false; + bool up_mt_edt_supported = false; + bool cp_mt_edt_supported = false; + bool wus_supported = false; + bool racs_supported = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -541,22 +544,22 @@ public: class uplink_data_status_t { public: - bool psi_7; - bool psi_6; - bool psi_5; - bool psi_4; - bool psi_3; - bool psi_2; - bool psi_1; - bool psi_0; - bool psi_15; - bool psi_14; - bool psi_13; - bool psi_12; - bool psi_11; - bool psi_10; - bool psi_9; - bool psi_8; + bool psi_7 = false; + bool psi_6 = false; + bool psi_5 = false; + bool psi_4 = false; + bool psi_3 = false; + bool psi_2 = false; + bool psi_1 = false; + bool psi_0 = false; + bool psi_15 = false; + bool psi_14 = false; + bool psi_13 = false; + bool psi_12 = false; + bool psi_11 = false; + bool psi_10 = false; + bool psi_9 = false; + bool psi_8 = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -568,22 +571,22 @@ public: class pdu_session_status_t { public: - bool psi_7; - bool psi_6; - bool psi_5; - bool psi_4; - bool psi_3; - bool psi_2; - bool psi_1; - bool psi_0; - bool psi_15; - bool psi_14; - bool psi_13; - bool psi_12; - bool psi_11; - bool psi_10; - bool psi_9; - bool psi_8; + bool psi_7 = false; + bool psi_6 = false; + bool psi_5 = false; + bool psi_4 = false; + bool psi_3 = false; + bool psi_2 = false; + bool psi_1 = false; + bool psi_0 = false; + bool psi_15 = false; + bool psi_14 = false; + bool psi_13 = false; + bool psi_12 = false; + bool psi_11 = false; + bool psi_10 = false; + bool psi_9 = false; + bool psi_8 = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -595,8 +598,8 @@ public: class mico_indication_t { public: - bool sprti; - bool aai; + bool sprti = false; + bool aai = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -608,8 +611,8 @@ public: class ue_status_t { public: - bool n1_mode_reg; - bool s1_mode_reg; + bool n1_mode_reg = false; + bool s1_mode_reg = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -621,22 +624,22 @@ public: class allowed_pdu_session_status_t { public: - bool psi_7; - bool psi_6; - bool psi_5; - bool psi_4; - bool psi_3; - bool psi_2; - bool psi_1; - bool psi_0; - bool psi_15; - bool psi_14; - bool psi_13; - bool psi_12; - bool psi_11; - bool psi_10; - bool psi_9; - bool psi_8; + bool psi_7 = false; + bool psi_6 = false; + bool psi_5 = false; + bool psi_4 = false; + bool psi_3 = false; + bool psi_2 = false; + bool psi_1 = false; + bool psi_0 = false; + bool psi_15 = false; + bool psi_14 = false; + bool psi_13 = false; + bool psi_12 = false; + bool psi_11 = false; + bool psi_10 = false; + bool psi_9 = false; + bool psi_8 = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -658,7 +661,7 @@ public: }; typedef nas_enumerated UE_usage_setting_type; - UE_usage_setting_type ue_usage_setting; + UE_usage_setting_type ue_usage_setting = UE_usage_setting_type_::options::voice_centric; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -683,7 +686,7 @@ public: }; typedef nas_enumerated drx_value_type; - drx_value_type drx_value; + drx_value_type drx_value = drx_value_type_::options::drx_value_not_specified; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -749,7 +752,7 @@ public: }; typedef nas_enumerated Payload_container_type_type; - Payload_container_type_type payload_container_type; + Payload_container_type_type payload_container_type = Payload_container_type_type_::options::n1_sm_information; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -773,8 +776,8 @@ public: class network_slicing_indication_t { public: - bool nssci; - bool dcni; + bool nssci = false; + bool dcni = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -830,10 +833,10 @@ public: }; typedef nas_enumerated PNB_EPS_CIoT_type; - PNB_EPS_CIoT_type pnb_eps_c_io_t; - PNB_5GS_CIoT_type pnb_5gs_c_io_t; - NG_RAN_RCU_type ng_ran_rcu; - SMS_requested_type sms_requested; + PNB_EPS_CIoT_type pnb_eps_c_io_t = PNB_EPS_CIoT_type_::options::no_additional_information; + PNB_5GS_CIoT_type pnb_5gs_c_io_t = PNB_5GS_CIoT_type_::options::no_additional_information; + NG_RAN_RCU_type ng_ran_rcu = NG_RAN_RCU_type_::options::ue_radio_capability_update_not_needed; + SMS_requested_type sms_requested = SMS_requested_type_::options::sms_over_nas_not_supported; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -877,22 +880,22 @@ public: class eps_bearer_context_status_t { public: - bool ebi_7; - bool ebi_6; - bool ebi_5; - bool ebi_4; - bool ebi_3; - bool ebi_2; - bool ebi_1; - bool ebi_0; - bool ebi_15; - bool ebi_14; - bool ebi_13; - bool ebi_12; - bool ebi_11; - bool ebi_10; - bool ebi_9; - bool ebi_8; + bool ebi_7 = false; + bool ebi_6 = false; + bool ebi_5 = false; + bool ebi_4 = false; + bool ebi_3 = false; + bool ebi_2 = false; + bool ebi_1 = false; + bool ebi_0 = false; + bool ebi_15 = false; + bool ebi_14 = false; + bool ebi_13 = false; + bool ebi_12 = false; + bool ebi_11 = false; + bool ebi_10 = false; + bool ebi_9 = false; + bool ebi_8 = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1016,7 +1019,7 @@ public: class additional_information_requested_t { public: - bool cipher_key; + bool cipher_key = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1038,7 +1041,7 @@ public: class n5gc_indication_t { public: - bool n5gcreg; + bool n5gcreg = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1065,7 +1068,7 @@ public: }; typedef nas_enumerated nb_n1_mode_drx_value_type; - nb_n1_mode_drx_value_type nb_n1_mode_drx_value; + nb_n1_mode_drx_value_type nb_n1_mode_drx_value = nb_n1_mode_drx_value_type_::options::drx_value_not_specified; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1119,10 +1122,11 @@ public: }; typedef nas_enumerated registration_result_type; - Emergency_registered_type emergency_registered; - NSSAA_to_be_performed_type nssaa_to_be_performed; - SMS_allowed_type sms_allowed; - registration_result_type registration_result; + Emergency_registered_type emergency_registered = + Emergency_registered_type_::options::not_registered_for_emergency_services; + NSSAA_to_be_performed_type nssaa_to_be_performed = NSSAA_to_be_performed_type_::options::nssaa_is_to_be_performed; + SMS_allowed_type sms_allowed = SMS_allowed_type_::options::sms_over_nas_not_allowed; + registration_result_type registration_result = registration_result_type_::options::access_3_gpp; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1186,22 +1190,22 @@ public: class pdu_session_reactivation_result_t { public: - bool psi_7; - bool psi_6; - bool psi_5; - bool psi_4; - bool psi_3; - bool psi_2; - bool psi_1; - bool psi_0; - bool psi_15; - bool psi_14; - bool psi_13; - bool psi_12; - bool psi_11; - bool psi_10; - bool psi_9; - bool psi_8; + bool psi_7 = false; + bool psi_6 = false; + bool psi_5 = false; + bool psi_4 = false; + bool psi_3 = false; + bool psi_2 = false; + bool psi_1 = false; + bool psi_0 = false; + bool psi_15 = false; + bool psi_14 = false; + bool psi_13 = false; + bool psi_12 = false; + bool psi_11 = false; + bool psi_10 = false; + bool psi_9 = false; + bool psi_8 = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1309,7 +1313,7 @@ public: }; typedef nas_enumerated NSSAI_inclusion_mode_type; - NSSAI_inclusion_mode_type nssai_inclusion_mode; + NSSAI_inclusion_mode_type nssai_inclusion_mode = NSSAI_inclusion_mode_type_::options::nssai_inclusion_mode_a; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1331,7 +1335,7 @@ public: class non_3_gpp_nw_provided_policies_t { public: - bool n3_en; + bool n3_en = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1353,7 +1357,8 @@ public: }; typedef nas_enumerated Deletion_request_type; - Deletion_request_type deletion_request; + Deletion_request_type deletion_request = + Deletion_request_type_::options::ue_radio_capability_id_deletion_not_requested; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1448,7 +1453,7 @@ public: }; typedef nas_enumerated cause_5gmm_type; - cause_5gmm_type cause_5gmm; + cause_5gmm_type cause_5gmm = cause_5gmm_type_::options::illegal_ue; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1491,9 +1496,10 @@ public: }; typedef nas_enumerated access_type_type; - switch_off_type switch_off; - re_registration_required_type re_registration_required; - access_type_type access_type; + switch_off_type switch_off = switch_off_type_::options::normal_de_registration; + re_registration_required_type re_registration_required = + re_registration_required_type_::options::re_registration_not_required; + access_type_type access_type = access_type_type_::options::access_3_gpp; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1535,7 +1541,7 @@ public: }; typedef nas_enumerated Service_type_value_type; - Service_type_value_type service_type_value; + Service_type_value_type service_type_value = Service_type_value_type_::options::signalling; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1559,7 +1565,8 @@ public: }; typedef nas_enumerated control_plane_service_type_value_type; - control_plane_service_type_value_type control_plane_service_type_value; + control_plane_service_type_value_type control_plane_service_type_value = + control_plane_service_type_value_type_::options::mobile_originating_request; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1622,7 +1629,7 @@ public: }; typedef nas_enumerated value_type; - value_type value; + value_type value = value_type_::options::no_adjustment_for_daylight_saving_time; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1634,7 +1641,7 @@ public: class sms_indication_t { public: - bool sms_availability_indication; + bool sms_availability_indication = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1656,7 +1663,7 @@ public: }; typedef nas_enumerated SCMR_type; - SCMR_type scmr; + SCMR_type scmr = SCMR_type_::options::no_additional_information; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1743,7 +1750,7 @@ public: }; typedef nas_enumerated identity_types; - identity_types type_of_identity; + identity_types type_of_identity = identity_types_::options::suci; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1787,8 +1794,9 @@ public: }; typedef nas_enumerated ciphering_algorithm_type; - ciphering_algorithm_type ciphering_algorithm; - integrity_protection_algorithm_type integrity_protection_algorithm; + ciphering_algorithm_type ciphering_algorithm = ciphering_algorithm_type_::options::ea0_5g; + integrity_protection_algorithm_type integrity_protection_algorithm = + integrity_protection_algorithm_type_::options::ia0_5g; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1810,7 +1818,7 @@ public: }; typedef nas_enumerated imeisv_request_type; - imeisv_request_type imeisv_request; + imeisv_request_type imeisv_request = imeisv_request_type_::options::imeisv_not_requested; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1854,8 +1862,9 @@ public: }; typedef nas_enumerated ciphering_algorithm_type; - ciphering_algorithm_type ciphering_algorithm; - integrity_protection_algorithm_type integrity_protection_algorithm; + ciphering_algorithm_type ciphering_algorithm = ciphering_algorithm_type_::options::eea0; + integrity_protection_algorithm_type integrity_protection_algorithm = + integrity_protection_algorithm_type_::options::eia0; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1867,8 +1876,8 @@ public: class additional_5g_security_information_t { public: - bool rinmr; - bool hdp; + bool rinmr = false; + bool hdp = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1880,44 +1889,44 @@ public: class s1_ue_security_capability_t { public: - bool eea0; - bool eea1_128; - bool eea2_128; - bool eea3_128; - bool eea4; - bool eea5; - bool eea6; - bool eea7; - bool eia0; - bool eia1_128; - bool eia2_128; - bool eia3_128; - bool eia4; - bool eia5; - bool eia6; - bool eia7; - bool uea0; - bool uea1; - bool uea2; - bool uea3; - bool uea4; - bool uea5; - bool uea6; - bool uea7; - bool uia1; - bool uia2; - bool uia3; - bool uia4; - bool uia5; - bool uia6; - bool uia7; - bool gea1; - bool gea2; - bool gea3; - bool gea4; - bool gea5; - bool gea6; - bool gea7; + bool eea0 = false; + bool eea1_128 = false; + bool eea2_128 = false; + bool eea3_128 = false; + bool eea4 = false; + bool eea5 = false; + bool eea6 = false; + bool eea7 = false; + bool eia0 = false; + bool eia1_128 = false; + bool eia2_128 = false; + bool eia3_128 = false; + bool eia4 = false; + bool eia5 = false; + bool eia6 = false; + bool eia7 = false; + bool uea0 = false; + bool uea1 = false; + bool uea2 = false; + bool uea3 = false; + bool uea4 = false; + bool uea5 = false; + bool uea6 = false; + bool uea7 = false; + bool uia1 = false; + bool uia2 = false; + bool uia3 = false; + bool uia4 = false; + bool uia5 = false; + bool uia6 = false; + bool uia7 = false; + bool gea1 = false; + bool gea2 = false; + bool gea3 = false; + bool gea4 = false; + bool gea5 = false; + bool gea6 = false; + bool gea7 = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1939,7 +1948,7 @@ public: }; typedef nas_enumerated Access_type_value_type; - Access_type_value_type access_type_value; + Access_type_value_type access_type_value = Access_type_value_type_::options::access_3_gpp; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -1978,7 +1987,7 @@ public: }; typedef nas_enumerated Request_type_value_type; - Request_type_value_type request_type_value; + Request_type_value_type request_type_value = request_type_t::Request_type_value_type_::options::initial_request; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2011,7 +2020,8 @@ public: }; typedef nas_enumerated MA_PDU_session_information_value_type; - MA_PDU_session_information_value_type ma_pdu_session_information_value; + MA_PDU_session_information_value_type ma_pdu_session_information_value = + MA_PDU_session_information_value_type_::options::ma_pdu_session_network_upgrade_is_allowed; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2035,7 +2045,8 @@ public: }; typedef nas_enumerated Downlink_data_expected_type; - Downlink_data_expected_type downlink_data_expected; + Downlink_data_expected_type downlink_data_expected = + Downlink_data_expected_type_::options::no_information_regarding_ddx_is_conveyed; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2069,8 +2080,8 @@ public: }; typedef nas_enumerated max_data_rate_UPIP_downlink_type; - max_data_rate_UPIP_uplink_type max_data_rate_upip_uplink; - max_data_rate_UPIP_downlink_type max_data_rate_upip_downlink; + max_data_rate_UPIP_uplink_type max_data_rate_upip_uplink = max_data_rate_UPIP_uplink_type_::options::kbps_64; + max_data_rate_UPIP_downlink_type max_data_rate_upip_downlink = max_data_rate_UPIP_downlink_type_::options::kbps_64; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2096,7 +2107,7 @@ public: }; typedef nas_enumerated PDU_session_type_value_type; - PDU_session_type_value_type pdu_session_type_value; + PDU_session_type_value_type pdu_session_type_value = PDU_session_type_value_type_::options::ipv4; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2123,7 +2134,7 @@ public: }; typedef nas_enumerated SSC_mode_value_type; - SSC_mode_value_type ssc_mode_value; + SSC_mode_value_type ssc_mode_value = ssc_mode_t::SSC_mode_value_type_::options::ssc_mode_1; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2157,7 +2168,7 @@ public: class always_on_pdu_session_requested_t { public: - bool apsi; + bool apsi = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2248,7 +2259,7 @@ public: }; typedef nas_enumerated CID_Length_type; - CID_Length_type cid__length; + CID_Length_type cid__length = CID_Length_type_::options::ethernet_header_compression_not_used; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2271,8 +2282,8 @@ public: }; typedef nas_enumerated PDU_session_type_value_type; - bool si6_lla; - PDU_session_type_value_type pdu_session_type_value; + bool si6_lla = false; + PDU_session_type_value_type pdu_session_type_value = PDU_session_type_value_type_::options::ipv4; std::array ipv4; std::array ipv6; std::array smf_i_pv6_link_local_address; @@ -2334,9 +2345,9 @@ public: }; typedef nas_enumerated unit_session_AMBR_type; - unit_session_AMBR_type unit_session_ambr_for_downlink; + unit_session_AMBR_type unit_session_ambr_for_downlink = unit_session_AMBR_type_::options::not_used; uint16_t session_ambr_for_downlink; - unit_session_AMBR_type unit_session_ambr_for_uplink; + unit_session_AMBR_type unit_session_ambr_for_uplink = unit_session_AMBR_type_::options::not_used; uint16_t session_ambr_for_uplink; SRSASN_CODE pack(asn1::bit_ref& bref); @@ -2400,7 +2411,7 @@ public: }; typedef nas_enumerated cause_value_type; - cause_value_type cause_value; + cause_value_type cause_value = cause_value_type_::options::operator_determined_barring; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2437,7 +2448,7 @@ public: class always_on_pdu_session_indication_t { public: - bool apsr; + bool apsr = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2479,7 +2490,7 @@ public: }; typedef nas_enumerated EPT_S1_type; - EPT_S1_type ept_s1; + EPT_S1_type ept_s1 = EPT_S1_type_::options::ethernet_pdn_type_in_s1_mode_not_supported; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2515,7 +2526,7 @@ public: class control_plane_only_indication_t { public: - bool cpoi; + bool cpoi = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2527,9 +2538,9 @@ public: class allowed_ssc_mode_t { public: - bool ssc3; - bool ssc2; - bool ssc1; + bool ssc3 = false; + bool ssc2 = false; + bool ssc1 = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2551,7 +2562,8 @@ public: }; typedef nas_enumerated abo_type; - abo_type abo; + abo_type abo = + congestion_re_attempt_indicator_5gsm_t::abo_type_::options::the_back_off_timer_is_applied_in_the_registered_plmn; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); @@ -2563,8 +2575,8 @@ public: class re_attempt_indicator_t { public: - bool eplmnc; - bool ratc; + bool eplmnc = false; + bool ratc = false; SRSASN_CODE pack(asn1::bit_ref& bref); SRSASN_CODE unpack(asn1::cbit_ref& bref); diff --git a/lib/include/srsran/asn1/nas_5g_msg.h b/lib/include/srsran/asn1/nas_5g_msg.h index d3ceed0b8..3b6b39bc8 100644 --- a/lib/include/srsran/asn1/nas_5g_msg.h +++ b/lib/include/srsran/asn1/nas_5g_msg.h @@ -2480,7 +2480,7 @@ public: private: SRSASN_CODE unpack(asn1::cbit_ref& bref); SRSASN_CODE pack(asn1::bit_ref& bref); - srslog::detail::any msg_container; + srslog::detail::any msg_container = srslog::detail::any{registration_request_t()}; }; } // namespace nas_5g } // namespace srsran diff --git a/lib/include/srsran/common/band_helper.h b/lib/include/srsran/common/band_helper.h index dbf84c2d2..1f393bcbb 100644 --- a/lib/include/srsran/common/band_helper.h +++ b/lib/include/srsran/common/band_helper.h @@ -114,6 +114,15 @@ public: */ double get_ul_center_freq(const srsran_carrier_nr_t& carrier); + /** + * @brief Compute the absolute frequency point A for a arfcn + * + * @param nof_prb Number of PRBs. + * @param arfcn Given ARFCN. + * @return frequency point A in arfcn notation. + */ + uint32_t get_abs_freq_point_a_arfcn(uint32_t nof_prb, uint32_t arfcn); + class sync_raster_t { protected: @@ -148,6 +157,8 @@ private: // internal helper double get_center_freq_from_abs_freq_point_a(uint32_t nof_prb, uint32_t freq_point_a_arfcn); + double get_abs_freq_point_a_from_center_freq(uint32_t nof_prb, double center_freq); + // Elements of TS 38.101-1 Table 5.2-1: NR operating bands in FR1 struct nr_operating_band { uint16_t band; @@ -249,22 +260,22 @@ private: {1, KHZ_100, 384000, 20, 396000, 422000, 20, 434000}, {2, KHZ_100, 370000, 20, 382000, 386000, 20, 398000}, {3, KHZ_100, 342000, 20, 357000, 361000, 20, 376000}, - + {5, KHZ_100, 164800, 20, 169800, 173800, 20, 178800}, {7, KHZ_100, 500000, 20, 514000, 524000, 20, 538000}, {8, KHZ_100, 176000, 20, 183000, 185000, 20, 192000}, - + {12, KHZ_100, 139800, 20, 143200, 145800, 20, 149200}, - + {20, KHZ_100, 166400, 20, 172400, 158200, 20, 164200}, {25, KHZ_100, 370000, 20, 383000, 386000, 20, 399000}, {28, KHZ_100, 140600, 20, 149600, 151600, 20, 160600}, - + {34, KHZ_100, 402000, 20, 405000, 402000, 20, 405000}, {38, KHZ_100, 514000, 20, 524000, 514000, 20, 524000}, {39, KHZ_100, 376000, 20, 384000, 376000, 20, 384000}, - + {40, KHZ_100, 460000, 20, 480000, 460000, 20, 480000}, {41, KHZ_15, 499200, 3, 537999, 499200, 3, 537999}, @@ -272,13 +283,13 @@ private: {50, KHZ_100, 286400, 20, 303400, 286400, 20, 303400}, {51, KHZ_100, 285400, 20, 286400, 285400, 20, 286400}, - + {66, KHZ_100, 342000, 20, 356000, 422000, 20, 440000}, - + {70, KHZ_100, 339000, 20, 342000, 399000, 20, 404000}, {71, KHZ_100, 132600, 20, 139600, 123400, 20, 130400}, {74, KHZ_100, 285400, 20, 294000, 295000, 20, 303600}, - + {75, KHZ_100, 0, 0, 0, 286400, 20, 303400}, {76, KHZ_100, 0, 0, 0, 285400, 20, 286400}, @@ -297,23 +308,22 @@ private: {83, KHZ_100, 140600, 20, 149600, 0, 0, 0}, {84, KHZ_100, 384000, 20, 396000, 0, 0, 0}, {86, KHZ_100, 342000, 20, 356000, 0, 0, 0} - // clang-format on + // clang-format on }}; static const uint32_t nof_nr_bands_fr2 = 8; - static constexpr std::array nr_band_table_fr2 = {{ - {257, KHZ_60, 2054166, 1, 2104165, 2054166, 1, 2104165}, - {257, KHZ_120, 2054167, 2, 2104165, 2054167, 20, 2104165}, - - {258, KHZ_60, 2016667, 1, 2070832, 2016667, 1, 2070832}, - {258, KHZ_120, 2016667, 2, 2070831, 2016667, 2, 2070832}, - - {260, KHZ_60, 2229166, 1, 2279165, 2229166, 1, 2279165}, - {260, KHZ_120, 2229167, 2, 2279165, 2229167, 2, 2279165}, - - {261, KHZ_60, 2070833, 1, 2084999, 2070833, 1, 2084999}, - {261, KHZ_120, 2070833, 2, 2084999, 2070833, 2, 2084999} - }}; + static constexpr std::array nr_band_table_fr2 = { + {{257, KHZ_60, 2054166, 1, 2104165, 2054166, 1, 2104165}, + {257, KHZ_120, 2054167, 2, 2104165, 2054167, 20, 2104165}, + + {258, KHZ_60, 2016667, 1, 2070832, 2016667, 1, 2070832}, + {258, KHZ_120, 2016667, 2, 2070831, 2016667, 2, 2070832}, + + {260, KHZ_60, 2229166, 1, 2279165, 2229166, 1, 2279165}, + {260, KHZ_120, 2229167, 2, 2279165, 2229167, 2, 2279165}, + + {261, KHZ_60, 2070833, 1, 2084999, 2070833, 1, 2084999}, + {261, KHZ_120, 2070833, 2, 2084999, 2070833, 2, 2084999}}}; // Elements of TS 38.101-1 Table 5.4.3.3-1 : Applicable SS raster entries per operating band struct nr_band_ss_raster { @@ -326,35 +336,35 @@ private: }; static const uint32_t nof_nr_band_ss_raster = 29; static constexpr std::array nr_band_ss_raster_table = {{ - {1, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5419}, - {2, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4969}, - {3, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4517, 1, 4693}, - {5, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2177, 1, 2230}, - {5, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 2183, 1, 2224}, - {7, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6554, 1, 6718}, - {8, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2318, 1, 2395}, - {12, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1828, 1, 1858}, - {20, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1982, 1, 2047}, - {25, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4981}, - {28, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1901, 1, 2002}, - {34, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5030, 1, 5056}, - {38, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6431, 1, 6544}, - {39, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4706, 1, 4795}, - {40, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5756, 1, 5995}, - {41, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6246, 3, 6717}, - {41, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 6252, 3, 6714}, - {50, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, - {51, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, - {66, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5494}, - {66, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 5285, 1, 5488}, - {70, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4993, 1, 5044}, - {71, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1547, 1, 1624}, - {74, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3692, 1, 3790}, - {75, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, - {76, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, - {77, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8329}, - {78, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8051}, - {79, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 8480, 16, 8880}, + {1, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5419}, + {2, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4969}, + {3, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4517, 1, 4693}, + {5, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2177, 1, 2230}, + {5, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 2183, 1, 2224}, + {7, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6554, 1, 6718}, + {8, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2318, 1, 2395}, + {12, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1828, 1, 1858}, + {20, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1982, 1, 2047}, + {25, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4981}, + {28, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1901, 1, 2002}, + {34, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5030, 1, 5056}, + {38, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6431, 1, 6544}, + {39, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4706, 1, 4795}, + {40, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5756, 1, 5995}, + {41, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6246, 3, 6717}, + {41, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 6252, 3, 6714}, + {50, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, + {51, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, + {66, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5494}, + {66, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 5285, 1, 5488}, + {70, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4993, 1, 5044}, + {71, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1547, 1, 1624}, + {74, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3692, 1, 3790}, + {75, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, + {76, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, + {77, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8329}, + {78, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8051}, + {79, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 8480, 16, 8880}, }}; }; diff --git a/lib/include/srsran/common/block_queue.h b/lib/include/srsran/common/block_queue.h index 296ca64ba..076b496a6 100644 --- a/lib/include/srsran/common/block_queue.h +++ b/lib/include/srsran/common/block_queue.h @@ -44,7 +44,6 @@ namespace srsran { template class block_queue { - public: // Callback functions for mutexed operations inside pop/push methods class call_mutexed_itf @@ -116,7 +115,7 @@ public: bool full() { // queue is full? pthread_mutex_lock(&mutex); - bool ret = not check_queue_space_unlocked(false); + bool ret = not check_queue_space_nolock(false); pthread_mutex_unlock(&mutex); return ret; } @@ -172,7 +171,7 @@ private: return ret; } - bool check_queue_space_unlocked(bool block) + bool check_queue_space_nolock(bool block) { num_threads++; if (capacity > 0) { @@ -199,7 +198,7 @@ private: return std::move(value); } pthread_mutex_lock(&mutex); - bool ret = check_queue_space_unlocked(block); + bool ret = check_queue_space_nolock(block); if (ret) { if (mutexed_callback) { mutexed_callback->pushing(value); @@ -219,7 +218,7 @@ private: return false; } pthread_mutex_lock(&mutex); - bool ret = check_queue_space_unlocked(block); + bool ret = check_queue_space_nolock(block); if (ret) { if (mutexed_callback) { mutexed_callback->pushing(value); diff --git a/lib/include/srsran/common/tsan_options.h b/lib/include/srsran/common/tsan_options.h index ad3580d3f..f73ad6edc 100644 --- a/lib/include/srsran/common/tsan_options.h +++ b/lib/include/srsran/common/tsan_options.h @@ -46,9 +46,12 @@ const char* __tsan_default_options() const char* __tsan_default_suppressions() { - // External uninstrumented libraries - return "called_from_lib:libzmq.so\n" - "called_from_lib:libpgm-5.2.so\n"; + return + // External uninstrumented libraries + "called_from_lib:libzmq.so\n" + "called_from_lib:libpgm-5.2.so\n" + // Lock order inversion issue in this function, ignore it as it uses rw locks in read mode + "deadlock:srsenb::mac::rlc_buffer_state\n"; } #ifdef __cplusplus diff --git a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h index 0e383be50..60b8071f2 100644 --- a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h +++ b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h @@ -40,7 +40,8 @@ struct gtpu_args_t { class gtpu_interface_pdcp { public: - virtual void write_pdu(uint16_t rnti, uint32_t bearer_id, srsran::unique_byte_buffer_t pdu) = 0; + // PDCP will only know LCIDs, translation to EPS bearer id will be done by gtpu_pdcp_adapter + virtual void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) = 0; }; // GTPU interface for RRC @@ -58,6 +59,7 @@ public: uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, + uint32_t& addr_in, const bearer_props* props = nullptr) = 0; virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0; virtual void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) = 0; diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index b85c9144a..1ea9f6948 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -266,8 +266,7 @@ public: // Combined interface for PHY to access stack (MAC and RRC) class stack_interface_phy_lte : public mac_interface_phy_lte -{ -}; +{}; } // namespace srsenb diff --git a/lib/include/srsran/interfaces/enb_pdcp_interfaces.h b/lib/include/srsran/interfaces/enb_pdcp_interfaces.h index d28f7cd4c..6030ea3c6 100644 --- a/lib/include/srsran/interfaces/enb_pdcp_interfaces.h +++ b/lib/include/srsran/interfaces/enb_pdcp_interfaces.h @@ -40,6 +40,7 @@ public: class pdcp_interface_rrc { public: + virtual void set_enabled(uint16_t rnti, uint32_t lcid, bool enable) = 0; virtual void reset(uint16_t rnti) = 0; virtual void add_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0; diff --git a/lib/include/srsran/interfaces/enb_x2_interfaces.h b/lib/include/srsran/interfaces/enb_x2_interfaces.h index bbc71022a..9d1149066 100644 --- a/lib/include/srsran/interfaces/enb_x2_interfaces.h +++ b/lib/include/srsran/interfaces/enb_x2_interfaces.h @@ -19,6 +19,7 @@ * */ +#include "srsran/interfaces/enb_gtpu_interfaces.h" #include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_rrc_interface_types.h" @@ -89,6 +90,13 @@ public: * @param nr_rnti The RNTI that has been assigned to the UE on the SgNB */ virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; + + /** + * @brief Signal user activity (i.e. DL/UL traffic) for given RNTI + * + * @param eutra_rnti The RNTI that the EUTRA RRC uses + */ + virtual void set_activity_user(uint16_t eutra_rnti) = 0; }; class stack_nr_interface_stack_eutra @@ -102,7 +110,8 @@ public: class x2_interface : public rrc_nr_interface_rrc, public rrc_eutra_interface_rrc_nr, public stack_nr_interface_stack_eutra, - public pdcp_interface_gtpu + public pdcp_interface_gtpu, // allow GTPU to access PDCP in DL direction + public gtpu_interface_pdcp // allow PDCP to access GTPU in UL direction {}; } // namespace srsenb diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 4d3fe3228..b25917a8d 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -143,8 +143,9 @@ public: virtual int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) = 0; /// User management - virtual int add_user(uint16_t rnti) = 0; - virtual int update_user(uint16_t new_rnti, uint16_t old_rnti) = 0; + virtual int add_user(uint16_t rnti) = 0; + virtual int update_user(uint16_t new_rnti, uint16_t old_rnti) = 0; + virtual void set_activity_user(uint16_t rnti) = 0; }; // NR interface is almost identical to EUTRA version @@ -169,6 +170,7 @@ public: srsran_carrier_nr_t carrier; srsran_pdcch_cfg_nr_t pdcch; srsran_prach_cfg_t prach; + srsran_duplex_mode_t duplex_mode; }; virtual int set_common_cfg(const common_cfg_t& common_cfg) = 0; diff --git a/lib/include/srsran/interfaces/gnb_mac_interfaces.h b/lib/include/srsran/interfaces/gnb_mac_interfaces.h index f59f4db68..39aea1c9c 100644 --- a/lib/include/srsran/interfaces/gnb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_mac_interfaces.h @@ -36,6 +36,8 @@ public: virtual uint16_t reserve_rnti(uint32_t enb_cc_idx) = 0; virtual int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) = 0; + + virtual int remove_ue(uint16_t rnti) = 0; }; // NR interface is identical to EUTRA interface diff --git a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h index fd53075a3..4db79dbb0 100644 --- a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h @@ -21,20 +21,38 @@ #ifndef SRSRAN_GNB_RRC_NR_INTERFACES_H #define SRSRAN_GNB_RRC_NR_INTERFACES_H +#include "srsenb/hdr/phy/phy_interfaces.h" #include "srsran/asn1/ngap.h" #include "srsran/common/byte_buffer.h" + namespace srsenb { class rrc_interface_ngap_nr { public: - virtual int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key) = 0; - virtual int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) = 0; - virtual int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) = 0; - virtual int start_security_mode_procedure(uint16_t rnti) = 0; - virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0; + virtual int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key) = 0; + virtual int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) = 0; + virtual int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) = 0; + virtual int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) = 0; + virtual int start_security_mode_procedure(uint16_t rnti) = 0; + virtual int + establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) = 0; + virtual int allocate_lcid(uint16_t rnti) = 0; + virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0; +}; + +// Cell/Sector configuration for NR cells +struct rrc_cell_cfg_nr_t { + phy_cell_cfg_nr_t phy_cell; // already contains all PHY-related parameters (i.e. RF port, PCI, etc.) + uint32_t tac; // Tracking area code + uint32_t dl_arfcn; // DL freq already included in phy_cell + uint32_t ul_arfcn; // UL freq also in phy_cell + uint32_t band; + srsran_duplex_mode_t duplex_mode; }; +typedef std::vector rrc_cell_list_nr_t; + } // namespace srsenb #endif // SRSRAN_GNB_RRC_NR_INTERFACES_H \ No newline at end of file diff --git a/lib/include/srsran/interfaces/rrc_interface_types.h b/lib/include/srsran/interfaces/rrc_interface_types.h index 431dadfbf..b7685922e 100644 --- a/lib/include/srsran/interfaces/rrc_interface_types.h +++ b/lib/include/srsran/interfaces/rrc_interface_types.h @@ -194,6 +194,49 @@ inline std::string to_string(const scg_failure_cause_t& cause) "nulltype"}; return enum_to_text(options, (uint32_t)scg_failure_cause_t::nulltype, (uint32_t)cause); } + +enum class nr_establishment_cause_t { + emergency, + highPriorityAccess, + mt_Access, + mo_Signalling, + mo_Data, + mo_VoiceCall, + mo_VideoCall, + mo_SMS, + mps_PriorityAccess, + mcs_PriorityAccess, + spare6, + spare5, + spare4, + spare3, + spare2, + spare1, + nulltype +}; +inline std::string to_string(const nr_establishment_cause_t& cause) +{ + constexpr static const char* options[] = { + "emergency", + "highPriorityAccess", + "mt_Access", + "mo_Signalling", + "mo_Data", + "mo_VoiceCall", + "mo_VideoCall", + "mo_SMS", + "mps_PriorityAccess", + "mcs_PriorityAccess", + "spare6", + "spare5", + "spare4", + "spare3", + "spare2", + "spare1", + }; + return enum_to_text(options, (uint32_t)nr_establishment_cause_t::nulltype, (uint32_t)cause); +} + /*************************** * PHY Config **************************/ diff --git a/lib/include/srsran/interfaces/ue_nas_interfaces.h b/lib/include/srsran/interfaces/ue_nas_interfaces.h index a1850064e..dc16ea3d9 100644 --- a/lib/include/srsran/interfaces/ue_nas_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nas_interfaces.h @@ -22,10 +22,26 @@ #ifndef SRSRAN_UE_NAS_INTERFACES_H #define SRSRAN_UE_NAS_INTERFACES_H +#include "srsran/asn1/nas_5g_ies.h" #include "srsran/interfaces/rrc_interface_types.h" namespace srsue { +enum apn_types { + ipv4 = 0b001, + ipv6 = 0b010, + ipv4v6 = 0b011, + unstructured = 0b100, + ethernet = 0b101, +}; +class pdu_session_cfg_t +{ +public: + std::string apn_name; + apn_types apn_type; + std::string apn_user; + std::string apn_pass; +}; class nas_interface_rrc { public: @@ -51,12 +67,20 @@ public: class nas_5g_interface_rrc_nr { public: + virtual int write_pdu(srsran::unique_byte_buffer_t pdu) = 0; }; class nas_5g_interface_procedures { public: virtual int send_registration_request() = 0; + virtual int send_pdu_session_establishment_request(uint32_t transaction_identity, + uint16_t pdu_session_id, + const pdu_session_cfg_t& pdu_session) = 0; + virtual int + add_pdu_session(uint16_t pdu_session_id, uint16_t pdu_session_type, srsran::nas_5g::pdu_address_t pdu_address) = 0; + + virtual uint32_t allocate_next_proc_trans_id() = 0; }; } // namespace srsue diff --git a/lib/include/srsran/interfaces/ue_pdcp_interfaces.h b/lib/include/srsran/interfaces/ue_pdcp_interfaces.h index 20ac7ae10..5807551c0 100644 --- a/lib/include/srsran/interfaces/ue_pdcp_interfaces.h +++ b/lib/include/srsran/interfaces/ue_pdcp_interfaces.h @@ -33,6 +33,7 @@ public: virtual void reestablish() = 0; virtual void reestablish(uint32_t lcid) = 0; virtual void reset() = 0; + virtual void set_enabled(uint32_t lcid, bool enabled) = 0; virtual void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu, int sn = -1) = 0; virtual int add_bearer(uint32_t lcid, srsran::pdcp_config_t cnfg) = 0; virtual void del_bearer(uint32_t lcid) = 0; diff --git a/lib/include/srsran/interfaces/ue_rrc_interfaces.h b/lib/include/srsran/interfaces/ue_rrc_interfaces.h index b9d216704..87d5f23c5 100644 --- a/lib/include/srsran/interfaces/ue_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/ue_rrc_interfaces.h @@ -125,6 +125,12 @@ public: class rrc_nr_interface_nas_5g { public: + virtual ~rrc_nr_interface_nas_5g() = default; + virtual int write_sdu(srsran::unique_byte_buffer_t sdu) = 0; + virtual bool is_connected() = 0; + virtual int connection_request(srsran::nr_establishment_cause_t cause, srsran::unique_byte_buffer_t sdu) = 0; + virtual uint16_t get_mcc() = 0; + virtual uint16_t get_mnc() = 0; }; } // namespace srsue diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index f96aa232b..3b243285c 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -366,6 +366,14 @@ typedef enum SRSRAN_API { SRSRAN_DUPLEX_MODE_INVALID } srsran_duplex_mode_t; +/** + * @brief Determines whether the first DMRS goes into symbol index 2 or 3 + */ +typedef enum { + srsran_dmrs_sch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default) + srsran_dmrs_sch_typeA_pos_3 // Start in slot symbol index 3 +} srsran_dmrs_sch_typeA_pos_t; + /** * @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP) */ diff --git a/lib/include/srsran/phy/gnb/gnb_dl.h b/lib/include/srsran/phy/gnb/gnb_dl.h index 50e3afa89..bb088ee5c 100644 --- a/lib/include/srsran/phy/gnb/gnb_dl.h +++ b/lib/include/srsran/phy/gnb/gnb_dl.h @@ -22,6 +22,7 @@ #ifndef SRSRAN_GNB_DL_H #define SRSRAN_GNB_DL_H +#include "srsran/phy/ch_estimation/csi_rs.h" #include "srsran/phy/common/phy_common_nr.h" #include "srsran/phy/dft/ofdm.h" #include "srsran/phy/phch/pdcch_cfg_nr.h" @@ -87,4 +88,8 @@ srsran_gnb_dl_pdcch_dl_info(const srsran_gnb_dl_t* q, const srsran_dci_dl_nr_t* SRSRAN_API int srsran_gnb_dl_pdcch_ul_info(const srsran_gnb_dl_t* q, const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len); +SRSRAN_API int srsran_gnb_dl_nzp_csi_rs_put(srsran_gnb_dl_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_csi_rs_nzp_resource_t* resource); + #endif // SRSRAN_GNB_DL_H diff --git a/lib/include/srsran/phy/phch/pbch_msg_nr.h b/lib/include/srsran/phy/phch/pbch_msg_nr.h new file mode 100644 index 000000000..8d1e09c09 --- /dev/null +++ b/lib/include/srsran/phy/phch/pbch_msg_nr.h @@ -0,0 +1,62 @@ +/** + * + * \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 SRSRAN_PBCH_MSG_NR_H +#define SRSRAN_PBCH_MSG_NR_H + +#include "srsran/config.h" +#include "srsran/phy/common/phy_common_nr.h" +#include +#include + +/** + * @brief NR PBCH payload size generated by higher layers, deduced from TS 38.331 MIB description + */ +#define SRSRAN_PBCH_MSG_NR_SZ 24 + +/** + * @brief Describes the NR PBCH message + */ +typedef struct SRSRAN_API { + uint8_t payload[SRSRAN_PBCH_MSG_NR_SZ]; ///< Actual PBCH payload provided by higher layers + uint8_t sfn_4lsb; ///< SFN 4 LSB + uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1 + uint8_t k_ssb_msb; ///< Subcarrier offset MSB described in TS 38.211 7.4.3.1 + bool hrf; ///< Half Radio Frame bit + bool crc; ///< Decoder only, it is true only if the received CRC matches +} srsran_pbch_msg_nr_t; + +typedef struct SRSRAN_API { + uint32_t sfn; ///< System frame number + uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1 + bool hrf; ///< Half Radio Frame bit + srsran_subcarrier_spacing_t scs_common; ///< Subcarrier spacing common + uint32_t ssb_offset; ///< SSB subcarrier offset + srsran_dmrs_sch_typeA_pos_t dmrs_typeA_pos; ///< DMRS typeA position + uint32_t coreset0_idx; ///< CORESET Zero configuration index (0-15) + uint32_t ss0_idx; ///< SearchSpace Zero configuration index (0-15) + bool cell_barred; ///< Set to true if the cell is barred + bool intra_freq_reselection; ///< Set to true if allowed + uint32_t spare; ///< Unused bits +} srsran_mib_nr_t; + +SRSRAN_API bool srsran_pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg); + +SRSRAN_API int srsran_pbch_msg_nr_mib_pack(const srsran_mib_nr_t* mib, srsran_pbch_msg_nr_t* msg); + +SRSRAN_API int srsran_pbch_msg_nr_mib_unpack(const srsran_pbch_msg_nr_t* pbch_msg, srsran_mib_nr_t* mib); + +SRSRAN_API uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len); + +SRSRAN_API uint32_t srsran_pbch_msg_nr_mib_info(const srsran_mib_nr_t* mib, char* str, uint32_t str_len); + +#endif // SRSRAN_PBCH_MSG_NR_H diff --git a/lib/include/srsran/phy/phch/pbch_nr.h b/lib/include/srsran/phy/phch/pbch_nr.h index 7df782284..0c5460c38 100644 --- a/lib/include/srsran/phy/phch/pbch_nr.h +++ b/lib/include/srsran/phy/phch/pbch_nr.h @@ -29,11 +29,7 @@ #include "srsran/phy/fec/polar/polar_encoder.h" #include "srsran/phy/fec/polar/polar_rm.h" #include "srsran/phy/modem/modem_table.h" - -/** - * @brief NR PBCH payload size generated by higher layers, deduced from TS 38.331 MIB description - */ -#define SRSRAN_PBCH_NR_PAYLOAD_SZ 24 +#include "srsran/phy/phch/pbch_msg_nr.h" /** * @brief Describes the NR PBCH object initialisation arguments @@ -68,18 +64,6 @@ typedef struct SRSRAN_API { srsran_modem_table_t qpsk; } srsran_pbch_nr_t; -/** - * @brief Describes the PBCH message - */ -typedef struct SRSRAN_API { - uint8_t payload[SRSRAN_PBCH_NR_PAYLOAD_SZ]; ///< Actual PBCH payload provided by higher layers - uint8_t sfn_4lsb; ///< SFN 4 LSB - uint8_t ssb_idx; ///< SS/PBCH blocks index described in TS 38.213 4.1 - uint8_t k_ssb_msb; ///< Subcarrier offset MSB described in TS 38.211 7.4.3.1 - bool hrf; ///< Half Radio Frame bit - bool crc; ///< Decoder only, it is true only if the received CRC matches -} srsran_pbch_msg_nr_t; - /** * @brief Initialises an NR PBCH object with the provided arguments * @param q NR PBCH object @@ -121,6 +105,4 @@ SRSRAN_API int srsran_pbch_nr_decode(srsran_pbch_nr_t* q, const cf_t ce[SRSRAN_SSB_NOF_RE], srsran_pbch_msg_nr_t* msg); -SRSRAN_API uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len); - #endif // SRSRAN_PBCH_NR_H diff --git a/lib/include/srsran/phy/phch/phch_cfg_nr.h b/lib/include/srsran/phy/phch/phch_cfg_nr.h index cd6e04ebf..5e1a40789 100644 --- a/lib/include/srsran/phy/phch/phch_cfg_nr.h +++ b/lib/include/srsran/phy/phch/phch_cfg_nr.h @@ -58,14 +58,6 @@ typedef enum { srsran_dmrs_sch_len_2 // double, 2 symbol long } srsran_dmrs_sch_len_t; -/** - * @brief Determines whether the first pilot goes into symbol index 2 or 3 - */ -typedef enum { - srsran_dmrs_sch_typeA_pos_2 = 0, // Start in slot symbol index 2 (default) - srsran_dmrs_sch_typeA_pos_3 // Start in slot symbol index 3 -} srsran_dmrs_sch_typeA_pos_t; - /** * @brief Determines additional symbols if possible to be added */ diff --git a/lib/include/srsran/phy/phch/prach.h b/lib/include/srsran/phy/phch/prach.h index 298180b69..a1a0927cc 100644 --- a/lib/include/srsran/phy/phch/prach.h +++ b/lib/include/srsran/phy/phch/prach.h @@ -32,6 +32,7 @@ #include "srsran/config.h" #include "srsran/phy/common/phy_common.h" +#include "srsran/phy/common/phy_common_nr.h" #include "srsran/phy/dft/dft.h" #include #include @@ -126,7 +127,7 @@ typedef struct SRSRAN_API { } srsran_prach_sf_config_t; ///@brief Maximum number of subframe number candidates for PRACH NR configuration -#define PRACH_NR_CFG_MAX_NOF_SF 5 +#define PRACH_NR_CFG_MAX_NOF_SF 10 /** * @brief PRACH configuration for NR as described in TS 38.211 Tables 6.3.3.2-2, 6.3.3.2-3 and 6.3.3.2-4 @@ -186,11 +187,17 @@ SRSRAN_API bool srsran_prach_tti_opportunity_config_tdd(uint32_t config_idx, uint32_t current_tti, uint32_t* prach_idx); +SRSRAN_API const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_paired(uint32_t config_idx); + +SRSRAN_API bool srsran_prach_nr_tti_opportunity_fr1_paired(uint32_t config_idx, uint32_t current_tti); + +SRSRAN_API uint32_t srsran_prach_nr_start_symbol_fr1_paired(uint32_t config_idx); + SRSRAN_API const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_unpaired(uint32_t config_idx); SRSRAN_API bool srsran_prach_nr_tti_opportunity_fr1_unpaired(uint32_t config_idx, uint32_t current_tti); -SRSRAN_API uint32_t srsran_prach_nr_start_symbol_fr1_unpaired(uint32_t config_idx); +SRSRAN_API uint32_t srsran_prach_nr_start_symbol(uint32_t config_idx, srsran_duplex_mode_t duplex_mode); SRSRAN_API uint32_t srsran_prach_f_ra_tdd(uint32_t config_idx, uint32_t tdd_ul_dl_config, diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index 681bb3f4b..8f4edbd56 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -401,6 +401,7 @@ private: void update_notification_ack_info(uint32_t rlc_sn); void debug_state(); + void empty_queue_nolock(); int required_buffer_size(const rlc_amd_retx_t& retx); void retransmit_pdu(uint32_t sn); diff --git a/lib/include/srsran/rlc/rlc_tm.h b/lib/include/srsran/rlc/rlc_tm.h index a9c26de86..020897b4b 100644 --- a/lib/include/srsran/rlc/rlc_tm.h +++ b/lib/include/srsran/rlc/rlc_tm.h @@ -77,6 +77,7 @@ private: std::atomic tx_enabled = {true}; + std::mutex metrics_mutex; rlc_bearer_metrics_t metrics = {}; // Thread-safe queues for MAC messages diff --git a/lib/include/srsran/rlc/rlc_um_base.h b/lib/include/srsran/rlc/rlc_um_base.h index f694d80ed..afde99b3a 100644 --- a/lib/include/srsran/rlc/rlc_um_base.h +++ b/lib/include/srsran/rlc/rlc_um_base.h @@ -174,6 +174,7 @@ protected: bool tx_enabled = false; bool rx_enabled = false; + std::mutex metrics_mutex; rlc_bearer_metrics_t metrics = {}; }; diff --git a/srsue/hdr/stack/rrc/rrc_common.h b/lib/include/srsran/rrc/rrc_common.h similarity index 80% rename from srsue/hdr/stack/rrc/rrc_common.h rename to lib/include/srsran/rrc/rrc_common.h index 028b5650a..1bbeff415 100644 --- a/srsue/hdr/stack/rrc/rrc_common.h +++ b/lib/include/srsran/rrc/rrc_common.h @@ -22,23 +22,15 @@ #ifndef SRSUE_RRC_COMMON_H #define SRSUE_RRC_COMMON_H -namespace srsue { +namespace srsran { #include -// RRC states (3GPP 36.331 v10.0.0) -typedef enum { - RRC_STATE_IDLE = 0, - RRC_STATE_CONNECTED, - RRC_STATE_N_ITEMS, -} rrc_state_t; -static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", "CONNECTED"}; - enum quant_s { quant_rsrp, quant_rsrq }; uint8_t rrc_value_to_range(quant_s quant, const float value); float rrc_range_to_value(quant_s quant, const uint8_t range); -} // namespace srsue +} // namespace srsran #endif // SRSUE_RRC_COMMON_H diff --git a/lib/include/srsran/upper/gtpu.h b/lib/include/srsran/upper/gtpu.h index 00183e21f..2ec152b64 100644 --- a/lib/include/srsran/upper/gtpu.h +++ b/lib/include/srsran/upper/gtpu.h @@ -67,8 +67,11 @@ namespace srsran { #define GTPU_MSG_END_MARKER 254 #define GTPU_MSG_DATA_PDU 255 +#define GTPU_EXT_NO_MORE_EXTENSION_HEADERS 0x00 #define GTPU_EXT_HEADER_PDCP_PDU_NUMBER 0b11000000 +#define GTPU_EXT_HEADER_PDU_SESSION_CONTAINER 0x85 +#define GTPU_EXT_HEADER_PDU_SESSION_CONTAINER_LEN 4 struct gtpu_header_t { uint8_t flags = 0; uint8_t message_type = 0; diff --git a/lib/include/srsran/upper/pdcp.h b/lib/include/srsran/upper/pdcp.h index 4e6a5a840..f64cbfb66 100644 --- a/lib/include/srsran/upper/pdcp.h +++ b/lib/include/srsran/upper/pdcp.h @@ -45,6 +45,7 @@ public: void reestablish() override; void reestablish(uint32_t lcid) override; void reset() override; + void set_enabled(uint32_t lcid, bool enabled) override; void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override; void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu); int add_bearer(uint32_t lcid, pdcp_config_t cnfg) override; diff --git a/lib/include/srsran/upper/pdcp_entity_base.h b/lib/include/srsran/upper/pdcp_entity_base.h index 46cd20f75..ee3bc04cc 100644 --- a/lib/include/srsran/upper/pdcp_entity_base.h +++ b/lib/include/srsran/upper/pdcp_entity_base.h @@ -69,6 +69,7 @@ public: virtual void reset() = 0; virtual void reestablish() = 0; + void set_enabled(bool enabled) { active = enabled; } bool is_active() { return active; } bool is_srb() { return cfg.rb_type == PDCP_RB_IS_SRB; } bool is_drb() { return cfg.rb_type == PDCP_RB_IS_DRB; } diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index dcb0b4928..5b74eec28 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -283,6 +283,8 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, srsran_duplex_config_nr_t* in_srsran_duplex_config_nr) { srsran_duplex_config_nr_t srsran_duplex_config_nr = {}; + srsran_duplex_config_nr.mode = SRSRAN_DUPLEX_MODE_TDD; + switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) { case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: srsran_duplex_config_nr.tdd.pattern1.period_ms = 1; diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 557886aab..866d8f4ae 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -36,6 +36,7 @@ set(SOURCES arch_select.cc pcap.c phy_cfg_nr.cc phy_cfg_nr_default.cc + rrc_common.cc rlc_pcap.cc s1ap_pcap.cc security.cc diff --git a/lib/src/common/band_helper.cc b/lib/src/common/band_helper.cc index 55a463739..b377b6af3 100644 --- a/lib/src/common/band_helper.cc +++ b/lib/src/common/band_helper.cc @@ -50,7 +50,7 @@ uint32_t srsran_band_helper::freq_to_nr_arfcn(double freq) if (not is_valid_raster_param(params)) { return 0; } - return (((freq + params.F_REF_Offs_MHz * 1e6) / 1e3 / params.delta_F_global_kHz) + params.N_REF_Offs); + return (((freq - params.F_REF_Offs_MHz * 1e6) / 1e3 / params.delta_F_global_kHz) + params.N_REF_Offs); } // Implements 5.4.2.1 in TS 38.104 @@ -138,6 +138,20 @@ double srsran_band_helper::get_center_freq_from_abs_freq_point_a(uint32_t nof_pr SRSRAN_NRE); } +uint32_t srsran_band_helper::get_abs_freq_point_a_arfcn(uint32_t nof_prb, uint32_t arfcn) +{ + return freq_to_nr_arfcn(get_abs_freq_point_a_from_center_freq(nof_prb, nr_arfcn_to_freq(arfcn))); +} + +double srsran_band_helper::get_abs_freq_point_a_from_center_freq(uint32_t nof_prb, double center_freq) +{ + // for FR1 unit of resources blocks for freq calc is always 180kHz regardless for actual SCS of carrier + // TODO: add offset_to_carrier + return center_freq - + (nof_prb / 2 * SRSRAN_SUBC_SPACING_NR(srsran_subcarrier_spacing_t::srsran_subcarrier_spacing_15kHz) * + SRSRAN_NRE); +} + srsran_ssb_patern_t srsran_band_helper::get_ssb_pattern(uint16_t band, srsran_subcarrier_spacing_t scs) const { // Look for the given band and SCS diff --git a/lib/src/common/enb_events.cc b/lib/src/common/enb_events.cc index e6d12c3e3..ca50d8b3c 100644 --- a/lib/src/common/enb_events.cc +++ b/lib/src/common/enb_events.cc @@ -73,6 +73,47 @@ static double get_time_stamp() return std::chrono::duration_cast(tp).count() * 1e-3; } +/// Escapes the input string. +static std::string escape_string(const std::string& s) +{ + fmt::memory_buffer buff; + for (auto c : s) { + switch (c) { + case ' ': + break; + case '"': + fmt::format_to(buff, "\\\""); + break; + case '\\': + fmt::format_to(buff, "\\\\"); + break; + case '\b': + fmt::format_to(buff, "\\b"); + break; + case '\f': + fmt::format_to(buff, "\\f"); + break; + case '\n': + fmt::format_to(buff, "\\n"); + break; + case '\r': + fmt::format_to(buff, "\\r"); + break; + case '\t': + fmt::format_to(buff, "\\t"); + break; + default: + // Cast to signed char for machines that treat chars as an unsigned type. + if ((signed char)c >= '\x00' && (signed char)c <= '\x1f') { + fmt::format_to(buff, "\\u{:04x}", c); + } else { + buff.push_back(c); + } + } + } + return fmt::to_string(buff); +} + namespace { /// Common metrics to all events. @@ -200,7 +241,8 @@ public: { rrc_event_t ctx(""); - const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str; + const std::string& asn1 = + (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str); ctx.write("event"); ctx.write(get_time_stamp()); @@ -284,7 +326,8 @@ public: { meas_report_event_t ctx(""); - const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str; + const std::string& asn1 = + (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str); ctx.write("event"); ctx.write(get_time_stamp()); @@ -304,7 +347,8 @@ public: { rlf_report_event_t ctx(""); - const std::string& asn1 = (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : asn1_txt_str; + const std::string& asn1 = + (asn1_format == event_logger::asn1_output_format::octets) ? asn1_oct_str : escape_string(asn1_txt_str); ctx.write("event"); ctx.write(get_time_stamp()); diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index 89ae602cc..20403bf8d 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -466,6 +466,8 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) make_prach_default_lte(prach); break; } + + prach.tdd_config.configured = (duplex.mode == SRSRAN_DUPLEX_MODE_TDD); } } // namespace srsran diff --git a/srsue/src/stack/rrc/rrc_common.cc b/lib/src/common/rrc_common.cc similarity index 94% rename from srsue/src/stack/rrc/rrc_common.cc rename to lib/src/common/rrc_common.cc index c5b38c3b8..a7c496b9f 100644 --- a/srsue/src/stack/rrc/rrc_common.cc +++ b/lib/src/common/rrc_common.cc @@ -19,9 +19,9 @@ * */ -#include "srsue/hdr/stack/rrc/rrc_common.h" +#include "srsran/rrc/rrc_common.h" -namespace srsue { +namespace srsran { uint8_t rrc_value_to_range(quant_s quant, const float value) { @@ -57,4 +57,4 @@ float rrc_range_to_value(quant_s quant, const uint8_t range) return val; } -} // namespace srsue \ No newline at end of file +} // namespace srsran \ No newline at end of file diff --git a/lib/src/common/test/band_helper_test.cc b/lib/src/common/test/band_helper_test.cc index f9c049a68..0fb5fb338 100644 --- a/lib/src/common/test/band_helper_test.cc +++ b/lib/src/common/test/band_helper_test.cc @@ -86,6 +86,9 @@ int bands_test_nr() TESTASSERT(band_vector.at(0) == 77); TESTASSERT(band_vector.at(1) == 78); + // n78 + TESTASSERT(bands.get_abs_freq_point_a_arfcn(52, 634240) == 633928); + // Invalid configs // For 30 kHz, 620001 is not a valid ARFCN, only every 2nd band_vector = bands.get_bands_nr(620001, srsran::srsran_band_helper::KHZ_30); diff --git a/lib/src/gtpu/gtpu.cc b/lib/src/gtpu/gtpu.cc index 91bd90ac1..3942a5ac9 100644 --- a/lib/src/gtpu/gtpu.cc +++ b/lib/src/gtpu/gtpu.cc @@ -121,17 +121,26 @@ bool gtpu_read_ext_header(srsran::byte_buffer_t* pdu, return true; } - if (header->next_ext_hdr_type == GTPU_EXT_HEADER_PDCP_PDU_NUMBER) { - pdu->msg += HEADER_PDCP_PDU_NUMBER_SIZE; - pdu->N_bytes -= HEADER_PDCP_PDU_NUMBER_SIZE; - header->ext_buffer.resize(HEADER_PDCP_PDU_NUMBER_SIZE); - for (size_t i = 0; i < HEADER_PDCP_PDU_NUMBER_SIZE; ++i) { - header->ext_buffer[i] = **ptr; - (*ptr)++; - } - } else { - logger.error("gtpu_read_header - Unhandled GTP-U Extension Header Type: 0x%x", header->next_ext_hdr_type); - return false; + // TODO: Iterate over next headers until no more extension headers + switch (header->next_ext_hdr_type) { + case GTPU_EXT_HEADER_PDCP_PDU_NUMBER: + pdu->msg += HEADER_PDCP_PDU_NUMBER_SIZE; + pdu->N_bytes -= HEADER_PDCP_PDU_NUMBER_SIZE; + header->ext_buffer.resize(HEADER_PDCP_PDU_NUMBER_SIZE); + for (size_t i = 0; i < HEADER_PDCP_PDU_NUMBER_SIZE; ++i) { + header->ext_buffer[i] = **ptr; + (*ptr)++; + } + break; + case GTPU_EXT_HEADER_PDU_SESSION_CONTAINER: + pdu->msg += GTPU_EXT_HEADER_PDU_SESSION_CONTAINER_LEN; + pdu->N_bytes -= GTPU_EXT_HEADER_PDU_SESSION_CONTAINER_LEN; + logger.warning("skip parsing of GTPU_EXT_HEADER_PDU_SESSION_CONTAINER"); + // TODO: Save Header Extension + break; + default: + logger.error("gtpu_read_header - Unhandled GTP-U Extension Header Type: 0x%x", header->next_ext_hdr_type); + return false; } return true; } diff --git a/lib/src/pdcp/pdcp.cc b/lib/src/pdcp/pdcp.cc index 2715f7959..8cb55300d 100644 --- a/lib/src/pdcp/pdcp.cc +++ b/lib/src/pdcp/pdcp.cc @@ -72,6 +72,15 @@ void pdcp::reset() pdcp_array.clear(); } +void pdcp::set_enabled(uint32_t lcid, bool enabled) +{ + if (valid_lcid(lcid)) { + pdcp_array.at(lcid)->set_enabled(enabled); + } else { + logger.warning("LCID %d doesn't exist while setting enabled", lcid); + } +} + /******************************************************************************* RRC/GW interface *******************************************************************************/ diff --git a/lib/src/pdcp/pdcp_entity_lte.cc b/lib/src/pdcp/pdcp_entity_lte.cc index 9e9362aee..73edecca1 100644 --- a/lib/src/pdcp/pdcp_entity_lte.cc +++ b/lib/src/pdcp/pdcp_entity_lte.cc @@ -143,6 +143,11 @@ void pdcp_entity_lte::reset() // GW/RRC interface void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn) { + if (!active) { + logger.warning("Dropping %s SDU due to inactive bearer", rrc->get_rb_name(lcid)); + return; + } + if (rlc->sdu_queue_is_full(lcid)) { logger.info(sdu->msg, sdu->N_bytes, "Dropping %s SDU due to full queue", rrc->get_rb_name(lcid)); return; @@ -225,6 +230,11 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn) // RLC interface void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu) { + if (!active) { + logger.warning("Dropping %s PDU due to inactive bearer", rrc->get_rb_name(lcid)); + return; + } + // Handle control PDUs if (is_drb() && is_control_pdu(pdu)) { logger.info("Handling PDCP control PDU"); diff --git a/lib/src/phy/gnb/gnb_dl.c b/lib/src/phy/gnb/gnb_dl.c index 1741351a4..ab0865eea 100644 --- a/lib/src/phy/gnb/gnb_dl.c +++ b/lib/src/phy/gnb/gnb_dl.c @@ -176,7 +176,7 @@ void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q) return; } - float norm_factor = gnb_dl_get_norm_factor(q->pdcch.carrier.nof_prb); + float norm_factor = gnb_dl_get_norm_factor(q->pdsch.carrier.nof_prb); for (uint32_t i = 0; i < q->nof_tx_antennas; i++) { srsran_ofdm_tx_sf(&q->fft[i]); @@ -318,3 +318,19 @@ int srsran_gnb_dl_pdcch_ul_info(const srsran_gnb_dl_t* q, const srsran_dci_ul_nr return len; } + +int srsran_gnb_dl_nzp_csi_rs_put(srsran_gnb_dl_t* q, + const srsran_slot_cfg_t* slot_cfg, + const srsran_csi_rs_nzp_resource_t* resource) +{ + if (q == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + if (srsran_csi_rs_nzp_put_resource(&q->carrier, slot_cfg, resource, q->sf_symbols[0]) < SRSRAN_SUCCESS) { + ERROR("Error putting NZP-CSI-RS resource"); + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} diff --git a/lib/src/phy/phch/dci_nr.c b/lib/src/phy/phch/dci_nr.c index 233074726..c866ac7ff 100644 --- a/lib/src/phy/phch/dci_nr.c +++ b/lib/src/phy/phch/dci_nr.c @@ -1278,7 +1278,7 @@ static uint32_t dci_nr_format_1_0_to_str(const srsran_dci_dl_nr_t* dci, char* st // HARQ process number – 4 bits if (rnti_type == srsran_rnti_type_c || rnti_type == srsran_rnti_type_tc) { - len = srsran_print_check(str, str_len, len, "harq_id=%d ", dci->harq_feedback); + len = srsran_print_check(str, str_len, len, "harq_id=%d ", dci->pid); } // System information indicator – 1 bit diff --git a/lib/src/phy/phch/pbch_msg_nr.c b/lib/src/phy/phch/pbch_msg_nr.c new file mode 100644 index 000000000..9f223be24 --- /dev/null +++ b/lib/src/phy/phch/pbch_msg_nr.c @@ -0,0 +1,179 @@ +/** + * + * \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 "srsran/phy/phch/pbch_msg_nr.h" +#include "srsran/phy/utils/bit.h" +#include "srsran/phy/utils/vector.h" + +static bool pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg) +{ + return msg->payload[0] == 0; +} + +bool srsran_pbch_msg_nr_is_mib(const srsran_pbch_msg_nr_t* msg) +{ + if (msg == NULL) { + return false; + } + + return pbch_msg_nr_is_mib(msg); +} + +int srsran_pbch_msg_nr_mib_pack(const srsran_mib_nr_t* mib, srsran_pbch_msg_nr_t* pbch_msg) +{ + if (mib == NULL || pbch_msg == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Copy PBCH message context + pbch_msg->sfn_4lsb = mib->sfn & 0b1111; + pbch_msg->ssb_idx = mib->ssb_idx; + pbch_msg->k_ssb_msb = mib->ssb_offset >> 4U; + pbch_msg->hrf = mib->hrf; + + // Pack MIB payload + uint8_t* y = pbch_msg->payload; + + // MIB - 1 bit + *(y++) = 0; + + // systemFrameNumber - 6 bits MSB + srsran_bit_unpack(mib->sfn >> 4U, &y, 6); + + // subCarrierSpacingCommon - 1 bit + *(y++) = (mib->scs_common == srsran_subcarrier_spacing_15kHz || mib->scs_common == srsran_subcarrier_spacing_60kHz) + ? 0 + : 1; + + // ssb-SubcarrierOffset - 4 bits + srsran_bit_unpack(mib->ssb_offset, &y, 4); + + // dmrs-TypeA-Position - 1 bit + *(y++) = (mib->dmrs_typeA_pos == srsran_dmrs_sch_typeA_pos_2) ? 0 : 1; + + // pdcch-ConfigSIB1 + // controlResourceSetZero - 4 bits + srsran_bit_unpack(mib->coreset0_idx, &y, 4); + + // searchSpaceZero - 4 bits + srsran_bit_unpack(mib->ss0_idx, &y, 4); + + // Barred - 1 bit + *(y++) = (mib->cell_barred) ? 0 : 1; + + // intraFreqReselection - 1 bit + *(y++) = (mib->intra_freq_reselection) ? 0 : 1; + + // Spare - 1 bit + srsran_bit_unpack(mib->spare, &y, 1); + + return SRSRAN_SUCCESS; +} + +int srsran_pbch_msg_nr_mib_unpack(const srsran_pbch_msg_nr_t* pbch_msg, srsran_mib_nr_t* mib) +{ + if (mib == NULL || pbch_msg == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Copy PBCH message context + mib->sfn = pbch_msg->sfn_4lsb; + mib->ssb_idx = pbch_msg->ssb_idx; + mib->hrf = pbch_msg->hrf; + mib->ssb_offset = pbch_msg->k_ssb_msb << 4U; + + // Pack MIB payload + uint8_t* y = (uint8_t*)pbch_msg->payload; + + // MIB - 1 bit + if (!pbch_msg_nr_is_mib(pbch_msg)) { + return SRSRAN_ERROR; + } + y++; + + // systemFrameNumber - 6 bits MSB + mib->sfn |= srsran_bit_pack(&y, 6) << 4U; + + // subCarrierSpacingCommon - 1 bit + mib->scs_common = *(y++) == 0 ? srsran_subcarrier_spacing_15kHz : srsran_subcarrier_spacing_30kHz; + + // ssb-SubcarrierOffset - 4 bits + mib->ssb_offset |= srsran_bit_pack(&y, 4); + + // dmrs-TypeA-Position - 1 bit + mib->dmrs_typeA_pos = *(y++) == 0 ? srsran_dmrs_sch_typeA_pos_2 : srsran_dmrs_sch_typeA_pos_3; + + // pdcch-ConfigSIB1 + // controlResourceSetZero - 4 bits + mib->coreset0_idx = srsran_bit_pack(&y, 4); + + // searchSpaceZero - 4 bits + mib->ss0_idx = srsran_bit_pack(&y, 4); + + // Barred - 1 bit + mib->cell_barred = (*(y++) == 0); + + // intraFreqReselection - 1 bit + mib->intra_freq_reselection = (*(y++) == 0); + + // Spare - 1 bit + mib->spare = srsran_bit_pack(&y, 1); + + return SRSRAN_SUCCESS; +} + +uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len) +{ + if (msg == NULL || str == NULL || str_len == 0) { + return 0; + } + + uint32_t len = 0; + + len = srsran_print_check(str, str_len, len, "payload="); + + len += srsran_vec_sprint_hex(&str[len], str_len - len, (uint8_t*)msg->payload, SRSRAN_PBCH_MSG_NR_SZ); + + len = srsran_print_check(str, + str_len, + len, + " sfn_lsb=%d ssb_idx=%d k_ssb_msb=%d hrf=%d ", + msg->sfn_4lsb, + msg->ssb_idx, + msg->k_ssb_msb, + msg->hrf); + + return len; +} + +uint32_t srsran_pbch_msg_nr_mib_info(const srsran_mib_nr_t* mib, char* str, uint32_t str_len) +{ + uint32_t len = 0; + + len = srsran_print_check(str, + str_len, + len, + "sfn=%d ssb_idx=%d hrf=%c scs=%d ssb_offset=%d dmrs_typeA_pos=%s coreset0=%d ss0=%d " + "barred=%c intra_freq_reselection=%c spare=%d", + mib->sfn, + mib->ssb_idx, + mib->hrf ? 'y' : 'n', + SRSRAN_SUBC_SPACING_NR(mib->scs_common) / 1000, + mib->ssb_offset, + mib->dmrs_typeA_pos == srsran_dmrs_sch_typeA_pos_2 ? "pos2" : "pos3", + mib->coreset0_idx, + mib->ss0_idx, + mib->cell_barred ? 'y' : 'n', + mib->intra_freq_reselection ? 'y' : 'n', + mib->spare); + + return len; +} diff --git a/lib/src/phy/phch/pbch_nr.c b/lib/src/phy/phch/pbch_nr.c index c12cb4c31..077b398f8 100644 --- a/lib/src/phy/phch/pbch_nr.c +++ b/lib/src/phy/phch/pbch_nr.c @@ -52,7 +52,7 @@ /* * Number of generated payload bits, called A */ -#define PBCH_NR_A (SRSRAN_PBCH_NR_PAYLOAD_SZ + 8) +#define PBCH_NR_A (SRSRAN_PBCH_MSG_NR_SZ + 8) /* * Number of payload bits plus CRC @@ -193,7 +193,7 @@ static void pbch_nr_pbch_msg_pack(const srsran_pbch_nr_cfg_t* cfg, const srsran_pbch_msg_nr_t* msg, uint8_t a[PBCH_NR_A]) { // Extract actual payload size - uint32_t A_hat = SRSRAN_PBCH_NR_PAYLOAD_SZ; + uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ; // Put SFN in a_hat[A_hat] to a_hat[A_hat + 3] uint32_t j_sfn = 0; @@ -240,7 +240,7 @@ pbch_nr_pbch_msg_unpack(const srsran_pbch_nr_cfg_t* cfg, const uint8_t a[PBCH_NR } // Extract actual payload size - uint32_t A_hat = SRSRAN_PBCH_NR_PAYLOAD_SZ; + uint32_t A_hat = SRSRAN_PBCH_MSG_NR_SZ; // Put SFN in a_hat[A_hat] to a_hat[A_hat + 3] uint32_t j_sfn = 0; @@ -660,27 +660,3 @@ int srsran_pbch_nr_decode(srsran_pbch_nr_t* q, return SRSRAN_SUCCESS; } - -uint32_t srsran_pbch_msg_info(const srsran_pbch_msg_nr_t* msg, char* str, uint32_t str_len) -{ - if (msg == NULL || str == NULL || str_len == 0) { - return 0; - } - - uint32_t len = 0; - - len = srsran_print_check(str, str_len, len, "payload="); - - len += srsran_vec_sprint_hex(&str[len], str_len - len, (uint8_t*)msg->payload, SRSRAN_PBCH_NR_PAYLOAD_SZ); - - len = srsran_print_check(str, - str_len, - len, - " sfn_lsb=%d ssb_idx=%d k_ssb_msb=%d hrf=%d ", - msg->sfn_4lsb, - msg->ssb_idx, - msg->k_ssb_msb, - msg->hrf); - - return len; -} diff --git a/lib/src/phy/phch/prach.c b/lib/src/phy/phch/prach.c index 85144d694..7551ec969 100644 --- a/lib/src/phy/phch/prach.c +++ b/lib/src/phy/phch/prach.c @@ -24,6 +24,7 @@ #include #include "srsran/phy/common/phy_common.h" +#include "srsran/phy/common/phy_common_nr.h" #include "srsran/phy/phch/prach.h" #include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/vector.h" @@ -127,16 +128,20 @@ bool srsran_prach_tti_opportunity(srsran_prach_t* p, uint32_t current_tti, int a return false; } - if (p->is_nr) { - return srsran_prach_nr_tti_opportunity_fr1_unpaired(p->config_idx, current_tti); - } - uint32_t config_idx = p->config_idx; - if (!p->tdd_config.configured) { - return srsran_prach_tti_opportunity_config_fdd(config_idx, current_tti, allowed_subframe); + if (p->tdd_config.configured) { + if (p->is_nr) { + return srsran_prach_nr_tti_opportunity_fr1_unpaired(p->config_idx, current_tti); + } else { + return srsran_prach_tti_opportunity_config_tdd( + config_idx, p->tdd_config.sf_config, current_tti, &p->current_prach_idx); + } } else { - return srsran_prach_tti_opportunity_config_tdd( - config_idx, p->tdd_config.sf_config, current_tti, &p->current_prach_idx); + if (p->is_nr) { + return srsran_prach_nr_tti_opportunity_fr1_paired(p->config_idx, current_tti); + } else { + return srsran_prach_tti_opportunity_config_fdd(config_idx, current_tti, allowed_subframe); + } } } @@ -290,6 +295,66 @@ void srsran_prach_sf_config(uint32_t config_idx, srsran_prach_sf_config_t* sf_co memcpy(sf_config, &prach_sf_config[config_idx % 16], sizeof(srsran_prach_sf_config_t)); } +const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_paired(uint32_t config_idx) +{ + if (config_idx < PRACH_NR_CFG_FR1_PAIRED_NOF_CFG) { + return &prach_nr_cfg_fr1_paired[config_idx]; + } + + ERROR("Invalid configuration index %d", config_idx); + return NULL; +} + +bool srsran_prach_nr_tti_opportunity_fr1_paired(uint32_t config_idx, uint32_t current_tti) +{ + uint32_t sfn = current_tti / SRSRAN_NOF_SF_X_FRAME; + uint32_t sf_idx = current_tti % SRSRAN_NOF_SF_X_FRAME; + + // Get configuration + const prach_nr_config_t* cfg = srsran_prach_nr_get_cfg_fr1_paired(config_idx); + if (cfg == NULL) { + return false; + } + + // Protect zero division + if (cfg->x == 0) { + ERROR("Invalid Zero value"); + return false; + } + + // Check for System Frame Number match + if (sfn % cfg->x != cfg->y) { + return false; + } + + // Protect subframe number vector access + if (cfg->nof_subframe_number > PRACH_NR_CFG_MAX_NOF_SF) { + ERROR("Invalid number of subframes (%d)", cfg->nof_subframe_number); + return false; + } + + // Check for subframe number match + for (uint32_t i = 0; i < cfg->nof_subframe_number; i++) { + if (cfg->subframe_number[i] == sf_idx) { + return true; + } + } + + // If reached here, no opportunity + return false; +} + +uint32_t srsran_prach_nr_start_symbol_fr1_paired(uint32_t config_idx) +{ + // Get configuration + const prach_nr_config_t* cfg = srsran_prach_nr_get_cfg_fr1_paired(config_idx); + if (cfg == NULL) { + return 0; + } + + return cfg->starting_symbol; +} + const prach_nr_config_t* srsran_prach_nr_get_cfg_fr1_unpaired(uint32_t config_idx) { if (config_idx < PRACH_NR_CFG_FR1_UNPAIRED_NOF_CFG) { @@ -339,12 +404,21 @@ bool srsran_prach_nr_tti_opportunity_fr1_unpaired(uint32_t config_idx, uint32_t return false; } -uint32_t srsran_prach_nr_start_symbol_fr1_unpaired(uint32_t config_idx) +uint32_t srsran_prach_nr_start_symbol(uint32_t config_idx, srsran_duplex_mode_t duplex_mode) { - // Get configuration - const prach_nr_config_t* cfg = srsran_prach_nr_get_cfg_fr1_unpaired(config_idx); - if (cfg == NULL) { - return false; + const prach_nr_config_t* cfg; + if (duplex_mode == SRSRAN_DUPLEX_MODE_TDD) { + // Get configuration + cfg = srsran_prach_nr_get_cfg_fr1_unpaired(config_idx); + if (cfg == NULL) { + return 0; + } + } else { + // Get configuration + cfg = srsran_prach_nr_get_cfg_fr1_paired(config_idx); + if (cfg == NULL) { + return 0; + } } return cfg->starting_symbol; diff --git a/lib/src/phy/phch/prach_tables.h b/lib/src/phy/phch/prach_tables.h index bc0727a5e..de89cec39 100644 --- a/lib/src/phy/phch/prach_tables.h +++ b/lib/src/phy/phch/prach_tables.h @@ -455,10 +455,29 @@ static const prach_nr_config_t prach_nr_cfg_fr1_unpaired[PRACH_NR_CFG_FR1_UNPAIR {0, 1, 0, {8}, 1, 0}, {0, 1, 0, {7}, 1, 0}, {0, 1, 0, {6}, 1, 0}, {0, 1, 0, {5}, 1, 0}, {0, 1, 0, {4}, 1, 0}, {0, 1, 0, {3}, 1, 0}, - {0, 1, 0, {2}, 1, 0}, {0, 1, 0, {1, 6}, 1, 0}, - {0, 1, 0, {1, 6}, 1, 7}, {0, 1, 0, {4, 9}, 1, 0}, - {0, 1, 0, {3, 8}, 1, 0}, {0, 1, 0, {2, 7}, 1, 0}, - {0, 1, 0, {8, 9}, 1, 0}, {0, 1, 0, {4, 8, 9}, 1, 0}, - {0, 1, 0, {3, 4, 9}, 1, 0}, {0, 1, 0, {7, 8, 9}, 1, 0}, - {0, 1, 0, {3, 4, 8, 9}, 1, 0}, {0, 1, 0, {6, 7, 8, 9}, 1, 0}, - {0, 1, 0, {1, 4, 6, 9}, 1, 0}, {0, 1, 0, {1, 3, 5, 7, 9}, 1, 0}}; + {0, 1, 0, {2}, 1, 0}, {0, 1, 0, {1, 6}, 2, 0}, + {0, 1, 0, {1, 6}, 2, 7}, {0, 1, 0, {4, 9}, 2, 0}, + {0, 1, 0, {3, 8}, 2, 0}, {0, 1, 0, {2, 7}, 2, 0}, + {0, 1, 0, {8, 9}, 2, 0}, {0, 1, 0, {4, 8, 9}, 3, 0}, + {0, 1, 0, {3, 4, 9}, 3, 0}, {0, 1, 0, {7, 8, 9}, 3, 0}, + {0, 1, 0, {3, 4, 8, 9}, 4, 0}, {0, 1, 0, {6, 7, 8, 9}, 4, 0}, + {0, 1, 0, {1, 4, 6, 9}, 4, 0}, {0, 1, 0, {1, 3, 5, 7, 9}, 5, 0}}; + +#define PRACH_NR_CFG_FR1_PAIRED_NOF_CFG 28 + +// Table 6.3.3.2-2: Random access configurations for FR1 and paired spectrum. +static const prach_nr_config_t prach_nr_cfg_fr1_paired[PRACH_NR_CFG_FR1_PAIRED_NOF_CFG] = { + {0, 16, 1, {1}, 1, 0}, {0, 16, 1, {4}, 1, 0}, + {0, 16, 1, {7}, 1, 0}, {0, 16, 1, {9}, 1, 0}, + {0, 8, 1, {1}, 1, 0}, {0, 8, 1, {4}, 1, 0}, + {0, 8, 1, {7}, 1, 0}, {0, 8, 1, {9}, 1, 0}, + {0, 4, 1, {1}, 1, 0}, {0, 4, 1, {4}, 1, 0}, + {0, 4, 1, {7}, 1, 0}, {0, 4, 1, {9}, 1, 0}, + {0, 2, 1, {1}, 1, 0}, {0, 2, 1, {4}, 1, 0}, + {0, 2, 1, {7}, 1, 0}, {0, 2, 1, {9}, 1, 0}, + {0, 1, 0, {1}, 1, 0}, {0, 1, 0, {4}, 1, 0}, + {0, 1, 0, {7}, 1, 0}, {0, 1, 0, {1, 6}, 2, 0}, + {0, 1, 0, {2, 7}, 2, 0}, {0, 1, 0, {3, 8}, 2, 0}, + {0, 1, 0, {1, 4, 7}, 3, 0}, {0, 1, 0, {2, 5, 8}, 3, 0}, + {0, 1, 0, {3, 6, 9}, 3, 0}, {0, 1, 0, {0, 2, 4, 6, 8}, 5, 0}, + {0, 1, 0, {1, 3, 5, 7, 9}, 5, 0}, {0, 1, 0, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 10, 0}}; \ No newline at end of file diff --git a/lib/src/phy/phch/regs.c b/lib/src/phy/phch/regs.c index ecb85be65..5e152277c 100644 --- a/lib/src/phy/phch/regs.c +++ b/lib/src/phy/phch/regs.c @@ -616,6 +616,7 @@ int regs_num_x_symbol(uint32_t symbol, uint32_t nof_port, srsran_cp_t cp) ERROR("Invalid symbol %d", symbol); return SRSRAN_ERROR; } + return SRSRAN_ERROR; } /** diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 7569d3624..77c9b059b 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -639,6 +639,10 @@ add_executable(dci_nr_test dci_nr_test.c) target_link_libraries(dci_nr_test srsran_phy) add_nr_test(dci_nr_test dci_nr_test) +add_executable(mib_nr_test mib_nr_test.c) +target_link_libraries(mib_nr_test srsran_phy) +add_nr_test(mib_nr_test mib_nr_test) + add_executable(pucch_nr_test pucch_nr_test.c) target_link_libraries(pucch_nr_test srsran_phy) add_nr_test(pucch_nr_test pucch_nr_test) diff --git a/lib/src/phy/phch/test/mib_nr_test.c b/lib/src/phy/phch/test/mib_nr_test.c new file mode 100644 index 000000000..4ea88fbc7 --- /dev/null +++ b/lib/src/phy/phch/test/mib_nr_test.c @@ -0,0 +1,109 @@ +/** + * + * \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 "srsran/phy/phch/pbch_msg_nr.h" +#include "srsran/phy/utils/debug.h" +#include "srsran/phy/utils/random.h" +#include "srsran/support/srsran_test.h" +#include +#include + +static uint32_t nof_repetitions = 16; +static srsran_random_t random_gen = NULL; + +static int test_packing_unpacking() +{ + for (uint32_t r = 0; r < nof_repetitions; r++) { + srsran_mib_nr_t mib = {}; + mib.sfn = srsran_random_uniform_int_dist(random_gen, 0, 1023); + mib.ssb_idx = srsran_random_uniform_int_dist(random_gen, 0, 127); + mib.hrf = srsran_random_bool(random_gen, 0.5f); + mib.scs_common = + srsran_random_bool(random_gen, 0.5f) ? srsran_subcarrier_spacing_15kHz : srsran_subcarrier_spacing_30kHz; + mib.ssb_offset = srsran_random_uniform_int_dist(random_gen, 0, 31); + mib.dmrs_typeA_pos = + srsran_random_bool(random_gen, 0.5f) ? srsran_dmrs_sch_typeA_pos_2 : srsran_dmrs_sch_typeA_pos_3; + mib.coreset0_idx = srsran_random_uniform_int_dist(random_gen, 0, 15); + mib.ss0_idx = srsran_random_uniform_int_dist(random_gen, 0, 15); + mib.cell_barred = srsran_random_bool(random_gen, 0.5f); + mib.intra_freq_reselection = srsran_random_bool(random_gen, 0.5f); + mib.spare = srsran_random_uniform_int_dist(random_gen, 0, 1); + + srsran_pbch_msg_nr_t pbch_msg = {}; + TESTASSERT(srsran_pbch_msg_nr_mib_pack(&mib, &pbch_msg) == SRSRAN_SUCCESS); + + TESTASSERT(srsran_pbch_msg_nr_is_mib(&pbch_msg)); + + srsran_mib_nr_t mib2 = {}; + TESTASSERT(srsran_pbch_msg_nr_mib_unpack(&pbch_msg, &mib2) == SRSRAN_SUCCESS); + + char str1[256]; + char str2[256]; + char strp[256]; + srsran_pbch_msg_nr_mib_info(&mib, str1, (uint32_t)sizeof(str1)); + srsran_pbch_msg_nr_mib_info(&mib2, str2, (uint32_t)sizeof(str2)); + srsran_pbch_msg_info(&pbch_msg, strp, (uint32_t)sizeof(strp)); + + if (memcmp(&mib, &mib2, sizeof(srsran_mib_nr_t)) != 0) { + ERROR("Failed packing/unpacking MIB"); + printf(" Source: %s\n", str1); + printf("Unpacked: %s\n", str2); + printf(" Packed: %s\n", strp); + return SRSRAN_ERROR; + } + } + + return SRSRAN_SUCCESS; +} + +static void usage(char* prog) +{ + printf("Usage: %s [cpndv]\n", prog); + printf("\t-v Increase verbose [default none]\n"); + printf("\t-R Set number of Packing/Unpacking [default %d]\n", nof_repetitions); +} + +static void parse_args(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "vR")) != -1) { + switch (opt) { + case 'v': + srsran_verbose++; + break; + case 'R': + nof_repetitions = (uint32_t)strtol(argv[optind], NULL, 10); + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +int main(int argc, char** argv) +{ + parse_args(argc, argv); + + int ret = SRSRAN_ERROR; + random_gen = srsran_random_init(1234); + + if (test_packing_unpacking() < SRSRAN_SUCCESS) { + goto clean_exit; + } + + ret = SRSRAN_SUCCESS; + +clean_exit: + srsran_random_free(random_gen); + return ret; +} diff --git a/lib/src/phy/rf/rf_uhd_imp.cc b/lib/src/phy/rf/rf_uhd_imp.cc index 0abd6192f..a932ab5db 100644 --- a/lib/src/phy/rf/rf_uhd_imp.cc +++ b/lib/src/phy/rf/rf_uhd_imp.cc @@ -498,7 +498,7 @@ bool rf_uhd_rx_wait_lo_locked(void* h) return is_locked; } -static inline int rf_uhd_start_rx_stream_unsafe(rf_uhd_handler_t* handler) +static inline int rf_uhd_start_rx_stream_nolock(rf_uhd_handler_t* handler) { // Check if stream was not created or started if (not handler->uhd->is_rx_ready() or handler->rx_stream_enabled) { @@ -521,10 +521,10 @@ int rf_uhd_start_rx_stream(void* h, bool now) rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; std::unique_lock lock(handler->rx_mutex); - return rf_uhd_start_rx_stream_unsafe(handler); + return rf_uhd_start_rx_stream_nolock(handler); } -static inline int rf_uhd_stop_rx_stream_unsafe(rf_uhd_handler_t* handler) +static inline int rf_uhd_stop_rx_stream_nolock(rf_uhd_handler_t* handler) { // Check if stream was created or stream was not started if (not handler->uhd->is_rx_ready() or not handler->rx_stream_enabled) { @@ -547,7 +547,7 @@ int rf_uhd_stop_rx_stream(void* h) rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h; std::unique_lock lock(handler->rx_mutex); - if (rf_uhd_stop_rx_stream_unsafe(handler) < SRSRAN_SUCCESS) { + if (rf_uhd_stop_rx_stream_nolock(handler) < SRSRAN_SUCCESS) { return SRSRAN_ERROR; } @@ -946,7 +946,7 @@ int rf_uhd_close(void* h) return SRSRAN_SUCCESS; } -static inline void rf_uhd_set_master_clock_rate_unsafe(rf_uhd_handler_t* handler, double rate) +static inline void rf_uhd_set_master_clock_rate_nolock(rf_uhd_handler_t* handler, double rate) { // Set master clock rate if it is allowed and change is required if (handler->dynamic_master_rate and handler->current_master_clock != rate) { @@ -994,14 +994,14 @@ double rf_uhd_set_rx_srate(void* h, double freq) // Stop RX streamer if (RF_UHD_IMP_PROHIBITED_STOP_START.count(handler->devname) == 0) { - if (rf_uhd_stop_rx_stream_unsafe(handler) != SRSRAN_SUCCESS) { + if (rf_uhd_stop_rx_stream_nolock(handler) != SRSRAN_SUCCESS) { return SRSRAN_ERROR; } } // Set master clock rate if (fmod(handler->current_master_clock, freq) > 0.0) { - rf_uhd_set_master_clock_rate_unsafe(handler, 4 * freq); + rf_uhd_set_master_clock_rate_nolock(handler, 4 * freq); } if (handler->nof_rx_channels > 1) { @@ -1052,7 +1052,7 @@ double rf_uhd_set_tx_srate(void* h, double freq) // Set master clock rate if (fmod(handler->current_master_clock, freq) > 0.0) { - rf_uhd_set_master_clock_rate_unsafe(handler, 4 * freq); + rf_uhd_set_master_clock_rate_nolock(handler, 4 * freq); } if (handler->nof_tx_channels > 1) { @@ -1267,7 +1267,7 @@ int rf_uhd_recv_with_time_multi(void* h, // Start stream if not started if (not handler->rx_stream_enabled) { - if (rf_uhd_start_rx_stream_unsafe(handler) != SRSRAN_SUCCESS) { + if (rf_uhd_start_rx_stream_nolock(handler) != SRSRAN_SUCCESS) { return SRSRAN_ERROR; } } @@ -1312,7 +1312,7 @@ int rf_uhd_recv_with_time_multi(void* h, if (RF_UHD_IMP_PROHIBITED_STOP_START.count(handler->devname) == 0) { // Stop Rx stream - rf_uhd_stop_rx_stream_unsafe(handler); + rf_uhd_stop_rx_stream_nolock(handler); } return -1; diff --git a/lib/src/phy/sync/test/CMakeLists.txt b/lib/src/phy/sync/test/CMakeLists.txt index 02c78ea83..8ad607146 100644 --- a/lib/src/phy/sync/test/CMakeLists.txt +++ b/lib/src/phy/sync/test/CMakeLists.txt @@ -141,11 +141,21 @@ add_test(cfo_test_2 cfo_test -f 0.99849 -n 1000) add_executable(ssb_measure_test ssb_measure_test.c) target_link_libraries(ssb_measure_test srsran_phy) -add_nr_test(ssb_measure_test ssb_measure_test) add_executable(ssb_decode_test ssb_decode_test.c) target_link_libraries(ssb_decode_test srsran_phy) -add_nr_test(ssb_decode_test ssb_decode_test) + +# For each supported SSB subcarrier spacing +foreach (SSB_SCS 15 30) + # For each supported Cell/Carrier subcarrier spacing + foreach (CELL_SCS 15 30) + # Test SSB measurements + add_nr_test(ssb_measure_test_${SSB_SCS}_${CELL_SCS} ssb_measure_test -s ${SSB_SCS} -S ${CELL_SCS}) + + # Test SSB PBCH decoding + add_nr_test(ssb_decode_test_${SSB_SCS}_${CELL_SCS} ssb_decode_test -s ${SSB_SCS} -S ${CELL_SCS}) + endforeach () +endforeach () add_executable(ssb_file_test ssb_file_test.c) target_link_libraries(ssb_file_test srsran_phy) diff --git a/lib/src/phy/sync/test/ssb_decode_test.c b/lib/src/phy/sync/test/ssb_decode_test.c index 7c5d5f652..c924253f0 100644 --- a/lib/src/phy/sync/test/ssb_decode_test.c +++ b/lib/src/phy/sync/test/ssb_decode_test.c @@ -50,14 +50,30 @@ static cf_t* buffer = NULL; // Base-band buffer static void usage(char* prog) { printf("Usage: %s [v]\n", prog); + printf("\t-s SSB subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(ssb_scs)); + printf("\t-S cell/carrier subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(carrier_scs)); printf("\t-v [set srsran_verbose to debug, default none]\n"); } static void parse_args(int argc, char** argv) { int opt; - while ((opt = getopt(argc, argv, "v")) != -1) { + while ((opt = getopt(argc, argv, "Ssv")) != -1) { switch (opt) { + case 's': + ssb_scs = srsran_subcarrier_spacing_from_str(argv[optind]); + if (ssb_scs == srsran_subcarrier_spacing_invalid) { + ERROR("Invalid SSB subcarrier spacing %s\n", argv[optind]); + exit(-1); + } + break; + case 'S': + carrier_scs = srsran_subcarrier_spacing_from_str(argv[optind]); + if (carrier_scs == srsran_subcarrier_spacing_invalid) { + ERROR("Invalid Cell/Carrier subcarrier spacing %s\n", argv[optind]); + exit(-1); + } + break; case 'v': srsran_verbose++; break; @@ -91,7 +107,7 @@ static void gen_pbch_msg(srsran_pbch_msg_nr_t* pbch_msg, uint32_t ssb_idx) SRSRAN_MEM_ZERO(pbch_msg, srsran_pbch_msg_nr_t, 1); // Generate payload - srsran_random_bit_vector(random_gen, pbch_msg->payload, SRSRAN_PBCH_NR_PAYLOAD_SZ); + srsran_random_bit_vector(random_gen, pbch_msg->payload, SRSRAN_PBCH_MSG_NR_SZ); pbch_msg->ssb_idx = ssb_idx; pbch_msg->crc = true; diff --git a/lib/src/phy/sync/test/ssb_measure_test.c b/lib/src/phy/sync/test/ssb_measure_test.c index 98343b6c9..7b91872ed 100644 --- a/lib/src/phy/sync/test/ssb_measure_test.c +++ b/lib/src/phy/sync/test/ssb_measure_test.c @@ -54,14 +54,30 @@ static cf_t* buffer = NULL; // Base-band buffer static void usage(char* prog) { printf("Usage: %s [v]\n", prog); + printf("\t-s SSB subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(ssb_scs)); + printf("\t-S cell/carrier subcarrier spacing [default, %s kHz]\n", srsran_subcarrier_spacing_to_str(carrier_scs)); printf("\t-v [set srsran_verbose to debug, default none]\n"); } static void parse_args(int argc, char** argv) { int opt; - while ((opt = getopt(argc, argv, "v")) != -1) { + while ((opt = getopt(argc, argv, "Ssv")) != -1) { switch (opt) { + case 's': + ssb_scs = srsran_subcarrier_spacing_from_str(argv[optind]); + if (ssb_scs == srsran_subcarrier_spacing_invalid) { + ERROR("Invalid SSB subcarrier spacing %s\n", argv[optind]); + exit(-1); + } + break; + case 'S': + carrier_scs = srsran_subcarrier_spacing_from_str(argv[optind]); + if (carrier_scs == srsran_subcarrier_spacing_invalid) { + ERROR("Invalid Cell/Carrier subcarrier spacing %s\n", argv[optind]); + exit(-1); + } + break; case 'v': srsran_verbose++; break; diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 965513f67..e18d14c41 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -23,6 +23,7 @@ #include "srsran/common/standard_streams.h" #include "srsran/common/string_helpers.h" #include "srsran/config.h" +#include "srsran/support/srsran_assert.h" #include #include #include @@ -711,6 +712,13 @@ void radio::set_rx_srate(const double& srate) } } + // Assert ratio is integer + srsran_assert(((uint32_t)cur_rx_srate % (uint32_t)srate) == 0, + "The sampling rate ratio is not integer (%.2f MHz / %.2 MHz = %.3f)", + cur_rx_srate / 1e6, + srate / 1e6, + cur_rx_srate / srate); + // Update decimators uint32_t ratio = (uint32_t)ceil(cur_rx_srate / srate); for (uint32_t ch = 0; ch < nof_channels; ch++) { @@ -957,6 +965,13 @@ void radio::set_tx_srate(const double& srate) } } + // Assert ratio is integer + srsran_assert(((uint32_t)cur_tx_srate % (uint32_t)srate) == 0, + "The sampling rate ratio is not integer (%.2f MHz / %.2 MHz = %.3f)", + cur_rx_srate / 1e6, + srate / 1e6, + cur_rx_srate / srate); + // Update interpolators uint32_t ratio = (uint32_t)ceil(cur_tx_srate / srate); for (uint32_t ch = 0; ch < nof_channels; ch++) { diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index 5354fba06..f7fa6b5ab 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -308,6 +308,7 @@ void rlc_am_lte::rlc_am_lte_tx::set_bsr_callback(bsr_callback_t callback) bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_) { + std::lock_guard lock(mutex); if (cfg_.tx_queue_length > MAX_SDUS_PER_RLC_PDU) { logger.error("Configuring Tx queue length of %d PDUs too big. Maximum value is %d.", cfg_.tx_queue_length, @@ -334,6 +335,8 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_) poll_retx_timer.set(static_cast(cfg.t_poll_retx), [this](uint32_t timerid) { timer_expired(timerid); }); } + // make sure Tx queue is empty before attempting to resize + empty_queue_nolock(); tx_sdu_queue.resize(cfg_.tx_queue_length); tx_enabled = true; @@ -343,10 +346,10 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_) void rlc_am_lte::rlc_am_lte_tx::stop() { - empty_queue(); - std::lock_guard lock(mutex); + empty_queue_nolock(); + tx_enabled = false; if (parent->timers != nullptr && poll_retx_timer.is_valid()) { @@ -378,7 +381,11 @@ void rlc_am_lte::rlc_am_lte_tx::stop() void rlc_am_lte::rlc_am_lte_tx::empty_queue() { std::lock_guard lock(mutex); + empty_queue_nolock(); +} +void rlc_am_lte::rlc_am_lte_tx::empty_queue_nolock() +{ // deallocate all SDUs in transmit queue while (tx_sdu_queue.size() > 0) { unique_byte_buffer_t buf = tx_sdu_queue.read(); diff --git a/lib/src/rlc/rlc_tm.cc b/lib/src/rlc/rlc_tm.cc index aa2a0eeb7..a55245b16 100644 --- a/lib/src/rlc/rlc_tm.cc +++ b/lib/src/rlc/rlc_tm.cc @@ -135,11 +135,13 @@ uint32_t rlc_tm::get_buffer_state() rlc_bearer_metrics_t rlc_tm::get_metrics() { + std::lock_guard lock(metrics_mutex); return metrics; } void rlc_tm::reset_metrics() { + std::lock_guard lock(metrics_mutex); metrics = {}; } @@ -165,6 +167,7 @@ uint32_t rlc_tm::read_pdu(uint8_t* payload, uint32_t nof_bytes) ul_queue.size(), ul_queue.size_bytes()); + std::lock_guard lock(metrics_mutex); metrics.num_tx_pdu_bytes += pdu_size; return pdu_size; } else { @@ -184,8 +187,11 @@ void rlc_tm::write_pdu(uint8_t* payload, uint32_t nof_bytes) memcpy(buf->msg, payload, nof_bytes); buf->N_bytes = nof_bytes; buf->set_timestamp(); - metrics.num_rx_pdu_bytes += nof_bytes; - metrics.num_rx_pdus++; + { + std::lock_guard lock(metrics_mutex); + metrics.num_rx_pdu_bytes += nof_bytes; + metrics.num_rx_pdus++; + } if (srsran::srb_to_lcid(srsran::lte_srb::srb0) == lcid) { rrc->write_pdu(lcid, std::move(buf)); } else { diff --git a/lib/src/rlc/rlc_um_base.cc b/lib/src/rlc/rlc_um_base.cc index 29fe89d65..fc5584a77 100644 --- a/lib/src/rlc/rlc_um_base.cc +++ b/lib/src/rlc/rlc_um_base.cc @@ -91,15 +91,18 @@ void rlc_um_base::write_sdu(unique_byte_buffer_t sdu) { if (not tx_enabled || not tx) { logger.debug("%s is currently deactivated. Dropping SDU (%d B)", rb_name.c_str(), sdu->N_bytes); + std::lock_guard lock(metrics_mutex); metrics.num_lost_sdus++; return; } int sdu_bytes = sdu->N_bytes; //< Store SDU length for book-keeping if (tx->try_write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) { + std::lock_guard lock(metrics_mutex); metrics.num_tx_sdus++; metrics.num_tx_sdu_bytes += sdu_bytes; } else { + std::lock_guard lock(metrics_mutex); metrics.num_lost_sdus++; } } @@ -111,6 +114,7 @@ void rlc_um_base::discard_sdu(uint32_t discard_sn) return; } tx->discard_sdu(discard_sn); + std::lock_guard lock(metrics_mutex); metrics.num_lost_sdus++; } @@ -144,6 +148,7 @@ uint32_t rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes) if (tx && tx_enabled) { uint32_t len = tx->build_data_pdu(payload, nof_bytes); if (len > 0) { + std::lock_guard lock(metrics_mutex); metrics.num_tx_pdu_bytes += len; metrics.num_tx_pdus++; } @@ -155,19 +160,24 @@ uint32_t rlc_um_base::read_pdu(uint8_t* payload, uint32_t nof_bytes) void rlc_um_base::write_pdu(uint8_t* payload, uint32_t nof_bytes) { if (rx && rx_enabled) { - metrics.num_rx_pdus++; - metrics.num_rx_pdu_bytes += nof_bytes; + { + std::lock_guard lock(metrics_mutex); + metrics.num_rx_pdus++; + metrics.num_rx_pdu_bytes += nof_bytes; + } rx->handle_data_pdu(payload, nof_bytes); } } rlc_bearer_metrics_t rlc_um_base::get_metrics() { + std::lock_guard lock(metrics_mutex); return metrics; } void rlc_um_base::reset_metrics() { + std::lock_guard lock(metrics_mutex); metrics = {}; } diff --git a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc index c1c59a8a8..012464f67 100644 --- a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc +++ b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc @@ -1230,43 +1230,142 @@ int test_cell_group_config_fdd() cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = true; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.set_setup(); - //TODO? // nzp-CSI-RS Resource cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list_present = true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(1); + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(5); auto& nzp_csi_res = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; - nzp_csi_res.nzp_csi_rs_res_id = 0; - nzp_csi_res.res_map.freq_domain_alloc.set_row2(); - nzp_csi_res.res_map.freq_domain_alloc.row2().from_number(0b100000000000); - nzp_csi_res.res_map.nrof_ports = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; - nzp_csi_res.res_map.first_ofdm_symbol_in_time_domain = 4; - nzp_csi_res.res_map.cdm_type = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; - nzp_csi_res.res_map.density.set_one(); - nzp_csi_res.res_map.freq_band.start_rb = 0; - nzp_csi_res.res_map.freq_band.nrof_rbs = 52; - nzp_csi_res.pwr_ctrl_offset = 0; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup(); + // item 0 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].nzp_csi_rs_res_id = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.set_row2(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.row2().from_number(0b100000000000); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.density.set_one(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].pwr_ctrl_offset = 0; // Skip pwr_ctrl_offset_ss_present - nzp_csi_res.scrambling_id = 500; - nzp_csi_res.periodicity_and_offset_present = true; - nzp_csi_res.periodicity_and_offset.set_slots80(); - nzp_csi_res.periodicity_and_offset.slots80() = 1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].scrambling_id = 500; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.slots80() = 1; // optional - nzp_csi_res.qcl_info_periodic_csi_rs_present = true; - nzp_csi_res.qcl_info_periodic_csi_rs = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].qcl_info_periodic_csi_rs = 0; + // item 1 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].nzp_csi_rs_res_id = 1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].scrambling_id = 500; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset.slots40() = 11; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].qcl_info_periodic_csi_rs = 0; + // item 2 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].nzp_csi_rs_res_id = 2; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.first_ofdm_symbol_in_time_domain = 8; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].scrambling_id = 500; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset.slots40() = 11; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].qcl_info_periodic_csi_rs = 0; + // item 3 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].nzp_csi_rs_res_id = 3; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].scrambling_id = 500; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset.slots40() = 12; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].qcl_info_periodic_csi_rs = 0; + // item 4 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].nzp_csi_rs_res_id = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.first_ofdm_symbol_in_time_domain = 8; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].scrambling_id = 500; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset.slots40() = 12; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].qcl_info_periodic_csi_rs = 0; - //TODO? // nzp-CSI-RS ResourceSet cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list_present = true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1); + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(2); auto& nzp_csi_res_set = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; - nzp_csi_res_set.nzp_csi_res_set_id = 1; - nzp_csi_res_set.nzp_csi_rs_res.resize(1); - nzp_csi_res_set.nzp_csi_rs_res[0] = 1; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup(); + // item 0 + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_res_set_id = 0; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_rs_res.resize(1); + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_rs_res[0] = 0; + // item 1 + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_res_set_id = 1; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res.resize(4); + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[0] = 1; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[1] = 2; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[2] = 3; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[3] = 4; // Skip TRS info + // CSI IM config + // TODO: add csi im config + + // CSI resource config + // TODO: add csi resource config + // CSI report config cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list_present = true; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list.resize(1); @@ -1396,6 +1495,10 @@ int test_cell_group_config_fdd() cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.dummy = time_align_timer_opts::ms500; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul.freq_band_list + .push_back(5); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul.absolute_freq_point_a = + 166364; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul .scs_specific_carrier_list.resize(1); auto& ul_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul diff --git a/lib/test/common/choice_type_test.cc b/lib/test/common/choice_type_test.cc index 582173eed..e9970f17c 100644 --- a/lib/test/common/choice_type_test.cc +++ b/lib/test/common/choice_type_test.cc @@ -89,15 +89,15 @@ int test_tagged_union() { using srsran::choice_details::tagged_union_t; tagged_union_t u; - u.construct_unsafe(5); + u.construct_unchecked(5); TESTASSERT(u.is()); TESTASSERT(u.get_unchecked() == 5); - u.destroy_unsafe(); + u.destroy_unchecked(); TESTASSERT(C::counter == 0); - u.construct_unsafe(C{}); + u.construct_unchecked(C{}); TESTASSERT(C::counter == 1); - u.destroy_unsafe(); + u.destroy_unchecked(); TESTASSERT(C::counter == 0); return SRSRAN_SUCCESS; diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index a76b90874..bbc402425 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -178,7 +178,8 @@ enable = false # target_bler: Target BLER (in decimal) to achieve via adaptive link # max_delta_dl_cqi: Maximum shift in CQI for adaptive DL link # max_delta_ul_snr: Maximum shift in UL SNR for adaptive UL link -# adaptive_link_step_size: Step size or learning rate used in adaptive link +# adaptive_dl_mcs_step_size: Step size or learning rate used in adaptive DL MCS link +# adaptive_ul_mcs_step_size: Step size or learning rate used in adaptive UL MCS link # min_tpc_tti_interval: Minimum TTI interval between TPCs different than 1 # ul_snr_avg_alpha: Exponential Average alpha coefficient used in estimation of UL SNR # init_ul_snr_value: Initial UL SNR value used for computing MCS in the first UL grant @@ -204,7 +205,8 @@ enable = false #target_bler = 0.05 #max_delta_dl_cqi = 5 #max_delta_ul_snr = 5 -#adaptive_link_step_size = 0.001 +#adaptive_dl_mcs_step_size = 0.001 +#adaptive_ul_mcs_step_size = 0.001 #min_tpc_tti_interval = 1 #ul_snr_avg_alpha=0.05 #init_ul_snr_value=5 diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index a2084eaba..e4fa13b06 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -157,13 +157,13 @@ public: private: const static int ENB_POOL_SIZE = 1024 * 10; - int parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg); + int parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg_, rrc_nr_cfg_t& rrc_cfg_nr_); srslog::sink& log_sink; srslog::basic_logger& enb_log; - all_args_t args = {}; - bool started = false; + all_args_t args = {}; + std::atomic started = {false}; phy_cfg_t phy_cfg = {}; rrc_cfg_t rrc_cfg = {}; @@ -173,8 +173,8 @@ private: x2_adapter x2; std::unique_ptr eutra_stack = nullptr; std::unique_ptr nr_stack = nullptr; - std::unique_ptr radio = nullptr; - std::unique_ptr phy = nullptr; + std::unique_ptr radio = nullptr; + std::unique_ptr phy = nullptr; // System metrics processor. srsran::sys_metrics_processor sys_proc; diff --git a/srsenb/hdr/metrics_json.h b/srsenb/hdr/metrics_json.h index 5fc2df2e5..a6401a8f8 100644 --- a/srsenb/hdr/metrics_json.h +++ b/srsenb/hdr/metrics_json.h @@ -35,10 +35,9 @@ namespace srsenb { class metrics_json : public srsran::metrics_listener { public: - metrics_json(srslog::log_channel& c) : log_c(c) {} + metrics_json(srslog::log_channel& c, enb_metrics_interface* enb_) : log_c(c), enb(enb_) {} void set_metrics(const enb_metrics_t& m, const uint32_t period_usec) override; - void set_handle(enb_metrics_interface* enb_); void stop() override {} private: diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 3b98d54db..bd55dc4f9 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -127,6 +127,10 @@ public: { rrc.sgnb_addition_complete(eutra_rnti, nr_rnti); } + void set_activity_user(uint16_t eutra_rnti) final { rrc.set_activity_user(eutra_rnti); } + + // gtpu_interface_pdcp + void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu); private: static const int STACK_MAIN_THREAD_PRIO = 4; diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 2195c7396..046769a6f 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -29,8 +29,6 @@ #include "srsenb/hdr/stack/mac/nr/mac_nr.h" #include "srsenb/hdr/stack/rrc/rrc_nr.h" -#include "srsenb/hdr/stack/upper/pdcp_nr.h" -#include "srsenb/hdr/stack/upper/rlc_nr.h" #include "upper/pdcp.h" #include "upper/rlc.h" #include "upper/sdap.h" @@ -38,10 +36,6 @@ #include "enb_stack_base.h" #include "srsran/interfaces/gnb_interfaces.h" -// This is needed for GW -#include "srsran/interfaces/ue_interfaces.h" -#include "srsue/hdr/stack/upper/gw.h" - namespace srsenb { class gnb_stack_nr final : public srsenb::enb_stack_base, diff --git a/srsenb/hdr/stack/mac/nr/mac_nr.h b/srsenb/hdr/stack/mac/nr/mac_nr.h index 113fd16d3..ac328e9ef 100644 --- a/srsenb/hdr/stack/mac/nr/mac_nr.h +++ b/srsenb/hdr/stack/mac/nr/mac_nr.h @@ -37,16 +37,17 @@ namespace srsenb { struct mac_nr_args_t { - srsran::phy_cfg_nr_t phy_base_cfg = {}; - int fixed_dl_mcs = -1; - int fixed_ul_mcs = -1; - srsenb::pcap_args_t pcap; + srsran::phy_cfg_nr_t phy_base_cfg = {}; + int fixed_dl_mcs = -1; + int fixed_ul_mcs = -1; + sched_nr_interface::sched_cfg_t sched_cfg = {}; + srsenb::pcap_args_t pcap; }; class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr, public mac_interface_rlc_nr { public: - mac_nr(srsran::task_sched_handle task_sched_, const srsenb::sched_nr_interface::sched_cfg_t& sched_cfg = {}); + explicit mac_nr(srsran::task_sched_handle task_sched_); ~mac_nr(); int init(const mac_nr_args_t& args_, @@ -63,13 +64,12 @@ public: uint16_t reserve_rnti(uint32_t enb_cc_idx) override; int read_pdu_bcch_bch(uint8_t* payload); int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override; + int remove_ue(uint16_t rnti) override; // MAC interface for RLC - // TODO: - int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) override { return 0; } + int rlc_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t tx_queue, uint32_t retx_queue) override; // Interface for PHY - void process_pdus(); int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override; @@ -80,11 +80,10 @@ public: private: uint16_t add_ue_(uint32_t enb_cc_idx); uint16_t alloc_ue(uint32_t enb_cc_idx); - int remove_ue(uint16_t rnti); // internal misc helpers - bool is_rnti_valid_unsafe(uint16_t rnti); - bool is_rnti_active_unsafe(uint16_t rnti); + bool is_rnti_valid_nolock(uint16_t rnti); + bool is_rnti_active_nolock(uint16_t rnti); // handle UCI data from either PUCCH or PUSCH bool handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value); @@ -93,7 +92,7 @@ private: int handle_pdu(srsran::unique_byte_buffer_t pdu); // Encoding - srsran::byte_buffer_t* assemble_rar(srsran::const_span grants); + srsran::byte_buffer_t* assemble_rar(srsran::const_span grants); srsran::unique_byte_buffer_t rar_pdu_buffer = nullptr; // Interaction with other components @@ -112,10 +111,10 @@ private: std::atomic started = {false}; - const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage - srsran::slot_point pdsch_slot, pusch_slot; - srsenb::sched_nr sched; - std::vector cell_config; + const static uint32_t NUMEROLOGY_IDX = 0; /// only 15kHz supported at this stage + srsran::slot_point pdsch_slot, pusch_slot; + srsenb::sched_nr sched; + std::vector cell_config; // Map of active UEs pthread_rwlock_t rwlock = {}; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsenb/hdr/stack/mac/nr/sched_nr.h index 274f1cc5c..f349e62cc 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr.h @@ -45,9 +45,9 @@ class ul_sched_result_buffer; class sched_nr final : public sched_nr_interface { public: - explicit sched_nr(const sched_cfg_t& sched_cfg); + explicit sched_nr(); ~sched_nr() override; - int cell_cfg(srsran::const_span cell_list) override; + int config(const sched_cfg_t& sched_cfg, srsran::const_span cell_list) override; void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override; void ue_rem(uint16_t rnti) override; bool ue_exists(uint16_t rnti) override; @@ -56,7 +56,7 @@ public: void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override; void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) override; - void ul_sr_info(slot_point slot_rx, uint16_t rnti) override; + void ul_sr_info(uint16_t rnti) override; void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) override; void dl_buffer_state(uint16_t rnti, uint32_t lcid, uint32_t newtx, uint32_t retx); @@ -68,7 +68,7 @@ private: // args sched_nr_impl::sched_params cfg; - srslog::basic_logger& logger; + srslog::basic_logger* logger = nullptr; using sched_worker_manager = sched_nr_impl::sched_worker_manager; std::unique_ptr sched_workers; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h index 0bf47ef14..08a8146df 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h @@ -39,12 +39,16 @@ const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS; using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t; using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t; +using pdsch_t = mac_interface_phy_nr::pdsch_t; +using pusch_t = mac_interface_phy_nr::pusch_t; +using pucch_t = mac_interface_phy_nr::pucch_t; using pdcch_dl_list_t = srsran::bounded_vector; using pdcch_ul_list_t = srsran::bounded_vector; -using pucch_t = mac_interface_phy_nr::pucch_t; using pucch_list_t = srsran::bounded_vector; -using pusch_t = mac_interface_phy_nr::pusch_t; using pusch_list_t = srsran::bounded_vector; +using nzp_csi_rs_list = srsran::bounded_vector; +using ssb_t = mac_interface_phy_nr::ssb_t; +using ssb_list = srsran::bounded_vector; using sched_cfg_t = sched_nr_interface::sched_cfg_t; using cell_cfg_t = sched_nr_interface::cell_cfg_t; @@ -102,9 +106,10 @@ struct sched_cell_params { }; struct sched_params { - const sched_cfg_t sched_cfg; + sched_cfg_t sched_cfg; std::vector cells; + sched_params() = default; explicit sched_params(const sched_cfg_t& sched_cfg_); }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h index 68a7e1199..7ed0de753 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h @@ -32,6 +32,7 @@ namespace srsenb { namespace sched_nr_impl { +// typedefs using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -39,9 +40,9 @@ using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t; const static size_t MAX_CORESET_PER_BWP = 3; using slot_coreset_list = std::array, MAX_CORESET_PER_BWP>; -using pdsch_t = mac_interface_phy_nr::pdsch_t; using pdsch_list_t = srsran::bounded_vector; using sched_rar_list_t = sched_nr_interface::sched_rar_list_t; +using pucch_list_t = srsran::bounded_vector; struct harq_ack_t { const srsran::phy_cfg_nr_t* phy_cfg; @@ -55,9 +56,12 @@ struct bwp_slot_grid { bwp_rb_bitmap dl_prbs; bwp_rb_bitmap ul_prbs; + ssb_list ssb; + nzp_csi_rs_list nzp_csi_rs; pdcch_dl_list_t dl_pdcchs; pdcch_ul_list_t ul_pdcchs; pdsch_list_t pdschs; + pucch_list_t pucch; sched_rar_list_t rar; slot_coreset_list coresets; pusch_list_t puschs; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h index 985304ca6..3ddcf9800 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h @@ -52,6 +52,12 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, srsran_dci_location_t dci_pos, srsran_dci_ul_nr_t& dci); +/// Log UE state for slot being scheduled +void log_sched_slot_ues(srslog::basic_logger& logger, + slot_point pdcch_slot, + uint32_t cc, + const slot_ue_map_t& slot_ues); + /// Log Scheduling Result for a given BWP and slot void log_sched_bwp_result(srslog::basic_logger& logger, slot_point pdcch_slot, diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 1d0ad0203..681f1f861 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -39,6 +39,7 @@ const static size_t SCHED_NR_MAX_NOF_RBGS = 18; const static size_t SCHED_NR_MAX_TB = 1; const static size_t SCHED_NR_MAX_HARQ = 16; const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2; +const static size_t SCHED_NR_MAX_LCID = 32; class sched_nr_interface { @@ -78,7 +79,7 @@ public: bool pdsch_enabled = true; bool pusch_enabled = true; bool auto_refill_buffer = false; - std::string logger_name = "MAC"; + std::string logger_name = "MAC-NR"; }; struct ue_cc_cfg_t { @@ -91,7 +92,8 @@ public: int fixed_dl_mcs = -1; int fixed_ul_mcs = -1; srsran::bounded_vector carriers; - srsran::phy_cfg_nr_t phy_cfg = {}; + std::array ue_bearers = {}; + srsran::phy_cfg_nr_t phy_cfg = {}; }; ////// RACH ////// @@ -124,17 +126,17 @@ public: dl_sched_t dl_sched; }; - virtual ~sched_nr_interface() = default; - virtual int cell_cfg(srsran::const_span ue_cfg) = 0; - virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; - virtual void ue_rem(uint16_t rnti) = 0; - virtual bool ue_exists(uint16_t rnti) = 0; - virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0; - virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0; + virtual ~sched_nr_interface() = default; + virtual int config(const sched_cfg_t& sched_cfg, srsran::const_span ue_cfg) = 0; + virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0; + virtual void ue_rem(uint16_t rnti) = 0; + virtual bool ue_exists(uint16_t rnti) = 0; + virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0; + virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0; virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0; virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0; - virtual void ul_sr_info(slot_point, uint16_t rnti) = 0; + virtual void ul_sr_info(uint16_t rnti) = 0; virtual void ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) = 0; }; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_signalling.h b/srsenb/hdr/stack/mac/nr/sched_nr_signalling.h new file mode 100644 index 000000000..e7bc59f96 --- /dev/null +++ b/srsenb/hdr/stack/mac/nr/sched_nr_signalling.h @@ -0,0 +1,36 @@ +/** + * + * \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 SRSRAN_SCHED_NR_SIGNALLING_H +#define SRSRAN_SCHED_NR_SIGNALLING_H + +#include "sched_nr_cfg.h" +#include "sched_nr_interface.h" + +namespace srsenb { +namespace sched_nr_impl { + +/// Schedule NZP-CSI-RS resources for given slot +void sched_nzp_csi_rs(srsran::const_span nzp_csi_rs_sets, + const srsran_slot_cfg_t& slot_cfg, + nzp_csi_rs_list& csi_rs_list); + +/// For a given BWP and slot, schedule SSB, NZP CSI RS and SIBs +void sched_dl_signalling(const bwp_params& bwp_params, + slot_point sl_pdcch, + ssb_list& ssb_list, + nzp_csi_rs_list& nzp_csi_rs); + +} // namespace sched_nr_impl +} // namespace srsenb + +#endif // SRSRAN_SCHED_NR_SIGNALLING_H diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index fe517a607..dc4e210d7 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -54,16 +54,17 @@ public: int dl_pending_bytes = 0, ul_pending_bytes = 0; // UE parameters that are sector specific - const bwp_ue_cfg* cfg = nullptr; - harq_entity* harq_ent = nullptr; - slot_point pdcch_slot; - slot_point pdsch_slot; - slot_point pusch_slot; - slot_point uci_slot; - uint32_t dl_cqi = 0; - uint32_t ul_cqi = 0; - dl_harq_proc* h_dl = nullptr; - ul_harq_proc* h_ul = nullptr; + const bwp_ue_cfg* cfg = nullptr; + harq_entity* harq_ent = nullptr; + slot_point pdcch_slot; + slot_point pdsch_slot; + slot_point pusch_slot; + slot_point uci_slot; + uint32_t dl_cqi = 0; + uint32_t ul_cqi = 0; + dl_harq_proc* h_dl = nullptr; + ul_harq_proc* h_ul = nullptr; + srsran_uci_cfg_nr_t uci_cfg = {}; }; class ue_carrier @@ -100,7 +101,7 @@ public: void rlc_buffer_state(uint32_t lcid, uint32_t newtx, uint32_t retx) { buffers.dl_buffer_state(lcid, newtx, retx); } void ul_bsr(uint32_t lcg, uint32_t bsr_val) { buffers.ul_bsr(lcg, bsr_val); } - void ul_sr_info(slot_point slot_rx) { last_sr_slot = slot_rx; } + void ul_sr_info() { last_sr_slot = last_pdcch_slot - TX_ENB_DELAY; } bool has_ca() const { @@ -117,6 +118,7 @@ private: const uint16_t rnti; const sched_params& sched_cfg; + slot_point last_pdcch_slot; slot_point last_sr_slot; int ul_pending_bytes = 0, dl_pending_bytes = 0; diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h index 50a2545ea..abf632693 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_worker.h @@ -61,6 +61,7 @@ private: void alloc_dl_ues(); void alloc_ul_ues(); + void postprocess_decisions(); const sched_cell_params& cfg; serv_cell_manager& cell; diff --git a/srsenb/hdr/stack/mac/sched_interface.h b/srsenb/hdr/stack/mac/sched_interface.h index 608f38e07..60d136f34 100644 --- a/srsenb/hdr/stack/mac/sched_interface.h +++ b/srsenb/hdr/stack/mac/sched_interface.h @@ -71,7 +71,8 @@ public: float target_bler = 0.05; float max_delta_dl_cqi = 5; float max_delta_ul_snr = 5; - float adaptive_link_step_size = 0.001; + float adaptive_dl_mcs_step_size = 0.001; + float adaptive_ul_mcs_step_size = 0.001; uint32_t min_tpc_tti_interval = 1; float ul_snr_avg_alpha = 0.05; int init_ul_snr_value = 5; diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h index b38e32576..839bf4880 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h @@ -103,7 +103,8 @@ private: cc_st cc_state_ = cc_st::idle; // CQI - float delta_inc = 0, delta_dec = 0; + float ul_delta_inc = 0, ul_delta_dec = 0; + float dl_delta_inc = 0, dl_delta_dec = 0; float dl_cqi_coeff = 0, ul_snr_coeff = 0; float max_cqi_coeff = -5, max_snr_coeff = 5; diff --git a/srsenb/hdr/stack/ngap/ngap.h b/srsenb/hdr/stack/ngap/ngap.h index 1f9ca697b..aeaf83e81 100644 --- a/srsenb/hdr/stack/ngap/ngap.h +++ b/srsenb/hdr/stack/ngap/ngap.h @@ -37,6 +37,7 @@ #include "srsran/common/threads.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" +#include "srsran/interfaces/enb_gtpu_interfaces.h" #include "srsran/srslog/srslog.h" #include #include @@ -51,7 +52,7 @@ public: srslog::basic_logger& logger, srsran::socket_manager_itf* rx_socket_handler); ~ngap(); - int init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_); + int init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_, gtpu_interface_rrc* gtpu_); void stop(); // RRC NR interface @@ -93,6 +94,7 @@ private: // args rrc_interface_ngap_nr* rrc = nullptr; + gtpu_interface_rrc* gtpu = nullptr; ngap_args_t args = {}; srslog::basic_logger& logger; srsran::task_sched_handle task_sched; @@ -134,7 +136,7 @@ private: // TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg); // TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request - bool handle_pdu_session_resource_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); + bool handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); class user_list { diff --git a/srsenb/hdr/stack/ngap/ngap_interfaces.h b/srsenb/hdr/stack/ngap/ngap_interfaces.h index c9fcaf916..90ffe1543 100644 --- a/srsenb/hdr/stack/ngap/ngap_interfaces.h +++ b/srsenb/hdr/stack/ngap/ngap_interfaces.h @@ -22,11 +22,17 @@ #ifndef SRSENB_NGAP_INTERFACES_H #define SRSENB_NGAP_INTERFACES_H +#include "srsran/asn1/ngap_utils.h" + namespace srsenb { class ngap_interface_ngap_proc { public: virtual bool send_initial_ctxt_setup_response() = 0; + virtual bool + send_pdu_session_resource_setup_response(uint16_t pdu_session_id, + uint32_t teid_out, + asn1::bounded_bitstring<1, 160, true, true> transport_layer_address) = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/ngap/ngap_ue.h b/srsenb/hdr/stack/ngap/ngap_ue.h index 59aef5242..9e695ee7e 100644 --- a/srsenb/hdr/stack/ngap/ngap_ue.h +++ b/srsenb/hdr/stack/ngap/ngap_ue.h @@ -22,16 +22,21 @@ #define SRSENB_NGAP_UE_H #include "ngap.h" +#include "ngap_ue_bearer_manager.h" #include "ngap_ue_proc.h" #include "ngap_ue_utils.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/ngap.h" +#include "srsran/interfaces/enb_gtpu_interfaces.h" namespace srsenb { class ngap::ue : public ngap_interface_ngap_proc { public: - explicit ue(ngap* ngap_ptr_, rrc_interface_ngap_nr* rrc_ptr_, srslog::basic_logger& logger_); + explicit ue(ngap* ngap_ptr_, + rrc_interface_ngap_nr* rrc_ptr_, + gtpu_interface_rrc* gtpu_ptr_, + srslog::basic_logger& logger_); virtual ~ue(); // TS 38.413 - Section 9.2.5.1 - Initial UE Message bool send_initial_ue_message(asn1::ngap_nr::rrcestablishment_cause_e cause, @@ -44,31 +49,39 @@ public: bool send_initial_ctxt_setup_response(); // TS 38.413 - Section 9.2.2.3 - Initial Context Setup Failure bool send_initial_ctxt_setup_failure(asn1::ngap_nr::cause_c cause); + // TS 38.413 - Section 9.2.1.2 - PDU Session Resource Setup Response + bool send_pdu_session_resource_setup_response(uint16_t pdu_session_id, + uint32_t teid_in, + asn1::bounded_bitstring<1, 160, true, true> addr_in); // TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg); // TS 38.413 - Section 9.2.2.5 - UE Context Release Command bool handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg); + // TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request + bool handle_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); bool was_uectxtrelease_requested() const { return release_requested; } void ue_ctxt_setup_complete(); void notify_rrc_reconf_complete(const bool reconf_complete_outcome); - srsran::proc_t initial_context_setup_proc; - srsran::proc_t ue_context_release_proc; - ngap_ue_ctxt_t ctxt = {}; uint16_t stream_id = 1; private: // args - ngap* ngap_ptr; - rrc_interface_ngap_nr* rrc_ptr; + ngap* ngap_ptr = nullptr; // state - bool release_requested = false; + bool release_requested = false; + ngap_ue_bearer_manager bearer_manager; // logger srslog::basic_logger& logger; + + // procedures + srsran::proc_t initial_context_setup_proc; + srsran::proc_t ue_context_release_proc; + srsran::proc_t ue_pdu_session_res_setup_proc; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h b/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h new file mode 100644 index 000000000..ed4c3bdeb --- /dev/null +++ b/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h @@ -0,0 +1,73 @@ +/** + * + * \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 SRSENB_NGAP_UE_BEARER_MANAGER_H +#define SRSENB_NGAP_UE_BEARER_MANAGER_H + +#include "srsran/asn1/asn1_utils.h" +#include "srsran/asn1/ngap.h" +#include "srsran/config.h" +#include "srsran/interfaces/enb_gtpu_interfaces.h" +#include "srsran/interfaces/gnb_rrc_nr_interfaces.h" + +namespace srsenb { + +/** + * @brief Manages the GTPU bearers as part of the NGAP session procedures + * */ + +class ngap_ue_bearer_manager +{ +public: + struct pdu_session_t { + struct gtpu_tunnel { + uint32_t teid_out = 0; + uint32_t teid_in = 0; + asn1::bounded_bitstring<1, 160, true, true> address_out; + asn1::bounded_bitstring<1, 160, true, true> address_in; + }; + uint8_t id = 0; + uint8_t lcid = 0; + asn1::ngap_nr::qos_flow_level_qos_params_s qos_params; + std::vector tunnels; + }; + + ngap_ue_bearer_manager(rrc_interface_ngap_nr* rrc_, gtpu_interface_rrc* gtpu_, srslog::basic_logger& logger_); + ~ngap_ue_bearer_manager(); + + int add_pdu_session(uint16_t rnti, + uint8_t pdu_session_id, + const asn1::ngap_nr::qos_flow_level_qos_params_s& qos, + const asn1::bounded_bitstring<1, 160, true, true>& addr, + uint32_t teid_out, + uint16_t& lcid, + asn1::bounded_bitstring<1, 160, true, true>& addr_in, + uint32_t& teid_in, + asn1::ngap_nr::cause_c& cause); + +private: + gtpu_interface_rrc* gtpu = nullptr; + rrc_interface_ngap_nr* rrc = nullptr; + std::map pdu_session_list; + srslog::basic_logger& logger; + + int add_gtpu_bearer(uint16_t rnti, + uint32_t lcid, + uint32_t pdu_session_id, + uint32_t teid_out, + asn1::bounded_bitstring<1, 160, true, true> address, + pdu_session_t::gtpu_tunnel& tunnel, // out parameter + const gtpu_interface_rrc::bearer_props* props = nullptr); + void rem_gtpu_bearer(uint16_t rnti, uint32_t pdu_session_id); +}; +} // namespace srsenb +#endif // SRSENB_NGAP_UE_BEARER_MANAGER_H \ No newline at end of file diff --git a/srsenb/hdr/stack/ngap/ngap_ue_proc.h b/srsenb/hdr/stack/ngap/ngap_ue_proc.h index 47f6a5fb7..179e8079f 100644 --- a/srsenb/hdr/stack/ngap/ngap_ue_proc.h +++ b/srsenb/hdr/stack/ngap/ngap_ue_proc.h @@ -30,6 +30,7 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/stack_procedure.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" +#include "srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h" #include #include @@ -44,9 +45,10 @@ class ngap_ue_initial_context_setup_proc public: explicit ngap_ue_initial_context_setup_proc(ngap_interface_ngap_proc* parent_, rrc_interface_ngap_nr* rrc_, - ngap_ue_ctxt_t* ue_ctxt); + ngap_ue_ctxt_t* ue_ctxt, + srslog::basic_logger& logger_); srsran::proc_outcome_t init(const asn1::ngap_nr::init_context_setup_request_s& msg); - srsran::proc_outcome_t react(const bool security_mode_command_outcome); + srsran::proc_outcome_t react(const bool rrc_reconf_outcome); srsran::proc_outcome_t step(); static const char* name() { return "Initial Context Setup"; } @@ -63,7 +65,8 @@ class ngap_ue_ue_context_release_proc public: explicit ngap_ue_ue_context_release_proc(ngap_interface_ngap_proc* parent_, rrc_interface_ngap_nr* rrc_, - ngap_ue_ctxt_t* ue_ctxt); + ngap_ue_ctxt_t* ue_ctxt, + srslog::basic_logger& logger_); srsran::proc_outcome_t init(const asn1::ngap_nr::ue_context_release_cmd_s& msg); srsran::proc_outcome_t step(); static const char* name() { return "UE Context Release"; } @@ -79,7 +82,7 @@ private: class ngap_ue_ue_context_modification_proc { public: - explicit ngap_ue_ue_context_modification_proc(ngap_interface_ngap_proc* parent_); + explicit ngap_ue_ue_context_modification_proc(ngap_interface_ngap_proc* parent_, srslog::basic_logger& logger_); srsran::proc_outcome_t init(); srsran::proc_outcome_t step(); static const char* name() { return "UE Context Modification"; } @@ -88,6 +91,26 @@ private: ngap_interface_ngap_proc* parent; }; +class ngap_ue_pdu_session_res_setup_proc +{ +public: + explicit ngap_ue_pdu_session_res_setup_proc(ngap_interface_ngap_proc* parent_, + rrc_interface_ngap_nr* rrc_, + ngap_ue_ctxt_t* ue_ctxt, + ngap_ue_bearer_manager* bearer_manager, + srslog::basic_logger& logger_); + srsran::proc_outcome_t init(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); + srsran::proc_outcome_t step(); + static const char* name() { return "UE PDU Session Resource Setup"; } + +private: + ngap_ue_ctxt_t* ue_ctxt; + ngap_interface_ngap_proc* parent; + ngap_ue_bearer_manager* bearer_manager; + rrc_interface_ngap_nr* rrc = nullptr; + srslog::basic_logger& logger; +}; + } // namespace srsenb #endif \ No newline at end of file diff --git a/srsenb/hdr/stack/rrc/rrc_cell_cfg.h b/srsenb/hdr/stack/rrc/rrc_cell_cfg.h index 22e7193b6..c1ce44a5d 100644 --- a/srsenb/hdr/stack/rrc/rrc_cell_cfg.h +++ b/srsenb/hdr/stack/rrc/rrc_cell_cfg.h @@ -136,8 +136,9 @@ public: const enb_cell_common_list& enb_common_list); ~ue_cell_ded_list(); - ue_cell_ded* add_cell(uint32_t enb_cc_idx); + ue_cell_ded* add_cell(uint32_t enb_cc_idx, bool init_pucch = true); bool rem_last_cell(); + bool init_pucch_pcell(); bool set_cells(const std::vector& enb_cc_idxs); ue_cell_ded* get_ue_cc_idx(uint32_t ue_cc_idx) { return (ue_cc_idx < nof_cells()) ? &cell_list[ue_cc_idx] : nullptr; } diff --git a/srsenb/hdr/stack/rrc/rrc_config.h b/srsenb/hdr/stack/rrc/rrc_config.h index 050f73606..1b6fd9fdb 100644 --- a/srsenb/hdr/stack/rrc/rrc_config.h +++ b/srsenb/hdr/stack/rrc/rrc_config.h @@ -73,12 +73,12 @@ struct rrc_cfg_t { bool meas_cfg_present = false; srsran_cell_t cell; cell_list_t cell_list; - cell_list_t cell_list_nr; - uint32_t max_mac_dl_kos; - uint32_t max_mac_ul_kos; - uint32_t rlf_release_timer_ms; - srb_cfg_t srb1_cfg; - srb_cfg_t srb2_cfg; + uint32_t num_nr_cells = 0; /// number of configured NR cells (used to configure RF) + uint32_t max_mac_dl_kos; + uint32_t max_mac_ul_kos; + uint32_t rlf_release_timer_ms; + srb_cfg_t srb1_cfg; + srb_cfg_t srb2_cfg; }; constexpr uint32_t UE_PCELL_CC_IDX = 0; diff --git a/srsenb/hdr/stack/rrc/rrc_config_nr.h b/srsenb/hdr/stack/rrc/rrc_config_nr.h index 3f344e220..152b25851 100644 --- a/srsenb/hdr/stack/rrc/rrc_config_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_config_nr.h @@ -23,6 +23,7 @@ #define SRSRAN_RRC_CONFIG_NR_H #include "srsran/asn1/rrc_nr.h" +#include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include "srsue/hdr/phy/phy_common.h" namespace srsenb { @@ -43,7 +44,7 @@ struct rrc_nr_cfg_t { uint32_t nof_sibs; rrc_nr_cfg_sr_t sr_cfg; rrc_cfg_cqi_t cqi_cfg; - srsran_cell_t cell; + rrc_cell_list_nr_t cell_list; std::string log_level; uint32_t log_hex_limit; diff --git a/srsenb/hdr/stack/rrc/rrc_endc.h b/srsenb/hdr/stack/rrc/rrc_endc.h index 57d169531..6ceadb069 100644 --- a/srsenb/hdr/stack/rrc/rrc_endc.h +++ b/srsenb/hdr/stack/rrc/rrc_endc.h @@ -57,7 +57,16 @@ public: uint16_t nr_rnti; /// RNTI assigned to UE on NR carrier }; - rrc_endc(srsenb::rrc::ue* outer_ue); + // Parameter of the (NR)-carrier required for NR cell measurement handling + struct rrc_endc_cfg_t { + bool act_from_b1_event = true; // ENDC will only be activated from B1 measurment + uint32_t nr_dl_arfcn = 634176; + uint32_t nr_band = 78; + asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_e_ ssb_ssc = + asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz15; + }; + + rrc_endc(srsenb::rrc::ue* outer_ue, const rrc_endc_cfg_t& endc_cfg_); bool fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg); void handle_eutra_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps); @@ -66,8 +75,8 @@ public: bool is_endc_supported(); private: - // Send SgNB addition request to gNB - bool start_sgnb_addition(); + // Send SgNB addition request to gNB (either triggered through MeasReport or upon start) + void start_sgnb_addition(); bool is_endc_activation_running() const { return not is_in_state(); } @@ -77,6 +86,7 @@ private: // vars bool endc_supported = false; + rrc_endc_cfg_t endc_cfg = {}; asn1::rrc::rrc_conn_recfg_complete_s pending_recfg_complete; // fixed ENDC variables diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 011746433..214491a60 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -71,14 +71,18 @@ public: void get_metrics(srsenb::rrc_metrics_t& m); rrc_nr_cfg_t update_default_cfg(const rrc_nr_cfg_t& rrc_cfg); - int add_user(uint16_t rnti); - int update_user(uint16_t new_rnti, uint16_t old_rnti); void config_phy(); void config_mac(); int32_t generate_sibs(); int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) final; int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) final; + /// User manegement + int add_user(uint16_t rnti); + void rem_user(uint16_t rnti); + int update_user(uint16_t new_rnti, uint16_t old_rnti); + void set_activity_user(uint16_t rnti); + // RLC interface // TODO void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) {} @@ -99,7 +103,10 @@ public: int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates); int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps); int start_security_mode_procedure(uint16_t rnti); + int establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid); void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu); + int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates); + int allocate_lcid(uint16_t rnti); class ue { @@ -117,6 +124,7 @@ public: bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; } bool is_inactive() { return state == rrc_nr_state_t::RRC_INACTIVE; } bool is_endc() { return endc; } + uint16_t get_eutra_rnti() { return eutra_rnti; } // setters @@ -142,6 +150,9 @@ public: asn1::rrc_nr::cell_group_cfg_s cell_group_cfg; asn1::rrc_nr::radio_bearer_cfg_s radio_bearer_cfg; + // MAC controller + sched_nr_interface::ue_cfg_t uecfg{}; + const uint32_t drb1_lcid = 4; // NSA specific variables @@ -150,7 +161,8 @@ public: }; private: - rrc_nr_cfg_t cfg = {}; + static constexpr uint32_t UE_PSCELL_CC_IDX = 0; // first NR cell is always Primary Secondary Cell for UE + rrc_nr_cfg_t cfg = {}; // interfaces phy_interface_stack_nr* phy = nullptr; diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index 293dc9b3d..0d4002053 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -60,6 +60,9 @@ public: void protocol_failure(); void deactivate_bearers() { mac_ctrl.set_radio_bearer_state(mac_lc_ch_cfg_t::IDLE); } + // Init PUCCH resources for PCell + bool init_pucch(); + rrc_state_t get_state(); void get_metrics(rrc_ue_metrics_t& ue_metrics) const; diff --git a/srsenb/hdr/stack/rrc/ue_rr_cfg.h b/srsenb/hdr/stack/rrc/ue_rr_cfg.h index 2a0553936..07ab44477 100644 --- a/srsenb/hdr/stack/rrc/ue_rr_cfg.h +++ b/srsenb/hdr/stack/rrc/ue_rr_cfg.h @@ -54,18 +54,18 @@ class bearer_cfg_handler; struct ue_var_cfg_t; /// Fill RadioResourceConfigDedicated with data known at the RRCSetup/Reestablishment stage -void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, - const rrc_cfg_t& enb_cfg, - const ue_cell_ded_list& ue_cell_list); +int fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, + const rrc_cfg_t& enb_cfg, + const ue_cell_ded_list& ue_cell_list); /// Apply Reconf updates and update current state -void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, - ue_var_cfg_t& current_ue_cfg, - const rrc_cfg_t& enb_cfg, - const ue_cell_ded_list& ue_cell_list, - bearer_cfg_handler& bearers, - const srsran::rrc_ue_capabilities_t& ue_caps, - bool phy_cfg_updated); +int apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, + ue_var_cfg_t& current_ue_cfg, + const rrc_cfg_t& enb_cfg, + const ue_cell_ded_list& ue_cell_list, + bearer_cfg_handler& bearers, + const srsran::rrc_ue_capabilities_t& ue_caps, + bool phy_cfg_updated); /// Apply radioResourceConfigDedicated updates to the current UE RRC configuration void apply_rr_cfg_ded_diff(asn1::rrc::rr_cfg_ded_s& current_rr_cfg_ded, diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index 65dcaed2d..8b885007b 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -154,6 +154,7 @@ public: uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, + uint32_t& addr_in, const bearer_props* props = nullptr) override; void set_tunnel_status(uint32_t teidin, bool dl_active) override; void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) override; diff --git a/srsenb/hdr/stack/upper/pdcp.h b/srsenb/hdr/stack/upper/pdcp.h index 58fb1b239..7c193ba9f 100644 --- a/srsenb/hdr/stack/upper/pdcp.h +++ b/srsenb/hdr/stack/upper/pdcp.h @@ -53,6 +53,7 @@ public: void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} // pdcp_interface_rrc + void set_enabled(uint16_t rnti, uint32_t lcid, bool enabled) override; void reset(uint16_t rnti) override; void add_user(uint16_t rnti) override; void rem_user(uint16_t rnti) override; diff --git a/srsenb/hdr/stack/upper/pdcp_nr.h b/srsenb/hdr/stack/upper/pdcp_nr.h deleted file mode 100644 index 160081eb1..000000000 --- a/srsenb/hdr/stack/upper/pdcp_nr.h +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Copyright 2013-2021 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include "srsran/interfaces/gnb_interfaces.h" -#include "srsran/interfaces/ue_gw_interfaces.h" -#include "srsran/interfaces/ue_rlc_interfaces.h" -#include "srsran/upper/pdcp.h" -#include - -#ifndef SRSENB_PDCP_NR_H -#define SRSENB_PDCP_NR_H - -namespace srsenb { - -struct pdcp_nr_args_t { - std::string log_level; - uint32_t log_hex_limit; -}; - -class pdcp_nr : public pdcp_interface_rlc_nr, public pdcp_interface_sdap_nr, public pdcp_interface_rrc_nr -{ -public: - explicit pdcp_nr(srsran::task_sched_handle task_sched_, const char* logname); - virtual ~pdcp_nr() = default; - void init(const pdcp_nr_args_t& args_, - rlc_interface_pdcp_nr* rlc_, - rrc_interface_pdcp_nr* rrc_, - sdap_interface_pdcp_nr* gtpu_); - void stop(); - - // pdcp_interface_rlc_nr - void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu); - void notify_delivery(uint16_t rnti, uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn); - void notify_failure(uint16_t rnti, uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn); - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} - - // pdcp_interface_rrc_nr - void reset(uint16_t rnti) final; - void add_user(uint16_t rnti) final; - void rem_user(uint16_t rnti) final; - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) final; - void add_bearer(uint16_t rnti, uint32_t lcid, srsran::pdcp_config_t cnfg) final; - void config_security(uint16_t rnti, uint32_t lcid, srsran::as_security_config_t sec_cfg) final; - void enable_integrity(uint16_t rnti, uint32_t lcid) final; - void enable_encryption(uint16_t rnti, uint32_t lcid) final; - -private: - class user_interface_rlc final : public srsue::rlc_interface_pdcp - { - public: - uint16_t rnti; - srsenb::rlc_interface_pdcp_nr* rlc; - // rlc_interface_pdcp_nr - void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) final; - void discard_sdu(uint32_t lcid, uint32_t discard_sn) final; - bool rb_is_um(uint32_t lcid) final; - bool sdu_queue_is_full(uint32_t lcid) final; - }; - - class user_interface_sdap : public srsue::gw_interface_pdcp - { - public: - uint16_t rnti; - srsenb::sdap_interface_pdcp_nr* sdap; - // gw_interface_pdcp - void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final; - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) final {} - }; - - class user_interface_rrc : public srsue::rrc_interface_pdcp - { - public: - uint16_t rnti; - srsenb::rrc_interface_pdcp_nr* rrc; - // rrc_interface_pdcp_nr - void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final; - void write_pdu_bcch_bch(srsran::unique_byte_buffer_t pdu) final; - void write_pdu_bcch_dlsch(srsran::unique_byte_buffer_t pdu) final; - void write_pdu_pcch(srsran::unique_byte_buffer_t pdu) final; - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final {} - void notify_pdcp_integrity_error(uint32_t lcid) final {} - const char* get_rb_name(uint32_t lcid) final; - }; - - class user_interface - { - public: - user_interface_rlc rlc_itf; - user_interface_sdap sdap_itf; - user_interface_rrc rrc_itf; - std::unique_ptr pdcp; - }; - - // args - pdcp_nr_args_t m_args = {}; - rlc_interface_pdcp_nr* m_rlc = nullptr; - rrc_interface_pdcp_nr* m_rrc = nullptr; - sdap_interface_pdcp_nr* m_sdap = nullptr; - - std::map users; - - srsran::task_sched_handle task_sched; - srslog::basic_logger& logger; -}; - -} // namespace srsenb - -#endif // SRSENB_PDCP_NR_H diff --git a/srsenb/hdr/stack/upper/rlc_nr.h b/srsenb/hdr/stack/upper/rlc_nr.h deleted file mode 100644 index c64057d3c..000000000 --- a/srsenb/hdr/stack/upper/rlc_nr.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright 2013-2021 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#ifndef SRSENB_RLC_NR_H -#define SRSENB_RLC_NR_H - -#include "srsran/interfaces/gnb_interfaces.h" -#include "srsran/interfaces/gnb_mac_interfaces.h" -#include "srsran/rlc/rlc.h" -#include - -namespace srsenb { - -typedef struct { - uint32_t lcid; - uint32_t plmn; - uint16_t mtch_stop; - uint8_t* payload; -} mch_service_t; - -class rlc_nr final : public rlc_interface_mac_nr, public rlc_interface_rrc_nr, public rlc_interface_pdcp_nr -{ -public: - explicit rlc_nr(const char* logname); - void init(pdcp_interface_rlc_nr* pdcp_, - rrc_interface_rlc_nr* rrc_, - mac_interface_rlc_nr* mac_, - srsran::timer_handler* timers_); - void stop(); - - // rlc_interface_rrc_nr - void clear_buffer(uint16_t rnti); - void add_user(uint16_t rnti); - void rem_user(uint16_t rnti); - void add_bearer(uint16_t rnti, uint32_t lcid, srsran::rlc_config_t cnfg); - void add_bearer_mrb(uint16_t rnti, uint32_t lcid); - - // rlc_interface_pdcp_nr - void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu); - bool rb_is_um(uint16_t rnti, uint32_t lcid); - bool sdu_queue_is_full(uint16_t rnti, uint32_t lcid); - const char* get_rb_name(uint32_t lcid); - - // rlc_interface_mac_nr - int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes); - // void read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload); - void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes); - void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size); - -private: - class user_interface : public srsue::pdcp_interface_rlc, public srsue::rrc_interface_rlc - { - public: - void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu); - void notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns); - void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns); - void write_pdu_bcch_bch(srsran::unique_byte_buffer_t sdu); - void write_pdu_bcch_dlsch(srsran::unique_byte_buffer_t sdu); - void write_pdu_pcch(srsran::unique_byte_buffer_t sdu); - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) {} - void max_retx_attempted() final; - void protocol_failure() final; - const char* get_rb_name(uint32_t lcid) final; - uint16_t rnti; - - srsenb::pdcp_interface_rlc_nr* m_pdcp = nullptr; - srsenb::rrc_interface_rlc_nr* m_rrc = nullptr; - std::unique_ptr m_rlc; - rlc_nr* parent = nullptr; - }; - - // args - srsran::timer_handler* timers = nullptr; - mac_interface_rlc_nr* m_mac = nullptr; - pdcp_interface_rlc_nr* m_pdcp = nullptr; - rrc_interface_rlc_nr* m_rrc = nullptr; - srslog::basic_logger& logger; - - // state - std::map users; - std::vector mch_services; -}; - -} // namespace srsenb - -#endif // SRSENB_RLC_NR_H diff --git a/srsenb/hdr/x2_adapter.h b/srsenb/hdr/x2_adapter.h index 0d6639743..8f31eb826 100644 --- a/srsenb/hdr/x2_adapter.h +++ b/srsenb/hdr/x2_adapter.h @@ -94,6 +94,14 @@ public: eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti); } + void set_activity_user(uint16_t eutra_rnti) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->set_activity_user(eutra_rnti); + } + // stack_nr_interface_stack_eutra void tti_clock() { @@ -119,6 +127,15 @@ public: return nr_stack->get_buffered_pdus(rnti, lcid); } + // gtpu_interface_pdcp + void write_pdu(uint16_t rnti, uint32_t bearer_id, srsran::unique_byte_buffer_t pdu) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->write_pdu(rnti, bearer_id, std::move(pdu)); + } + private: enb_stack_lte* eutra_stack = nullptr; gnb_stack_nr* nr_stack = nullptr; diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index cfb984a7f..e5d6fd02c 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -87,14 +87,25 @@ cell_list = } ); - // ReportCfg (only A3 supported) - meas_report_desc = { - a3_report_type = "RSRP"; - a3_offset = 6; - a3_hysteresis = 0; - a3_time_to_trigger = 480; - rsrq_config = 4; - }; + // Select measurement report configuration (all reports are combined with all measurement objects) + meas_report_desc = + ( + { + eventA = 3 + a3_offset = 6; + hysteresis = 0; + time_to_trigger = 480; + trigger_quant = "RSRP"; + max_report_cells = 1; + report_interv = 120; + report_amount = 1; + } + ); + meas_quant_desc = { + // averaging filter coefficient + rsrq_config = 4; + rsrp_config = 4; + }; } // Add here more cells ); diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index cbab78e61..9a854bffb 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -52,7 +52,7 @@ int enb::init(const all_args_t& args_) enb_log.info("%s", get_build_string().c_str()); // Validate arguments - if (parse_args(args_, rrc_cfg)) { + if (parse_args(args_, rrc_cfg, rrc_nr_cfg)) { srsran::console("Error processing arguments.\n"); return SRSRAN_ERROR; } @@ -72,7 +72,7 @@ int enb::init(const all_args_t& args_) } std::unique_ptr tmp_nr_stack; - if (not rrc_cfg.cell_list_nr.empty()) { + if (not rrc_nr_cfg.cell_list.empty()) { // add NR stack tmp_nr_stack.reset(new gnb_stack_nr(log_sink)); if (tmp_nr_stack == nullptr) { @@ -157,6 +157,10 @@ void enb::stop() { if (started) { // tear down in reverse order + if (radio) { + radio->stop(); + } + if (phy) { phy->stop(); } @@ -169,10 +173,6 @@ void enb::stop() nr_stack->stop(); } - if (radio) { - radio->stop(); - } - // Now that everything is teared down, log sector stop events. const std::string& sib9_hnb_name = rrc_cfg.sibs[8].sib9().hnb_name_present ? rrc_cfg.sibs[8].sib9().hnb_name.to_string() : ""; @@ -184,11 +184,11 @@ void enb::stop() } } -int enb::parse_args(const all_args_t& args_, rrc_cfg_t& _rrc_cfg) +int enb::parse_args(const all_args_t& args_, rrc_cfg_t& rrc_cfg_, rrc_nr_cfg_t& rrc_cfg_nr_) { // set member variable args = args_; - return enb_conf_sections::parse_cfg_files(&args, &_rrc_cfg, &phy_cfg); + return enb_conf_sections::parse_cfg_files(&args, &rrc_cfg_, &rrc_cfg_nr_, &phy_cfg); } void enb::start_plot() @@ -203,12 +203,15 @@ void enb::print_pool() bool enb::get_metrics(enb_metrics_t* m) { + if (!started) { + return false; + } radio->get_metrics(&m->rf); phy->get_metrics(m->phy); if (eutra_stack) { eutra_stack->get_metrics(&m->stack); } - m->running = started; + m->running = true; m->sys = sys_proc.get_metrics(); return true; } @@ -240,6 +243,9 @@ std::string enb::get_build_string() void enb::toggle_padding() { + if (!started) { + return; + } if (eutra_stack) { eutra_stack->toggle_padding(); } @@ -247,6 +253,9 @@ void enb::toggle_padding() void enb::tti_clock() { + if (!started) { + return; + } if (eutra_stack) { eutra_stack->tti_clock(); } diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index e174b58de..4b7b6c472 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -25,6 +25,7 @@ #include "srsran/common/band_helper.h" #include "srsran/common/multiqueue.h" #include "srsran/phy/common/phy_common.h" +#include "srsran/rrc/rrc_common.h" #include #define HANDLEPARSERCODE(cond) \ @@ -644,7 +645,7 @@ int field_qci::parse(libconfig::Setting& root) namespace rr_sections { -int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_) +int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr_cfg_) { /* Transmission mode config section */ if (args_->enb.transmission_mode < 1 || args_->enb.transmission_mode > 4) { @@ -759,7 +760,7 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_) bool nr_cell_cnfg_present = false; parser::section nr_cell_cnfg("nr_cell_list"); nr_cell_cnfg.set_optional(&nr_cell_cnfg_present); - nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_cfg_)); + nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_nr_cfg_, rrc_cfg_)); // Run parser with two sections parser p(args_->enb_files.rr_config); @@ -787,30 +788,92 @@ static int parse_meas_cell_list(rrc_meas_cfg_t* meas_cfg, Setting& root) return 0; } -static int parse_meas_report_desc(rrc_meas_cfg_t* meas_cfg, Setting& root) +static int parse_meas_report_desc(rrc_meas_cfg_t* meas_cfg, Setting& cellroot) { - // NOTE: For now, only support one meas_report for all cells. - // TODO: for a1 - // TODO: for a2 - // meas report parsing - meas_cfg->meas_reports.resize(1); - asn1::rrc::report_cfg_eutra_s& meas_item = meas_cfg->meas_reports[0]; - HANDLEPARSERCODE(asn1_parsers::str_to_enum(meas_item.trigger_quant, root["a3_report_type"])); - auto& event = meas_item.trigger_type.set_event(); - event.event_id.set_event_a3().report_on_leave = false; - event.event_id.event_a3().a3_offset = (int)root["a3_offset"]; - event.hysteresis = (int)root["a3_hysteresis"]; - meas_item.max_report_cells = 1; // TODO: parse - meas_item.report_amount.value = report_cfg_eutra_s::report_amount_e_::r1; // TODO: parse - meas_item.report_interv.value = report_interv_e::ms120; // TODO: parse - meas_item.report_quant.value = report_cfg_eutra_s::report_quant_opts::both; // TODO: parse + // NOTE: Events A1, A2, A3 and A4 are supported. A3 and A4 will be configured for all neighbour cells + + Setting& root = cellroot["meas_report_desc"]; + + meas_cfg->meas_reports.resize(root.getLength()); + for (int i = 0; i < root.getLength(); i++) { + asn1::rrc::report_cfg_eutra_s& meas_item = meas_cfg->meas_reports[i]; + + // Parse trigger quantity before event + HANDLEPARSERCODE(asn1_parsers::str_to_enum(meas_item.trigger_quant, root[i]["trigger_quant"])); + + auto& event = meas_item.trigger_type.set_event(); + + // Configure event + switch ((int)root[i]["eventA"]) { + case 1: + if (!root[i].exists("a1_thresh")) { + ERROR("Missing a1_thresh field for A1 event\n"); + return SRSRAN_ERROR; + } + if (meas_item.trigger_quant == report_cfg_eutra_s::trigger_quant_opts::rsrp) { + event.event_id.set_event_a1().a1_thres.set_thres_rsrp() = + rrc_value_to_range(srsran::quant_rsrp, (int)root[i]["a1_thresh"]); + } else { + event.event_id.set_event_a1().a1_thres.set_thres_rsrq() = + rrc_value_to_range(srsran::quant_rsrq, (int)root[i]["a1_thresh"]); + } + break; + case 2: + if (!root[i].exists("a2_thresh")) { + ERROR("Missing a2_thresh field for A2 event\n"); + return SRSRAN_ERROR; + } + if (meas_item.trigger_quant == report_cfg_eutra_s::trigger_quant_opts::rsrp) { + event.event_id.set_event_a2().a2_thres.set_thres_rsrp() = + rrc_value_to_range(srsran::quant_rsrp, (int)root[i]["a2_thresh"]); + } else { + event.event_id.set_event_a2().a2_thres.set_thres_rsrq() = + rrc_value_to_range(srsran::quant_rsrq, (int)root[i]["a2_thresh"]); + } + break; + case 3: + if (!root[i].exists("a3_offset")) { + ERROR("Missing a3_offset field for A3 event\n"); + return SRSRAN_ERROR; + } + event.event_id.set_event_a3().report_on_leave = false; + event.event_id.event_a3().a3_offset = (int)root[i]["a3_offset"]; + break; + case 4: + if (!root[i].exists("a4_thresh")) { + ERROR("Missing a4_thresh field for A4 event\n"); + return SRSRAN_ERROR; + } + if (meas_item.trigger_quant == report_cfg_eutra_s::trigger_quant_opts::rsrp) { + event.event_id.set_event_a4().a4_thres.set_thres_rsrp() = + rrc_value_to_range(srsran::quant_rsrp, (int)root[i]["a4_thresh"]); + } else { + event.event_id.set_event_a4().a4_thres.set_thres_rsrq() = + rrc_value_to_range(srsran::quant_rsrq, (int)root[i]["a4_thresh"]); + } + break; + default: + ERROR("Invalid or unsupported event A%d in meas_report_desc (only A1-A4 are supported)\n", + (int)root[i]["eventA"]); + return SRSRAN_ERROR; + } + + // Configure common variables + event.hysteresis = (int)root[i]["hysteresis"]; + HANDLEPARSERCODE(asn1_parsers::number_to_enum(event.time_to_trigger, root[i]["time_to_trigger"])); + meas_item.report_quant.value = report_cfg_eutra_s::report_quant_opts::both; // TODO: parse + meas_item.max_report_cells = (int)root[i]["max_report_cells"]; + HANDLEPARSERCODE(asn1_parsers::number_to_enum(meas_item.report_interv, root[i]["report_interv"])); + HANDLEPARSERCODE(asn1_parsers::number_to_enum(meas_item.report_amount, root[i]["report_amount"])); + } + // quant coeff parsing auto& quant = meas_cfg->quant_cfg; - HANDLEPARSERCODE(asn1_parsers::number_to_enum(event.time_to_trigger, root["a3_time_to_trigger"])); - HANDLEPARSERCODE( - asn1_parsers::opt_number_to_enum(quant.filt_coef_rsrp, quant.filt_coef_rsrp_present, root, "rsrp_config")); - HANDLEPARSERCODE( - asn1_parsers::opt_number_to_enum(quant.filt_coef_rsrq, quant.filt_coef_rsrq_present, root, "rsrq_config")); + + HANDLEPARSERCODE(asn1_parsers::opt_number_to_enum( + quant.filt_coef_rsrp, quant.filt_coef_rsrp_present, cellroot["meas_quant_desc"], "rsrp_config")); + HANDLEPARSERCODE(asn1_parsers::opt_number_to_enum( + quant.filt_coef_rsrq, quant.filt_coef_rsrq_present, cellroot["meas_quant_desc"], "rsrq_config")); return SRSRAN_SUCCESS; } @@ -873,7 +936,7 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) ERROR("PARSER ERROR: \"ho_active\" is set to true, but field \"meas_report_desc\" doesn't exist.\n"); return SRSRAN_ERROR; } - HANDLEPARSERCODE(parse_meas_report_desc(&cell_cfg.meas_cfg, cellroot["meas_report_desc"])); + HANDLEPARSERCODE(parse_meas_report_desc(&cell_cfg.meas_cfg, cellroot)); } if (cellroot.exists("scell_list")) { @@ -903,46 +966,55 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) return SRSRAN_SUCCESS; } -static int parse_nr_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) +static int parse_nr_cell_list(all_args_t* args, rrc_nr_cfg_t* rrc_cfg_nr, rrc_cfg_t* rrc_cfg_eutra, Setting& root) { for (uint32_t n = 0; n < (uint32_t)root.getLength(); ++n) { - cell_cfg_t cell_cfg = {}; - auto& cellroot = root[n]; + rrc_cell_cfg_nr_t cell_cfg = {}; + auto& cellroot = root[n]; - parse_opt_field(cell_cfg.rf_port, cellroot, "rf_port"); - HANDLEPARSERCODE(parse_required_field(cell_cfg.cell_id, cellroot, "cell_id")); + parse_opt_field(cell_cfg.phy_cell.rf_port, cellroot, "rf_port"); + HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.carrier.pci, cellroot, "pci")); + HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.cell_id, cellroot, "cell_id")); + HANDLEPARSERCODE(parse_required_field(cell_cfg.phy_cell.root_seq_idx, cellroot, "root_seq_idx")); HANDLEPARSERCODE(parse_required_field(cell_cfg.tac, cellroot, "tac")); - HANDLEPARSERCODE(parse_required_field(cell_cfg.pci, cellroot, "pci")); - cell_cfg.pci = cell_cfg.pci % SRSRAN_NOF_NID_NR; - HANDLEPARSERCODE(parse_required_field(cell_cfg.dl_earfcn, cellroot, "dl_arfcn")); + + cell_cfg.phy_cell.carrier.pci = cell_cfg.phy_cell.carrier.pci % SRSRAN_NOF_NID_NR; + HANDLEPARSERCODE(parse_required_field(cell_cfg.dl_arfcn, cellroot, "dl_arfcn")); + parse_opt_field(cell_cfg.ul_arfcn, cellroot, "ul_arfcn"); // frequencies get derived from ARFCN - // Add further cell-specific parameters + // TODO: Add further cell-specific parameters - rrc_cfg->cell_list_nr.push_back(cell_cfg); + rrc_cfg_nr->cell_list.push_back(cell_cfg); } // Configuration check - for (auto it = rrc_cfg->cell_list_nr.begin(); it != rrc_cfg->cell_list_nr.end(); ++it) { + for (auto it = rrc_cfg_nr->cell_list.begin(); it != rrc_cfg_nr->cell_list.end(); ++it) { // check against NR cells - for (auto it2 = it + 1; it2 != rrc_cfg->cell_list_nr.end(); it2++) { + for (auto it2 = it + 1; it2 != rrc_cfg_nr->cell_list.end(); it2++) { // Check RF port is not repeated - if (it->rf_port == it2->rf_port) { + if (it->phy_cell.rf_port == it2->phy_cell.rf_port) { ERROR("Repeated RF port for multiple cells"); return SRSRAN_ERROR; } - // Check cell ID is not repeated - if (it->cell_id == it2->cell_id) { + // Check cell PCI not repeated + if (it->phy_cell.carrier.pci == it2->phy_cell.carrier.pci) { + ERROR("Repeated cell PCI"); + return SRSRAN_ERROR; + } + + // Check cell PCI and cell ID is not repeated + if (it->phy_cell.cell_id == it2->phy_cell.cell_id) { ERROR("Repeated Cell identifier"); return SRSRAN_ERROR; } } // also check RF port against EUTRA cells - for (auto it_eutra = rrc_cfg->cell_list.begin(); it_eutra != rrc_cfg->cell_list.end(); ++it_eutra) { + for (auto it_eutra = rrc_cfg_eutra->cell_list.begin(); it_eutra != rrc_cfg_eutra->cell_list.end(); ++it_eutra) { // Check RF port is not repeated - if (it->rf_port == it_eutra->rf_port) { + if (it->phy_cell.rf_port == it_eutra->rf_port) { ERROR("Repeated RF port for multiple cells"); return SRSRAN_ERROR; } @@ -960,7 +1032,7 @@ int cell_list_section::parse(libconfig::Setting& root) int nr_cell_list_section::parse(libconfig::Setting& root) { - HANDLEPARSERCODE(parse_nr_cell_list(args, rrc_cfg, root)); + HANDLEPARSERCODE(parse_nr_cell_list(args, nr_rrc_cfg, eutra_rrc_cfg, root)); return 0; } @@ -999,7 +1071,7 @@ int parse_cell_cfg(all_args_t* args_, srsran_cell_t* cell) return SRSRAN_SUCCESS; } -int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_) +int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr_cfg_, phy_cfg_t* phy_cfg_) { // Parse config files srsran_cell_t cell_common_cfg = {}; @@ -1031,7 +1103,7 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_) } try { - if (rr_sections::parse_rr(args_, rrc_cfg_) != SRSRAN_SUCCESS) { + if (rr_sections::parse_rr(args_, rrc_cfg_, rrc_nr_cfg_) != SRSRAN_SUCCESS) { fprintf(stderr, "Error parsing Radio Resources configuration\n"); return SRSRAN_ERROR; } @@ -1057,7 +1129,22 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_) } // Set fields derived from others, and check for correctness of the parsed configuration - return enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, cell_common_cfg); + if (enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, cell_common_cfg) != SRSRAN_SUCCESS) { + fprintf(stderr, "Error deriving EUTRA cell parameters\n"); + return SRSRAN_ERROR; + } + + // do the same for NR + if (enb_conf_sections::set_derived_args_nr(args_, rrc_nr_cfg_, phy_cfg_) != SRSRAN_SUCCESS) { + fprintf(stderr, "Error deriving NR cell parameters\n"); + return SRSRAN_ERROR; + } + + // update number of NR cells + rrc_cfg_->num_nr_cells = rrc_nr_cfg_->cell_list.size(); + args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_nr_cfg_->cell_list.size(); + + return SRSRAN_SUCCESS; } int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, const srsran_cell_t& cell_cfg_) @@ -1164,59 +1251,6 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ phy_cfg_->phy_cell_cfg.push_back(phy_cell_cfg); } - // Use helper class to derive NR carrier parameters - srsran::srsran_band_helper band_helper; - - // Create NR dedicated cell configuration from RRC configuration - for (auto it = rrc_cfg_->cell_list_nr.begin(); it != rrc_cfg_->cell_list_nr.end(); ++it) { - auto& cfg = *it; - phy_cell_cfg_nr_t phy_cell_cfg = {}; - phy_cell_cfg.carrier.max_mimo_layers = cell_cfg_.nof_ports; - switch (cell_cfg_.nof_prb) { - case 25: - phy_cell_cfg.carrier.nof_prb = 25; - break; - case 50: - phy_cell_cfg.carrier.nof_prb = 52; - break; - case 100: - phy_cell_cfg.carrier.nof_prb = 106; - break; - default: - ERROR("The only accepted number of PRB is: 25, 50, 100"); - return SRSRAN_ERROR; - } - phy_cell_cfg.carrier.pci = cfg.pci; - phy_cell_cfg.cell_id = cfg.cell_id; - phy_cell_cfg.root_seq_idx = cfg.root_seq_idx; - phy_cell_cfg.rf_port = cfg.rf_port; - phy_cell_cfg.num_ra_preambles = - rrc_cfg_->sibs[1].sib2().rr_cfg_common.rach_cfg_common.preamb_info.nof_ra_preambs.to_number(); - - if (cfg.dl_freq_hz > 0) { - phy_cell_cfg.dl_freq_hz = cfg.dl_freq_hz; - } else { - phy_cell_cfg.dl_freq_hz = band_helper.nr_arfcn_to_freq(cfg.dl_earfcn); - } - - if (cfg.ul_freq_hz > 0) { - phy_cell_cfg.ul_freq_hz = cfg.ul_freq_hz; - } else { - // auto-detect UL frequency - if (cfg.ul_earfcn == 0) { - // derive UL ARFCN from given DL ARFCN - cfg.ul_earfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_earfcn); - if (cfg.ul_earfcn == 0) { - ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_earfcn); - return SRSRAN_ERROR; - } - } - phy_cell_cfg.ul_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ul_earfcn); - } - - phy_cfg_->phy_cell_cfg_nr.push_back(phy_cell_cfg); - } - if (args_->enb.transmission_mode == 1) { phy_cfg_->pdsch_cnfg.p_b = 0; // Default TM1 rrc_cfg_->sibs[1].sib2().rr_cfg_common.pdsch_cfg_common.p_b = 0; @@ -1327,7 +1361,6 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ } // Patch certain args that are not exposed yet - args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_cfg_->cell_list_nr.size(); args_->rf.nof_antennas = args_->enb.nof_ports; // MAC needs to know the cell bandwidth to dimension softbuffers @@ -1353,6 +1386,75 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ return SRSRAN_SUCCESS; } +/** + * @brief Set the derived args for the NR RRC and PHY config + * + * Mainly configures the RRC parameter based on the arguments and config files + * read. Since for NSA we are still using a commong PHY between EUTRA and NR + * the PHY configuration is also updated accordingly. + * + * @param args_ + * @param nr_rrc_cfg + * @param phy_cfg_ + * @return int + */ +int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_) +{ + // Use helper class to derive NR carrier parameters + srsran::srsran_band_helper band_helper; + + // Create NR dedicated cell configuration from RRC configuration + for (auto it = rrc_cfg_->cell_list.begin(); it != rrc_cfg_->cell_list.end(); ++it) { + auto& cfg = *it; + cfg.phy_cell.carrier.max_mimo_layers = args_->enb.nof_ports; + + // NR cells have the same bandwidth as EUTRA cells, adjust PRB sizes + switch (args_->enb.n_prb) { + case 25: + cfg.phy_cell.carrier.nof_prb = 25; + break; + case 50: + cfg.phy_cell.carrier.nof_prb = 52; + break; + case 100: + cfg.phy_cell.carrier.nof_prb = 106; + break; + default: + ERROR("The only accepted number of PRB is: 25, 50, 100"); + return SRSRAN_ERROR; + } + // phy_cell_cfg.root_seq_idx = cfg.root_seq_idx; + cfg.phy_cell.num_ra_preambles = 52; // FIXME: read from config + + if (cfg.phy_cell.dl_freq_hz == 0) { + cfg.phy_cell.dl_freq_hz = band_helper.nr_arfcn_to_freq(cfg.dl_arfcn); + } + + if (cfg.phy_cell.ul_freq_hz == 0) { + // auto-detect UL frequency + if (cfg.ul_arfcn == 0) { + // derive UL ARFCN from given DL ARFCN + cfg.ul_arfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_arfcn); + if (cfg.ul_arfcn == 0) { + ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_arfcn); + return SRSRAN_ERROR; + } + } + cfg.phy_cell.ul_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ul_arfcn); + } + + // band + cfg.band = band_helper.get_band_from_dl_arfcn(cfg.dl_arfcn); + + // duplex mode + cfg.duplex_mode = band_helper.get_duplex_mode(cfg.band); + + phy_cfg_->phy_cell_cfg_nr.push_back(cfg.phy_cell); + } + + return SRSRAN_SUCCESS; +} + } // namespace enb_conf_sections namespace sib_sections { diff --git a/srsenb/src/enb_cfg_parser.h b/srsenb/src/enb_cfg_parser.h index 7a059299c..ef7f52078 100644 --- a/srsenb/src/enb_cfg_parser.h +++ b/srsenb/src/enb_cfg_parser.h @@ -19,8 +19,8 @@ * */ -#ifndef ENB_CFG_PARSER_SIB1_H -#define ENB_CFG_PARSER_SIB1_H +#ifndef ENB_CFG_PARSER_H +#define ENB_CFG_PARSER_H #include "srsenb/hdr/parser.h" #include @@ -31,6 +31,7 @@ #include #include "srsenb/hdr/stack/rrc/rrc.h" +#include "srsenb/hdr/stack/rrc/rrc_config_nr.h" #include "srsran/asn1/asn1_utils.h" namespace srsenb { @@ -46,8 +47,9 @@ bool sib_is_present(const asn1::rrc::sched_info_list_l& l, asn1::rrc::sib_type_e namespace enb_conf_sections { int parse_cell_cfg(all_args_t* args_, srsran_cell_t* cell); -int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_); +int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_cfg_nr_, phy_cfg_t* phy_cfg_); int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, const srsran_cell_t& cell_cfg_); +int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_); } // namespace enb_conf_sections @@ -94,15 +96,18 @@ private: class nr_cell_list_section final : public parser::field_itf { public: - explicit nr_cell_list_section(all_args_t* all_args_, rrc_cfg_t* rrc_cfg_) : args(all_args_), rrc_cfg(rrc_cfg_) {} + explicit nr_cell_list_section(all_args_t* all_args_, rrc_nr_cfg_t* nr_rrc_cfg_, rrc_cfg_t* eutra_rrc_cfg_) : + args(all_args_), nr_rrc_cfg(nr_rrc_cfg_), eutra_rrc_cfg(eutra_rrc_cfg_) + {} int parse(Setting& root) override; const char* get_name() override { return "nr_cell_list"; } private: - rrc_cfg_t* rrc_cfg; - all_args_t* args; + rrc_nr_cfg_t* nr_rrc_cfg; + rrc_cfg_t* eutra_rrc_cfg; + all_args_t* args; }; } // namespace rr_sections @@ -582,4 +587,4 @@ private: }; } // namespace srsenb -#endif +#endif // ENB_CFG_PARSER_H diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index d06e32144..be16a38a6 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -165,7 +165,8 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("scheduler.target_bler", bpo::value(&args->stack.mac.sched.target_bler)->default_value(0.05), "Target BLER (in decimal) to achieve via adaptive link") ("scheduler.max_delta_dl_cqi", bpo::value(&args->stack.mac.sched.max_delta_dl_cqi)->default_value(5.0), "Maximum shift in CQI for adaptive DL link") ("scheduler.max_delta_ul_snr", bpo::value(&args->stack.mac.sched.max_delta_ul_snr)->default_value(5.0), "Maximum shift in UL SNR for adaptive UL link") - ("scheduler.adaptive_link_step_size", bpo::value(&args->stack.mac.sched.adaptive_link_step_size)->default_value(0.001), "Step size or learning rate used in adaptive link") + ("scheduler.adaptive_dl_mcs_step_size", bpo::value(&args->stack.mac.sched.adaptive_dl_mcs_step_size)->default_value(0.001), "Step size or learning rate used in adaptive DL MCS link") + ("scheduler.adaptive_ul_mcs_step_size", bpo::value(&args->stack.mac.sched.adaptive_ul_mcs_step_size)->default_value(0.001), "Step size or learning rate used in adaptive UL MCS link") ("scheduler.min_tpc_tti_interval", bpo::value(&args->stack.mac.sched.min_tpc_tti_interval)->default_value(1), "Minimum TTI interval between positive or negative TPCs") ("scheduler.ul_snr_avg_alpha", bpo::value(&args->stack.mac.sched.ul_snr_avg_alpha)->default_value(0.05), "Exponential Average alpha coefficient used in estimation of UL SNR") ("scheduler.init_ul_snr_value", bpo::value(&args->stack.mac.sched.init_ul_snr_value)->default_value(5), "Initial UL SNR value used for computing MCS in the first UL grant") @@ -615,10 +616,9 @@ int main(int argc, char* argv[]) metrics_file.set_handle(enb.get()); } - srsenb::metrics_json json_metrics(json_channel); + srsenb::metrics_json json_metrics(json_channel, enb.get()); if (args.general.report_json_enable) { metricshub.add_listener(&json_metrics); - json_metrics.set_handle(enb.get()); } // create input thread diff --git a/srsenb/src/metrics_json.cc b/srsenb/src/metrics_json.cc index 79b1acba9..3a05505fe 100644 --- a/srsenb/src/metrics_json.cc +++ b/srsenb/src/metrics_json.cc @@ -24,11 +24,6 @@ using namespace srsenb; -void metrics_json::set_handle(enb_metrics_interface* enb_) -{ - enb = enb_; -} - namespace { /// Bearer container metrics. diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 3a285490d..e043740c3 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -339,8 +339,11 @@ bool slot_worker::work_dl() } // Put NZP-CSI-RS - for (srsran_csi_rs_nzp_resource_t& pdsch : dl_sched.nzp_csi_rs) { - // ... + for (srsran_csi_rs_nzp_resource_t& nzp_csi_rs : dl_sched.nzp_csi_rs) { + if (srsran_gnb_dl_nzp_csi_rs_put(&gnb_dl, &dl_slot_cfg, &nzp_csi_rs) < SRSRAN_SUCCESS) { + logger.error("NZP-CSI-RS: Error putting signal"); + return false; + } } // Generate baseband signal diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index 4ed65dee4..ae26849e8 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -140,7 +140,8 @@ int worker_pool::set_common_cfg(const phy_interface_rrc_nr::common_cfg_t& common return SRSRAN_ERROR; } prach_cfg.freq_offset -= lte_nr_prach_offset; - prach_cfg.is_nr = true; + prach_cfg.is_nr = true; + prach_cfg.tdd_config.configured = (common_cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD); // Set the PRACH configuration prach.init(0, cell, prach_cfg, &prach_stack_adaptor, logger, 0, nof_prach_workers); diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 1fa414831..30f3e48bc 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -19,6 +19,10 @@ * */ +#include "srsenb/hdr/phy/phy.h" +#include "srsran/common/band_helper.h" +#include "srsran/common/phy_cfg_nr_default.h" +#include "srsran/common/threads.h" #include #include #include @@ -26,10 +30,6 @@ #include #include -#include "srsenb/hdr/phy/phy.h" -#include "srsran/common/phy_cfg_nr_default.h" -#include "srsran/common/threads.h" - #define Error(fmt, ...) \ if (SRSRAN_DEBUG_ENABLED) \ phy_log.error(fmt, ##__VA_ARGS__) @@ -348,6 +348,8 @@ int phy::init_nr(const phy_args_t& args, const phy_cfg_t& cfg, stack_interface_p tx_rx.set_nr_workers(nr_workers.get()); + srsran::srsran_band_helper band_helper; + // perform initial config of PHY (during RRC init PHY isn't running yet) static const srsran::phy_cfg_nr_t default_phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}}; @@ -355,6 +357,7 @@ int phy::init_nr(const phy_args_t& args, const phy_cfg_t& cfg, stack_interface_p common_cfg.carrier = default_phy_cfg.carrier; common_cfg.pdcch = default_phy_cfg.pdcch; common_cfg.prach = default_phy_cfg.prach; + common_cfg.duplex_mode = SRSRAN_DUPLEX_MODE_TDD; // TODO: make dynamic if (set_common_cfg(common_cfg) < SRSRAN_SUCCESS) { phy_log.error("Couldn't set common PHY config"); return SRSRAN_ERROR; diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index ed0d04b29..2edcaafae 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -212,7 +212,9 @@ int enb_stack_lte::init(const stack_args_t& args_, void enb_stack_lte::tti_clock() { - sync_task_queue.push([this]() { tti_clock_impl(); }); + if (started.load(std::memory_order_relaxed)) { + sync_task_queue.push([this]() { tti_clock_impl(); }); + } } void enb_stack_lte::tti_clock_impl() @@ -290,4 +292,10 @@ void enb_stack_lte::run_thread() } } +void enb_stack_lte::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) +{ + // call GTPU adapter to map to EPS bearer + gtpu_adapter->write_pdu(rnti, lcid, std::move(pdu)); +} + } // namespace srsenb diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index b9c35d903..e2e9b6138 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -79,8 +79,6 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, // Init all layers mac_nr_args_t mac_args = {}; - mac_args.fixed_dl_mcs = 28; - mac_args.fixed_ul_mcs = 10; mac_args.pcap = args.mac_pcap; mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap"; if (mac.init(mac_args, phy, nullptr, &rlc, &rrc) != SRSRAN_SUCCESS) { @@ -89,7 +87,7 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, } rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); - pdcp.init(&rlc, &rrc, nullptr); + pdcp.init(&rlc, &rrc, x2_); if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, nullptr, nullptr, x2_) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsenb/src/stack/mac/nr/CMakeLists.txt index 3d5b229fd..b25a9e192 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsenb/src/stack/mac/nr/CMakeLists.txt @@ -31,7 +31,8 @@ set(SOURCES mac_nr.cc sched_nr_cell.cc sched_nr_rb.cc sched_nr_time_rr.cc - harq_softbuffer.cc) + harq_softbuffer.cc + sched_nr_signalling.cc) add_library(srsgnb_mac STATIC ${SOURCES}) target_link_libraries(srsgnb_mac srsenb_mac_common) diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index e48239baa..f241b6ff3 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -35,10 +35,9 @@ namespace srsenb { -mac_nr::mac_nr(srsran::task_sched_handle task_sched_, const sched_nr_interface::sched_cfg_t& sched_cfg) : +mac_nr::mac_nr(srsran::task_sched_handle task_sched_) : logger(srslog::fetch_basic_logger("MAC-NR")), task_sched(task_sched_), - sched(sched_cfg), bcch_bch_payload(srsran::make_byte_buffer()), rar_pdu_buffer(srsran::make_byte_buffer()) { @@ -107,7 +106,7 @@ void mac_nr::get_metrics(srsenb::mac_metrics_t& metrics) int mac_nr::cell_cfg(const std::vector& nr_cells) { cell_config = nr_cells; - sched.cell_cfg(nr_cells); + sched.config(args.sched_cfg, nr_cells); detected_rachs.resize(nr_cells.size()); // read SIBs from RRC (SIB1 for now only) @@ -149,8 +148,6 @@ uint16_t mac_nr::reserve_rnti(uint32_t enb_cc_idx) // Add new user to the scheduler so that it can RX/TX SRB0 srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1); - ue_cfg.fixed_dl_mcs = args.fixed_dl_mcs; - ue_cfg.fixed_ul_mcs = args.fixed_ul_mcs; sched.ue_cfg(rnti, ue_cfg); return rnti; @@ -178,6 +175,7 @@ void mac_nr::rach_detected(const rach_info_t& rach_info) rar_info.prach_slot = slot_point{NUMEROLOGY_IDX, rach_info.slot_index}; // TODO: fill remaining fields as required sched.dl_rach_info(enb_cc_idx, rar_info); + rrc->add_user(rnti); logger.info("RACH: slot=%d, cc=%d, preamble=%d, offset=%d, temp_crnti=0x%x", rach_info.slot_index, @@ -206,7 +204,7 @@ uint16_t mac_nr::alloc_ue(uint32_t enb_cc_idx) // Pre-check if rnti is valid { srsran::rwlock_read_guard read_lock(rwlock); - if (not is_rnti_valid_unsafe(rnti)) { + if (not is_rnti_valid_nolock(rnti)) { continue; } } @@ -216,7 +214,7 @@ uint16_t mac_nr::alloc_ue(uint32_t enb_cc_idx) // Add UE to rnti map srsran::rwlock_write_guard rw_lock(rwlock); - if (not is_rnti_valid_unsafe(rnti)) { + if (not is_rnti_valid_nolock(rnti)) { continue; } auto ret = ue_db.insert(rnti, std::move(ue_ptr)); @@ -234,7 +232,8 @@ uint16_t mac_nr::alloc_ue(uint32_t enb_cc_idx) int mac_nr::remove_ue(uint16_t rnti) { srsran::rwlock_write_guard lock(rwlock); - if (is_rnti_active_unsafe(rnti)) { + if (is_rnti_active_nolock(rnti)) { + sched.ue_rem(rnti); ue_db.erase(rnti); } else { logger.error("User rnti=0x%x not found", rnti); @@ -244,7 +243,7 @@ int mac_nr::remove_ue(uint16_t rnti) return SRSRAN_SUCCESS; } -bool mac_nr::is_rnti_valid_unsafe(uint16_t rnti) +bool mac_nr::is_rnti_valid_nolock(uint16_t rnti) { if (not started) { logger.info("RACH ignored as eNB is being shutdown"); @@ -261,7 +260,7 @@ bool mac_nr::is_rnti_valid_unsafe(uint16_t rnti) return true; } -bool mac_nr::is_rnti_active_unsafe(uint16_t rnti) +bool mac_nr::is_rnti_active_nolock(uint16_t rnti) { if (not ue_db.contains(rnti)) { logger.error("User rnti=0x%x not found", rnti); @@ -270,6 +269,12 @@ bool mac_nr::is_rnti_active_unsafe(uint16_t rnti) return ue_db[rnti]->is_active(); } +int mac_nr::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue) +{ + sched.dl_buffer_state(rnti, lc_id, tx_queue, retx_queue); + return SRSRAN_SUCCESS; +} + int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { return 0; @@ -297,7 +302,7 @@ int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched for (pdsch_t& pdsch : dl_sched.pdsch) { if (pdsch.sch.grant.rnti_type == srsran_rnti_type_c) { uint16_t rnti = pdsch.sch.grant.rnti; - if (not is_rnti_active_unsafe(rnti)) { + if (not is_rnti_active_nolock(rnti)) { continue; } for (auto& tb_data : pdsch.data) { @@ -314,7 +319,7 @@ int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched } else if (pdsch.sch.grant.rnti_type == srsran_rnti_type_ra) { sched_nr_interface::sched_rar_t& rar = dl_res.rar[rar_count++]; // for RARs we could actually move the byte_buffer to the PHY, as there are no retx - pdsch.data[0] = assemble_rar(rar.grants); + pdsch.data[0] = assemble_rar(rar.grants); } } return SRSRAN_SUCCESS; @@ -348,6 +353,11 @@ bool mac_nr::handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg bool is_ok = (value.ack[i] == 1) and value.valid; sched.dl_ack_info(rnti, 0, ack_bit->pid, 0, is_ok); } + + // Process SR + if (value.valid and value.sr > 0) { + sched.ul_sr_info(cfg_.pucch.rnti); + } return true; } @@ -372,7 +382,7 @@ int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr:: auto process_pdu_task = [this, rnti](srsran::unique_byte_buffer_t& pdu) { srsran::rwlock_read_guard lock(rwlock); - if (is_rnti_active_unsafe(rnti)) { + if (is_rnti_active_nolock(rnti)) { ue_db[rnti]->process_pdu(std::move(pdu)); } else { logger.debug("Discarding PDU rnti=0x%x", rnti); @@ -415,7 +425,8 @@ srsran::byte_buffer_t* mac_nr::assemble_rar(srsran::const_span packed_ul_grant = {}; - std::copy(std::begin(dci_msg.payload), std::begin(dci_msg.payload)+SRSRAN_RAR_UL_GRANT_NBITS, packed_ul_grant.begin()); + std::copy( + std::begin(dci_msg.payload), std::begin(dci_msg.payload) + SRSRAN_RAR_UL_GRANT_NBITS, packed_ul_grant.begin()); rar_subpdu.set_ul_grant(packed_ul_grant); } diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsenb/src/stack/mac/nr/sched_nr.cc index ac2420b96..945dcd784 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsenb/src/stack/mac/nr/sched_nr.cc @@ -74,12 +74,15 @@ private: /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : cfg(sched_cfg), logger(srslog::fetch_basic_logger("MAC-NR")) {} +sched_nr::sched_nr() : logger(&srslog::fetch_basic_logger("MAC-NR")) {} sched_nr::~sched_nr() {} -int sched_nr::cell_cfg(srsran::const_span cell_list) +int sched_nr::config(const sched_cfg_t& sched_cfg, srsran::const_span cell_list) { + cfg = sched_params{sched_cfg}; + logger = &srslog::fetch_basic_logger(sched_cfg.logger_name); + // Initiate Common Sched Configuration cfg.cells.reserve(cell_list.size()); for (uint32_t cc = 0; cc < cell_list.size(); ++cc) { @@ -119,9 +122,9 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg) if (not ue_db.contains(rnti)) { auto ret = ue_db.insert(rnti, std::unique_ptr(new ue{rnti, uecfg, cfg})); if (ret.has_value()) { - logger.info("SCHED: New user rnti=0x%x, cc=%d", rnti, cfg.cells[0].cc); + logger->info("SCHED: New user rnti=0x%x, cc=%d", rnti, cfg.cells[0].cc); } else { - logger.error("SCHED: Failed to create new user rnti=0x%x", rnti); + logger->error("SCHED: Failed to create new user rnti=0x%x", rnti); } } else { ue_db[rnti]->set_cfg(uecfg); @@ -170,9 +173,9 @@ void sched_nr::ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) sched_workers->enqueue_cc_feedback(rnti, cc, [pid, crc](ue_carrier& ue_cc) { ue_cc.harq_ent.ul_crc_info(pid, crc); }); } -void sched_nr::ul_sr_info(slot_point slot_rx, uint16_t rnti) +void sched_nr::ul_sr_info(uint16_t rnti) { - sched_workers->enqueue_event(rnti, [this, rnti, slot_rx]() { ue_db[rnti]->ul_sr_info(slot_rx); }); + sched_workers->enqueue_event(rnti, [this, rnti]() { ue_db[rnti]->ul_sr_info(); }); } void sched_nr::ul_bsr(uint16_t rnti, uint32_t lcg_id, uint32_t bsr) @@ -204,4 +207,4 @@ int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg return SRSRAN_SUCCESS; } -} // namespace srsenb \ No newline at end of file +} // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr_cell.cc b/srsenb/src/stack/mac/nr/sched_nr_cell.cc index 29234fe5e..4bbe574de 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cell.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cell.cc @@ -26,7 +26,9 @@ namespace srsenb { namespace sched_nr_impl { -si_sched::si_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {} +si_sched::si_sched(const bwp_params& bwp_cfg_) : + bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) +{} void si_sched::run_slot(bwp_slot_allocator& slot_alloc) { @@ -84,7 +86,9 @@ void si_sched::run_slot(bwp_slot_allocator& slot_alloc) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -ra_sched::ra_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {} +ra_sched::ra_sched(const bwp_params& bwp_cfg_) : + bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) +{} alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) @@ -232,7 +236,7 @@ bwp_ctxt::bwp_ctxt(const bwp_params& bwp_cfg) : ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// serv_cell_manager::serv_cell_manager(const sched_cell_params& cell_cfg_) : - cfg(cell_cfg_), logger(srslog::fetch_basic_logger("MAC")) + cfg(cell_cfg_), logger(srslog::fetch_basic_logger(cell_cfg_.sched_cfg.logger_name)) { for (uint32_t bwp_id = 0; bwp_id < cfg.cell_cfg.bwps.size(); ++bwp_id) { bwps.emplace_back(cell_cfg_.bwps[bwp_id]); diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc index abcd85ef0..1609c6b03 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc @@ -55,6 +55,9 @@ void bwp_slot_grid::reset() pdschs.clear(); puschs.clear(); pending_acks.clear(); + pucch.clear(); + ssb.clear(); + nzp_csi_rs.clear(); } bwp_res_grid::bwp_res_grid(const bwp_params& bwp_cfg_) : cfg(&bwp_cfg_) diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc index 7b2ae2972..578a3d62b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_helpers.cc @@ -121,6 +121,27 @@ void fill_ul_dci_ue_fields(const slot_ue& ue, fill_dci_common(ue, bwp_cfg, dci); } +void log_sched_slot_ues(srslog::basic_logger& logger, slot_point pdcch_slot, uint32_t cc, const slot_ue_map_t& slot_ues) +{ + if (not logger.info.enabled() or slot_ues.empty()) { + return; + } + + fmt::memory_buffer fmtbuf; + fmt::format_to(fmtbuf, "SCHED: UE candidates, pdcch_tti={}, cc={}: [", pdcch_slot, cc); + + const char* use_comma = ""; + for (const auto& ue_pair : slot_ues) { + auto& ue = ue_pair->second; + + fmt::format_to( + fmtbuf, "{}{{rnti=0x{:x}, dl_bs={}, ul_bs={}}}", use_comma, ue.rnti, ue.dl_pending_bytes, ue.ul_pending_bytes); + use_comma = ", "; + } + + logger.info("%s]", srsran::to_c_str(fmtbuf)); +} + void log_sched_bwp_result(srslog::basic_logger& logger, slot_point pdcch_slot, const bwp_res_grid& res_grid, @@ -171,13 +192,14 @@ void log_sched_bwp_result(srslog::basic_logger& logger, if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti]; fmt::format_to(fmtbuf, - "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, tbs={}, tti_pusch={}", + "SCHED: UL {}, cc={}, rnti=0x{:x}, pid={}, f={}, nrtx={}, pending_bytes={}, tbs={}, tti_pusch={}", ue.h_ul->nof_retx() == 0 ? "tx" : "retx", res_grid.cfg->cc, ue.rnti, pdcch.dci.pid, srsran_dci_format_nr_string(pdcch.dci.ctx.format), ue.h_ul->nof_retx(), + ue.ul_pending_bytes, ue.h_ul->tbs(), ue.pusch_slot); } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_tc) { diff --git a/srsenb/src/stack/mac/nr/sched_nr_signalling.cc b/srsenb/src/stack/mac/nr/sched_nr_signalling.cc new file mode 100644 index 000000000..f7c0e9b9e --- /dev/null +++ b/srsenb/src/stack/mac/nr/sched_nr_signalling.cc @@ -0,0 +1,55 @@ +/** + * + * \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 "srsenb/hdr/stack/mac/nr/sched_nr_signalling.h" + +namespace srsenb { +namespace sched_nr_impl { + +void sched_nzp_csi_rs(srsran::const_span nzp_csi_rs_sets_cfg, + const srsran_slot_cfg_t& slot_cfg, + nzp_csi_rs_list& csi_rs_list) +{ + for (const srsran_csi_rs_nzp_set_t& set : nzp_csi_rs_sets_cfg) { + // For each NZP-CSI-RS resource available in the set + for (uint32_t i = 0; i < set.count; ++i) { + // Select resource + const srsran_csi_rs_nzp_resource_t& nzp_csi_resource = set.data[i]; + + // Check if the resource is scheduled for this slot + if (srsran_csi_rs_send(&nzp_csi_resource.periodicity, &slot_cfg)) { + csi_rs_list.push_back(nzp_csi_resource); + } + } + } +} + +void sched_dl_signalling(const bwp_params& bwp_params, + slot_point sl_pdcch, + ssb_list& ssb_list, + nzp_csi_rs_list& nzp_csi_rs) +{ + srsran_slot_cfg_t cfg; + cfg.idx = sl_pdcch.to_uint(); + + // Schedule SSB + // TODO + + // Schedule NZP-CSI-RS + sched_nzp_csi_rs(bwp_params.cfg.pdsch.nzp_csi_rs_sets, cfg, nzp_csi_rs); + + // Schedule SIBs + // TODO +} + +} // namespace sched_nr_impl +} // namespace srsenb diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 711d5cccc..0f351b8eb 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -105,10 +105,16 @@ void ue::set_cfg(const ue_cfg_t& cfg) carriers[ue_cc_cfg.cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[ue_cc_cfg.cc])); } } + + for (uint32_t lcid = 0; lcid < cfg.ue_bearers.size(); ++lcid) { + buffers.config_lcid(lcid, cfg.ue_bearers[lcid]); + } } void ue::new_slot(slot_point pdcch_slot) { + last_pdcch_slot = pdcch_slot; + for (auto& ue_cc_cfg : ue_cfg.carriers) { auto& cc = carriers[ue_cc_cfg.cc]; if (cc != nullptr) { @@ -128,14 +134,17 @@ void ue::new_slot(slot_point pdcch_slot) auto& cc = carriers[ue_cc_cfg.cc]; if (cc != nullptr) { // Discount UL HARQ pending bytes to BSR - for (uint32_t pid = 0; pid < cc->harq_ent.nof_dl_harqs(); ++pid) { - ul_pending_bytes -= cc->harq_ent.ul_harq(pid).tbs(); - if (last_sr_slot.valid() and cc->harq_ent.ul_harq(pid).harq_slot_tx() > last_sr_slot) { - last_sr_slot.clear(); + for (uint32_t pid = 0; pid < cc->harq_ent.nof_ul_harqs(); ++pid) { + if (not cc->harq_ent.ul_harq(pid).empty()) { + ul_pending_bytes -= cc->harq_ent.ul_harq(pid).tbs(); + if (last_sr_slot.valid() and cc->harq_ent.ul_harq(pid).harq_slot_tx() > last_sr_slot) { + last_sr_slot.clear(); + } } } } } + ul_pending_bytes = std::max(0, ul_pending_bytes); if (ul_pending_bytes == 0 and last_sr_slot.valid()) { // If unanswered SR is pending ul_pending_bytes = 512; diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index 389f0efd1..7106387bf 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -20,13 +20,17 @@ */ #include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" +#include "srsenb/hdr/stack/mac/nr/sched_nr_signalling.h" #include "srsran/common/string_helpers.h" namespace srsenb { namespace sched_nr_impl { slot_cc_worker::slot_cc_worker(serv_cell_manager& cc_sched) : - cell(cc_sched), cfg(cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid), logger(srslog::fetch_basic_logger("MAC")) + cell(cc_sched), + cfg(cc_sched.cfg), + bwp_alloc(cc_sched.bwps[0].grid), + logger(srslog::fetch_basic_logger(cc_sched.cfg.sched_cfg.logger_name)) {} void slot_cc_worker::enqueue_cc_event(srsran::move_callback ev) @@ -96,6 +100,9 @@ void slot_cc_worker::run(slot_point pdcch_slot, ue_map_t& ue_db) // Create an BWP allocator object that will passed along to RA, SI, Data schedulers bwp_alloc.new_slot(slot_rx + TX_ENB_DELAY, slot_ues); + // Log UEs state for slot + log_sched_slot_ues(logger, bwp_alloc.get_pdcch_tti(), cfg.cc, slot_ues); + // Allocate pending RARs cell.bwps[0].ra.run_slot(bwp_alloc); @@ -103,6 +110,9 @@ void slot_cc_worker::run(slot_point pdcch_slot, ue_map_t& ue_db) alloc_dl_ues(); alloc_ul_ues(); + // Post-processing of scheduling decisions + postprocess_decisions(); + // Log CC scheduler result log_sched_bwp_result(logger, bwp_alloc.get_pdcch_tti(), cell.bwps[0].grid, slot_ues); @@ -127,12 +137,89 @@ void slot_cc_worker::alloc_ul_ues() cell.bwps[0].data_sched->sched_ul_users(slot_ues, bwp_alloc); } +void slot_cc_worker::postprocess_decisions() +{ + auto& bwp_slot = cell.bwps[0].grid[bwp_alloc.get_pdcch_tti()]; + srsran_slot_cfg_t slot_cfg{}; + slot_cfg.idx = bwp_alloc.get_pdcch_tti().to_uint(); + + for (auto& ue_pair : slot_ues) { + auto& ue = ue_pair.second; + // Group pending HARQ ACKs + srsran_pdsch_ack_nr_t ack = {}; + + for (auto& h_ack : bwp_slot.pending_acks) { + if (h_ack.res.rnti == ue.rnti) { + ack.nof_cc = 1; + + srsran_harq_ack_m_t ack_m = {}; + ack_m.resource = h_ack.res; + ack_m.present = true; + srsran_harq_ack_insert_m(&ack, &ack_m); + } + } + + srsran_uci_cfg_nr_t uci_cfg = {}; + if (not ue.cfg->phy().get_uci_cfg(slot_cfg, ack, uci_cfg)) { + logger.error("Error getting UCI configuration"); + continue; + } + + if (uci_cfg.ack.count == 0 and uci_cfg.nof_csi == 0 and uci_cfg.o_sr == 0) { + continue; + } + + bool has_pusch = false; + for (auto& pusch : bwp_slot.puschs) { + if (pusch.sch.grant.rnti == ue.rnti) { + // Put UCI configuration in PUSCH config + has_pusch = true; + if (not ue.cfg->phy().get_pusch_uci_cfg(slot_cfg, uci_cfg, pusch.sch)) { + logger.error("Error setting UCI configuration in PUSCH"); + continue; + } + break; + } + } + if (not has_pusch) { + // If any UCI information is triggered, schedule PUCCH + bwp_slot.pucch.emplace_back(); + mac_interface_phy_nr::pucch_t& pucch = bwp_slot.pucch.back(); + + uci_cfg.pucch.rnti = ue.rnti; + pucch.candidates.emplace_back(); + pucch.candidates.back().uci_cfg = uci_cfg; + if (not ue.cfg->phy().get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource)) { + logger.error("Error getting UCI CFG"); + continue; + } + + // If this slot has a SR opportunity and the selected PUCCH format is 1, consider positive SR. + if (uci_cfg.o_sr > 0 and uci_cfg.ack.count > 0 and + pucch.candidates.back().resource.format == SRSRAN_PUCCH_NR_FORMAT_1) { + // Set SR negative + if (uci_cfg.o_sr > 0) { + uci_cfg.sr_positive_present = false; + } + + // Append new resource + pucch.candidates.emplace_back(); + pucch.candidates.back().uci_cfg = uci_cfg; + if (not ue.cfg->phy().get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource)) { + logger.error("Error getting UCI CFG"); + continue; + } + } + } + } +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_, srsran::span > cells_) : - cfg(cfg_), ue_db(ue_db_), logger(srslog::fetch_basic_logger("MAC")), cells(cells_) + cfg(cfg_), ue_db(ue_db_), logger(srslog::fetch_basic_logger(cfg_.sched_cfg.logger_name)), cells(cells_) { cc_worker_list.reserve(cfg.cells.size()); for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) { @@ -178,6 +265,12 @@ void sched_worker_manager::update_ue_db(slot_point slot_tx, bool locked_context) void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res) { + // Fill DL signalling messages that do not depend on UEs state + serv_cell_manager& serv_cell = *cells[cc]; + bwp_slot_grid& bwp_slot = serv_cell.bwps[0].grid[slot_tx]; + sched_dl_signalling(*serv_cell.bwps[0].cfg, slot_tx, bwp_slot.ssb, bwp_slot.nzp_csi_rs); + + // Synchronization point between CC workers, to avoid concurrency in UE state access srsran::bounded_vector waiting_cvars; { std::unique_lock lock(slot_mutex); @@ -259,64 +352,14 @@ bool sched_worker_manager::save_sched_result(slot_point pdcch_slot, // NOTE: Unlocked region auto& bwp_slot = cells[cc]->bwps[0].grid[pdcch_slot]; - dl_res.dl_sched.pdcch_dl = bwp_slot.dl_pdcchs; - dl_res.dl_sched.pdcch_ul = bwp_slot.ul_pdcchs; - dl_res.dl_sched.pdsch = bwp_slot.pdschs; - dl_res.rar = bwp_slot.rar; - ul_res.pusch = bwp_slot.puschs; - - // Group pending HARQ ACKs - srsran_pdsch_ack_nr_t ack = {}; - ack.nof_cc = not bwp_slot.pending_acks.empty(); - const srsran::phy_cfg_nr_t* phy_cfg = nullptr; - for (const harq_ack_t& pending_ack : bwp_slot.pending_acks) { - srsran_harq_ack_m_t ack_m = {}; - ack_m.resource = pending_ack.res; - ack_m.present = true; - srsran_harq_ack_insert_m(&ack, &ack_m); - phy_cfg = pending_ack.phy_cfg; - } - - if (phy_cfg != nullptr) { - srsran_slot_cfg_t slot_cfg{}; - slot_cfg.idx = pdcch_slot.slot_idx(); - srsran_uci_cfg_nr_t uci_cfg = {}; - srsran_assert(phy_cfg->get_uci_cfg(slot_cfg, ack, uci_cfg), "Error getting UCI CFG"); - - if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) { - if (not ul_res.pusch.empty()) { - // Put UCI configuration in PUSCH config - bool ret = phy_cfg->get_pusch_uci_cfg(slot_cfg, uci_cfg, ul_res.pusch[0].sch); - srsran_assert(ret, "Error setting UCI configuration in PUSCH"); - } else { - // Put UCI configuration in PUCCH config - ul_res.pucch.emplace_back(); - pucch_t& pucch = ul_res.pucch.back(); - pucch.candidates.emplace_back(); - pucch.candidates.back().uci_cfg = uci_cfg; - srsran_assert(phy_cfg->get_pucch_uci_cfg( - slot_cfg, pucch.candidates.back().uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource), - "Error getting PUCCH UCI cfg"); - - // If this slot has a SR opportunity and the selected PUCCH format is 1, consider positive SR. - if (uci_cfg.sr_positive_present and uci_cfg.ack.count > 0 and - pucch.candidates.back().resource.format == SRSRAN_PUCCH_NR_FORMAT_1) { - // Set SR negative - if (uci_cfg.o_sr > 0) { - uci_cfg.sr_positive_present = false; - } - - // Append new resource - pucch.candidates.emplace_back(); - pucch.candidates.back().uci_cfg = uci_cfg; - srsran_assert( - phy_cfg->get_pucch_uci_cfg( - slot_cfg, pucch.candidates.back().uci_cfg, pucch.pucch_cfg, pucch.candidates.back().resource), - "Error getting PUCCH UCI cfg"); - } - } - } - } + dl_res.dl_sched.pdcch_dl = bwp_slot.dl_pdcchs; + dl_res.dl_sched.pdcch_ul = bwp_slot.ul_pdcchs; + dl_res.dl_sched.pdsch = bwp_slot.pdschs; + dl_res.rar = bwp_slot.rar; + dl_res.dl_sched.ssb = bwp_slot.ssb; + dl_res.dl_sched.nzp_csi_rs = bwp_slot.nzp_csi_rs; + ul_res.pusch = bwp_slot.puschs; + ul_res.pucch = bwp_slot.pucch; // clear up BWP slot bwp_slot.reset(); diff --git a/srsenb/src/stack/mac/nr/ue_nr.cc b/srsenb/src/stack/mac/nr/ue_nr.cc index f6850a2e5..ca88a54e3 100644 --- a/srsenb/src/stack/mac/nr/ue_nr.cc +++ b/srsenb/src/stack/mac/nr/ue_nr.cc @@ -77,7 +77,7 @@ int ue_nr::process_pdu(srsran::unique_byte_buffer_t pdu) if (logger.info.enabled()) { fmt::memory_buffer str_buffer; mac_pdu_ul.to_string(str_buffer); - logger.info("0x%x %s", rnti, srsran::to_c_str(str_buffer)); + logger.info("Rx PDU: rnti=0x%x, %s", rnti, srsran::to_c_str(str_buffer)); } for (uint32_t i = 0; i < mac_pdu_ul.get_num_subpdus(); ++i) { @@ -95,7 +95,7 @@ int ue_nr::process_pdu(srsran::unique_byte_buffer_t pdu) if (true /*sched->ue_exists(c_crnti)*/) { rrc->update_user(rnti, c_rnti); rnti = c_rnti; - sched->ul_bsr(rnti, 0, 1); // provide UL grant regardless of other BSR content for UE to complete RA + sched->ul_sr_info(rnti); // provide UL grant regardless of other BSR content for UE to complete RA } else { logger.warning("Updating user C-RNTI: rnti=0x%x already released.", c_rnti); // Disable scheduling for all bearers. The new rnti will be removed on msg3 timer expiry in the RRC @@ -108,10 +108,6 @@ int ue_nr::process_pdu(srsran::unique_byte_buffer_t pdu) case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::SHORT_TRUNC_BSR: { srsran::mac_sch_subpdu_nr::lcg_bsr_t sbsr = subpdu.get_sbsr(); uint32_t buffer_size_bytes = buff_size_field_to_bytes(sbsr.buffer_size, srsran::SHORT_BSR); - // FIXME: a UE might send a zero BSR but still needs an UL grant to finish RA procedure - if (buffer_size_bytes == 0) { - buffer_size_bytes++; - } sched->ul_bsr(rnti, sbsr.lcg_id, buffer_size_bytes); } break; case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::LONG_BSR: @@ -156,6 +152,12 @@ int ue_nr::generate_pdu(srsran::byte_buffer_t* pdu, uint32_t grant_size) // add to MAC PDU and pack mac_pdu_dl.add_sdu(lcid, ue_rlc_buffer->msg, ue_rlc_buffer->N_bytes); + + // Indicate DRB activity in DL to RRC + if (lcid > 3) { + rrc->set_activity_user(rnti); + logger.debug("DL activity rnti=0x%x, n_bytes=%d", rnti, ue_rlc_buffer->N_bytes); + } } mac_pdu_dl.pack(); @@ -181,8 +183,8 @@ void ue_nr::metrics_read(mac_ue_metrics_t* metrics_) // set PCell sector id std::array cc_list; //= sched->get_enb_ue_cc_map(rnti); - auto it = std::find(cc_list.begin(), cc_list.end(), 0); - ue_metrics.cc_idx = std::distance(cc_list.begin(), it); + auto it = std::find(cc_list.begin(), cc_list.end(), 0); + ue_metrics.cc_idx = std::distance(cc_list.begin(), it); *metrics_ = ue_metrics; diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc index 988c734f5..40cb799c1 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc @@ -60,8 +60,10 @@ sched_ue_cell::sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg dl_cqi_ctxt(cell_cfg_.nof_prb(), 0, cell_cfg_.sched_cfg->init_dl_cqi) { float target_bler = cell_cfg->sched_cfg->target_bler; - delta_inc = cell_cfg->sched_cfg->adaptive_link_step_size; // delta_{down} of OLLA - delta_dec = (1 - target_bler) * delta_inc / target_bler; + dl_delta_inc = cell_cfg->sched_cfg->adaptive_dl_mcs_step_size; // delta_{down} of OLLA + dl_delta_dec = (1 - target_bler) * dl_delta_inc / target_bler; + ul_delta_inc = cell_cfg->sched_cfg->adaptive_ul_mcs_step_size; // delta_{down} of OLLA + ul_delta_dec = (1 - target_bler) * ul_delta_inc / target_bler; max_cqi_coeff = cell_cfg->sched_cfg->max_delta_dl_cqi; max_snr_coeff = cell_cfg->sched_cfg->max_delta_ul_snr; } @@ -211,8 +213,8 @@ int sched_ue_cell::set_ul_crc(tti_point tti_rx, bool crc_res) if (ul_harq != nullptr) { int mcs = ul_harq->get_mcs(0); // Note: Avoid keeping increasing the snr delta offset, if MCS is already is at its limit - float delta_dec_eff = mcs <= 0 ? 0 : delta_dec; - float delta_inc_eff = mcs >= (int)max_mcs_ul ? 0 : delta_inc; + float delta_dec_eff = mcs <= 0 ? 0 : ul_delta_dec; + float delta_inc_eff = mcs >= (int)max_mcs_ul ? 0 : ul_delta_inc; ul_snr_coeff += crc_res ? delta_inc_eff : -delta_dec_eff; ul_snr_coeff = std::min(std::max(-max_snr_coeff, ul_snr_coeff), max_snr_coeff); logger.info("SCHED: UL adaptive link: rnti=0x%x, snr_estim=%.2f, last_mcs=%d, snr_offset=%f", @@ -248,8 +250,8 @@ int sched_ue_cell::set_ack_info(tti_point tti_rx, uint32_t tb_idx, bool ack) if (cell_cfg->sched_cfg->target_bler > 0 and fixed_mcs_dl < 0) { int mcs = std::get<2>(p2); // Note: Avoid keeping increasing the snr delta offset, if MCS is already is at its limit - float delta_dec_eff = mcs <= 0 ? 0 : delta_dec; - float delta_inc_eff = mcs >= (int)max_mcs_dl ? 0 : delta_inc; + float delta_dec_eff = mcs <= 0 ? 0 : dl_delta_dec; + float delta_inc_eff = mcs >= (int)max_mcs_dl ? 0 : dl_delta_inc; dl_cqi_coeff += ack ? delta_inc_eff : -delta_dec_eff; dl_cqi_coeff = std::min(std::max(-max_cqi_coeff, dl_cqi_coeff), max_cqi_coeff); logger.info("SCHED: DL adaptive link: rnti=0x%x, cqi=%d, last_mcs=%d, cqi_offset=%f", diff --git a/srsenb/src/stack/ngap/CMakeLists.txt b/srsenb/src/stack/ngap/CMakeLists.txt index a4d2ca9c6..e50cca2b1 100644 --- a/srsenb/src/stack/ngap/CMakeLists.txt +++ b/srsenb/src/stack/ngap/CMakeLists.txt @@ -18,5 +18,5 @@ # and at http://www.gnu.org/licenses/. # -set(SOURCES ngap.cc ngap_ue.cc ngap_ue_proc.cc) +set(SOURCES ngap.cc ngap_ue.cc ngap_ue_proc.cc ngap_ue_bearer_manager.cc) add_library(srsgnb_ngap STATIC ${SOURCES}) diff --git a/srsenb/src/stack/ngap/ngap.cc b/srsenb/src/stack/ngap/ngap.cc index be2265301..86f8b92d1 100644 --- a/srsenb/src/stack/ngap/ngap.cc +++ b/srsenb/src/stack/ngap/ngap.cc @@ -30,6 +30,13 @@ using srsran::uint32_to_uint8; #define procWarning(fmt, ...) ngap_ptr->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define procInfo(fmt, ...) ngap_ptr->logger.info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define WarnUnsupportFeature(cond, featurename) \ + do { \ + if (cond) { \ + logger.warning("Not handling feature - %s", featurename); \ + } \ + } while (0) + using namespace asn1::ngap_nr; namespace srsenb { @@ -114,10 +121,11 @@ ngap::ngap(srsran::task_sched_handle task_sched_, ngap::~ngap() {} -int ngap::init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_) +int ngap::init(const ngap_args_t& args_, rrc_interface_ngap_nr* rrc_, gtpu_interface_rrc * gtpu_) { rrc = rrc_; args = args_; + gtpu = gtpu_; build_tai_cgi(); @@ -216,7 +224,7 @@ void ngap::initial_ue(uint16_t rnti, asn1::ngap_nr::rrcestablishment_cause_e cause, srsran::unique_byte_buffer_t pdu) { - std::unique_ptr ue_ptr{new ue{this, rrc, logger}}; + std::unique_ptr ue_ptr{new ue{this, rrc, gtpu, logger}}; ue_ptr->ctxt.rnti = rnti; ue_ptr->ctxt.gnb_cc_idx = gnb_cc_idx; ue* u = users.add_user(std::move(ue_ptr)); @@ -233,7 +241,7 @@ void ngap::initial_ue(uint16_t rnti, srsran::unique_byte_buffer_t pdu, uint32_t s_tmsi) { - std::unique_ptr ue_ptr{new ue{this, rrc, logger}}; + std::unique_ptr ue_ptr{new ue{this, rrc, gtpu, logger}}; ue_ptr->ctxt.rnti = rnti; ue_ptr->ctxt.gnb_cc_idx = gnb_cc_idx; ue* u = users.add_user(std::move(ue_ptr)); @@ -423,6 +431,8 @@ bool ngap::handle_initiating_message(const asn1::ngap_nr::init_msg_s& msg) return handle_initial_ctxt_setup_request(msg.value.init_context_setup_request()); case ngap_elem_procs_o::init_msg_c::types_opts::ue_context_release_cmd: return handle_ue_ctxt_release_cmd(msg.value.ue_context_release_cmd()); + case ngap_elem_procs_o::init_msg_c::types_opts::pdu_session_res_setup_request: + return handle_ue_pdu_session_res_setup_request(msg.value.pdu_session_res_setup_request()); default: logger.error("Unhandled initiating message: %s", msg.value.type().to_string()); } @@ -541,10 +551,21 @@ bool ngap::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cm return true; } -bool ngap::handle_pdu_session_resource_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) +bool ngap::handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) { - // TODO - logger.warning("Not implemented yet"); + + ue* u = + handle_ngapmsg_ue_id(msg.protocol_ies.ran_ue_ngap_id.value.value, msg.protocol_ies.amf_ue_ngap_id.value.value); + if (u == nullptr) { + logger.warning("Can not find UE"); + return false; + } + + if (msg.protocol_ies.ue_aggregate_maximum_bit_rate_present) { + rrc->set_aggregate_max_bitrate(u->ctxt.rnti, msg.protocol_ies.ue_aggregate_maximum_bit_rate.value); + } + u->handle_pdu_session_res_setup_request(msg); + return true; } diff --git a/srsenb/src/stack/ngap/ngap_ue.cc b/srsenb/src/stack/ngap/ngap_ue.cc index 6cc595e31..a4e53bf18 100644 --- a/srsenb/src/stack/ngap/ngap_ue.cc +++ b/srsenb/src/stack/ngap/ngap_ue.cc @@ -32,12 +32,16 @@ namespace srsenb { /* ngap_ptr::ue Class ********************************************************************************/ -ngap::ue::ue(ngap* ngap_ptr_, rrc_interface_ngap_nr* rrc_ptr_, srslog::basic_logger& logger_) : +ngap::ue::ue(ngap* ngap_ptr_, + rrc_interface_ngap_nr* rrc_ptr_, + gtpu_interface_rrc* gtpu_ptr_, + srslog::basic_logger& logger_) : logger(logger_), ngap_ptr(ngap_ptr_), - rrc_ptr(rrc_ptr_), - initial_context_setup_proc(this, rrc_ptr, &ctxt), - ue_context_release_proc(this, rrc_ptr, &ctxt) + bearer_manager(rrc_ptr_, gtpu_ptr_, logger_), + initial_context_setup_proc(this, rrc_ptr_, &ctxt, logger_), + ue_context_release_proc(this, rrc_ptr_, &ctxt, logger_), + ue_pdu_session_res_setup_proc(this, rrc_ptr_, &ctxt, &bearer_manager, logger_) { ctxt.ran_ue_ngap_id = ngap_ptr->next_gnb_ue_ngap_id++; gettimeofday(&ctxt.init_timestamp, nullptr); @@ -91,6 +95,10 @@ bool ngap::ue::send_initial_ue_message(asn1::ngap_nr::rrcestablishment_cause_e c container.user_location_info.value.user_location_info_nr().tai.plmn_id = ngap_ptr->tai.plmn_id; container.user_location_info.value.user_location_info_nr().tai.tac = ngap_ptr->tai.tac; + // UE context request for setup in the NAS registration request + container.ue_context_request_present = true; + container.ue_context_request.value = asn1::ngap_nr::ue_context_request_opts::options::requested; + return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "InitialUEMessage"); } @@ -147,7 +155,7 @@ bool ngap::ue::send_initial_ctxt_setup_response() } ngap_pdu_c tx_pdu; - tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_INIT_CONTEXT_SETUP); + tx_pdu.set_successful_outcome().load_info_obj(ASN1_NGAP_NR_ID_INIT_CONTEXT_SETUP); init_context_setup_resp_s& container = tx_pdu.successful_outcome().value.init_context_setup_resp(); // AMF UE NGAP ID @@ -156,13 +164,7 @@ bool ngap::ue::send_initial_ctxt_setup_response() // RAN UE NGAP ID container.protocol_ies.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id; - /* // TODO: PDU Session Resource Setup Response List - Integrate PDU Session and Bearer management into NGAP - container.protocol_ies.pdu_session_res_setup_list_cxt_res_present = true; - - // Case PDU Session Resource Failed to Setup List - container.protocol_ies.pdu_session_res_failed_to_setup_list_cxt_res_present = true; */ - - return true; + return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "InitialContextSetupResponse"); } bool ngap::ue::send_initial_ctxt_setup_failure(cause_c cause) @@ -191,6 +193,45 @@ bool ngap::ue::send_initial_ctxt_setup_failure(cause_c cause) return true; } +bool ngap::ue::send_pdu_session_resource_setup_response(uint16_t pdu_session_id, + uint32_t teid_in, + asn1::bounded_bitstring<1, 160, true, true> addr_in) +{ + if (not ngap_ptr->amf_connected) { + logger.warning("AMF not connected"); + return false; + } + // TODO: QOS Params + ngap_pdu_c tx_pdu; + tx_pdu.set_successful_outcome().load_info_obj(ASN1_NGAP_NR_ID_PDU_SESSION_RES_SETUP); + pdu_session_res_setup_resp_s& container = tx_pdu.successful_outcome().value.pdu_session_res_setup_resp(); + container.protocol_ies.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value(); + container.protocol_ies.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id; + container.protocol_ies.pdu_session_res_setup_list_su_res_present = true; + pdu_session_res_setup_item_su_res_s su_res; + su_res.pdu_session_res_setup_resp_transfer.resize(512); + su_res.pdu_session_id = pdu_session_id; + pdu_session_res_setup_resp_transfer_s resp_transfer; + + gtp_tunnel_s& gtp_tunnel = resp_transfer.dlqos_flow_per_tnl_info.uptransport_layer_info.set_gtp_tunnel(); + + gtp_tunnel.gtp_teid.from_number(teid_in); + gtp_tunnel.transport_layer_address = addr_in; + asn1::ngap_nr::associated_qos_flow_list_l qos_flow_list; + asn1::ngap_nr::associated_qos_flow_item_s qos_flow_item; + qos_flow_item.qos_flow_id = 1; + qos_flow_list.push_back(qos_flow_item); + resp_transfer.dlqos_flow_per_tnl_info.associated_qos_flow_list = qos_flow_list; + + asn1::bit_ref bref(su_res.pdu_session_res_setup_resp_transfer.data(), + su_res.pdu_session_res_setup_resp_transfer.size()); + resp_transfer.pack(bref); + su_res.pdu_session_res_setup_resp_transfer.resize(bref.distance_bytes()); + + container.protocol_ies.pdu_session_res_setup_list_su_res.value.push_back(su_res); + return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "PDUSessionResourceSetupResponse"); +} + /******************************************************************************* /* NGAP message handler ********************************************************************************/ @@ -214,4 +255,13 @@ bool ngap::ue::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_releas return true; } +bool ngap::ue::handle_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) +{ + if (not ue_pdu_session_res_setup_proc.launch(msg)) { + logger.error("Failed to start UE PDU Session Resource Setup Procedure"); + return false; + } + return true; +} + } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc b/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc new file mode 100644 index 000000000..19c71526f --- /dev/null +++ b/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc @@ -0,0 +1,110 @@ +/** + * + * \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 "srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h" + +namespace srsenb { +ngap_ue_bearer_manager::ngap_ue_bearer_manager(rrc_interface_ngap_nr* rrc_, + gtpu_interface_rrc* gtpu_, + srslog::basic_logger& logger_) : + gtpu(gtpu_), rrc(rrc_), logger(logger_) +{} +ngap_ue_bearer_manager::~ngap_ue_bearer_manager(){}; + +int ngap_ue_bearer_manager::add_pdu_session(uint16_t rnti, + uint8_t pdu_session_id, + const asn1::ngap_nr::qos_flow_level_qos_params_s& qos, + const asn1::bounded_bitstring<1, 160, true, true>& addr_out, + uint32_t teid_out, + uint16_t& lcid, + asn1::bounded_bitstring<1, 160, true, true>& addr_in, + uint32_t& teid_in, + asn1::ngap_nr::cause_c& cause) +{ + // RRC call for QoS parameter and lcid <-> ID mapping + lcid = rrc->allocate_lcid(rnti); + + // Only add session if gtpu was successful + pdu_session_t::gtpu_tunnel tunnel; + + if (addr_out.length() > 32) { + logger.error("Only addresses with length <= 32 (IPv4) are supported"); + cause.set_radio_network().value = asn1::ngap_nr::cause_radio_network_opts::invalid_qos_combination; + return SRSRAN_ERROR; + } + + // TODO: remove lcid and just use pdu_session_id and rnti as id for GTP tunnel + int rtn = add_gtpu_bearer(rnti, lcid, pdu_session_id, teid_out, addr_out, tunnel); + if (rtn != SRSRAN_SUCCESS) { + logger.error("Adding PDU Session ID=%d to GTPU", pdu_session_id); + return SRSRAN_ERROR; + } + + pdu_session_list[pdu_session_id].id = pdu_session_id; + pdu_session_list[pdu_session_id].lcid = lcid; + pdu_session_list[pdu_session_id].qos_params = qos; + pdu_session_list[pdu_session_id].tunnels.push_back(tunnel); + + // return values + teid_in = tunnel.teid_in; + addr_in = tunnel.address_in; + + return SRSRAN_SUCCESS; +} + +int ngap_ue_bearer_manager::add_gtpu_bearer(uint16_t rnti, + uint32_t lcid, + uint32_t pdu_session_id, + uint32_t teid_out, + asn1::bounded_bitstring<1, 160, true, true> address_out, + pdu_session_t::gtpu_tunnel& tunnel, + const gtpu_interface_rrc::bearer_props* props) +{ + // Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf + uint32_t addr_in; + srsran::expected rtn = gtpu->add_bearer(rnti, lcid, address_out.to_number(), teid_out, addr_in, props); + if (rtn.is_error()) { + logger.error("Failed adding pdu_session_id=%d to GTPU", pdu_session_id); + return SRSRAN_ERROR; + } + + tunnel.teid_out = teid_out; + tunnel.address_out = address_out; + + logger.info("Addr in %x", addr_in); + + tunnel.address_in.from_number(addr_in); + tunnel.teid_in = rtn.value(); + + logger.info("Added GTPU tunnel rnti 0x%04x, lcid %d, pdu_session_id=%d, teid_out %d, teid_in %d, address out 0x%x, " + "address in 0x%x", + rnti, + lcid, + pdu_session_id, + tunnel.teid_out, + tunnel.teid_in, + tunnel.address_out.to_number(), + tunnel.address_in.to_number()); + return SRSRAN_SUCCESS; +} + +void ngap_ue_bearer_manager::rem_gtpu_bearer(uint16_t rnti, uint32_t pdu_session_id) +{ + auto it = pdu_session_list.find(pdu_session_id); + if (it == pdu_session_list.end()) { + logger.warning("Removing pdu_session=%d from GTPU", pdu_session_id); + return; + } + gtpu->rem_bearer(rnti, it->second.lcid); +} + +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/ngap/ngap_ue_proc.cc b/srsenb/src/stack/ngap/ngap_ue_proc.cc index f52b32c11..3efe8b118 100644 --- a/srsenb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsenb/src/stack/ngap/ngap_ue_proc.cc @@ -27,13 +27,9 @@ namespace srsenb { ngap_ue_initial_context_setup_proc::ngap_ue_initial_context_setup_proc(ngap_interface_ngap_proc* parent_, rrc_interface_ngap_nr* rrc_, - ngap_ue_ctxt_t* ue_ctxt_) : - logger(srslog::fetch_basic_logger("NGAP UE")) -{ - parent = parent_; - rrc = rrc_; - ue_ctxt = ue_ctxt_; -}; + ngap_ue_ctxt_t* ue_ctxt_, + srslog::basic_logger& logger_) : + logger(logger_), parent(parent_), rrc(rrc_), ue_ctxt(ue_ctxt_){}; proc_outcome_t ngap_ue_initial_context_setup_proc::init(const asn1::ngap_nr::init_context_setup_request_s& msg) { @@ -61,25 +57,26 @@ proc_outcome_t ngap_ue_initial_context_setup_proc::init(const asn1::ngap_nr::ini return proc_outcome_t::yield; }; -proc_outcome_t ngap_ue_initial_context_setup_proc::react(bool security_mode_command_outcome) +proc_outcome_t ngap_ue_initial_context_setup_proc::react(bool rrc_reconf_outcome) { - if(security_mode_command_outcome == true) { + if (rrc_reconf_outcome == true) { parent->send_initial_ctxt_setup_response(); return proc_outcome_t::success; - } - // TODO: error handling if security mode command fails + } + return proc_outcome_t::error; } -proc_outcome_t ngap_ue_initial_context_setup_proc::step() +proc_outcome_t ngap_ue_initial_context_setup_proc::step() { return proc_outcome_t::yield; } ngap_ue_ue_context_release_proc::ngap_ue_ue_context_release_proc(ngap_interface_ngap_proc* parent_, rrc_interface_ngap_nr* rrc_, - ngap_ue_ctxt_t* ue_ctxt_) : - logger(srslog::fetch_basic_logger("NGAP UE")) + ngap_ue_ctxt_t* ue_ctxt_, + srslog::basic_logger& logger_) : + logger(logger_) { parent = parent_; rrc = rrc_; @@ -90,6 +87,7 @@ proc_outcome_t ngap_ue_ue_context_release_proc::init(const asn1::ngap_nr::ue_con { // ue_ngap_ids_c ue_ngap_ids = msg.protocol_ies.ue_ngap_ids.value; // cause_c cause = msg.protocol_ies.cause.value; + logger.info("Started %s", name()); return proc_outcome_t::success; } @@ -98,4 +96,95 @@ proc_outcome_t ngap_ue_ue_context_release_proc::step() return proc_outcome_t::success; } +ngap_ue_pdu_session_res_setup_proc::ngap_ue_pdu_session_res_setup_proc(ngap_interface_ngap_proc* parent_, + rrc_interface_ngap_nr* rrc_, + ngap_ue_ctxt_t* ue_ctxt_, + ngap_ue_bearer_manager* bearer_manager_, + srslog::basic_logger& logger_) : + parent(parent_), rrc(rrc_), ue_ctxt(ue_ctxt_), bearer_manager(bearer_manager_), logger(logger_) +{} + +proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) +{ + if (msg.protocol_ies.pdu_session_res_setup_list_su_req.value.size() != 1) { + logger.error("Not handling zero or multiple su requests"); + return proc_outcome_t::error; + } + + asn1::ngap_nr::pdu_session_res_setup_item_su_req_s su_req = + msg.protocol_ies.pdu_session_res_setup_list_su_req.value[0]; + + asn1::cbit_ref pdu_session_bref(su_req.pdu_session_res_setup_request_transfer.data(), + su_req.pdu_session_res_setup_request_transfer.size()); + + asn1::ngap_nr::pdu_session_res_setup_request_transfer_s pdu_ses_res_setup_req_trans; + + if (pdu_ses_res_setup_req_trans.unpack(pdu_session_bref) != SRSRAN_SUCCESS) { + logger.error("Unable to unpack PDU session response setup request"); + return proc_outcome_t::error; + } + + if (pdu_ses_res_setup_req_trans.protocol_ies.qos_flow_setup_request_list.value.size() != 1) { + logger.error("Expected one item in QoS flow setup request list"); + return proc_outcome_t::error; + } + + if (pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.type() != + asn1::ngap_nr::up_transport_layer_info_c::types::gtp_tunnel) { + logger.error("Expected GTP Tunnel"); + return proc_outcome_t::error; + } + asn1::ngap_nr::qos_flow_setup_request_item_s qos_flow_setup = + pdu_ses_res_setup_req_trans.protocol_ies.qos_flow_setup_request_list.value[0]; + srsran::const_span nas_pdu_dummy; + uint32_t teid_out = 0; + + teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[0] << 24u; + teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[1] << 16u; + teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[2] << 8u; + teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[3]; + + // TODO: Check cause + asn1::ngap_nr::cause_c cause; + uint32_t teid_in; + uint16_t lcid; + asn1::bounded_bitstring<1, 160, true, true> addr_in; + + if (bearer_manager->add_pdu_session( + ue_ctxt->rnti, + su_req.pdu_session_id, + qos_flow_setup.qos_flow_level_qos_params, + pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().transport_layer_address, + teid_out, + lcid, + addr_in, + teid_in, + cause) != SRSRAN_SUCCESS) { + logger.warning("Failed to add pdu session\n"); + return proc_outcome_t::error; + } + + logger.info("Added PDU Session with LCID %d, teid_out %d, teid_in %d, addr_in %s", + lcid, + teid_out, + teid_in, + addr_in.to_string()); + + // QoS parameter mapping in config in LTE enb + if (su_req.pdu_session_nas_pdu_present) { + if (rrc->establish_rrc_bearer(ue_ctxt->rnti, su_req.pdu_session_id, su_req.pdu_session_nas_pdu, lcid) == + SRSRAN_SUCCESS) { + parent->send_pdu_session_resource_setup_response(su_req.pdu_session_id, teid_in, addr_in); + return proc_outcome_t::success; + } + } + + return proc_outcome_t::yield; +} + +proc_outcome_t ngap_ue_pdu_session_res_setup_proc::step() +{ + return proc_outcome_t::success; +} + } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 6ca21561f..527dddc9f 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -246,12 +246,12 @@ int rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg) if (rnti == SRSRAN_MRNTI) { for (auto& mbms_item : mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9) { uint32_t lcid = mbms_item.lc_ch_id_r9; - + uint32_t addr_in; // adding UE object to MAC for MRNTI without scheduling configuration (broadcast not part of regular scheduling) mac->ue_cfg(SRSRAN_MRNTI, NULL); rlc->add_bearer_mrb(SRSRAN_MRNTI, lcid); pdcp->add_bearer(SRSRAN_MRNTI, lcid, srsran::make_drb_pdcp_config_t(1, false)); - gtpu->add_bearer(SRSRAN_MRNTI, lcid, 1, 1); + gtpu->add_bearer(SRSRAN_MRNTI, lcid, 1, 1, addr_in); } } return SRSRAN_SUCCESS; @@ -660,11 +660,7 @@ void rrc::rem_user(uint16_t rnti) { auto user_it = users.find(rnti); if (user_it != users.end()) { - srsran::console("Disconnecting rnti=0x%x.\n", rnti); - logger.info("Disconnecting rnti=0x%x.", rnti); - - /* First remove MAC and GTPU to stop processing DL/UL traffic for this user - */ + // First remove MAC and GTPU to stop processing DL/UL traffic for this user mac->ue_rem(rnti); // MAC handles PHY gtpu->rem_user(rnti); @@ -674,6 +670,8 @@ void rrc::rem_user(uint16_t rnti) pdcp->rem_user(rnti); users.erase(rnti); + + srsran::console("Disconnecting rnti=0x%x.\n", rnti); logger.info("Removed user rnti=0x%x", rnti); } else { logger.error("Removing user rnti=0x%x (does not exist)", rnti); diff --git a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc index afe076be9..a70e58b37 100644 --- a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc @@ -394,9 +394,10 @@ srsran::expected bearer_cfg_handler::add_gtpu_bearer(uint32_t // Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf erab_t& erab = it->second; erab_t::gtpu_tunnel bearer; + uint32_t addr_in; bearer.teid_out = teid_out; bearer.addr = addr; - srsran::expected teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, props); + srsran::expected teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, addr_in, props); if (teidin.is_error()) { logger->error("Adding erab_id=%d to GTPU", erab_id); return srsran::default_error_t(); diff --git a/srsenb/src/stack/rrc/rrc_cell_cfg.cc b/srsenb/src/stack/rrc/rrc_cell_cfg.cc index 7777ee7c3..9d6b8c42f 100644 --- a/srsenb/src/stack/rrc/rrc_cell_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_cell_cfg.cc @@ -179,7 +179,7 @@ const ue_cell_ded* ue_cell_ded_list::find_cell(uint32_t earfcn, uint32_t pci) co return it == cell_list.end() ? nullptr : &(*it); } -ue_cell_ded* ue_cell_ded_list::add_cell(uint32_t enb_cc_idx) +ue_cell_ded* ue_cell_ded_list::add_cell(uint32_t enb_cc_idx, bool init_pucch) { const enb_cell_common* cell_common = common_list.get_cc_idx(enb_cc_idx); if (cell_common == nullptr) { @@ -202,9 +202,11 @@ ue_cell_ded* ue_cell_ded_list::add_cell(uint32_t enb_cc_idx) cell_list.emplace_back(cell_list.size(), *cell_common); // Allocate CQI, SR, and PUCCH CS resources. If failure, do not add new cell - if (not alloc_cell_resources(ue_cc_idx)) { - rem_last_cell(); - return nullptr; + if (init_pucch) { + if (not alloc_cell_resources(ue_cc_idx)) { + rem_last_cell(); + return nullptr; + } } return &cell_list.back(); @@ -225,6 +227,17 @@ bool ue_cell_ded_list::rem_last_cell() return true; } +bool ue_cell_ded_list::init_pucch_pcell() +{ + if (not alloc_cell_resources(UE_PCELL_CC_IDX)) { + dealloc_sr_resources(); + dealloc_pucch_cs_resources(); + dealloc_cqi_resources(UE_PCELL_CC_IDX); + return false; + } + return true; +} + bool ue_cell_ded_list::alloc_cell_resources(uint32_t ue_cc_idx) { const uint32_t meas_gap_duration = 6; @@ -274,7 +287,7 @@ bool ue_cell_ded_list::alloc_cell_resources(uint32_t ue_cc_idx) } } if (not alloc_cqi_resources(ue_cc_idx, cfg.cqi_cfg.period)) { - logger.error("Failed to allocate CQIresources for cell ue_cc_idx=%d", ue_cc_idx); + logger.error("Failed to allocate CQI resources for cell ue_cc_idx=%d", ue_cc_idx); return false; } @@ -368,7 +381,7 @@ bool ue_cell_ded_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period) // Allocate all CQI resources for all carriers now // Find freq-time resources with least number of users - int i_min = 0, j_min = 0; + int i_min = -1, j_min = -1; uint32_t min_users = std::numeric_limits::max(); for (uint32_t i = 0; i < cfg.sibs[1].sib2().rr_cfg_common.pucch_cfg_common.nrb_cqi; i++) { for (uint32_t j = 0; j < cfg.cqi_cfg.nof_subframes; j++) { @@ -379,7 +392,7 @@ bool ue_cell_ded_list::alloc_cqi_resources(uint32_t ue_cc_idx, uint32_t period) } } } - if (pucch_res->cqi_sched.nof_users[i_min][j_min] > max_users) { + if (pucch_res->cqi_sched.nof_users[i_min][j_min] > max_users || i_min == -1 || j_min == -1) { logger.error("Not enough PUCCH resources to allocate Scheduling Request"); return false; } @@ -469,7 +482,7 @@ bool ue_cell_ded_list::alloc_sr_resources(uint32_t period) uint32_t max_users = 12 * c / delta_pucch_shift; // Find freq-time resources with least number of users - int i_min = 0, j_min = 0; + int i_min = -1, j_min = -1; uint32_t min_users = std::numeric_limits::max(); for (uint32_t i = 0; i < cfg.sr_cfg.nof_prb; i++) { for (uint32_t j = 0; j < cfg.sr_cfg.nof_subframes; j++) { @@ -481,7 +494,7 @@ bool ue_cell_ded_list::alloc_sr_resources(uint32_t period) } } - if (pucch_res->sr_sched.nof_users[i_min][j_min] > max_users) { + if (pucch_res->sr_sched.nof_users[i_min][j_min] > max_users || i_min == -1 || j_min == -1) { logger.error("Not enough PUCCH resources to allocate Scheduling Request"); return false; } diff --git a/srsenb/src/stack/rrc/rrc_endc.cc b/srsenb/src/stack/rrc/rrc_endc.cc index aab608864..32fd1f4ff 100644 --- a/srsenb/src/stack/rrc/rrc_endc.cc +++ b/srsenb/src/stack/rrc/rrc_endc.cc @@ -38,9 +38,18 @@ using namespace asn1::rrc; * rrc_endc class ************************************************************************************************/ -rrc::ue::rrc_endc::rrc_endc(rrc::ue* outer_ue) : - base_t(outer_ue->parent->logger), rrc_ue(outer_ue), rrc_enb(outer_ue->parent), logger(outer_ue->parent->logger) -{} +rrc::ue::rrc_endc::rrc_endc(rrc::ue* outer_ue, const rrc_endc_cfg_t& endc_cfg_) : + base_t(outer_ue->parent->logger), + rrc_ue(outer_ue), + rrc_enb(outer_ue->parent), + logger(outer_ue->parent->logger), + endc_cfg(endc_cfg_) +{ + // start SgNB activation if B1 events are disabled + if (endc_cfg.act_from_b1_event == false) { + start_sgnb_addition(); + } +} //! Method to add NR fields to a RRC Connection Reconfiguration Message bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg) @@ -50,7 +59,7 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn return false; } - if (not is_endc_activation_running()) { + if (not is_endc_activation_running() && endc_cfg.act_from_b1_event) { // add hard-coded measConfig conn_recfg->meas_cfg_present = true; meas_cfg_s& meas_cfg = conn_recfg->meas_cfg; @@ -59,26 +68,16 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn meas_obj_to_add_mod_s meas_obj = {}; meas_obj.meas_obj_id = meas_cfg.meas_obj_to_add_mod_list.size() + 1; - meas_obj.meas_obj.set_meas_obj_eutra(); - meas_obj.meas_obj.meas_obj_eutra().carrier_freq = 300; - meas_obj.meas_obj.meas_obj_eutra().allowed_meas_bw = allowed_meas_bw_opts::mbw50; - meas_obj.meas_obj.meas_obj_eutra().presence_ant_port1 = false; - meas_obj.meas_obj.meas_obj_eutra().neigh_cell_cfg.from_number(0b01); - meas_cfg.meas_obj_to_add_mod_list.push_back(meas_obj); - - meas_obj_to_add_mod_s meas_obj2 = {}; - meas_obj2.meas_obj_id = meas_cfg.meas_obj_to_add_mod_list.size() + 1; - meas_obj2.meas_obj.set_meas_obj_nr_r15(); - meas_obj2.meas_obj.meas_obj_nr_r15().carrier_freq_r15 = 634176; - meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.periodicity_and_offset_r15.set_sf20_r15(); - meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.ssb_dur_r15 = + meas_obj.meas_obj.set_meas_obj_nr_r15(); + meas_obj.meas_obj.meas_obj_nr_r15().carrier_freq_r15 = endc_cfg.nr_dl_arfcn; + meas_obj.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.periodicity_and_offset_r15.set_sf20_r15(); + meas_obj.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.ssb_dur_r15 = asn1::rrc::mtc_ssb_nr_r15_s::ssb_dur_r15_opts::sf1; - meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.subcarrier_spacing_ssb_r15 = - asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz30; - meas_obj2.meas_obj.meas_obj_nr_r15().ext = true; - meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.set_present(true); - meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.get()->set_setup() = 78; - meas_cfg.meas_obj_to_add_mod_list.push_back(meas_obj2); + meas_obj.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.subcarrier_spacing_ssb_r15 = endc_cfg.ssb_ssc; + meas_obj.meas_obj.meas_obj_nr_r15().ext = true; + meas_obj.meas_obj.meas_obj_nr_r15().band_nr_r15.set_present(true); + meas_obj.meas_obj.meas_obj_nr_r15().band_nr_r15.get()->set_setup() = endc_cfg.nr_band; + meas_cfg.meas_obj_to_add_mod_list.push_back(meas_obj); // report config meas_cfg.report_cfg_to_add_mod_list_present = true; @@ -114,8 +113,8 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn // measIdToAddModList meas_cfg.meas_id_to_add_mod_list_present = true; meas_id_to_add_mod_s meas_id = {}; - meas_id.meas_id = meas_obj.meas_obj_id; - meas_id.meas_obj_id = meas_obj2.meas_obj_id; + meas_id.meas_id = meas_cfg.meas_id_to_add_mod_list.size() + 1; + meas_id.meas_obj_id = meas_obj.meas_obj_id; meas_id.report_cfg_id = report_cfg.report_cfg_id; meas_cfg.meas_id_to_add_mod_list.push_back(meas_id); @@ -178,7 +177,7 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn void rrc::ue::rrc_endc::handle_eutra_capabilities(const asn1::rrc::ue_eutra_cap_s& eutra_caps) { // skip any further checks if eNB runs without NR cells - if (rrc_enb->cfg.cell_list_nr.empty()) { + if (rrc_enb->cfg.num_nr_cells == 0) { Debug("Skipping UE capabilities. No NR cell configured."); return; } @@ -252,6 +251,11 @@ void rrc::ue::rrc_endc::handle_ue_meas_report(const meas_report_s& msg) return; } + start_sgnb_addition(); +} + +void rrc::ue::rrc_endc::start_sgnb_addition() +{ // Start EN-DC activation using EPS bearer of EUTRA DRB1 rrc_nr_interface_rrc::sgnb_addition_req_params_t params = {}; params.eps_bearer_id = diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 504746023..db293f141 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -180,9 +180,20 @@ uint16_t rrc::start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& } // Register new user in RRC - add_user(rnti, ue_cfg); + if (add_user(rnti, ue_cfg) != SRSRAN_SUCCESS) { + logger.error("Failed to create user"); + cause.set_radio_network().value = asn1::s1ap::cause_radio_network_opts::no_radio_res_available_in_target_cell; + return SRSRAN_INVALID_RNTI; + } auto it = users.find(rnti); ue* ue_ptr = it->second.get(); + if (not ue_ptr->init_pucch()) { + rem_user(rnti); + logger.warning("Failed to allocate PUCCH resources for rnti=0x%x", rnti); + cause.set_radio_network().value = asn1::s1ap::cause_radio_network_opts::no_radio_res_available_in_target_cell; + return SRSRAN_INVALID_RNTI; + } + // Reset activity timer (Response is not expected) ue_ptr->set_activity_timeout(ue::UE_INACTIVITY_TIMEOUT); ue_ptr->set_activity(false); @@ -225,6 +236,14 @@ bool rrc::ue::rrc_mobility::fill_conn_recfg_no_ho_cmd(asn1::rrc::rrc_conn_recfg_ //! Method called whenever the eNB receives a MeasReport from the UE. In normal situations, an HO procedure is started void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsran::unique_byte_buffer_t pdu) { + asn1::json_writer json_writer; + msg.to_json(json_writer); + event_logger::get().log_measurement_report( + rrc_ue->ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx, + asn1::octstring_to_string(pdu->msg, pdu->N_bytes), + json_writer.to_string(), + rrc_ue->rnti); + if (not is_in_state()) { Info("Received a MeasReport while UE is performing Handover. Ignoring..."); return; @@ -232,12 +251,12 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr // Check if meas_id is valid const meas_results_s& meas_res = msg.crit_exts.c1().meas_report_r8().meas_results; if (not meas_res.meas_result_neigh_cells_present) { - Info("Received a MeasReport, but the UE did not detect any cell."); + Debug("Received a MeasReport, but the UE did not detect any cell."); return; } if (meas_res.meas_result_neigh_cells.type().value != meas_results_s::meas_result_neigh_cells_c_::types::meas_result_list_eutra) { - Error("MeasReports regarding non-EUTRA are not supported!"); + Debug("Skipping non-EUTRA MeasReport."); return; } const meas_id_list& measid_list = rrc_ue->current_ue_cfg.meas_cfg.meas_id_to_add_mod_list; @@ -277,14 +296,6 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr break; } } - - asn1::json_writer json_writer; - msg.to_json(json_writer); - event_logger::get().log_measurement_report( - rrc_ue->ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX)->cell_common->enb_cc_idx, - asn1::octstring_to_string(pdu->msg, pdu->N_bytes), - json_writer.to_string(), - rrc_ue->rnti); } /** @@ -698,7 +709,10 @@ void rrc::ue::rrc_mobility::s1_source_ho_st::handle_ho_cmd(wait_ho_cmd& s, const /* Enter Handover Execution */ // TODO: Do anything with MeasCfg info within the Msg (e.g. update ue_var_meas)? - // Disable DRBs in the MAC, while Reconfiguration is taking place. + // Disable DRBs in the MAC and PDCP, while Reconfiguration is taking place. + for (const drb_to_add_mod_s& drb : rrc_ue->bearer_list.get_established_drbs()) { + rrc_ue->parent->pdcp->set_enabled(rrc_ue->rnti, drb_to_lcid((lte_drb)drb.drb_id), false); + } rrc_ue->mac_ctrl.set_drb_activation(false); rrc_ue->mac_ctrl.update_mac(mac_controller::proc_stage_t::other); @@ -859,11 +873,11 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev& if (ho_req.transparent_container->erab_info_list_present) { const auto& lst = ho_req.transparent_container->erab_info_list; const auto* it = std::find_if( - lst.begin(), - lst.end(), - [&erab](const asn1::s1ap::protocol_ie_single_container_s& fwd_erab) { + lst.begin(), + lst.end(), + [&erab](const asn1::s1ap::protocol_ie_single_container_s& fwd_erab) { return fwd_erab.value.erab_info_list_item().erab_id == erab.second.id; - }); + }); if (it == lst.end()) { continue; } @@ -1042,7 +1056,7 @@ void rrc::ue::rrc_mobility::handle_status_transfer(s1_target_ho_st& s, const sta const auto& drbs = rrc_ue->bearer_list.get_established_drbs(); lte_drb drbid = lte_lcid_to_drb(erab_it->second.lcid); auto drb_it = std::find_if( - drbs.begin(), drbs.end(), [drbid](const drb_to_add_mod_s& drb) { return (lte_drb)drb.drb_id == drbid; }); + drbs.begin(), drbs.end(), [drbid](const drb_to_add_mod_s& drb) { return (lte_drb)drb.drb_id == drbid; }); if (drb_it == drbs.end()) { logger.warning("The DRB id=%d does not exist", drbid); } diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index d6432c725..cc07839ae 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -23,8 +23,10 @@ #include "srsenb/hdr/common/common_enb.h" #include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" #include "srsran/asn1/rrc_nr_utils.h" +#include "srsran/common/band_helper.h" #include "srsran/common/common_nr.h" #include "srsran/common/phy_cfg_nr_default.h" +#include "srsran/common/standard_streams.h" using namespace asn1::rrc_nr; @@ -119,14 +121,6 @@ rrc_nr_cfg_t rrc_nr::update_default_cfg(const rrc_nr_cfg_t& current) cfg_default.mib.dmrs_type_a_position.value = mib_s::dmrs_type_a_position_opts::pos2; cfg_default.mib.sys_frame_num.from_number(0); - cfg_default.cell.nof_prb = 25; - cfg_default.cell.nof_ports = 1; - cfg_default.cell.id = 0; - cfg_default.cell.cp = SRSRAN_CP_NORM; - cfg_default.cell.frame_type = SRSRAN_FDD; - cfg_default.cell.phich_length = SRSRAN_PHICH_NORM; - cfg_default.cell.phich_resources = SRSRAN_PHICH_R_1; - // Fill SIB1 cfg_default.sib1.cell_access_related_info.plmn_id_list.resize(1); cfg_default.sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list.resize(1); @@ -175,16 +169,37 @@ int rrc_nr::add_user(uint16_t rnti) } } +void rrc_nr::rem_user(uint16_t rnti) +{ + auto user_it = users.find(rnti); + if (user_it != users.end()) { + // First remove MAC and GTPU to stop processing DL/UL traffic for this user + mac->remove_ue(rnti); // MAC handles PHY + rlc->rem_user(rnti); + pdcp->rem_user(rnti); + users.erase(rnti); + + srsran::console("Disconnecting rnti=0x%x.\n", rnti); + logger.info("Removed user rnti=0x%x", rnti); + } else { + logger.error("Removing user rnti=0x%x (does not exist)", rnti); + } +} + /* Function called by MAC after the reception of a C-RNTI CE indicating that the UE still has a * valid RNTI. */ int rrc_nr::update_user(uint16_t new_rnti, uint16_t old_rnti) { + if (new_rnti == old_rnti) { + logger.error("rnti=0x%x received MAC CRNTI CE with same rnti"); + return SRSRAN_ERROR; + } + // Remove new_rnti auto new_ue_it = users.find(new_rnti); if (new_ue_it != users.end()) { - // TODO: cleanup new user? - return SRSRAN_ERROR; + task_sched.defer_task([this, new_rnti]() { rem_user(new_rnti); }); } // Send Reconfiguration to old_rnti if is RRC_CONNECT or RRC Release if already released here @@ -201,6 +216,22 @@ int rrc_nr::update_user(uint16_t new_rnti, uint16_t old_rnti) return SRSRAN_SUCCESS; } +void rrc_nr::set_activity_user(uint16_t rnti) +{ + auto it = users.find(rnti); + if (it == users.end()) { + logger.info("rnti=0x%x not found. Can't set activity", rnti); + return; + } + ue* ue_ptr = it->second.get(); + + // inform EUTRA RRC about user activity + if (ue_ptr->is_endc()) { + // inform EUTRA RRC about user activity + rrc_eutra->set_activity_user(ue_ptr->get_eutra_rnti()); + } +} + void rrc_nr::config_phy() { static const srsran::phy_cfg_nr_t default_phy_cfg = @@ -209,6 +240,7 @@ void rrc_nr::config_phy() common_cfg.carrier = default_phy_cfg.carrier; common_cfg.pdcch = default_phy_cfg.pdcch; common_cfg.prach = default_phy_cfg.prach; + common_cfg.duplex_mode = SRSRAN_DUPLEX_MODE_TDD; // TODO: make dynamic if (phy->set_common_cfg(common_cfg) < SRSRAN_SUCCESS) { logger.error("Couldn't set common PHY config"); return; @@ -222,7 +254,7 @@ void rrc_nr::config_mac() std::vector sched_cells_cfg = {srsenb::get_default_cells_cfg(1)}; // FIXME: entire SI configuration, etc needs to be ported to NR - sched_interface::cell_cfg_t cell_cfg; + sched_interface::cell_cfg_t cell_cfg; set_sched_cell_cfg_sib1(&cell_cfg, cfg.sib1); // set SIB length @@ -235,7 +267,7 @@ void rrc_nr::config_mac() logger.info("Allocating %d PRBs for PUCCH", cell_cfg.nrb_pucch); // Copy Cell configuration - cell_cfg.cell = cfg.cell; + // cell_cfg.cell = cfg.cell; // Configure MAC/scheduler mac->cell_cfg(sched_cells_cfg); @@ -399,6 +431,10 @@ int rrc_nr::ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_max { return SRSRAN_SUCCESS; } +int rrc_nr::set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) +{ + return SRSRAN_SUCCESS; +} int rrc_nr::ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) { return SRSRAN_SUCCESS; @@ -407,6 +443,16 @@ int rrc_nr::start_security_mode_procedure(uint16_t rnti) { return SRSRAN_SUCCESS; } +int rrc_nr::establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) +{ + return SRSRAN_SUCCESS; +} + +int rrc_nr::allocate_lcid(uint16_t rnti) +{ + return SRSRAN_SUCCESS; +} + void rrc_nr::write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) {} /******************************************************************************* @@ -456,7 +502,7 @@ int rrc_nr::sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstri Every function in UE class is called from a mutex environment thus does not need extra protection. *******************************************************************************/ -rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_) : parent(parent_), rnti(rnti_) {} +rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_) : parent(parent_), rnti(rnti_), uecfg(srsenb::get_default_ue_cfg(1)) {} void rrc_nr::ue::send_connection_setup() { @@ -503,6 +549,10 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) // Helper for the RRC Reconfiguration sender to pack hard-coded config int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) { + auto& pscell_cfg = parent->cfg.cell_list.at(UE_PSCELL_CC_IDX); + + srsran::srsran_band_helper band_helper; + // RLC for DRB1 (with fixed LCID) cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true; cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1); @@ -556,43 +606,42 @@ int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group // PDCCH config cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg_present = true; auto& pdcch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg; - pdcch_cfg_dedicated.set_setup(); - pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list_present = true; - pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list.resize(1); - pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].ctrl_res_set_id = 2; - pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].freq_domain_res.from_number( + auto& pdcch_ded_setup = pdcch_cfg_dedicated.set_setup(); + pdcch_ded_setup.ctrl_res_set_to_add_mod_list_present = true; + pdcch_ded_setup.ctrl_res_set_to_add_mod_list.resize(1); + pdcch_ded_setup.ctrl_res_set_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_ded_setup.ctrl_res_set_to_add_mod_list[0].freq_domain_res.from_number( 0b111111110000000000000000000000000000000000000); - pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].dur = 1; - pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].cce_reg_map_type.set_non_interleaved(); - pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].precoder_granularity = + pdcch_ded_setup.ctrl_res_set_to_add_mod_list[0].dur = 1; + pdcch_ded_setup.ctrl_res_set_to_add_mod_list[0].cce_reg_map_type.set_non_interleaved(); + pdcch_ded_setup.ctrl_res_set_to_add_mod_list[0].precoder_granularity = asn1::rrc_nr::ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle; // search spaces - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list_present = true; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list.resize(1); - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_id = 2; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id_present = true; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id = 2; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset_present = true; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot_present = true; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot.from_number( - 0b10000000000000); - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates_present = true; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level1 = + pdcch_ded_setup.search_spaces_to_add_mod_list_present = true; + pdcch_ded_setup.search_spaces_to_add_mod_list.resize(1); + pdcch_ded_setup.search_spaces_to_add_mod_list[0].search_space_id = 2; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].ctrl_res_set_id_present = true; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset_present = true; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); + pdcch_ded_setup.search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot_present = true; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot.from_number(0b10000000000000); + pdcch_ded_setup.search_spaces_to_add_mod_list[0].nrof_candidates_present = true; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level1 = asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level1_opts::n0; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level2 = + pdcch_ded_setup.search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level2 = asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level2_opts::n2; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level4 = - asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level8 = + pdcch_ded_setup.search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level4 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n2; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level8 = asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level16 = + pdcch_ded_setup.search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level16 = asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type_present = true; - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.set_ue_specific(); - pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.ue_specific().dci_formats = asn1:: - rrc_nr::search_space_s::search_space_type_c_::ue_specific_s_::dci_formats_opts::formats0_minus0_and_minus1_minus0; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].search_space_type_present = true; + pdcch_ded_setup.search_spaces_to_add_mod_list[0].search_space_type.set_ue_specific(); + pdcch_ded_setup.search_spaces_to_add_mod_list[0].search_space_type.ue_specific().dci_formats = asn1::rrc_nr:: + search_space_s::search_space_type_c_::ue_specific_s_::dci_formats_opts::formats0_minus0_and_minus1_minus0; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg_present = true; auto& pdsch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg; @@ -662,8 +711,8 @@ int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group sr_res1.sched_request_res_id = 1; sr_res1.sched_request_id = 0; sr_res1.periodicity_and_offset_present = true; - sr_res1.periodicity_and_offset.set_sl40(); - sr_res1.res_present = true; + sr_res1.res_present = true; + sr_res1.res = 2; // PUCCH resource for SR // DL data ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; @@ -705,8 +754,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group resource_big, ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list[1], 1)) { parent->logger.warning("Failed to create >2 bit NR PUCCH resource"); } - if (not srsran::make_phy_res_config( - resource_big, ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list[2], 2)) { + if (not srsran::make_phy_res_config(resource_sr, ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list[2], 2)) { parent->logger.warning("Failed to create SR NR PUCCH resource"); } @@ -777,85 +825,61 @@ int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = true; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.set_setup(); - // nzp-CSI-RS Resource - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list_present = true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(1); - auto& nzp_csi_res = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; - nzp_csi_res.nzp_csi_rs_res_id = 0; - nzp_csi_res.res_map.freq_domain_alloc.set_row2(); - nzp_csi_res.res_map.freq_domain_alloc.row2().from_number(0b100000000000); - nzp_csi_res.res_map.nrof_ports = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; - nzp_csi_res.res_map.first_ofdm_symbol_in_time_domain = 4; - nzp_csi_res.res_map.cdm_type = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; - nzp_csi_res.res_map.density.set_one(); - nzp_csi_res.res_map.freq_band.start_rb = 0; - nzp_csi_res.res_map.freq_band.nrof_rbs = 52; - nzp_csi_res.pwr_ctrl_offset = 0; - // Skip pwr_ctrl_offset_ss_present - nzp_csi_res.periodicity_and_offset_present = true; - nzp_csi_res.periodicity_and_offset.set_slots80(); - // optional - nzp_csi_res.qcl_info_periodic_csi_rs_present = true; - nzp_csi_res.qcl_info_periodic_csi_rs = 0; - - // nzp-CSI-RS ResourceSet - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list_present = - true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1); - auto& nzp_csi_res_set = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; - nzp_csi_res_set.nzp_csi_rs_res.resize(1); - // Skip TRS info - - // CSI report config - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list_present = true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list.resize(1); - auto& csi_report = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; - csi_report.report_cfg_id = 0; - csi_report.res_for_ch_meas = 0; - csi_report.csi_im_res_for_interference_present = true; - csi_report.csi_im_res_for_interference = 1; - csi_report.report_cfg_type.set_periodic(); - csi_report.report_cfg_type.periodic().report_slot_cfg.set_slots80(); - csi_report.report_cfg_type.periodic().pucch_csi_res_list.resize(1); - csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].ul_bw_part_id = 0; - csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 0; // was 17 in orig PCAP - csi_report.report_quant.set_cri_ri_pmi_cqi(); - // Report freq config (optional) - csi_report.report_freq_cfg_present = true; - csi_report.report_freq_cfg.cqi_format_ind_present = true; - csi_report.report_freq_cfg.cqi_format_ind = - asn1::rrc_nr::csi_report_cfg_s::report_freq_cfg_s_::cqi_format_ind_opts::wideband_cqi; - csi_report.time_restrict_for_ch_meass = asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_ch_meass_opts::not_cfgured; - csi_report.time_restrict_for_interference_meass = - asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_interference_meass_opts::not_cfgured; - csi_report.group_based_beam_report.set_disabled(); - // Skip CQI table (optional) - csi_report.cqi_table_present = true; - csi_report.cqi_table = asn1::rrc_nr::csi_report_cfg_s::cqi_table_opts::table2; - csi_report.subband_size = asn1::rrc_nr::csi_report_cfg_s::subband_size_opts::value1; + // NOTE: Disable CQI configuration until srsENB NR PHY supports it + // // CSI report config + // cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list_present = + // true; + // cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list.resize(1); + // auto& csi_report = + // cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + // csi_report.report_cfg_id = 0; + // csi_report.res_for_ch_meas = 0; + // csi_report.csi_im_res_for_interference_present = true; + // csi_report.csi_im_res_for_interference = 1; + // csi_report.report_cfg_type.set_periodic(); + // csi_report.report_cfg_type.periodic().report_slot_cfg.set_slots80(); + // csi_report.report_cfg_type.periodic().pucch_csi_res_list.resize(1); + // csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].ul_bw_part_id = 0; + // csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 1; // was 17 in orig PCAP + // csi_report.report_quant.set_cri_ri_pmi_cqi(); + // // Report freq config (optional) + // csi_report.report_freq_cfg_present = true; + // csi_report.report_freq_cfg.cqi_format_ind_present = true; + // csi_report.report_freq_cfg.cqi_format_ind = + // asn1::rrc_nr::csi_report_cfg_s::report_freq_cfg_s_::cqi_format_ind_opts::wideband_cqi; + // csi_report.time_restrict_for_ch_meass = + // asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_ch_meass_opts::not_cfgured; + // csi_report.time_restrict_for_interference_meass = + // asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_interference_meass_opts::not_cfgured; + // csi_report.group_based_beam_report.set_disabled(); + // // Skip CQI table (optional) + // csi_report.cqi_table_present = true; + // csi_report.cqi_table = asn1::rrc_nr::csi_report_cfg_s::cqi_table_opts::table2; + // csi_report.subband_size = asn1::rrc_nr::csi_report_cfg_s::subband_size_opts::value1; // Reconfig with Sync cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = rnti; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.n_timing_advance_offset = asn1::rrc_nr::serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dmrs_type_a_position = asn1::rrc_nr::serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present = true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci = 500; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci = pscell_cfg.phy_cell.carrier.pci; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing_present = true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing = - subcarrier_spacing_opts::khz30; // DL config cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list + .push_back(parent->cfg.cell_list[0].band); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + band_helper.get_abs_freq_point_a_arfcn(parent->cfg.cell_list[0].phy_cell.carrier.nof_prb, + parent->cfg.cell_list[0].dl_arfcn); cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl .absolute_freq_ssb_present = true; @@ -937,6 +961,12 @@ int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.dummy = time_align_timer_opts::ms500; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul.freq_band_list + .push_back(parent->cfg.cell_list[0].band); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul.absolute_freq_point_a = + band_helper.get_abs_freq_point_a_arfcn(parent->cfg.cell_list[0].phy_cell.carrier.nof_prb, + parent->cfg.cell_list[0].ul_arfcn); + ; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul .scs_specific_carrier_list.resize(1); auto& ul_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul @@ -1018,58 +1048,184 @@ int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group // Helper for the RRC Reconfiguration sender to pack hard-coded config int rrc_nr::ue::pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed_secondary_cell_config) { - auto& cell_group_cfg_pack = cell_group_cfg; pack_secondary_cell_group_config_common(cell_group_cfg); - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + uint32_t absolute_freq_ssb; + + if (parent->cfg.cell_list[0].band == 3) { // band n3 + absolute_freq_ssb = 367930; + } else if (parent->cfg.cell_list[0].band == 5) { // band n5 + absolute_freq_ssb = 176210; + } else if (parent->cfg.cell_list[0].band == 7) { // band n7 + absolute_freq_ssb = 529470; + } else { + parent->logger.error("Unsupported dl_arfcn."); + return SRSRAN_ERROR; + } + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; // UL config dedicated - auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; // SR resources - auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; - sr_res1.periodicity_and_offset.sl40() = 4; - sr_res1.res_present = true; - sr_res1.res = 16; // PUCCH resource for SR + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + sr_res1.periodicity_and_offset.set_sl40() = 8; + sr_res1.res = 2; // PUCCH resource for SR // DL data - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(1); ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 4; // nzp-CSI-RS Resource - auto& nzp_csi_res = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; - nzp_csi_res.scrambling_id = 500; - nzp_csi_res.periodicity_and_offset_present = true; - nzp_csi_res.periodicity_and_offset.set_slots80(); - nzp_csi_res.periodicity_and_offset.slots80() = 1; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(5); + auto& nzp_csi_res = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup(); + // item 0 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].nzp_csi_rs_res_id = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.set_row2(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.row2().from_number(0b100000000000); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.density.set_one(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].scrambling_id = parent->cfg.cell_list[0].phy_cell.cell_id; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.slots80() = 1; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[0].qcl_info_periodic_csi_rs = 0; + // item 1 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].nzp_csi_rs_res_id = 1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].scrambling_id = parent->cfg.cell_list[0].phy_cell.cell_id; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].periodicity_and_offset.slots40() = 11; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[1].qcl_info_periodic_csi_rs = 0; + // item 2 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].nzp_csi_rs_res_id = 2; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.first_ofdm_symbol_in_time_domain = 8; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].scrambling_id = parent->cfg.cell_list[0].phy_cell.cell_id; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].periodicity_and_offset.slots40() = 11; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[2].qcl_info_periodic_csi_rs = 0; + // item 3 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].nzp_csi_rs_res_id = 3; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].scrambling_id = parent->cfg.cell_list[0].phy_cell.cell_id; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].periodicity_and_offset.slots40() = 12; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[3].qcl_info_periodic_csi_rs = 0; + // item 4 + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].nzp_csi_rs_res_id = 4; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_domain_alloc.set_row1(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.first_ofdm_symbol_in_time_domain = 8; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.density.set_three(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_band.start_rb = 0; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].scrambling_id = parent->cfg.cell_list[0].phy_cell.cell_id; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset.set_slots40(); + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].periodicity_and_offset.slots40() = 12; + // optional + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.nzp_csi_rs_res_to_add_mod_list[4].qcl_info_periodic_csi_rs = 0; // nzp-CSI-RS ResourceSet - auto& nzp_csi_res_set = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; - nzp_csi_res_set.nzp_csi_res_set_id = 1; - nzp_csi_res_set.nzp_csi_rs_res[0] = 1; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list_present = + true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(2); + auto& nzp_csi_res_set = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup(); + // item 0 + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_res_set_id = 0; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_rs_res.resize(1); + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[0].nzp_csi_rs_res[0] = 0; + // item 1 + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_res_set_id = 1; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res.resize(4); + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[0] = 1; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[1] = 2; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[2] = 3; + nzp_csi_res_set.nzp_csi_rs_res_set_to_add_mod_list[1].nzp_csi_rs_res[3] = 4; + // Skip TRS info + + // CSI IM config + // TODO: add csi im config - // CSI report config - auto& csi_report = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5; + // CSI resource config + // TODO: add csi resource config + + // NOTE: Disable CQI configuration until srsENB NR PHY supports it + // // CSI report config + // auto& csi_report = + // cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + // csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5; // Reconfig with Sync - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = -36; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing = + subcarrier_spacing_opts::khz15; // DL config - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = - 176210; // TODO: calculate from actual DL ARFCN - - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list - .push_back(5); - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = - 175364; // TODO: calculate from actual DL ARFCN + absolute_freq_ssb; // TODO: calculate from actual DL ARFCN // RACH config cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present = @@ -1078,7 +1234,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; rach_cfg_common_pack.set_setup(); - rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 16; + rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 16; // SSB config (optional) cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; @@ -1100,24 +1256,21 @@ int rrc_nr::ue::pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed // Helper for the RRC Reconfiguration sender to pack hard-coded config int rrc_nr::ue::pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed_secondary_cell_config) { - auto& cell_group_cfg_pack = cell_group_cfg; pack_secondary_cell_group_config_common(cell_group_cfg); - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; // UL config dedicated - auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; // SR resources - auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; // SR resources - sr_res1.periodicity_and_offset.sl40() = 7; - sr_res1.res_present = true; - sr_res1.res = 2; // PUCCH resource for SR + sr_res1.periodicity_and_offset.set_sl40() = 8; + sr_res1.res = 2; // PUCCH resource for SR // DL data - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(6); ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 6; ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[1] = 5; @@ -1127,46 +1280,59 @@ int rrc_nr::ue::pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[5] = 4; // nzp-CSI-RS Resource + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(1); auto& nzp_csi_res = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; - nzp_csi_res.scrambling_id = 0; - nzp_csi_res.periodicity_and_offset_present = true; - nzp_csi_res.periodicity_and_offset.set_slots80(); - nzp_csi_res.periodicity_and_offset.slots80() = 0; + nzp_csi_res.nzp_csi_rs_res_id = 0; + nzp_csi_res.res_map.freq_domain_alloc.set_row2(); + nzp_csi_res.res_map.freq_domain_alloc.row2().from_number(0b100000000000); + nzp_csi_res.res_map.nrof_ports = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.res_map.cdm_type = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.res_map.density.set_one(); + nzp_csi_res.res_map.freq_band.start_rb = 0; + nzp_csi_res.res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.scrambling_id = 0; + nzp_csi_res.periodicity_and_offset_present = true; + nzp_csi_res.periodicity_and_offset.set_slots80() = 0; + // optional + nzp_csi_res.qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.qcl_info_periodic_csi_rs = 0; // nzp-CSI-RS ResourceSet + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list_present = + true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1); auto& nzp_csi_res_set = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; nzp_csi_res_set.nzp_csi_res_set_id = 0; + nzp_csi_res_set.nzp_csi_rs_res.resize(1); nzp_csi_res_set.nzp_csi_rs_res[0] = 0; // Skip TRS info - // CSI report config - auto& csi_report = - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 8; + // NOTE: Disable CQI configuration until srsENB NR PHY supports it + // // CSI report config + // auto& csi_report = + // cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + // csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 7; // Reconfig with Sync cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); - - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing = + subcarrier_spacing_opts::khz30; // DL config - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = 634176; // TODO: calculate from actual DL ARFCN - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list - .push_back(78); - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = - 633928; // TODO: calculate from actual DL ARFCN - auto& pdcch_cfg_common = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common; pdcch_cfg_common.set_setup(); - pdcch_cfg_common.setup().ext = false; - + pdcch_cfg_common.setup().ext = false; // RACH config cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present = @@ -1175,7 +1341,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; rach_cfg_common_pack.set_setup(); - rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0; + rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0; // SSB config (optional) cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; @@ -1213,9 +1379,17 @@ int rrc_nr::ue::pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfi // add secondary cell group config recfg_ies.secondary_cell_group_present = true; - if (pack_secondary_cell_group_config_tdd(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { - parent->logger.error("Failed to pack TDD RRC Reconfiguration"); - return SRSRAN_ERROR; + + if (parent->cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { + if (pack_secondary_cell_group_config_fdd(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack TDD RRC Reconfiguration"); + return SRSRAN_ERROR; + } + } else { + if (pack_secondary_cell_group_config_tdd(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack TDD RRC Reconfiguration"); + return SRSRAN_ERROR; + } } // now pack .. @@ -1297,6 +1471,12 @@ void rrc_nr::ue::crnti_ce_received() if (endc) { // send SgNB addition complete for ENDC users parent->rrc_eutra->sgnb_addition_complete(eutra_rnti, rnti); + + // Add DRB1 to MAC + for (auto& drb : cell_group_cfg.rlc_bearer_to_add_mod_list) { + uecfg.ue_bearers[drb.lc_ch_id].direction = mac_lc_ch_cfg_t::BOTH; + } + parent->mac->ue_cfg(rnti, uecfg); } } @@ -1377,6 +1557,8 @@ int rrc_nr::ue::add_drb() srsran::pdcp_config_t pdcp_cnfg = srsran::make_drb_pdcp_config_t(drb_item.drb_id, false, drb_item.pdcp_cfg); parent->pdcp->add_bearer(rnti, rlc.lc_ch_id, pdcp_cnfg); + // Note: DRB1 is only activated in the MAC when the C-RNTI CE is received + return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index e20f8c6d1..99a4073a6 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -56,10 +56,16 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_, const sched_interface::ue_cfg_t& sch rrc::ue::~ue() {} +bool rrc::ue::init_pucch() +{ + // Allocate PUCCH resources for PCell + return ue_cell_list.init_pucch_pcell(); +} + int rrc::ue::init() { - // Allocate cell and PUCCH resources - if (ue_cell_list.add_cell(mac_ctrl.get_ue_sched_cfg().supported_cc_list[0].enb_cc_idx) == nullptr) { + // Allocate cell (PUCCH resources are not allocated here) + if (ue_cell_list.add_cell(mac_ctrl.get_ue_sched_cfg().supported_cc_list[0].enb_cc_idx, false) == nullptr) { return SRSRAN_ERROR; } @@ -90,7 +96,8 @@ int rrc::ue::init() mobility_handler = make_rnti_obj(rnti, this); if (parent->rrc_nr != nullptr) { - endc_handler = make_rnti_obj(rnti, this); + rrc::ue::rrc_endc::rrc_endc_cfg_t endc_cfg = {}; // TODO: set or derive parameter in eNB config + endc_handler = make_rnti_obj(rnti, this, endc_cfg); } return SRSRAN_SUCCESS; @@ -386,8 +393,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) break; case ul_dcch_msg_type_c::c1_c_::types::ue_cap_info: if (handle_ue_cap_info(&ul_dcch_msg.msg.c1().ue_cap_info()) == SRSRAN_SUCCESS) { - if (not parent->cfg.cell_list_nr.empty() && endc_handler->is_endc_supported() && - state == RRC_STATE_WAIT_FOR_UE_CAP_INFO) { + if (endc_handler != nullptr && endc_handler->is_endc_supported() && state == RRC_STATE_WAIT_FOR_UE_CAP_INFO) { // request EUTRA-NR and NR capabilities as well send_ue_cap_enquiry({asn1::rrc::rat_type_opts::options::eutra_nr, asn1::rrc::rat_type_opts::options::nr}); state = RRC_STATE_WAIT_FOR_UE_CAP_INFO_ENDC; // avoid endless loop @@ -446,6 +452,13 @@ void rrc::ue::handle_rrc_con_req(rrc_conn_request_s* msg) return; } + // Allocate PUCCH resources and reject if not available + if (not init_pucch()) { + parent->logger.warning("Could not allocate PUCCH resources for rnti=0x%x. Sending Connection Reject", rnti); + send_connection_reject(procedure_result_code::fail_in_radio_interface_proc); + return; + } + rrc_conn_request_r8_ies_s* msg_r8 = &msg->crit_exts.rrc_conn_request_r8(); if (msg_r8->ue_id.type() == init_ue_id_c::types::s_tmsi) { @@ -482,7 +495,10 @@ void rrc::ue::send_connection_setup() rr_cfg_ded_s& rr_cfg = setup_r8.rr_cfg_ded; // Fill RR config dedicated - fill_rr_cfg_ded_setup(rr_cfg, parent->cfg, ue_cell_list); + if (fill_rr_cfg_ded_setup(rr_cfg, parent->cfg, ue_cell_list)) { + parent->logger.error("Generating ConnectionSetup. Aborting"); + return; + } // Apply ConnectionSetup Configuration to MAC scheduler mac_ctrl.handle_con_setup(setup_r8); @@ -603,6 +619,14 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg) srsran::console("RRCReestablishmentReject for rnti=0x%x. Cause: MME not connected.\n", rnti); return; } + + // Allocate PUCCH resources and reject if not available + if (not init_pucch()) { + parent->logger.warning("Could not allocate PUCCH resources for rnti=0x%x. Sending RRCReestablishmentReject", rnti); + send_connection_reest_rej(procedure_result_code::fail_in_radio_interface_proc); + return; + } + parent->logger.debug("rnti=0x%x, phyid=0x%x, smac=0x%x, cause=%s", (uint32_t)msg->crit_exts.rrc_conn_reest_request_r8().ue_id.c_rnti.to_number(), msg->crit_exts.rrc_conn_reest_request_r8().ue_id.pci, @@ -701,7 +725,10 @@ void rrc::ue::send_connection_reest(uint8_t ncc) rr_cfg_ded_s& rr_cfg = reest_r8.rr_cfg_ded; // Fill RR config dedicated - fill_rr_cfg_ded_setup(rr_cfg, parent->cfg, ue_cell_list); + if (fill_rr_cfg_ded_setup(rr_cfg, parent->cfg, ue_cell_list)) { + parent->logger.error("Generating ConnectionReestablishment. Aborting..."); + return; + } // Set NCC reest_r8.next_hop_chaining_count = ncc; @@ -808,8 +835,11 @@ void rrc::ue::send_connection_reconf(srsran::unique_byte_buffer_t pdu, rrc_conn_recfg_r8_ies_s& recfg_r8 = rrc_conn_recfg.crit_exts.set_c1().set_rrc_conn_recfg_r8(); // Fill RR Config Ded and SCells - apply_reconf_updates( - recfg_r8, current_ue_cfg, parent->cfg, ue_cell_list, bearer_list, ue_capabilities, phy_cfg_updated); + if (apply_reconf_updates( + recfg_r8, current_ue_cfg, parent->cfg, ue_cell_list, bearer_list, ue_capabilities, phy_cfg_updated)) { + parent->logger.error("Generating ConnectionReconfiguration. Aborting..."); + return; + } // Add measConfig if (mobility_handler != nullptr) { diff --git a/srsenb/src/stack/rrc/ue_meas_cfg.cc b/srsenb/src/stack/rrc/ue_meas_cfg.cc index b5b2900de..6427e8979 100644 --- a/srsenb/src/stack/rrc/ue_meas_cfg.cc +++ b/srsenb/src/stack/rrc/ue_meas_cfg.cc @@ -360,11 +360,12 @@ bool fill_meascfg_enb_cfg(meas_cfg_s& meascfg, const ue_cell_ded_list& ue_cell_l meascfg.quant_cfg.quant_cfg_eutra = pcell_meascfg.quant_cfg; // Insert all measIds - // TODO: add this to the parser + // TODO: add this to the parser. Now we combine all reports with all objects if (meascfg.report_cfg_to_add_mod_list.size() > 0) { for (const auto& measobj : meascfg.meas_obj_to_add_mod_list) { - add_measid_cfg( - meascfg.meas_id_to_add_mod_list, measobj.meas_obj_id, meascfg.report_cfg_to_add_mod_list[0].report_cfg_id); + for (const auto& measrep : meascfg.report_cfg_to_add_mod_list) { + add_measid_cfg(meascfg.meas_id_to_add_mod_list, measobj.meas_obj_id, measrep.report_cfg_id); + } } } diff --git a/srsenb/src/stack/rrc/ue_rr_cfg.cc b/srsenb/src/stack/rrc/ue_rr_cfg.cc index 6df72d286..93d8c1ee2 100644 --- a/srsenb/src/stack/rrc/ue_rr_cfg.cc +++ b/srsenb/src/stack/rrc/ue_rr_cfg.cc @@ -75,11 +75,17 @@ void fill_srbs_reconf(srb_to_add_mod_list_l& srbs, const srb_to_add_mod_list_l& * SR Config *****************************/ -void fill_sr_cfg_setup(sched_request_cfg_c& sr_cfg, const ue_cell_ded_list& ue_cell_list) +int fill_sr_cfg_setup(sched_request_cfg_c& sr_cfg, const ue_cell_ded_list& ue_cell_list) { - auto& setup = sr_cfg.setup(); - setup.sr_cfg_idx = ue_cell_list.get_sr_res()->sr_I; - setup.sr_pucch_res_idx = ue_cell_list.get_sr_res()->sr_N_pucch; + if (ue_cell_list.get_sr_res()) { + auto& setup = sr_cfg.setup(); + setup.sr_cfg_idx = ue_cell_list.get_sr_res()->sr_I; + setup.sr_pucch_res_idx = ue_cell_list.get_sr_res()->sr_N_pucch; + return SRSRAN_SUCCESS; + } else { + srslog::fetch_basic_logger("RRC").error("SR resource is not configured."); + return SRSRAN_ERROR; + } } /****************************** @@ -161,11 +167,11 @@ int fill_cqi_report_setup(cqi_report_cfg_s& cqi_rep, const rrc_cfg_t& enb_cfg, c return SRSRAN_SUCCESS; } -void fill_cqi_report_reconf(cqi_report_cfg_s& cqi_rep, const rrc_cfg_t& enb_cfg, const ue_cell_ded_list& ue_cell_list) +int fill_cqi_report_reconf(cqi_report_cfg_s& cqi_rep, const rrc_cfg_t& enb_cfg, const ue_cell_ded_list& ue_cell_list) { // Get RRC setup CQI config if (fill_cqi_report_setup(cqi_rep, enb_cfg, ue_cell_list) == SRSRAN_ERROR) { - return; + return SRSRAN_ERROR; } if (cqi_rep.cqi_report_mode_aperiodic_present) { @@ -189,9 +195,11 @@ void fill_cqi_report_reconf(cqi_report_cfg_s& cqi_rep, const rrc_cfg_t& enb_cfg, cqi_setup.ri_cfg_idx = ri_idx; } else { srslog::fetch_basic_logger("RRC").warning("Warning: Configured wrong M_ri parameter."); + return SRSRAN_ERROR; } } } + return SRSRAN_SUCCESS; } /****************************** @@ -240,26 +248,33 @@ void fill_phy_cfg_ded_enb_cfg(phys_cfg_ded_s& phy_cfg, const rrc_cfg_t& enb_cfg) fill_cqi_report_enb_cfg(phy_cfg.cqi_report_cfg, enb_cfg); } -void fill_phy_cfg_ded_setup(phys_cfg_ded_s& phy_cfg, const rrc_cfg_t& enb_cfg, const ue_cell_ded_list& ue_cell_list) +int fill_phy_cfg_ded_setup(phys_cfg_ded_s& phy_cfg, const rrc_cfg_t& enb_cfg, const ue_cell_ded_list& ue_cell_list) { // Set PHYConfigDedicated base fill_phy_cfg_ded_enb_cfg(phy_cfg, enb_cfg); // Setup SR PUCCH config - fill_sr_cfg_setup(phy_cfg.sched_request_cfg, ue_cell_list); + if (fill_sr_cfg_setup(phy_cfg.sched_request_cfg, ue_cell_list)) { + return SRSRAN_ERROR; + } // Setup CQI PUCCH config - fill_cqi_report_setup(phy_cfg.cqi_report_cfg, enb_cfg, ue_cell_list); + if (fill_cqi_report_setup(phy_cfg.cqi_report_cfg, enb_cfg, ue_cell_list)) { + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } /// Fills ASN1 PhysicalConfigurationDedicated struct with eNB config params at RRCReconf -void fill_phy_cfg_ded_reconf(phys_cfg_ded_s& phy_cfg, - const rrc_cfg_t& enb_cfg, - const ue_cell_ded_list& ue_cell_list, - const srsran::rrc_ue_capabilities_t& ue_caps) +int fill_phy_cfg_ded_reconf(phys_cfg_ded_s& phy_cfg, + const rrc_cfg_t& enb_cfg, + const ue_cell_ded_list& ue_cell_list, + const srsran::rrc_ue_capabilities_t& ue_caps) { // Use RRCSetup as starting point - fill_phy_cfg_ded_setup(phy_cfg, enb_cfg, ue_cell_list); + if (fill_phy_cfg_ded_setup(phy_cfg, enb_cfg, ue_cell_list)) { + return SRSRAN_ERROR; + } // Antenna Configuration ant_info_ded_s& ant_info = phy_cfg.ant_info.explicit_value(); @@ -276,6 +291,7 @@ void fill_phy_cfg_ded_reconf(phys_cfg_ded_s& phy_cfg, phy_cfg.cqi_report_cfg_pcell_v1250->alt_cqi_table_r12.value = cqi_report_cfg_v1250_s::alt_cqi_table_r12_opts::all_sfs; } + return SRSRAN_SUCCESS; } /*********************************** @@ -305,9 +321,9 @@ void fill_rr_cfg_ded_enb_cfg(asn1::rrc::rr_cfg_ded_s& rr_cfg, const rrc_cfg_t& e rr_cfg.sps_cfg_present = false; } -void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, - const rrc_cfg_t& enb_cfg, - const ue_cell_ded_list& ue_cell_list) +int fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, + const rrc_cfg_t& enb_cfg, + const ue_cell_ded_list& ue_cell_list) { // Establish default enb config fill_rr_cfg_ded_enb_cfg(rr_cfg, enb_cfg); @@ -318,16 +334,16 @@ void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, // Setup SR/CQI configs rr_cfg.phys_cfg_ded_present = true; - fill_phy_cfg_ded_setup(rr_cfg.phys_cfg_ded, enb_cfg, ue_cell_list); + return fill_phy_cfg_ded_setup(rr_cfg.phys_cfg_ded, enb_cfg, ue_cell_list); } -void fill_rr_cfg_ded_reconf(asn1::rrc::rr_cfg_ded_s& rr_cfg, - const rr_cfg_ded_s& current_rr_cfg, - const rrc_cfg_t& enb_cfg, - const ue_cell_ded_list& ue_cell_list, - const bearer_cfg_handler& bearers, - const srsran::rrc_ue_capabilities_t& ue_caps, - bool phy_cfg_updated) +int fill_rr_cfg_ded_reconf(asn1::rrc::rr_cfg_ded_s& rr_cfg, + const rr_cfg_ded_s& current_rr_cfg, + const rrc_cfg_t& enb_cfg, + const ue_cell_ded_list& ue_cell_list, + const bearer_cfg_handler& bearers, + const srsran::rrc_ue_capabilities_t& ue_caps, + bool phy_cfg_updated) { // (Re)establish SRBs fill_srbs_reconf(rr_cfg.srb_to_add_mod_list, current_rr_cfg.srb_to_add_mod_list, enb_cfg); @@ -344,8 +360,9 @@ void fill_rr_cfg_ded_reconf(asn1::rrc::rr_cfg_ded_s& rr_cfg, // PhysCfgDed update needed if (phy_cfg_updated) { rr_cfg.phys_cfg_ded_present = true; - fill_phy_cfg_ded_reconf(rr_cfg.phys_cfg_ded, enb_cfg, ue_cell_list, ue_caps); + return fill_phy_cfg_ded_reconf(rr_cfg.phys_cfg_ded, enb_cfg, ue_cell_list, ue_caps); } + return SRSRAN_SUCCESS; } /** @@ -569,18 +586,20 @@ void apply_scells_to_add_diff(asn1::rrc::scell_to_add_mod_list_r10_l& current_sc **********************************/ /// Apply Reconf updates and update current state -void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, - ue_var_cfg_t& current_ue_cfg, - const rrc_cfg_t& enb_cfg, - const ue_cell_ded_list& ue_cell_list, - bearer_cfg_handler& bearers, - const srsran::rrc_ue_capabilities_t& ue_caps, - bool phy_cfg_updated) +int apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, + ue_var_cfg_t& current_ue_cfg, + const rrc_cfg_t& enb_cfg, + const ue_cell_ded_list& ue_cell_list, + bearer_cfg_handler& bearers, + const srsran::rrc_ue_capabilities_t& ue_caps, + bool phy_cfg_updated) { // Compute pending updates and fill reconf msg recfg_r8.rr_cfg_ded_present = true; - fill_rr_cfg_ded_reconf( - recfg_r8.rr_cfg_ded, current_ue_cfg.rr_cfg, enb_cfg, ue_cell_list, bearers, ue_caps, phy_cfg_updated); + if (fill_rr_cfg_ded_reconf( + recfg_r8.rr_cfg_ded, current_ue_cfg.rr_cfg, enb_cfg, ue_cell_list, bearers, ue_caps, phy_cfg_updated)) { + return SRSRAN_ERROR; + } fill_scells_reconf(recfg_r8, current_ue_cfg.scells, enb_cfg, ue_cell_list, ue_caps); recfg_r8.meas_cfg_present |= recfg_r8.meas_cfg.meas_gap_cfg_present; @@ -590,6 +609,7 @@ void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, // Update current rr_cfg_ded and scells state apply_rr_cfg_ded_diff(current_ue_cfg.rr_cfg, recfg_r8.rr_cfg_ded); apply_scells_to_add_diff(current_ue_cfg.scells, recfg_r8); + return SRSRAN_SUCCESS; } } // namespace srsenb diff --git a/srsenb/src/stack/upper/CMakeLists.txt b/srsenb/src/stack/upper/CMakeLists.txt index 70c4e1b5c..13d222aec 100644 --- a/srsenb/src/stack/upper/CMakeLists.txt +++ b/srsenb/src/stack/upper/CMakeLists.txt @@ -22,5 +22,5 @@ set(SOURCES gtpu.cc pdcp.cc rlc.cc) add_library(srsenb_upper STATIC ${SOURCES}) target_link_libraries(srsenb_upper srsran_asn1 srsran_gtpu) -set(SOURCES pdcp_nr.cc rlc_nr.cc sdap.cc) -add_library(srsgnb_upper STATIC ${SOURCES}) +set(SOURCES sdap.cc) +add_library(srsgnb_upper STATIC ${SOURCES}) \ No newline at end of file diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index bfc4a59c9..2a860465b 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -485,11 +485,15 @@ void gtpu::send_pdu_to_tunnel(const gtpu_tunnel& tx_tun, srsran::unique_byte_buf } } -srsran::expected -gtpu::add_bearer(uint16_t rnti, uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, const bearer_props* props) +srsran::expected gtpu::add_bearer(uint16_t rnti, + uint32_t eps_bearer_id, + uint32_t addr_out, + uint32_t teid_out, + uint32_t& addr_in, + const bearer_props* props) { // Allocate a TEID for the incoming tunnel - const gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, eps_bearer_id, teid_out, addr); + const gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, eps_bearer_id, teid_out, addr_out); if (new_tun == nullptr) { return default_error_t(); } @@ -513,6 +517,13 @@ gtpu::add_bearer(uint16_t rnti, uint32_t eps_bearer_id, uint32_t addr, uint32_t } } + // Return bind address for S1AP and NGAP setup + struct in_addr inaddr; + if ((inet_pton(AF_INET, gtp_bind_addr.c_str(), &inaddr)) < 1) { + logger.error("Invalid address or failure during conversion: %s\n", gtp_bind_addr.c_str()); + } + addr_in = ntohl(inaddr.s_addr); + return teid_in; } diff --git a/srsenb/src/stack/upper/pdcp.cc b/srsenb/src/stack/upper/pdcp.cc index d0342a7a4..83b62c995 100644 --- a/srsenb/src/stack/upper/pdcp.cc +++ b/srsenb/src/stack/upper/pdcp.cc @@ -95,6 +95,13 @@ void pdcp::del_bearer(uint16_t rnti, uint32_t lcid) } } +void pdcp::set_enabled(uint16_t rnti, uint32_t lcid, bool enabled) +{ + if (users.count(rnti)) { + users[rnti].pdcp->set_enabled(lcid, enabled); + } +} + void pdcp::reset(uint16_t rnti) { if (users.count(rnti)) { diff --git a/srsenb/src/stack/upper/pdcp_nr.cc b/srsenb/src/stack/upper/pdcp_nr.cc deleted file mode 100644 index a9fc86472..000000000 --- a/srsenb/src/stack/upper/pdcp_nr.cc +++ /dev/null @@ -1,189 +0,0 @@ -/** - * Copyright 2013-2021 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include "srsenb/hdr/stack/upper/pdcp_nr.h" -#include "srsenb/hdr/common/common_enb.h" - -namespace srsenb { - -pdcp_nr::pdcp_nr(srsran::task_sched_handle task_sched_, const char* logname) : - task_sched(task_sched_), logger(srslog::fetch_basic_logger(logname)) -{} - -void pdcp_nr::init(const pdcp_nr_args_t& args_, - rlc_interface_pdcp_nr* rlc_, - rrc_interface_pdcp_nr* rrc_, - sdap_interface_pdcp_nr* sdap_) -{ - m_args = args_; - m_rlc = rlc_; - m_rrc = rrc_; - m_sdap = sdap_; - - logger.set_level(srslog::str_to_basic_level(m_args.log_level)); - logger.set_hex_dump_max_size(m_args.log_hex_limit); -} - -void pdcp_nr::stop() -{ - for (auto& user : users) { - user.second.pdcp->stop(); - } - users.clear(); -} - -void pdcp_nr::add_user(uint16_t rnti) -{ - if (users.count(rnti) == 0) { - users[rnti].pdcp.reset(new srsran::pdcp(task_sched, "PDCP")); - users[rnti].rlc_itf.rnti = rnti; - users[rnti].sdap_itf.rnti = rnti; - users[rnti].rrc_itf.rnti = rnti; - users[rnti].rlc_itf.rlc = m_rlc; - users[rnti].rrc_itf.rrc = m_rrc; - users[rnti].sdap_itf.sdap = m_sdap; - users[rnti].pdcp->init(&users[rnti].rlc_itf, &users[rnti].rrc_itf, &users[rnti].sdap_itf); - } -} - -void pdcp_nr::rem_user(uint16_t rnti) -{ - users.erase(rnti); -} - -void pdcp_nr::add_bearer(uint16_t rnti, uint32_t lcid, srsran::pdcp_config_t cfg) -{ - if (users.count(rnti)) { - users[rnti].pdcp->add_bearer(lcid, cfg); - } -} - -void pdcp_nr::reset(uint16_t rnti) -{ - if (users.count(rnti)) { - users[rnti].pdcp->reset(); - } -} - -void pdcp_nr::config_security(uint16_t rnti, uint32_t lcid, srsran::as_security_config_t sec_cfg) -{ - if (users.count(rnti)) { - users[rnti].pdcp->config_security(lcid, sec_cfg); - } -} - -void pdcp_nr::enable_integrity(uint16_t rnti, uint32_t lcid) -{ - users[rnti].pdcp->enable_integrity(lcid, srsran::DIRECTION_TXRX); -} - -void pdcp_nr::enable_encryption(uint16_t rnti, uint32_t lcid) -{ - users[rnti].pdcp->enable_encryption(lcid, srsran::DIRECTION_TXRX); -} - -void pdcp_nr::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) -{ - if (users.count(rnti)) { - users[rnti].pdcp->write_pdu(lcid, std::move(sdu)); - } else { - logger.error("Can't write PDU. RNTI=0x%X doesn't exist.", rnti); - } -} - -void pdcp_nr::notify_delivery(uint16_t rnti, uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) -{ - if (users.count(rnti)) { - users[rnti].pdcp->notify_delivery(lcid, pdcp_sns); - } else { - logger.error("Can't notify Ack of PDU. RNTI=0x%X doesn't exist.", rnti); - } -} - -void pdcp_nr::notify_failure(uint16_t rnti, uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) -{ - if (users.count(rnti)) { - users[rnti].pdcp->notify_failure(lcid, pdcp_sns); - } else { - logger.error("Can't notify Ack of PDU. RNTI=0x%X doesn't exist.", rnti); - } -} - -void pdcp_nr::write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) -{ - if (users.count(rnti)) { - users[rnti].pdcp->write_sdu(lcid, std::move(sdu)); - } else { - logger.error("Can't write SDU. RNTI=0x%X doesn't exist.", rnti); - } -} - -void pdcp_nr::user_interface_sdap::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) -{ - sdap->write_pdu(rnti, lcid, std::move(pdu)); -} - -void pdcp_nr::user_interface_rlc::write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) -{ - rlc->write_sdu(rnti, lcid, std::move(sdu)); -} - -void pdcp_nr::user_interface_rlc::discard_sdu(uint32_t lcid, uint32_t discard_sn) -{ - fprintf(stderr, "discard_sdu method not implemented.\n"); -} - -bool pdcp_nr::user_interface_rlc::rb_is_um(uint32_t lcid) -{ - return rlc->rb_is_um(rnti, lcid); -} - -bool pdcp_nr::user_interface_rlc::sdu_queue_is_full(uint32_t lcid) -{ - return rlc->sdu_queue_is_full(rnti, lcid); -} - -void pdcp_nr::user_interface_rrc::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu) -{ - rrc->write_pdu(rnti, lcid, std::move(pdu)); -} - -void pdcp_nr::user_interface_rrc::write_pdu_bcch_bch(srsran::unique_byte_buffer_t pdu) -{ - ERROR("Error: Received BCCH from ue=%d", rnti); -} - -void pdcp_nr::user_interface_rrc::write_pdu_bcch_dlsch(srsran::unique_byte_buffer_t pdu) -{ - ERROR("Error: Received BCCH from ue=%d", rnti); -} - -void pdcp_nr::user_interface_rrc::write_pdu_pcch(srsran::unique_byte_buffer_t pdu) -{ - ERROR("Error: Received PCCH from ue=%d", rnti); -} - -const char* pdcp_nr::user_interface_rrc::get_rb_name(uint32_t lcid) -{ - return srsenb::get_rb_name(lcid); -} - -} // namespace srsenb diff --git a/srsenb/src/stack/upper/rlc_nr.cc b/srsenb/src/stack/upper/rlc_nr.cc deleted file mode 100644 index 46e6514c4..000000000 --- a/srsenb/src/stack/upper/rlc_nr.cc +++ /dev/null @@ -1,233 +0,0 @@ -/** - * Copyright 2013-2021 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include "srsenb/hdr/stack/upper/rlc_nr.h" -#include "srsran/common/common_nr.h" -namespace srsenb { - -rlc_nr::rlc_nr(const char* logname) : logger(srslog::fetch_basic_logger(logname)) {} - -void rlc_nr::init(pdcp_interface_rlc_nr* pdcp_, - rrc_interface_rlc_nr* rrc_, - mac_interface_rlc_nr* mac_, - srsran::timer_handler* timers_) -{ - m_pdcp = pdcp_; - m_rrc = rrc_; - m_mac = mac_; - timers = timers_; -} - -void rlc_nr::stop() -{ - for (auto& user : users) { - user.second.m_rlc->stop(); - } - users.clear(); -} - -void rlc_nr::add_user(uint16_t rnti) -{ - if (users.count(rnti) == 0) { - user_interface user_itf; - user_itf.rnti = rnti; - user_itf.m_pdcp = m_pdcp; - user_itf.m_rrc = m_rrc; - user_itf.parent = this; - user_itf.m_rlc.reset(new srsran::rlc(logger.id().c_str())); - users[rnti] = std::move(user_itf); - users[rnti].m_rlc->init(&users[rnti], &users[rnti], timers, (int)srsran::nr_srb::srb0); - } -} - -void rlc_nr::rem_user(uint16_t rnti) -{ - if (users.count(rnti)) { - users[rnti].m_rlc->stop(); - users.erase(rnti); - } else { - logger.error("Removing rnti=0x%x. Already removed", rnti); - } -} - -void rlc_nr::clear_buffer(uint16_t rnti) -{ - if (users.count(rnti)) { - users[rnti].m_rlc->empty_queue(); - for (int i = 0; i < SRSRAN_N_RADIO_BEARERS; i++) { - m_mac->rlc_buffer_state(rnti, i, 0, 0); - } - logger.info("Cleared buffer rnti=0x%x", rnti); - } -} - -void rlc_nr::add_bearer(uint16_t rnti, uint32_t lcid, srsran::rlc_config_t cnfg) -{ - if (users.count(rnti)) { - users[rnti].m_rlc->add_bearer(lcid, cnfg); - } -} - -void rlc_nr::add_bearer_mrb(uint16_t rnti, uint32_t lcid) -{ - if (users.count(rnti)) { - users[rnti].m_rlc->add_bearer_mrb(lcid); - } -} - -void rlc_nr::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) -{ - m_rrc->read_pdu_pcch(payload, buffer_size); -} - -int rlc_nr::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) -{ - int ret; - uint32_t tx_queue; - - if (users.count(rnti)) { - if (rnti != SRSRAN_MRNTI) { - ret = users[rnti].m_rlc->read_pdu(lcid, payload, nof_bytes); - tx_queue = users[rnti].m_rlc->get_buffer_state(lcid); - } else { - ret = users[rnti].m_rlc->read_pdu_mch(lcid, payload, nof_bytes); - tx_queue = users[rnti].m_rlc->get_total_mch_buffer_state(lcid); - } - // In the eNodeB, there is no polling for buffer state from the scheduler, thus - // communicate buffer state every time a PDU is read - - uint32_t retx_queue = 0; - logger.debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d", rnti, lcid, tx_queue); - m_mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); - } else { - ret = SRSRAN_ERROR; - } - return ret; -} - -void rlc_nr::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) -{ - if (users.count(rnti)) { - users[rnti].m_rlc->write_pdu(lcid, payload, nof_bytes); - - // In the eNodeB, there is no polling for buffer state from the scheduler, thus - // communicate buffer state every time a new PDU is written - uint32_t tx_queue = users[rnti].m_rlc->get_buffer_state(lcid); - uint32_t retx_queue = 0; - logger.debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d", rnti, lcid, tx_queue); - m_mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); - } -} - -// void rlc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload) -//{ -// // RLC is transparent for BCCH -// m_rrc->read_pdu_bcch_dlsch(sib_index, payload); -//} - -void rlc_nr::write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) -{ - uint32_t tx_queue; - - if (users.count(rnti)) { - if (rnti != SRSRAN_MRNTI) { - users[rnti].m_rlc->write_sdu(lcid, std::move(sdu)); - tx_queue = users[rnti].m_rlc->get_buffer_state(lcid); - } else { - users[rnti].m_rlc->write_sdu_mch(lcid, std::move(sdu)); - tx_queue = users[rnti].m_rlc->get_total_mch_buffer_state(lcid); - } - // In the eNodeB, there is no polling for buffer state from the scheduler, thus - // communicate buffer state every time a new SDU is written - - uint32_t retx_queue = 0; - m_mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); - logger.info("Buffer state: rnti=0x%x, lcid=%d, tx_queue=%d", rnti, lcid, tx_queue); - } -} - -bool rlc_nr::rb_is_um(uint16_t rnti, uint32_t lcid) -{ - bool ret = false; - if (users.count(rnti)) { - ret = users[rnti].m_rlc->rb_is_um(lcid); - } - return ret; -} - -bool rlc_nr::sdu_queue_is_full(uint16_t rnti, uint32_t lcid) -{ - bool ret = false; - if (users.count(rnti)) { - ret = users[rnti].m_rlc->sdu_queue_is_full(lcid); - } - return ret; -} -void rlc_nr::user_interface::max_retx_attempted() -{ - m_rrc->max_retx_attempted(rnti); -} - -void rlc_nr::user_interface::protocol_failure() -{ - m_rrc->protocol_failure(rnti); -} - -void rlc_nr::user_interface::write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) -{ - if (lcid == (int)srsran::nr_srb::srb0) { - m_rrc->write_pdu(rnti, lcid, std::move(sdu)); - } else { - m_pdcp->write_pdu(rnti, lcid, std::move(sdu)); - } -} - -void rlc_nr::user_interface::write_pdu_bcch_bch(srsran::unique_byte_buffer_t sdu) -{ - ERROR("Error: Received BCCH from ue=%d", rnti); -} - -void rlc_nr::user_interface::write_pdu_bcch_dlsch(srsran::unique_byte_buffer_t sdu) -{ - ERROR("Error: Received BCCH from ue=%d", rnti); -} - -void rlc_nr::user_interface::write_pdu_pcch(srsran::unique_byte_buffer_t sdu) -{ - ERROR("Error: Received PCCH from ue=%d", rnti); -} - -const char* rlc_nr::user_interface::get_rb_name(uint32_t lcid) -{ - return m_rrc->get_rb_name(lcid); -} - -void rlc_nr::user_interface::notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) -{ - m_pdcp->notify_delivery(rnti, lcid, pdcp_sns); -} - -void rlc_nr::user_interface::notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) -{ - m_pdcp->notify_failure(rnti, lcid, pdcp_sns); -} - -} // namespace srsenb diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index eb3fdc928..98b9de557 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -118,8 +118,12 @@ public: class gtpu_dummy : public srsenb::gtpu_interface_rrc { public: - srsran::expected - add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) override + srsran::expected add_bearer(uint16_t rnti, + uint32_t lcid, + uint32_t addr, + uint32_t teid_out, + uint32_t& addr_in, + const bearer_props* props) override { return 1; } diff --git a/srsenb/test/common/dummy_classes_common.h b/srsenb/test/common/dummy_classes_common.h index 3988d24fb..9a40f82cd 100644 --- a/srsenb/test/common/dummy_classes_common.h +++ b/srsenb/test/common/dummy_classes_common.h @@ -48,6 +48,7 @@ public: class pdcp_dummy : public pdcp_interface_rrc, public pdcp_interface_gtpu { public: + void set_enabled(uint16_t rnti, uint32_t lcid, bool enabled) override {} void reset(uint16_t rnti) override {} void add_user(uint16_t rnti) override {} void rem_user(uint16_t rnti) override {} diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsenb/test/common/dummy_classes_nr.h index fc4277eb3..e1a574f97 100644 --- a/srsenb/test/common/dummy_classes_nr.h +++ b/srsenb/test/common/dummy_classes_nr.h @@ -30,10 +30,11 @@ namespace srsenb { class rrc_nr_dummy : public rrc_interface_mac_nr { public: - int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } - int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } - int add_user(uint16_t rnti) { return SRSRAN_SUCCESS; } - int update_user(uint16_t new_rnti, uint16_t old_rnti) { return SRSRAN_SUCCESS; } + int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int add_user(uint16_t rnti) { return SRSRAN_SUCCESS; } + int update_user(uint16_t new_rnti, uint16_t old_rnti) { return SRSRAN_SUCCESS; } + void set_activity_user(uint16_t rnti) {} }; class rlc_nr_dummy : public rlc_interface_mac_nr @@ -52,6 +53,8 @@ public: int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override { return SRSRAN_SUCCESS; } + int remove_ue(uint16_t rnti) override { return SRSRAN_SUCCESS; } + srsenb::sched_interface::cell_cfg_t cellcfgobj; }; diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index d6fddafe4..4ebb630f1 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -96,7 +96,12 @@ inline sched_nr_interface::ue_cfg_t get_default_ue_cfg( uecfg.carriers[cc].cc = cc; uecfg.carriers[cc].active = true; } - uecfg.phy_cfg = phy_cfg; + uecfg.phy_cfg = phy_cfg; + uecfg.ue_bearers[0].direction = mac_lc_ch_cfg_t::BOTH; + + // Note: dynamic MCS not yet supported + uecfg.fixed_dl_mcs = 28; + uecfg.fixed_ul_mcs = 10; return uecfg; } diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsenb/test/mac/nr/sched_nr_sim_ue.cc index db900b387..89fa1833b 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.cc +++ b/srsenb/test/mac/nr/sched_nr_sim_ue.cc @@ -104,7 +104,7 @@ sched_nr_sim_base::sched_nr_sim_base(const sched_nr_interface::sched_cfg_t& std::string test_name_) : logger(srslog::fetch_basic_logger("TEST")), mac_logger(srslog::fetch_basic_logger("MAC")), - sched_ptr(new sched_nr(sched_args)), + sched_ptr(new sched_nr()), test_name(std::move(test_name_)) { logger.info("\n=========== Start %s ===========", test_name.c_str()); @@ -112,7 +112,7 @@ sched_nr_sim_base::sched_nr_sim_base(const sched_nr_interface::sched_cfg_t& for (uint32_t cc = 0; cc < cell_cfg_list.size(); ++cc) { cell_params.emplace_back(cc, cell_cfg_list[cc], sched_args); } - sched_ptr->cell_cfg(cell_cfg_list); // call parent cfg + sched_ptr->config(sched_args, cell_cfg_list); // call parent cfg TESTASSERT(cell_params.size() > 0); } diff --git a/srsenb/test/ngap/ngap_test.cc b/srsenb/test/ngap/ngap_test.cc index aa0d45e62..d81d96b7c 100644 --- a/srsenb/test/ngap/ngap_test.cc +++ b/srsenb/test/ngap/ngap_test.cc @@ -82,11 +82,20 @@ public: { return SRSRAN_SUCCESS; } + int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) + { + return SRSRAN_SUCCESS; + } int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) { return SRSRAN_SUCCESS; } - int start_security_mode_procedure(uint16_t rnti) { return SRSRAN_SUCCESS; } + int start_security_mode_procedure(uint16_t rnti) { return SRSRAN_SUCCESS; } + int establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) + { + return SRSRAN_SUCCESS; + } + int allocate_lcid(uint16_t rnti) { return SRSRAN_SUCCESS; } void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) {} }; struct dummy_socket_manager : public srsran::socket_manager_itf { @@ -171,8 +180,9 @@ int main(int argc, char** argv) args.amf_addr = "127.0.0.1"; args.gnb_name = "srsgnb01"; - rrc_nr_dummy rrc; - ngap_obj.init(args, &rrc); + rrc_nr_dummy rrc; + gtpu_interface_rrc* gtpu = nullptr; + ngap_obj.init(args, &rrc, gtpu); // Start the log backend. srsran::test_init(argc, argv); diff --git a/srsenb/test/rrc/CMakeLists.txt b/srsenb/test/rrc/CMakeLists.txt index ecccbdc23..405e1ad5d 100644 --- a/srsenb/test/rrc/CMakeLists.txt +++ b/srsenb/test/rrc/CMakeLists.txt @@ -19,7 +19,7 @@ # add_library(test_helpers test_helpers.cc) -target_link_libraries(test_helpers srsenb_rrc srsenb_common rrc_asn1 s1ap_asn1 srsran_common enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) +target_link_libraries(test_helpers srsenb_rrc srsenb_common rrc_asn1 rrc_nr_asn1 s1ap_asn1 srsran_common enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) add_executable(rrc_nr_test rrc_nr_test.cc) target_link_libraries(rrc_nr_test srsgnb_rrc srsran_common rrc_nr_asn1 ${ATOMIC_LIBS}) diff --git a/srsenb/test/rrc/test_helpers.cc b/srsenb/test/rrc/test_helpers.cc index 55049e05f..53035754c 100644 --- a/srsenb/test/rrc/test_helpers.cc +++ b/srsenb/test/rrc/test_helpers.cc @@ -48,7 +48,9 @@ int parse_default_cfg_phy(rrc_cfg_t* rrc_cfg, phy_cfg_t* phy_cfg, srsenb::all_ar args.general.rrc_inactivity_timer = 60000; - return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, phy_cfg); + rrc_nr_cfg_t rrc_cfg_nr; + + return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &rrc_cfg_nr, phy_cfg); } int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args) @@ -74,8 +76,9 @@ int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args) args.general.rrc_inactivity_timer = 60000; phy_cfg_t phy_cfg; + rrc_nr_cfg_t rrc_cfg_nr; - return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &phy_cfg); + return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &rrc_cfg_nr, &phy_cfg); } int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srsran::timer_handler& timers, uint16_t rnti) diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index 0c5b16f89..87d8637d7 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -253,10 +253,11 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) senb_gtpu.init(gtpu_args, &senb_pdcp); gtpu_args.gtp_bind_addr = tenb_addr_str; tenb_gtpu.init(gtpu_args, &tenb_pdcp); - + uint32_t addr_in1; + uint32_t addr_in2; // create tunnels MME-SeNB and MME-TeNB - uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1_bearer_id, sgw_addr, sgw_teidout1).value(); - uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, sgw_addr, sgw_teidout2).value(); + uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1_bearer_id, sgw_addr, sgw_teidout1, addr_in1).value(); + uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, sgw_addr, sgw_teidout2, addr_in2).value(); // Buffer PDUs in SeNB PDCP for (size_t sn = 6; sn < 10; ++sn) { @@ -269,11 +270,13 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) gtpu::bearer_props props; props.flush_before_teidin_present = true; props.flush_before_teidin = tenb_teid_in; - uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, senb_addr, 0, &props).value(); + uint32_t addr_in3; + uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, senb_addr, 0, addr_in3, &props).value(); props = {}; props.forward_from_teidin_present = true; props.forward_from_teidin = senb_teid_in; - senb_gtpu.add_bearer(rnti, drb1_bearer_id, tenb_addr, dl_tenb_teid_in, &props); + uint32_t addr_in4; + senb_gtpu.add_bearer(rnti, drb1_bearer_id, tenb_addr, dl_tenb_teid_in, addr_in4, &props); std::vector data_vec(10); std::iota(data_vec.begin(), data_vec.end(), 0); diff --git a/srsepc/src/spgw/gtpc.cc b/srsepc/src/spgw/gtpc.cc index b3680a701..17e482673 100644 --- a/srsepc/src/spgw/gtpc.cc +++ b/srsepc/src/spgw/gtpc.cc @@ -524,7 +524,7 @@ pkt_discard: bool spgw::gtpc::free_all_queued_packets(spgw_tunnel_ctx_t* tunnel_ctx) { if (!tunnel_ctx->paging_pending) { - m_logger.warning("Freeing queue with paging not pending."); + m_logger.info("Trying to free queued packets, but paging is not pending."); } while (!tunnel_ctx->paging_queue.empty()) { diff --git a/srsue/hdr/phy/lte/cc_worker.h b/srsue/hdr/phy/lte/cc_worker.h index cc57d0895..b9d4a6a20 100644 --- a/srsue/hdr/phy/lte/cc_worker.h +++ b/srsue/hdr/phy/lte/cc_worker.h @@ -41,16 +41,16 @@ public: uint32_t get_buffer_len(); void set_tti(uint32_t tti); - void set_cfo_unlocked(float cfo); + void set_cfo_nolock(float cfo); float get_ref_cfo() const; // Functions to set configuration. // Warning: all these functions are unlocked and must be called while the worker is not processing data - void reset_cell_unlocked(); - bool set_cell_unlocked(srsran_cell_t cell_); - void set_tdd_config_unlocked(srsran_tdd_config_t config); - void set_config_unlocked(const srsran::phy_cfg_t& phy_cfg); - void upd_config_dci_unlocked(const srsran_dci_cfg_t& dci_cfg); + void reset_cell_nolock(); + bool set_cell_nolock(srsran_cell_t cell_); + void set_tdd_config_nolock(srsran_tdd_config_t config); + void set_config_nolock(const srsran::phy_cfg_t& phy_cfg); + void upd_config_dci_nolock(const srsran_dci_cfg_t& dci_cfg); void set_uci_periodic_cqi(srsran_uci_data_t* uci_data); diff --git a/srsue/hdr/phy/lte/sf_worker.h b/srsue/hdr/phy/lte/sf_worker.h index f495dd968..ccccbdc95 100644 --- a/srsue/hdr/phy/lte/sf_worker.h +++ b/srsue/hdr/phy/lte/sf_worker.h @@ -45,18 +45,18 @@ public: sf_worker(uint32_t max_prb, phy_common* phy_, srslog::basic_logger& logger); virtual ~sf_worker(); - void reset_cell_unlocked(uint32_t cc_idx); - bool set_cell_unlocked(uint32_t cc_idx, srsran_cell_t cell_); + void reset_cell_nolock(uint32_t cc_idx); + bool set_cell_nolock(uint32_t cc_idx, srsran_cell_t cell_); /* Functions used by main PHY thread */ cf_t* get_buffer(uint32_t cc_idx, uint32_t antenna_idx); uint32_t get_buffer_len(); void set_context(const srsran::phy_common_interface::worker_context_t& w_ctx); void set_prach(cf_t* prach_ptr, float prach_power); - void set_cfo_unlocked(const uint32_t& cc_idx, float cfo); + void set_cfo_nolock(const uint32_t& cc_idx, float cfo); - void set_tdd_config_unlocked(srsran_tdd_config_t config); - void set_config_unlocked(uint32_t cc_idx, const srsran::phy_cfg_t& phy_cfg); + void set_tdd_config_nolock(srsran_tdd_config_t config); + void set_config_nolock(uint32_t cc_idx, const srsran::phy_cfg_t& phy_cfg); ///< Methods for plotting called from GUI thread int read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna); diff --git a/srsue/hdr/stack/mac/dl_harq.h b/srsue/hdr/stack/mac/dl_harq.h index f64b9dd50..9302051e6 100644 --- a/srsue/hdr/stack/mac/dl_harq.h +++ b/srsue/hdr/stack/mac/dl_harq.h @@ -85,7 +85,7 @@ private: bool calc_is_new_transmission(mac_interface_phy_lte::mac_grant_dl_t grant); // Internal function to reset process, caller must hold the mutex - void reset_unsafe(); + void reset_nolock(); std::mutex mutex; @@ -118,14 +118,14 @@ private: dl_sps dl_sps_assig; - std::vector proc; - dl_harq_process bcch_proc; - demux* demux_unit = nullptr; - srslog::basic_logger& logger; - srsran::mac_pcap* pcap = nullptr; - ue_rnti* rntis = nullptr; - uint16_t last_temporal_crnti = 0; - int si_window_start = 0; + std::vector proc; + dl_harq_process bcch_proc; + demux* demux_unit = nullptr; + srslog::basic_logger& logger; + srsran::mac_pcap* pcap = nullptr; + ue_rnti* rntis = nullptr; + uint16_t last_temporal_crnti = 0; + int si_window_start = 0; std::mutex retx_cnt_mutex = {}; diff --git a/srsue/hdr/stack/mac/mux.h b/srsue/hdr/stack/mac/mux.h index bccf3f7f9..611f3bbc2 100644 --- a/srsue/hdr/stack/mac/mux.h +++ b/srsue/hdr/stack/mac/mux.h @@ -66,7 +66,7 @@ public: void print_logical_channel_state(const std::string& info); private: - uint8_t* pdu_get_unsafe(srsran::byte_buffer_t* payload, uint32_t pdu_sz); + uint8_t* pdu_get_nolock(srsran::byte_buffer_t* payload, uint32_t pdu_sz); bool pdu_move_to_msg3(uint32_t pdu_sz); uint32_t allocate_sdu(uint32_t lcid, srsran::sch_pdu* pdu, int max_sdu_sz); bool sched_sdu(srsran::logical_channel_config_t* ch, int* sdu_space, int max_sdu_sz); diff --git a/srsue/hdr/stack/mac/proc_ra.h b/srsue/hdr/stack/mac/proc_ra.h index 2c484f513..220c62660 100644 --- a/srsue/hdr/stack/mac/proc_ra.h +++ b/srsue/hdr/stack/mac/proc_ra.h @@ -87,7 +87,7 @@ private: void response_error(); void complete(); - bool contention_resolution_id_received_unsafe(uint64_t rx_contention_id); + bool contention_resolution_id_received_nolock(uint64_t rx_contention_id); // Buffer to receive RAR PDU static const uint32_t MAX_RAR_PDU_LEN = 2048; diff --git a/srsue/hdr/stack/mac_nr/mac_nr.h b/srsue/hdr/stack/mac_nr/mac_nr.h index 395911740..f9898f068 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr.h +++ b/srsue/hdr/stack/mac_nr/mac_nr.h @@ -107,6 +107,7 @@ public: /// Interface for MUX srsran::mac_sch_subpdu_nr::lcg_bsr_t generate_sbsr(); + void set_padding_bytes(uint32_t nof_bytes); void msg3_flush() { mux.msg3_flush(); } bool msg3_is_transmitted() { return mux.msg3_is_transmitted(); } @@ -156,8 +157,7 @@ private: std::atomic started = {false}; - uint16_t c_rnti = SRSRAN_INVALID_RNTI; - uint64_t contention_id = 0; + ue_rnti rntis; // thread-safe helper to store RNTIs, contention ID, etc std::array metrics = {}; diff --git a/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h b/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h index b7df32290..9d94fea7a 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h +++ b/srsue/hdr/stack/mac_nr/mac_nr_interfaces.h @@ -63,11 +63,17 @@ public: class mac_interface_mux_nr { public: + // MUX can ask MAC if a C-RNTI is present + virtual bool has_crnti() = 0; + // MUX can query MAC for current C-RNTI for Msg3 transmission virtual uint16_t get_crnti() = 0; // MUX queries MAC to return LCG state for SBSR virtual srsran::mac_sch_subpdu_nr::lcg_bsr_t generate_sbsr() = 0; + + // MUX informs MAC about padding bytes so BSR proc can decide whether to create BSR or not + virtual void set_padding_bytes(uint32_t nof_bytes) = 0; }; /** diff --git a/srsue/hdr/stack/mac_nr/proc_bsr_nr.h b/srsue/hdr/stack/mac_nr/proc_bsr_nr.h index bc97c09a5..ea567540b 100644 --- a/srsue/hdr/stack/mac_nr/proc_bsr_nr.h +++ b/srsue/hdr/stack/mac_nr/proc_bsr_nr.h @@ -78,7 +78,7 @@ public: /// MUX interface for BSR generation srsran::mac_sch_subpdu_nr::lcg_bsr_t generate_sbsr(); - bool generate_padding_bsr(uint32_t nof_padding_bytes); + void set_padding_bytes(uint32_t nof_bytes); private: const static int QUEUE_STATUS_PERIOD_MS = 1000; diff --git a/srsue/hdr/stack/mac_nr/proc_sr_nr.h b/srsue/hdr/stack/mac_nr/proc_sr_nr.h index 909bbcbf5..5d52d5bf0 100644 --- a/srsue/hdr/stack/mac_nr/proc_sr_nr.h +++ b/srsue/hdr/stack/mac_nr/proc_sr_nr.h @@ -49,7 +49,7 @@ public: bool sr_opportunity(uint32_t tti, uint32_t sr_id, bool meas_gap, bool ul_sch_tx); private: - void reset_unsafe(); + void reset_nolock(); int sr_counter = 0; bool is_pending_sr = false; diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index a8fb25f3b..330482cea 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -23,7 +23,6 @@ #define SRSUE_RRC_H #include "rrc_cell.h" -#include "rrc_common.h" #include "rrc_metrics.h" #include "rrc_rlf_report.h" #include "srsran/asn1/rrc_utils.h" @@ -35,6 +34,7 @@ #include "srsran/common/security.h" #include "srsran/common/stack_procedure.h" #include "srsran/interfaces/ue_interfaces.h" +#include "srsran/rrc/rrc_common.h" #include "srsran/srslog/srslog.h" #include @@ -54,6 +54,7 @@ typedef struct { uint32_t release; uint32_t feature_group; std::array supported_bands; + std::vector supported_bands_nr; uint32_t nof_supported_bands; bool support_ca; int mbms_service_id; diff --git a/srsue/hdr/stack/rrc/rrc_metrics.h b/srsue/hdr/stack/rrc/rrc_metrics.h index bfc0018fc..6c5901786 100644 --- a/srsue/hdr/stack/rrc/rrc_metrics.h +++ b/srsue/hdr/stack/rrc/rrc_metrics.h @@ -22,11 +22,18 @@ #ifndef SRSUE_RRC_METRICS_H #define SRSUE_RRC_METRICS_H -#include "rrc_common.h" #include "srsran/interfaces/phy_interface_types.h" namespace srsue { +// RRC states (3GPP 36.331 v10.0.0) +typedef enum { + RRC_STATE_IDLE = 0, + RRC_STATE_CONNECTED, + RRC_STATE_N_ITEMS, +} rrc_state_t; +static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", "CONNECTED"}; + struct rrc_metrics_t { rrc_state_t state; std::vector neighbour_cells; diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index 37a659e40..a34835719 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -22,6 +22,7 @@ #ifndef SRSUE_RRC_NR_H #define SRSUE_RRC_NR_H +#include "srsran/adt/circular_map.h" #include "srsran/asn1/rrc_nr.h" #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/block_queue.h" @@ -194,10 +195,9 @@ private: std::map drb_eps_bearer_id; // Map of drb id to eps_bearer_id // temporary maps for building the pucch nr resources - std::map res_list; - std::map res_list_present; - std::map csi_rs_zp_res; - std::map csi_rs_nzp_res; + srsran::static_circular_map pucch_res_list; + std::map csi_rs_zp_res; + std::map csi_rs_nzp_res; 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); diff --git a/srsue/hdr/stack/ue_stack_base.h b/srsue/hdr/stack/ue_stack_base.h index 8dc220561..07a53b0a7 100644 --- a/srsue/hdr/stack/ue_stack_base.h +++ b/srsue/hdr/stack/ue_stack_base.h @@ -65,7 +65,6 @@ typedef struct { } stack_log_args_t; typedef struct { - std::string type; pkt_trace_args_t pkt_trace; stack_log_args_t log; usim_args_t usim; diff --git a/srsue/hdr/stack/upper/gw.h b/srsue/hdr/stack/upper/gw.h index 8d7060e74..869e07502 100644 --- a/srsue/hdr/stack/upper/gw.h +++ b/srsue/hdr/stack/upper/gw.h @@ -63,14 +63,9 @@ public: void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu); // NAS interface - int setup_if_addr(uint32_t eps_bearer_id, - uint8_t pdn_type, - uint32_t ip_addr, - uint8_t* ipv6_if_addr, - char* err_str); + int setup_if_addr(uint32_t eps_bearer_id, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_addr, char* err_str); int deactivate_eps_bearer(const uint32_t eps_bearer_id); - int apply_traffic_flow_template(const uint8_t& eps_bearer_id, - const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); + int apply_traffic_flow_template(const uint8_t& eps_bearer_id, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); void set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms); // RRC interface @@ -84,13 +79,13 @@ private: gw_args_t args = {}; - std::atomic running = {false}; - bool run_enable = false; - int32_t netns_fd = 0; - int32_t tun_fd = 0; - struct ifreq ifr = {}; - int32_t sock = 0; - bool if_up = false; + std::atomic running = {false}; + std::atomic run_enable = {false}; + int32_t netns_fd = 0; + int32_t tun_fd = 0; + struct ifreq ifr = {}; + int32_t sock = 0; + bool if_up = false; static const int NOT_ASSIGNED = -1; int32_t default_eps_bearer_id = NOT_ASSIGNED; diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index 10ab99adb..d833171a9 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -272,8 +272,6 @@ private: srsran::proc_manager_list_t callbacks; srsran::proc_t plmn_searcher; - - const std::string gw_setup_failure_str = "Failed to setup/configure GW interface"; }; } // namespace srsue diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index 88b1a5162..0d394d993 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -23,6 +23,8 @@ #define SRSUE_NAS_5G_H #include "nas_base.h" +#include "srsran/asn1/nas_5g_ies.h" +#include "srsran/asn1/nas_5g_msg.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" #include "srsran/common/nas_pcap.h" @@ -40,6 +42,9 @@ using srsran::byte_buffer_t; +#define MAX_PDU_SESSIONS 15 +#define MAX_TRANS_ID 255 + namespace srsue { /** @@ -60,6 +65,8 @@ public: // Stack+RRC interface bool is_registered(); + int write_pdu(srsran::unique_byte_buffer_t pdu); + // timer callback void timer_expired(uint32_t timeout_id); @@ -77,13 +84,23 @@ private: bool running = false; + bool initial_sec_command = false; + srsran::nas_5g::mobile_identity_5gs_t::guti_5g_s guti_5g; + + srsran::nas_5g::nas_5gs_msg initial_registration_request_stored; + nas_args_t cfg = {}; - mm5g_state_t state = {}; + mm5g_state_t state; // Security bool ia5g_caps[8] = {}; bool ea5g_caps[8] = {}; + // TS 23.003 Sec. 6.2.2 IMEISV's last two octets are Software Version Number (SVN) + // which identifies the software version number of the mobile equipment + const uint8_t ue_svn_oct1 = 0x5; + const uint8_t ue_svn_oct2 = 0x3; + // timers srsran::task_sched_handle task_sched; srsran::timer_handler::unique_timer t3502; // started when registration failure and the attempt counter is equal to 5 @@ -105,10 +122,70 @@ private: // Procedures // Forward declartion class registration_procedure; + class pdu_session_establishment_procedure; + + srsran::proc_t registration_proc; + srsran::proc_t pdu_session_establishment_proc; - srsran::proc_t registration_proc; + // Network information + srsran::nas_5g::network_name_t full_network_name; + // Message sender int send_registration_request(); + int send_authentication_response(const uint8_t res[16]); + int send_security_mode_reject(const srsran::nas_5g::cause_5gmm_t::cause_5gmm_type_::options cause); + int send_authentication_failure(const srsran::nas_5g::cause_5gmm_t::cause_5gmm_type_::options cause, + const uint8_t* auth_fail_param); + int send_security_mode_complete(const srsran::nas_5g::security_mode_command_t& security_mode_command); + int send_registration_complete(); + int send_pdu_session_establishment_request(uint32_t transaction_identity, + uint16_t pdu_session_id, + const pdu_session_cfg_t& pdu_session); + + void fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_caps); + int apply_security_config(srsran::unique_byte_buffer_t& pdu, uint8_t sec_hdr_type); + + // message handler + int handle_registration_accept(srsran::nas_5g::registration_accept_t& registration_accept); + int handle_registration_reject(srsran::nas_5g::registration_reject_t& registration_reject); + int handle_authentication_request(srsran::nas_5g::authentication_request_t& authentication_request); + int handle_identity_request(srsran::nas_5g::identity_request_t& identity_request); + int handle_service_accept(srsran::nas_5g::service_accept_t& service_accept); + int handle_service_reject(srsran::nas_5g::service_reject_t& service_reject); + int handle_security_mode_command(srsran::nas_5g::security_mode_command_t& security_mode_command, + srsran::unique_byte_buffer_t pdu); + int handle_deregistration_accept_ue_terminated( + srsran::nas_5g::deregistration_accept_ue_terminated_t& deregistration_accept_ue_terminated); + int handle_deregistration_request_ue_terminated( + srsran::nas_5g::deregistration_request_ue_terminated_t& deregistration_request_ue_terminated); + int handle_configuration_update_command(srsran::nas_5g::configuration_update_command_t& configuration_update_command); + int handle_dl_nas_transport(srsran::nas_5g::dl_nas_transport_t& dl_nas_transport); + + // message handler container + int handle_n1_sm_information(std::vector payload_container_contents); + + // Transaction ID management + std::array pdu_trans_ids; + uint32_t allocate_next_proc_trans_id(); + void release_proc_trans_id(uint32_t proc_id); + + int trigger_pdu_session_est(); + + // PDU Session Management + int add_pdu_session(uint16_t pdu_session_id, uint16_t pdu_session_type, srsran::nas_5g::pdu_address_t pdu_address); + int init_pdu_sessions(std::vector pdu_session_cfgs); + int configure_pdu_session(uint16_t pdu_session_id); + bool unestablished_pdu_sessions(); + int get_unestablished_pdu_session(uint16_t& pdu_session_id, pdu_session_cfg_t& pdu_session_cfg); + + struct pdu_session_t { + bool configured; + bool established; + uint16_t pdu_session_id; + pdu_session_cfg_t pdu_session_cfg; + }; + + std::array pdu_sessions; }; } // namespace srsue #endif \ No newline at end of file diff --git a/srsue/hdr/stack/upper/nas_5g_procedures.h b/srsue/hdr/stack/upper/nas_5g_procedures.h index 71e10769f..5cea4304f 100644 --- a/srsue/hdr/stack/upper/nas_5g_procedures.h +++ b/srsue/hdr/stack/upper/nas_5g_procedures.h @@ -39,11 +39,38 @@ public: explicit registration_procedure(nas_5g_interface_procedures* parent_nas_); srsran::proc_outcome_t init(); srsran::proc_outcome_t step(); + srsran::proc_outcome_t then(); static const char* name() { return "Registration Procedure"; } private: nas_5g_interface_procedures* parent_nas; }; + +/** + * @brief 5G NAS (5GSM) UE-requested PDU session establishment procedure + * + * Specified in 24 501 V16.7.0 + * UE-requested 5GSM procedures + * 6.4.1 UE-requested PDU session establishment procedure + */ +class nas_5g::pdu_session_establishment_procedure +{ +public: + explicit pdu_session_establishment_procedure(nas_5g_interface_procedures* parent_nas_, srslog::basic_logger& logger_); + srsran::proc_outcome_t init(const uint16_t pdu_session_id, const pdu_session_cfg_t pdu_session); + srsran::proc_outcome_t react(const srsran::nas_5g::pdu_session_establishment_accept_t& pdu_session_est_accept); + srsran::proc_outcome_t react(const srsran::nas_5g::pdu_session_establishment_reject_t& pdu_session_est_reject); + srsran::proc_outcome_t step(); + srsran::proc_outcome_t then(); + static const char* name() { return "PDU Session Establishment Procedure"; } + +private: + srslog::basic_logger& logger; + nas_5g_interface_procedures* parent_nas; + uint32_t transaction_identity = 0; + uint16_t pdu_session_id = 0; +}; + } // namespace srsue #endif // SRSUE_NAS_5G_PROCEDURES_H_ \ No newline at end of file diff --git a/srsue/hdr/stack/upper/nas_5gmm_state.h b/srsue/hdr/stack/upper/nas_5gmm_state.h index c558e7983..be0b39233 100644 --- a/srsue/hdr/stack/upper/nas_5gmm_state.h +++ b/srsue/hdr/stack/upper/nas_5gmm_state.h @@ -66,6 +66,7 @@ public: update_needed, }; + mm5g_state_t(srslog::basic_logger& logger_) : logger(logger_) {} // FSM setters void set_null(); void set_deregistered(deregistered_substate_t substate); @@ -86,7 +87,7 @@ private: state_t state = state_t::null; deregistered_substate_t deregistered_substate = deregistered_substate_t::null; registered_substate_t registered_substate = registered_substate_t::null; - srslog::basic_logger& logger = srslog::fetch_basic_logger("NAS-5G"); + srslog::basic_logger& logger; }; const char* mm5g_state_text(mm5g_state_t::state_t type); diff --git a/srsue/hdr/stack/upper/nas_base.h b/srsue/hdr/stack/upper/nas_base.h index 14e5010bf..d95b9e997 100644 --- a/srsue/hdr/stack/upper/nas_base.h +++ b/srsue/hdr/stack/upper/nas_base.h @@ -58,9 +58,17 @@ protected: LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; }; - nas_sec_ctxt ctxt = {}; - uint8_t k_nas_enc[32] = {}; - uint8_t k_nas_int[32] = {}; + struct nas_5g_sec_ctxt { + uint8_t ksi; + uint8_t k_amf[32]; + uint32_t tx_count; + uint32_t rx_count; + }; + + nas_sec_ctxt ctxt = {}; + nas_5g_sec_ctxt ctxt_5g = {}; + uint8_t k_nas_enc[32] = {}; + uint8_t k_nas_int[32] = {}; int parse_security_algorithm_list(std::string algorithm_string, bool* algorithm_caps); @@ -74,6 +82,8 @@ protected: uint32_t mac_offset = 0; uint32_t seq_offset = 0; uint32_t bearer_id = 0; + + const std::string gw_setup_failure_str = "Failed to setup/configure GW interface"; }; } // namespace srsue diff --git a/srsue/hdr/stack/upper/nas_config.h b/srsue/hdr/stack/upper/nas_config.h index 104de01d1..90d196142 100644 --- a/srsue/hdr/stack/upper/nas_config.h +++ b/srsue/hdr/stack/upper/nas_config.h @@ -22,6 +22,7 @@ #ifndef SRSUE_NAS_CONFIG_H #define SRSUE_NAS_CONFIG_H +#include "srsran/interfaces/ue_nas_interfaces.h" #include namespace srsue { @@ -43,9 +44,12 @@ public: bool force_imsi_attach; std::string eia; std::string eea; + nas_sim_args_t sim; + + // 5G args std::string ia5g; std::string ea5g; - nas_sim_args_t sim; + std::vector pdu_session_cfgs; }; } // namespace srsue diff --git a/srsue/hdr/stack/upper/test/nas_test_common.h b/srsue/hdr/stack/upper/test/nas_test_common.h index 46659b366..98cb28adf 100644 --- a/srsue/hdr/stack/upper/test/nas_test_common.h +++ b/srsue/hdr/stack/upper/test/nas_test_common.h @@ -140,15 +140,23 @@ public: plmns[0].plmn_id.from_number(mcc, mnc); plmns[0].tac = 0xffff; } - void init(nas_5g* nas_5g_) { nas_5g_ptr = nas_5g_; } - void write_sdu(unique_byte_buffer_t sdu) + void init(srsue::nas_5g* nas_5g_) { nas_5g_ptr = nas_5g_; } + int write_sdu(unique_byte_buffer_t sdu) { last_sdu_len = sdu->N_bytes; // printf("NAS generated SDU (len=%d):\n", sdu->N_bytes); + return SRSRAN_SUCCESS; + } + virtual bool is_connected() { return true; } + virtual int connection_request(srsran::nr_establishment_cause_t cause, srsran::unique_byte_buffer_t sdu) + { + return SRSRAN_SUCCESS; } + uint16_t get_mcc() { return 0x0000; } + uint16_t get_mnc() { return 0x0000; } private: - nas_5g* nas_5g_ptr; + srsue::nas_5g* nas_5g_ptr; uint32_t last_sdu_len; nas_interface_rrc::found_plmn_t plmns[nas_interface_rrc::MAX_FOUND_PLMNS]; }; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index fecc4d20e..3dda9e26d 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -76,7 +76,6 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) common.add_options() ("ue.radio", bpo::value(&args->rf.type)->default_value("multi"), "Type of the radio [multi]") ("ue.phy", bpo::value(&args->phy.type)->default_value("lte"), "Type of the PHY [lte]") - ("ue.stack", bpo::value(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]") ("rf.srate", bpo::value(&args->rf.srate_hz)->default_value(0.0), "Force Tx and Rx sampling rate in Hz") ("rf.freq_offset", bpo::value(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset") diff --git a/srsue/src/phy/lte/cc_worker.cc b/srsue/src/phy/lte/cc_worker.cc index cdd9d9bba..7a767e90f 100644 --- a/srsue/src/phy/lte/cc_worker.cc +++ b/srsue/src/phy/lte/cc_worker.cc @@ -121,15 +121,15 @@ void cc_worker::reset() { // constructor sets defaults srsran::phy_cfg_t empty_cfg; - set_config_unlocked(empty_cfg); + set_config_nolock(empty_cfg); } -void cc_worker::reset_cell_unlocked() +void cc_worker::reset_cell_nolock() { cell_initiated = false; } -bool cc_worker::set_cell_unlocked(srsran_cell_t cell_) +bool cc_worker::set_cell_nolock(srsran_cell_t cell_) { if (cell.id != cell_.id || !cell_initiated) { cell = cell_; @@ -180,7 +180,7 @@ void cc_worker::set_tti(uint32_t tti) sf_cfg_ul.shortened = false; } -void cc_worker::set_cfo_unlocked(float cfo) +void cc_worker::set_cfo_nolock(float cfo) { ue_ul_cfg.cfo_value = cfo; } @@ -190,7 +190,7 @@ float cc_worker::get_ref_cfo() const return ue_dl.chest_res.cfo; } -void cc_worker::set_tdd_config_unlocked(srsran_tdd_config_t config) +void cc_worker::set_tdd_config_nolock(srsran_tdd_config_t config) { sf_cfg_dl.tdd_config = config; sf_cfg_ul.tdd_config = config; @@ -883,7 +883,7 @@ void cc_worker::set_uci_ack(srsran_uci_data_t* uci_data, /* Translates RRC structs into PHY structs */ -void cc_worker::set_config_unlocked(const srsran::phy_cfg_t& phy_cfg) +void cc_worker::set_config_nolock(const srsran::phy_cfg_t& phy_cfg) { // Save configuration ue_dl_cfg.cfg = phy_cfg.dl_cfg; @@ -892,7 +892,7 @@ void cc_worker::set_config_unlocked(const srsran::phy_cfg_t& phy_cfg) phy->set_pdsch_cfg(&ue_dl_cfg.cfg.pdsch); } -void cc_worker::upd_config_dci_unlocked(const srsran_dci_cfg_t& dci_cfg) +void cc_worker::upd_config_dci_nolock(const srsran_dci_cfg_t& dci_cfg) { ue_dl_cfg.cfg.dci = dci_cfg; } diff --git a/srsue/src/phy/lte/sf_worker.cc b/srsue/src/phy/lte/sf_worker.cc index cecc7f135..ec623b36c 100644 --- a/srsue/src/phy/lte/sf_worker.cc +++ b/srsue/src/phy/lte/sf_worker.cc @@ -73,15 +73,15 @@ sf_worker::~sf_worker() } } -void sf_worker::reset_cell_unlocked(uint32_t cc_idx) +void sf_worker::reset_cell_nolock(uint32_t cc_idx) { - cc_workers[cc_idx]->reset_cell_unlocked(); + cc_workers[cc_idx]->reset_cell_nolock(); } -bool sf_worker::set_cell_unlocked(uint32_t cc_idx, srsran_cell_t cell_) +bool sf_worker::set_cell_nolock(uint32_t cc_idx, srsran_cell_t cell_) { if (cc_idx < cc_workers.size()) { - if (!cc_workers[cc_idx]->set_cell_unlocked(cell_)) { + if (!cc_workers[cc_idx]->set_cell_nolock(cell_)) { Error("Setting cell for cc=%d", cc_idx); return false; } @@ -129,26 +129,26 @@ void sf_worker::set_prach(cf_t* prach_ptr_, float prach_power_) prach_power = prach_power_; } -void sf_worker::set_cfo_unlocked(const uint32_t& cc_idx, float cfo) +void sf_worker::set_cfo_nolock(const uint32_t& cc_idx, float cfo) { - cc_workers[cc_idx]->set_cfo_unlocked(cfo); + cc_workers[cc_idx]->set_cfo_nolock(cfo); } -void sf_worker::set_tdd_config_unlocked(srsran_tdd_config_t config) +void sf_worker::set_tdd_config_nolock(srsran_tdd_config_t config) { for (auto& cc_worker : cc_workers) { - cc_worker->set_tdd_config_unlocked(config); + cc_worker->set_tdd_config_nolock(config); } tdd_config = config; } -void sf_worker::set_config_unlocked(uint32_t cc_idx, const srsran::phy_cfg_t& phy_cfg) +void sf_worker::set_config_nolock(uint32_t cc_idx, const srsran::phy_cfg_t& phy_cfg) { if (cc_idx < cc_workers.size()) { - cc_workers[cc_idx]->set_config_unlocked(phy_cfg); + cc_workers[cc_idx]->set_config_nolock(phy_cfg); if (cc_idx > 0) { // Update DCI config for PCell - cc_workers[0]->upd_config_dci_unlocked(phy_cfg.dl_cfg.dci); + cc_workers[0]->upd_config_dci_nolock(phy_cfg.dl_cfg.dci); } } else { Error("Setting config for cc=%d; Invalid cc_idx", cc_idx); diff --git a/srsue/src/phy/lte/worker_pool.cc b/srsue/src/phy/lte/worker_pool.cc index 0a3895bb8..6081c292c 100644 --- a/srsue/src/phy/lte/worker_pool.cc +++ b/srsue/src/phy/lte/worker_pool.cc @@ -87,7 +87,7 @@ sf_worker* worker_pool::wait_worker(uint32_t tti) uint32_t worker_id = w->get_id(); for (uint32_t cc_idx = 0; cc_idx < SRSRAN_MAX_CARRIERS; cc_idx++) { if (phy_cfg_stash[cc_idx].is_pending(worker_id)) { - w->set_config_unlocked(cc_idx, phy_cfg_stash[cc_idx].get_cfg(worker_id)); + w->set_config_nolock(cc_idx, phy_cfg_stash[cc_idx].get_cfg(worker_id)); } } diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index 87361b936..b3dfeb2fe 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -99,7 +99,7 @@ void sf_worker::work_imp() // Notify MAC about PRACH transmission phy_state.stack->prach_sent(TTI_TX(tti_rx), - srsran_prach_nr_start_symbol_fr1_unpaired(phy_state.cfg.prach.config_idx), + srsran_prach_nr_start_symbol(phy_state.cfg.prach.config_idx, phy_state.cfg.duplex.mode), SRSRAN_SLOT_NR_MOD(phy_state.cfg.carrier.scs, TTI_TX(tti_rx)), 0, 0); diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index e5061dbff..f69fefb32 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -181,6 +181,7 @@ bool worker_pool::set_config(const srsran::phy_cfg_nr_t& cfg) return false; } prach_cfg.freq_offset -= lte_nr_prach_offset; + prach_cfg.tdd_config.configured = (cfg.duplex.mode == SRSRAN_DUPLEX_MODE_TDD); // Set the PRACH configuration if (not prach_buffer->set_cell(cell, prach_cfg)) { diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index c91dbbf89..efbe1a1f1 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -536,10 +536,10 @@ bool phy::set_scell(srsran_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) if (w) { // Reset secondary serving cell configuration, this needs to be done when the sf_worker is reserved to prevent // resetting the cell while it is working - w->reset_cell_unlocked(cc_idx); + w->reset_cell_nolock(cc_idx); // Set the new cell - w->set_cell_unlocked(cc_idx, cell_info); + w->set_cell_nolock(cc_idx, cell_info); // Release the new worker, it should not start processing until the SCell state is set to configured w->release(); @@ -587,7 +587,7 @@ void phy::set_config_tdd(srsran_tdd_config_t& tdd_config_) // set_tdd_config is not protected so run when worker is finished lte::sf_worker* w = lte_workers.wait_worker_id(i); if (w) { - w->set_tdd_config_unlocked(tdd_config); + w->set_tdd_config_nolock(tdd_config); w->release(); } } @@ -673,9 +673,9 @@ bool phy::set_config(const srsran::phy_cfg_nr_t& cfg) // tune radio for (uint32_t i = 0; i < common.args->nof_nr_carriers; i++) { - logger_phy.info("Tuning Rx channel %d to %.2f GHz", i + common.args->nof_lte_carriers, dl_freq_hz / 1e6); + logger_phy.info("Tuning Rx channel %d to %.2f MHz", i + common.args->nof_lte_carriers, dl_freq_hz / 1e6); radio->set_rx_freq(i + common.args->nof_lte_carriers, dl_freq_hz); - logger_phy.info("Tuning Tx channel %d to %.2f GHz", i + common.args->nof_lte_carriers, ul_freq_hz / 1e6); + logger_phy.info("Tuning Tx channel %d to %.2f MHz", i + common.args->nof_lte_carriers, ul_freq_hz / 1e6); radio->set_tx_freq(i + common.args->nof_lte_carriers, ul_freq_hz); } diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 592a94987..8c3461959 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -526,7 +526,7 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, // Set CFO for all Carriers for (uint32_t cc = 0; cc < worker_com->args->nof_lte_carriers; cc++) { - lte_worker->set_cfo_unlocked(cc, get_tx_cfo()); + lte_worker->set_cfo_nolock(cc, get_tx_cfo()); worker_com->update_cfo_measurement(cc, cfo); } @@ -862,14 +862,14 @@ bool sync::set_cell(float cfo_in) // Reset cell configuration for (uint32_t i = 0; i < worker_com->args->nof_phy_threads; i++) { - (*lte_worker_pool)[i]->reset_cell_unlocked(0); + (*lte_worker_pool)[i]->reset_cell_nolock(0); } bool success = true; for (uint32_t i = 0; i < worker_com->args->nof_phy_threads; i++) { lte::sf_worker* w = lte_worker_pool->wait_worker_id(i); if (w) { - success &= w->set_cell_unlocked(0, cell.get()); + success &= w->set_cell_nolock(0, cell.get()); w->release(); } } diff --git a/srsue/src/stack/mac/dl_harq.cc b/srsue/src/stack/mac/dl_harq.cc index fb3754fc4..61afe18fa 100644 --- a/srsue/src/stack/mac/dl_harq.cc +++ b/srsue/src/stack/mac/dl_harq.cc @@ -216,10 +216,10 @@ bool dl_harq_entity::dl_harq_process::dl_tb_process::init(int pid, dl_harq_entit void dl_harq_entity::dl_harq_process::dl_tb_process::reset() { std::lock_guard lock(mutex); - reset_unsafe(); + reset_nolock(); } -void dl_harq_entity::dl_harq_process::dl_tb_process::reset_unsafe() +void dl_harq_entity::dl_harq_process::dl_tb_process::reset_nolock() { bzero(&cur_grant, sizeof(mac_interface_phy_lte::mac_grant_dl_t)); is_first_tb = true; @@ -309,7 +309,7 @@ void dl_harq_entity::dl_harq_process::dl_tb_process::new_grant_dl(mac_interface_ n_retx > RESET_DUPLICATE_TIMEOUT ? "yes" : "no"); if (n_retx > RESET_DUPLICATE_TIMEOUT) { // reset without trying to acquire the mutex again - reset_unsafe(); + reset_nolock(); } } @@ -369,7 +369,7 @@ void dl_harq_entity::dl_harq_process::dl_tb_process::tb_decoded(mac_interface_ph if (ack && is_bcch) { // reset without trying to acquire the mutex again - reset_unsafe(); + reset_nolock(); } mutex.unlock(); diff --git a/srsue/src/stack/mac/mux.cc b/srsue/src/stack/mac/mux.cc index 2bb8e4672..40623f59f 100644 --- a/srsue/src/stack/mac/mux.cc +++ b/srsue/src/stack/mac/mux.cc @@ -108,11 +108,11 @@ srsran::ul_sch_lcid bsr_format_convert(bsr_proc::bsr_format_t format) uint8_t* mux::pdu_get(srsran::byte_buffer_t* payload, uint32_t pdu_sz) { std::lock_guard lock(mutex); - return pdu_get_unsafe(payload, pdu_sz); + return pdu_get_nolock(payload, pdu_sz); } // Multiplexing and logical channel priorization as defined in Section 5.4.3 -uint8_t* mux::pdu_get_unsafe(srsran::byte_buffer_t* payload, uint32_t pdu_sz) +uint8_t* mux::pdu_get_nolock(srsran::byte_buffer_t* payload, uint32_t pdu_sz) { // Logical Channel Procedure payload->clear(); @@ -372,7 +372,7 @@ uint8_t* mux::msg3_get(srsran::byte_buffer_t* payload, uint32_t pdu_sz) std::lock_guard lock(mutex); if (pdu_sz < msg3_buff.get_tailroom()) { if (msg3_is_empty()) { - if (!pdu_get_unsafe(&msg3_buff, pdu_sz)) { + if (!pdu_get_nolock(&msg3_buff, pdu_sz)) { Error("Moving PDU from Mux unit to Msg3 buffer"); return NULL; } diff --git a/srsue/src/stack/mac/proc_ra.cc b/srsue/src/stack/mac/proc_ra.cc index 3cdab7207..ccab33d56 100644 --- a/srsue/src/stack/mac/proc_ra.cc +++ b/srsue/src/stack/mac/proc_ra.cc @@ -161,9 +161,9 @@ void ra_proc::state_pdcch_setup() rInfo("seq=%d, ra-rnti=0x%x, ra-tti=%d, f_id=%d", sel_preamble.load(), ra_rnti, info.tti_ra, info.f_id); srsran::console( "Random Access Transmission: seq=%d, tti=%d, ra-rnti=0x%x\n", sel_preamble.load(), info.tti_ra, ra_rnti); - rar_window_st = ra_tti + 3; + rar_window_st = ra_tti + 3; rntis->set_rar_rnti(ra_rnti); - state = RESPONSE_RECEPTION; + state = RESPONSE_RECEPTION; } else { rDebug("preamble not yet transmitted"); } @@ -228,7 +228,7 @@ void ra_proc::initialization() transmitted_contention_id = 0; preambleTransmissionCounter = 1; mux_unit->msg3_flush(); - backoff_param_ms = 0; + backoff_param_ms = 0; transmitted_crnti = 0; resource_selection(); } @@ -545,14 +545,14 @@ void ra_proc::timer_expired(uint32_t timer_id) */ bool ra_proc::contention_resolution_id_received(uint64_t rx_contention_id) { - task_queue.push([this, rx_contention_id]() { contention_resolution_id_received_unsafe(rx_contention_id); }); + task_queue.push([this, rx_contention_id]() { contention_resolution_id_received_nolock(rx_contention_id); }); return (transmitted_contention_id == rx_contention_id); } /* * Performs the actions defined in 5.1.5 for Temporal C-RNTI Contention Resolution */ -bool ra_proc::contention_resolution_id_received_unsafe(uint64_t rx_contention_id) +bool ra_proc::contention_resolution_id_received_nolock(uint64_t rx_contention_id) { bool uecri_successful = false; diff --git a/srsue/src/stack/mac_nr/mac_nr.cc b/srsue/src/stack/mac_nr/mac_nr.cc index 4e6d271f7..9f0bf0546 100644 --- a/srsue/src/stack/mac_nr/mac_nr.cc +++ b/srsue/src/stack/mac_nr/mac_nr.cc @@ -155,7 +155,7 @@ void mac_nr::update_buffer_states() mac_interface_phy_nr::sched_rnti_t mac_nr::get_ul_sched_rnti_nr(const uint32_t tti) { - return {c_rnti, srsran_rnti_type_c}; + return {rntis.get_crnti(), srsran_rnti_type_c}; } bool mac_nr::is_si_opportunity() @@ -200,12 +200,12 @@ mac_interface_phy_nr::sched_rnti_t mac_nr::get_dl_sched_rnti_nr(const uint32_t t bool mac_nr::has_crnti() { - return c_rnti != SRSRAN_INVALID_RNTI; + return rntis.get_crnti() != SRSRAN_INVALID_RNTI; } uint16_t mac_nr::get_crnti() { - return c_rnti; + return rntis.get_crnti(); } uint16_t mac_nr::get_temp_crnti() @@ -218,6 +218,11 @@ srsran::mac_sch_subpdu_nr::lcg_bsr_t mac_nr::generate_sbsr() return proc_bsr.generate_sbsr(); } +void mac_nr::set_padding_bytes(uint32_t nof_bytes) +{ + proc_bsr.set_padding_bytes(nof_bytes); +} + void mac_nr::bch_decoded_ok(uint32_t tti, srsran::unique_byte_buffer_t payload) { // Send MIB to RLC @@ -336,7 +341,7 @@ void mac_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant, *action = {}; // 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 == get_crnti()) { proc_ra.pdcch_to_crnti(); } @@ -436,14 +441,14 @@ void mac_nr::set_config(const srsran::rach_nr_cfg_t& rach_cfg) void mac_nr::set_contention_id(uint64_t ue_identity) { - contention_id = ue_identity; + rntis.set_contention_id(ue_identity); } bool mac_nr::set_crnti(const uint16_t c_rnti_) { if (is_valid_crnti(c_rnti_)) { logger.info("Setting C-RNTI to 0x%X", c_rnti_); - c_rnti = c_rnti_; + rntis.set_crnti(c_rnti_); return true; } else { logger.warning("Failed to set C-RNTI, 0x%X is not valid.", c_rnti_); diff --git a/srsue/src/stack/mac_nr/mux_nr.cc b/srsue/src/stack/mac_nr/mux_nr.cc index 3703e7ac5..f54f37aa8 100644 --- a/srsue/src/stack/mac_nr/mux_nr.cc +++ b/srsue/src/stack/mac_nr/mux_nr.cc @@ -72,14 +72,15 @@ 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); if (msg3_is_pending()) { - // If Msg3 is pending, pack it - // 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_sbsr_ce(mac.generate_sbsr()); + // only C-RNTI or CCCH SDU can be transmitted in Msg3 + if (mac.has_crnti()) { + tx_pdu.add_crnti_ce(mac.get_crnti()); + } + // TODO: add CCCH check msg3_transmitted(); } else { // Pack normal UL data PDU - int32_t remaining_len = tx_pdu.get_remaing_len(); // local variable to reserv space for CEs + int32_t remaining_len = tx_pdu.get_remaing_len(); // local variable to reserve space for CEs if (add_bsr_ce == sbsr_ce) { // reserve space for SBSR @@ -124,16 +125,26 @@ srsran::unique_byte_buffer_t mux_nr::get_pdu(uint32_t max_pdu_len) } } } + } - // Second add fixed-sized MAC CEs (e.g. SBSR) - if (add_bsr_ce == sbsr_ce) { - tx_pdu.add_sbsr_ce(mac.generate_sbsr()); - add_bsr_ce = no_bsr; - } + // check if + if (add_bsr_ce == no_bsr) { + // tell BSR proc we still have space in PDU and let it decide to create a padding BSR + mac.set_padding_bytes(tx_pdu.get_remaing_len()); + } - // Lastly, add variable-sized MAC CEs + // Second add fixed-sized MAC CEs (e.g. SBSR) + if (add_bsr_ce == sbsr_ce) { + tx_pdu.add_sbsr_ce(mac.generate_sbsr()); + add_bsr_ce = no_bsr; + } else if (add_bsr_ce == lbsr_ce) { + // TODO: implement LBSR support + tx_pdu.add_sbsr_ce(mac.generate_sbsr()); + add_bsr_ce = no_bsr; } + // Lastly, add variable-sized MAC CEs + // Pack PDU tx_pdu.pack(); diff --git a/srsue/src/stack/mac_nr/proc_bsr_nr.cc b/srsue/src/stack/mac_nr/proc_bsr_nr.cc index bcd3fb50f..e3b106467 100644 --- a/srsue/src/stack/mac_nr/proc_bsr_nr.cc +++ b/srsue/src/stack/mac_nr/proc_bsr_nr.cc @@ -218,8 +218,8 @@ void proc_bsr_nr::new_grant_ul(uint32_t grant_size) sr->reset(); } -// This function is called by MUX only if Regular BSR has not been triggered before -bool proc_bsr_nr::generate_padding_bsr(uint32_t nof_padding_bytes) +// This function is called by MUX only if no BSR has been triggered before +void proc_bsr_nr::set_padding_bytes(uint32_t nof_bytes) { std::lock_guard lock(mutex); @@ -228,16 +228,14 @@ bool proc_bsr_nr::generate_padding_bsr(uint32_t nof_padding_bytes) const uint32_t LBSR_CE_SUBHEADER_LEN = 1; // if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller // than the size of the Long BSR plus its subheader - if (nof_padding_bytes >= SBSR_CE_SUBHEADER_LEN + srsran::mac_sch_subpdu_nr::sizeof_ce(SHORT_BSR, true) && - nof_padding_bytes <= LBSR_CE_SUBHEADER_LEN + srsran::mac_sch_subpdu_nr::sizeof_ce(LONG_BSR, true)) { - // generate padding BSR - set_trigger(PADDING); - // generate_bsr(bsr, nof_padding_bytes); - set_trigger(NONE); - return true; + if (nof_bytes >= SBSR_CE_SUBHEADER_LEN + srsran::mac_sch_subpdu_nr::sizeof_ce(SHORT_BSR, true) && + nof_bytes < LBSR_CE_SUBHEADER_LEN + srsran::mac_sch_subpdu_nr::sizeof_ce(LONG_BSR, true)) { + // generate short padding BSR + mux->generate_bsr_mac_ce(SHORT_BSR); + } else if (nof_bytes >= LBSR_CE_SUBHEADER_LEN + srsran::mac_sch_subpdu_nr::sizeof_ce(LONG_BSR, true)) { + // report Long BSR if more than one LCG has data to send + mux->generate_bsr_mac_ce(LONG_BSR); } - - return false; } int proc_bsr_nr::setup_lcid(uint32_t lcid, uint32_t new_lcg, uint32_t priority) diff --git a/srsue/src/stack/mac_nr/proc_sr_nr.cc b/srsue/src/stack/mac_nr/proc_sr_nr.cc index 6897efd09..b84494a55 100644 --- a/srsue/src/stack/mac_nr/proc_sr_nr.cc +++ b/srsue/src/stack/mac_nr/proc_sr_nr.cc @@ -44,10 +44,10 @@ int32_t proc_sr_nr::init(mac_interface_sr_nr* mac_, phy_interface_mac_nr* phy_, void proc_sr_nr::reset() { std::lock_guard lock(mutex); - reset_unsafe(); + reset_nolock(); } -void proc_sr_nr::reset_unsafe() +void proc_sr_nr::reset_nolock() { is_pending_sr = false; } @@ -101,7 +101,7 @@ void proc_sr_nr::step(uint32_t tti) // 2> initiate a Random Access procedure (see clause 5.1) on the SpCell and cancel the pending SR. logger.info("SR: PUCCH not configured. Starting RA procedure"); mac->start_ra(); - reset_unsafe(); + reset_nolock(); return; } @@ -119,7 +119,7 @@ void proc_sr_nr::step(uint32_t tti) // ... TODO mac->start_ra(); - reset_unsafe(); + reset_nolock(); } } diff --git a/srsue/src/stack/mac_nr/test/mac_nr_test.cc b/srsue/src/stack/mac_nr/test/mac_nr_test.cc index f423fbdc0..014bcac36 100644 --- a/srsue/src/stack/mac_nr/test/mac_nr_test.cc +++ b/srsue/src/stack/mac_nr/test/mac_nr_test.cc @@ -220,10 +220,12 @@ int mac_nr_ul_logical_channel_prioritization_test1() // PDU layout (20B in total) // - 2 B MAC subheader for SCH LCID=4 // - 10 B sduPDU + // - 1 B subheader SBRS (padding BSR) + // - 1 B SBSR (BSR will report bytes to transmit because BSR state isn't updated after packing PDU yet) // - 1 B subheader padding - // - 7 B padding + // - 5 B padding const uint8_t tv[] = {0x04, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + 0x04, 0x04, 0x3d, 0xc1, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00}; // dummy layers dummy_phy phy; diff --git a/srsue/src/stack/rrc/CMakeLists.txt b/srsue/src/stack/rrc/CMakeLists.txt index 7d83545e8..d797aa4ef 100644 --- a/srsue/src/stack/rrc/CMakeLists.txt +++ b/srsue/src/stack/rrc/CMakeLists.txt @@ -20,7 +20,7 @@ add_subdirectory(test) -set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc rrc_common.cc rrc_rlf_report.cc phy_controller.cc) +set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc rrc_rlf_report.cc phy_controller.cc) add_library(srsue_rrc STATIC ${SOURCES}) set(SOURCES rrc_nr.cc) diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index e3c00849b..4479827d2 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -2119,10 +2119,12 @@ void rrc::handle_ue_capability_enquiry(const ue_cap_enquiry_s& enquiry) irat_params_nr_r15.en_dc_r15_present = true; irat_params_nr_r15.supported_band_list_en_dc_r15_present = true; - supported_band_nr_r15_s supported_band_nr_r15; - supported_band_nr_r15.band_nr_r15 = 78; + uint32_t nof_supported_nr_bands = args.supported_bands_nr.size(); + irat_params_nr_r15.supported_band_list_en_dc_r15.resize(nof_supported_nr_bands); + for (uint32_t k = 0; k < nof_supported_nr_bands; k++) { + irat_params_nr_r15.supported_band_list_en_dc_r15[k].band_nr_r15 = args.supported_bands_nr[k]; + } - irat_params_nr_r15.supported_band_list_en_dc_r15.push_back(supported_band_nr_r15); ue_eutra_cap_v1450_ies->non_crit_ext.non_crit_ext.irat_params_nr_r15_present = true; ue_eutra_cap_v1450_ies->non_crit_ext.non_crit_ext.irat_params_nr_r15 = irat_params_nr_r15; ue_eutra_cap_v1450_ies->non_crit_ext.non_crit_ext.non_crit_ext_present = true; diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 79606f703..6a782f7cf 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -712,8 +712,8 @@ bool rrc_nr::apply_res_csi_report_cfg(const asn1::rrc_nr::csi_report_cfg_s& csi_ uint32_t res_id = csi_report_cfg.report_cfg_type.periodic() .pucch_csi_res_list[0] .pucch_res; // TODO: support and check more items - if (res_list_present[res_id] == true) { - phy_cfg.csi.reports[report_cfg_id].periodic.resource = res_list[res_id]; + if (pucch_res_list.contains(res_id)) { + phy_cfg.csi.reports[report_cfg_id].periodic.resource = pucch_res_list[res_id]; } else { logger.error("Resources set not present for assigning pucch sets (res_id %d)", res_id); return false; @@ -734,9 +734,6 @@ bool rrc_nr::apply_csi_meas_cfg(const asn1::rrc_nr::csi_meas_cfg_s& csi_meas_cfg return false; } } - } else { - logger.warning("Option csi_report_cfg_to_add_mod_list not present"); - return false; } if (csi_meas_cfg.nzp_csi_rs_res_to_add_mod_list_present) { @@ -762,7 +759,7 @@ bool rrc_nr::apply_csi_meas_cfg(const asn1::rrc_nr::csi_meas_cfg_s& csi_meas_cfg uint8_t res = csi_meas_cfg.nzp_csi_rs_res_set_to_add_mod_list[i].nzp_csi_rs_res[j]; // use temporally stored values to assign if (csi_rs_nzp_res.find(res) == csi_rs_nzp_res.end()) { - logger.warning("Can not find p_zp_csi_rs_res in temporally stored csi_rs_zp_res"); + logger.warning("Can not find nzp_csi_rs_res in temporally stored csi_rs_nzp_res"); return false; } phy_cfg.pdsch.nzp_csi_rs_sets[set_id].data[j] = csi_rs_nzp_res[res]; @@ -1011,9 +1008,8 @@ bool rrc_nr::apply_sp_cell_ded_ul_pucch(const asn1::rrc_nr::pucch_cfg_s& pucch_c if (pucch_cfg.res_to_add_mod_list_present) { for (uint32_t i = 0; i < pucch_cfg.res_to_add_mod_list.size(); i++) { uint32_t res_id = pucch_cfg.res_to_add_mod_list[i].pucch_res_id; - if (make_phy_res_config(pucch_cfg.res_to_add_mod_list[i], format_2_max_code_rate, &res_list[res_id]) == true) { - res_list_present[res_id] = true; - } else { + pucch_res_list.insert(res_id, {}); + if (!make_phy_res_config(pucch_cfg.res_to_add_mod_list[i], format_2_max_code_rate, &pucch_res_list[res_id])) { logger.warning("Warning while building pucch_nr_resource structure"); return false; } @@ -1031,8 +1027,8 @@ bool rrc_nr::apply_sp_cell_ded_ul_pucch(const asn1::rrc_nr::pucch_cfg_s& pucch_c phy_cfg.pucch.sets[set_id].nof_resources = pucch_cfg.res_set_to_add_mod_list[i].res_list.size(); for (uint32_t j = 0; j < pucch_cfg.res_set_to_add_mod_list[i].res_list.size(); j++) { uint32_t res_id = pucch_cfg.res_set_to_add_mod_list[i].res_list[j]; - if (res_list_present[res_id] == true) { - phy_cfg.pucch.sets[set_id].resources[j] = res_list[res_id]; + if (pucch_res_list.contains(res_id)) { + phy_cfg.pucch.sets[set_id].resources[j] = pucch_res_list[res_id]; } else { logger.error( "Resources set not present for assign pucch sets (res_id %d, setid %d, j %d)", res_id, set_id, j); @@ -1043,24 +1039,26 @@ bool rrc_nr::apply_sp_cell_ded_ul_pucch(const asn1::rrc_nr::pucch_cfg_s& pucch_c if (pucch_cfg.sched_request_res_to_add_mod_list_present) { for (uint32_t i = 0; i < pucch_cfg.sched_request_res_to_add_mod_list.size(); i++) { - uint32_t res_id = pucch_cfg.sched_request_res_to_add_mod_list[i].sched_request_res_id; + uint32_t sr_res_id = pucch_cfg.sched_request_res_to_add_mod_list[i].sched_request_res_id; srsran_pucch_nr_sr_resource_t srsran_pucch_nr_sr_resource; if (make_phy_sr_resource(pucch_cfg.sched_request_res_to_add_mod_list[i], &srsran_pucch_nr_sr_resource) == true) { // TODO: fix that if indexing is solved - phy_cfg.pucch.sr_resources[res_id] = srsran_pucch_nr_sr_resource; + phy_cfg.pucch.sr_resources[sr_res_id] = srsran_pucch_nr_sr_resource; // Set PUCCH resource if (pucch_cfg.sched_request_res_to_add_mod_list[i].res_present) { uint32_t pucch_res_id = pucch_cfg.sched_request_res_to_add_mod_list[i].res; - if (res_list_present[res_id]) { - phy_cfg.pucch.sr_resources[res_id].resource = res_list[pucch_res_id]; + if (pucch_res_list.contains(pucch_res_id)) { + phy_cfg.pucch.sr_resources[sr_res_id].resource = pucch_res_list[pucch_res_id]; } else { - logger.warning("Warning SR's PUCCH resource is invalid (%d)", pucch_res_id); - phy_cfg.pucch.sr_resources[res_id].configured = false; + logger.warning("Warning SR (%d) PUCCH resource is invalid (%d)", sr_res_id, pucch_res_id); + phy_cfg.pucch.sr_resources[sr_res_id].configured = false; + return false; } } else { logger.warning("Warning SR resource is present but no PUCCH resource is assigned to it"); - phy_cfg.pucch.sr_resources[res_id].configured = false; + phy_cfg.pucch.sr_resources[sr_res_id].configured = false; + return false; } } else { @@ -1202,6 +1200,7 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) } if (recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present) { + logger.info("TDD UL DL config present, using TDD"); srsran_duplex_config_nr_t duplex; if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &duplex) == true) { phy_cfg.duplex = duplex; @@ -1210,8 +1209,7 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) return false; } } else { - logger.warning("TDD UL DL config not present"); - return false; + logger.info("TDD UL DL config not present, using FDD"); } } } else { diff --git a/srsue/src/stack/rrc/rrc_rlf_report.cc b/srsue/src/stack/rrc/rrc_rlf_report.cc index 12c2d29f3..eb5f977e3 100644 --- a/srsue/src/stack/rrc/rrc_rlf_report.cc +++ b/srsue/src/stack/rrc/rrc_rlf_report.cc @@ -20,7 +20,7 @@ */ #include "srsue/hdr/stack/rrc/rrc_rlf_report.h" -#include "srsue/hdr/stack/rrc/rrc_common.h" +#include "srsran/rrc/rrc_common.h" namespace srsue { @@ -48,9 +48,9 @@ void rrc_rlf_report::set_failure(meas_cell_list& meas_cells, fa // set the measResultLastServCell to include the RSRP and RSRQ, if available, of the PCell based on // measurements collected up to the moment the UE detected radio link failure rlf_report.meas_result_last_serv_cell_r9.rsrp_result_r9 = - rrc_value_to_range(quant_rsrp, meas_cells.serving_cell().get_rsrp()); + rrc_value_to_range(srsran::quant_rsrp, meas_cells.serving_cell().get_rsrp()); rlf_report.meas_result_last_serv_cell_r9.rsrq_result_r9 = - rrc_value_to_range(quant_rsrq, meas_cells.serving_cell().get_rsrq()); + rrc_value_to_range(srsran::quant_rsrq, meas_cells.serving_cell().get_rsrq()); rlf_report.meas_result_last_serv_cell_r9.rsrq_result_r9_present = true; // set the measResultNeighCells to include the best measured cells, other than the PCell, ordered such that @@ -70,8 +70,8 @@ void rrc_rlf_report::set_failure(meas_cell_list& meas_cells, fa meas.pci = f->get_pci(); meas.meas_result.rsrp_result_present = true; meas.meas_result.rsrq_result_present = true; - meas.meas_result.rsrp_result = rrc_value_to_range(quant_rsrp, f->get_rsrp()); - meas.meas_result.rsrq_result = rrc_value_to_range(quant_rsrq, f->get_rsrq()); + meas.meas_result.rsrp_result = rrc_value_to_range(srsran::quant_rsrp, f->get_rsrp()); + meas.meas_result.rsrq_result = rrc_value_to_range(srsran::quant_rsrq, f->get_rsrq()); meas2.meas_result_list_r9.push_back(meas); rlf_report.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.push_back(meas2); } diff --git a/srsue/src/stack/rrc/test/rrc_meas_test.cc b/srsue/src/stack/rrc/test/rrc_meas_test.cc index 3548f7f6e..49d43942a 100644 --- a/srsue/src/stack/rrc/test/rrc_meas_test.cc +++ b/srsue/src/stack/rrc/test/rrc_meas_test.cc @@ -253,7 +253,7 @@ private: bool meas_res_received = false; }; -class rrc_test : public rrc +class rrc_test : public srsue::rrc { stack_test_dummy* stack = nullptr; diff --git a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc index 5626836d2..5b57fec13 100644 --- a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc @@ -71,6 +71,7 @@ class dummy_rlc : public rlc_interface_rrc class dummy_pdcp : public pdcp_interface_rrc { + void set_enabled(uint32_t lcid, bool enabled) {}; void reestablish(){}; void reestablish(uint32_t lcid){}; void reset(){}; diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index 242939dc2..5d1c1176e 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -188,6 +188,13 @@ void gw::write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) int gw::setup_if_addr(uint32_t eps_bearer_id, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_addr, char* err_str) { int err; + + // Make sure the worker thread is terminated before spawning a new one. + if (running) { + run_enable = false; + thread_cancel(); + wait_thread_finish(); + } if (pdn_type == LIBLTE_MME_PDN_TYPE_IPV4 || pdn_type == LIBLTE_MME_PDN_TYPE_IPV4V6) { err = setup_if_addr4(ip_addr, err_str); if (err != SRSRAN_SUCCESS) { @@ -204,6 +211,7 @@ int gw::setup_if_addr(uint32_t eps_bearer_id, uint8_t pdn_type, uint32_t ip_addr default_eps_bearer_id = static_cast(eps_bearer_id); // Setup a thread to receive packets from the TUN device + run_enable = true; start(GW_THREAD_PRIO); return SRSRAN_SUCCESS; @@ -455,6 +463,9 @@ int gw::setup_if_addr4(uint32_t ip_addr, char* err_str) } } + if (sock > 0) { + close(sock); + } // Setup the IP address sock = socket(AF_INET, SOCK_DGRAM, 0); ifr.ifr_addr.sa_family = AF_INET; @@ -504,6 +515,9 @@ int gw::setup_if_addr6(uint8_t* ipv6_if_id, char* err_str) } } + if (sock > 0) { + close(sock); + } // Setup the IP address sock = socket(AF_INET6, SOCK_DGRAM, 0); ifr.ifr_addr.sa_family = AF_INET6; diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc index 18cf6571b..265e0dade 100644 --- a/srsue/src/stack/upper/nas_5g.cc +++ b/srsue/src/stack/upper/nas_5g.cc @@ -57,7 +57,9 @@ nas_5g::nas_5g(srslog::basic_logger& logger_, srsran::task_sched_handle task_sch t3511(task_sched_.get_unique_timer()), t3521(task_sched_.get_unique_timer()), reregistration_timer(task_sched_.get_unique_timer()), - registration_proc(this) + registration_proc(this), + state(logger_), + pdu_session_establishment_proc(this, logger_) { // Configure timers t3502.set(t3502_duration_ms, [this](uint32_t tid) { timer_expired(tid); }); @@ -103,6 +105,10 @@ int nas_5g::init(usim_interface_nas* usim_, ea5g_caps[3] = true; } + if (init_pdu_sessions(cfg.pdu_session_cfgs) != SRSRAN_SUCCESS) { + logger.warning("Failure while configuring pdu sessions"); + } + running = true; return SRSRAN_SUCCESS; } @@ -145,6 +151,94 @@ void nas_5g::run_tti() } } +int nas_5g::write_pdu(srsran::unique_byte_buffer_t pdu) +{ + logger.info(pdu->msg, pdu->N_bytes, "DL PDU (length %d)", pdu->N_bytes); + + nas_5gs_msg nas_msg; + + if (nas_msg.unpack_outer_hdr(pdu) != SRSRAN_SUCCESS) { + logger.error("Unable to unpack outer NAS header"); + return SRSRAN_ERROR; + } + + switch (nas_msg.hdr.security_header_type) { + case nas_5gs_hdr::security_header_type_opts::plain_5gs_nas_message: + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected: + if (integrity_check(pdu.get()) == false) { + logger.error("Not handling NAS message with integrity check error"); + return SRSRAN_ERROR; + } + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered: + if (integrity_check(pdu.get()) == false) { + logger.error("Not handling NAS message with integrity check error"); + return SRSRAN_ERROR; + } else { + cipher_decrypt(pdu.get()); + } + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected_with_new_5G_nas_context: + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered_with_new_5G_nas_context: + return SRSRAN_ERROR; + default: + logger.error("Not handling NAS message with unkown security header"); + break; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu->msg, pdu->N_bytes); + } + + logger.info(pdu->msg, pdu->N_bytes, "Decrypted DL PDU (length %d)", pdu->N_bytes); + + // Parse the message header + if (nas_msg.unpack(pdu) != SRSRAN_SUCCESS) { + logger.error("Unable to unpack complete NAS pdu"); + return SRSRAN_ERROR; + } + + switch (nas_msg.hdr.message_type) { + case msg_opts::options::registration_accept: + handle_registration_accept(nas_msg.registration_accept()); + break; + case msg_opts::options::registration_reject: + handle_registration_reject(nas_msg.registration_reject()); + break; + case msg_opts::options::authentication_request: + handle_authentication_request(nas_msg.authentication_request()); + break; + case msg_opts::options::identity_request: + handle_identity_request(nas_msg.identity_request()); + break; + case msg_opts::options::security_mode_command: + handle_security_mode_command(nas_msg.security_mode_command(), std::move(pdu)); + break; + case msg_opts::options::service_accept: + handle_service_accept(nas_msg.service_accept()); + break; + case msg_opts::options::service_reject: + handle_service_reject(nas_msg.service_reject()); + break; + case msg_opts::options::deregistration_accept_ue_terminated: + handle_deregistration_accept_ue_terminated(nas_msg.deregistration_accept_ue_terminated()); + break; + case msg_opts::options::deregistration_request_ue_terminated: + handle_deregistration_request_ue_terminated(nas_msg.deregistration_request_ue_terminated()); + break; + case msg_opts::options::dl_nas_transport: + handle_dl_nas_transport(nas_msg.dl_nas_transport()); + break; + default: + logger.error( + "Not handling NAS message type: %s (0x%02x)", nas_msg.hdr.message_type.to_string(), nas_msg.hdr.message_type); + break; + } + return SRSRAN_SUCCESS; +} + /******************************************************************************* * Senders ******************************************************************************/ @@ -159,25 +253,27 @@ int nas_5g::send_registration_request() logger.info("Generating registration request"); - nas_5gs_msg nas_msg; - nas_msg.hdr.extended_protocol_discriminator = + initial_registration_request_stored.hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_opts::extended_protocol_discriminator_5gmm; - registration_request_t& reg_req = nas_msg.set_registration_request(); + registration_request_t& reg_req = initial_registration_request_stored.set_registration_request(); reg_req.registration_type_5gs.follow_on_request_bit = - registration_type_5gs_t::follow_on_request_bit_type_::options::no_follow_on_request_pending; + registration_type_5gs_t::follow_on_request_bit_type_::options::follow_on_request_pending; reg_req.registration_type_5gs.registration_type = registration_type_5gs_t::registration_type_type_::options::initial_registration; mobile_identity_5gs_t::suci_s& suci = reg_req.mobile_identity_5gs.set_suci(); suci.supi_format = mobile_identity_5gs_t::suci_s::supi_format_type_::options::imsi; usim->get_home_mcc_bytes(suci.mcc.data(), suci.mcc.size()); - usim->get_home_mcc_bytes(suci.mnc.data(), suci.mnc.size()); + usim->get_home_mnc_bytes(suci.mnc.data(), suci.mnc.size()); suci.scheme_output.resize(5); usim->get_home_msin_bcd(suci.scheme_output.data(), 5); logger.info("Requesting IMSI attach (IMSI=%s)", usim->get_imsi_str().c_str()); - if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + reg_req.ue_security_capability_present = true; + fill_security_caps(reg_req.ue_security_capability); + + if (initial_registration_request_stored.pack(pdu) != SRSASN_SUCCESS) { logger.error("Failed to pack registration request"); return SRSRAN_ERROR; } @@ -190,17 +286,524 @@ int nas_5g::send_registration_request() logger.debug("Starting T3410. Timeout in %d ms.", t3510.duration()); t3510.run(); + if (rrc_nr->is_connected() == true) { + rrc_nr->write_sdu(std::move(pdu)); + } else { + logger.debug("Initiating RRC NR Connection"); + if (rrc_nr->connection_request(nr_establishment_cause_t::mo_Signalling, std::move(pdu)) != SRSRAN_SUCCESS) { + logger.warning("Error starting RRC NR connection"); + return SRSRAN_ERROR; + } + } + state.set_registered_initiated(); return SRSRAN_SUCCESS; } -/******************************************************************************* - * UE Stack and RRC common Interface - ******************************************************************************/ -bool nas_5g::is_registered() +int nas_5g::send_registration_complete() { - return state.get_state() == mm5g_state_t::state_t::registered; + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + logger.info("Generating Registration Complete"); + + nas_5gs_msg nas_msg; + registration_complete_t& reg_comp = nas_msg.set_registration_complete(); + + if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack registration complete."); + return SRSRAN_ERROR; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + logger.info("Sending Registration Complete"); + rrc_nr->write_sdu(std::move(pdu)); + + return SRSRAN_SUCCESS; +} + +int nas_5g::send_authentication_response(const uint8_t res[16]) +{ + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + logger.info("Generating Authentication Response"); + + nas_5gs_msg nas_msg; + authentication_response_t& auth_resp = nas_msg.set_authentication_response(); + auth_resp.authentication_response_parameter_present = true; + auth_resp.authentication_response_parameter.res.resize(16); + memcpy(auth_resp.authentication_response_parameter.res.data(), res, 16); + + if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack authentication response"); + return SRSRAN_ERROR; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + logger.info("Sending Authentication Response"); + rrc_nr->write_sdu(std::move(pdu)); + + return SRSRAN_SUCCESS; +} + +int nas_5g::send_security_mode_reject(const cause_5gmm_t::cause_5gmm_type_::options cause) +{ + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + nas_5gs_msg nas_msg; + security_mode_reject_t& security_mode_reject = nas_msg.set_security_mode_reject(); + security_mode_reject.cause_5gmm.cause_5gmm = cause; + + if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack authentication response"); + return SRSRAN_ERROR; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + logger.info("Sending Authentication Response"); + rrc_nr->write_sdu(std::move(pdu)); + + return SRSRAN_SUCCESS; +} + +int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_command_t& security_mode_command) +{ + uint8_t current_sec_hdr = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT; + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + logger.info("Generating Security Mode Complete"); + + nas_5gs_msg nas_msg; + security_mode_complete_t& security_mode_complete = nas_msg.set_security_mode_complete(); + + if (security_mode_command.imeisv_request_present) { + security_mode_complete.imeisv_present = true; + mobile_identity_5gs_t::imeisv_s& imeisv = security_mode_complete.imeisv.set_imeisv(); + usim->get_imei_vec(imeisv.imeisv.data(), 15); + imeisv.imeisv[14] = ue_svn_oct1; + imeisv.imeisv[15] = ue_svn_oct2; + } + + registration_request_t& modified_registration_request = initial_registration_request_stored.registration_request(); + modified_registration_request.capability_5gmm_present = true; + modified_registration_request.requested_nssai_present = true; + modified_registration_request.update_type_5gs_present = true; + + s_nssai_t s_nssai; + s_nssai.type = s_nssai_t::SST_type_::options::sst; + s_nssai.sst = 1; + modified_registration_request.requested_nssai.s_nssai_list = {s_nssai}; + + modified_registration_request.capability_5gmm.lpp = 0; + modified_registration_request.capability_5gmm.ho_attach = 0; + modified_registration_request.capability_5gmm.s1_mode = 0; + + modified_registration_request.update_type_5gs.ng_ran_rcu.value = + update_type_5gs_t::NG_RAN_RCU_type::options::ue_radio_capability_update_not_needed; + modified_registration_request.update_type_5gs.sms_requested.value = + update_type_5gs_t::SMS_requested_type::options::sms_over_nas_not_supported; + + security_mode_complete.nas_message_container_present = true; + initial_registration_request_stored.pack(security_mode_complete.nas_message_container.nas_message_container); + + nas_msg.hdr.security_header_type = + nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered_with_new_5G_nas_context; + nas_msg.hdr.sequence_number = ctxt.tx_count; + + if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack security mode complete"); + return SRSRAN_ERROR; + } + + cipher_encrypt(pdu.get()); + integrity_generate(&k_nas_int[16], + ctxt.tx_count, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[SEQ_5G_OFFSET], + pdu->N_bytes - SEQ_5G_OFFSET, + &pdu->msg[MAC_5G_OFFSET]); + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + logger.info("Sending Security Mode Complete"); + rrc_nr->write_sdu(std::move(pdu)); + ctxt.tx_count++; + + return SRSRAN_SUCCESS; +} + +int nas_5g::send_authentication_failure(const cause_5gmm_t::cause_5gmm_type_::options cause, + const uint8_t* auth_fail_param) +{ + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + nas_5gs_msg nas_msg; + authentication_failure_t& auth_fail = nas_msg.set_authentication_failure(); + + if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack authentication failure."); + return SRSRAN_ERROR; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + logger.info("Sending Authentication Failure"); + rrc_nr->write_sdu(std::move(pdu)); + + return SRSRAN_SUCCESS; +} + +uint32_t nas_5g::allocate_next_proc_trans_id() +{ + uint32_t i = 0; + for (auto pdu_trans_id : pdu_trans_ids) { + i++; + if (pdu_trans_id == false) { + pdu_trans_id = true; + } + } + // TODO if Trans ID exhausted + return i; +} + +void nas_5g::release_proc_trans_id(uint32_t proc_id) +{ + if (proc_id < MAX_TRANS_ID) { + pdu_trans_ids[proc_id] = false; + } + return; +} + +int nas_5g::send_pdu_session_establishment_request(uint32_t transaction_identity, + uint16_t pdu_session_id, + const pdu_session_cfg_t& pdu_session_cfg) +{ + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + logger.info("Generating PDU Session Establishment Request"); + + nas_5gs_msg nas_msg; + nas_msg.hdr.pdu_session_identity = pdu_session_id; + nas_msg.hdr.procedure_transaction_identity = transaction_identity; + + pdu_session_establishment_request_t& pdu_ses_est_req = nas_msg.set_pdu_session_establishment_request(); + pdu_ses_est_req.integrity_protection_maximum_data_rate.max_data_rate_upip_downlink = + integrity_protection_maximum_data_rate_t::max_data_rate_UPIP_downlink_type_::options::full_data_rate; + pdu_ses_est_req.integrity_protection_maximum_data_rate.max_data_rate_upip_uplink = + integrity_protection_maximum_data_rate_t::max_data_rate_UPIP_uplink_type_::options::full_data_rate; + + pdu_ses_est_req.pdu_session_type_present = true; + pdu_ses_est_req.pdu_session_type.pdu_session_type_value = + static_cast(pdu_session_cfg.apn_type); + + pdu_ses_est_req.ssc_mode_present = true; + pdu_ses_est_req.ssc_mode.ssc_mode_value = ssc_mode_t::SSC_mode_value_type_::options::ssc_mode_1; + + // TODO set the capability and extended protocol configuration + pdu_ses_est_req.capability_5gsm_present = false; + pdu_ses_est_req.extended_protocol_configuration_options_present = false; + + // Build up the Envelope for the PDU session request + nas_5gs_msg env_nas_msg; + env_nas_msg.hdr.security_header_type = nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered; + + // TODO move that seq number setting to the security part + env_nas_msg.hdr.sequence_number = ctxt.tx_count; + + ul_nas_transport_t& ul_nas_msg = env_nas_msg.set_ul_nas_transport(); + ul_nas_msg.payload_container_type.payload_container_type.value = + payload_container_type_t::Payload_container_type_type_::options::n1_sm_information; + + // Pack the pdu session est request into the envelope + if (nas_msg.pack(ul_nas_msg.payload_container.payload_container_contents) != SRSASN_SUCCESS) { + logger.error("Failed to pack PDU Session Establishment Request."); + return SRSRAN_ERROR; + } + + ul_nas_msg.pdu_session_id_present = true; + ul_nas_msg.pdu_session_id.pdu_session_identity_2_value = pdu_session_id; + + ul_nas_msg.request_type_present = true; + ul_nas_msg.request_type.request_type_value = request_type_t::Request_type_value_type_::options::initial_request; + + ul_nas_msg.s_nssai_present = true; + ul_nas_msg.s_nssai.type = s_nssai_t::SST_type_::options::sst; + ul_nas_msg.s_nssai.sst = 1; + + ul_nas_msg.dnn_present = true; + ul_nas_msg.dnn.dnn_value.resize(pdu_session_cfg.apn_name.size() + 1); + ul_nas_msg.dnn.dnn_value.data()[0] = static_cast(pdu_session_cfg.apn_name.size()); + + memcpy(ul_nas_msg.dnn.dnn_value.data() + 1, pdu_session_cfg.apn_name.data(), pdu_session_cfg.apn_name.size()); + + if (env_nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack UL NAS transport."); + return SRSRAN_ERROR; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + cipher_encrypt(pdu.get()); + integrity_generate(&k_nas_int[16], + ctxt.tx_count, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[SEQ_5G_OFFSET], + pdu->N_bytes - SEQ_5G_OFFSET, + &pdu->msg[MAC_5G_OFFSET]); + + logger.info("Sending PDU Session Establishment Request in UL NAS transport."); + rrc_nr->write_sdu(std::move(pdu)); + + return SRSRAN_SUCCESS; +} + +// Message handler +int nas_5g::handle_registration_accept(registration_accept_t& registration_accept) +{ + if (state.get_state() != mm5g_state_t::state_t::registered_initiated) { + logger.warning("Not compatibale with current state %s", state.get_full_state_text()); + return SRSRAN_ERROR; + } + + bool send_reg_complete = false; + logger.info("Handling Registration Accept"); + if (registration_accept.guti_5g_present) { + guti_5g = registration_accept.guti_5g.guti_5g(); + send_reg_complete = true; + } + + // TODO: reset counters and everything what is needed by the specification + t3521.set(registration_accept.t3512_value.timer_value); + registration_proc.run(); + state.set_registered(mm5g_state_t::registered_substate_t::normal_service); + + if (send_reg_complete == true) { + send_registration_complete(); + } + // TODO: use the state machine to trigger that transition + trigger_pdu_session_est(); + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_registration_reject(registration_reject_t& registration_reject) +{ + logger.info("Handling Registration Reject"); + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_authentication_request(authentication_request_t& authentication_request) +{ + logger.info("Handling Registration Request"); + + // Generate authentication response using RAND, AUTN & KSI-ASME + uint16 mcc, mnc; + mcc = rrc_nr->get_mcc(); + mnc = rrc_nr->get_mnc(); + plmn_id_t plmn_id; + plmn_id.from_number(mcc, mnc); + + if (authentication_request.authentication_parameter_rand_present == false) { + logger.error("authentication_parameter_rand_present is not present"); + return SRSRAN_ERROR; + } + + if (authentication_request.authentication_parameter_autn_present == false) { + logger.error("authentication_parameter_autn_present is not present"); + return SRSRAN_ERROR; + } + + uint8_t res_star[16]; + + logger.info(authentication_request.authentication_parameter_rand.rand.data(), + authentication_request.authentication_parameter_rand.rand.size(), + "Authentication request RAND"); + + logger.info(authentication_request.authentication_parameter_autn.autn.data(), + authentication_request.authentication_parameter_rand.rand.size(), + "Authentication request AUTN"); + + logger.info("Serving network name %s", plmn_id.to_serving_network_name_string().c_str()); + auth_result_t auth_result = + usim->generate_authentication_response_5g(authentication_request.authentication_parameter_rand.rand.data(), + authentication_request.authentication_parameter_autn.autn.data(), + plmn_id.to_serving_network_name_string().c_str(), + authentication_request.abba.abba_contents.data(), + authentication_request.abba.abba_contents.size(), + res_star, + ctxt_5g.k_amf); + logger.info(ctxt_5g.k_amf, 32, "Generated k_amf:"); + if (auth_result == AUTH_OK) { + logger.info("Network authentication successful"); + send_authentication_response(res_star); + logger.info(res_star, 16, "Generated res_star (%d):", 16); + + } else if (auth_result == AUTH_SYNCH_FAILURE) { + logger.error("Network authentication synchronization failure."); + // send_authentication_failure(LIBLTE_MME_EMM_CAUSE_SYNCH_FAILURE, res); + } else { + logger.warning("Network authentication failure"); + srsran::console("Warning: Network authentication failure\n"); + // send_authentication_failure(LIBLTE_MME_EMM_CAUSE_MAC_FAILURE, nullptr); + } + + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_identity_request(identity_request_t& identity_request) +{ + logger.info("Handling Identity Request"); + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_service_accept(srsran::nas_5g::service_accept_t& service_accept) +{ + logger.info("Handling Service Accept"); + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_service_reject(srsran::nas_5g::service_reject_t& service_reject) +{ + logger.info("Handling Service Accept"); + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_security_mode_command(security_mode_command_t& security_mode_command, + srsran::unique_byte_buffer_t pdu) +{ + logger.info("Handling Security Mode Command"); + ctxt.cipher_algo = + (CIPHERING_ALGORITHM_ID_ENUM)security_mode_command.selected_nas_security_algorithms.ciphering_algorithm.value; + ctxt.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) + security_mode_command.selected_nas_security_algorithms.integrity_protection_algorithm.value; + + // Check capabilities + // TODO: Check replayed sec capabilities + if (!ea5g_caps[ctxt.cipher_algo] || !ia5g_caps[ctxt.integ_algo]) { + logger.warning("Sending Security Mode Reject due to security capabilities mismatch"); + send_security_mode_reject(cause_5gmm_t::cause_5gmm_type_::options::ue_security_capabilities_mismatch); + return SRSRAN_ERROR; + } + + initial_sec_command = false; // TODO + + if (initial_sec_command) { + ctxt.rx_count = 0; + ctxt.tx_count = 0; + initial_sec_command = false; + } + + // Generate NAS keys + logger.debug(ctxt_5g.k_amf, 32, "K AMF"); + logger.debug("cipher_algo %d, integ_algo %d", ctxt.cipher_algo, ctxt.integ_algo); + + usim->generate_nas_keys_5g(ctxt_5g.k_amf, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); + logger.info(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); + logger.info(k_nas_int, 32, "NAS integrity key - k_nas_int"); + + logger.debug("Generating integrity check. integ_algo:%d, count_dl:%d", ctxt.integ_algo, ctxt.rx_count); + + if (not integrity_check(pdu.get())) { + logger.warning("Sending Security Mode Reject due to integrity check failure"); + send_security_mode_reject(cause_5gmm_t::cause_5gmm_type_::options::mac_failure); + return SRSRAN_ERROR; + } + + send_security_mode_complete(security_mode_command); + ctxt.rx_count++; + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_deregistration_accept_ue_terminated( + deregistration_accept_ue_terminated_t& deregistration_accept_ue_terminated) +{ + logger.info("Handling Deregistration Accept UE Terminated"); + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_deregistration_request_ue_terminated( + deregistration_request_ue_terminated_t& deregistration_request_ue_terminated) +{ + logger.info("Handling Deregistration Request UE Terminated"); + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_dl_nas_transport(srsran::nas_5g::dl_nas_transport_t& dl_nas_transport) +{ + logger.info("Handling DL NAS transport"); + switch (dl_nas_transport.payload_container_type.payload_container_type) { + case payload_container_type_t::Payload_container_type_type_::options::n1_sm_information: + return handle_n1_sm_information(dl_nas_transport.payload_container.payload_container_contents); + break; + default: + logger.warning("Not handling payload container %x", + dl_nas_transport.payload_container_type.payload_container_type.value); + break; + } + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_n1_sm_information(std::vector payload_container_contents) +{ + logger.info(payload_container_contents.data(), + payload_container_contents.size(), + "Payload contents (length %d)", + payload_container_contents.size()); + + nas_5gs_msg nas_msg; + nas_msg.unpack(payload_container_contents); + + switch (nas_msg.hdr.message_type) { + case msg_opts::options::pdu_session_establishment_accept: + pdu_session_establishment_proc.trigger(nas_msg.pdu_session_establishment_accept()); + break; + case msg_opts::options::pdu_session_establishment_reject: + pdu_session_establishment_proc.trigger(nas_msg.pdu_session_establishment_reject()); + break; + default: + logger.error( + "Not handling NAS message type: %s (0x%02x)", nas_msg.hdr.message_type.to_string(), nas_msg.hdr.message_type); + break; + } + return SRSRAN_SUCCESS; } /******************************************************************************* @@ -212,8 +815,13 @@ void nas_5g::timer_expired(uint32_t timeout_id) } /******************************************************************************* - * UE Stack Interface + * UE Stack & RRC Interface ******************************************************************************/ +bool nas_5g::is_registered() +{ + return state.get_state() == mm5g_state_t::state_t::registered; +} + int nas_5g::switch_on() { logger.info("Switching on"); @@ -248,4 +856,187 @@ int nas_5g::start_service_request() return SRSRAN_SUCCESS; } +/******************************************************************************* + * Helpers + ******************************************************************************/ + +void nas_5g::fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_caps) +{ + if (ia5g_caps[0] == true) { + sec_caps.ia0_5g_supported = true; + } + if (ia5g_caps[1] == true) { + sec_caps.ia1_128_5g_supported = true; + } + if (ia5g_caps[2] == true) { + sec_caps.ia2_128_5g_supported = true; + } + if (ia5g_caps[3] == true) { + sec_caps.ia3_128_5g_supported = true; + } + if (ia5g_caps[4] == true) { + sec_caps.ia4_5g_supported = true; + } + if (ia5g_caps[5] == true) { + sec_caps.ia5_5g_supported = true; + } + if (ia5g_caps[6] == true) { + sec_caps.ia6_5g_supported = true; + } + if (ia5g_caps[7] == true) { + sec_caps.ia7_5g_supported = true; + } + + if (ea5g_caps[0] == true) { + sec_caps.ea0_5g_supported = true; + } + if (ea5g_caps[1] == true) { + sec_caps.ea1_128_5g_supported = true; + } + if (ea5g_caps[2] == true) { + sec_caps.ea2_128_5g_supported = true; + } + if (ea5g_caps[3] == true) { + sec_caps.ea3_128_5g_supported = true; + } + if (ea5g_caps[4] == true) { + sec_caps.ea4_5g_supported = true; + } + if (ea5g_caps[5] == true) { + sec_caps.ea5_5g_supported = true; + } + if (ea5g_caps[6] == true) { + sec_caps.ea6_5g_supported = true; + } + if (ea5g_caps[7] == true) { + sec_caps.ea7_5g_supported = true; + } +} + +/******************************************************************************* + * Helpers for Session Management + ******************************************************************************/ + +int nas_5g::trigger_pdu_session_est() +{ + if (unestablished_pdu_sessions() == true) { + pdu_session_cfg_t pdu_session_cfg; + uint16_t pdu_session_id; + get_unestablished_pdu_session(pdu_session_id, pdu_session_cfg); + pdu_session_establishment_proc.launch(pdu_session_id, pdu_session_cfg); + } + return SRSRAN_SUCCESS; +} + +int nas_5g::init_pdu_sessions(std::vector pdu_session_cfgs) +{ + uint16_t i = 0; + for (auto pdu_session_cfg : pdu_session_cfgs) { + pdu_sessions[i].configured = true; + pdu_sessions[i].pdu_session_id = i + 1; + pdu_sessions[i].pdu_session_cfg = pdu_session_cfg; + } + return SRSRAN_SUCCESS; +} + +int nas_5g::configure_pdu_session(uint16_t pdu_session_id) +{ + for (auto pdu_session : pdu_sessions) { + if (pdu_session.pdu_session_id == pdu_session_id) { + pdu_session.established = true; + } + } + return SRSRAN_SUCCESS; +} + +bool nas_5g::unestablished_pdu_sessions() +{ + for (auto pdu_session : pdu_sessions) { + if (pdu_session.configured == true && pdu_session.established == false) { + return true; + } + } + return false; +} + +int nas_5g::get_unestablished_pdu_session(uint16_t& pdu_session_id, pdu_session_cfg_t& pdu_session_cfg) +{ + for (auto pdu_session : pdu_sessions) { + if (pdu_session.configured == true && pdu_session.established == false) { + pdu_session_id = pdu_session.pdu_session_id; + pdu_session_cfg = pdu_session.pdu_session_cfg; + } + } + return SRSRAN_SUCCESS; +} + +int nas_5g::add_pdu_session(uint16_t pdu_session_id, + uint16_t pdu_session_type, + srsran::nas_5g::pdu_address_t pdu_address) +{ + char* err_str = nullptr; + + // Copy IPv4 + uint32_t ip_addr = 0; + + ip_addr |= pdu_address.ipv4.data()[0] << 24u; + ip_addr |= pdu_address.ipv4.data()[1] << 16u; + ip_addr |= pdu_address.ipv4.data()[2] << 8u; + ip_addr |= pdu_address.ipv4.data()[3]; + + // Copy IPv6 + uint8_t ipv6_if_id[8] = {}; + memcpy(ipv6_if_id, pdu_address.ipv6.data(), 8); + + if (!(pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4V6 || pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4 || + pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV6)) { + logger.warning("PDU session typed expected to be of IPV4 or IPV6 or IPV4V6"); + return SRSRAN_ERROR; + } + + if (gw->setup_if_addr(pdu_session_id, pdu_session_type, ip_addr, ipv6_if_id, err_str)) { + logger.error("%s - %s", gw_setup_failure_str.c_str(), err_str ? err_str : ""); + srsran::console("%s\n", gw_setup_failure_str.c_str()); + return SRSRAN_ERROR; + } + + if (pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4V6 || pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4) { + logger.info("PDU Session Establishment successful. IP: %u.%u.%u.%u", + pdu_address.ipv4.data()[0], + pdu_address.ipv4.data()[1], + pdu_address.ipv4.data()[2], + pdu_address.ipv4.data()[3]); + + srsran::console("PDU Session Establishment successful. IP: %u.%u.%u.%u\n", + pdu_address.ipv4.data()[0], + pdu_address.ipv4.data()[1], + pdu_address.ipv4.data()[2], + pdu_address.ipv4.data()[3]); + } + + if (pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4V6 || pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV6) { + logger.info("PDU Session Establishment successful. IPv6 interface id: %02x%02x:%02x%02x:%02x%02x:%02x%02x", + pdu_address.ipv6.data()[0], + pdu_address.ipv6.data()[1], + pdu_address.ipv6.data()[2], + pdu_address.ipv6.data()[3], + pdu_address.ipv6.data()[4], + pdu_address.ipv6.data()[5], + pdu_address.ipv6.data()[6], + pdu_address.ipv6.data()[7]); + + srsran::console("PDU Session Establishment successful. IPv6 interface id: %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + pdu_address.ipv6.data()[0], + pdu_address.ipv6.data()[1], + pdu_address.ipv6.data()[2], + pdu_address.ipv6.data()[3], + pdu_address.ipv6.data()[4], + pdu_address.ipv6.data()[5], + pdu_address.ipv6.data()[6], + pdu_address.ipv6.data()[7]); + } + + return SRSRAN_SUCCESS; +} + } // namespace srsue \ No newline at end of file diff --git a/srsue/src/stack/upper/nas_5g_procedures.cc b/srsue/src/stack/upper/nas_5g_procedures.cc index 7384dca60..cbe1dc7ba 100644 --- a/srsue/src/stack/upper/nas_5g_procedures.cc +++ b/srsue/src/stack/upper/nas_5g_procedures.cc @@ -44,4 +44,54 @@ srsran::proc_outcome_t nas_5g::registration_procedure::step() return srsran::proc_outcome_t::success; } +// PDU Sessions Establishment Procedure +nas_5g::pdu_session_establishment_procedure::pdu_session_establishment_procedure( + nas_5g_interface_procedures* parent_nas_, + srslog::basic_logger& logger_) : + logger(logger_), parent_nas(parent_nas_) +{} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::init(const uint16_t pdu_session_id_, + const pdu_session_cfg_t pdu_session_cfg) +{ + // Get PDU transaction identity + transaction_identity = parent_nas->allocate_next_proc_trans_id(); + pdu_session_id = pdu_session_id_; + parent_nas->send_pdu_session_establishment_request(transaction_identity, pdu_session_id, pdu_session_cfg); + + return srsran::proc_outcome_t::yield; +} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::react( + const srsran::nas_5g::pdu_session_establishment_accept_t& pdu_session_est_accept) +{ + // TODO check the pdu session values + if (pdu_session_est_accept.dnn_present == false) { + logger.warning("Expected DNN in PDU session establishment accept"); + return proc_outcome_t::error; + } + if (pdu_session_est_accept.pdu_address_present == false) { + logger.warning("Expected PDU Address in PDU session establishment accept"); + return proc_outcome_t::error; + } + if (parent_nas->add_pdu_session(pdu_session_id, + pdu_session_est_accept.selected_pdu_session_type.pdu_session_type_value, + pdu_session_est_accept.pdu_address) != SRSRAN_SUCCESS) { + logger.warning("Adding PDU session failed\n"); + return srsran::proc_outcome_t::error; + } + return srsran::proc_outcome_t::success; +} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::react( + const srsran::nas_5g::pdu_session_establishment_reject_t& session_est_reject) +{ + return srsran::proc_outcome_t::success; +} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::step() +{ + return srsran::proc_outcome_t::success; +} + } // namespace srsue \ No newline at end of file diff --git a/srsue/src/test/ttcn3/src/ttcn3_ue.cc b/srsue/src/test/ttcn3/src/ttcn3_ue.cc index 783bf1d03..831e6c73e 100644 --- a/srsue/src/test/ttcn3/src/ttcn3_ue.cc +++ b/srsue/src/test/ttcn3/src/ttcn3_ue.cc @@ -59,24 +59,18 @@ int ttcn3_ue::init(all_args_t args, syssim_interface_phy* syssim_, const std::st args.phy.dl_earfcn = "3400"; args.rf.type = "none"; - args.stack.type = "lte"; args.phy.type = "lte_ttcn3"; // Instantiate layers and stack together our UE - if (args.stack.type == "lte") { - stack = std::unique_ptr(new ue_stack_lte); - if (!stack) { - srsran::console("Error creating LTE stack instance.\n"); - return SRSRAN_ERROR; - } + stack = std::unique_ptr(new ue_stack_lte); + if (!stack) { + srsran::console("Error creating LTE stack instance.\n"); + return SRSRAN_ERROR; + } - phy = std::unique_ptr(new srsue::lte_ttcn3_phy); - if (!phy) { - srsran::console("Error creating LTE PHY instance.\n"); - return SRSRAN_ERROR; - } - } else { - srsran::console("Invalid stack type %s. Supported values are [lte].\n", args.stack.type.c_str()); + phy = std::unique_ptr(new srsue::lte_ttcn3_phy); + if (!phy) { + srsran::console("Error creating LTE PHY instance.\n"); return SRSRAN_ERROR; } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index a24bf08e1..32a67b345 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -63,109 +63,71 @@ int ue::init(const all_args_t& args_) } // Instantiate layers and stack together our UE - if (args.stack.type == "lte") { - std::unique_ptr lte_stack(new ue_stack_lte); - if (!lte_stack) { - srsran::console("Error creating LTE stack instance.\n"); - return SRSRAN_ERROR; - } - - std::unique_ptr gw_ptr(new gw(srslog::fetch_basic_logger("GW"))); - if (!gw_ptr) { - srsran::console("Error creating a GW instance.\n"); - return SRSRAN_ERROR; - } - - std::unique_ptr lte_phy = std::unique_ptr(new srsue::phy); - if (!lte_phy) { - srsran::console("Error creating LTE PHY instance.\n"); - return SRSRAN_ERROR; - } - - std::unique_ptr lte_radio = std::unique_ptr(new srsran::radio); - if (!lte_radio) { - srsran::console("Error creating radio multi instance.\n"); - return SRSRAN_ERROR; - } - - // init layers - if (lte_radio->init(args.rf, lte_phy.get())) { - srsran::console("Error initializing radio.\n"); - return SRSRAN_ERROR; - } - - // from here onwards do not exit immediately if something goes wrong as sub-layers may already use interfaces - if (lte_phy->init(args.phy, lte_stack.get(), lte_radio.get())) { - srsran::console("Error initializing PHY.\n"); - ret = SRSRAN_ERROR; - } + std::unique_ptr lte_stack(new ue_stack_lte); + if (!lte_stack) { + srsran::console("Error creating LTE stack instance.\n"); + return SRSRAN_ERROR; + } - srsue::phy_args_nr_t phy_args_nr = {}; - phy_args_nr.max_nof_prb = args.phy.nr_max_nof_prb; - phy_args_nr.rf_channel_offset = args.phy.nof_lte_carriers; - phy_args_nr.nof_carriers = args.phy.nof_nr_carriers; - phy_args_nr.nof_phy_threads = args.phy.nof_phy_threads; - phy_args_nr.worker_cpu_mask = args.phy.worker_cpu_mask; - phy_args_nr.log = args.phy.log; - phy_args_nr.store_pdsch_ko = args.phy.nr_store_pdsch_ko; - if (lte_phy->init(phy_args_nr, lte_stack.get(), lte_radio.get())) { - srsran::console("Error initializing NR PHY.\n"); - ret = SRSRAN_ERROR; - } + std::unique_ptr gw_ptr(new gw(srslog::fetch_basic_logger("GW"))); + if (!gw_ptr) { + srsran::console("Error creating a GW instance.\n"); + return SRSRAN_ERROR; + } - if (lte_stack->init(args.stack, lte_phy.get(), lte_phy.get(), gw_ptr.get())) { - srsran::console("Error initializing stack.\n"); - ret = SRSRAN_ERROR; - } + std::unique_ptr lte_phy = std::unique_ptr(new srsue::phy); + if (!lte_phy) { + srsran::console("Error creating LTE PHY instance.\n"); + return SRSRAN_ERROR; + } - if (gw_ptr->init(args.gw, lte_stack.get())) { - srsran::console("Error initializing GW.\n"); - ret = SRSRAN_ERROR; - } + std::unique_ptr lte_radio = std::unique_ptr(new srsran::radio); + if (!lte_radio) { + srsran::console("Error creating radio multi instance.\n"); + return SRSRAN_ERROR; + } - // move ownership - stack = std::move(lte_stack); - gw_inst = std::move(gw_ptr); - phy = std::move(lte_phy); - radio = std::move(lte_radio); - } else if (args.stack.type == "nr") { - logger.info("Initializing NR stack"); - std::unique_ptr nr_stack(new srsue::ue_stack_nr()); - std::unique_ptr nr_radio(new srsran::radio_null); - std::unique_ptr nr_phy; - std::unique_ptr gw_ptr(new gw(srslog::fetch_basic_logger("GW"))); - - // Init layers - if (nr_radio->init(args.rf, nullptr)) { - srsran::console("Error initializing radio.\n"); - return SRSRAN_ERROR; - } + // init layers + if (lte_radio->init(args.rf, lte_phy.get())) { + srsran::console("Error initializing radio.\n"); + return SRSRAN_ERROR; + } - if (nr_phy->init(args.phy)) { - srsran::console("Error initializing PHY.\n"); - return SRSRAN_ERROR; - } + // from here onwards do not exit immediately if something goes wrong as sub-layers may already use interfaces + if (lte_phy->init(args.phy, lte_stack.get(), lte_radio.get())) { + srsran::console("Error initializing PHY.\n"); + ret = SRSRAN_ERROR; + } - if (nr_stack->init(args.stack)) { - srsran::console("Error initializing stack.\n"); - return SRSRAN_ERROR; - } + srsue::phy_args_nr_t phy_args_nr = {}; + phy_args_nr.max_nof_prb = args.phy.nr_max_nof_prb; + phy_args_nr.rf_channel_offset = args.phy.nof_lte_carriers; + phy_args_nr.nof_carriers = args.phy.nof_nr_carriers; + phy_args_nr.nof_phy_threads = args.phy.nof_phy_threads; + phy_args_nr.worker_cpu_mask = args.phy.worker_cpu_mask; + phy_args_nr.log = args.phy.log; + phy_args_nr.store_pdsch_ko = args.phy.nr_store_pdsch_ko; + if (lte_phy->init(phy_args_nr, lte_stack.get(), lte_radio.get())) { + srsran::console("Error initializing NR PHY.\n"); + ret = SRSRAN_ERROR; + } - if (gw_ptr->init(args.gw, nr_stack.get())) { - srsran::console("Error initializing GW.\n"); - return SRSRAN_ERROR; - } + if (lte_stack->init(args.stack, lte_phy.get(), lte_phy.get(), gw_ptr.get())) { + srsran::console("Error initializing stack.\n"); + ret = SRSRAN_ERROR; + } - // move ownership - stack = std::move(nr_stack); - gw_inst = std::move(gw_ptr); - phy = std::move(nr_phy); - radio = std::move(nr_radio); - } else { - srsran::console("Invalid stack type %s. Supported values are [lte].\n", args.stack.type.c_str()); + if (gw_ptr->init(args.gw, lte_stack.get())) { + srsran::console("Error initializing GW.\n"); ret = SRSRAN_ERROR; } + // move ownership + stack = std::move(lte_stack); + gw_inst = std::move(gw_ptr); + phy = std::move(lte_phy); + radio = std::move(lte_radio); + if (phy) { srsran::console("Waiting PHY to initialize ... "); phy->wait_initialize(); @@ -266,6 +228,7 @@ int ue::parse_args(const all_args_t& args_) if (not args.stack.rrc_nr.supported_bands_nr_str.empty()) { // Populates supported bands srsran::string_parse_list(args.stack.rrc_nr.supported_bands_nr_str, ',', args.stack.rrc_nr.supported_bands_nr); + args.stack.rrc.supported_bands_nr = args.stack.rrc_nr.supported_bands_nr; } else { logger.error("Error: rat.nr.bands list is empty"); srsran::console("Error: rat.nr.bands list is empty\n"); diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index 3689ba83c..c745c4a96 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -105,9 +105,10 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_prach nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW} - --duration=1000 # 100 slots + # Test PRACH transmission and detection + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_prach_fdd nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=FDD + --duration=1000 # 1000 slots --gnb.stack.pdsch.slots=none # No PDSCH --gnb.stack.pusch.slots=none # No PUSCH --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} @@ -115,5 +116,38 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --ue.stack.prach.preamble=10 # Use preamble 10 --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) + + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_prach_tdd nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=6D+4U + --duration=1000 # 1000 slots + --gnb.stack.pdsch.slots=none # No PDSCH + --gnb.stack.pusch.slots=none # No PUSCH + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.stack.prach.period=30 # Transmit PRACH every 30 radio frames + --ue.stack.prach.preamble=10 # Use preamble 10 + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ) + + # Test scheduling request + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_sr nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW} + --duration=1000 # 1000 slots + --gnb.stack.pdsch.slots=none # No PDSCH + --gnb.stack.pusch.slots=none # No PUSCH + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.stack.sr.period=4 # Transmit SR every 4 opportunities + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ) + + # Test scheduling request multiplexed with HARQ ACK feedback + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_sr_harq nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW} + --duration=1000 # 1000 slots + --gnb.stack.pdsch.slots=all # All PDSCH + --gnb.stack.pusch.slots=none # No PUSCH + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.stack.sr.period=4 # Transmit SR every 4 opportunities + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ) endforeach () endif () diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 4b48644cb..ee7cac1a2 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -91,6 +91,7 @@ private: std::unique_ptr mac; srsran::slot_point pdsch_slot, pusch_slot; srslog::basic_logger& sched_logger; + bool autofill_pdsch_bsr = false; std::mutex metrics_mutex; metrics_t metrics = {}; @@ -346,12 +347,14 @@ public: sched_logger.set_level(srslog::str_to_basic_level(args.log_level)); srslog::fetch_basic_logger("MAC-NR").set_level(srslog::str_to_basic_level(args.log_level)); + autofill_pdsch_bsr = args.pdsch.slots != "" and args.pdsch.slots != "none"; + // create sched object - srsenb::sched_nr_interface::sched_cfg_t sched_cfg{}; - sched_cfg.pdsch_enabled = args.pdsch.slots != "" and args.pdsch.slots != "none"; - sched_cfg.pusch_enabled = args.pusch.slots != "" and args.pusch.slots != "none"; - mac.reset(new srsenb::mac_nr{&task_sched, sched_cfg}); - mac->init(srsenb::mac_nr_args_t{}, nullptr, nullptr, &rlc_obj, &rrc_obj); + mac.reset(new srsenb::mac_nr{&task_sched}); + srsenb::mac_nr_args_t mac_args{}; + mac_args.sched_cfg.pdsch_enabled = args.pdsch.slots != "" and args.pdsch.slots != "none"; + mac_args.sched_cfg.pusch_enabled = args.pusch.slots != "" and args.pusch.slots != "none"; + mac->init(mac_args, nullptr, nullptr, &rlc_obj, &rrc_obj); std::vector cells_cfg = srsenb::get_default_cells_cfg(1, phy_cfg); mac->cell_cfg(cells_cfg); @@ -362,6 +365,7 @@ public: srsenb::sched_nr_interface::ue_cfg_t ue_cfg = srsenb::get_default_ue_cfg(1, phy_cfg); ue_cfg.fixed_dl_mcs = args.pdsch.mcs; ue_cfg.fixed_ul_mcs = args.pusch.mcs; + ue_cfg.ue_bearers[4].direction = srsenb::mac_lc_ch_cfg_t::BOTH; mac->ue_cfg(args.rnti, ue_cfg); } @@ -453,6 +457,10 @@ public: } if (not use_dummy_sched) { + if (autofill_pdsch_bsr) { + mac->rlc_buffer_state(rnti, 0, 10000, 0); + } + int ret = mac->get_dl_sched(slot_cfg, dl_sched); for (pdsch_t& pdsch : dl_sched.pdsch) { @@ -485,6 +493,20 @@ public: return SRSRAN_ERROR; } + // Schedule NZP-CSI-RS, iterate all NZP-CSI-RS sets + for (const srsran_csi_rs_nzp_set_t& set : phy_cfg.pdsch.nzp_csi_rs_sets) { + // For each NZP-CSI-RS resource available in the set + for (uint32_t i = 0; i < set.count; i++) { + // Select resource + const srsran_csi_rs_nzp_resource_t& nzp_csi_resource = set.data[i]; + + // Check if the resource is scheduled for this slot + if (srsran_csi_rs_send(&nzp_csi_resource.periodicity, &slot_cfg)) { + dl_sched.nzp_csi_rs.push_back(nzp_csi_resource); + } + } + } + return SRSRAN_SUCCESS; } diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index f282254ca..ece74f7c0 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -49,7 +49,7 @@ test_bench::args_t::args_t(int argc, char** argv) ("rnti", bpo::value(&rnti)->default_value(rnti), "UE RNTI") ("duration", bpo::value(&durations_slots)->default_value(durations_slots), "Test duration in slots") ("lib.log.level", bpo::value(&phy_lib_log_level)->default_value(phy_lib_log_level), "PHY librray log level") - ("reference", bpo::value(&reference_cfg_str)->default_value(reference_cfg_str), "Reference PHY configuration arguments") + ("reference", bpo::value(&reference_cfg_str)->default_value(reference_cfg_str), "Reference PHY configuration arguments") ; options_gnb_stack.add_options() @@ -69,25 +69,25 @@ test_bench::args_t::args_t(int argc, char** argv) ; options_gnb_phy.add_options() - ("gnb.phy.nof_threads", bpo::value(&gnb_phy.nof_phy_threads)->default_value(1), "Number of threads") - ("gnb.phy.log.level", bpo::value(&gnb_phy.log.phy_level)->default_value("warning"), "gNb PHY log level") - ("gnb.phy.log.hex_limit", bpo::value(&gnb_phy.log.phy_hex_limit)->default_value(0), "gNb PHY log hex limit") - ("gnb.phy.log.id_preamble", bpo::value(&gnb_phy.log.id_preamble)->default_value("GNB/"), "gNb PHY log ID preamble") - ("gnb.phy.pusch.max_iter", bpo::value(&gnb_phy.pusch_max_nof_iter)->default_value(10), "PUSCH LDPC max number of iterations") - ; + ("gnb.phy.nof_threads", bpo::value(&gnb_phy.nof_phy_threads)->default_value(1), "Number of threads") + ("gnb.phy.log.level", bpo::value(&gnb_phy.log.phy_level)->default_value("warning"), "gNb PHY log level") + ("gnb.phy.log.hex_limit", bpo::value(&gnb_phy.log.phy_hex_limit)->default_value(0), "gNb PHY log hex limit") + ("gnb.phy.log.id_preamble", bpo::value(&gnb_phy.log.id_preamble)->default_value("GNB/"), "gNb PHY log ID preamble") + ("gnb.phy.pusch.max_iter", bpo::value(&gnb_phy.pusch_max_nof_iter)->default_value(10), "PUSCH LDPC max number of iterations") + ; options_ue_phy.add_options() - ("ue.phy.nof_threads", bpo::value(&ue_phy.nof_phy_threads)->default_value(1), "Number of threads") - ("ue.phy.log.level", bpo::value(&ue_phy.log.phy_level)->default_value("warning"), "UE PHY log level") - ("ue.phy.log.hex_limit", bpo::value(&ue_phy.log.phy_hex_limit)->default_value(0), "UE PHY log hex limit") - ("ue.phy.log.id_preamble", bpo::value(&ue_phy.log.id_preamble)->default_value(" UE/"), "UE PHY log ID preamble") - ; + ("ue.phy.nof_threads", bpo::value(&ue_phy.nof_phy_threads)->default_value(1), "Number of threads") + ("ue.phy.log.level", bpo::value(&ue_phy.log.phy_level)->default_value("warning"), "UE PHY log level") + ("ue.phy.log.hex_limit", bpo::value(&ue_phy.log.phy_hex_limit)->default_value(0), "UE PHY log hex limit") + ("ue.phy.log.id_preamble", bpo::value(&ue_phy.log.id_preamble)->default_value(" UE/"), "UE PHY log ID preamble") + ; options_ue_stack.add_options() - ("ue.stack.sr.period", bpo::value(&ue_stack.sr_period)->default_value(ue_stack.sr_period), "SR period in number of opportunities. Set 0 to disable and 1 for all.") - ("ue.stack.prach.period", bpo::value(&ue_stack.prach_period)->default_value(ue_stack.prach_period), "PRACH period in SFN. Set 0 to disable and 1 for all.") - ("ue.stack.prach.preamble", bpo::value(&ue_stack.prach_preamble)->default_value(ue_stack.prach_preamble), "PRACH preamble. Set 0 to disable and 1 for all.") - ; + ("ue.stack.sr.period", bpo::value(&ue_stack.sr_period)->default_value(ue_stack.sr_period), "SR period in number of opportunities. Set 0 to disable and 1 for all.") + ("ue.stack.prach.period", bpo::value(&ue_stack.prach_period)->default_value(ue_stack.prach_period), "PRACH period in SFN. Set 0 to disable and 1 for all.") + ("ue.stack.prach.preamble", bpo::value(&ue_stack.prach_preamble)->default_value(ue_stack.prach_preamble), "PRACH preamble. Set 0 to disable and 1 for all.") + ; options.add(options_gnb_stack).add(options_gnb_phy).add(options_ue_stack).add(options_ue_phy).add_options() ("help", "Show this message") @@ -273,11 +273,14 @@ int main(int argc, char** argv) // Print SR if (metrics.ue_stack.sr_count > 0) { srsran::console("SR:\n"); - srsran::console(" +------------+------------+\n"); - srsran::console(" | %10s | %10s |\n", "Transmit'd", "Received"); - srsran::console(" +------------+------------+\n"); - srsran::console(" | %10d | %10d |\n", metrics.ue_stack.sr_count, metrics.gnb_stack.sr_count); - srsran::console(" +------------+------------+\n"); + srsran::console(" +------------+------------+------------+\n"); + srsran::console(" | %10s | %10s | %10s |\n", "Transmit'd", "Received", "Detection"); + srsran::console(" +------------+------------+------------+\n"); + srsran::console(" | %10d | %10d | %10.5f |\n", + metrics.ue_stack.sr_count, + metrics.gnb_stack.sr_count, + (double)metrics.gnb_stack.sr_count / (double)metrics.ue_stack.sr_count); + srsran::console(" +------------+------------+------------+\n"); } // Assert metrics diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index 446a4ee10..62b3f79d5 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -91,6 +91,7 @@ public: common_cfg.carrier = args.phy_cfg.carrier; common_cfg.pdcch = args.phy_cfg.pdcch; common_cfg.prach = args.phy_cfg.prach; + common_cfg.duplex_mode = args.phy_cfg.duplex.mode; if (gnb_phy.set_common_cfg(common_cfg) < SRSRAN_SUCCESS) { return;