- Replace heap allocation with stack allocation for seq_arr_t structures
- Use proper seq_arr_free() with free functions for ASN.1 structures
- Remove unnecessary malloc/free calls for sequence containers
- Improve memory safety and performance with automatic cleanup
Fixes 128-byte memory leak:
Direct leak of 128 byte(s) in 2 object(s) allocated from:
/#0 0x7e7f39ab4a57 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
/#1 0x56df8b07312d in SEQUENCE_decode_uper /home/guido/repo/openairinterface5g/develop/cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:37
/#2 0x56df8b056551 in uper_decode /home/guido/repo/openairinterface5g/develop/cmake_targets/ran_build/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83
/#3 0x56df8a896b1b in get_nr_mtc /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c:4216
/#4 0x56df8a82feb8 in ue_context_setup_request /home/guido/repo/openairinterface5g/develop/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:635
/#5 0x56df8a66a298 in nr_initiate_handover /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:218
/#6 0x56df8a6720af in nr_rrc_trigger_n2_ho_target /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB_mobility.c:526
/#7 0x56df8a5cf338 in rrc_gNB_process_e1_bearer_context_setup_resp /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:2633
/#8 0x56df8a5d28ab in rrc_gnb_task /home/guido/repo/openairinterface5g/develop/openair2/RRC/NR/rrc_gNB.c:3012
/#9 0x7e7f38494ac2 in start_thread nptl/pthread_create.c:442
- Add early check for existing UE context by AMF UE NGAP ID at beginning of rrc_gNB_process_Handover_Request
- Add dedicated function to get UE context by AMF UE NGAP ID: rrc_gNB_get_ue_context_by_amf_ue_ngap_id()
- Send handover failure with appropriate cause if UE context already exists
- Remove redundant ho_context NULL check that could never be true for newly created UE contexts
- Prevents duplicate handover processing and resource leaks
Add check for cu_exists_f1_ue_data() before calling cu_get_f1_ue_data()
to prevent assertion failure when telnet command 'ci fetch_du_by_ue_id'
is used for UEs that have been handed over via N2 (and no longer have
F1 UE data).
This fixes the crash:
Assertion (ret == HASH_TABLE_OK && data != ((void *)0)) failed!
In get_hashtable_data() /oai-ran/openair2/F1AP/f1ap_ids.c:36
element for ue_id 1 not found
The function now returns NULL gracefully when F1 UE data is not available.
Co-authored-by: Guido Casati <hello@guidocasati.com>
- Add proper cleanup of allocated ASN.1 structures in all return paths
- Fix early returns that were leaking NR_HandoverPreparationInformation
- Fix early returns that were leaking NR_RRCReconfiguration
- Add cleanup at end of successful function execution
This prevents memory leaks when processing handover preparation information
during N2 handover procedures.
- Add UE context cleanup before sending handover failure message
- Prevents memory/resource leak when PDU session establishment fails during handover
- UE context was created but never cleaned up on failure path
This fixes a bug where UE contexts would accumulate over time
when handovers failed after context creation.
- Fixed incorrect log messages that said 'PCI=%lu' when printing nr_cell_id
- Now prints both NR Cell ID and PCI when DU is found
- Provides better debugging information for handover requests
Improvements to RRC PDU session and DRB handling logic
This merge request introduces a major simplification and cleanup of the gNB RRC
PDU Sessions and DRBs handling logic. The core goals of this work are to:
- Replace fixed-size PDU Session, DRBs and QoS arrays with dynamic containers
- Simplify and modularize helper functions for session/DRB management
- Prepare for further refactoring of the PDU Session state machine
- Improve code safety and maintainability through better bounds checking
- Replace simple counter-based DRB ID assignment with actual DRB ID lookup
- Add nested loop to iterate through DRBs for each PDU session to be release
- Improve logic flow with early continue for non-matching PDU sessions
This ensures DRB release list contains correct DRB IDs that correspond to actual DRB entities
* There is no IE corresponding to PDU sessions failed to release
in the PDU SESSION RESOURCE RELEASE RESPONSE message. This was removed
and the corresponding code was refactored and cleaned up.
* In the Release Command handler, only established PDU Session are set to be
released. The Response message is filled accordingly.
Motivation:
The previous architecture had several issues:
- Duplicate DRB generation logic in generateDRB() and generateDRB_ASN1()
- Embedded SDAP/PDCP configs in drb_t created tight coupling
- No clear separation between RRC internal state and ASN.1 encoding
- Maintenance burden due to duplicated configuration logic
New Architecture:
- drb_t now only stores DRB-specific data (ID, PDU session ID, PDCP config)
- SDAP configuration moved to PDU session level (following PDCP design pattern)
- ASN.1 encoding helpers (nr_rrc_build_*_config_ie()) handle conversion
- Single source of truth for DRB creation in RRC via nr_rrc_add_drb()
Key changes:
- Store nr_sdap_configuration_t per PDU session
- Simplified drb_t structure: removed embedded SDAP/PDCP configs, added pdusession_id
- New helper: nr_rrc_build_sdap_config_ie()
- Updated createDRBlist() to use new helper functions and proper DRB ID lookup
- Refactored trigger_bearer_setup() to use nr_rrc_add_drb() and fill_e1_drb_to_setup()
- Removed generateDRB() and generateDRB_ASN1() functions
- Updated set_bearer_context_pdcp_config() to return config by value
- Added SDAP configuration header file for type definitions
This eliminates code duplication, improves maintainability, and creates
a cleaner separation between RRC state management and ASN.1 encoding.
- Move QoS-related enums and structures from ngap_messages_types.h to 5g_platform_types.h
- Replace ngap_* QoS types with generic qos_* types for better reusability
- Update field names from allocation_retention_priority to arp for consistency
- Update all references across RRC and NGAP modules to use new type names
- Remove duplicate QoS type definitions from NGAP-specific header
This improves code organization by centralizing QoS parameter definitions
in a common platform types header and eliminates NGAP-specific naming
in favor of more generic, reusable type definitions.
The maximum number of QoS flows is 64.
- Replace QOSFLOW_MAX_VALUE with MAX_QOS_FLOWS constant
- Move MAX_QOS_FLOWS definition to common/platform_constants.h
- Remove duplicate QOSFLOW_MAX_VALUE definition from ngap_messages_types.h
This improves maintainability by centralizing the QoS flow limit constant
and eliminates duplicate definitions across different header files.
- Limit scope of get_default_rbconfig function: from asn1_msg.c/.h to rrc_gNB_nsa.c where it's used
- Create new rrc_gNB_asn1.c/h files for ASN.1 utility functions: they can be used in other RRC files
- Add nr_rrc_build_pdcp_config_ie function for building PDCP configuration IEs
- Update get_default_rbconfig to use the new PDCP config builder
- Add rrc_gNB_asn1.c to CMakeLists.txt build configuration
The previous DRB management relied on a fixed-size array (established_drbs[MAX_DRBS_PER_UE])
and manual status tracking using DRB_ACTIVE/INACTIVE flags. This approach was inefficient,
and made assumptions about DRB ID allocation that do not generalize well
to dynamic procedures like bearer modification or removal.
* Replace fixed-size array established_drbs[] with dynamic
seq_arr_t *drbs in gNB_RRC_UE_t
* Refactor get_drb() and added nr_rrc_add_drb() with clean abstractions
using find and seq_arr lib
* Updated all DRB-related logic (e.g., generateDRB,
F1AP/E1AP tunnel config, reestablishment, mobility) to use seq_arr.
* Removed status field and DRB_ACTIVE/INACTIVE logic: list presence implies active
* DRB ID allocation now tracked via seq_arr size : simplifies DRB management and
avoids DRB ID–indexed assumptions: code assumed DRB IDs mapped directly to
array indices: established_drbs[drb_id - 1]. This could break when:
DRB IDs are not sequential, DRBs are removed and re-added, or there are gaps in IDs
The RRC PDU Session struct is converted from a fixed-size array
to a dynamically sized seq_arr. This improves flexibility and
simplifies session management by eliminating arbitrary size limits
and enabling dynamic addition/removal of PDU sessions.
Helper functions and loops have been adapted to use the seq_arr API.
This change is a step toward more robust and maintainable handling
of PDU sessions in the gNB RRC layer.
The "status" state machine remains untouched in this commit and
is refactored in a later commit.
Also:
* add macro to push to seq_arr and return the new element
* move initialization of xid (RRC PDU Session struct) to
find_pduSession (temporary, will be finalized in a later
commit) since with the new seq_arr design the initialization
is no longer possible in the UE context generation (also
does not belong to it, initialize when adding a new PDU Session)
- Process all PDU sessions in handover request instead of only the first one
- Add DevAssert for bounds checking on nb_of_pdusessions
- Fix logic error where multiple PDU sessions were ignored in handover scenarios
Previously, the RRC layer was incorrectly allocating stack memory for the ho_required_transfer field and passing it to NGAP, however it was not used. The IE is mandatory but contains only 1 optional IE, therefore is encoded in the NG message with empty content.
Changes:
- Remove unnecessary ho_required_transfer field from pdusession_resource_t definition, the IE is encoded anyway with empty content. If Direct Forwarding Path Availability is needed at any stage in the future it can be added to pdusession_resource_t and filled in RRC.
- Add clarifying comment about empty HandoverRequiredTransfer structure
N2 handover
This MR introduces full support for N2 handover, covering handover
decision, preparation, execution, and notification between source and
target NG-RAN nodes.
Key features:
1. Handover Decision & Preparation:
- Implement N2 handover decision based on UE measurement reports.
- Generate the Handover Preparation Information message, including
RRCReconfiguration.
- Send Handover Required message from the source NG-RAN to the AMF.
2. Handover Execution:
- Decode and handle the Handover Request on the target NG-RAN.
- Process the Handover Command on the source gNB, triggering
RRCReconfiguration.
- Initiate Handover Notify after successful completion.
3 NGAP & RRC Enhancements:
- Implement NGAP encoding/decoding functions for Handover Required,
Handover Request, Handover Command, Handover Failure, and Handover
Notify (3GPP TS 38.413).
- Adds NG-RAN Status Transfer support (UL/DL) for PDCP COUNT
preservation during mobility:
- support for NGAP Uplink and Downlink RAN Status Transfer messages
(TS 38.413 §9.2.3.13-14) to enable proper PDCP COUNT value
transfer during handover or recovery: NGAP encoding/decoding for
RAN Status Transfer, PDCP helpers to extract and apply COUNT (HFN
+ SN) per DRB. This aligns with TS 38.300 §9.2.3.2.1 and TS 23.502
§4.9.1.3.3, ensuring PDCP status preservation in AM.
4. Testing:
- Introduce a Telnet command to manually trigger N2 handover using UE
ID and neighbor PCI.
- Add configuration file for testing N2 handover with a target gNB.
This commit completes the NGAP Mobility Management procedure for N2 handover.
Upon failure on source gNB the Handover Cancel message is sent to the AMF which
in return responds with an ack.
Upon reception of NG RAN Status at the target CU-CP, send PDCP Status
via E1 Bearer Context Modification to the target CU-UP and update PDCP Count
upon reception of the message.
For the sake of simplicity, re-used and extended legacy e1_send_bearer_updates.
Further refactoring is not addressed in this commit.
Once fetched the PDCP Status from the PDCP entity over E1, the CU-CP triggers
the NG RAN Status Transfer procedure to transfer the PDCP Status to the target
CU.
This commit is also introducing the RRC callback.
The E1 Bearer Context Modification Request shall send a PDCP Status Request IE
during handover, e.g. the HO context is set to source, and it is not target, i.e.
only in N2 not in F1.
The current function "e1_send_bearer_updates" used to fill the E1 Request has been
refactored only for the sake of this commit and to avoid duplicated and redundant code.
The function itself deeper analysis and eventually a refactoring that will not be addressed
in this commit.
* the command gets in input the neighbour PCI and the UE ID
* the telnet ci function to retrieve the UE context was extended in the process
* add function to trigger handover on the same gNB for testing purposes
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
* trigger upon reception of MasterKeyUpdate
* derive NH, store NH NCC and valid NH key in RRC
* masterKeyUpdate: derive enc/int keys after master key update
and set PDCP security for SRB1
* call nr_rrc_process_reconfiguration_v1530 before nr_rrc_ue_process_RadioBearerConfig
and move dedicatedNAS_MessageList processing at the end of the flow. The sequence
shall be (1) keys/security update (2) radioBearerConfig processing, with PDCP entity
creation, PDCP reestablishment, SDAP entity creation (3) NAS PDUs processing, which
triggers PDU Session Establishment Accept, which sets up the TUN interface.
SDAP entity is a pre-requisite, therefore the radioBearerConfig has to be processed
(in nr_rrc_ue_process_RadioBearerConfig, add_drb) early enough, or it may cause a
race condition in SDAP.
* add trigger function to (1) add the callbacks and (2) initiate
handover on the target NG-RAN
* add handover failure callback on target NG-RAN: the Handover
Failure is a procedure that belongs to the target NG-RAN and
it is different from the Handover Cancel procedure
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
This commit introduces the NG Mobility Management Procedure known as
Handover Notification. The outbound message is sent by the target NG-RAN
and is known as Handover Notify. The procedure is used to indicate to
the AMF that the UE has arrived to the target cell and the NG-based
handover has been successfully completed
* after RRCReconfiguration complete, in the N2 callback for HO success
* add NGAP encoder for the message
* RRC callback to trigger Handover Notify message
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
* add NG Handover Command message decoder
* process in RRC: encode RRCReconfiguration message
from the received HandoverCommandMessage
* trigger RRCReconfiguration for handover
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
* generate Handover Command for the source NG-RAN
to be added to the target to source transparent
container of the Handover Acknowledge message
* add Handover Acknowledge callback for N2
* send NG Handover Acknowledge to AMF
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
This commit completes the NG Mobility Management Procedure known as
Handover Resource Allocation. The outbound message is sent by the
target NG-RAN and is known as Handover Request Acknowledge.
Major changes:
* add RRC callback to trigger the generation of NG Handover
Request Acknowledge on the target NG-RAN
* add NG Handover Request Acknowledge encoder
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
This commit introduces the NG Mobility Management Procedure known as
Handover Resource Allocation. The inbound message is sent by the AMF
and is known as Handover Request.
Major changes:
(0) Add Handover Resource Allocation initiating message decoding
* add case for NGAP initiating message and unsuccessful message decoding
(1) handle Handover Request on the target NG-RAN
(2) decode NG Handover Request message
(3) process payload, e.g. create UE context,
store IDs, set UP security and trigger bearer setup
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
This message is sent from the Target NG-RAN to the AMF.
The commit introduces:
* NGAP encoding function
* N2 callback for the target gNB
* handle the failure in RRC, inform NGAP
* send NGAP message to AMF via SCTP
Note: UE context in NGAP is fetched from the amf_ue_ngap_id
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
(1) add N2 ho decision based on measurements
(2) add trigger for N2 HO on source CU
(3) generate NG Handover Preparation Information message,
including RRCReconfiguration, to be passed to the
NG Handover Required message
(4) call RRC callback for Handover Required message
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
This commit introduces the NG Mobility Management Procedure known as
Handover Preparation. The outbound message is sent by the source NG-RAN
and is known as Handover Required.
* introduce NGAP library for Mobility Management
* introduce NGAP IEs encoder functions for Handover Required and relevant common IEs
* handle RRC trigger in NGAP and Send NGAP Handover Required to the AMF
Co-authored-by: batuhan duyuler <batuhan.duyuler@firecell.io>
During the N2 HO review has been found that the HO context
was not allocated at trigger time but later in the flow. This
might lead to issues in some scenarios (e.g. in N2 HO)
and it was fixed in this commit.
During the review of the N2 HO MR it has been found that the wrong type
plmn_identity_t (S1AP) was used in RRC. Now updated to the platform type plmn_id_t.