@@ -19,6 +19,193 @@ using namespace asn1::f1ap;
1919// / \brief Convert the UE Context Setup Request from common type to ASN.1.
2020// / \param[out] asn1_request The ASN.1 struct to store the result.
2121// / \param[in] request The common type UE Context Setup Request.
22+ static void fill_asn1_ue_context_setup_request (asn1::f1ap::ue_context_setup_request_s& asn1_request,
23+ const f1ap_ue_context_setup_request& request,
24+ const f1ap_ue_ids& ue_ids);
25+
26+ // / \brief Convert the UE Context Setup Failure from ASN.1 to common type.
27+ // / \param[in] response The common type UE Context Setup Response.
28+ // / \param[in] ue_index UE index.
29+ // / \param[in] asn1_failure The ASN.1 struct to convert.
30+ static void fill_f1ap_ue_context_setup_response (f1ap_ue_context_setup_response& response,
31+ ue_index_t ue_index,
32+ const asn1::f1ap::ue_context_setup_fail_s& asn1_failure);
33+
34+ // / \brief Convert the UE Context Setup Response from ASN.1 to common type.
35+ // / \param[out] response The common type struct to store the result.
36+ // / \param[in] ue_index UE index.
37+ // / \param[in] asn1_response The ASN.1 UE Context Setup Response.
38+ static void fill_f1ap_ue_context_setup_response (f1ap_ue_context_setup_response& response,
39+ ue_index_t ue_index,
40+ const asn1::f1ap::ue_context_setup_resp_s& asn1_response);
41+
42+ // ---- UE Context Setup Procedure ----
43+
44+ ue_context_setup_procedure::ue_context_setup_procedure (const f1ap_ue_context_setup_request& request_,
45+ f1ap_ue_context_list& ue_ctxt_list_,
46+ f1ap_du_processor_notifier& du_processor_notifier_,
47+ f1ap_message_notifier& f1ap_notif_,
48+ srslog::basic_logger& logger_,
49+ optional<rrc_ue_transfer_context> rrc_context_) :
50+ request(request_),
51+ ue_ctxt_list(ue_ctxt_list_),
52+ du_processor_notifier(du_processor_notifier_),
53+ f1ap_notifier(f1ap_notif_),
54+ logger(logger_),
55+ rrc_context(rrc_context_)
56+ {
57+ srsran_assert (request.ue_index != ue_index_t ::invalid, " UE index of F1AP UeContextSetupRequest must not be invalid" );
58+ }
59+
60+ void ue_context_setup_procedure::operator ()(coro_context<async_task<f1ap_ue_context_setup_response>>& ctx)
61+ {
62+ CORO_BEGIN (ctx);
63+
64+ logger.debug (" ue={} proc=\" {}\" : started..." , request.ue_index , name ());
65+
66+ // Create F1AP UE context if it doesn't exist.
67+ if (not find_or_create_f1ap_ue_context ()) {
68+ CORO_EARLY_RETURN (handle_procedure_result ());
69+ }
70+
71+ // Subscribe to respective publisher to receive UE CONTEXT SETUP RESPONSE/FAILURE message.
72+ transaction_sink.subscribe_to (ue_ctxt->ev_mng .context_setup_outcome );
73+
74+ // Send command to DU.
75+ send_ue_context_setup_request ();
76+
77+ // Await CU response.
78+ CORO_AWAIT (transaction_sink);
79+
80+ // Handle result of the transaction.
81+ CORO_RETURN (handle_procedure_result ());
82+ }
83+
84+ bool ue_context_setup_procedure::find_or_create_f1ap_ue_context ()
85+ {
86+ // Check if F1AP UE context exists first.
87+ ue_ctxt = ue_ctxt_list.find (request.ue_index );
88+ if (ue_ctxt != nullptr ) {
89+ logger.debug (" {}: UE context found" , f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
90+ return true ;
91+ }
92+
93+ // F1AP UE context does not yet exist.
94+ // Allocate gNB-CU-UE-F1AP-ID.
95+ gnb_cu_ue_f1ap_id_t tmp_cu_ue_f1ap_id = ue_ctxt_list.next_gnb_cu_ue_f1ap_id ();
96+ if (tmp_cu_ue_f1ap_id == gnb_cu_ue_f1ap_id_t ::invalid) {
97+ logger.warning (" ue={} proc=\" {}\" : No CU UE F1AP ID available" , request.ue_index , name ());
98+ return false ;
99+ }
100+
101+ // Create F1AP UE context.
102+ ue_ctxt = &ue_ctxt_list.add_ue (request.ue_index , tmp_cu_ue_f1ap_id);
103+ logger.info (" {}: UE successfully created." , f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
104+
105+ return true ;
106+ }
107+
108+ bool ue_context_setup_procedure::create_ue_rrc_context (const f1ap_ue_context_setup_response& ue_ctxt_setup_resp)
109+ {
110+ if (not ue_ctxt_setup_resp.success or ue_ctxt_setup_resp.ue_index == ue_index_t ::invalid) {
111+ logger.warning (" Couldn't create UE in target cell" );
112+ return false ;
113+ }
114+
115+ if (ue_ctxt_setup_resp.c_rnti .has_value ()) {
116+ // An C-RNTI has been allocated by the DU. In such case, we need to create a new UE RRC context in the CU-CP.
117+
118+ ue_rrc_context_creation_request req;
119+ req.ue_index = ue_ctxt_setup_resp.ue_index ;
120+ req.c_rnti = ue_ctxt_setup_resp.c_rnti .value ();
121+ req.cgi = request.sp_cell_id ;
122+ req.du_to_cu_rrc_container = ue_ctxt_setup_resp.du_to_cu_rrc_info .cell_group_cfg .copy ();
123+ req.prev_context = std::move (rrc_context);
124+
125+ ue_rrc_context_creation_response resp = du_processor_notifier.on_ue_rrc_context_creation_request (req);
126+ if (resp.f1ap_rrc_notifier == nullptr ) {
127+ logger.warning (" Couldn't create UE RRC context in target cell" );
128+ return false ;
129+ }
130+
131+ // Add RRC notifier to F1AP UE context.
132+ ue_ctxt_list.add_rrc_notifier (req.ue_index , resp.f1ap_rrc_notifier );
133+
134+ logger.debug (" ue={} Added RRC UE notifier" , req.ue_index );
135+ }
136+
137+ return true ;
138+ }
139+
140+ void ue_context_setup_procedure::send_ue_context_setup_request ()
141+ {
142+ // Pack message into PDU
143+ f1ap_message f1ap_ue_ctxt_setup_request_msg;
144+ f1ap_ue_ctxt_setup_request_msg.pdu .set_init_msg ();
145+ f1ap_ue_ctxt_setup_request_msg.pdu .init_msg ().load_info_obj (ASN1_F1AP_ID_UE_CONTEXT_SETUP);
146+ ue_context_setup_request_s& req = f1ap_ue_ctxt_setup_request_msg.pdu .init_msg ().value .ue_context_setup_request ();
147+
148+ // Convert common type to asn1
149+ fill_asn1_ue_context_setup_request (req, request, ue_ctxt->ue_ids );
150+
151+ if (logger.debug .enabled ()) {
152+ asn1::json_writer js;
153+ f1ap_ue_ctxt_setup_request_msg.pdu .to_json (js);
154+ logger.debug (" Containerized UeContextSetupRequest: {}" , js.to_string ());
155+ }
156+
157+ // send UE context setup request message
158+ f1ap_notifier.on_new_message (f1ap_ue_ctxt_setup_request_msg);
159+ }
160+
161+ f1ap_ue_context_setup_response ue_context_setup_procedure::handle_procedure_result ()
162+ {
163+ f1ap_ue_context_setup_response resp;
164+ resp.ue_index = request.ue_index ;
165+ resp.success = false ;
166+
167+ if (ue_ctxt == nullptr ) {
168+ logger.warning (" ue={} proc=\" {}\" failed" , request.ue_index , name ());
169+ return resp;
170+ }
171+
172+ if (transaction_sink.successful ()) {
173+ const auto & asn1_resp = transaction_sink.response ();
174+
175+ // Update gNB DU F1AP ID in F1AP UE context.
176+ ue_ctxt->ue_ids .du_ue_f1ap_id = int_to_gnb_du_ue_f1ap_id (asn1_resp->gnb_du_ue_f1ap_id );
177+ logger.debug (" {}: Updated UE gNB-DU-UE-ID" , f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
178+
179+ // Fill response to the UE context setup procedure.
180+ fill_f1ap_ue_context_setup_response (resp, request.ue_index , transaction_sink.response ());
181+
182+ // Create UE RRC context in CU-CP, if required.
183+ resp.success = create_ue_rrc_context (resp);
184+
185+ return resp;
186+ }
187+
188+ // Procedure failed.
189+
190+ if (transaction_sink.failed ()) {
191+ logger.warning (" {}: Procedure failed. Cause: {}" ,
192+ f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()},
193+ get_cause_str (transaction_sink.failure ()->cause ));
194+
195+ // Fill response to the UE context setup procedure.
196+ fill_f1ap_ue_context_setup_response (resp, request.ue_index , transaction_sink.failure ());
197+
198+ } else {
199+ logger.warning (" {}: Procedure failed. Cause: Timeout reached while waiting for DU response." ,
200+ f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
201+ }
202+
203+ // Delete created F1AP UE context.
204+ ue_ctxt_list.remove_ue (request.ue_index );
205+
206+ return resp;
207+ }
208+
22209static void fill_asn1_ue_context_setup_request (asn1::f1ap::ue_context_setup_request_s& asn1_request,
23210 const f1ap_ue_context_setup_request& request,
24211 const f1ap_ue_ids& ue_ids)
@@ -220,9 +407,6 @@ static void fill_f1ap_ue_context_setup_response(f1ap_ue_context_setup_response&
220407 }
221408}
222409
223- // / \brief Convert the UE Context Setup Response from ASN.1 to common type.
224- // / \param[out] response The common type struct to store the result.
225- // / \param[in] asn1_response The ASN.1 UE Context Setup Response.
226410static void fill_f1ap_ue_context_setup_response (f1ap_ue_context_setup_response& response,
227411 ue_index_t ue_index,
228412 const asn1::f1ap::ue_context_setup_resp_s& asn1_response)
@@ -321,168 +505,3 @@ static void fill_f1ap_ue_context_setup_response(f1ap_ue_context_setup_response&
321505 }
322506 }
323507}
324-
325- ue_context_setup_procedure::ue_context_setup_procedure (const f1ap_ue_context_setup_request& request_,
326- f1ap_ue_context_list& ue_ctxt_list_,
327- f1ap_du_processor_notifier& du_processor_notifier_,
328- f1ap_message_notifier& f1ap_notif_,
329- srslog::basic_logger& logger_,
330- optional<rrc_ue_transfer_context> rrc_context_) :
331- request(request_),
332- ue_ctxt_list(ue_ctxt_list_),
333- du_processor_notifier(du_processor_notifier_),
334- f1ap_notifier(f1ap_notif_),
335- logger(logger_),
336- rrc_context(rrc_context_)
337- {
338- srsran_assert (request.ue_index != ue_index_t ::invalid, " UE index of F1AP UeContextSetupRequest must not be invalid" );
339- }
340-
341- void ue_context_setup_procedure::operator ()(coro_context<async_task<f1ap_ue_context_setup_response>>& ctx)
342- {
343- CORO_BEGIN (ctx);
344-
345- logger.debug (" ue={} proc=\" {}\" : started..." , request.ue_index , name ());
346-
347- // Create F1AP UE context if it doesn't exist.
348- if (not find_or_create_f1ap_ue_context ()) {
349- CORO_EARLY_RETURN (handle_procedure_result ());
350- }
351-
352- // Subscribe to respective publisher to receive UE CONTEXT SETUP RESPONSE/FAILURE message.
353- transaction_sink.subscribe_to (ue_ctxt->ev_mng .context_setup_outcome );
354-
355- // Send command to DU.
356- send_ue_context_setup_request ();
357-
358- // Await CU response.
359- CORO_AWAIT (transaction_sink);
360-
361- // Handle result of the transaction.
362- CORO_RETURN (handle_procedure_result ());
363- }
364-
365- bool ue_context_setup_procedure::find_or_create_f1ap_ue_context ()
366- {
367- // Check if F1AP UE context exists first.
368- ue_ctxt = ue_ctxt_list.find (request.ue_index );
369- if (ue_ctxt != nullptr ) {
370- logger.debug (" {}: UE context found" , f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
371- return true ;
372- }
373-
374- // F1AP UE context does not yet exist.
375- // Allocate gNB-CU-UE-F1AP-ID.
376- gnb_cu_ue_f1ap_id_t tmp_cu_ue_f1ap_id = ue_ctxt_list.next_gnb_cu_ue_f1ap_id ();
377- if (tmp_cu_ue_f1ap_id == gnb_cu_ue_f1ap_id_t ::invalid) {
378- logger.warning (" ue={} proc=\" {}\" : No CU UE F1AP ID available" , request.ue_index , name ());
379- return false ;
380- }
381-
382- // Create F1AP UE context.
383- ue_ctxt = &ue_ctxt_list.add_ue (request.ue_index , tmp_cu_ue_f1ap_id);
384- logger.info (" {}: UE successfully created." , f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
385-
386- return true ;
387- }
388-
389- bool ue_context_setup_procedure::create_ue_rrc_context (const f1ap_ue_context_setup_response& ue_ctxt_setup_resp)
390- {
391- if (not ue_ctxt_setup_resp.success or ue_ctxt_setup_resp.ue_index == ue_index_t ::invalid) {
392- logger.warning (" Couldn't create UE in target cell" );
393- return false ;
394- }
395-
396- if (ue_ctxt_setup_resp.c_rnti .has_value ()) {
397- // An C-RNTI has been allocated by the DU. In such case, we need to create a new UE RRC context in the CU-CP.
398-
399- ue_rrc_context_creation_request req;
400- req.ue_index = ue_ctxt_setup_resp.ue_index ;
401- req.c_rnti = ue_ctxt_setup_resp.c_rnti .value ();
402- req.cgi = request.sp_cell_id ;
403- req.du_to_cu_rrc_container = ue_ctxt_setup_resp.du_to_cu_rrc_info .cell_group_cfg .copy ();
404- req.prev_context = std::move (rrc_context);
405-
406- ue_rrc_context_creation_response resp = du_processor_notifier.on_ue_rrc_context_creation_request (req);
407- if (resp.f1ap_rrc_notifier == nullptr ) {
408- logger.warning (" Couldn't create UE RRC context in target cell" );
409- return false ;
410- }
411-
412- // Add RRC notifier to F1AP UE context.
413- ue_ctxt_list.add_rrc_notifier (req.ue_index , resp.f1ap_rrc_notifier );
414-
415- logger.debug (" ue={} Added RRC UE notifier" , req.ue_index );
416- }
417-
418- return true ;
419- }
420-
421- void ue_context_setup_procedure::send_ue_context_setup_request ()
422- {
423- // Pack message into PDU
424- f1ap_message f1ap_ue_ctxt_setup_request_msg;
425- f1ap_ue_ctxt_setup_request_msg.pdu .set_init_msg ();
426- f1ap_ue_ctxt_setup_request_msg.pdu .init_msg ().load_info_obj (ASN1_F1AP_ID_UE_CONTEXT_SETUP);
427- ue_context_setup_request_s& req = f1ap_ue_ctxt_setup_request_msg.pdu .init_msg ().value .ue_context_setup_request ();
428-
429- // Convert common type to asn1
430- fill_asn1_ue_context_setup_request (req, request, ue_ctxt->ue_ids );
431-
432- if (logger.debug .enabled ()) {
433- asn1::json_writer js;
434- f1ap_ue_ctxt_setup_request_msg.pdu .to_json (js);
435- logger.debug (" Containerized UeContextSetupRequest: {}" , js.to_string ());
436- }
437-
438- // send UE context setup request message
439- f1ap_notifier.on_new_message (f1ap_ue_ctxt_setup_request_msg);
440- }
441-
442- f1ap_ue_context_setup_response ue_context_setup_procedure::handle_procedure_result ()
443- {
444- f1ap_ue_context_setup_response resp;
445- resp.ue_index = request.ue_index ;
446- resp.success = false ;
447-
448- if (ue_ctxt == nullptr ) {
449- logger.warning (" ue={} proc=\" {}\" failed" , request.ue_index , name ());
450- return resp;
451- }
452-
453- if (transaction_sink.successful ()) {
454- const auto & asn1_resp = transaction_sink.response ();
455-
456- // Update gNB DU F1AP ID in F1AP UE context.
457- ue_ctxt->ue_ids .du_ue_f1ap_id = int_to_gnb_du_ue_f1ap_id (asn1_resp->gnb_du_ue_f1ap_id );
458- logger.debug (" {}: Updated UE gNB-DU-UE-ID" , f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
459-
460- // Fill response to the UE context setup procedure.
461- fill_f1ap_ue_context_setup_response (resp, request.ue_index , transaction_sink.response ());
462-
463- // Create UE RRC context in CU-CP, if required.
464- resp.success = create_ue_rrc_context (resp);
465-
466- return resp;
467- }
468-
469- // Procedure failed.
470-
471- if (transaction_sink.failed ()) {
472- logger.warning (" {}: Procedure failed. Cause: {}" ,
473- f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()},
474- get_cause_str (transaction_sink.failure ()->cause ));
475-
476- // Fill response to the UE context setup procedure.
477- fill_f1ap_ue_context_setup_response (resp, request.ue_index , transaction_sink.failure ());
478-
479- } else {
480- logger.warning (" {}: Procedure failed. Cause: Timeout reached while waiting for DU response." ,
481- f1ap_ue_log_prefix{ue_ctxt->ue_ids , name ()});
482- }
483-
484- // Delete created F1AP UE context.
485- ue_ctxt_list.remove_ue (request.ue_index );
486-
487- return resp;
488- }
0 commit comments