/src/ocudu/lib/rrc/ue/rrc_ue_impl.h
Line | Count | Source |
1 | | // SPDX-FileCopyrightText: Copyright (C) 2021-2026 Software Radio Systems Limited |
2 | | // SPDX-FileCopyrightText: Copyright (C) 2026 OCUDU contributors |
3 | | // SPDX-License-Identifier: BSD-3-Clause-Open-MPI |
4 | | // Portions of this file may implement 3GPP specifications, which may be subject to additional licensing requirements. |
5 | | |
6 | | #pragma once |
7 | | |
8 | | #include "procedures/rrc_ue_event_manager.h" |
9 | | #include "rrc_ue_context.h" |
10 | | #include "rrc_ue_logger.h" |
11 | | #include "ocudu/asn1/rrc_nr/ul_dcch_msg.h" |
12 | | #include "ocudu/asn1/rrc_nr/ul_dcch_msg_ies.h" |
13 | | #include "ocudu/ran/cu_cp_types.h" |
14 | | #include "ocudu/rrc/rrc_cell_context.h" |
15 | | #include "ocudu/rrc/rrc_ue.h" |
16 | | |
17 | | namespace ocudu::ocucp { |
18 | | |
19 | | /// Main UE representation in RRC |
20 | | class rrc_ue_impl final : public rrc_ue_interface, public rrc_ue_controller |
21 | | { |
22 | | public: |
23 | | rrc_ue_impl(rrc_pdu_f1ap_notifier& f1ap_pdu_notifier_, |
24 | | rrc_ue_ngap_notifier& ngap_notifier_, |
25 | | rrc_ue_context_update_notifier& cu_cp_notifier_, |
26 | | rrc_ue_measurement_notifier& measurement_notifier_, |
27 | | rrc_ue_cu_cp_ue_notifier& cu_cp_ue_notifier_, |
28 | | rrc_ue_event_notifier& metrics_notifier_, |
29 | | rrc_ue_srb_pdcp_manager& pdcp_manager_, |
30 | | cu_cp_ue_index_t ue_index_, |
31 | | rnti_t c_rnti_, |
32 | | const rrc_cell_context& cell_, |
33 | | const rrc_ue_cfg_t& cfg_, |
34 | | const byte_buffer& du_to_cu_container_, |
35 | | std::optional<rrc_ue_transfer_context> rrc_context, |
36 | | std::optional<rrc_resume_context_t> remote_resume_context = std::nullopt); |
37 | | ~rrc_ue_impl(); |
38 | | |
39 | | // rrc_ul_pdu_handler |
40 | | void handle_ul_ccch_pdu(byte_buffer pdu, rnti_t c_rnti) override; |
41 | | void handle_ul_dcch_pdu(srb_id_t srb_id, byte_buffer rrc_pdu, bool integrity_verified) override; |
42 | | |
43 | | // rrc_ue_interface |
44 | 0 | rrc_ue_controller& get_controller() override { return *this; } |
45 | 102k | rrc_ul_pdu_handler& get_ul_pdu_handler() override { return *this; } |
46 | 24.8k | rrc_ngap_message_handler& get_rrc_ngap_message_handler() override { return *this; } |
47 | 48.5k | rrc_ue_control_message_handler& get_rrc_ue_control_message_handler() override { return *this; } |
48 | 0 | rrc_ue_context_handler& get_rrc_ue_context_handler() override { return *this; } |
49 | 0 | rrc_ue_capability_handler& get_rrc_ue_capability_handler() override { return *this; } |
50 | | |
51 | | // rrc_ngap_message_handler |
52 | | void handle_dl_nas_transport_message(byte_buffer nas_pdu) override; |
53 | | byte_buffer get_packed_handover_preparation_message() override; |
54 | | |
55 | | // rrc_ue_control_message_handler |
56 | | rrc_ue_security_mode_command_context get_security_mode_command_context() override; |
57 | | async_task<bool> handle_security_mode_complete_expected(uint8_t transaction_id) override; |
58 | | byte_buffer get_packed_ue_capability_rat_container_list() const override; |
59 | | bool verify_reestablishment_short_mac_i(const security::sec_short_mac_i& short_mac_i, |
60 | | pci_t source_pci, |
61 | | rnti_t source_c_rnti, |
62 | | nr_cell_identity target_nci) override; |
63 | | bool verify_resume_mac_i(const security::sec_short_mac_i& resume_mac_i, nr_cell_identity target_nci) override; |
64 | | byte_buffer get_packed_ue_radio_access_cap_info() const override; |
65 | | async_task<bool> handle_rrc_reconfiguration_request(const rrc_reconfiguration_procedure_request& msg) override; |
66 | | rrc_ue_handover_reconfiguration_context |
67 | | get_rrc_ue_handover_reconfiguration_context(const rrc_reconfiguration_procedure_request& request) override; |
68 | | rrc_ue_cond_reconfiguration_context |
69 | | get_rrc_ue_cond_reconfiguration_context(const rrc_reconfiguration_procedure_request& request) override; |
70 | | async_task<bool> handle_handover_reconfiguration_complete_expected(uint8_t transaction_id, |
71 | | std::chrono::milliseconds timeout_ms, |
72 | | bool release_on_failure = true) override; |
73 | | bool store_ue_capabilities(byte_buffer ue_capabilities) override; |
74 | | async_task<bool> handle_rrc_ue_capability_transfer_request(const rrc_ue_capability_transfer_request& msg) override; |
75 | | void fill_ue_derived_location(cu_cp_user_location_info_nr& user_location_info) const override; |
76 | | void request_coarse_ue_location() override; |
77 | | |
78 | | /// Returns the TAC of the configured area holding the coarse position the UE reported, if any. |
79 | | std::optional<tac_t> get_ue_location_derived_tac() const; |
80 | | |
81 | | /// Returns the Mapped Cell ID of the configured area holding the coarse position the UE reported, if any. |
82 | | std::optional<nr_cell_identity> get_ue_mapped_cell_id() const; |
83 | | rrc_ue_release_context |
84 | | get_rrc_ue_release_context(bool requires_rrc_message, |
85 | | std::optional<std::chrono::seconds> release_wait_time = std::nullopt, |
86 | | std::optional<rrc_inactivity_context> inactivity_context = std::nullopt, |
87 | | std::optional<cu_cp_release_redirect_nr_info> redirect_nr_info = std::nullopt) override; |
88 | | rrc_ue_transfer_context get_transfer_context() override; |
89 | | std::optional<rrc_meas_cfg> |
90 | | generate_meas_config(const std::optional<rrc_meas_cfg>& current_meas_config = std::nullopt, |
91 | | bool cond_meas = false, |
92 | | span<const pci_t> candidate_pcis = {}) override; |
93 | | byte_buffer get_packed_meas_config(span<const pci_t> candidate_pcis = {}) override; |
94 | | void update_meas_config(const rrc_meas_cfg& cfg) override; |
95 | 0 | std::optional<rrc_meas_cfg> get_meas_config() override { return context.meas_cfg; } |
96 | | std::optional<byte_buffer> get_packed_location_meas_info() const override; |
97 | | std::optional<uint8_t> get_serving_cell_mo() override; |
98 | | byte_buffer get_rrc_handover_command(const rrc_reconfiguration_procedure_request& request, |
99 | | unsigned transaction_id) override; |
100 | | byte_buffer handle_rrc_handover_command(byte_buffer cmd) override; |
101 | | bool handle_rrc_handover_preparation_info(byte_buffer pdu) override; |
102 | | void create_srb(const srb_creation_message& msg) override; |
103 | | static_vector<srb_id_t, MAX_NOF_SRBS> get_srbs() override; |
104 | 0 | void set_rrc_state(rrc_state state) override { context.state = state; } |
105 | | rrc_state get_rrc_state() const override; |
106 | | void cancel_handover_reconfiguration_transaction(uint8_t transaction_id) override; |
107 | | void cancel_all_transactions() override; |
108 | | |
109 | | // rrc_ue_context_handler |
110 | | rrc_ue_reestablishment_context_response get_context() override; |
111 | | void update_c_rnti(rnti_t crnti) override; |
112 | 0 | rrc_cell_context get_cell_context() const override { return context.cell; } |
113 | | void update_cell_group_config(byte_buffer cell_group_config) override; |
114 | 0 | byte_buffer& get_cell_group_config() override { return context.cell_group_config; } |
115 | | |
116 | | // rrc_ue_capability_handler |
117 | 0 | bool is_rrc_inactive_supported() const override { return context.capabilities.rrc_inactive_supported; } |
118 | | bool is_conditional_handover_supported() const override |
119 | 0 | { |
120 | 0 | return context.capabilities.conditional_handover_supported; |
121 | 0 | } |
122 | | bool is_conditional_handover_two_trigger_events_supported() const override |
123 | 0 | { |
124 | 0 | return context.capabilities.conditional_handover_two_trigger_events_supported; |
125 | 0 | } |
126 | | bool is_conditional_handover_event_a4_supported() const override |
127 | 0 | { |
128 | 0 | return context.capabilities.conditional_handover_event_a4_supported; |
129 | 0 | } |
130 | | bool is_conditional_handover_location_based_supported() const override |
131 | 0 | { |
132 | 0 | return context.capabilities.conditional_handover_location_based_supported; |
133 | 0 | } |
134 | | bool is_conditional_handover_time_based_supported() const override |
135 | 0 | { |
136 | 0 | return context.capabilities.conditional_handover_time_based_supported; |
137 | 0 | } |
138 | | |
139 | | private: |
140 | | void stop() override; |
141 | | |
142 | | // message handlers |
143 | | void handle_pdu(srb_id_t srb_id, byte_buffer rrc_pdu, bool integrity_verified); |
144 | | void handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg); |
145 | | void handle_rrc_reest_request(const asn1::rrc_nr::rrc_reest_request_s& msg); |
146 | | void handle_rrc_resume_request(const asn1::rrc_nr::rrc_resume_request_s& msg, rnti_t c_rnti); |
147 | | void handle_ul_info_transfer(const asn1::rrc_nr::ul_info_transfer_ies_s& ul_info_transfer); |
148 | | void handle_security_mode_complete(const asn1::rrc_nr::security_mode_complete_s& msg); |
149 | | |
150 | | void handle_measurement_report(const asn1::rrc_nr::meas_report_s& msg); |
151 | | void handle_location_measurement_indication(const asn1::rrc_nr::location_meas_ind_s& msg); |
152 | | void handle_rrc_transaction_complete(const asn1::rrc_nr::ul_dcch_msg_s& msg, uint8_t transaction_id_); |
153 | | /// Dispatches the UL-DCCH message class extension, which is where UEInformationResponse lives. |
154 | | void handle_ul_dcch_msg_class_ext(const asn1::rrc_nr::ul_dcch_msg_s& ul_dcch_msg, bool integrity_verified); |
155 | | void cancel_rrc_transaction(uint8_t transaction_id_); |
156 | | |
157 | | // message senders |
158 | | /// Packs a DL-CCCH message and logs the message |
159 | | void send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_ccch_msg); |
160 | | void send_dl_dcch(srb_id_t srb_id, const asn1::rrc_nr::dl_dcch_msg_s& dl_dcch_msg); |
161 | | |
162 | | // rrc_ue_setup_proc_notifier |
163 | | void on_new_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_ccch_msg) override; |
164 | | void on_ue_release_required(const ngap_cause_t& cause) override; |
165 | | |
166 | | // rrc_ue_security_mode_command_proc_notifier |
167 | | void on_new_dl_dcch(srb_id_t srb_id, const asn1::rrc_nr::dl_dcch_msg_s& dl_dcch_msg) override; |
168 | | void on_new_as_security_context(bool security_mode_active) override; |
169 | | void on_as_security_activated() override; |
170 | | |
171 | | // helpers |
172 | | void handle_illegal_pdu_integrity(const char* msg, bool integrity_verified); |
173 | | |
174 | | rrc_ue_logger logger; |
175 | | rrc_ue_context_t context; |
176 | | rrc_pdu_f1ap_notifier& f1ap_pdu_notifier; // PDU notifier to the F1AP |
177 | | rrc_ue_ngap_notifier& ngap_notifier; // notifier to the NGAP |
178 | | rrc_ue_context_update_notifier& cu_cp_notifier; // notifier to the CU-CP |
179 | | rrc_ue_measurement_notifier& measurement_notifier; // cell measurement notifier |
180 | | rrc_ue_cu_cp_ue_notifier& cu_cp_ue_notifier; // cu-cp ue notifier |
181 | | rrc_ue_event_notifier& metrics_notifier; // metrics notifier |
182 | | byte_buffer du_to_cu_container; // initial RRC message from DU to CU |
183 | | |
184 | | // RRC procedures handling |
185 | | std::unique_ptr<rrc_ue_event_manager> event_mng; |
186 | | }; |
187 | | |
188 | | } // namespace ocudu::ocucp |