@@ -41,7 +41,10 @@ class cu_cp_reestablishment_test : public cu_cp_test_environment, public ::testi
4141
4242 // / Run RRC Reestablishment.
4343 // / \return Returns true if Reestablishment is successful, and false if the gNB fallbacked to RRC Setup.
44- bool run_rrc_reestablishment (gnb_du_ue_f1ap_id_t new_du_ue_id, rnti_t new_rnti, rnti_t old_rnti_, pci_t old_pci_)
44+ bool send_rrc_reest_request_and_wait_response (gnb_du_ue_f1ap_id_t new_du_ue_id,
45+ rnti_t new_rnti,
46+ rnti_t old_rnti_,
47+ pci_t old_pci_)
4548 {
4649 // Generate RRC Reestablishment Request.
4750 byte_buffer rrc_container =
@@ -67,6 +70,34 @@ class cu_cp_reestablishment_test : public cu_cp_test_environment, public ::testi
6770 return dl_rrc_msg.srb_id == 1 ;
6871 }
6972
73+ optional<f1ap_message> ue_sends_rrc_setup_request_and_waits_rrc_setup (gnb_du_ue_f1ap_id_t du_ue_id, rnti_t crnti)
74+ {
75+ ngap_message ngap_pdu;
76+ srsran_assert (not this ->get_amf ().try_pop_rx_pdu (ngap_pdu), " there are still NGAP messages to pop from AMF" );
77+ f1ap_message f1ap_pdu;
78+ srsran_assert (not this ->get_du (du_idx).try_pop_dl_pdu (f1ap_pdu), " there are still F1AP DL messages to pop from DU" );
79+
80+ // Inject Initial UL RRC message
81+ f1ap_message init_ul_rrc_msg = generate_init_ul_rrc_message_transfer (du_ue_id, crnti);
82+ test_logger.info (" c-rnti={} du_ue_id={}: Injecting Initial UL RRC message" , crnti, du_ue_id);
83+ get_du (du_idx).push_ul_pdu (init_ul_rrc_msg);
84+
85+ // Wait for DL RRC message transfer (containing RRC Setup)
86+ bool result = this ->wait_for_f1ap_tx_pdu (du_idx, f1ap_pdu, std::chrono::milliseconds{1000 });
87+ if (not result) {
88+ return nullopt ;
89+ }
90+
91+ // Check if the DL RRC Message with Msg4 is valid.
92+ report_error_if_not (test_helpers::is_valid_dl_rrc_message_transfer_with_msg4 (f1ap_pdu), " invalid DL RRC message" );
93+ dl_rrc_msg_transfer_s& dl_rrc_msg = f1ap_pdu.pdu .init_msg ().value .dl_rrc_msg_transfer ();
94+ report_error_if_not (int_to_gnb_du_ue_f1ap_id (dl_rrc_msg->gnb_du_ue_f1ap_id ) == du_ue_id,
95+ " invalid gNB-DU-UE-F1AP-ID" );
96+ report_error_if_not (int_to_srb_id (dl_rrc_msg->srb_id ) == srb_id_t ::srb0, " invalid SRB-Id" );
97+
98+ return f1ap_pdu;
99+ }
100+
70101 void ue_sends_rrc_setup_complete (gnb_du_ue_f1ap_id_t du_ue_id, gnb_cu_ue_f1ap_id_t cu_ue_id)
71102 {
72103 // Generate RRC Setup Complete.
@@ -111,7 +142,8 @@ TEST_F(cu_cp_reestablishment_test, when_old_ue_does_not_exist_then_reestablishme
111142 EXPECT_TRUE (connect_new_ue (du_idx, old_du_ue_id, old_crnti));
112143
113144 // Reestablishment Request to RNTI that does not exist.
114- ASSERT_FALSE (run_rrc_reestablishment (int_to_gnb_du_ue_f1ap_id (1 ), to_rnti (0x4602 ), to_rnti (0x4603 ), old_pci))
145+ ASSERT_FALSE (
146+ send_rrc_reest_request_and_wait_response (int_to_gnb_du_ue_f1ap_id (1 ), to_rnti (0x4602 ), to_rnti (0x4603 ), old_pci))
115147 << " RRC setup should have been sent" ;
116148
117149 // UE sends RRC Setup Complete
@@ -127,7 +159,8 @@ TEST_F(cu_cp_reestablishment_test, when_old_ue_has_no_ngap_context_then_reestabl
127159 // Connect UE 0x4601.
128160 EXPECT_TRUE (connect_new_ue (du_idx, old_du_ue_id, old_crnti));
129161
130- ASSERT_FALSE (run_rrc_reestablishment (int_to_gnb_du_ue_f1ap_id (1 ), to_rnti (0x4602 ), old_crnti, old_pci))
162+ ASSERT_FALSE (
163+ send_rrc_reest_request_and_wait_response (int_to_gnb_du_ue_f1ap_id (1 ), to_rnti (0x4602 ), old_crnti, old_pci))
131164 << " RRC setup should have been sent" ;
132165
133166 // old UE should not be removed at this stage.
@@ -190,3 +223,44 @@ TEST_F(cu_cp_reestablishment_test,
190223 auto report = this ->get_cu_cp ().get_metrics_handler ().request_metrics_report ();
191224 ASSERT_EQ (report.ues .size (), 1 ) << " Old UE should not be removed yet" ;
192225}
226+
227+ TEST_F (cu_cp_reestablishment_test, when_old_ue_is_busy_with_a_procedure_then_reestablishment_fallback_still_completes)
228+ {
229+ // UE 0x4601 sends RRC Setup Request, the gNB responds with RRC Setup and waits for RRC Setup Complete.
230+ auto msg = this ->ue_sends_rrc_setup_request_and_waits_rrc_setup (old_du_ue_id, old_crnti);
231+ ASSERT_TRUE (msg.has_value ());
232+
233+ // Send RRC Reestablishment Request and DU receives RRC Setup (Fallback).
234+ gnb_du_ue_f1ap_id_t new_du_ue_id = int_to_gnb_du_ue_f1ap_id (1 );
235+ rnti_t new_crnti = to_rnti (0x4602 );
236+ ASSERT_FALSE (send_rrc_reest_request_and_wait_response (new_du_ue_id, new_crnti, old_crnti, old_pci));
237+
238+ // new UE sends RRC Setup Complete and completes fallback procedure.
239+ gnb_cu_ue_f1ap_id_t cu_ue_id = int_to_gnb_cu_ue_f1ap_id (1 );
240+ this ->ue_sends_rrc_setup_complete (new_du_ue_id, cu_ue_id);
241+
242+ // STATUS: NGAP Initial UE Message should be sent for the new UE.
243+ ngap_message ngap_pdu;
244+ ASSERT_TRUE (this ->wait_for_ngap_tx_pdu (ngap_pdu));
245+ ASSERT_TRUE (test_helpers::is_valid_init_ue_message (ngap_pdu));
246+
247+ // STATUS: UE Context Released Command for old UE not yet sent because the old UE is busy with an RRC Setup procedure.
248+ f1ap_message f1ap_pdu;
249+ ASSERT_FALSE (this ->get_du (du_idx).try_pop_dl_pdu (f1ap_pdu)) << " UE Context Release Command sent to soon" ;
250+
251+ // Send RRC Setup Complete for old UE.
252+ gnb_cu_ue_f1ap_id_t old_cu_ue_id =
253+ int_to_gnb_cu_ue_f1ap_id (msg->pdu .init_msg ().value .dl_rrc_msg_transfer ()->gnb_cu_ue_f1ap_id );
254+ this ->ue_sends_rrc_setup_complete (old_du_ue_id, old_cu_ue_id);
255+
256+ // STATUS: CU-CP sends UE Context Release Command after the previous procedure times out.
257+ ASSERT_TRUE (this ->wait_for_f1ap_tx_pdu (du_idx, f1ap_pdu));
258+ ASSERT_TRUE (test_helpers::is_valid_ue_context_release_command (f1ap_pdu));
259+ auto report = this ->get_cu_cp ().get_metrics_handler ().request_metrics_report ();
260+ ASSERT_EQ (report.ues .size (), 2 ) << " Old UE should not be removed yet as its RRC Setup procedure is not completed" ;
261+
262+ // STATUS: UE Context Release Complete for old UE and it should be finally removed.
263+ this ->get_du (du_idx).push_ul_pdu (test_helpers::generate_ue_context_release_complete (f1ap_pdu));
264+ report = this ->get_cu_cp ().get_metrics_handler ().request_metrics_report ();
265+ ASSERT_EQ (report.ues .size (), 1 ) << " Old UE was not removed" ;
266+ }
0 commit comments