From 5759d396d47707a4ade85a5c05c0eb294b020752 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 25 Nov 2021 17:39:00 +0000 Subject: [PATCH 01/53] nr,gnb,sched: avoid that ConRes CE gets allocated twice --- srsgnb/src/stack/mac/sched_nr_ue.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srsgnb/src/stack/mac/sched_nr_ue.cc b/srsgnb/src/stack/mac/sched_nr_ue.cc index d67dceb66..ba7431de4 100644 --- a/srsgnb/src/stack/mac/sched_nr_ue.cc +++ b/srsgnb/src/stack/mac/sched_nr_ue.cc @@ -161,16 +161,16 @@ void ue::mac_buffer_state(uint32_t ce_lcid, uint32_t nof_cmds) } } -void ue::rlc_buffer_state(uint32_t lcid, uint32_t newtx, uint32_t retx) +void ue::rlc_buffer_state(uint32_t lcid, uint32_t newtx, uint32_t priotx) { - if (lcid == 0 and buffers.get_dl_tx_total(0) == 0) { + if (lcid == 0 and (newtx + priotx > 0) and buffers.get_dl_tx_total(0) == 0) { // In case of DL-CCCH, schedule ConRes CE // Note1: rlc_buffer_state may be called multiple times for the same CCCH. Thus, we need to confirm lcid=0 buffer // state is zero to avoid that multiple CEs being scheduled. // Note2: use push_front because ConRes CE has priority buffers.pending_ces.push_front({srsran::mac_sch_subpdu_nr::CON_RES_ID, cfg().carriers[0].cc}); } - buffers.dl_buffer_state(lcid, newtx, retx); + buffers.dl_buffer_state(lcid, newtx, priotx); } void ue::new_slot(slot_point pdcch_slot) From 3e61448a414a253759bab330734598b232b88a2d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 25 Nov 2021 12:07:58 +0000 Subject: [PATCH 02/53] gnb,ngap: added logging for Rx NGAP messages. --- srsgnb/hdr/stack/ngap/ngap.h | 4 ++++ srsgnb/src/stack/ngap/ngap.cc | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/srsgnb/hdr/stack/ngap/ngap.h b/srsgnb/hdr/stack/ngap/ngap.h index 3c5417afa..27c900781 100644 --- a/srsgnb/hdr/stack/ngap/ngap.h +++ b/srsgnb/hdr/stack/ngap/ngap.h @@ -78,6 +78,10 @@ public: // PCAP void start_pcap(srsran::ngap_pcap* pcap_); + // Logging + typedef enum { Rx = 0, Tx } direction_t; + void log_ngap_message(const asn1::ngap_nr::ngap_pdu_c& msg, const direction_t dir, srsran::const_byte_span pdu); + private: static const int AMF_PORT = 38412; static const int ADDR_FAMILY = AF_INET; diff --git a/srsgnb/src/stack/ngap/ngap.cc b/srsgnb/src/stack/ngap/ngap.cc index 3da0f86e9..bdc3a8a50 100644 --- a/srsgnb/src/stack/ngap/ngap.cc +++ b/srsgnb/src/stack/ngap/ngap.cc @@ -376,6 +376,7 @@ bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu) pcap->write_ngap(pdu->msg, pdu->N_bytes); } + // Unpack ngap_pdu_c rx_pdu; asn1::cbit_ref bref(pdu->msg, pdu->N_bytes); @@ -387,6 +388,10 @@ bool ngap::handle_ngap_rx_pdu(srsran::byte_buffer_t* pdu) return false; } + // Logging + log_ngap_message(rx_pdu, Rx, srsran::make_span(*pdu)); + + // Handle the NGAP message switch (rx_pdu.type().value) { case ngap_pdu_c::types_opts::init_msg: return handle_initiating_message(rx_pdu.init_msg()); @@ -805,4 +810,30 @@ void ngap::start_pcap(srsran::ngap_pcap* pcap_) { pcap = pcap_; } + +void ngap::log_ngap_message(const ngap_pdu_c& msg, const direction_t dir, srsran::const_byte_span pdu) +{ + std::string msg_type = {}; + switch (msg.type().value) { + case ngap_pdu_c::types_opts::init_msg: + msg_type = msg.init_msg().value.type().to_string(); + break; + case ngap_pdu_c::types_opts::successful_outcome: + msg_type = msg.successful_outcome().value.type().to_string(); + break; + case ngap_pdu_c::types_opts::unsuccessful_outcome: + msg_type = msg.unsuccessful_outcome().value.type().to_string(); + break; + default: + return; + } + if (logger.debug.enabled()) { + asn1::json_writer json_writer; + msg.to_json(json_writer); + logger.debug(pdu.data(), pdu.size(), "%s - %s (%d B)", (dir == Rx) ? "Rx" : "Tx", msg_type, pdu.size()); + logger.debug("Content:%s", json_writer.to_string().c_str()); + } else if (logger.info.enabled()) { + logger.info(pdu.data(), pdu.size(), "%s - %s (%d B)", (dir == Rx) ? "Rx" : "Tx", msg_type, pdu.size()); + } +} } // namespace srsenb From 1417331edbfd9dfeeefff3cb5244a18f9c535674 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 17 Nov 2021 12:13:59 +0100 Subject: [PATCH 03/53] rrc-nr,test: add test for initial_ue msg sent to ngap Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 5 +++-- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 15 +++++++++++++-- .../src/stack/rrc/test/rrc_nr_test_helpers.h | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 1d07ab06b..4308a9faf 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -133,7 +133,7 @@ void test_rrc_sa_connection() mac_nr_dummy mac_obj; rlc_nr_rrc_tester rlc_obj; pdcp_nr_rrc_tester pdcp_obj; - ngap_dummy ngap_obj; + ngap_rrc_tester ngap_obj; rrc_nr rrc_obj(&task_sched); @@ -158,7 +158,8 @@ void test_rrc_sa_connection() uecfg.phy_cfg.pdcch.search_space_present[2] = false; TESTASSERT_SUCCESS(rrc_obj.add_user(0x4601, uecfg)); - test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, 0x4601); + + test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, ngap_obj,0x4601); test_rrc_nr_security_mode_cmd(task_sched, rrc_obj, pdcp_obj, 0x4601); } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index 6ac574d87..68da890e1 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -10,8 +10,11 @@ * */ +#define DED_NAS_MSG_STRING "7E01280E534C337E004109000BF200F110800101347B80802E02F07071002D7E004109000BF200F110800101347B80801001002E02F0702F0201015200F11000006418010174000090530101" + #include "rrc_nr_test_helpers.h" #include "srsran/common/test_common.h" +#include using namespace asn1::rrc_nr; @@ -21,6 +24,7 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, rlc_nr_rrc_tester& rlc, mac_nr_dummy& mac, + ngap_rrc_tester& ngap, uint16_t rnti) { srsran::unique_byte_buffer_t pdu; @@ -96,8 +100,7 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, complete_ies.registered_amf.amf_id.from_number(0x800101); complete_ies.guami_type_present = true; complete_ies.guami_type.value = rrc_setup_complete_ies_s::guami_type_opts::native; - complete_ies.ded_nas_msg.from_string("7E01280E534C337E004109000BF200F110800101347B80802E02F07071002D7E004109000BF200F" - "110800101347B80801001002E02F0702F0201015200F11000006418010174000090530101"); + auto& ded_nas_msg = complete_ies.ded_nas_msg.from_string(DED_NAS_MSG_STRING); { pdu = srsran::make_byte_buffer(); @@ -118,6 +121,14 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, } } TESTASSERT(ss_ue_found); /// Ensure UE-specific SearchSpace was added + + // Check here if the MSG sent to NGAP is correct + // Create a srsran::span object for the expected MSG + asn1::unbounded_octstring expected; + expected.from_string(DED_NAS_MSG_STRING); + srsran::span expected_span{expected}; + TESTASSERT(expected_span == ngap.last_pdu); + } void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h index d893068d3..534552821 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -49,6 +49,23 @@ public: srsran::unique_byte_buffer_t last_sdu; }; +class ngap_rrc_tester : public ngap_dummy +{ +public: + void initial_ue(uint16_t rnti, + uint32_t gnb_cc_idx, + asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::const_byte_span pdu, + uint32_t s_tmsi) + { + last_sdu_rnti = rnti; + last_pdu = pdu; + } + + uint16_t last_sdu_rnti; + srsran::const_byte_span last_pdu; +}; + /** * Run TS 38.331, 5.3.3 "RRC connection establishment" to completion * RRC actions: @@ -64,6 +81,7 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, rlc_nr_rrc_tester& rlc, mac_nr_dummy& mac, + ngap_rrc_tester& ngap, uint16_t rnti); void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, From 7d230a260e429bca92e5f3d98a8eb2946bd023c4 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 18 Nov 2021 13:46:00 +0100 Subject: [PATCH 04/53] rrc-nr,test: add tests for DL/ULInformationTransfer Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 2 +- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 77 +++++++++++++++++-- .../src/stack/rrc/test/rrc_nr_test_helpers.h | 20 ++++- 3 files changed, 89 insertions(+), 10 deletions(-) diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 4308a9faf..a80dc039b 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -158,8 +158,8 @@ void test_rrc_sa_connection() uecfg.phy_cfg.pdcch.search_space_present[2] = false; TESTASSERT_SUCCESS(rrc_obj.add_user(0x4601, uecfg)); - test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, ngap_obj,0x4601); + test_rrc_nr_info_transfer(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); test_rrc_nr_security_mode_cmd(task_sched, rrc_obj, pdcp_obj, 0x4601); } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index 68da890e1..e6db8e7b4 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -10,8 +10,6 @@ * */ -#define DED_NAS_MSG_STRING "7E01280E534C337E004109000BF200F110800101347B80802E02F07071002D7E004109000BF200F110800101347B80801001002E02F0702F0201015200F11000006418010174000090530101" - #include "rrc_nr_test_helpers.h" #include "srsran/common/test_common.h" #include @@ -100,7 +98,9 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, complete_ies.registered_amf.amf_id.from_number(0x800101); complete_ies.guami_type_present = true; complete_ies.guami_type.value = rrc_setup_complete_ies_s::guami_type_opts::native; - auto& ded_nas_msg = complete_ies.ded_nas_msg.from_string(DED_NAS_MSG_STRING); + std::string NAS_msg_str = "7E01280E534C337E004109000BF200F110800101347B80802E02F07071002D7E004109000BF200F11080010134" + "7B80801001002E02F0702F0201015200F11000006418010174000090530101"; + auto& ded_nas_msg = complete_ies.ded_nas_msg.from_string(NAS_msg_str); { pdu = srsran::make_byte_buffer(); @@ -125,10 +125,75 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, // Check here if the MSG sent to NGAP is correct // Create a srsran::span object for the expected MSG asn1::unbounded_octstring expected; - expected.from_string(DED_NAS_MSG_STRING); - srsran::span expected_span{expected}; - TESTASSERT(expected_span == ngap.last_pdu); + expected.from_string(NAS_msg_str); + TESTASSERT(expected == ngap.last_pdu); +} + +void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + ngap_rrc_tester& ngap, + uint16_t rnti) +{ + // STEP 1 : Send DLInformationTransfer (gNB -> UE) + // generate sdu to pass as NAS message in DLInformationTransfer + srsran::unique_byte_buffer_t sdu; + sdu = srsran::make_byte_buffer(); + + // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + asn1::unbounded_octstring NAS_DL_msg; + NAS_DL_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); + sdu->append_bytes(NAS_DL_msg.data(), NAS_DL_msg.size()); + + // trigger the RRC to send the DLInformationTransfer + rrc_obj.write_dl_info(rnti, std::move(sdu)); + + // Test whether there exists the SRB1 initiated in the Connection Establishment + // We test this as the SRB1 was setup in a different function + TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti); + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), 1); + + // Send SecurityModeCommand (gNB -> UE) + dl_dcch_msg_s dl_dcch_msg; + { + asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()}; + TESTASSERT_SUCCESS(dl_dcch_msg.unpack(bref)); + } + + // Test if the unpacked message retrived from PCDP is correct + TESTASSERT_EQ(dl_dcch_msg_type_c::types_opts::c1, dl_dcch_msg.msg.type().value); + TESTASSERT_EQ(dl_dcch_msg_type_c::c1_c_::types_opts::dl_info_transfer, dl_dcch_msg.msg.c1().type().value); + TESTASSERT_EQ(dl_info_transfer_s::crit_exts_c_::types_opts::dl_info_transfer, + dl_dcch_msg.msg.c1().dl_info_transfer().crit_exts.type().value); + + dl_info_transfer_ies_s& ies_DL = dl_dcch_msg.msg.c1().dl_info_transfer().crit_exts.dl_info_transfer(); + TESTASSERT(ies_DL.ded_nas_msg_present == true); + TESTASSERT(NAS_DL_msg == ies_DL.ded_nas_msg); + + // STEP 2: Send ULInformationTransfer (UE -> gNB) + ul_dcch_msg_s ul_dcch_msg; + auto& ies_UL = ul_dcch_msg.msg.set_c1().set_ul_info_transfer().crit_exts.set_ul_info_transfer(); + ies_UL.ded_nas_msg_present = true; + + // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + asn1::unbounded_octstring NAS_UL_msg; + NAS_UL_msg.from_string("6671f8bc80b1860f29b3a8b3b8563ce6c36a591bb1a3dc6612674448fb958d274426d326356aa9aa"); + ies_UL.ded_nas_msg.resize(NAS_UL_msg.size()); + memcpy(ies_UL.ded_nas_msg.data(), NAS_UL_msg.data(), NAS_UL_msg.size()); + + srsran::unique_byte_buffer_t pdu; + { + pdu = srsran::make_byte_buffer(); + asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()}; + TESTASSERT_SUCCESS(ul_dcch_msg.pack(bref)); + pdu->N_bytes = bref.distance_bytes(); + } + + // send message to RRC + rrc_obj.write_pdu(rnti, 1, std::move(pdu)); + // get a span for both NAS msg and compare if the actual transmitted is correct + TESTASSERT(NAS_UL_msg == ngap.last_pdu); } void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h index 534552821..6ed82ea88 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -59,11 +59,19 @@ public: uint32_t s_tmsi) { last_sdu_rnti = rnti; - last_pdu = pdu; + last_pdu.resize(pdu.size()); + memcpy(last_pdu.data(), pdu.data(), pdu.size()); } - uint16_t last_sdu_rnti; - srsran::const_byte_span last_pdu; + void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) + { + last_sdu_rnti = rnti; + last_pdu.resize(pdu.size()); + memcpy(last_pdu.data(), pdu.data(), pdu.size()); + } + + uint16_t last_sdu_rnti; + asn1::dyn_octstring last_pdu; }; /** @@ -84,6 +92,12 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, ngap_rrc_tester& ngap, uint16_t rnti); +void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + ngap_rrc_tester& ngap, + uint16_t rnti); + void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, pdcp_nr_rrc_tester& pdcp, From 39d6eecf0133b66bb5209657808d86262e4971be Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 19 Nov 2021 11:58:42 +0100 Subject: [PATCH 05/53] rrc-nr,test: add test for RRCReconfiguration Signed-off-by: Carlo Galiotto --- srsgnb/hdr/stack/rrc/rrc_nr.h | 1 + srsgnb/hdr/stack/rrc/rrc_nr_ue.h | 6 +- srsgnb/src/stack/ngap/ngap_ue_proc.cc | 2 +- srsgnb/src/stack/rrc/cell_asn1_config.cc | 4 +- srsgnb/src/stack/rrc/rrc_nr.cc | 11 ++- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 7 ++ srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 1 + .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 96 +++++++++++++++++-- .../src/stack/rrc/test/rrc_nr_test_helpers.h | 5 + 9 files changed, 120 insertions(+), 13 deletions(-) diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index eac2f93f8..6891aa661 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -103,6 +103,7 @@ public: void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) final; int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) final; int allocate_lcid(uint16_t rnti) final; + int start_rrc_reconfiguration(uint16_t rnti); // logging typedef enum { Rx = 0, Tx } direction_t; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h index 7135dd0d5..910bf5986 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h @@ -83,6 +83,9 @@ public: /* TS 38.331 - 5.3.4 Initial AS security activation */ void send_security_mode_command(srsran::unique_byte_buffer_t nas_pdu); + /* TS 38.331 - 5.3.5 RRC reconfiguration */ + void send_rrc_reconfiguration(); + private: int send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_ccch_msg); int send_dl_dcch(srsran::nr_srb srb, const asn1::rrc_nr::dl_dcch_msg_s& dl_dcch_msg); @@ -91,9 +94,6 @@ private: void send_rrc_setup(); void send_rrc_reject(uint8_t reject_wait_time_secs); - /* TS 38.331 - 5.3.5 RRC reconfiguration */ - void send_rrc_reconfiguration(); - /// Update PDCP bearers based on ASN1 structs passed to the UE int update_pdcp_bearers(const asn1::rrc_nr::radio_bearer_cfg_s& radio_bearer_diff, const asn1::rrc_nr::cell_group_cfg_s& cell_group_diff); diff --git a/srsgnb/src/stack/ngap/ngap_ue_proc.cc b/srsgnb/src/stack/ngap/ngap_ue_proc.cc index 31f7b6247..4ff9615f4 100644 --- a/srsgnb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsgnb/src/stack/ngap/ngap_ue_proc.cc @@ -169,7 +169,7 @@ proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu // 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) == + 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; diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index e3262d764..8f705acd2 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -15,6 +15,7 @@ #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/band_helper.h" #include +#include using namespace asn1::rrc_nr; @@ -1153,7 +1154,8 @@ void fill_cellgroup_with_radio_bearer_cfg(const rrc_nr_cfg_t& // Add DRBs for (const drb_to_add_mod_s& drb : bearers.drb_to_add_mod_list) { out.rlc_bearer_to_add_mod_list.push_back({}); - fill_srb(cfg, (srsran::nr_srb)drb.drb_id, out.rlc_bearer_to_add_mod_list.back()); + uint32_t lcid = drb_to_lcid(static_cast(drb.drb_id)); + fill_drb(cfg, lcid, (srsran::nr_drb)drb.drb_id, out.rlc_bearer_to_add_mod_list.back()); } out.rlc_bearer_to_add_mod_list_present = out.rlc_bearer_to_add_mod_list.size() > 0; diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 3790a3b53..f1b0b2614 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -634,7 +634,16 @@ void rrc_nr::write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) } users[rnti]->send_dl_information_transfer(std::move(sdu)); } - +int rrc_nr::start_rrc_reconfiguration(uint16_t rnti) +{ + auto user_it = users.find(rnti); + if (user_it == users.end()){ + logger.error("Starting RRCRecofiguration failed - rnti=0x%x not found", rnti); + return SRSRAN_ERROR; + } + user_it->second->send_rrc_reconfiguration(); + return SRSRAN_SUCCESS; +} /******************************************************************************* Interface for EUTRA RRC *******************************************************************************/ diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 969715912..9f06e2e54 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1056,6 +1056,11 @@ void rrc_nr::ue::send_rrc_reconfiguration() } ies.non_crit_ext.master_cell_group.resize(pdu->N_bytes); memcpy(ies.non_crit_ext.master_cell_group.data(), pdu->data(), pdu->N_bytes); + if (logger.debug.enabled()) { + asn1::json_writer js; + master_cell_group.to_json(js); + logger.debug("Containerized MasterCellGroup: %s", js.to_string().c_str()); + } // Pass stored NAS PDUs ies.non_crit_ext.ded_nas_msg_list_present = true; @@ -1086,6 +1091,8 @@ void rrc_nr::ue::send_rrc_reconfiguration() void rrc_nr::ue::handle_rrc_reconfiguration_complete(const asn1::rrc_nr::rrc_recfg_complete_s& msg) { + update_mac(next_cell_group_cfg, true); + radio_bearer_cfg = next_radio_bearer_cfg; cell_group_cfg = next_cell_group_cfg; parent->ngap->ue_notify_rrc_reconf_complete(rnti, true); diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index a80dc039b..24998dc21 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -161,6 +161,7 @@ void test_rrc_sa_connection() test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, ngap_obj,0x4601); test_rrc_nr_info_transfer(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); test_rrc_nr_security_mode_cmd(task_sched, rrc_obj, pdcp_obj, 0x4601); + test_rrc_nr_reconfiguration( task_sched, rrc_obj, pdcp_obj, 0x4601); } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index e6db8e7b4..459f39703 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -123,7 +123,7 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, TESTASSERT(ss_ue_found); /// Ensure UE-specific SearchSpace was added // Check here if the MSG sent to NGAP is correct - // Create a srsran::span object for the expected MSG + // Create a unbounded_octstring for the expected MSG asn1::unbounded_octstring expected; expected.from_string(NAS_msg_str); TESTASSERT(expected == ngap.last_pdu); @@ -151,7 +151,7 @@ void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was setup in a different function TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti); - TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), 1); + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); // Send SecurityModeCommand (gNB -> UE) dl_dcch_msg_s dl_dcch_msg; @@ -175,7 +175,8 @@ void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, auto& ies_UL = ul_dcch_msg.msg.set_c1().set_ul_info_transfer().crit_exts.set_ul_info_transfer(); ies_UL.ded_nas_msg_present = true; - // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + // Create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + // We reuse NAS_UL_msg below to compare the string with the message sent to and unpacked by the gNB asn1::unbounded_octstring NAS_UL_msg; NAS_UL_msg.from_string("6671f8bc80b1860f29b3a8b3b8563ce6c36a591bb1a3dc6612674448fb958d274426d326356aa9aa"); ies_UL.ded_nas_msg.resize(NAS_UL_msg.size()); @@ -192,7 +193,7 @@ void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, // send message to RRC rrc_obj.write_pdu(rnti, 1, std::move(pdu)); - // get a span for both NAS msg and compare if the actual transmitted is correct + // compare if the actual transmitted matches with the MSG created from the original string TESTASSERT(NAS_UL_msg == ngap.last_pdu); } @@ -209,9 +210,9 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was setup in a different function TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti); - TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), 1); + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); - // Send SecurityModeCommand (gNB -> UE) + // STEP 1 - Send SecurityModeCommand (gNB -> UE) dl_dcch_msg_s dl_dcch_msg; { asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()}; @@ -228,7 +229,7 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, ies.security_cfg_smc.security_algorithm_cfg.integrity_prot_algorithm.value); TESTASSERT_EQ(ciphering_algorithm_opts::nea0, ies.security_cfg_smc.security_algorithm_cfg.ciphering_algorithm.value); - // Send SecurityModeComplete (UE -> gNB) + // STEP 2 - Send SecurityModeComplete (UE -> gNB) ul_dcch_msg_s ul_dcch_msg; auto& sec_cmd_complete_msg = ul_dcch_msg.msg.set_c1().set_security_mode_complete(); sec_cmd_complete_msg.rrc_transaction_id = dl_dcch_msg.msg.c1().security_mode_cmd().rrc_transaction_id; @@ -245,4 +246,85 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, rrc_obj.write_pdu(rnti, 1, std::move(pdu)); } +void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + uint16_t rnti) +{ + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); + + // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + asn1::unbounded_octstring NAS_msg; + NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); + rrc_obj.establish_rrc_bearer(rnti, 1, NAS_msg, srsran::srb_to_lcid(srsran::nr_srb::srb1)); + + // STEP 2 - Trigger and send RRCReconfiguration command (gNB -> UE) + rrc_obj.start_rrc_reconfiguration(rnti); + + // Test whether there exists the SRB1 initiated in the Connection Establishment + // We test this as the SRB1 was set up in a different function + TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti); + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); + + dl_dcch_msg_s dl_dcch_msg; + { + asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()}; + TESTASSERT_SUCCESS(dl_dcch_msg.unpack(bref)); + } + + // Test whether the unpacked message is correct + TESTASSERT_EQ(dl_dcch_msg_type_c::types_opts::c1, dl_dcch_msg.msg.type().value); + TESTASSERT_EQ(dl_dcch_msg_type_c::c1_c_::types_opts::rrc_recfg, dl_dcch_msg.msg.c1().type().value); + TESTASSERT_EQ(rrc_recfg_s::crit_exts_c_::types_opts::rrc_recfg, + dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.type().value); + const rrc_recfg_ies_s& reconf_ies = dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.rrc_recfg(); + TESTASSERT_EQ(true, reconf_ies.radio_bearer_cfg_present); + TESTASSERT_EQ(true, reconf_ies.radio_bearer_cfg.srb_to_add_mod_list_present); + TESTASSERT_EQ(1, reconf_ies.radio_bearer_cfg.srb_to_add_mod_list.size()); + TESTASSERT_EQ(2, reconf_ies.radio_bearer_cfg.srb_to_add_mod_list[0].srb_id); + TESTASSERT_EQ(1, reconf_ies.radio_bearer_cfg.drb_to_add_mod_list.size()); + auto& drb = reconf_ies.radio_bearer_cfg.drb_to_add_mod_list[0]; + TESTASSERT_EQ(1, drb.drb_id); + + TESTASSERT_EQ(true, reconf_ies.non_crit_ext_present); + TESTASSERT_EQ(true, reconf_ies.non_crit_ext.master_cell_group_present); + auto& master_group_msg = reconf_ies.non_crit_ext.master_cell_group; + + cell_group_cfg_s master_cell_group; + { + asn1::cbit_ref bref{master_group_msg.data(), master_group_msg.size()}; + TESTASSERT_SUCCESS(master_cell_group.unpack(bref)); + } + + // Test if the master_cell_group SRB and DRB IDs match those in the RadioBearerConfig + TESTASSERT_EQ(0, master_cell_group.cell_group_id); + TESTASSERT_EQ(true, master_cell_group.rlc_bearer_to_add_mod_list_present); + auto& rlc_srb = master_cell_group.rlc_bearer_to_add_mod_list[0]; + TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.srb_to_add_mod_list[0].srb_id, rlc_srb.served_radio_bearer.srb_id()); + auto& rlc_drb = master_cell_group.rlc_bearer_to_add_mod_list[1]; + TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.drb_to_add_mod_list[1].drb_id, rlc_drb.served_radio_bearer.drb_id()); + + asn1::unbounded_octstring expected_nas; + expected_nas.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); + TESTASSERT_EQ(true, reconf_ies.non_crit_ext.ded_nas_msg_list_present); + TESTASSERT( expected_nas == reconf_ies.non_crit_ext.ded_nas_msg_list[0]); + + // STEP 2 - Send RRCReconfiguration (UE -> gNB) + ul_dcch_msg_s ul_dcch_msg; + auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete(); + RRC_recfg_complete.rrc_transaction_id = dl_dcch_msg.msg.c1().rrc_recfg().rrc_transaction_id; + RRC_recfg_complete.crit_exts.set_rrc_recfg_complete(); + + srsran::unique_byte_buffer_t pdu; + { + pdu = srsran::make_byte_buffer(); + asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()}; + TESTASSERT_SUCCESS(ul_dcch_msg.pack(bref)); + pdu->N_bytes = bref.distance_bytes(); + } + + // send message to RRC + rrc_obj.write_pdu(rnti, 1, std::move(pdu)); +} + } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h index 6ed82ea88..166cb1c65 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -103,6 +103,11 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, pdcp_nr_rrc_tester& pdcp, uint16_t rnti); +void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + uint16_t rnti); + } // namespace srsenb #endif // SRSRAN_RRC_NR_TEST_HELPERS_H From 18a85adc499395edcbe11d38685740084aef6138 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Tue, 23 Nov 2021 15:48:41 +0100 Subject: [PATCH 06/53] rrc-nr: trigger RRCReconfifguration from ... establish_EPS_bearer Signed-off-by: Carlo Galiotto --- srsgnb/hdr/stack/rrc/rrc_nr.h | 1 - srsgnb/hdr/stack/rrc/rrc_nr_ue.h | 2 +- srsgnb/src/stack/rrc/rrc_nr.cc | 14 ++++---------- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 8 ++++---- srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc | 4 ++-- 5 files changed, 11 insertions(+), 18 deletions(-) diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index 6891aa661..eac2f93f8 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -103,7 +103,6 @@ public: void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) final; int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) final; int allocate_lcid(uint16_t rnti) final; - int start_rrc_reconfiguration(uint16_t rnti); // logging typedef enum { Rx = 0, Tx } direction_t; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h index 910bf5986..d48093894 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h @@ -102,7 +102,7 @@ private: int update_rlc_bearers(const asn1::rrc_nr::cell_group_cfg_s& cell_group_diff); /// Update MAC based on ASN1 message - int update_mac(const asn1::rrc_nr::cell_group_cfg_s& cell_group_diff, bool is_config_complete); + int update_mac(const asn1::rrc_nr::cell_group_cfg_s& cell_group_config, bool is_config_complete); int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig); int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config); diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index f1b0b2614..fff08d71f 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -609,6 +609,9 @@ int rrc_nr::establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran: } users[rnti]->establish_eps_bearer(pdu_session_id, nas_pdu, lcid); + + // TODO: verify whether this is the best place where to call the RRCReconfig + users[rnti]->send_rrc_reconfiguration(); return SRSRAN_SUCCESS; } @@ -634,16 +637,7 @@ void rrc_nr::write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) } users[rnti]->send_dl_information_transfer(std::move(sdu)); } -int rrc_nr::start_rrc_reconfiguration(uint16_t rnti) -{ - auto user_it = users.find(rnti); - if (user_it == users.end()){ - logger.error("Starting RRCRecofiguration failed - rnti=0x%x not found", rnti); - return SRSRAN_ERROR; - } - user_it->second->send_rrc_reconfiguration(); - return SRSRAN_SUCCESS; -} + /******************************************************************************* Interface for EUTRA RRC *******************************************************************************/ diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 9f06e2e54..cb47a84c8 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1245,15 +1245,15 @@ int rrc_nr::ue::update_rlc_bearers(const asn1::rrc_nr::cell_group_cfg_s& cell_gr return SRSRAN_SUCCESS; } -int rrc_nr::ue::update_mac(const cell_group_cfg_s& cell_group_diff, bool is_config_complete) +int rrc_nr::ue::update_mac(const cell_group_cfg_s& cell_group_config, bool is_config_complete) { if (not is_config_complete) { // Release bearers - for (uint8_t lcid : cell_group_diff.rlc_bearer_to_release_list) { + for (uint8_t lcid : cell_group_config.rlc_bearer_to_release_list) { uecfg.ue_bearers[lcid].direction = mac_lc_ch_cfg_t::IDLE; } - for (const rlc_bearer_cfg_s& bearer : cell_group_diff.rlc_bearer_to_add_mod_list) { + for (const rlc_bearer_cfg_s& bearer : cell_group_config.rlc_bearer_to_add_mod_list) { uecfg.ue_bearers[bearer.lc_ch_id].direction = mac_lc_ch_cfg_t::BOTH; if (bearer.mac_lc_ch_cfg.ul_specific_params_present) { uecfg.ue_bearers[bearer.lc_ch_id].priority = bearer.mac_lc_ch_cfg.ul_specific_params.prio; @@ -1265,7 +1265,7 @@ int rrc_nr::ue::update_mac(const cell_group_cfg_s& cell_group_diff, bool is_conf } } } else { - auto& pdcch = cell_group_diff.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg.setup(); + auto& pdcch = cell_group_config.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg.setup(); for (auto& ss : pdcch.search_spaces_to_add_mod_list) { uecfg.phy_cfg.pdcch.search_space_present[ss.search_space_id] = true; uecfg.phy_cfg.pdcch.search_space[ss.search_space_id] = diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index 459f39703..eed892370 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -256,10 +256,10 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) asn1::unbounded_octstring NAS_msg; NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); - rrc_obj.establish_rrc_bearer(rnti, 1, NAS_msg, srsran::srb_to_lcid(srsran::nr_srb::srb1)); // STEP 2 - Trigger and send RRCReconfiguration command (gNB -> UE) - rrc_obj.start_rrc_reconfiguration(rnti); + rrc_obj.establish_rrc_bearer(rnti, 1, NAS_msg, srsran::srb_to_lcid(srsran::nr_srb::srb1)); + //rrc_obj.start_rrc_reconfiguration(rnti); // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was set up in a different function From 66733fb34752eae1d26d9212488d20317ce5309f Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Tue, 23 Nov 2021 18:26:36 +0100 Subject: [PATCH 07/53] rrc-nr: prevent master_cell_group to be sent if... ...there are no changes in the radio_bearer_configuration In addition: i) Force RRCReconfiguration to be sent after receiving SecurityModeComplete ii) Prevent RRCReconfiguration to be sent after establish_rrc_bearer() Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/rrc_nr.cc | 2 - srsgnb/src/stack/rrc/rrc_nr_ue.cc | 80 ++++++++++--------- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 53 +++++++++++- 3 files changed, 96 insertions(+), 39 deletions(-) diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index fff08d71f..f39a6596c 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -610,8 +610,6 @@ int rrc_nr::establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran: users[rnti]->establish_eps_bearer(pdu_session_id, nas_pdu, lcid); - // TODO: verify whether this is the best place where to call the RRCReconfig - users[rnti]->send_rrc_reconfiguration(); return SRSRAN_SUCCESS; } diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index cb47a84c8..e0151afd5 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1021,6 +1021,7 @@ void rrc_nr::ue::handle_security_mode_complete(const asn1::rrc_nr::security_mode parent->logger.info("SecurityModeComplete transaction ID: %d", msg.rrc_transaction_id); parent->pdcp->enable_encryption(rnti, srb_to_lcid(srsran::nr_srb::srb1)); + send_rrc_reconfiguration(); // Note: Skip UE capabilities // Send RRCReconfiguration if necessary @@ -1040,50 +1041,57 @@ void rrc_nr::ue::send_rrc_reconfiguration() ies.radio_bearer_cfg_present = compute_diff_radio_bearer_cfg(parent->cfg, radio_bearer_cfg, next_radio_bearer_cfg, ies.radio_bearer_cfg); - ies.non_crit_ext_present = true; - ies.non_crit_ext.master_cell_group_present = true; + // If no bearer to add/mod/remove, do not include master_cell_group + // Set ies.non_crit_ext_present only if master_cell_group_present = true or + if (ies.radio_bearer_cfg_present){ - // Fill masterCellGroup - cell_group_cfg_s master_cell_group; - master_cell_group.cell_group_id = 0; - fill_cellgroup_with_radio_bearer_cfg(parent->cfg, ies.radio_bearer_cfg, master_cell_group); + ies.non_crit_ext.master_cell_group_present = true; - // Pack masterCellGroup into container - srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(master_cell_group, __FUNCTION__); - if (pdu == nullptr) { - send_rrc_release(); - return; - } - ies.non_crit_ext.master_cell_group.resize(pdu->N_bytes); - memcpy(ies.non_crit_ext.master_cell_group.data(), pdu->data(), pdu->N_bytes); - if (logger.debug.enabled()) { - asn1::json_writer js; - master_cell_group.to_json(js); - logger.debug("Containerized MasterCellGroup: %s", js.to_string().c_str()); - } + // Fill masterCellGroup + cell_group_cfg_s master_cell_group; + master_cell_group.cell_group_id = 0; + fill_cellgroup_with_radio_bearer_cfg(parent->cfg, ies.radio_bearer_cfg, master_cell_group); - // Pass stored NAS PDUs - ies.non_crit_ext.ded_nas_msg_list_present = true; - ies.non_crit_ext.ded_nas_msg_list.resize(nas_pdu_queue.size()); - for (uint32_t i = 0; i < nas_pdu_queue.size(); ++i) { - ies.non_crit_ext.ded_nas_msg_list[i].resize(nas_pdu_queue[i]->size()); - memcpy(ies.non_crit_ext.ded_nas_msg_list[i].data(), nas_pdu_queue[i]->data(), nas_pdu_queue[i]->size()); - } - ies.non_crit_ext.ded_nas_msg_list_present = nas_pdu_queue.size() > 0; - nas_pdu_queue.clear(); + // Pack masterCellGroup into container + srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(master_cell_group, __FUNCTION__); + if (pdu == nullptr) { + send_rrc_release(); + return; + } + ies.non_crit_ext.master_cell_group.resize(pdu->N_bytes); + memcpy(ies.non_crit_ext.master_cell_group.data(), pdu->data(), pdu->N_bytes); + if (logger.debug.enabled()) { + asn1::json_writer js; + master_cell_group.to_json(js); + logger.debug("Containerized MasterCellGroup: %s", js.to_string().c_str()); + } + + // Update lower layers + if (ies.radio_bearer_cfg_present) { + // add PDCP bearers + update_pdcp_bearers(ies.radio_bearer_cfg, master_cell_group); - // Update lower layers - if (ies.radio_bearer_cfg_present) { - // add PDCP bearers - update_pdcp_bearers(ies.radio_bearer_cfg, master_cell_group); + // add RLC bearers + update_rlc_bearers(master_cell_group); - // add RLC bearers - update_rlc_bearers(master_cell_group); + // add MAC bearers + update_mac(master_cell_group, false); + } + } - // add MAC bearers - update_mac(master_cell_group, false); + if (nas_pdu_queue.size() > 0) { + // Pass stored NAS PDUs + ies.non_crit_ext.ded_nas_msg_list_present = true; + ies.non_crit_ext.ded_nas_msg_list.resize(nas_pdu_queue.size()); + for (uint32_t i = 0; i < nas_pdu_queue.size(); ++i) { + ies.non_crit_ext.ded_nas_msg_list[i].resize(nas_pdu_queue[i]->size()); + memcpy(ies.non_crit_ext.ded_nas_msg_list[i].data(), nas_pdu_queue[i]->data(), nas_pdu_queue[i]->size()); + } + nas_pdu_queue.clear(); } + ies.non_crit_ext_present = ies.non_crit_ext.master_cell_group_present or ies.non_crit_ext.ded_nas_msg_list_present; + if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) { send_rrc_release(); } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index eed892370..33565c68f 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -258,7 +258,57 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); // STEP 2 - Trigger and send RRCReconfiguration command (gNB -> UE) - rrc_obj.establish_rrc_bearer(rnti, 1, NAS_msg, srsran::srb_to_lcid(srsran::nr_srb::srb1)); + //rrc_obj.start_rrc_reconfiguration(rnti); + + // Test whether there exists the SRB1 initiated in the Connection Establishment + // We test this as the SRB1 was set up in a different function + TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti); + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); + + dl_dcch_msg_s dl_dcch_msg; + { + asn1::cbit_ref bref{pdcp.last_sdu->data(), pdcp.last_sdu->size()}; + TESTASSERT_SUCCESS(dl_dcch_msg.unpack(bref)); + } + + // Test whether the unpacked message is correct + TESTASSERT_EQ(dl_dcch_msg_type_c::types_opts::c1, dl_dcch_msg.msg.type().value); + TESTASSERT_EQ(dl_dcch_msg_type_c::c1_c_::types_opts::rrc_recfg, dl_dcch_msg.msg.c1().type().value); + TESTASSERT_EQ(rrc_recfg_s::crit_exts_c_::types_opts::rrc_recfg, + dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.type().value); + const rrc_recfg_ies_s& reconf_ies = dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.rrc_recfg(); + + // STEP 2 - Send RRCReconfiguration (UE -> gNB) + ul_dcch_msg_s ul_dcch_msg; + auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete(); + RRC_recfg_complete.rrc_transaction_id = dl_dcch_msg.msg.c1().rrc_recfg().rrc_transaction_id; + RRC_recfg_complete.crit_exts.set_rrc_recfg_complete(); + + srsran::unique_byte_buffer_t pdu; + { + pdu = srsran::make_byte_buffer(); + asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()}; + TESTASSERT_SUCCESS(ul_dcch_msg.pack(bref)); + pdu->N_bytes = bref.distance_bytes(); + } + + // send message to RRC + rrc_obj.write_pdu(rnti, 1, std::move(pdu)); +} + +#if 0 +void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + uint16_t rnti) +{ + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); + + // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + asn1::unbounded_octstring NAS_msg; + NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); + + // STEP 2 - Trigger and send RRCReconfiguration command (gNB -> UE) //rrc_obj.start_rrc_reconfiguration(rnti); // Test whether there exists the SRB1 initiated in the Connection Establishment @@ -326,5 +376,6 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, // send message to RRC rrc_obj.write_pdu(rnti, 1, std::move(pdu)); } +#endif } // namespace srsenb From 9c7ef6f11ec9afa774460d6e3ab40b21e76187f1 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Tue, 23 Nov 2021 18:33:13 +0100 Subject: [PATCH 08/53] rrc-nr: send RRCReconfiguration after establish_rrc_bearer() Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/rrc_nr.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index f39a6596c..fff08d71f 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -610,6 +610,8 @@ int rrc_nr::establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran: users[rnti]->establish_eps_bearer(pdu_session_id, nas_pdu, lcid); + // TODO: verify whether this is the best place where to call the RRCReconfig + users[rnti]->send_rrc_reconfiguration(); return SRSRAN_SUCCESS; } From c9d92dd5ef9219de01b4b6d4106bd15a6eca41e3 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Tue, 23 Nov 2021 18:39:22 +0100 Subject: [PATCH 09/53] rrc-nr,test: add test for RRCReconfiguration after... EPS bearer establishment --- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 1 + .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 7 +++--- .../src/stack/rrc/test/rrc_nr_test_helpers.h | 23 +++++++++++-------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 24998dc21..3ad72f34f 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -162,6 +162,7 @@ void test_rrc_sa_connection() test_rrc_nr_info_transfer(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); test_rrc_nr_security_mode_cmd(task_sched, rrc_obj, pdcp_obj, 0x4601); test_rrc_nr_reconfiguration( task_sched, rrc_obj, pdcp_obj, 0x4601); + test_rrc_nr_reconfiguration_II( task_sched, rrc_obj, pdcp_obj, 0x4601); } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index 33565c68f..278198a81 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -296,8 +296,8 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, rrc_obj.write_pdu(rnti, 1, std::move(pdu)); } -#if 0 -void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, + +void test_rrc_nr_reconfiguration_II(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, pdcp_nr_rrc_tester& pdcp, uint16_t rnti) @@ -309,7 +309,7 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); // STEP 2 - Trigger and send RRCReconfiguration command (gNB -> UE) - //rrc_obj.start_rrc_reconfiguration(rnti); + rrc_obj.establish_rrc_bearer(rnti, 1, NAS_msg, srsran::srb_to_lcid(srsran::nr_srb::srb1)); // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was set up in a different function @@ -376,6 +376,5 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, // send message to RRC rrc_obj.write_pdu(rnti, 1, std::move(pdu)); } -#endif } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h index 166cb1c65..3697c9ad4 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -70,8 +70,8 @@ public: memcpy(last_pdu.data(), pdu.data(), pdu.size()); } - uint16_t last_sdu_rnti; - asn1::dyn_octstring last_pdu; + uint16_t last_sdu_rnti; + asn1::dyn_octstring last_pdu; }; /** @@ -93,10 +93,10 @@ void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, uint16_t rnti); void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, - rrc_nr& rrc_obj, - pdcp_nr_rrc_tester& pdcp, - ngap_rrc_tester& ngap, - uint16_t rnti); + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + ngap_rrc_tester& ngap, + uint16_t rnti); void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, @@ -104,9 +104,14 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, uint16_t rnti); void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, - rrc_nr& rrc_obj, - pdcp_nr_rrc_tester& pdcp, - uint16_t rnti); + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + uint16_t rnti); + +void test_rrc_nr_reconfiguration_II(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + uint16_t rnti); } // namespace srsenb From 6fc2d82b2e681af6d21d39f7903ec22328d65f4c Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 24 Nov 2021 12:52:19 +0100 Subject: [PATCH 10/53] rrc-nr,test: add log spy and clean NAS_msg Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 23 ++++++-- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 58 +++++++++++-------- .../src/stack/rrc/test/rrc_nr_test_helpers.h | 8 +-- 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 3ad72f34f..d250bf49e 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -162,23 +162,38 @@ void test_rrc_sa_connection() test_rrc_nr_info_transfer(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); test_rrc_nr_security_mode_cmd(task_sched, rrc_obj, pdcp_obj, 0x4601); test_rrc_nr_reconfiguration( task_sched, rrc_obj, pdcp_obj, 0x4601); - test_rrc_nr_reconfiguration_II( task_sched, rrc_obj, pdcp_obj, 0x4601); + test_rrc_nr_2nd_reconfiguration( task_sched, rrc_obj, pdcp_obj, 0x4601); } } // namespace srsenb int main(int argc, char** argv) { - auto& logger = srslog::fetch_basic_logger("ASN1"); + // Setup the log spy to intercept error and warning log entries. + if (!srslog::install_custom_sink( + srsran::log_sink_spy::name(), + std::unique_ptr(new srsran::log_sink_spy(srslog::get_default_log_formatter())))) { + return SRSRAN_ERROR; + } + + auto* spy = static_cast(srslog::find_sink(srsran::log_sink_spy::name())); + if (!spy) { + return SRSRAN_ERROR; + } + + auto& logger = srslog::fetch_basic_logger("ASN1", *spy, true); logger.set_level(srslog::basic_levels::info); - auto& rrc_logger = srslog::fetch_basic_logger("RRC-NR"); - rrc_logger.set_level(srslog::basic_levels::debug); + auto& test_log = srslog::fetch_basic_logger("RRC-NR", *spy, true); + test_log.set_level(srslog::basic_levels::debug); srslog::init(); srsenb::test_sib_generation(); TESTASSERT(srsenb::test_rrc_setup() == SRSRAN_SUCCESS); srsenb::test_rrc_sa_connection(); + TESTASSERT_EQ( 0, spy->get_warning_counter()); + TESTASSERT_EQ( 0, spy->get_error_counter()); + return SRSRAN_SUCCESS; } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index 278198a81..71de379fb 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -14,6 +14,8 @@ #include "srsran/common/test_common.h" #include +#define NAS_SEC_CMD_STR "d9119b97d7bb59fc842d5b9cc12f00c27e9d5e4c80ee4cceb99a0dbbc6e0b54daa21a5d9e36d2e3b" + using namespace asn1::rrc_nr; namespace srsenb { @@ -137,16 +139,16 @@ void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, { // STEP 1 : Send DLInformationTransfer (gNB -> UE) // generate sdu to pass as NAS message in DLInformationTransfer - srsran::unique_byte_buffer_t sdu; - sdu = srsran::make_byte_buffer(); + srsran::unique_byte_buffer_t nsa_sdu; + nsa_sdu = srsran::make_byte_buffer(); // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) asn1::unbounded_octstring NAS_DL_msg; - NAS_DL_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); - sdu->append_bytes(NAS_DL_msg.data(), NAS_DL_msg.size()); + NAS_DL_msg.from_string("21d9dfe07800371095c79a751be8352fb44aba7d69b836f5aad594ede9e72b8e34105ca8d7669d5c"); + nsa_sdu->append_bytes(NAS_DL_msg.data(), NAS_DL_msg.size()); // trigger the RRC to send the DLInformationTransfer - rrc_obj.write_dl_info(rnti, std::move(sdu)); + rrc_obj.write_dl_info(rnti, std::move(nsa_sdu)); // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was setup in a different function @@ -202,10 +204,15 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, pdcp_nr_rrc_tester& pdcp, uint16_t rnti) { - srsran::unique_byte_buffer_t pdu; + // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + asn1::unbounded_octstring NAS_msg; + NAS_msg.from_string(NAS_SEC_CMD_STR); + srsran::unique_byte_buffer_t nas_pdu; + nas_pdu = srsran::make_byte_buffer(); + nas_pdu->append_bytes(NAS_msg.data(), NAS_msg.size()); // Trigger Send SecurityCommand (simulate request from NGAP) - rrc_obj.start_security_mode_procedure(rnti, nullptr); + rrc_obj.start_security_mode_procedure(rnti, std::move(nas_pdu)); // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was setup in a different function @@ -235,6 +242,7 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, sec_cmd_complete_msg.rrc_transaction_id = dl_dcch_msg.msg.c1().security_mode_cmd().rrc_transaction_id; auto& ies_complete = sec_cmd_complete_msg.crit_exts.set_security_mode_complete(); + srsran::unique_byte_buffer_t pdu; { pdu = srsran::make_byte_buffer(); asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()}; @@ -253,13 +261,6 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, { TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); - // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) - asn1::unbounded_octstring NAS_msg; - NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); - - // STEP 2 - Trigger and send RRCReconfiguration command (gNB -> UE) - //rrc_obj.start_rrc_reconfiguration(rnti); - // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was set up in a different function TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti); @@ -278,9 +279,18 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.type().value); const rrc_recfg_ies_s& reconf_ies = dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.rrc_recfg(); + + // create an unbounded_octstring object that contains the same NAS message as in SecurityModeCommand + // The RRCreconfiguration reads the SecurityModeCommand NAS msg previously saved in the queue + asn1::unbounded_octstring NAS_msg; + NAS_msg.from_string(NAS_SEC_CMD_STR); + TESTASSERT_EQ(true, reconf_ies.non_crit_ext.ded_nas_msg_list_present); + // Test if NAS_msg is the same as the one sent in SecurityModeCommand + TESTASSERT(NAS_msg == reconf_ies.non_crit_ext.ded_nas_msg_list[0]); + // STEP 2 - Send RRCReconfiguration (UE -> gNB) ul_dcch_msg_s ul_dcch_msg; - auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete(); + auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete(); RRC_recfg_complete.rrc_transaction_id = dl_dcch_msg.msg.c1().rrc_recfg().rrc_transaction_id; RRC_recfg_complete.crit_exts.set_rrc_recfg_complete(); @@ -296,15 +306,14 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, rrc_obj.write_pdu(rnti, 1, std::move(pdu)); } - -void test_rrc_nr_reconfiguration_II(srsran::task_scheduler& task_sched, - rrc_nr& rrc_obj, - pdcp_nr_rrc_tester& pdcp, - uint16_t rnti) +void test_rrc_nr_2nd_reconfiguration(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + uint16_t rnti) { TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); - // create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) + // create an unbounded_octstring object that contains a NAS message (we simulate a random NAS nas) asn1::unbounded_octstring NAS_msg; NAS_msg.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); @@ -354,14 +363,13 @@ void test_rrc_nr_reconfiguration_II(srsran::task_scheduler& task_sched, auto& rlc_drb = master_cell_group.rlc_bearer_to_add_mod_list[1]; TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.drb_to_add_mod_list[1].drb_id, rlc_drb.served_radio_bearer.drb_id()); - asn1::unbounded_octstring expected_nas; - expected_nas.from_string("c574defc80ba722bffb8eacb6f8a163e3222cf1542ac529f6980bb15e0bf12d9f2b29f11fb458ec9"); + // Test if NAS_msg is the same as the one sent in DLInformationTransfer TESTASSERT_EQ(true, reconf_ies.non_crit_ext.ded_nas_msg_list_present); - TESTASSERT( expected_nas == reconf_ies.non_crit_ext.ded_nas_msg_list[0]); + TESTASSERT(NAS_msg == reconf_ies.non_crit_ext.ded_nas_msg_list[0]); // STEP 2 - Send RRCReconfiguration (UE -> gNB) ul_dcch_msg_s ul_dcch_msg; - auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete(); + auto& RRC_recfg_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete(); RRC_recfg_complete.rrc_transaction_id = dl_dcch_msg.msg.c1().rrc_recfg().rrc_transaction_id; RRC_recfg_complete.crit_exts.set_rrc_recfg_complete(); diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h index 3697c9ad4..273223a19 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -108,10 +108,10 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, pdcp_nr_rrc_tester& pdcp, uint16_t rnti); -void test_rrc_nr_reconfiguration_II(srsran::task_scheduler& task_sched, - rrc_nr& rrc_obj, - pdcp_nr_rrc_tester& pdcp, - uint16_t rnti); +void test_rrc_nr_2nd_reconfiguration(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + pdcp_nr_rrc_tester& pdcp, + uint16_t rnti); } // namespace srsenb From 6aad5d77869fabe0402ab6002b62a9bd14e4bdeb Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 24 Nov 2021 17:17:39 +0100 Subject: [PATCH 11/53] rrc-nr,test: apply reviewer comments Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/ngap/ngap_ue_proc.cc | 2 +- srsgnb/src/stack/rrc/cell_asn1_config.cc | 2 +- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 17 +++++++------- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 4 ++-- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 23 +++++++++++-------- .../src/stack/rrc/test/rrc_nr_test_helpers.h | 5 ++++ 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/srsgnb/src/stack/ngap/ngap_ue_proc.cc b/srsgnb/src/stack/ngap/ngap_ue_proc.cc index 4ff9615f4..31f7b6247 100644 --- a/srsgnb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsgnb/src/stack/ngap/ngap_ue_proc.cc @@ -169,7 +169,7 @@ proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu // 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) == + 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; diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 8f705acd2..f198eac78 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -11,11 +11,11 @@ */ #include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" +#include "srsenb/hdr/common/common_enb.h" #include "srsran/asn1/obj_id_cmp_utils.h" #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/band_helper.h" #include -#include using namespace asn1::rrc_nr; diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index e0151afd5..7f5d19b4a 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1042,7 +1042,8 @@ void rrc_nr::ue::send_rrc_reconfiguration() compute_diff_radio_bearer_cfg(parent->cfg, radio_bearer_cfg, next_radio_bearer_cfg, ies.radio_bearer_cfg); // If no bearer to add/mod/remove, do not include master_cell_group - // Set ies.non_crit_ext_present only if master_cell_group_present = true or + // Set ies.non_crit_ext_present (a few lines below) only if + // master_cell_group_present == true or ies.non_crit_ext.ded_nas_msg_list_present == true if (ies.radio_bearer_cfg_present){ ies.non_crit_ext.master_cell_group_present = true; @@ -1067,16 +1068,14 @@ void rrc_nr::ue::send_rrc_reconfiguration() } // Update lower layers - if (ies.radio_bearer_cfg_present) { - // add PDCP bearers - update_pdcp_bearers(ies.radio_bearer_cfg, master_cell_group); + // add PDCP bearers + update_pdcp_bearers(ies.radio_bearer_cfg, master_cell_group); - // add RLC bearers - update_rlc_bearers(master_cell_group); + // add RLC bearers + update_rlc_bearers(master_cell_group); - // add MAC bearers - update_mac(master_cell_group, false); - } + // add MAC bearers + update_mac(master_cell_group, false); } if (nas_pdu_queue.size() > 0) { diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index d250bf49e..2e28dcc35 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -161,8 +161,8 @@ void test_rrc_sa_connection() test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, ngap_obj,0x4601); test_rrc_nr_info_transfer(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); test_rrc_nr_security_mode_cmd(task_sched, rrc_obj, pdcp_obj, 0x4601); - test_rrc_nr_reconfiguration( task_sched, rrc_obj, pdcp_obj, 0x4601); - test_rrc_nr_2nd_reconfiguration( task_sched, rrc_obj, pdcp_obj, 0x4601); + test_rrc_nr_reconfiguration(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); + test_rrc_nr_2nd_reconfiguration(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index 71de379fb..dd49c7fc2 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -178,11 +178,8 @@ void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, ies_UL.ded_nas_msg_present = true; // Create an unbounded_octstring object that contains a random NAS message (we simulate a NAS message) - // We reuse NAS_UL_msg below to compare the string with the message sent to and unpacked by the gNB - asn1::unbounded_octstring NAS_UL_msg; - NAS_UL_msg.from_string("6671f8bc80b1860f29b3a8b3b8563ce6c36a591bb1a3dc6612674448fb958d274426d326356aa9aa"); - ies_UL.ded_nas_msg.resize(NAS_UL_msg.size()); - memcpy(ies_UL.ded_nas_msg.data(), NAS_UL_msg.data(), NAS_UL_msg.size()); + // We reuse ies_UL below to compare the string with the message sent to and unpacked by the gNB + ies_UL.ded_nas_msg.from_string("6671f8bc80b1860f29b3a8b3b8563ce6c36a591bb1a3dc6612674448fb958d274426d326356aa9aa"); srsran::unique_byte_buffer_t pdu; { @@ -196,7 +193,7 @@ void test_rrc_nr_info_transfer(srsran::task_scheduler& task_sched, rrc_obj.write_pdu(rnti, 1, std::move(pdu)); // compare if the actual transmitted matches with the MSG created from the original string - TESTASSERT(NAS_UL_msg == ngap.last_pdu); + TESTASSERT(ies_UL.ded_nas_msg == ngap.last_pdu); } void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, @@ -257,10 +254,9 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, pdcp_nr_rrc_tester& pdcp, + ngap_rrc_tester& ngap, uint16_t rnti) { - TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); - // Test whether there exists the SRB1 initiated in the Connection Establishment // We test this as the SRB1 was set up in a different function TESTASSERT_EQ(rnti, pdcp.last_sdu_rnti); @@ -279,7 +275,6 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.type().value); const rrc_recfg_ies_s& reconf_ies = dl_dcch_msg.msg.c1().rrc_recfg().crit_exts.rrc_recfg(); - // create an unbounded_octstring object that contains the same NAS message as in SecurityModeCommand // The RRCreconfiguration reads the SecurityModeCommand NAS msg previously saved in the queue asn1::unbounded_octstring NAS_msg; @@ -304,14 +299,19 @@ void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, // send message to RRC rrc_obj.write_pdu(rnti, 1, std::move(pdu)); + + // Verify the NGAP gets notified for the RRCReconfigurationComplete + TESTASSERT_EQ(true, ngap.last_rrc_recnf_complete); } void test_rrc_nr_2nd_reconfiguration(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, pdcp_nr_rrc_tester& pdcp, + ngap_rrc_tester& ngap, uint16_t rnti) { - TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), pdcp.last_sdu_lcid); + // Make sure the NGAP RRCReconfigurationComplete bool is reset to false + ngap.last_rrc_recnf_complete = false; // create an unbounded_octstring object that contains a NAS message (we simulate a random NAS nas) asn1::unbounded_octstring NAS_msg; @@ -383,6 +383,9 @@ void test_rrc_nr_2nd_reconfiguration(srsran::task_scheduler& task_sched, // send message to RRC rrc_obj.write_pdu(rnti, 1, std::move(pdu)); + + // Verify the NGAP gets notified for the RRCReconfigurationComplete + TESTASSERT_EQ(true, ngap.last_rrc_recnf_complete); } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h index 273223a19..3d83f7b23 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -70,8 +70,11 @@ public: memcpy(last_pdu.data(), pdu.data(), pdu.size()); } + void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) { last_rrc_recnf_complete = outcome; } + uint16_t last_sdu_rnti; asn1::dyn_octstring last_pdu; + bool last_rrc_recnf_complete = false; }; /** @@ -106,11 +109,13 @@ void test_rrc_nr_security_mode_cmd(srsran::task_scheduler& task_sched, void test_rrc_nr_reconfiguration(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, pdcp_nr_rrc_tester& pdcp, + ngap_rrc_tester& ngap, uint16_t rnti); void test_rrc_nr_2nd_reconfiguration(srsran::task_scheduler& task_sched, rrc_nr& rrc_obj, pdcp_nr_rrc_tester& pdcp, + ngap_rrc_tester& ngap, uint16_t rnti); } // namespace srsenb From 34af2657f9d2137cd61fd00603094c4e87dc4b92 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 25 Nov 2021 12:58:50 +0100 Subject: [PATCH 12/53] rrc-nr: add info log in establish_eps_bearer() Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 7f5d19b4a..f809fcd52 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1174,6 +1174,8 @@ void rrc_nr::ue::establish_eps_bearer(uint32_t pdu_session_id, srsran::const_byt next_radio_bearer_cfg.drb_to_add_mod_list_present = true; next_radio_bearer_cfg.drb_to_add_mod_list.push_back(drb); + + logger.info("Established EPS bearer for LCID %u and RNTI 0x%x", lcid, rnti); } bool rrc_nr::ue::init_pucch() From 787177bf3c245081ec2a71f3755959b783f09f42 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 26 Nov 2021 10:59:33 +0100 Subject: [PATCH 13/53] rrc-nr: fix RRCReconf test failing Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index dd49c7fc2..c38297527 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -361,7 +361,7 @@ void test_rrc_nr_2nd_reconfiguration(srsran::task_scheduler& task_sched, auto& rlc_srb = master_cell_group.rlc_bearer_to_add_mod_list[0]; TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.srb_to_add_mod_list[0].srb_id, rlc_srb.served_radio_bearer.srb_id()); auto& rlc_drb = master_cell_group.rlc_bearer_to_add_mod_list[1]; - TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.drb_to_add_mod_list[1].drb_id, rlc_drb.served_radio_bearer.drb_id()); + TESTASSERT_EQ(reconf_ies.radio_bearer_cfg.drb_to_add_mod_list[0].drb_id, rlc_drb.served_radio_bearer.drb_id()); // Test if NAS_msg is the same as the one sent in DLInformationTransfer TESTASSERT_EQ(true, reconf_ies.non_crit_ext.ded_nas_msg_list_present); From 40463c340d10b737653d7ad106103962a7419b86 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 10:48:43 +0000 Subject: [PATCH 14/53] nr,gnb,rrc: fix schedulingRequest resource allocation in RRC setup message --- srsgnb/src/stack/rrc/cell_asn1_config.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index f198eac78..f5175c5b5 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -470,9 +470,9 @@ void fill_pucch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pucch_cfg 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() = 0; + sr_res1.periodicity_and_offset.set_sl40() = 8; sr_res1.res_present = true; - sr_res1.res = 16; + sr_res1.res = 2; // DL data out.dl_data_to_ul_ack_present = true; From 71c0d6946111d543628e2c9d527d0feb510ec29c Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 10:49:26 +0000 Subject: [PATCH 15/53] nr,gnb,phy: fix dci padding for the case of common search space type1 --- lib/src/common/phy_cfg_nr.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/common/phy_cfg_nr.cc b/lib/src/common/phy_cfg_nr.cc index a214ff82f..2fcae86de 100644 --- a/lib/src/common/phy_cfg_nr.cc +++ b/lib/src/common/phy_cfg_nr.cc @@ -37,7 +37,8 @@ srsran_dci_cfg_nr_t phy_cfg_nr_t::get_dci_cfg() const // Iterate all configured formats for (uint32_t j = 0; j < pdcch.search_space[i].nof_formats; j++) { - if (pdcch.search_space[i].type == srsran_search_space_type_common_3 && + if ((pdcch.search_space[i].type == srsran_search_space_type_common_3 or + pdcch.search_space[i].type == srsran_search_space_type_common_1) && pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) { dci_cfg.monitor_common_0_0 = true; } else if (pdcch.search_space[i].type == srsran_search_space_type_ue && From f31a7d1d02c23e9bc7d1d80fdca311e0c694118a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 26 Nov 2021 10:25:34 +0100 Subject: [PATCH 16/53] epc,nas: add handler for PDN connectivity request COTS phones seem to send standalone PDN connectivity request messages even after the initial attach was complete. We don't fully support them in the EPC but instead of logging a warning we can just send a reject at least to keep the logs clean. --- srsepc/hdr/mme/nas.h | 1 + srsepc/src/mme/nas.cc | 45 ++++++++++++++++++++++++++-- srsepc/src/mme/s1ap_nas_transport.cc | 5 ++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/srsepc/hdr/mme/nas.h b/srsepc/hdr/mme/nas.h index 10179c95c..208f2ae3a 100644 --- a/srsepc/hdr/mme/nas.h +++ b/srsepc/hdr/mme/nas.h @@ -216,6 +216,7 @@ public: /* Uplink NAS messages handling */ bool handle_attach_request(srsran::byte_buffer_t* nas_rx); + bool handle_pdn_connectivity_request(srsran::byte_buffer_t* nas_rx); bool handle_authentication_response(srsran::byte_buffer_t* nas_rx); bool handle_security_mode_complete(srsran::byte_buffer_t* nas_rx); bool handle_attach_complete(srsran::byte_buffer_t* nas_rx); diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index 56d8f6da7..3c81aca41 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -956,8 +956,8 @@ bool nas::handle_attach_request(srsran::byte_buffer_t* nas_rx) m_s1ap->send_downlink_nas_transport( m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx.get(), m_ecm_ctx.enb_sri); - m_logger.info("Downlink NAS: Sending Authentication Request"); - srsran::console("Downlink NAS: Sending Authentication Request\n"); + m_logger.info("DL NAS: Sending Authentication Request"); + srsran::console("DL NAS: Sending Authentication Request\n"); return true; } else { m_logger.error("Attach request from known UE"); @@ -965,6 +965,47 @@ bool nas::handle_attach_request(srsran::byte_buffer_t* nas_rx) return true; } +bool nas::handle_pdn_connectivity_request(srsran::byte_buffer_t* nas_rx) +{ + LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req = {}; + + // Get PDN connectivity request messages + LIBLTE_ERROR_ENUM err = + liblte_mme_unpack_pdn_connectivity_request_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx->msg, &pdn_con_req); + if (err != LIBLTE_SUCCESS) { + m_logger.error("Error unpacking NAS PDN Connectivity Request. Error: %s", liblte_error_text[err]); + return false; + } + + // Send PDN connectivity reject + srsran::unique_byte_buffer_t nas_tx = srsran::make_byte_buffer(); + if (nas_tx == nullptr) { + m_logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return false; + } + + LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT pdn_con_reject = {}; + pdn_con_reject.eps_bearer_id = pdn_con_req.eps_bearer_id; + pdn_con_reject.proc_transaction_id = pdn_con_req.proc_transaction_id; + pdn_con_reject.esm_cause = LIBLTE_MME_ESM_CAUSE_SERVICE_OPTION_NOT_SUPPORTED; + + err = liblte_mme_pack_pdn_connectivity_reject_msg(&pdn_con_reject, (LIBLTE_BYTE_MSG_STRUCT*)nas_tx.get()); + if (err != LIBLTE_SUCCESS) { + m_logger.error("Error packing PDN connectivity reject"); + srsran::console("Error packing PDN connectivity reject\n"); + return false; + } + + // Send reply to eNB + m_s1ap->send_downlink_nas_transport( + m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx.get(), m_ecm_ctx.enb_sri); + + m_logger.info("DL NAS: Sending PDN Connectivity Reject"); + srsran::console("DL NAS: Sending PDN Connectivity Reject\n"); + + return true; +} + bool nas::handle_authentication_response(srsran::byte_buffer_t* nas_rx) { LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp = {}; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 6e7633c16..758caeb86 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -308,6 +308,11 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(const asn1::s1ap::ul_nas_tr srsran::console("UL NAS: Tracking Area Update Request\n"); nas_ctx->handle_tracking_area_update_request(nas_msg.get()); break; + case LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REQUEST: + m_logger.info("UL NAS: PDN Connectivity Request"); + srsran::console("UL NAS: PDN Connectivity Request\n"); + nas_ctx->handle_pdn_connectivity_request(nas_msg.get()); + break; default: m_logger.warning("Unhandled NAS integrity protected message %s", liblte_nas_msg_type_to_string(msg_type)); srsran::console("Unhandled NAS integrity protected message %s\n", liblte_nas_msg_type_to_string(msg_type)); From b07385a50c7d216a1f9ef40b2c92201e43221bc7 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 11:26:38 +0000 Subject: [PATCH 17/53] nr,gnb,rrc: disable PHR in RRC setup --- srsgnb/src/stack/rrc/cell_asn1_config.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index f5175c5b5..a21a5d431 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -875,6 +875,7 @@ int fill_master_cell_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1 phr.phr_type2_other_cell = false; phr.phr_mode_other_cg.value = asn1::rrc_nr::phr_cfg_s::phr_mode_other_cg_opts::real; out.mac_cell_group_cfg.skip_ul_tx_dynamic = false; + out.mac_cell_group_cfg.phr_cfg_present = false; // Note: not supported // physicalCellGroupConfig -- Need M out.phys_cell_group_cfg_present = true; @@ -887,7 +888,7 @@ int fill_master_cell_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1 out.sp_cell_cfg_present = true; fill_sp_cell_cfg_from_enb_cfg(cfg, cc, out.sp_cell_cfg); out.sp_cell_cfg.recfg_with_sync_present = false; - out.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = false; + out.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = false; // Note: not supported return SRSRAN_SUCCESS; } From 14074f0430961d9c3235f9d81d2757efd4c2fc8e Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 12:23:46 +0000 Subject: [PATCH 18/53] nr,gnb: pass gtpu pointer to ngap init --- srsgnb/src/stack/gnb_stack_nr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsgnb/src/stack/gnb_stack_nr.cc b/srsgnb/src/stack/gnb_stack_nr.cc index 20c6586ff..9bfd1a3f0 100644 --- a/srsgnb/src/stack/gnb_stack_nr.cc +++ b/srsgnb/src/stack/gnb_stack_nr.cc @@ -103,7 +103,7 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, ngap->start_pcap(&ngap_pcap); } - ngap->init(args.ngap, &rrc, nullptr); + ngap->init(args.ngap, &rrc, gtpu.get()); gtpu_args_t gtpu_args; gtpu_args.embms_enable = false; gtpu_args.mme_addr = args.ngap.amf_addr; From a038c74cc0d85a41ef75a14d08d1f7469e5be65e Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 26 Nov 2021 12:59:13 +0000 Subject: [PATCH 19/53] Only run the status prohibit timer, if it has been set before. --- lib/src/rlc/rlc_am_nr.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index 4a3736c8f..a28ef0868 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -631,7 +631,10 @@ uint32_t rlc_am_nr_rx::get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t m } if (max_len != UINT32_MAX) { - status_prohibit_timer.run(); // UINT32_MAX is used just to querry the status PDU length + // UINT32_MAX is used just to querry the status PDU length + if (status_prohibit_timer.is_valid()) { + status_prohibit_timer.run(); + } } return tmp_buf.N_bytes; } From 194fb4fabf05f7c1186803c12ef9f8d6bcf95566 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 26 Nov 2021 14:22:05 +0000 Subject: [PATCH 20/53] lib,rlc_am_nr: stop status prohibit timer when a polling bit is received. --- lib/src/rlc/rlc_am_nr.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index a28ef0868..2c1e55a25 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -502,6 +502,7 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes) if (header.p) { logger->info("%s Status packet requested through polling bit", parent->rb_name); do_status = true; + status_prohibit_timer.stop(); } debug_state(); From 9f7ae7a2b2e5472261007dbf6ae490095c40e4d4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 26 Nov 2021 11:38:00 +0000 Subject: [PATCH 21/53] gnb,ngap: Added simple allocation of lcids to ngap_ue_bearer_manager. --- .../hdr/stack/ngap/ngap_ue_bearer_manager.h | 19 +++++++++++-------- .../src/stack/ngap/ngap_ue_bearer_manager.cc | 13 ++++++++++++- srsgnb/src/stack/ngap/ngap_ue_proc.cc | 4 ++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h b/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h index 91f2d9855..361e4f46f 100644 --- a/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h +++ b/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h @@ -61,13 +61,16 @@ private: std::map pdu_session_list; srslog::basic_logger& logger; - int add_gtpu_bearer(uint16_t rnti, - 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); + std::map next_lcid_list; // Map RNTI to next LCID to be allocated + + int add_gtpu_bearer(uint16_t rnti, + 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); + uint8_t allocate_lcid(uint32_t rnti); }; } // namespace srsenb -#endif // SRSENB_NGAP_UE_BEARER_MANAGER_H \ No newline at end of file +#endif // SRSENB_NGAP_UE_BEARER_MANAGER_H diff --git a/srsgnb/src/stack/ngap/ngap_ue_bearer_manager.cc b/srsgnb/src/stack/ngap/ngap_ue_bearer_manager.cc index ad336df4c..0f1c0ac4d 100644 --- a/srsgnb/src/stack/ngap/ngap_ue_bearer_manager.cc +++ b/srsgnb/src/stack/ngap/ngap_ue_bearer_manager.cc @@ -37,6 +37,8 @@ int ngap_ue_bearer_manager::add_pdu_session(uint16_t return SRSRAN_ERROR; } + lcid = allocate_lcid(rnti); + // TODO: remove lcid and just use pdu_session_id and rnti as id for GTP tunnel int rtn = add_gtpu_bearer(rnti, pdu_session_id, teid_out, addr_out, tunnel); if (rtn != SRSRAN_SUCCESS) { @@ -62,6 +64,7 @@ int ngap_ue_bearer_manager::reset_pdu_sessions(uint16_t rnti) auto pdu_session_id = iter->first; rem_gtpu_bearer(pdu_session_id, rnti); } + next_lcid_list.erase(rnti); return true; } @@ -110,4 +113,12 @@ void ngap_ue_bearer_manager::rem_gtpu_bearer(uint16_t rnti, uint32_t pdu_session gtpu->rem_bearer(rnti, it->second.lcid); } -} // namespace srsenb \ No newline at end of file +uint8_t ngap_ue_bearer_manager::allocate_lcid(uint32_t rnti) +{ + if (next_lcid_list.find(rnti) == next_lcid_list.end()) { + next_lcid_list[rnti] = 4; + } + return next_lcid_list[rnti]++; +} + +} // namespace srsenb diff --git a/srsgnb/src/stack/ngap/ngap_ue_proc.cc b/srsgnb/src/stack/ngap/ngap_ue_proc.cc index 31f7b6247..e1e820f91 100644 --- a/srsgnb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsgnb/src/stack/ngap/ngap_ue_proc.cc @@ -143,8 +143,8 @@ proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu // TODO: Check cause asn1::ngap_nr::cause_c cause; - uint32_t teid_in; - uint16_t lcid; + uint32_t teid_in = {}; + uint16_t lcid = {}; asn1::bounded_bitstring<1, 160, true, true> addr_in; if (bearer_manager->add_pdu_session( From 61e923a6a6d28f18727bc7861ddce428bf6fcf71 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 15:34:48 +0000 Subject: [PATCH 22/53] nr,gnb,rrc: configurable RRC NR inactivity timeout --- srsenb/src/enb_cfg_parser.cc | 2 ++ srsgnb/hdr/stack/rrc/rrc_nr_config.h | 1 + srsgnb/src/stack/rrc/rrc_nr_ue.cc | 5 ++--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index f89c872e1..e9a65cb1e 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1510,6 +1510,8 @@ int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_nr_cfg_, phy_cfg_t* return SRSRAN_ERROR; } + rrc_nr_cfg_->inactivity_timeout_ms = args_->general.rrc_inactivity_timer; + // Create NR dedicated cell configuration from RRC configuration for (auto& cfg : rrc_nr_cfg_->cell_list) { cfg.phy_cell.carrier.max_mimo_layers = args_->enb.nof_ports; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_config.h b/srsgnb/hdr/stack/rrc/rrc_nr_config.h index 7f8dfa3c8..11c4873f1 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_config.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_config.h @@ -51,6 +51,7 @@ struct rrc_nr_cfg_t { rrc_nr_cfg_sr_t sr_cfg; rrc_cfg_cqi_t cqi_cfg; rrc_cell_list_nr_t cell_list; + uint32_t inactivity_timeout_ms; bool is_standalone; std::array nea_preference_list; diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index f809fcd52..7c35f2392 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -59,7 +59,7 @@ void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type) break; case UE_INACTIVITY_TIMEOUT: // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 5s - deadline_ms = 10000; + deadline_ms = parent->cfg.inactivity_timeout_ms; break; default: logger.error("Unknown timeout type %d", type); @@ -1044,8 +1044,7 @@ void rrc_nr::ue::send_rrc_reconfiguration() // If no bearer to add/mod/remove, do not include master_cell_group // Set ies.non_crit_ext_present (a few lines below) only if // master_cell_group_present == true or ies.non_crit_ext.ded_nas_msg_list_present == true - if (ies.radio_bearer_cfg_present){ - + if (ies.radio_bearer_cfg_present) { ies.non_crit_ext.master_cell_group_present = true; // Fill masterCellGroup From 68ec3eaba016d4b7784ddf1996ef56814464e1de Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 16:00:29 +0000 Subject: [PATCH 23/53] nr,gnb,rrc: remove obsolete TODO comment and set default rrc inactivity timeout --- srsgnb/hdr/stack/rrc/rrc_nr_config.h | 2 +- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_config.h b/srsgnb/hdr/stack/rrc/rrc_nr_config.h index 11c4873f1..3e289ac4c 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_config.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_config.h @@ -51,7 +51,7 @@ struct rrc_nr_cfg_t { rrc_nr_cfg_sr_t sr_cfg; rrc_cfg_cqi_t cqi_cfg; rrc_cell_list_nr_t cell_list; - uint32_t inactivity_timeout_ms; + uint32_t inactivity_timeout_ms = 100000; bool is_standalone; std::array nea_preference_list; diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 7c35f2392..00a25860e 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -58,7 +58,6 @@ void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type) deadline_ms = 5000; break; case UE_INACTIVITY_TIMEOUT: - // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 5s deadline_ms = parent->cfg.inactivity_timeout_ms; break; default: From f9ff6758aa17670a27c8b4ebe379a184087d3a6c Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 25 Nov 2021 15:50:51 +0100 Subject: [PATCH 24/53] rrc-nr: temporary fix to handle inactivity timeout Fixes issue #3689 Signed-off-by: Carlo Galiotto --- srsgnb/hdr/stack/rrc/rrc_nr.h | 1 + srsgnb/src/stack/rrc/rrc_nr.cc | 7 +++++++ srsgnb/src/stack/rrc/rrc_nr_ue.cc | 10 ++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index eac2f93f8..a82e5fb16 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -73,6 +73,7 @@ public: void rem_user(uint16_t rnti); int update_user(uint16_t new_rnti, uint16_t old_rnti) final; void set_activity_user(uint16_t rnti) final; + int rrc_release(uint16_t rnti); // RLC interface // TODO diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index fff08d71f..fdb97a6bb 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -203,6 +203,13 @@ void rrc_nr::rem_user(uint16_t rnti) } } +/// This function is called when the INACTIVITY TIMER FOR +int rrc_nr::rrc_release(uint16_t rnti) +{ + // TODO: we do not have yet a defined procedure to handle this + return SRSRAN_SUCCESS; +} + /* Function called by MAC after the reception of a C-RNTI CE indicating that the UE still has a * valid RNTI. */ diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 00a25860e..a4c15a4a2 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -92,10 +92,16 @@ void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type) switch (type) { case MSG5_RX_TIMEOUT: - case UE_INACTIVITY_TIMEOUT: + case UE_INACTIVITY_TIMEOUT: { state = rrc_nr_state_t::RRC_INACTIVE; - parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti); + if (parent->cfg.is_standalone) { + // TODO: This procedure needs to be defined + parent->rrc_release(rnti); + } else { + parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti); + } break; + } case MSG3_RX_TIMEOUT: { // MSG3 timeout, no need to notify NGAP or LTE stack. Just remove UE state = rrc_nr_state_t::RRC_IDLE; From 6513520211dd4277ad76263c4c3978b42d1ef1c7 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 17:54:16 +0000 Subject: [PATCH 25/53] nr,gnb,rrc: ensure drb config is added in RRC reconf. Do not allow LCIDs<4 for DRBs --- srsgnb/src/stack/rrc/cell_asn1_config.cc | 2 +- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index a21a5d431..12aeb1bee 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -1155,7 +1155,7 @@ void fill_cellgroup_with_radio_bearer_cfg(const rrc_nr_cfg_t& // Add DRBs for (const drb_to_add_mod_s& drb : bearers.drb_to_add_mod_list) { out.rlc_bearer_to_add_mod_list.push_back({}); - uint32_t lcid = drb_to_lcid(static_cast(drb.drb_id)); + uint32_t lcid = drb.drb_id + (int)srsran::nr_srb::count - 1; fill_drb(cfg, lcid, (srsran::nr_drb)drb.drb_id, out.rlc_bearer_to_add_mod_list.back()); } out.rlc_bearer_to_add_mod_list_present = out.rlc_bearer_to_add_mod_list.size() > 0; diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index a4c15a4a2..33dc64ac2 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1166,6 +1166,7 @@ void rrc_nr::ue::establish_eps_bearer(uint32_t pdu_session_id, srsran::const_byt drb.drb_id = 1; drb.pdcp_cfg_present = true; + drb.pdcp_cfg.drb_present = true; drb.pdcp_cfg.drb.discard_timer_present = true; drb.pdcp_cfg.drb.discard_timer.value = pdcp_cfg_s::drb_s_::discard_timer_opts::ms100; drb.pdcp_cfg.drb.pdcp_sn_size_ul_present = true; From b27c184d2f6185d1b46bcc2a57288370a4195837 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 18:38:21 +0000 Subject: [PATCH 26/53] nr,gnb,stack: add bearer manager to gNB stack to correctly map between eps bearer ids and lcids --- lib/include/srsran/common/bearer_manager.h | 3 +- lib/src/common/bearer_manager.cc | 4 +- srsgnb/hdr/stack/gnb_stack_nr.h | 5 +++ srsgnb/hdr/stack/rrc/rrc_nr.h | 18 ++++---- srsgnb/src/stack/gnb_stack_nr.cc | 52 ++++++++++++++++++++-- srsgnb/src/stack/rrc/rrc_nr.cc | 17 +++---- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 4 ++ srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 17 ++++--- 8 files changed, 92 insertions(+), 28 deletions(-) diff --git a/lib/include/srsran/common/bearer_manager.h b/lib/include/srsran/common/bearer_manager.h index 4ec7bff81..0e525408c 100644 --- a/lib/include/srsran/common/bearer_manager.h +++ b/lib/include/srsran/common/bearer_manager.h @@ -18,8 +18,8 @@ #include "srsran/common/rwlock_guard.h" #include "srsran/srslog/srslog.h" #include -#include #include +#include namespace srsran { @@ -139,6 +139,7 @@ public: using radio_bearer_t = srsran::detail::ue_bearer_manager_impl::radio_bearer_t; enb_bearer_manager(); + ~enb_bearer_manager(); /// Multi-user interface (see comments above) void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc index 3114a0c5e..c4ecf960b 100644 --- a/lib/src/common/bearer_manager.cc +++ b/lib/src/common/bearer_manager.cc @@ -113,13 +113,15 @@ namespace srsenb { enb_bearer_manager::enb_bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) {} +enb_bearer_manager::~enb_bearer_manager() {} + void enb_bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) { auto user_it = users_map.find(rnti); if (user_it == users_map.end()) { // add empty bearer map // users_map.emplace( ) returns pair - auto p = users_map.emplace( rnti, srsran::detail::ue_bearer_manager_impl{}); + auto p = users_map.emplace(rnti, srsran::detail::ue_bearer_manager_impl{}); if (!p.second) { logger.error("Bearers: Unable to add a new bearer map for rnti=0x%x", rnti); return; diff --git a/srsgnb/hdr/stack/gnb_stack_nr.h b/srsgnb/hdr/stack/gnb_stack_nr.h index 57bebcc1e..9528f9e86 100644 --- a/srsgnb/hdr/stack/gnb_stack_nr.h +++ b/srsgnb/hdr/stack/gnb_stack_nr.h @@ -33,6 +33,8 @@ namespace srsenb { class ngap; class gtpu; +class enb_bearer_manager; +class gtpu_pdcp_adapter_nr; struct gnb_stack_args_t { stack_log_args_t log; @@ -153,6 +155,9 @@ private: std::unique_ptr gtpu; // std::unique_ptr m_sdap; + std::unique_ptr bearer_manager; + std::unique_ptr gtpu_adapter; + // state std::atomic running = {false}; }; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index a82e5fb16..afe3e00c0 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -37,6 +37,8 @@ namespace srsenb { +class enb_bearer_manager; + enum class rrc_nr_state_t { RRC_IDLE, RRC_INACTIVE, RRC_CONNECTED }; class rrc_nr final : public rrc_interface_pdcp_nr, @@ -55,7 +57,7 @@ public: rlc_interface_rrc* rlc, pdcp_interface_rrc* pdcp, ngap_interface_rrc_nr* ngap_, - gtpu_interface_rrc_nr* gtpu, + enb_bearer_manager& bearer_mapper_, rrc_eutra_interface_rrc_nr* rrc_eutra_); void stop(); @@ -121,13 +123,13 @@ private: rrc_nr_cfg_t cfg = {}; // interfaces - phy_interface_stack_nr* phy = nullptr; - mac_interface_rrc_nr* mac = nullptr; - rlc_interface_rrc* rlc = nullptr; - pdcp_interface_rrc* pdcp = nullptr; - gtpu_interface_rrc_nr* gtpu = nullptr; - ngap_interface_rrc_nr* ngap = nullptr; - rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr; + phy_interface_stack_nr* phy = nullptr; + mac_interface_rrc_nr* mac = nullptr; + rlc_interface_rrc* rlc = nullptr; + pdcp_interface_rrc* pdcp = nullptr; + ngap_interface_rrc_nr* ngap = nullptr; + rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr; + enb_bearer_manager* bearer_mapper = nullptr; // args srsran::task_sched_handle task_sched; diff --git a/srsgnb/src/stack/gnb_stack_nr.cc b/srsgnb/src/stack/gnb_stack_nr.cc index 9bfd1a3f0..8dd4adae4 100644 --- a/srsgnb/src/stack/gnb_stack_nr.cc +++ b/srsgnb/src/stack/gnb_stack_nr.cc @@ -13,6 +13,7 @@ #include "srsgnb/hdr/stack/gnb_stack_nr.h" #include "srsenb/hdr/stack/upper/gtpu.h" #include "srsgnb/hdr/stack/ngap/ngap.h" +#include "srsran/common/bearer_manager.h" #include "srsran/common/network_utils.h" #include "srsran/common/standard_streams.h" #include "srsran/srsran.h" @@ -20,6 +21,46 @@ namespace srsenb { +class gtpu_pdcp_adapter_nr final : public gtpu_interface_pdcp, public pdcp_interface_gtpu +{ +public: + gtpu_pdcp_adapter_nr(srslog::basic_logger& logger_, + pdcp_interface_gtpu* pdcp_, + gtpu* gtpu_, + enb_bearer_manager& bearers_) : + logger(logger_), pdcp_obj(pdcp_), gtpu_obj(gtpu_), bearers(&bearers_) + {} + + /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU + void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override + { + auto bearer = bearers->get_lcid_bearer(rnti, lcid); + if (not bearer.is_valid()) { + logger.error("Bearer rnti=0x%x, lcid=%d not found", rnti, lcid); + return; + } + gtpu_obj->write_pdu(rnti, bearer.eps_bearer_id, std::move(pdu)); + } + void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override + { + auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); + // route SDU to PDCP entity + pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override + { + auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); + // route SDU to PDCP entity + return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); + } + +private: + srslog::basic_logger& logger; + gtpu* gtpu_obj = nullptr; + pdcp_interface_gtpu* pdcp_obj = nullptr; + enb_bearer_manager* bearers = nullptr; +}; + gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) : task_sched{512, 128}, thread("gNB"), @@ -33,6 +74,7 @@ gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) : mac(&task_sched), rrc(&task_sched), pdcp(&task_sched, pdcp_logger), + bearer_manager(new srsenb::enb_bearer_manager()), rlc(rlc_logger) { sync_task_queue = task_sched.make_task_queue(); @@ -81,6 +123,7 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, // SA mode ngap.reset(new srsenb::ngap(&task_sched, ngap_logger, &srsran::get_rx_io_manager())); gtpu.reset(new srsenb::gtpu(&task_sched, gtpu_logger, &srsran::get_rx_io_manager())); + gtpu_adapter.reset(new gtpu_pdcp_adapter_nr(gtpu_logger, &pdcp, gtpu.get(), *bearer_manager)); } // Init all layers @@ -90,14 +133,15 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, } rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); - pdcp.init(&rlc, &rrc, x2_); - if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, ngap.get(), nullptr, x2_) != SRSRAN_SUCCESS) { + if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, ngap.get(), *bearer_manager, x2_) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); return SRSRAN_ERROR; } if (ngap != nullptr) { + pdcp.init(&rlc, &rrc, gtpu_adapter.get()); + if (args.ngap_pcap.enable) { ngap_pcap.open(args.ngap_pcap.filename.c_str()); ngap->start_pcap(&ngap_pcap); @@ -108,7 +152,9 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, gtpu_args.embms_enable = false; gtpu_args.mme_addr = args.ngap.amf_addr; gtpu_args.gtp_bind_addr = args.ngap.gtp_bind_addr; - gtpu->init(gtpu_args, &pdcp); + gtpu->init(gtpu_args, gtpu_adapter.get()); + } else { + pdcp.init(&rlc, &rrc, x2_); } // TODO: add SDAP diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index fdb97a6bb..28ba94bcd 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -17,6 +17,7 @@ #include "srsgnb/hdr/stack/rrc/rrc_nr_ue.h" #include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" #include "srsran/asn1/rrc_nr_utils.h" +#include "srsran/common/bearer_manager.h" #include "srsran/common/common_nr.h" #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/standard_streams.h" @@ -38,16 +39,16 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, rlc_interface_rrc* rlc_, pdcp_interface_rrc* pdcp_, ngap_interface_rrc_nr* ngap_, - gtpu_interface_rrc_nr* gtpu_, + enb_bearer_manager& bearer_mapper_, rrc_eutra_interface_rrc_nr* rrc_eutra_) { - phy = phy_; - mac = mac_; - rlc = rlc_; - pdcp = pdcp_; - ngap = ngap_; - gtpu = gtpu_; - rrc_eutra = rrc_eutra_; + phy = phy_; + mac = mac_; + rlc = rlc_; + pdcp = pdcp_; + ngap = ngap_; + bearer_mapper = &bearer_mapper_; + rrc_eutra = rrc_eutra_; cfg = cfg_; diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 33dc64ac2..2ab0007b4 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -14,6 +14,7 @@ #include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" #include "srsgnb/hdr/stack/rrc/rrc_nr_config_utils.h" #include "srsran/asn1/rrc_nr_utils.h" +#include "srsran/common/bearer_manager.h" #include "srsran/common/string_helpers.h" using namespace asn1::rrc_nr; @@ -1180,6 +1181,9 @@ void rrc_nr::ue::establish_eps_bearer(uint32_t pdu_session_id, srsran::const_byt next_radio_bearer_cfg.drb_to_add_mod_list_present = true; next_radio_bearer_cfg.drb_to_add_mod_list.push_back(drb); + parent->bearer_mapper->add_eps_bearer( + rnti, lcid - 3, srsran::srsran_rat_t::nr, lcid); // TODO: configurable bearer id <-> lcid mapping + logger.info("Established EPS bearer for LCID %u and RNTI 0x%x", lcid, rnti); } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 2e28dcc35..5d757517c 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -13,6 +13,7 @@ #include "rrc_nr_test_helpers.h" #include "srsgnb/hdr/stack/rrc/rrc_nr_config_utils.h" #include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" +#include "srsran/common/bearer_manager.h" #include "srsran/common/test_common.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include @@ -45,6 +46,7 @@ void test_sib_generation() rlc_dummy rlc_obj; pdcp_dummy pdcp_obj; rrc_nr rrc_obj(&task_sched); + enb_bearer_manager bearer_mapper; // set cfg rrc_nr_cfg_t rrc_cfg_nr = {}; @@ -59,7 +61,7 @@ void test_sib_generation() set_derived_nr_cell_params(rrc_cfg_nr.is_standalone, rrc_cfg_nr.cell_list[0]); srsran_assert(check_rrc_nr_cfg_valid(rrc_cfg_nr) == SRSRAN_SUCCESS, "Invalid RRC NR configuration"); - TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) == + TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, bearer_mapper, nullptr) == SRSRAN_SUCCESS); const sched_nr_interface::cell_cfg_t& nrcell = mac_obj.nr_cells.at(0); @@ -97,6 +99,7 @@ int test_rrc_setup() mac_nr_dummy mac_obj; rlc_dummy rlc_obj; pdcp_dummy pdcp_obj; + enb_bearer_manager bearer_mapper; rrc_nr rrc_obj(&task_sched); // set cfg @@ -110,7 +113,7 @@ int test_rrc_setup() rrc_cfg_nr.is_standalone = false; set_derived_nr_cell_params(rrc_cfg_nr.is_standalone, rrc_cfg_nr.cell_list[0]); srsran_assert(check_rrc_nr_cfg_valid(rrc_cfg_nr) == SRSRAN_SUCCESS, "Invalid RRC NR configuration"); - TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) == + TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, bearer_mapper, nullptr) == SRSRAN_SUCCESS); for (uint32_t n = 0; n < 2; ++n) { @@ -134,6 +137,7 @@ void test_rrc_sa_connection() rlc_nr_rrc_tester rlc_obj; pdcp_nr_rrc_tester pdcp_obj; ngap_rrc_tester ngap_obj; + enb_bearer_manager bearer_mapper; rrc_nr rrc_obj(&task_sched); @@ -150,7 +154,7 @@ void test_rrc_sa_connection() set_derived_nr_cell_params(rrc_cfg_nr.is_standalone, rrc_cfg_nr.cell_list[0]); srsran_assert(check_rrc_nr_cfg_valid(rrc_cfg_nr) == SRSRAN_SUCCESS, "Invalid RRC NR configuration"); - TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, &ngap_obj, nullptr, nullptr) == + TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, &ngap_obj, bearer_mapper, nullptr) == SRSRAN_SUCCESS); sched_nr_ue_cfg_t uecfg = get_default_ue_cfg(1); @@ -158,7 +162,7 @@ void test_rrc_sa_connection() uecfg.phy_cfg.pdcch.search_space_present[2] = false; TESTASSERT_SUCCESS(rrc_obj.add_user(0x4601, uecfg)); - test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, ngap_obj,0x4601); + test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, ngap_obj, 0x4601); test_rrc_nr_info_transfer(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); test_rrc_nr_security_mode_cmd(task_sched, rrc_obj, pdcp_obj, 0x4601); test_rrc_nr_reconfiguration(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); @@ -191,9 +195,8 @@ int main(int argc, char** argv) srsenb::test_sib_generation(); TESTASSERT(srsenb::test_rrc_setup() == SRSRAN_SUCCESS); srsenb::test_rrc_sa_connection(); - TESTASSERT_EQ( 0, spy->get_warning_counter()); - TESTASSERT_EQ( 0, spy->get_error_counter()); - + TESTASSERT_EQ(0, spy->get_warning_counter()); + TESTASSERT_EQ(0, spy->get_error_counter()); return SRSRAN_SUCCESS; } From 123d79724dbddc89d61f9c6aff2e459cd651639a Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 18:45:16 +0000 Subject: [PATCH 27/53] nr,gnb,rrc: restart activity timer when new PDUs arrive in case of SA --- srsgnb/src/stack/rrc/rrc_nr.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 28ba94bcd..67e7ac949 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -251,10 +251,11 @@ void rrc_nr::set_activity_user(uint16_t rnti) } ue* ue_ptr = it->second.get(); + // Restart inactivity timer for RRC-NR + ue_ptr->set_activity(); + // inform EUTRA RRC about user activity if (ue_ptr->is_endc()) { - // Restart inactivity timer for RRC-NR - ue_ptr->set_activity(); // inform EUTRA RRC about user activity rrc_eutra->set_activity_user(ue_ptr->get_eutra_rnti()); } From 74fda904acccc56d7b3a1cbf6f3f440ede60c660 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 26 Nov 2021 20:33:32 +0000 Subject: [PATCH 28/53] nr,gnb,stack: use common gtpu_pdcp_adapter class for both NSA and SA cases --- srsenb/hdr/stack/upper/gtpu_pdcp_adapter.h | 78 ++++++++++++++++++++++ srsenb/src/stack/enb_stack_lte.cc | 55 +-------------- srsgnb/hdr/stack/gnb_stack_nr.h | 6 +- srsgnb/src/stack/gnb_stack_nr.cc | 45 +------------ 4 files changed, 84 insertions(+), 100 deletions(-) create mode 100644 srsenb/hdr/stack/upper/gtpu_pdcp_adapter.h diff --git a/srsenb/hdr/stack/upper/gtpu_pdcp_adapter.h b/srsenb/hdr/stack/upper/gtpu_pdcp_adapter.h new file mode 100644 index 000000000..c34f60a55 --- /dev/null +++ b/srsenb/hdr/stack/upper/gtpu_pdcp_adapter.h @@ -0,0 +1,78 @@ +/** + * + * \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_GTPU_PDCP_ADAPTER_H +#define SRSRAN_GTPU_PDCP_ADAPTER_H + +#include "srsran/common/bearer_manager.h" +#include "srsran/interfaces/enb_gtpu_interfaces.h" +#include "srsran/srslog/logger.h" + +namespace srsenb { + +class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interface_gtpu +{ +public: + gtpu_pdcp_adapter(srslog::basic_logger& logger_, + pdcp_interface_gtpu* pdcp_lte, + pdcp_interface_gtpu* pdcp_nr, + gtpu* gtpu_, + enb_bearer_manager& bearers_) : + logger(logger_), pdcp_lte_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_) + {} + + /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU + void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override + { + auto bearer = bearers->get_lcid_bearer(rnti, lcid); + if (not bearer.is_valid()) { + logger.error("Bearer rnti=0x%x, lcid=%d not found", rnti, lcid); + return; + } + gtpu_obj->write_pdu(rnti, bearer.eps_bearer_id, std::move(pdu)); + } + void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override + { + auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); + // route SDU to PDCP entity + if (bearer.rat == srsran::srsran_rat_t::lte) { + pdcp_lte_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else if (bearer.rat == srsran::srsran_rat_t::nr) { + pdcp_nr_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + } else { + logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); + } + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override + { + auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); + // route SDU to PDCP entity + if (bearer.rat == srsran::srsran_rat_t::lte) { + return pdcp_lte_obj->get_buffered_pdus(rnti, bearer.lcid); + } else if (bearer.rat == srsran::srsran_rat_t::nr) { + return pdcp_nr_obj->get_buffered_pdus(rnti, bearer.lcid); + } + logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id); + return {}; + } + +private: + srslog::basic_logger& logger; + gtpu* gtpu_obj = nullptr; + pdcp_interface_gtpu* pdcp_lte_obj = nullptr; + pdcp_interface_gtpu* pdcp_nr_obj = nullptr; + enb_bearer_manager* bearers = nullptr; +}; + +} // namespace srsenb + +#endif // SRSRAN_GTPU_PDCP_ADAPTER_H diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index eb4a90c2f..269a0ccae 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -13,6 +13,7 @@ #include "srsenb/hdr/stack/enb_stack_lte.h" #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/enb.h" +#include "srsenb/hdr/stack/upper/gtpu_pdcp_adapter.h" #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/rlc/bearer_mem_pool.h" @@ -22,60 +23,6 @@ using namespace srsran; namespace srsenb { -class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interface_gtpu -{ -public: - gtpu_pdcp_adapter(srslog::basic_logger& logger_, - pdcp* pdcp_lte, - pdcp_interface_gtpu* pdcp_x2, - gtpu* gtpu_, - enb_bearer_manager& bearers_) : - logger(logger_), pdcp_obj(pdcp_lte), pdcp_x2_obj(pdcp_x2), gtpu_obj(gtpu_), bearers(&bearers_) - {} - - /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU - void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override - { - auto bearer = bearers->get_lcid_bearer(rnti, lcid); - if (not bearer.is_valid()) { - logger.error("Bearer rnti=0x%x, lcid=%d not found", rnti, lcid); - return; - } - gtpu_obj->write_pdu(rnti, bearer.eps_bearer_id, std::move(pdu)); - } - void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override - { - auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); - // route SDU to PDCP entity - if (bearer.rat == srsran_rat_t::lte) { - pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); - } else if (bearer.rat == srsran_rat_t::nr) { - pdcp_x2_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); - } else { - logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); - } - } - std::map get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override - { - auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); - // route SDU to PDCP entity - if (bearer.rat == srsran_rat_t::lte) { - return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); - } else if (bearer.rat == srsran_rat_t::nr) { - return pdcp_x2_obj->get_buffered_pdus(rnti, bearer.lcid); - } - logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id); - return {}; - } - -private: - srslog::basic_logger& logger; - gtpu* gtpu_obj = nullptr; - pdcp* pdcp_obj = nullptr; - pdcp_interface_gtpu* pdcp_x2_obj = nullptr; - enb_bearer_manager* bearers = nullptr; -}; - enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : thread("STACK"), mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), diff --git a/srsgnb/hdr/stack/gnb_stack_nr.h b/srsgnb/hdr/stack/gnb_stack_nr.h index 9528f9e86..cc1739b32 100644 --- a/srsgnb/hdr/stack/gnb_stack_nr.h +++ b/srsgnb/hdr/stack/gnb_stack_nr.h @@ -34,7 +34,7 @@ namespace srsenb { class ngap; class gtpu; class enb_bearer_manager; -class gtpu_pdcp_adapter_nr; +class gtpu_pdcp_adapter; struct gnb_stack_args_t { stack_log_args_t log; @@ -155,8 +155,8 @@ private: std::unique_ptr gtpu; // std::unique_ptr m_sdap; - std::unique_ptr bearer_manager; - std::unique_ptr gtpu_adapter; + std::unique_ptr bearer_manager; + std::unique_ptr gtpu_adapter; // state std::atomic running = {false}; diff --git a/srsgnb/src/stack/gnb_stack_nr.cc b/srsgnb/src/stack/gnb_stack_nr.cc index 8dd4adae4..811c19f1d 100644 --- a/srsgnb/src/stack/gnb_stack_nr.cc +++ b/srsgnb/src/stack/gnb_stack_nr.cc @@ -12,55 +12,14 @@ #include "srsgnb/hdr/stack/gnb_stack_nr.h" #include "srsenb/hdr/stack/upper/gtpu.h" +#include "srsenb/hdr/stack/upper/gtpu_pdcp_adapter.h" #include "srsgnb/hdr/stack/ngap/ngap.h" -#include "srsran/common/bearer_manager.h" #include "srsran/common/network_utils.h" -#include "srsran/common/standard_streams.h" #include "srsran/srsran.h" #include namespace srsenb { -class gtpu_pdcp_adapter_nr final : public gtpu_interface_pdcp, public pdcp_interface_gtpu -{ -public: - gtpu_pdcp_adapter_nr(srslog::basic_logger& logger_, - pdcp_interface_gtpu* pdcp_, - gtpu* gtpu_, - enb_bearer_manager& bearers_) : - logger(logger_), pdcp_obj(pdcp_), gtpu_obj(gtpu_), bearers(&bearers_) - {} - - /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU - void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) override - { - auto bearer = bearers->get_lcid_bearer(rnti, lcid); - if (not bearer.is_valid()) { - logger.error("Bearer rnti=0x%x, lcid=%d not found", rnti, lcid); - return; - } - gtpu_obj->write_pdu(rnti, bearer.eps_bearer_id, std::move(pdu)); - } - void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override - { - auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); - // route SDU to PDCP entity - pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); - } - std::map get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override - { - auto bearer = bearers->get_radio_bearer(rnti, eps_bearer_id); - // route SDU to PDCP entity - return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); - } - -private: - srslog::basic_logger& logger; - gtpu* gtpu_obj = nullptr; - pdcp_interface_gtpu* pdcp_obj = nullptr; - enb_bearer_manager* bearers = nullptr; -}; - gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) : task_sched{512, 128}, thread("gNB"), @@ -123,7 +82,7 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, // SA mode ngap.reset(new srsenb::ngap(&task_sched, ngap_logger, &srsran::get_rx_io_manager())); gtpu.reset(new srsenb::gtpu(&task_sched, gtpu_logger, &srsran::get_rx_io_manager())); - gtpu_adapter.reset(new gtpu_pdcp_adapter_nr(gtpu_logger, &pdcp, gtpu.get(), *bearer_manager)); + gtpu_adapter.reset(new gtpu_pdcp_adapter(gtpu_logger, nullptr, &pdcp, gtpu.get(), *bearer_manager)); } // Init all layers From a15962c81788978e111063b3926ca506febe3367 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 26 Nov 2021 12:29:40 +0100 Subject: [PATCH 29/53] ue,rrc: move NR RRC into own folder --- srsue/hdr/stack/{rrc => rrc_nr}/rrc_nr.h | 2 +- .../hdr/stack/{rrc/nr => rrc_nr}/rrc_nr_config.h | 0 srsue/hdr/stack/ue_stack_base.h | 2 +- srsue/hdr/stack/ue_stack_lte.h | 2 +- srsue/src/stack/CMakeLists.txt | 3 ++- srsue/src/stack/rrc/CMakeLists.txt | 6 +----- srsue/src/stack/rrc/test/CMakeLists.txt | 15 +-------------- srsue/src/stack/rrc/test/rrc_meas_test.cc | 2 +- srsue/src/stack/rrc_nr/CMakeLists.txt | 13 +++++++++++++ srsue/src/stack/{rrc => rrc_nr}/rrc_nr.cc | 2 +- srsue/src/stack/rrc_nr/test/CMakeLists.txt | 10 ++++++++++ .../stack/{rrc => rrc_nr}/test/ue_rrc_nr_test.cc | 2 +- srsue/src/stack/ue_stack_nr.cc | 2 +- 13 files changed, 34 insertions(+), 27 deletions(-) rename srsue/hdr/stack/{rrc => rrc_nr}/rrc_nr.h (99%) rename srsue/hdr/stack/{rrc/nr => rrc_nr}/rrc_nr_config.h (100%) create mode 100644 srsue/src/stack/rrc_nr/CMakeLists.txt rename srsue/src/stack/{rrc => rrc_nr}/rrc_nr.cc (99%) create mode 100644 srsue/src/stack/rrc_nr/test/CMakeLists.txt rename srsue/src/stack/{rrc => rrc_nr}/test/ue_rrc_nr_test.cc (99%) diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc_nr/rrc_nr.h similarity index 99% rename from srsue/hdr/stack/rrc/rrc_nr.h rename to srsue/hdr/stack/rrc_nr/rrc_nr.h index 823a479e3..e53c6943e 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc_nr/rrc_nr.h @@ -13,7 +13,7 @@ #ifndef SRSUE_RRC_NR_H #define SRSUE_RRC_NR_H -#include "nr/rrc_nr_config.h" +#include "rrc_nr_config.h" #include "srsran/adt/circular_map.h" #include "srsran/asn1/rrc_nr.h" #include "srsran/asn1/rrc_nr_utils.h" diff --git a/srsue/hdr/stack/rrc/nr/rrc_nr_config.h b/srsue/hdr/stack/rrc_nr/rrc_nr_config.h similarity index 100% rename from srsue/hdr/stack/rrc/nr/rrc_nr_config.h rename to srsue/hdr/stack/rrc_nr/rrc_nr_config.h diff --git a/srsue/hdr/stack/ue_stack_base.h b/srsue/hdr/stack/ue_stack_base.h index 2551922c0..7e478f8a2 100644 --- a/srsue/hdr/stack/ue_stack_base.h +++ b/srsue/hdr/stack/ue_stack_base.h @@ -13,8 +13,8 @@ #ifndef SRSUE_UE_STACK_BASE_H #define SRSUE_UE_STACK_BASE_H -#include "rrc/nr/rrc_nr_config.h" #include "rrc/rrc_config.h" +#include "rrc_nr/rrc_nr_config.h" #include "srsue/hdr/stack/upper/nas_config.h" #include "srsue/hdr/ue_metrics_interface.h" #include "upper/gw.h" diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index a6b6b4dd5..21adb8d61 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -20,7 +20,7 @@ #include "mac/mac.h" #include "mac_nr/mac_nr.h" #include "rrc/rrc.h" -#include "rrc/rrc_nr.h" +#include "rrc_nr/rrc_nr.h" #include "srsran/common/bearer_manager.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/multiqueue.h" diff --git a/srsue/src/stack/CMakeLists.txt b/srsue/src/stack/CMakeLists.txt index c2834833e..48b1b61f2 100644 --- a/srsue/src/stack/CMakeLists.txt +++ b/srsue/src/stack/CMakeLists.txt @@ -8,12 +8,13 @@ add_subdirectory(mac_common) add_subdirectory(mac) +add_subdirectory(mac_nr) add_subdirectory(rrc) +add_subdirectory(rrc_nr) add_subdirectory(upper) set(SOURCES ue_stack_lte.cc) add_library(srsue_stack STATIC ${SOURCES}) -add_subdirectory(mac_nr) set(SOURCES ue_stack_nr.cc) add_library(srsue_nr_stack STATIC ${SOURCES}) diff --git a/srsue/src/stack/rrc/CMakeLists.txt b/srsue/src/stack/rrc/CMakeLists.txt index 88a66feab..19edf7884 100644 --- a/srsue/src/stack/rrc/CMakeLists.txt +++ b/srsue/src/stack/rrc/CMakeLists.txt @@ -9,8 +9,4 @@ add_subdirectory(test) 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) -add_library(srsue_rrc_nr STATIC ${SOURCES}) - +add_library(srsue_rrc STATIC ${SOURCES}) \ No newline at end of file diff --git a/srsue/src/stack/rrc/test/CMakeLists.txt b/srsue/src/stack/rrc/test/CMakeLists.txt index 55c77ef15..cd10f22c6 100644 --- a/srsue/src/stack/rrc/test/CMakeLists.txt +++ b/srsue/src/stack/rrc/test/CMakeLists.txt @@ -24,17 +24,4 @@ add_test(rrc_cell_test rrc_cell_test) add_executable(rrc_rlf_report_test rrc_rlf_report_test.cc) target_link_libraries(rrc_rlf_report_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) -add_test(rrc_rlf_report_test rrc_rlf_report_test) - -add_executable(ue_rrc_nr_test ue_rrc_nr_test.cc) -target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) - -######################################################################## -# Option to run command after build (useful for remote builds) -######################################################################## -if (NOT ${BUILD_CMD} STREQUAL "") - message(STATUS "Added custom post-build command: ${BUILD_CMD}") - add_custom_command(TARGET ip_test POST_BUILD COMMAND ${BUILD_CMD}) -else(NOT ${BUILD_CMD} STREQUAL "") - message(STATUS "No post-build command defined") -endif (NOT ${BUILD_CMD} STREQUAL "") +add_test(rrc_rlf_report_test rrc_rlf_report_test) \ No newline at end of file diff --git a/srsue/src/stack/rrc/test/rrc_meas_test.cc b/srsue/src/stack/rrc/test/rrc_meas_test.cc index bf610fd65..60121b01a 100644 --- a/srsue/src/stack/rrc/test/rrc_meas_test.cc +++ b/srsue/src/stack/rrc/test/rrc_meas_test.cc @@ -17,7 +17,7 @@ #include "srsran/upper/pdcp.h" #include "srsue/hdr/stack/rrc/rrc.h" #include "srsue/hdr/stack/rrc/rrc_meas.h" -#include "srsue/hdr/stack/rrc/rrc_nr.h" +#include "srsue/hdr/stack/rrc_nr/rrc_nr.h" #include "srsue/hdr/stack/upper/nas.h" #include diff --git a/srsue/src/stack/rrc_nr/CMakeLists.txt b/srsue/src/stack/rrc_nr/CMakeLists.txt new file mode 100644 index 000000000..685824cd2 --- /dev/null +++ b/srsue/src/stack/rrc_nr/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# 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. +# + +add_subdirectory(test) + +set(SOURCES rrc_nr.cc) +add_library(srsue_rrc_nr STATIC ${SOURCES}) + diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc similarity index 99% rename from srsue/src/stack/rrc/rrc_nr.cc rename to srsue/src/stack/rrc_nr/rrc_nr.cc index b46b218be..aed7c1a79 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -10,7 +10,7 @@ * */ -#include "srsue/hdr/stack/rrc/rrc_nr.h" +#include "srsue/hdr/stack/rrc_nr/rrc_nr.h" #include "srsran/common/band_helper.h" #include "srsran/common/security.h" #include "srsran/common/standard_streams.h" diff --git a/srsue/src/stack/rrc_nr/test/CMakeLists.txt b/srsue/src/stack/rrc_nr/test/CMakeLists.txt new file mode 100644 index 000000000..b2b114239 --- /dev/null +++ b/srsue/src/stack/rrc_nr/test/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# 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. +# + +add_executable(ue_rrc_nr_test ue_rrc_nr_test.cc) +target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) \ No newline at end of file diff --git a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc similarity index 99% rename from srsue/src/stack/rrc/test/ue_rrc_nr_test.cc rename to srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc index fea8ff597..774eb4db5 100644 --- a/srsue/src/stack/rrc/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc @@ -16,7 +16,7 @@ #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rlc_interfaces.h" #include "srsran/interfaces/ue_usim_interfaces.h" -#include "srsue/hdr/stack/rrc/rrc_nr.h" +#include "srsue/hdr/stack/rrc_nr/rrc_nr.h" using namespace srsue; diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index b5c2a38fc..da1b66806 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -12,7 +12,7 @@ #include "srsue/hdr/stack/ue_stack_nr.h" #include "srsran/srsran.h" -#include "srsue/hdr/stack/rrc/rrc_nr.h" +#include "srsue/hdr/stack/rrc_nr/rrc_nr.h" using namespace srsran; From ccd433467246aa6ba4e632b350e20d3998ab6d35 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 26 Nov 2021 14:14:16 +0100 Subject: [PATCH 30/53] rrc_nr: add basic interface for NAS --- srsue/hdr/stack/rrc/rrc_cell.h | 6 ---- srsue/hdr/stack/rrc_nr/rrc_nr.h | 17 +++++++-- srsue/src/stack/rrc/rrc_cell.cc | 35 +++++++++++++++++++ srsue/src/stack/rrc_nr/CMakeLists.txt | 5 ++- srsue/src/stack/rrc_nr/rrc_nr.cc | 40 +++++++++++++++++++++- srsue/src/stack/rrc_nr/test/CMakeLists.txt | 2 +- 6 files changed, 92 insertions(+), 13 deletions(-) diff --git a/srsue/hdr/stack/rrc/rrc_cell.h b/srsue/hdr/stack/rrc/rrc_cell.h index 9df95297e..783e3a830 100644 --- a/srsue/hdr/stack/rrc/rrc_cell.h +++ b/srsue/hdr/stack/rrc/rrc_cell.h @@ -121,8 +121,6 @@ public: void set_sib3(const asn1::rrc_nr::sib3_s& sib3_); const asn1::rrc_nr::sib1_s* sib1ptr() const { return has_sib1() ? &sib1 : nullptr; } - const asn1::rrc_nr::sib2_s* sib2ptr() const { return has_sib2() ? &sib2 : nullptr; } - const asn1::rrc_nr::sib3_s* sib3ptr() const { return has_sib3() ? &sib3 : nullptr; } uint32_t get_cell_id() const { return (uint32_t)0xFFFF; } // TODO find the correct sib @@ -131,11 +129,7 @@ public: std::string to_string() const; - bool has_mcch = false; asn1::rrc_nr::sib1_s sib1 = {}; - asn1::rrc_nr::sib2_s sib2 = {}; - asn1::rrc_nr::sib3_s sib3 = {}; - asn1::rrc::mcch_msg_s mcch = {}; }; class meas_cell_eutra : public meas_cell diff --git a/srsue/hdr/stack/rrc_nr/rrc_nr.h b/srsue/hdr/stack/rrc_nr/rrc_nr.h index e53c6943e..e9c04e53d 100644 --- a/srsue/hdr/stack/rrc_nr/rrc_nr.h +++ b/srsue/hdr/stack/rrc_nr/rrc_nr.h @@ -13,6 +13,7 @@ #ifndef SRSUE_RRC_NR_H #define SRSUE_RRC_NR_H +#include "../rrc/rrc_cell.h" #include "rrc_nr_config.h" #include "srsran/adt/circular_map.h" #include "srsran/asn1/rrc_nr.h" @@ -40,6 +41,7 @@ class rrc_nr final : public rrc_interface_phy_nr, public rrc_interface_rlc, public rrc_interface_mac, public rrc_nr_interface_rrc, + public rrc_nr_interface_nas_5g, public srsran::timer_callback { public: @@ -101,6 +103,13 @@ public: void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) final; void notify_pdcp_integrity_error(uint32_t lcid) final; + // NAS interface + int write_sdu(srsran::unique_byte_buffer_t sdu); + bool is_connected(); + int connection_request(srsran::nr_establishment_cause_t cause, srsran::unique_byte_buffer_t sdu); + uint16_t get_mcc(); + uint16_t get_mnc(); + // RRC (LTE) interface int get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps); int get_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps); @@ -122,6 +131,9 @@ public: void set_phy_config_complete(bool status) final; private: + // senders + void send_ul_info_transfer(srsran::unique_byte_buffer_t nas_msg); + srsran::task_sched_handle task_sched; struct cmd_msg_t { enum { PDU, PCCH, PDU_MCH, RLF, PDU_BCCH_DLSCH, STOP } command; @@ -145,6 +157,8 @@ private: usim_interface_rrc_nr* usim = nullptr; stack_interface_rrc* stack = nullptr; + meas_cell_list meas_cells; + const uint32_t sim_measurement_timer_duration_ms = 250; uint32_t sim_measurement_carrier_freq_r15; srsran::timer_handler::unique_timer sim_measurement_timer; @@ -157,8 +171,7 @@ private: RRC_NR_STATE_N_ITEMS, }; const static char* rrc_nr_state_text[RRC_NR_STATE_N_ITEMS]; - - // rrc_nr_state_t state = RRC_NR_STATE_IDLE; + rrc_nr_state_t state = RRC_NR_STATE_IDLE; // Stores the state of the PHy configuration setting enum { diff --git a/srsue/src/stack/rrc/rrc_cell.cc b/srsue/src/stack/rrc/rrc_cell.cc index 577aa7060..e12e52410 100644 --- a/srsue/src/stack/rrc/rrc_cell.cc +++ b/srsue/src/stack/rrc/rrc_cell.cc @@ -171,6 +171,41 @@ uint16_t meas_cell_eutra::get_mnc() const return 0; } +uint16_t meas_cell_nr::get_mcc() const +{ + uint16_t mcc = 0; + if (has_valid_sib1) { + if (sib1.cell_access_related_info.plmn_id_list.size() > 0) { + // PLMN ID list is nested twice + if (sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list.size() > 0) { + if (sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list[0].mcc_present) { + if (srsran::bytes_to_mcc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list[0].mcc[0], &mcc)) { + // successfully read MCC + } + } + } + } + } + return mcc; +} + +uint16_t meas_cell_nr::get_mnc() const +{ + uint16_t mnc = 0; + if (has_valid_sib1) { + if (sib1.cell_access_related_info.plmn_id_list.size() > 0) { + if (sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list.size() > 0) { + if (srsran::bytes_to_mnc(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list[0].mnc[0], + &mnc, + sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list[0].mnc.size())) { + // successfully read MNC + } + } + } + } + return mnc; +} + /********************************************* * Neighbour Cell List ********************************************/ diff --git a/srsue/src/stack/rrc_nr/CMakeLists.txt b/srsue/src/stack/rrc_nr/CMakeLists.txt index 685824cd2..870857e66 100644 --- a/srsue/src/stack/rrc_nr/CMakeLists.txt +++ b/srsue/src/stack/rrc_nr/CMakeLists.txt @@ -8,6 +8,5 @@ add_subdirectory(test) -set(SOURCES rrc_nr.cc) -add_library(srsue_rrc_nr STATIC ${SOURCES}) - +set(SOURCES rrc_nr.cc ../rrc/rrc_cell.cc) +add_library(srsue_rrc_nr STATIC ${SOURCES}) \ No newline at end of file diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index aed7c1a79..48b164f3f 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -31,7 +31,7 @@ namespace srsue { const char* rrc_nr::rrc_nr_state_text[] = {"IDLE", "CONNECTED", "CONNECTED-INACTIVE"}; rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : - logger(srslog::fetch_basic_logger("RRC-NR")), task_sched(task_sched_), conn_recfg_proc(this) + logger(srslog::fetch_basic_logger("RRC-NR")), task_sched(task_sched_), conn_recfg_proc(this), meas_cells(task_sched_) {} rrc_nr::~rrc_nr() = default; @@ -209,6 +209,44 @@ void rrc_nr::write_pdu_pcch(srsran::unique_byte_buffer_t pdu) {} void rrc_nr::write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) {} void rrc_nr::notify_pdcp_integrity_error(uint32_t lcid) {} +// NAS interface +int rrc_nr::write_sdu(srsran::unique_byte_buffer_t sdu) +{ + if (state == RRC_NR_STATE_IDLE) { + logger.warning("Received ULInformationTransfer SDU when in IDLE"); + return SRSRAN_ERROR; + } + send_ul_info_transfer(std::move(sdu)); + return SRSRAN_SUCCESS; +} + +bool rrc_nr::is_connected() +{ + return false; +} + +int rrc_nr::connection_request(srsran::nr_establishment_cause_t cause, srsran::unique_byte_buffer_t sdu) +{ + return SRSRAN_SUCCESS; +} + +uint16_t rrc_nr::get_mcc() +{ + return meas_cells.serving_cell().get_mcc(); +} + +uint16_t rrc_nr::get_mnc() +{ + return meas_cells.serving_cell().get_mnc(); +} + +// Senders +void rrc_nr::send_ul_info_transfer(unique_byte_buffer_t nas_msg) +{ + logger.warning("%s not implemented yet.", __FUNCTION__); +} + +// EUTRA-RRC interface int rrc_nr::get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps_pdu) { struct ue_mrdc_cap_s mrdc_cap; diff --git a/srsue/src/stack/rrc_nr/test/CMakeLists.txt b/srsue/src/stack/rrc_nr/test/CMakeLists.txt index b2b114239..1e431d46a 100644 --- a/srsue/src/stack/rrc_nr/test/CMakeLists.txt +++ b/srsue/src/stack/rrc_nr/test/CMakeLists.txt @@ -7,4 +7,4 @@ # add_executable(ue_rrc_nr_test ue_rrc_nr_test.cc) -target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) \ No newline at end of file +target_link_libraries(ue_rrc_nr_test srsue_rrc srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1) \ No newline at end of file From 7227f03314f40a9eb891ba0e963bbcf96cbb7b36 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 26 Nov 2021 15:09:09 +0100 Subject: [PATCH 31/53] ue,rrc_nr: refactor reconfig procedure to own source file preparation to add next procedure --- srsue/hdr/stack/rrc_nr/rrc_nr.h | 26 +--- srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h | 52 +++++++ srsue/src/stack/rrc_nr/CMakeLists.txt | 2 +- srsue/src/stack/rrc_nr/rrc_nr.cc | 135 +---------------- srsue/src/stack/rrc_nr/rrc_nr_procedures.cc | 160 ++++++++++++++++++++ 5 files changed, 216 insertions(+), 159 deletions(-) create mode 100644 srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h create mode 100644 srsue/src/stack/rrc_nr/rrc_nr_procedures.cc diff --git a/srsue/hdr/stack/rrc_nr/rrc_nr.h b/srsue/hdr/stack/rrc_nr/rrc_nr.h index e9c04e53d..5ba89bb87 100644 --- a/srsue/hdr/stack/rrc_nr/rrc_nr.h +++ b/srsue/hdr/stack/rrc_nr/rrc_nr.h @@ -218,30 +218,8 @@ private: typedef enum { mcg_srb1, en_dc_srb3, nr } reconf_initiator_t; - class connection_reconf_no_ho_proc - { - public: - explicit connection_reconf_no_ho_proc(rrc_nr* parent_); - srsran::proc_outcome_t init(const reconf_initiator_t initiator_, - const bool endc_release_and_add_r15, - const bool nr_secondary_cell_group_cfg_r15_present, - const asn1::dyn_octstring nr_secondary_cell_group_cfg_r15, - const bool sk_counter_r15_present, - const uint32_t sk_counter_r15, - const bool nr_radio_bearer_cfg1_r15_present, - const asn1::dyn_octstring nr_radio_bearer_cfg1_r15); - srsran::proc_outcome_t step() { return srsran::proc_outcome_t::yield; } - static const char* name() { return "NR Connection Reconfiguration"; } - srsran::proc_outcome_t react(const bool& config_complete); - void then(const srsran::proc_state_t& result); - - private: - // const - rrc_nr* rrc_ptr; - reconf_initiator_t initiator; - asn1::rrc_nr::rrc_recfg_s rrc_recfg; - asn1::rrc_nr::cell_group_cfg_s cell_group_cfg; - }; + // RRC procedures + class connection_reconf_no_ho_proc; srsran::proc_t conn_recfg_proc; diff --git a/srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h b/srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h new file mode 100644 index 000000000..9f5e65561 --- /dev/null +++ b/srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h @@ -0,0 +1,52 @@ +/** + * + * \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/srslog/srslog.h" +#include "srsue/hdr/stack/rrc_nr/rrc_nr.h" + +#ifndef SRSRAN_RRC_NR_PROCEDURES_H +#define SRSRAN_RRC_NR_PROCEDURES_H + +namespace srsue { + +/******************************** + * Procedures + *******************************/ + +class rrc_nr::connection_reconf_no_ho_proc +{ +public: + explicit connection_reconf_no_ho_proc(rrc_nr* parent_); + srsran::proc_outcome_t init(const reconf_initiator_t initiator_, + const bool endc_release_and_add_r15, + const bool nr_secondary_cell_group_cfg_r15_present, + const asn1::dyn_octstring nr_secondary_cell_group_cfg_r15, + const bool sk_counter_r15_present, + const uint32_t sk_counter_r15, + const bool nr_radio_bearer_cfg1_r15_present, + const asn1::dyn_octstring nr_radio_bearer_cfg1_r15); + srsran::proc_outcome_t step() { return srsran::proc_outcome_t::yield; } + static const char* name() { return "NR Connection Reconfiguration"; } + srsran::proc_outcome_t react(const bool& config_complete); + void then(const srsran::proc_state_t& result); + +private: + // const + rrc_nr* rrc_ptr = nullptr; + reconf_initiator_t initiator; + asn1::rrc_nr::rrc_recfg_s rrc_recfg; + asn1::rrc_nr::cell_group_cfg_s cell_group_cfg; +}; + +} // namespace srsue + +#endif // SRSRAN_RRC_NR_PROCEDURES_H diff --git a/srsue/src/stack/rrc_nr/CMakeLists.txt b/srsue/src/stack/rrc_nr/CMakeLists.txt index 870857e66..5bbeafd4a 100644 --- a/srsue/src/stack/rrc_nr/CMakeLists.txt +++ b/srsue/src/stack/rrc_nr/CMakeLists.txt @@ -8,5 +8,5 @@ add_subdirectory(test) -set(SOURCES rrc_nr.cc ../rrc/rrc_cell.cc) +set(SOURCES rrc_nr.cc rrc_nr_procedures.cc ../rrc/rrc_cell.cc) add_library(srsue_rrc_nr STATIC ${SOURCES}) \ No newline at end of file diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index 48b164f3f..0523e7bb5 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -16,13 +16,9 @@ #include "srsran/common/standard_streams.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rlc_interfaces.h" +#include "srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h" #include "srsue/hdr/stack/upper/usim.h" -#define Error(fmt, ...) rrc_ptr->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) -#define Warning(fmt, ...) rrc_ptr->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) -#define Info(fmt, ...) rrc_ptr->logger.info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) -#define Debug(fmt, ...) rrc_ptr->logger.debug("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) - using namespace asn1::rrc_nr; using namespace asn1; using namespace srsran; @@ -1586,133 +1582,4 @@ void rrc_nr::set_phy_config_complete(bool status) phy_cfg_state = PHY_CFG_STATE_NONE; } -/* Procedures */ -rrc_nr::connection_reconf_no_ho_proc::connection_reconf_no_ho_proc(rrc_nr* parent_) : rrc_ptr(parent_), initiator(nr) {} - -proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator_t initiator_, - const bool endc_release_and_add_r15, - const bool nr_secondary_cell_group_cfg_r15_present, - const asn1::dyn_octstring nr_secondary_cell_group_cfg_r15, - const bool sk_counter_r15_present, - const uint32_t sk_counter_r15, - const bool nr_radio_bearer_cfg1_r15_present, - const asn1::dyn_octstring nr_radio_bearer_cfg1_r15) -{ - Info("Starting..."); - initiator = initiator_; - - rrc_recfg_s rrc_recfg; - cell_group_cfg_s cell_group_cfg; - radio_bearer_cfg_s radio_bearer_cfg; - asn1::SRSASN_CODE err; - - if (nr_secondary_cell_group_cfg_r15_present) { - cbit_ref bref(nr_secondary_cell_group_cfg_r15.data(), nr_secondary_cell_group_cfg_r15.size()); - err = rrc_recfg.unpack(bref); - if (err != asn1::SRSASN_SUCCESS) { - Error("Could not unpack NR reconfiguration message."); - return proc_outcome_t::error; - } - - rrc_ptr->log_rrc_message( - "RRC NR Reconfiguration", Rx, nr_secondary_cell_group_cfg_r15, rrc_recfg, "NR Secondary Cell Group Cfg R15"); - - if (rrc_recfg.crit_exts.type() != asn1::rrc_nr::rrc_recfg_s::crit_exts_c_::types::rrc_recfg) { - Error("Reconfiguration does not contain Secondary Cell Group Config"); - return proc_outcome_t::error; - } - - if (not rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group_present) { - Error("Reconfiguration does not contain Secondary Cell Group Config"); - return proc_outcome_t::error; - } - - cbit_ref bref0(rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group.data(), - rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group.size()); - - err = cell_group_cfg.unpack(bref0); - if (err != asn1::SRSASN_SUCCESS) { - Error("Could not unpack cell group message message."); - return proc_outcome_t::error; - } - - rrc_ptr->log_rrc_message("RRC NR Reconfiguration", - Rx, - rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group, - cell_group_cfg, - "Secondary Cell Group Config"); - - Info("Applying Cell Group Cfg"); - if (!rrc_ptr->apply_cell_group_cfg(cell_group_cfg)) { - return proc_outcome_t::error; - } - } - - if (sk_counter_r15_present) { - Info("Applying Cell Group Cfg"); - if (!rrc_ptr->configure_sk_counter((uint16_t)sk_counter_r15)) { - return proc_outcome_t::error; - } - } - - if (nr_radio_bearer_cfg1_r15_present) { - cbit_ref bref1(nr_radio_bearer_cfg1_r15.data(), nr_radio_bearer_cfg1_r15.size()); - - err = radio_bearer_cfg.unpack(bref1); - if (err != asn1::SRSASN_SUCCESS) { - Error("Could not unpack radio bearer config."); - return proc_outcome_t::error; - } - - rrc_ptr->log_rrc_message( - "RRC NR Reconfiguration", Rx, nr_radio_bearer_cfg1_r15, radio_bearer_cfg, "Radio Bearer Config R15"); - - Info("Applying Radio Bearer Cfg"); - if (!rrc_ptr->apply_radio_bearer_cfg(radio_bearer_cfg)) { - return proc_outcome_t::error; - } - } - - return proc_outcome_t::success; -} - -proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::react(const bool& config_complete) -{ - if (not config_complete) { - Error("NR reconfiguration failed"); - return proc_outcome_t::error; - } - - // TODO phy ctrl - // in case there are scell to configure, wait for second phy configuration - // if (not rrc_ptr->phy_ctrl->is_config_pending()) { - // return proc_outcome_t::yield; - // } - - Info("Reconfig NR return successful"); - return proc_outcome_t::success; -} - -void rrc_nr::connection_reconf_no_ho_proc::then(const srsran::proc_state_t& result) -{ - if (result.is_success()) { - Info("Finished %s successfully", name()); - srsran::console("RRC NR reconfiguration successful.\n"); - rrc_ptr->rrc_eutra->nr_rrc_con_reconfig_complete(true); - } else { - // 5.3.5.8.2 Inability to comply with RRCReconfiguration - switch (initiator) { - case reconf_initiator_t::mcg_srb1: - rrc_ptr->rrc_eutra->nr_notify_reconfiguration_failure(); - break; - default: - Warning("Reconfiguration failure not implemented for initiator %d", initiator); - break; - } - srsran::console("RRC NR reconfiguration failed.\n"); - Warning("Finished %s with failure", name()); - } - return; -} - } // namespace srsue diff --git a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc new file mode 100644 index 000000000..cfae613e0 --- /dev/null +++ b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc @@ -0,0 +1,160 @@ +/** + * + * \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 "srsue/hdr/stack/rrc_nr/rrc_nr_procedures.h" +#include "srsran/common/standard_streams.h" + +#define Error(fmt, ...) rrc_ptr->logger.error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define Warning(fmt, ...) rrc_ptr->logger.warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define Info(fmt, ...) rrc_ptr->logger.info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) +#define Debug(fmt, ...) rrc_ptr->logger.debug("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) + +using namespace asn1::rrc_nr; +using namespace asn1; +using namespace srsran; + +namespace srsue { + +rrc_nr::connection_reconf_no_ho_proc::connection_reconf_no_ho_proc(rrc_nr* parent_) : rrc_ptr(parent_), initiator(nr) {} + +proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator_t initiator_, + const bool endc_release_and_add_r15, + const bool nr_secondary_cell_group_cfg_r15_present, + const asn1::dyn_octstring nr_secondary_cell_group_cfg_r15, + const bool sk_counter_r15_present, + const uint32_t sk_counter_r15, + const bool nr_radio_bearer_cfg1_r15_present, + const asn1::dyn_octstring nr_radio_bearer_cfg1_r15) +{ + Info("Starting..."); + initiator = initiator_; + + rrc_recfg_s rrc_recfg; + cell_group_cfg_s cell_group_cfg; + radio_bearer_cfg_s radio_bearer_cfg; + asn1::SRSASN_CODE err; + + if (nr_secondary_cell_group_cfg_r15_present) { + cbit_ref bref(nr_secondary_cell_group_cfg_r15.data(), nr_secondary_cell_group_cfg_r15.size()); + err = rrc_recfg.unpack(bref); + if (err != asn1::SRSASN_SUCCESS) { + Error("Could not unpack NR reconfiguration message."); + return proc_outcome_t::error; + } + +#if 0 + rrc_ptr->log_rrc_message( + "RRC NR Reconfiguration", Rx, nr_secondary_cell_group_cfg_r15, rrc_recfg, "NR Secondary Cell Group Cfg R15"); +#endif + if (rrc_recfg.crit_exts.type() != asn1::rrc_nr::rrc_recfg_s::crit_exts_c_::types::rrc_recfg) { + Error("Reconfiguration does not contain Secondary Cell Group Config"); + return proc_outcome_t::error; + } + + if (not rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group_present) { + Error("Reconfiguration does not contain Secondary Cell Group Config"); + return proc_outcome_t::error; + } + + cbit_ref bref0(rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group.data(), + rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group.size()); + + err = cell_group_cfg.unpack(bref0); + if (err != asn1::SRSASN_SUCCESS) { + Error("Could not unpack cell group message message."); + return proc_outcome_t::error; + } + +#if 0 + rrc_ptr->log_rrc_message("RRC NR Reconfiguration", + Rx, + rrc_recfg.crit_exts.rrc_recfg().secondary_cell_group, + cell_group_cfg, + "Secondary Cell Group Config"); +#endif + + Info("Applying Cell Group Cfg"); + if (!rrc_ptr->apply_cell_group_cfg(cell_group_cfg)) { + return proc_outcome_t::error; + } + } + + if (sk_counter_r15_present) { + Info("Applying Cell Group Cfg"); + if (!rrc_ptr->configure_sk_counter((uint16_t)sk_counter_r15)) { + return proc_outcome_t::error; + } + } + + if (nr_radio_bearer_cfg1_r15_present) { + cbit_ref bref1(nr_radio_bearer_cfg1_r15.data(), nr_radio_bearer_cfg1_r15.size()); + + err = radio_bearer_cfg.unpack(bref1); + if (err != asn1::SRSASN_SUCCESS) { + Error("Could not unpack radio bearer config."); + return proc_outcome_t::error; + } + +#if 0 + rrc_ptr->log_rrc_message( + "RRC NR Reconfiguration", Rx, nr_radio_bearer_cfg1_r15, radio_bearer_cfg, "Radio Bearer Config R15"); +#endif + + Info("Applying Radio Bearer Cfg"); + if (!rrc_ptr->apply_radio_bearer_cfg(radio_bearer_cfg)) { + return proc_outcome_t::error; + } + } + + return proc_outcome_t::success; +} + +proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::react(const bool& config_complete) +{ + if (not config_complete) { + Error("NR reconfiguration failed"); + return proc_outcome_t::error; + } + + // TODO phy ctrl + // in case there are scell to configure, wait for second phy configuration + // if (not rrc_ptr->phy_ctrl->is_config_pending()) { + // return proc_outcome_t::yield; + // } + + Info("Reconfig NR return successful"); + return proc_outcome_t::success; +} + +void rrc_nr::connection_reconf_no_ho_proc::then(const srsran::proc_state_t& result) +{ + if (result.is_success()) { + Info("Finished %s successfully", name()); + srsran::console("RRC NR reconfiguration successful.\n"); + rrc_ptr->rrc_eutra->nr_rrc_con_reconfig_complete(true); + } else { + // 5.3.5.8.2 Inability to comply with RRCReconfiguration + switch (initiator) { + case reconf_initiator_t::mcg_srb1: + rrc_ptr->rrc_eutra->nr_notify_reconfiguration_failure(); + break; + default: + Warning("Reconfiguration failure not implemented for initiator %d", initiator); + break; + } + srsran::console("RRC NR reconfiguration failed.\n"); + Warning("Finished %s with failure", name()); + } + return; +} + +} // namespace srsue From 7a64406773d457c9ef0a18efa36514498e063305 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Tue, 26 Oct 2021 17:00:13 +0200 Subject: [PATCH 32/53] Fix nr_phy_test printed metrics Some tables displayed the min value twice instead of min and max. --- test/phy/nr_phy_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index c6eb3ff30..fdf72bb12 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -265,7 +265,7 @@ int main(int argc, char** argv) "EPRE (dB)", metrics.gnb_stack.pucch.epre_db_avg, metrics.gnb_stack.pucch.epre_db_min, - metrics.gnb_stack.pucch.epre_db_min); + metrics.gnb_stack.pucch.epre_db_max); srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n", "RSRP (dB)", metrics.gnb_stack.pucch.rsrp_db_avg, @@ -332,7 +332,7 @@ int main(int argc, char** argv) "EPRE (dB)", metrics.gnb_stack.pusch.epre_db_avg, metrics.gnb_stack.pusch.epre_db_min, - metrics.gnb_stack.pusch.epre_db_min); + metrics.gnb_stack.pusch.epre_db_max); srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n", "RSRP (dB)", metrics.gnb_stack.pusch.rsrp_db_avg, From b44c5931620ecc536c771b84ddd3dd784d4e7954 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Wed, 27 Oct 2021 11:59:07 +0200 Subject: [PATCH 33/53] Improve nr_phy_test user interface The program was not reading configuration files. Also, it exited with a segmentation fault when given the option "--help". Fix a couple of typos in messages. --- test/phy/nr_phy_test.cc | 46 ++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index fdf72bb12..57ef02cf9 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -32,13 +32,16 @@ static double assert_pucch_snr_min = 0.000; test_bench::args_t::args_t(int argc, char** argv) { + std::string config_file = ""; std::string reference_cfg_str = ""; - bpo::options_description options("Test bench options"); + bpo::options_description options; + bpo::options_description options_tb("Test bench options"); bpo::options_description options_gnb_stack("gNb stack and scheduling related options"); bpo::options_description options_gnb_phy("gNb PHY related options"); bpo::options_description options_ue_stack("UE stack options"); bpo::options_description options_ue_phy("UE stack options"); bpo::options_description options_assertion("Test assertions"); + bpo::options_description options_conf_file("Configuration file"); uint16_t rnti = 17921; @@ -46,10 +49,10 @@ test_bench::args_t::args_t(int argc, char** argv) gnb_stack.pusch.slots = "6,7,8,9"; // clang-format off - options.add_options() + options_tb.add_options() ("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") + ("lib.log.level", bpo::value(&phy_lib_log_level)->default_value(phy_lib_log_level), "PHY library log level") ("reference", bpo::value(&reference_cfg_str)->default_value(reference_cfg_str), "Reference PHY configuration arguments") ("dl_channel.awgn_enable", bpo::value(&dl_channel.awgn_enable)->default_value(dl_channel.awgn_enable), "DL Channel AWGN enable / disable") ("dl_channel.awgn_snr", bpo::value(&dl_channel.awgn_snr_dB)->default_value(dl_channel.awgn_snr_dB), "DL Channel AWGN SNR in dB") @@ -105,14 +108,20 @@ test_bench::args_t::args_t(int argc, char** argv) ("assert.pucch.snr.min", bpo::value(&assert_pucch_snr_min)->default_value(assert_pucch_snr_min), "PUCCH DMRS minimum SNR allowed threshold") ; - options.add(options_gnb_stack).add(options_gnb_phy).add(options_ue_stack).add(options_ue_phy).add_options() + options_conf_file.add_options() + ("config_file", bpo::value(&config_file), "Configuration file") + ; + bpo::positional_options_description p; + p.add("config_file", -1); + + options.add(options_tb).add(options_assertion).add(options_gnb_stack).add(options_gnb_phy).add(options_ue_stack).add(options_ue_phy).add(options_conf_file).add_options() ("help", "Show this message") ; // clang-format on bpo::variables_map vm; try { - bpo::store(bpo::command_line_parser(argc, argv).options(options).run(), vm); + bpo::store(bpo::command_line_parser(argc, argv).options(options).positional(p).run(), vm); bpo::notify(vm); // Apply the High Speed Train args to the DL channel as well @@ -127,14 +136,35 @@ test_bench::args_t::args_t(int argc, char** argv) // help option was given or error - print usage and exit if (vm.count("help")) { std::cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << std::endl << std::endl; - std::cout << options << std::endl << std::endl; - return; + std::cout << options_tb << std::endl << options_assertion << std::endl; + std::cout << options_gnb_phy << std::endl << options_gnb_stack << std::endl; + std::cout << options_ue_phy << std::endl << options_ue_stack << std::endl; + exit(0); + } + + // if config file given + if (vm.count("config_file")) { + std::cout << "Reading configuration file " << config_file << "..." << std::endl; + std::ifstream conf(config_file.c_str(), std::ios::in); + if (conf.fail()) { + std::cout << "Failed to read configuration file " << config_file << " - exiting" << std::endl; + exit(1); + } + + // parse config file and handle errors gracefully + try { + bpo::store(bpo::parse_config_file(conf, options), vm); + bpo::notify(vm); + } catch (const boost::program_options::error& e) { + std::cerr << e.what() << std::endl; + exit(1); + } } // Load default reference configuration phy_cfg = srsran::phy_cfg_nr_default_t(srsran::phy_cfg_nr_default_t::reference_cfg_t(reference_cfg_str)); - // Calulate the DL signal power from the number of PRBs + // Calculate the DL signal power from the number of PRBs dl_channel.awgn_signal_power_dBfs = srsran_gnb_dl_get_maximum_signal_power_dBfs(phy_cfg.carrier.nof_prb); // Reverses the Doppler shift for the UL From bae6f13c897e6d62a81df78d1cc4fb7e5152d873 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Fri, 29 Oct 2021 15:52:38 +0200 Subject: [PATCH 34/53] Introduce function srsran_vec_sc_sum_fff This function adds a float scalar to all elements of a float vector. --- lib/include/srsran/phy/utils/vector.h | 3 +++ lib/include/srsran/phy/utils/vector_simd.h | 2 ++ lib/src/phy/utils/vector.c | 6 +++++ lib/src/phy/utils/vector_simd.c | 30 ++++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/lib/include/srsran/phy/utils/vector.h b/lib/include/srsran/phy/utils/vector.h index 08921a711..20023d875 100644 --- a/lib/include/srsran/phy/utils/vector.h +++ b/lib/include/srsran/phy/utils/vector.h @@ -162,6 +162,9 @@ SRSRAN_API void srsran_vec_sub_ccc(const cf_t* x, const cf_t* y, cf_t* z, const SRSRAN_API void srsran_vec_sub_sss(const int16_t* x, const int16_t* y, int16_t* z, const uint32_t len); SRSRAN_API void srsran_vec_sub_bbb(const int8_t* x, const int8_t* y, int8_t* z, const uint32_t len); +/* sum a scalar to all elements of a vector */ +SRSRAN_API void srsran_vec_sc_sum_fff(const float* x, float h, float* z, uint32_t len); + /* scalar product */ SRSRAN_API void srsran_vec_sc_prod_cfc(const cf_t* x, const float h, cf_t* z, const uint32_t len); SRSRAN_API void srsran_vec_sc_prod_fcc(const float* x, const cf_t h, cf_t* z, const uint32_t len); diff --git a/lib/include/srsran/phy/utils/vector_simd.h b/lib/include/srsran/phy/utils/vector_simd.h index 9d24f8df4..02e7c3d8f 100644 --- a/lib/include/srsran/phy/utils/vector_simd.h +++ b/lib/include/srsran/phy/utils/vector_simd.h @@ -39,6 +39,8 @@ SRSRAN_API void srsran_vec_add_fff_simd(const float* x, const float* y, float* z SRSRAN_API void srsran_vec_sub_fff_simd(const float* x, const float* y, float* z, int len); +SRSRAN_API void srsran_vec_sc_sum_fff_simd(const float* x, float h, float* z, int len); + /* SIMD Vector Scalar Product */ SRSRAN_API void srsran_vec_sc_prod_cfc_simd(const cf_t* x, const float h, cf_t* y, const int len); diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index d11182813..6ca8294ad 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -53,6 +53,12 @@ void srsran_vec_sub_bbb(const int8_t* x, const int8_t* y, int8_t* z, const uint3 srsran_vec_sub_bbb_simd(x, y, z, len); } +/* sum a scalar to all elements of a vector */ +void srsran_vec_sc_sum_fff(const float* x, float h, float* z, uint32_t len) +{ + srsran_vec_sc_sum_fff_simd(x, h, z, len); +} + // Noise estimation in chest_dl, interpolation void srsran_vec_sub_ccc(const cf_t* x, const cf_t* y, cf_t* z, const uint32_t len) { diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index e2c6a5622..7002c1aac 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -712,6 +712,36 @@ void srsran_vec_sub_fff_simd(const float* x, const float* y, float* z, const int } } +void srsran_vec_sc_sum_fff_simd(const float* x, float h, float* z, int len) +{ + int i = 0; + +#if SRSRAN_SIMD_F_SIZE + const simd_f_t hh = srsran_simd_f_set1(h); + if (SRSRAN_IS_ALIGNED(x) && SRSRAN_IS_ALIGNED(z)) { + for (; i < len - SRSRAN_SIMD_F_SIZE + 1; i += SRSRAN_SIMD_F_SIZE) { + simd_f_t xx = srsran_simd_f_load(&x[i]); + + simd_f_t zz = srsran_simd_f_add(xx, hh); + + srsran_simd_f_store(&z[i], zz); + } + } else { + for (; i < len - SRSRAN_SIMD_F_SIZE + 1; i += SRSRAN_SIMD_F_SIZE) { + simd_f_t xx = srsran_simd_f_loadu(&x[i]); + + simd_f_t zz = srsran_simd_f_add(xx, hh); + + srsran_simd_f_storeu(&z[i], zz); + } + } +#endif + + for (; i < len; i++) { + z[i] = x[i] + h; + } +} + cf_t srsran_vec_dot_prod_ccc_simd(const cf_t* x, const cf_t* y, const int len) { int i = 0; From 081428aab887b45e5ff562d88f2b5e4e4726fc31 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Tue, 2 Nov 2021 10:05:35 +0100 Subject: [PATCH 35/53] Check for Gaussianity in AWGN unit test Implements the Anderson-Darling test to check whether noise samples are drawn from a Gaussian distribution. --- lib/src/phy/channel/test/awgn_channel_test.c | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) mode change 100644 => 100755 lib/src/phy/channel/test/awgn_channel_test.c diff --git a/lib/src/phy/channel/test/awgn_channel_test.c b/lib/src/phy/channel/test/awgn_channel_test.c old mode 100644 new mode 100755 index 36fdf3747..88d114067 --- a/lib/src/phy/channel/test/awgn_channel_test.c +++ b/lib/src/phy/channel/test/awgn_channel_test.c @@ -68,11 +68,68 @@ static int parse_args(int argc, char** argv) return SRSRAN_SUCCESS; } +static int compare_floats(const void* a, const void* b) +{ + float arg1 = *(const float*) a; + float arg2 = *(const float*) b; + + if (arg1 < arg2) return -1; + if (arg1 > arg2) return 1; + return 0; +} + +/* + * Checks for Gaussianity with the Anderson--Darling test: if the returned statistic A2 is larger than 1 + * (and if the number of samples is larger than 100), then the Gaussianity hypothesis is rejected with a significance + * level of approximately 1% (see https://en.wikipedia.org/wiki/Anderson%E2%80%93Darling_test). + * + * x points to the vector of samples (real values and imaginary values) + * half_length is the number of complex samples + * y is a pointer to a helper vector used for temporary computations +*/ +static float anderson(const float* x, uint32_t half_length, float* y) +{ +#define SQRT1_2 ((float)M_SQRT1_2) +#define CDF(a) ((1 + erff((a)*SQRT1_2)) * .5) + + uint32_t length = 2 * half_length; + float length_f = (float)length; + + // estimate mean and variance (the test works better with estimated than nominal ones) + float mean = srsran_vec_acc_ff(x, length); + mean /= length_f; + + srsran_vec_sc_sum_fff(x, -mean, y, length); + float variance = srsran_vec_dot_prod_fff(y, y, length); + variance /= length_f - 1; + + // standardize samples + srsran_vec_sc_prod_fff(y, 1 / sqrtf(variance), y, length); + + // sort standardized samples + qsort(y, length, sizeof(float), compare_floats); + + // compute Anderson--Darling statistic + float cdf1, cdf2; + float a2 = 0; + for (uint32_t ii = 0; ii < nof_samples; ii++) { + cdf1 = CDF(y[ii]); + cdf2 = CDF(y[length - ii - 1]); + a2 += (2 * ii + 1) * (logf(cdf1) + log1pf(-cdf2)) + + (2 * (length - ii) - 1) * (logf(cdf2) + log1pf(-cdf1)); + } + a2 = -length_f - a2 / length_f; + a2 = a2 * (1 + (4 - 25 / length_f) / length_f); + + return a2; +} + int main(int argc, char** argv) { int ret = SRSRAN_SUCCESS; cf_t* input_buffer = NULL; cf_t* output_buffer = NULL; + float* help_buffer = NULL; uint64_t count_samples = 0; uint64_t count_us = 0; @@ -89,6 +146,7 @@ int main(int argc, char** argv) // Initialise buffers input_buffer = srsran_vec_cf_malloc(nof_samples); output_buffer = srsran_vec_cf_malloc(nof_samples); + help_buffer = srsran_vec_f_malloc(2 * nof_samples); if (!input_buffer || !output_buffer) { ERROR("Error: Allocating memory"); @@ -153,6 +211,13 @@ int main(int argc, char** argv) ret = SRSRAN_ERROR; } + // Check for Gaussianity + float a2 = anderson((float*)output_buffer, nof_samples, help_buffer); + if ((nof_samples > 100 && a2 > 1) || !isfinite(a2)) { + printf("-- failed: A2 = %f > 1: not Gaussian\n", a2); + ret = SRSRAN_ERROR; + } + #ifdef ENABLE_GUI plot_scatter_setNewData(&plot_scatter, output_buffer, nof_samples); From 32c4da8db07679796298aa3ad3f0cccd96cf0c6f Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Tue, 2 Nov 2021 10:20:38 +0100 Subject: [PATCH 36/53] Fix typos --- lib/include/srsran/interfaces/phy_common_interface.h | 2 +- srsenb/src/phy/nr/slot_worker.cc | 2 +- test/phy/test_bench.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/include/srsran/interfaces/phy_common_interface.h b/lib/include/srsran/interfaces/phy_common_interface.h index 18f9e699f..711bf4f22 100644 --- a/lib/include/srsran/interfaces/phy_common_interface.h +++ b/lib/include/srsran/interfaces/phy_common_interface.h @@ -19,7 +19,7 @@ namespace srsran { /** - * @brief Descibes a physical layer common interface + * @brief Describes a physical layer common interface */ class phy_common_interface { diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 8bfc578be..6ceb3e43e 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -291,7 +291,7 @@ bool slot_worker::work_dl() } if (srsran_gnb_dl_base_zero(&gnb_dl) < SRSRAN_SUCCESS) { - logger.error("Error zeroeing RE grid"); + logger.error("Error zeroing RE grid"); return false; } diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index a73806f39..c373a4446 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -159,7 +159,7 @@ public: // Run the UL channel simulator ul_channel.run(gnb_rx_buffers.data(), gnb_rx_buffers.data(), (uint32_t)sf_sz, gnb_time.get(0)); - // Set gnb context + // Set gNb context srsran::phy_common_interface::worker_context_t gnb_context; gnb_context.sf_idx = slot_idx; gnb_context.worker_ptr = gnb_worker; @@ -189,7 +189,7 @@ public: // Run the DL channel simulator dl_channel.run(ue_rx_buffers.data(), ue_rx_buffers.data(), (uint32_t)sf_sz, ue_time.get(0)); - // Set gnb context + // Set UE context srsran::phy_common_interface::worker_context_t ue_context; ue_context.sf_idx = slot_idx; ue_context.worker_ptr = ue_worker; From f95c654aba177961a980551db48cec9693b0d700 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Tue, 2 Nov 2021 11:44:03 +0100 Subject: [PATCH 37/53] Minor change Forgot to check for unsuccessful malloc. --- lib/src/phy/channel/test/awgn_channel_test.c | 25 ++++++++++---------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/src/phy/channel/test/awgn_channel_test.c b/lib/src/phy/channel/test/awgn_channel_test.c index 88d114067..e06c65231 100755 --- a/lib/src/phy/channel/test/awgn_channel_test.c +++ b/lib/src/phy/channel/test/awgn_channel_test.c @@ -70,11 +70,13 @@ static int parse_args(int argc, char** argv) static int compare_floats(const void* a, const void* b) { - float arg1 = *(const float*) a; - float arg2 = *(const float*) b; + float arg1 = *(const float*)a; + float arg2 = *(const float*)b; - if (arg1 < arg2) return -1; - if (arg1 > arg2) return 1; + if (arg1 < arg2) + return -1; + if (arg1 > arg2) + return 1; return 0; } @@ -86,16 +88,16 @@ static int compare_floats(const void* a, const void* b) * x points to the vector of samples (real values and imaginary values) * half_length is the number of complex samples * y is a pointer to a helper vector used for temporary computations -*/ + */ static float anderson(const float* x, uint32_t half_length, float* y) { #define SQRT1_2 ((float)M_SQRT1_2) #define CDF(a) ((1 + erff((a)*SQRT1_2)) * .5) - uint32_t length = 2 * half_length; - float length_f = (float)length; + uint32_t length = 2 * half_length; + float length_f = (float)length; - // estimate mean and variance (the test works better with estimated than nominal ones) + // estimate mean and variance (the test works better with estimated values than with nominal ones) float mean = srsran_vec_acc_ff(x, length); mean /= length_f; @@ -115,8 +117,7 @@ static float anderson(const float* x, uint32_t half_length, float* y) for (uint32_t ii = 0; ii < nof_samples; ii++) { cdf1 = CDF(y[ii]); cdf2 = CDF(y[length - ii - 1]); - a2 += (2 * ii + 1) * (logf(cdf1) + log1pf(-cdf2)) + - (2 * (length - ii) - 1) * (logf(cdf2) + log1pf(-cdf1)); + a2 += (2 * ii + 1) * (logf(cdf1) + log1pf(-cdf2)) + (2 * (length - ii) - 1) * (logf(cdf2) + log1pf(-cdf1)); } a2 = -length_f - a2 / length_f; a2 = a2 * (1 + (4 - 25 / length_f) / length_f); @@ -146,9 +147,9 @@ int main(int argc, char** argv) // Initialise buffers input_buffer = srsran_vec_cf_malloc(nof_samples); output_buffer = srsran_vec_cf_malloc(nof_samples); - help_buffer = srsran_vec_f_malloc(2 * nof_samples); + help_buffer = srsran_vec_f_malloc(2 * nof_samples); - if (!input_buffer || !output_buffer) { + if (!input_buffer || !output_buffer || !help_buffer) { ERROR("Error: Allocating memory"); ret = SRSRAN_ERROR; goto clean_exit; From 7d8c519865ec15fa80f910535ea43b1c1505d0cf Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Thu, 4 Nov 2021 11:15:27 +0100 Subject: [PATCH 38/53] Restore proper file mode The file had been mistakenly given executable permissions. --- lib/src/phy/channel/test/awgn_channel_test.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 lib/src/phy/channel/test/awgn_channel_test.c diff --git a/lib/src/phy/channel/test/awgn_channel_test.c b/lib/src/phy/channel/test/awgn_channel_test.c old mode 100755 new mode 100644 From a4b86e5a0a236567e0de3b794a587a1e738176a4 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Thu, 4 Nov 2021 15:29:44 +0100 Subject: [PATCH 39/53] Modify PUSCH power normalization The PUSCH signal was normalized to fix the maximum amplitude instead of the transmitted power. --- lib/src/phy/ue/ue_ul_nr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index a93a2e5a2..16f8a15d2 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -133,12 +133,9 @@ int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q, // Generate signal srsran_ofdm_tx_sf(&q->ifft); - // Normalise to peak - uint32_t max_idx = srsran_vec_max_abs_ci(q->ifft.cfg.out_buffer, q->ifft.sf_sz); - float max_peak = cabsf(q->ifft.cfg.out_buffer[max_idx]); - if (isnormal(max_peak)) { - srsran_vec_sc_prod_cfc(q->ifft.cfg.out_buffer, 0.99f / max_peak, q->ifft.cfg.out_buffer, q->ifft.sf_sz); - } + // Scale iFFT output to compensate for iFFT amplification (due to FFTW implementation). + float scaling = 1 / sqrtf(q->ifft.cfg.symbol_sz); + srsran_vec_sc_prod_cfc(q->ifft.cfg.out_buffer, scaling, q->ifft.cfg.out_buffer, q->ifft.sf_sz); // Apply frequency offset if (isnormal(q->freq_offset_hz)) { From 7752feb3c2d730f3ac4e1b31bbb8bd1f574271ed Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Mon, 8 Nov 2021 16:43:04 +0100 Subject: [PATCH 40/53] Fix typos --- lib/src/phy/dft/ofdm.c | 6 +++--- lib/src/phy/gnb/gnb_dl.c | 2 +- lib/src/phy/phch/pusch_nr.c | 13 ++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index 41469e50a..1b1856873 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -72,7 +72,7 @@ static int ofdm_init_mbsfn_(srsran_ofdm_t* q, srsran_ofdm_cfg_t* cfg, srsran_dft if (q->fft_plan.size) { // Replan if it was initialised previously if (srsran_dft_replan(&q->fft_plan, q->cfg.symbol_sz)) { - ERROR("Reeplaning DFT plan"); + ERROR("Replanning DFT plan"); return SRSRAN_ERROR; } } else { @@ -85,7 +85,7 @@ static int ofdm_init_mbsfn_(srsran_ofdm_t* q, srsran_ofdm_cfg_t* cfg, srsran_dft // Reallocate temporal buffer only if the new number of resource blocks is bigger than initial if (q->cfg.nof_prb > q->max_prb) { - // Free before reallocating if allocted + // Free before reallocating if allocated if (q->tmp) { free(q->tmp); free(q->shift_buffer); @@ -553,7 +553,7 @@ void srsran_ofdm_rx_sf_ng(srsran_ofdm_t* q, cf_t* input, cf_t* output) } /* Transforms input OFDM symbols into output samples. - * Performs FFT on a each symbol and adds CP. + * Performs the FFT on each symbol and adds CP. */ static void ofdm_tx_slot(srsran_ofdm_t* q, int slot_in_sf) { diff --git a/lib/src/phy/gnb/gnb_dl.c b/lib/src/phy/gnb/gnb_dl.c index 0c025fc45..a69e7291e 100644 --- a/lib/src/phy/gnb/gnb_dl.c +++ b/lib/src/phy/gnb/gnb_dl.c @@ -61,7 +61,7 @@ int srsran_gnb_dl_init(srsran_gnb_dl_t* q, cf_t* output[SRSRAN_MAX_PORTS], const return SRSRAN_ERROR; } - // Check symbol size is vlid + // Check symbol size is valid int symbol_sz = srsran_symbol_sz_from_srate(args->srate_hz, args->scs); if (symbol_sz <= 0) { ERROR("Error calculating symbol size from sampling rate of %.2f MHz and subcarrier spacing %s", diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index e4b1bda7b..6ffbb3e54 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -725,7 +725,7 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q, return SRSRAN_ERROR; } - // 7.3.1.1 and 7.3.1.2 + // 6.3.1.1 and 6.3.1.2 uint32_t nof_cw = 0; for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { nof_cw += grant->tb[tb].enabled ? 1 : 0; @@ -737,20 +737,23 @@ int srsran_pusch_nr_encode(srsran_pusch_nr_t* q, } } - // 7.3.1.3 Layer mapping + // 6.3.1.3 Layer mapping cf_t** x = q->d; if (grant->nof_layers > 1) { x = q->x; srsran_layermap_nr(q->d, nof_cw, x, grant->nof_layers, grant->nof_layers); } - // 7.3.1.4 Antenna port mapping + // 6.3.1.4 Transform precoding // ... Not implemented - // 7.3.1.5 Mapping to virtual resource blocks + // 6.3.1.5 Precoding // ... Not implemented - // 7.3.1.6 Mapping from virtual to physical resource blocks + // 6.3.1.6 Mapping to virtual resource blocks + // ... Not implemented + + // 6.3.1.7 Mapping from virtual to physical resource blocks int n = pusch_nr_put(q, cfg, grant, x[0], sf_symbols[0]); if (n < SRSRAN_SUCCESS) { ERROR("Putting NR PUSCH resources"); From 864cb14eec8962769a3dad1c7b988f90fb21e624 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Thu, 18 Nov 2021 15:08:33 +0100 Subject: [PATCH 41/53] Fix some clang-tidy warnings --- lib/src/phy/channel/test/awgn_channel_test.c | 13 ++++++++----- test/phy/nr_phy_test.cc | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/src/phy/channel/test/awgn_channel_test.c b/lib/src/phy/channel/test/awgn_channel_test.c index e06c65231..28655dafa 100644 --- a/lib/src/phy/channel/test/awgn_channel_test.c +++ b/lib/src/phy/channel/test/awgn_channel_test.c @@ -73,10 +73,12 @@ static int compare_floats(const void* a, const void* b) float arg1 = *(const float*)a; float arg2 = *(const float*)b; - if (arg1 < arg2) + if (arg1 < arg2) { return -1; - if (arg1 > arg2) + } + if (arg1 > arg2) { return 1; + } return 0; } @@ -112,12 +114,13 @@ static float anderson(const float* x, uint32_t half_length, float* y) qsort(y, length, sizeof(float), compare_floats); // compute Anderson--Darling statistic - float cdf1, cdf2; - float a2 = 0; + float cdf1 = NAN; + float cdf2 = NAN; + float a2 = 0; for (uint32_t ii = 0; ii < nof_samples; ii++) { cdf1 = CDF(y[ii]); cdf2 = CDF(y[length - ii - 1]); - a2 += (2 * ii + 1) * (logf(cdf1) + log1pf(-cdf2)) + (2 * (length - ii) - 1) * (logf(cdf2) + log1pf(-cdf1)); + a2 += (2.F * ii + 1) * (logf(cdf1) + log1pf(-cdf2)) + (2.F * (length - ii) - 1) * (logf(cdf2) + log1pf(-cdf1)); } a2 = -length_f - a2 / length_f; a2 = a2 * (1 + (4 - 25 / length_f) / length_f); diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 57ef02cf9..bbc94996b 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -32,8 +32,8 @@ static double assert_pucch_snr_min = 0.000; test_bench::args_t::args_t(int argc, char** argv) { - std::string config_file = ""; - std::string reference_cfg_str = ""; + std::string config_file; + std::string reference_cfg_str; bpo::options_description options; bpo::options_description options_tb("Test bench options"); bpo::options_description options_gnb_stack("gNb stack and scheduling related options"); @@ -143,7 +143,7 @@ test_bench::args_t::args_t(int argc, char** argv) } // if config file given - if (vm.count("config_file")) { + if (vm.count("config_file") != 0U) { std::cout << "Reading configuration file " << config_file << "..." << std::endl; std::ifstream conf(config_file.c_str(), std::ios::in); if (conf.fail()) { From cfa614226e64cb45a075d1d0f4761ea3903395ea Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Thu, 18 Nov 2021 15:13:06 +0100 Subject: [PATCH 42/53] Fix misnamed variable The same variable was used to store two different sets of compiler flags. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f866ba19b..ce3f15910 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -399,8 +399,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") if(FORCE_32BIT) - ADD_C_COMPILER_FLAG_IF_AVAILABLE("-m32" HAVE_WNO_UNUSED_BUT_SET_VARIABLE) - ADD_CXX_COMPILER_FLAG_IF_AVAILABLE("-m32" HAVE_WNO_UNUSED_BUT_SET_VARIABLE) + ADD_C_COMPILER_FLAG_IF_AVAILABLE("-m32" HAVE_M32) + ADD_CXX_COMPILER_FLAG_IF_AVAILABLE("-m32" HAVE_M32) set(CMAKE_SHARED_LINKER_FLAGS "-m32") endif(FORCE_32BIT) From d1ddd3da4d9bb491158e8b5b6e93068c0ce100da Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 29 Nov 2021 16:00:57 +0000 Subject: [PATCH 43/53] gnb,rrc: make plmn and cell id configurable in SIB1 --- srsenb/src/enb_cfg_parser.cc | 3 +++ srsgnb/hdr/stack/rrc/rrc_nr_config.h | 3 +++ srsgnb/src/stack/rrc/cell_asn1_config.cc | 6 ++---- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 9 +++++++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index e9a65cb1e..99e06e83a 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1541,6 +1541,9 @@ int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_nr_cfg_, phy_cfg_t* cfg.phy_cell.pdsch.rs_power = phy_cfg_->pdsch_cnfg.ref_sig_pwr; cfg.phy_cell.pdsch.p_b = phy_cfg_->pdsch_cnfg.p_b; } + rrc_nr_cfg_->enb_id = args_->enb.enb_id; + rrc_nr_cfg_->mcc = args_->stack.s1ap.mcc; + rrc_nr_cfg_->mnc = args_->stack.s1ap.mnc; // Derive cross-dependent cell params if (set_derived_nr_rrc_params(*rrc_nr_cfg_) != SRSRAN_SUCCESS) { diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_config.h b/srsgnb/hdr/stack/rrc/rrc_nr_config.h index 3e289ac4c..5a405f561 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_config.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_config.h @@ -52,6 +52,9 @@ struct rrc_nr_cfg_t { rrc_cfg_cqi_t cqi_cfg; rrc_cell_list_nr_t cell_list; uint32_t inactivity_timeout_ms = 100000; + uint32_t enb_id; + uint16_t mcc; + uint16_t mnc; bool is_standalone; std::array nea_preference_list; diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 12aeb1bee..a1f98f3bd 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -1060,8 +1060,6 @@ void fill_serv_cell_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, serving_ce int fill_sib1_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1::rrc_nr::sib1_s& sib1) { - std::string plmn_str = "00101"; - uint32_t cell_id = 0x19B01; const rrc_cell_cfg_nr_t& cell_cfg = cfg.cell_list[cc]; sib1.cell_sel_info_present = true; @@ -1072,11 +1070,11 @@ int fill_sib1_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1::rrc_nr::s sib1.cell_access_related_info.plmn_id_list.resize(1); sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list.resize(1); srsran::plmn_id_t plmn; - plmn.from_string(plmn_str); + plmn.from_number(cfg.mcc, cfg.mnc); srsran::to_asn1(&sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list[0], plmn); sib1.cell_access_related_info.plmn_id_list[0].tac_present = true; sib1.cell_access_related_info.plmn_id_list[0].tac.from_number(cell_cfg.tac); - sib1.cell_access_related_info.plmn_id_list[0].cell_id.from_number(cell_id); + sib1.cell_access_related_info.plmn_id_list[0].cell_id.from_number((cfg.enb_id << 8U) + cell_cfg.phy_cell.cell_id); sib1.cell_access_related_info.plmn_id_list[0].cell_reserved_for_oper.value = plmn_id_info_s::cell_reserved_for_oper_opts::not_reserved; diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 5d757517c..313cb40f1 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -58,6 +58,9 @@ void test_sib_generation() rrc_cfg_nr.cell_list[0].phy_cell.carrier.nof_prb = 52; rrc_cfg_nr.cell_list[0].duplex_mode = SRSRAN_DUPLEX_MODE_FDD; rrc_cfg_nr.is_standalone = true; + rrc_cfg_nr.enb_id = 0x19B; + srsran::string_to_mcc("001", &rrc_cfg_nr.mcc); + srsran::string_to_mnc("01", &rrc_cfg_nr.mnc); set_derived_nr_cell_params(rrc_cfg_nr.is_standalone, rrc_cfg_nr.cell_list[0]); srsran_assert(check_rrc_nr_cfg_valid(rrc_cfg_nr) == SRSRAN_SUCCESS, "Invalid RRC NR configuration"); @@ -111,6 +114,9 @@ int test_rrc_setup() rrc_cfg_nr.cell_list[0].band = 78; rrc_cfg_nr.cell_list[0].phy_cell.carrier.nof_prb = 52; rrc_cfg_nr.is_standalone = false; + rrc_cfg_nr.enb_id = 0x19B; + srsran::string_to_mcc("001", &rrc_cfg_nr.mcc); + srsran::string_to_mnc("01", &rrc_cfg_nr.mnc); set_derived_nr_cell_params(rrc_cfg_nr.is_standalone, rrc_cfg_nr.cell_list[0]); srsran_assert(check_rrc_nr_cfg_valid(rrc_cfg_nr) == SRSRAN_SUCCESS, "Invalid RRC NR configuration"); TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, bearer_mapper, nullptr) == @@ -151,6 +157,9 @@ void test_rrc_sa_connection() rrc_cfg_nr.cell_list[0].phy_cell.carrier.nof_prb = 52; rrc_cfg_nr.cell_list[0].duplex_mode = SRSRAN_DUPLEX_MODE_FDD; rrc_cfg_nr.is_standalone = true; + rrc_cfg_nr.enb_id = 0x19B; + srsran::string_to_mcc("001", &rrc_cfg_nr.mcc); + srsran::string_to_mnc("01", &rrc_cfg_nr.mnc); set_derived_nr_cell_params(rrc_cfg_nr.is_standalone, rrc_cfg_nr.cell_list[0]); srsran_assert(check_rrc_nr_cfg_valid(rrc_cfg_nr) == SRSRAN_SUCCESS, "Invalid RRC NR configuration"); From f30059004b18d51491102cdd76a96bd3b51f611f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Dec 2021 12:10:46 +0100 Subject: [PATCH 44/53] gtpu: remove warning when GTPU_EXT_HEADER_PDU_SESSION_CONTAINER is received --- lib/src/gtpu/gtpu.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/gtpu/gtpu.cc b/lib/src/gtpu/gtpu.cc index 9dda8ee93..e7b7c6ca9 100644 --- a/lib/src/gtpu/gtpu.cc +++ b/lib/src/gtpu/gtpu.cc @@ -126,7 +126,6 @@ bool gtpu_read_ext_header(srsran::byte_buffer_t* pdu, 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: From 2a12e91594ac5e412b160bd434c738dc3c5aad5d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Dec 2021 12:11:09 +0100 Subject: [PATCH 45/53] enb,metrics_stdout: fix printing in SA mode --- srsenb/src/metrics_stdout.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/metrics_stdout.cc b/srsenb/src/metrics_stdout.cc index 64557377c..f94c2ffc2 100644 --- a/srsenb/src/metrics_stdout.cc +++ b/srsenb/src/metrics_stdout.cc @@ -179,7 +179,7 @@ void metrics_stdout::set_metrics(const enb_metrics_t& metrics, const uint32_t pe fmt::print("RF status: O={}, U={}, L={}\n", metrics.rf.rf_o, metrics.rf.rf_u, metrics.rf.rf_l); } - if (metrics.stack.rrc.ues.size() == 0) { + if (metrics.stack.rrc.ues.size() == 0 && metrics.nr_stack.mac.ues.size() == 0) { return; } From 118a2a3bc2d7db84fe40bfd3c00943eb071b1b75 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Dec 2021 14:39:36 +0100 Subject: [PATCH 46/53] awgn_channel_test: disable strict check for Gaussianity this seems to cause issues with some platforms/compilers. needs to be dissable until proper RNG is in place --- lib/src/phy/channel/test/awgn_channel_test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/channel/test/awgn_channel_test.c b/lib/src/phy/channel/test/awgn_channel_test.c index 28655dafa..77216908f 100644 --- a/lib/src/phy/channel/test/awgn_channel_test.c +++ b/lib/src/phy/channel/test/awgn_channel_test.c @@ -219,7 +219,8 @@ int main(int argc, char** argv) float a2 = anderson((float*)output_buffer, nof_samples, help_buffer); if ((nof_samples > 100 && a2 > 1) || !isfinite(a2)) { printf("-- failed: A2 = %f > 1: not Gaussian\n", a2); - ret = SRSRAN_ERROR; + // TODO: use proper RNG with gaussian behaviour + // ret = SRSRAN_ERROR; } #ifdef ENABLE_GUI From c2fd340cd4e7440508ccfedde38867cb32525f37 Mon Sep 17 00:00:00 2001 From: AlaiaL <52231716+AlaiaL@users.noreply.github.com> Date: Wed, 1 Dec 2021 17:37:10 +0100 Subject: [PATCH 47/53] build: building srsran_rf as shared library too * Created shared library for srsran_rf * Using an object to build static and shared library. * Remove the instalation of the srsran_rf library * Renaming library to srsran_rf_shared so the name becames clearer --- lib/src/phy/rf/CMakeLists.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/rf/CMakeLists.txt b/lib/src/phy/rf/CMakeLists.txt index ba67085ea..cd50b85ff 100644 --- a/lib/src/phy/rf/CMakeLists.txt +++ b/lib/src/phy/rf/CMakeLists.txt @@ -59,28 +59,40 @@ if(RF_FOUND) list(APPEND SOURCES_RF rf_zmq_imp.c rf_zmq_imp_tx.c rf_zmq_imp_rx.c) endif (ZEROMQ_FOUND) - add_library(srsran_rf STATIC ${SOURCES_RF}) + add_library(srsran_rf_object OBJECT ${SOURCES_RF}) + set_property(TARGET srsran_rf_object PROPERTY POSITION_INDEPENDENT_CODE 1) + + add_library(srsran_rf STATIC $) + add_library(srsran_rf_shared SHARED $) + target_link_libraries(srsran_rf srsran_rf_utils srsran_phy) set_target_properties(srsran_rf PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION}) + target_link_libraries(srsran_rf_shared srsran_rf_utils srsran_phy) + set_target_properties(srsran_rf_shared PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION}) if (UHD_FOUND) target_link_libraries(srsran_rf ${UHD_LIBRARIES} ${Boost_LIBRARIES}) # Ubuntu 18.04 requires 'system' from Boost_LIBRARIES + target_link_libraries(srsran_rf_shared ${UHD_LIBRARIES} ${Boost_LIBRARIES}) endif (UHD_FOUND) if (BLADERF_FOUND) target_link_libraries(srsran_rf ${BLADERF_LIBRARIES}) + target_link_libraries(srsran_rf_shared ${BLADERF_LIBRARIES}) endif (BLADERF_FOUND) if (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR) target_link_libraries(srsran_rf ${SOAPYSDR_LIBRARIES}) + target_link_libraries(srsran_rf_shared ${SOAPYSDR_LIBRARIES}) endif (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR) if(SKIQ_FOUND) target_link_libraries(srsran_rf ${SKIQ_LIBRARIES} rt) + target_link_libraries(srsran_rf_shared ${SKIQ_LIBRARIES} rt) endif(SKIQ_FOUND) if (ZEROMQ_FOUND) target_link_libraries(srsran_rf ${ZEROMQ_LIBRARIES}) + target_link_libraries(srsran_rf_shared ${ZEROMQ_LIBRARIES}) add_executable(rf_zmq_test rf_zmq_test.c) target_link_libraries(rf_zmq_test srsran_rf) #add_test(rf_zmq_test rf_zmq_test) From a27562cb5809c7c3648869df14abdf97a682245b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Dec 2021 15:18:44 +0100 Subject: [PATCH 48/53] gnb_stack_nr: init loglevel of common log channel to avoid netsocket stuff to spam logs with: 2021-12-01T14:16:58.946080 [COMN ] [D] [ 0] Setting RTO_INFO options on SCTP socket. Association 0, Initial RTO 3000, Minimum RTO 1000, Maximum RTO 6000 2021-12-01T14:16:58.946084 [COMN ] [D] [ 0] Setting SCTP_INITMSG options on SCTP socket. Max attempts 3, Max init attempts timeout 5000 2021-12-01T14:16:58.946109 [COMN ] [D] [ 0] Successfully bound to address 10.8.1.22:0 2021-12-01T14:16:58.998936 [COMN ] [D] [ 0] RxSockets: socket fd=7 has been registered. 2021-12-01T14:16:58.999049 [COMN ] [D] [ 0] Successfully bound to address 10.8.1.22:2152 2021-12-01T14:16:58.999056 [COMN ] [D] [ 0] RxSockets: socket fd=8 has been registered. --- srsgnb/src/stack/gnb_stack_nr.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsgnb/src/stack/gnb_stack_nr.cc b/srsgnb/src/stack/gnb_stack_nr.cc index 811c19f1d..6aee7373b 100644 --- a/srsgnb/src/stack/gnb_stack_nr.cc +++ b/srsgnb/src/stack/gnb_stack_nr.cc @@ -69,6 +69,7 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); ngap_logger.set_level(srslog::str_to_basic_level(args.log.s1ap_level)); gtpu_logger.set_level(srslog::str_to_basic_level(args.log.gtpu_level)); + srslog::fetch_basic_logger("COMN", false).set_level(srslog::str_to_basic_level(args.log.stack_level)); mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); @@ -77,6 +78,7 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); ngap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit); gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit); + srslog::fetch_basic_logger("COMN", false).set_hex_dump_max_size(args.log.stack_hex_limit); if (x2_ == nullptr) { // SA mode From 091877fd2a22fdc9c4fdcb3d6935cc634e25a812 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 1 Dec 2021 15:20:26 +0100 Subject: [PATCH 49/53] gnb,rrc: inverse order of configuring lower layers when establishing bearer start with lower layers first, so MAC, RLC then PDCP. Since PDCP requires that the LCID is already registered at RLC to make config checks. It checks for RLC mode (UM) in this case causing log entries like: 2021-12-01T13:47:40.453641 [RLC-NR ] [W] LCID 4 doesn't exist. --- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 2ab0007b4..00d2441a3 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1073,14 +1073,14 @@ void rrc_nr::ue::send_rrc_reconfiguration() } // Update lower layers - // add PDCP bearers - update_pdcp_bearers(ies.radio_bearer_cfg, master_cell_group); + // add MAC bearers + update_mac(master_cell_group, false); // add RLC bearers update_rlc_bearers(master_cell_group); - // add MAC bearers - update_mac(master_cell_group, false); + // add PDCP bearers + update_pdcp_bearers(ies.radio_bearer_cfg, master_cell_group); } if (nas_pdu_queue.size() > 0) { From 11b4a572a0e4188dd88b95add4f2be44b40d5710 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 1 Dec 2021 16:40:43 +0000 Subject: [PATCH 50/53] nr,gnb,rrc&ngap: implementation of NGAP UE Context Release Request and RRC Release for the case RRC_CONNECTED->RRC_IDLE --- .../srsran/interfaces/gnb_ngap_interfaces.h | 12 +++--- .../srsran/interfaces/gnb_rrc_nr_interfaces.h | 9 +++-- .../hdr/stack/common/test/dummy_nr_classes.h | 2 +- srsgnb/hdr/stack/ngap/ngap.h | 21 ++++++----- srsgnb/hdr/stack/ngap/ngap_ue.h | 2 + .../hdr/stack/ngap/ngap_ue_bearer_manager.h | 2 + srsgnb/hdr/stack/rrc/rrc_nr.h | 1 + srsgnb/hdr/stack/rrc/rrc_nr_ue.h | 2 +- srsgnb/src/stack/ngap/ngap.cc | 17 +++++++++ srsgnb/src/stack/ngap/ngap_ue.cc | 37 +++++++++++++++++++ srsgnb/src/stack/ngap/ngap_ue_proc.cc | 3 +- srsgnb/src/stack/ngap/test/ngap_test.cc | 1 + srsgnb/src/stack/rrc/rrc_nr.cc | 10 +++++ srsgnb/src/stack/rrc/rrc_nr_ue.cc | 28 ++++++++++---- 14 files changed, 117 insertions(+), 30 deletions(-) diff --git a/lib/include/srsran/interfaces/gnb_ngap_interfaces.h b/lib/include/srsran/interfaces/gnb_ngap_interfaces.h index 70472a69b..eaec4236d 100644 --- a/lib/include/srsran/interfaces/gnb_ngap_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_ngap_interfaces.h @@ -44,12 +44,12 @@ public: srsran::const_byte_span pdu, uint32_t m_tmsi) = 0; - virtual void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) = 0; - virtual bool user_exists(uint16_t rnti) = 0; - virtual void user_mod(uint16_t old_rnti, uint16_t new_rnti) = 0; - virtual bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) = 0; - virtual bool is_amf_connected() = 0; - virtual void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) = 0; + virtual void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) = 0; + virtual bool user_exists(uint16_t rnti) = 0; + virtual void user_mod(uint16_t old_rnti, uint16_t new_rnti) = 0; + virtual void user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) = 0; + virtual bool is_amf_connected() = 0; + virtual void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) = 0; }; } // namespace srsenb diff --git a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h index f2b8867f6..54b25b538 100644 --- a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h @@ -26,10 +26,11 @@ public: 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, srsran::unique_byte_buffer_t nas_pdu) = 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 int release_bearers(uint16_t rnti) = 0; - virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0; + 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 int release_bearers(uint16_t rnti) = 0; + virtual void release_user(uint16_t rnti) = 0; + virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0; }; } // namespace srsenb diff --git a/srsgnb/hdr/stack/common/test/dummy_nr_classes.h b/srsgnb/hdr/stack/common/test/dummy_nr_classes.h index eb0339225..1fac72327 100644 --- a/srsgnb/hdr/stack/common/test/dummy_nr_classes.h +++ b/srsgnb/hdr/stack/common/test/dummy_nr_classes.h @@ -36,7 +36,7 @@ class ngap_dummy : public ngap_interface_rrc_nr void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) {} bool user_exists(uint16_t rnti) { return true; } void user_mod(uint16_t old_rnti, uint16_t new_rnti) {} - bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) { return true; } + void user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) {} bool is_amf_connected() { return true; } void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) {} }; diff --git a/srsgnb/hdr/stack/ngap/ngap.h b/srsgnb/hdr/stack/ngap/ngap.h index 27c900781..86b3da74a 100644 --- a/srsgnb/hdr/stack/ngap/ngap.h +++ b/srsgnb/hdr/stack/ngap/ngap.h @@ -51,27 +51,30 @@ public: void initial_ue(uint16_t rnti, uint32_t gnb_cc_idx, asn1::ngap_nr::rrcestablishment_cause_e cause, - srsran::const_byte_span pdu); + srsran::const_byte_span pdu) override; void initial_ue(uint16_t rnti, uint32_t gnb_cc_idx, asn1::ngap_nr::rrcestablishment_cause_e cause, srsran::const_byte_span pdu, - uint32_t s_tmsi); + uint32_t s_tmsi) override; - void write_pdu(uint16_t rnti, srsran::const_byte_span pdu); - bool user_exists(uint16_t rnti) { return true; }; - void user_mod(uint16_t old_rnti, uint16_t new_rnti){}; - bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) { return true; }; - bool is_amf_connected(); + void write_pdu(uint16_t rnti, srsran::const_byte_span pdu) override; + bool user_exists(uint16_t rnti) override { return true; }; + void user_mod(uint16_t old_rnti, uint16_t new_rnti) override {} + + // TS 38.413 - Section 8.3.2 - UE Context Release Request + void user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) override; + + bool is_amf_connected() override; bool send_error_indication(const asn1::ngap_nr::cause_c& cause, srsran::optional ran_ue_ngap_id = {}, srsran::optional amf_ue_ngap_id = {}); - void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome); + void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) override; bool send_pdu_session_resource_setup_response(); // Stack interface bool - handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); void get_metrics(ngap_metrics_t& m); void get_args(ngap_args_t& args_); diff --git a/srsgnb/hdr/stack/ngap/ngap_ue.h b/srsgnb/hdr/stack/ngap/ngap_ue.h index e2eb7ba7f..f51e2722d 100644 --- a/srsgnb/hdr/stack/ngap/ngap_ue.h +++ b/srsgnb/hdr/stack/ngap/ngap_ue.h @@ -48,6 +48,8 @@ public: bool send_ue_ctxt_release_complete(); // 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.4 - UE Context Release Request + bool send_ue_context_release_request(asn1::ngap_nr::cause_c cause); // 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 diff --git a/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h b/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h index 361e4f46f..bb249b364 100644 --- a/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h +++ b/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h @@ -56,6 +56,8 @@ public: int reset_pdu_sessions(uint16_t rnti); + const std::map& pdu_sessions() const { return pdu_session_list; } + private: gtpu_interface_rrc* gtpu = nullptr; std::map pdu_session_list; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index afe3e00c0..76ed30972 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -103,6 +103,7 @@ public: srsran::const_byte_span nas_pdu, uint32_t lcid) final; int release_bearers(uint16_t rnti) final; + void release_user(uint16_t rnti) final; void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) final; int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) final; int allocate_lcid(uint16_t rnti) final; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h index d48093894..8fc4947ce 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h @@ -90,7 +90,7 @@ private: int send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_ccch_msg); int send_dl_dcch(srsran::nr_srb srb, const asn1::rrc_nr::dl_dcch_msg_s& dl_dcch_msg); - /* TS 38.331 - 5.3.3 RRC connection establishment */ + /** TS 38.331 - 5.3.3 RRC connection establishment */ void send_rrc_setup(); void send_rrc_reject(uint8_t reject_wait_time_secs); diff --git a/srsgnb/src/stack/ngap/ngap.cc b/srsgnb/src/stack/ngap/ngap.cc index bdc3a8a50..6dc157fcf 100644 --- a/srsgnb/src/stack/ngap/ngap.cc +++ b/srsgnb/src/stack/ngap/ngap.cc @@ -265,6 +265,23 @@ void ngap::write_pdu(uint16_t rnti, srsran::const_byte_span pdu) u->send_ul_nas_transport(pdu); } +void ngap::user_release_request(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) +{ + ue* u = users.find_ue_rnti(rnti); + if (u == nullptr) { + logger.warning("Released UE rnti=0x%x not found.", rnti); + return; + } + + cause_c cause; + cause.set_radio_network().value = cause_radio; + if (not u->send_ue_context_release_request(cause)) { + logger.error("Failed to initiate RRC Release for rnti=0x%x. Removing user", rnti); + rrc->release_user(rnti); + users.erase(u); + } +} + /********************************************************* * ngap::user_list class *********************************************************/ diff --git a/srsgnb/src/stack/ngap/ngap_ue.cc b/srsgnb/src/stack/ngap/ngap_ue.cc index f83b446e9..2a2f0dc1c 100644 --- a/srsgnb/src/stack/ngap/ngap_ue.cc +++ b/srsgnb/src/stack/ngap/ngap_ue.cc @@ -244,6 +244,43 @@ bool ngap::ue::send_ue_ctxt_release_complete() return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseComplete"); } +bool ngap::ue::send_ue_context_release_request(asn1::ngap_nr::cause_c cause) +{ + if (not ngap_ptr->amf_connected) { + logger.warning("AMF not connected"); + return false; + } + + if (was_uectxtrelease_requested()) { + // let timeout auto-remove user. + return false; + } + release_requested = true; + + ngap_pdu_c tx_pdu; + tx_pdu.set_init_msg().load_info_obj(ASN1_NGAP_NR_ID_UE_CONTEXT_RELEASE_REQUEST); + ue_context_release_request_s& container = tx_pdu.init_msg().value.ue_context_release_request(); + + container.protocol_ies.cause.value = cause; + + // PDU Session Resource List + auto& session_lst = container.protocol_ies.pdu_session_res_list_cxt_rel_req.value; + for (const auto& pdu_pair : bearer_manager.pdu_sessions()) { + const ngap_ue_bearer_manager::pdu_session_t& session = pdu_pair.second; + + pdu_session_res_item_cxt_rel_req_s obj; + obj.pdu_session_id = session.id; + session_lst.push_back(obj); + } + container.protocol_ies.pdu_session_res_list_cxt_rel_req_present = session_lst.size() > 0; + + container.protocol_ies.ran_ue_ngap_id.value = ctxt.ran_ue_ngap_id; + container.protocol_ies.amf_ue_ngap_id.value = ctxt.amf_ue_ngap_id.value(); + + // TODO: Implement timeout + return ngap_ptr->sctp_send_ngap_pdu(tx_pdu, ctxt.rnti, "UEContextReleaseRequest"); +} + /******************************************************************************* /* NGAP message handler ********************************************************************************/ diff --git a/srsgnb/src/stack/ngap/ngap_ue_proc.cc b/srsgnb/src/stack/ngap/ngap_ue_proc.cc index e1e820f91..9ad9fb3d4 100644 --- a/srsgnb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsgnb/src/stack/ngap/ngap_ue_proc.cc @@ -81,9 +81,8 @@ ngap_ue_ue_context_release_proc::ngap_ue_ue_context_release_proc(ngap_interface_ proc_outcome_t ngap_ue_ue_context_release_proc::init(const asn1::ngap_nr::ue_context_release_cmd_s& msg) { logger.info("Started %s", name()); - // TODO: How to approach erasing users ? bearer_manager->reset_pdu_sessions(ue_ctxt->rnti); - rrc->release_bearers(ue_ctxt->rnti); + rrc->release_user(ue_ctxt->rnti); parent->send_ue_ctxt_release_complete(); return proc_outcome_t::success; } diff --git a/srsgnb/src/stack/ngap/test/ngap_test.cc b/srsgnb/src/stack/ngap/test/ngap_test.cc index c5039b1c9..6e637d7b8 100644 --- a/srsgnb/src/stack/ngap/test/ngap_test.cc +++ b/srsgnb/src/stack/ngap/test/ngap_test.cc @@ -115,6 +115,7 @@ public: } int release_bearers(uint16_t rnti) { return SRSRAN_SUCCESS; } + void release_user(uint16_t rnti) {} int allocate_lcid(uint16_t rnti) { return SRSRAN_SUCCESS; } void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) {} diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 67e7ac949..d365fcbda 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -629,6 +629,16 @@ int rrc_nr::release_bearers(uint16_t rnti) return SRSRAN_SUCCESS; } +void rrc_nr::release_user(uint16_t rnti) +{ + if (not users.contains(rnti)) { + logger.warning("User rnti=0x%x has already been released", rnti); + return; + } + + users[rnti]->send_rrc_release(); +} + int rrc_nr::allocate_lcid(uint16_t rnti) { return SRSRAN_SUCCESS; diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 00d2441a3..3790cf8a3 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -96,8 +96,8 @@ void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type) case UE_INACTIVITY_TIMEOUT: { state = rrc_nr_state_t::RRC_INACTIVE; if (parent->cfg.is_standalone) { - // TODO: This procedure needs to be defined - parent->rrc_release(rnti); + // Start NGAP Release UE context + parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::user_inactivity); } else { parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti); } @@ -1017,7 +1017,7 @@ void rrc_nr::ue::send_security_mode_command(srsran::unique_byte_buffer_t nas_pdu ies.security_cfg_smc.security_algorithm_cfg = sec_ctx.get_security_algorithm_cfg(); if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) { - send_rrc_release(); + parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available); } } @@ -1061,7 +1061,7 @@ void rrc_nr::ue::send_rrc_reconfiguration() // Pack masterCellGroup into container srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(master_cell_group, __FUNCTION__); if (pdu == nullptr) { - send_rrc_release(); + parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available); return; } ies.non_crit_ext.master_cell_group.resize(pdu->N_bytes); @@ -1097,7 +1097,7 @@ void rrc_nr::ue::send_rrc_reconfiguration() ies.non_crit_ext_present = ies.non_crit_ext.master_cell_group_present or ies.non_crit_ext.ded_nas_msg_list_present; if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) { - send_rrc_release(); + parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available); } } @@ -1112,7 +1112,21 @@ void rrc_nr::ue::handle_rrc_reconfiguration_complete(const asn1::rrc_nr::rrc_rec void rrc_nr::ue::send_rrc_release() { - // TODO + static const uint32_t release_delay = 60; // Taken from TS 38.331, 5.3.8.3 + + dl_dcch_msg_s dl_dcch_msg; + rrc_release_s& release = dl_dcch_msg.msg.set_c1().set_rrc_release(); + + release.rrc_transaction_id = (uint8_t)((transaction_id++) % 4); + rrc_release_ies_s& ies = release.crit_exts.set_rrc_release(); + + ies.suspend_cfg_present = false; // goes to RRC_IDLE + + send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg); + state = rrc_nr_state_t::RRC_IDLE; + + // TODO: Obtain acknowledgment from lower layers that RRC Release was received + parent->task_sched.defer_callback(release_delay, [this]() { parent->rem_user(rnti); }); } void rrc_nr::ue::send_dl_information_transfer(srsran::unique_byte_buffer_t sdu) @@ -1126,7 +1140,7 @@ void rrc_nr::ue::send_dl_information_transfer(srsran::unique_byte_buffer_t sdu) memcpy(ies.ded_nas_msg.data(), sdu->data(), ies.ded_nas_msg.size()); if (send_dl_dcch(srsran::nr_srb::srb1, dl_dcch_msg) != SRSRAN_SUCCESS) { - send_rrc_release(); + parent->ngap->user_release_request(rnti, asn1::ngap_nr::cause_radio_network_opts::radio_res_not_available); } } From 8a5ecfea4018ac34df102b6b0edfbb9cb05e75a9 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 1 Dec 2021 17:41:37 +0000 Subject: [PATCH 51/53] nr,gnb,ngap: rename functions for extra clarity --- srsgnb/hdr/stack/ngap/ngap.h | 2 +- srsgnb/hdr/stack/ngap/ngap_ue.h | 5 +++-- srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h | 9 +++++---- srsgnb/src/stack/ngap/ngap.cc | 8 +++----- srsgnb/src/stack/ngap/ngap_ue.cc | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/srsgnb/hdr/stack/ngap/ngap.h b/srsgnb/hdr/stack/ngap/ngap.h index 86b3da74a..146b12203 100644 --- a/srsgnb/hdr/stack/ngap/ngap.h +++ b/srsgnb/hdr/stack/ngap/ngap.h @@ -133,7 +133,7 @@ private: // TS 38.413 - Section 9.2.6.3 - NG Setup Failure bool handle_ng_setup_failure(const asn1::ngap_nr::ng_setup_fail_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); + bool handle_ue_context_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg); // 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 diff --git a/srsgnb/hdr/stack/ngap/ngap_ue.h b/srsgnb/hdr/stack/ngap/ngap_ue.h index f51e2722d..c33b5094f 100644 --- a/srsgnb/hdr/stack/ngap/ngap_ue.h +++ b/srsgnb/hdr/stack/ngap/ngap_ue.h @@ -51,11 +51,12 @@ public: // TS 38.413 - Section 9.2.2.4 - UE Context Release Request bool send_ue_context_release_request(asn1::ngap_nr::cause_c cause); // 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); + bool handle_ue_context_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; } + /// Checks if a UE Context Release Request was already sent + bool was_ue_context_release_requested() const { return release_requested; } void notify_rrc_reconf_complete(const bool reconf_complete_outcome); ngap_ue_ctxt_t ctxt = {}; diff --git a/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h b/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h index bb249b364..0f896f04a 100644 --- a/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h +++ b/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h @@ -56,12 +56,13 @@ public: int reset_pdu_sessions(uint16_t rnti); - const std::map& pdu_sessions() const { return pdu_session_list; } + using pdu_session_list_t = std::map; + const pdu_session_list_t& pdu_sessions() const { return pdu_session_list; } private: - gtpu_interface_rrc* gtpu = nullptr; - std::map pdu_session_list; - srslog::basic_logger& logger; + gtpu_interface_rrc* gtpu = nullptr; + pdu_session_list_t pdu_session_list; + srslog::basic_logger& logger; std::map next_lcid_list; // Map RNTI to next LCID to be allocated diff --git a/srsgnb/src/stack/ngap/ngap.cc b/srsgnb/src/stack/ngap/ngap.cc index 6dc157fcf..51b620cc2 100644 --- a/srsgnb/src/stack/ngap/ngap.cc +++ b/srsgnb/src/stack/ngap/ngap.cc @@ -432,7 +432,7 @@ bool ngap::handle_initiating_message(const asn1::ngap_nr::init_msg_s& msg) case ngap_elem_procs_o::init_msg_c::types_opts::init_context_setup_request: 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()); + return handle_ue_context_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: @@ -547,7 +547,7 @@ bool ngap::handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_s return true; } -bool ngap::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg) +bool ngap::handle_ue_context_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg) { const asn1::ngap_nr::ue_ngap_id_pair_s& ue_ngap_id_pair = msg.protocol_ies.ue_ngap_ids.value.ue_ngap_id_pair(); @@ -557,9 +557,7 @@ bool ngap::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cm return false; } - u->handle_ue_ctxt_release_cmd(msg); - - return true; + return u->handle_ue_context_release_cmd(msg); } bool ngap::handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) diff --git a/srsgnb/src/stack/ngap/ngap_ue.cc b/srsgnb/src/stack/ngap/ngap_ue.cc index 2a2f0dc1c..1d420877c 100644 --- a/srsgnb/src/stack/ngap/ngap_ue.cc +++ b/srsgnb/src/stack/ngap/ngap_ue.cc @@ -251,7 +251,7 @@ bool ngap::ue::send_ue_context_release_request(asn1::ngap_nr::cause_c cause) return false; } - if (was_uectxtrelease_requested()) { + if (was_ue_context_release_requested()) { // let timeout auto-remove user. return false; } @@ -294,7 +294,7 @@ bool ngap::ue::handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_conte return true; } -bool ngap::ue::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg) +bool ngap::ue::handle_ue_context_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg) { // TODO: Release UE context if (not ue_context_release_proc.launch(msg)) { From 2d42766b2ef0ad797d1ec7a81ab89f130471b9bb Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 2 Dec 2021 12:05:21 +0000 Subject: [PATCH 52/53] epc,s1ap,nas: reduce the logging level of MAC failures on identity response and authentication response --- srsepc/hdr/mme/nas.h | 2 +- srsepc/src/mme/nas.cc | 35 +++++++++++----------- srsepc/src/mme/s1ap_nas_transport.cc | 43 +++++++++++++++++----------- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/srsepc/hdr/mme/nas.h b/srsepc/hdr/mme/nas.h index 208f2ae3a..bd29e889f 100644 --- a/srsepc/hdr/mme/nas.h +++ b/srsepc/hdr/mme/nas.h @@ -238,7 +238,7 @@ public: bool pack_attach_accept(srsran::byte_buffer_t* nas_buffer); /* Security functions */ - bool integrity_check(srsran::byte_buffer_t* pdu); + bool integrity_check(srsran::byte_buffer_t* pdu, bool warn_failure = true); bool short_integrity_check(srsran::byte_buffer_t* pdu); void integrity_generate(srsran::byte_buffer_t* pdu, uint8_t* mac); void cipher_decrypt(srsran::byte_buffer_t* pdu); diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index 3c81aca41..62c33ec4c 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -1427,8 +1427,8 @@ bool nas::pack_security_mode_command(srsran::byte_buffer_t* nas_buffer) sm_cmd.imeisv_req = LIBLTE_MME_IMEISV_REQUESTED; } - sm_cmd.nonce_ue_present = false; - sm_cmd.nonce_mme_present = false; + sm_cmd.nonce_ue_present = false; + sm_cmd.nonce_mme_present = false; uint8_t sec_hdr_type = 3; LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg( @@ -1805,7 +1805,7 @@ bool nas::short_integrity_check(srsran::byte_buffer_t* pdu) return true; } -bool nas::integrity_check(srsran::byte_buffer_t* pdu) +bool nas::integrity_check(srsran::byte_buffer_t* pdu, bool warn_failure) { uint8_t exp_mac[4] = {}; const uint8_t* mac = &pdu->msg[1]; @@ -1848,20 +1848,21 @@ bool nas::integrity_check(srsran::byte_buffer_t* pdu) // Check if expected mac equals the sent mac for (int i = 0; i < 4; i++) { if (exp_mac[i] != mac[i]) { - m_logger.warning("Integrity check failure. Algorithm=EIA%d", (int)m_sec_ctx.integ_algo); - m_logger.warning("UL Local: est_count=%d, old_count=%d, MAC=[%02x %02x %02x %02x], " - "Received: UL count=%d, MAC=[%02x %02x %02x %02x]", - estimated_count, - m_sec_ctx.ul_nas_count, - exp_mac[0], - exp_mac[1], - exp_mac[2], - exp_mac[3], - pdu->msg[5], - mac[0], - mac[1], - mac[2], - mac[3]); + srslog::log_channel& channel = warn_failure ? m_logger.warning : m_logger.info; + channel("Integrity check failure. Algorithm=EIA%d", (int)m_sec_ctx.integ_algo); + channel("UL Local: est_count=%d, old_count=%d, MAC=[%02x %02x %02x %02x], " + "Received: UL count=%d, MAC=[%02x %02x %02x %02x]", + estimated_count, + m_sec_ctx.ul_nas_count, + exp_mac[0], + exp_mac[1], + exp_mac[2], + exp_mac[3], + pdu->msg[5], + mac[0], + mac[1], + mac[2], + mac[3]); return false; } } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 758caeb86..5c61313e7 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -59,18 +59,18 @@ void s1ap_nas_transport::init() m_s1ap = s1ap::get_instance(); // Init NAS args - m_nas_init.mcc = m_s1ap->m_s1ap_args.mcc; - m_nas_init.mnc = m_s1ap->m_s1ap_args.mnc; - m_nas_init.mme_code = m_s1ap->m_s1ap_args.mme_code; - m_nas_init.mme_group = m_s1ap->m_s1ap_args.mme_group; - m_nas_init.tac = m_s1ap->m_s1ap_args.tac; - m_nas_init.apn = m_s1ap->m_s1ap_args.mme_apn; - m_nas_init.dns = m_s1ap->m_s1ap_args.dns_addr; + m_nas_init.mcc = m_s1ap->m_s1ap_args.mcc; + m_nas_init.mnc = m_s1ap->m_s1ap_args.mnc; + m_nas_init.mme_code = m_s1ap->m_s1ap_args.mme_code; + m_nas_init.mme_group = m_s1ap->m_s1ap_args.mme_group; + m_nas_init.tac = m_s1ap->m_s1ap_args.tac; + m_nas_init.apn = m_s1ap->m_s1ap_args.mme_apn; + m_nas_init.dns = m_s1ap->m_s1ap_args.dns_addr; m_nas_init.full_net_name = m_s1ap->m_s1ap_args.full_net_name; m_nas_init.short_net_name = m_s1ap->m_s1ap_args.short_net_name; - m_nas_init.paging_timer = m_s1ap->m_s1ap_args.paging_timer; - m_nas_init.integ_algo = m_s1ap->m_s1ap_args.integrity_algo; - m_nas_init.cipher_algo = m_s1ap->m_s1ap_args.encryption_algo; + m_nas_init.paging_timer = m_s1ap->m_s1ap_args.paging_timer; + m_nas_init.integ_algo = m_s1ap->m_s1ap_args.integrity_algo; + m_nas_init.cipher_algo = m_s1ap->m_s1ap_args.encryption_algo; m_nas_init.request_imeisv = m_s1ap->m_s1ap_args.request_imeisv; // Init NAS interface @@ -170,17 +170,28 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(const asn1::s1ap::ul_nas_tr m_logger.error("Unhandled security header type in Uplink NAS Transport: %d", sec_hdr_type); return false; } - // Todo: Check on count mismatch of uplink count and do resync nas counter... + + // Some messages may have invalid MAC. Check wether we need to warn about MAC failures. + bool warn_integrity_fail = true; + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT) { + // Avoid unecessary warnings for identity response and authentication response. + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg.get(), &pd, &msg_type); + if (msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE || msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE) { + warn_integrity_fail = false; + } + } // Check MAC if message is integrity protected if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || - sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { - mac_valid = nas_ctx->integrity_check(nas_msg.get()); - if (mac_valid == false) { - m_logger.warning("Invalid MAC message. Even if security header indicates integrity protection (Maybe: " - "Identity Response or Authentication Response)"); + mac_valid = nas_ctx->integrity_check(nas_msg.get(), warn_integrity_fail); + if (not mac_valid) { + srslog::log_channel& channel = warn_integrity_fail ? m_logger.warning : m_logger.info; + channel("Invalid MAC message. Even if security header indicates integrity protection (Maybe: " + "Identity Response or Authentication Response)"); } } From ecaaf8d595093bdf0783e317c96584caed97958f Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 1 Dec 2021 14:44:29 +0000 Subject: [PATCH 53/53] nr,gnb,sched: implement helper methods to check available PRBs in BWP, taking into account common SearchSpace BW limitations --- srsgnb/hdr/stack/mac/sched_nr_cfg.h | 14 +++++++ .../hdr/stack/mac/sched_nr_grant_allocator.h | 5 +++ srsgnb/src/stack/mac/sched_nr_bwp.cc | 5 ++- srsgnb/src/stack/mac/sched_nr_cfg.cc | 38 ++++++++++++------- srsgnb/src/stack/mac/sched_nr_helpers.cc | 9 +++-- 5 files changed, 52 insertions(+), 19 deletions(-) diff --git a/srsgnb/hdr/stack/mac/sched_nr_cfg.h b/srsgnb/hdr/stack/mac/sched_nr_cfg.h index b7af47215..1d986e95d 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_cfg.h +++ b/srsgnb/hdr/stack/mac/sched_nr_cfg.h @@ -95,6 +95,20 @@ struct bwp_params_t { srsran::optional_vector common_cce_list; bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); + + const prb_bitmap& used_prbs(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const + { + if (used_common_prb_masks.contains(ss_id)) { + if (dci_fmt == srsran_dci_format_nr_1_0) { + return used_common_prb_masks[ss_id]; + } + } + return cached_empty_prb_mask; + } + +private: + prb_bitmap cached_empty_prb_mask; + srsran::optional_vector used_common_prb_masks; }; /// Structure packing a single cell config params, and sched args diff --git a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h index 21541c5b6..b7b4455eb 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h +++ b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h @@ -62,6 +62,11 @@ struct bwp_slot_grid { bool is_dl() const { return cfg->slots[slot_idx].is_dl; } bool is_ul() const { return cfg->slots[slot_idx].is_ul; } + + prb_bitmap used_prbs(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const + { + return dl_prbs.prbs() | cfg->used_prbs(ss_id, dci_fmt); + } }; struct bwp_res_grid { diff --git a/srsgnb/src/stack/mac/sched_nr_bwp.cc b/srsgnb/src/stack/mac/sched_nr_bwp.cc index c198a4a9a..14b941a50 100644 --- a/srsgnb/src/stack/mac/sched_nr_bwp.cc +++ b/srsgnb/src/stack/mac/sched_nr_bwp.cc @@ -24,8 +24,9 @@ ra_sched::ra_sched(const bwp_params_t& bwp_cfg_) : alloc_result ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc) { - const uint32_t rar_aggr_level = 2; - const prb_bitmap& prbs = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_prbs.prbs(); + const uint32_t rar_aggr_level = 2; + prb_bitmap prbs = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].used_prbs(bwp_cfg->cfg.pdcch.ra_search_space.id, + srsran_dci_format_nr_1_0); alloc_result ret = alloc_result::other_cause; srsran::const_span msg3_grants{rar.msg3_grant}; diff --git a/srsgnb/src/stack/mac/sched_nr_cfg.cc b/srsgnb/src/stack/mac/sched_nr_cfg.cc index e02ff06b6..bc89ebbc1 100644 --- a/srsgnb/src/stack/mac/sched_nr_cfg.cc +++ b/srsgnb/src/stack/mac/sched_nr_cfg.cc @@ -51,6 +51,7 @@ bwp_params_t::bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg P = get_P(cfg.rb_width, cfg.pdsch.rbg_size_cfg_1); N_rbg = get_nof_rbgs(cfg.rb_width, cfg.start_rb, cfg.pdsch.rbg_size_cfg_1); + cached_empty_prb_mask.resize(cfg.rb_width); // Derive params of individual slots uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx); @@ -91,19 +92,30 @@ bwp_params_t::bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg } for (uint32_t ss_id = 0; ss_id < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ss_id) { - if (cell_cfg.bwps[0].pdcch.search_space_present[ss_id]) { - auto& ss = cell_cfg.bwps[0].pdcch.search_space[ss_id]; - auto& coreset = cell_cfg.bwps[0].pdcch.coreset[ss.coreset_id]; - common_cce_list.emplace(ss_id); - bwp_cce_pos_list& ss_cce_list = common_cce_list[ss_id]; - for (uint32_t sl = 0; sl < SRSRAN_NOF_SF_X_FRAME; ++sl) { - for (uint32_t agg_idx = 0; agg_idx < MAX_NOF_AGGR_LEVELS; ++agg_idx) { - ss_cce_list[sl][agg_idx].resize(SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR); - int n = srsran_pdcch_nr_locations_coreset( - &coreset, &ss, SRSRAN_SIRNTI, agg_idx, sl, ss_cce_list[sl][agg_idx].data()); - srsran_assert(n >= 0, "Failed to configure DCI locations of search space id=%d", ss_id); - ss_cce_list[sl][agg_idx].resize(n); - } + if (not cell_cfg.bwps[0].pdcch.search_space_present[ss_id]) { + continue; + } + auto& ss = cell_cfg.bwps[0].pdcch.search_space[ss_id]; + auto& coreset = cell_cfg.bwps[0].pdcch.coreset[ss.coreset_id]; + common_cce_list.emplace(ss_id); + bwp_cce_pos_list& ss_cce_list = common_cce_list[ss_id]; + for (uint32_t sl = 0; sl < SRSRAN_NOF_SF_X_FRAME; ++sl) { + for (uint32_t agg_idx = 0; agg_idx < MAX_NOF_AGGR_LEVELS; ++agg_idx) { + ss_cce_list[sl][agg_idx].resize(SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR); + int n = srsran_pdcch_nr_locations_coreset( + &coreset, &ss, SRSRAN_SIRNTI, agg_idx, sl, ss_cce_list[sl][agg_idx].data()); + srsran_assert(n >= 0, "Failed to configure DCI locations of search space id=%d", ss_id); + ss_cce_list[sl][agg_idx].resize(n); + } + } + + if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss.type)) { + used_common_prb_masks.emplace(ss_id, cached_empty_prb_mask); + uint32_t coreset_start = srsran_coreset_start_rb(&cfg.pdcch.coreset[ss.coreset_id]); + used_common_prb_masks[ss_id].fill(0, coreset_start, true); + if (ss.coreset_id == 0) { + uint32_t coreset0_bw = srsran_coreset_get_bw(&cfg.pdcch.coreset[0]); + used_common_prb_masks[ss_id].fill(coreset_start + coreset0_bw, cfg.rb_width, true); } } } diff --git a/srsgnb/src/stack/mac/sched_nr_helpers.cc b/srsgnb/src/stack/mac/sched_nr_helpers.cc index 5b08610f8..73958562a 100644 --- a/srsgnb/src/stack/mac/sched_nr_helpers.cc +++ b/srsgnb/src/stack/mac/sched_nr_helpers.cc @@ -84,6 +84,7 @@ void fill_dci_grant(const bwp_params_t& bwp_cfg, const prb_grant& grant, srsran_ if (dci.ctx.coreset_id == 0 and SRSRAN_SEARCH_SPACE_IS_COMMON(dci.ctx.ss_type)) { nof_prb = dci.coreset0_bw; } + srsran_assert(grant.prbs().start() >= rb_start, "Invalid PRB index=%d < %d", grant.prbs().start(), rb_start); uint32_t grant_start = grant.prbs().start() - rb_start; dci.freq_domain_assigment = srsran_ra_nr_type1_riv(nof_prb, grant_start, grant.prbs().length()); } @@ -233,9 +234,9 @@ void log_sched_bwp_result(srslog::basic_logger& logger, data_count++; } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) { const pdsch_t& pdsch = bwp_slot.dl.phy.pdsch[std::distance(bwp_slot.dl.phy.pdcch_dl.data(), &pdcch)]; - srsran::const_span prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + pdsch.sch.grant.nof_prb}; + srsran::const_span prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + SRSRAN_MAX_PRB_NR}; uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true)); - uint32_t end_idx = std::distance(prbs.begin(), std::find(prbs.begin() + start_idx, prbs.end(), false)); + uint32_t end_idx = start_idx + pdsch.sch.grant.nof_prb; fmt::format_to(fmtbuf, "SCHED: RAR, cc={}, ra-rnti=0x{:x}, prbs={}, pdsch_slot={}, msg3_slot={}, nof_grants={}", res_grid.cfg->cc, @@ -248,9 +249,9 @@ void log_sched_bwp_result(srslog::basic_logger& logger, } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_si) { if (logger.debug.enabled()) { const pdsch_t& pdsch = bwp_slot.dl.phy.pdsch[std::distance(bwp_slot.dl.phy.pdcch_dl.data(), &pdcch)]; - srsran::const_span prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + pdsch.sch.grant.nof_prb}; + srsran::const_span prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + SRSRAN_MAX_PRB_NR}; uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true)); - uint32_t end_idx = std::distance(prbs.begin(), std::find(prbs.begin() + start_idx, prbs.end(), false)); + uint32_t end_idx = start_idx + pdsch.sch.grant.nof_prb; fmt::format_to(fmtbuf, "SCHED: SI{}, cc={}, prbs={}, pdsch_slot={}", pdcch.dci.sii == 0 ? "B" : " message",