Integration `2026.w05`
* !3850 Update vrtsim timing job thread
* !3853 Clear memory in shm_td_iq_channel after RX
* !3823 Fix RSRP overflow
* !3766 UE support to send CSI report on PUSCH
* !3848 Initial implementation of O-RU for 7.2 emulator
* !3860 NGAP: improve error handling in RRCReconfiguration from Handover Command decoding
* !3507 Create Debian and Redhat packages with CPack
* !3875 Fix FFT size for xran_fh_tx_send_slot_BySymbol() and xran_fh_rx_read_slot_BySymbol()
* !3593 NR UE: add support for multiple RF frontends
* !3769 Add Ethernet PDU session support and make PDU session request configurable
* !3831 semi-manual remove of not used #define commands
* Update RFsim4G UE configs for RFsim changes after !3593
* !3821 [FHI72] [xran F] Handle fragmented (un)compressed packets
* !3732 Implement TS 38.473 transparency for CellGroupConfig forwarding and handle re-establishment on a different DU
* !3880 Prevent the PNF from sending P7 messages after sending a STOP.indication
* !3868 CI: Upgrade Aerial pipeline to 25-3
* Revert one CI XML change after !3732Closes#1045, #837, and #1043
See merge request oai/openairinterface5g!3877
The CI test proved not as stable as expected (because the UE triggers A3
events which we don't want), so revert this functionality while we work
on a new pipeline.
This reverts commit bc62e8abca.
Prevent the PNF from sending P7 messages after sending a STOP.indication
Upon stopping the PNF, when sending the STOP.indication to the VNF, set
pnf_p7->terminate to 1.
Add a check on the PNF P7 send functions to not send a message after
pnf_p7->terminate is set.
This prevents the PNF from sending SLOT.indications after stopping,
which sometimes was causing the VNF to process a SLOT.indication after
it had received the indication to STOP.
Also, this MR adds a sanity check on the VNF P7 message handler to
ignore any P7 messages it receives after having it's own terminate flag
set to 1
This MR closes issue #1045
[FHI72] [xran F] Handle fragmented (un)compressed packets
In both E and F, the radio-transport fragmentation is not supported, and
all the "fragmented" (not seen as fragments in the xran, only as
sections) packets contain "E-bit" equal to 1. Per spec, the value 1 for
"E-bit" signifies the last fragment of one symbol. For more info, please
see "ecpriSeqid" section in the spec.
In E:
- nRBStart and nRBSize is updated according to the sent/received packet;
- max sections = 1;
- when a packet is fragmented, the xran uses memcpy(pos, iq_data_start,
size) function, and nothing is stored in start_prbu , num_prbu ,...
In F:
- nRBStart and nRBSize is only used for C-plane messages;
- nPrbElm represents the number of sections for DL only;
- based on the nPrbElm, each section contains UP_nRBStart and UP_nRBSize
parameters which represent the start and number of PRBs in one section
or one fragment;
- when a packet is fragmented, the xran uses nSecDesc and sec_desc to
extract the packet section content, and the data is stored in
start_prbu , num_prbu ,...
Previous work on the fragmentation in F:
- #884
- !3394 - only increases the XRAN_MAX_FRAGMENT from 4 to 6, since it was
only tested with BFP 8, but not end-to-end unfortunately. But this MR
fixes all the issues.
Tested with VVDN RU, 2x2, 16 bits, 100MHz, 30kHz, MTU <= 9216 B, and
Quectel UE RM520N-GL Revision: RM520NGLAAR03A03M4G.
Implement TS 38.473 transparency for CellGroupConfig forwarding and handle re-establishment on a different DU
This MR implements the following fixes that are relevant in RRC
procedures (e.g. re-establishment, reconfiguration):
1. Transparent CellGroupConfig forwarding
This MR implements TS 38.473 transparency requirements by ensuring that
the CellGroupConfig IE is transparently forwarded from the gNB-DU to the
UE without any re-encoding at the gNB-CU. The CU stores and forwards the
encoded bytes transparently, while the DU is responsible for all
encoding and modifications (e.g., reestablishRLC flags). Motivation
Motivation: The 3GPP TS 38.473 specification mandates that the
CellGroupConfig IE shall be transparently signaled to the UE.
Previously, the CU was re-encoding CellGroupConfig depending on the
scenario, instead of retrieving it from the DU, violating the
transparency requirement. CU may decode for internal use but must not
re-encode for forwarding. Solution
Solution: Core Principle: The CU stores the encoded CellGroupConfig
bytes received from the DU and forwards them directly to the UE without
any re-encoding. The DU handles all encoding and modifications.
Key Changes:
1. Transparent Forwarding in RRC Reconfiguration
- Modified build_RRCReconfiguration_IEs() to use pre-encoded bytes
directly
- Changed parameter from cell_group_config to cgc (encoded byte
array with buffer and size)
2. Encoded Bytes Storage
- Added byte_array_t mcg field to RRC UE structure to store encoded
CellGroupConfig
- Added store_cgc() helper function to save encoded cell group in
the RRC UE Context at gNB (from F1AP messages)
3. DU Encoding Responsibilities
- Add gNB-DU Configuration Query IE support to trigger cgc encoding
to request CellGroupConfig from DU
- DU encodes CellGroupConfig with proper reestablishRLC flags
during re-establishment
- DU removes SRB1 from rlc-BearerToAddModList during
re-establishment (SRB1 re-establishment is done before
RRCReconfiguration)
4. New functions
- Add rrc_detect_reestablishment() function to detect
re-establishment during UE Context Modification
- Extracted rrc_gNB_first_reconfiguration_after_reestablishment()
function to handle first reconfiguration after re-establishment
- Added dump_cgc() and dump_mcg() utility functions for debugging
purposes
5. Re-establishment Flow
- rrc_gNB_process_RRCReestablishmentComplete() requests
CellGroupConfig from DU via gNB_DU_Configuration_Query in UE
Context Modification Request
- DU detects re-establishment and add reestablishRLC IEs
- CU stores encoded CGC from the UE Context Modification Response
and forwards it transparently in subsequent RRC Reconfiguration
Testing
Manual Testing:
- RRC re-establishment procedure completes successfully
- RRC Reconfiguration after re-establishment includes all DU-provided information
Issues fixed
Closes issue #837
2. Trigger UE Context Setup fallback upon reestablishment on DU
different from the original one
As per 38.401 §8.7: if the UE accesses a DU different from the original
one during re-establishment, the CU must trigger UE Context Setup toward
the new DU. This refers to steps 9-10 and steps 9’-10’. Either one or
the other can be executed during re-establishment.
e.g. if this happens during handover, it shall trigger a UE Context
Setup fallback on the CU.
This MR implements the required behavior by:
- Adding a new helper function rrc_handle_f1_ho_reestab_on_target() to
handle F1 handover reestablishment on target DU. The function triggers
UE Context Setup procedure when the UE reestablishes on the target DU
during an ongoing F1 handover.
- Calling this function when detecting that the UE is reestablishing on
the target DU during handover, i.e.: (1) from
handle_rrcReestablishmentComplete(), as per 38.401 §8.7, NOTE on steps
9-10: CU gets UL RRC MESSAGE TRANSFER from a DU different than the
original (2) from rrc_CU_process_ue_modification_required, as per
38.401 §8.7, NOTE on steps 9'-10': CU gets a UE CONTEXT MODIFICATION
REQUIRED from a DU different from the original one.
Also:
- add helper rrc_fill_f1_ue_context_setup and adopt it in handover
- move DRB list filler fill_drb_to_be_setup into rrc_gNB.c and rename it
rrc_fill_f1_drb_to_setup for consistency
See also TS 38.401 Figure 8.7-1 "RRC connection reestablishment
procedure" for reference
3. DU: Handle missing old UE context in DL RRC Message Transfer
During F1 handover reestablishment, the CU may forward a DL RRC Message
Transfer to the target DU with old_gNB_DU_ue_id included, even though
the target DU does not have the old UE context yet.
The code previously used AssertFatal when the old UE context was not
found, causing a crash: "CU claims we should know UE %04x, but we don't"
According to TS 38.473, the gNB-DU shall release the old gNB-DU UE F1AP ID only:
> if the gNB-DU identifies the UE-associated logical F1-connection If
> there is no matching connection, there is nothing to release.
Fix:
- Check if old UE context exists before accessing it
- If old UE does not exist, log error, clean up any stale F1 UE data,
and return early (do not deliver RRC message since reestablishment
can't be completed)
The goal is to address a recurrent issue in the F1 pipeline, see
jenkins-oai.eurecom.fr/job/RAN-SA-Handover-CN5G/514:
Assertion (oldUE) failed!
In dl_rrc_message_transfer() /oai-ran/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:956
CU claims we should know UE 35ce, but we don't
The sufficient number of fragments needed for MTU 1500 and 8b compression is 6.
However, XRAN_MAX_FRAGMENT must be incremented by one (6+1 = 7).
In the MR https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/3394, XRAN_MAX_FRAGMENT was increased to 6,
but the Tx data was actually copied 5 times, and unfortunately I haven't tested end-to-end back then.
This commit was successfully tested with Liteon FR1.
Even though the jumbo frame has 9600 bytes by the spec, the max MTU is limited to the MTU of a switch, if any used.
However, the value can be < max MTU of a switch.
This is very important for fragmentation purposes. If not properly set, the PDSCH packets will be missing.
- increase requirements for Event A3 trigger to avoid unwanted handovers
and allow testing reestablishment on different DUs
- increase ping_packetloss_threshold from 5 to 30 because we are forcing
a reestablishment, thus, packet loss will inevitably happen
- further adjustments to avoid A3 Events
During F1 handover reestablishment, the CU may forward a DL RRC
Message Transfer to the target DU with old_gNB_DU_ue_id included,
even though the target DU does not have the old UE context yet.
The code previously used AssertFatal when the old UE context was
not found, causing a crash: CU claims we should know UE %04x, but we don't
According to TS 38.473, the gNB-DU shall release the old gNB-DU UE
F1AP ID only "if the gNB-DU identifies the UE-associated logical
F1-connection". If there is no matching connection, there is nothing
to release.
However, the primary purpose of DL RRC MESSAGE TRANSFER is to deliver
the RRC message to the UE. The RRC message delivery is independent of
whether the old UE context can be retrieved. Per TS 38.473, the RRC
message must be delivered to the new UE regardless of old context
retrieval status.
Additionally, per TS 38.331 5.3.7.2 and 5.3.7.4, during reestablishment:
- The UE releases spCellConfig, which must be removed from CellGroupConfig
- SRB1 RLC must be reconfigured with specific parameters
These operations are required for the new UE during reestablishment and
are independent of whether the old UE context can be retrieved.
Fixes:
- Check if old UE context exists before accessing it
- If old UE does not exist, log error and clean up any stale F1 UE data,
but continue to deliver the RRC message
- Restructure code so context transfer only happens when oldUE exists
- Keep GTP-U update and RLC context transfer inside oldUE check (they
require old UE context to exist)
- Move spCellConfig handling and reestablish_rlc flag to execute
regardless during re-establishemnt (per TS 38.331 5.3.7.2)
- Move SRB1 RLC reconfiguration outside the oldUE check so it executes
regardless during re-establishment (per TS 38.331 5.3.7.4)
- Add function documentation and improve spec references in comments
This commit fixes the timing of SRB and DRB PDCP re-establishment
during RRC connection re-establishment to align with 3GPP TS 38.331
specifications.
Key Changes:
1. SRB1 activation and re-establishment (TS 38.331 5.3.7.4):
- Move SRB1 activation to rrc_gNB_generate_RRCReestablishment()
- Use SRB1 constant instead of magic number 1 for clarity
- Remove redundant security configuration loop (handled by
nr_pdcp_reestablishment internally)
2. SRB2 re-establishment (TS 38.331 5.3.5.6.3 SRB addition/modification):
- Move SRB2 PDCP re-establishment from rrc_gNB_process_RRCReestablishmentComplete()
to rrc_gNB_generate_dedicatedRRCReconfiguration(): per spec: SRB2
should be re-established in the first RRCReconfiguration after
re-establishment (with reestablishPDCP=true flag)
3. DRB re-establishment (TS 38.331 5.3.5.6.5 DRB addition/modification):
- Move cuup_notify_reestablishment() from rrc_gNB_process_RRCReestablishmentComplete()
to rrc_gNB_generate_dedicatedRRCReconfiguration(). e.g at the first
reconfiguration after reestablishment
- Ensures CU-UP is notified at the correct time
As per TS 38.401 §8.7: if the UE accesses a DU different from the original
one during re-establishment, the CU must trigger UE Context Setup toward
the new DU. This refers to steps 9-10 and steps 9'-10'. Either one or the
other can be executed during re-establishment.
e.g. if this happens during F1 handover, it shall trigger a
UE Context Setup fallback on the CU.
This commit implements the required behavior:
1. Detection mechanism:
- Add `old_du_assoc_id` field to `f1_ue_data_t` to store the original
DU association ID
- At RRCReestablishmentRequest: Store original `du_assoc_id` in
`old_du_assoc_id` and update `du_assoc_id` to the new DU
- At RRCReestablishmentComplete: Compare `old_du_assoc_id` with the
`assoc_id` from the Complete message to detect different DU
2. UE Context Setup trigger:
- In `rrc_gNB_process_RRCReestablishmentComplete()`: When different DU
is detected, call `rrc_f1_ue_context_setup_for_target_du()` to trigger
UE Context Setup procedure (per TS 38.401 §8.7, NOTE on steps 9-10)
upon reception of UL RRC MESSAGE TRANSFER
- In `rrc_CU_process_ue_modification_required()`: Refuse UE Context
Modification Required when `old_du_assoc_id != 0` to avoid conflicts
with the ongoing UE Context Setup procedure (per TS 38.401 §8.7, NOTE
on steps 9'-10')
3. UE Context Setup:
- Replace `clone_CellGroupConfig()` with `get_cellgroup_config()` in
UE Context Setup handler
- Call `update_cellgroup_for_reestablishment()` during UE Context Setup
when `reestablish_rlc` flag is set to prepare CellGroupConfig with
reestablishRLC flags
- Clean up `old_du_assoc_id` in `rrc_CU_process_ue_context_setup_response()`
- Add `free_ue_context_mod_req()` call after UE Context Modification request
4. Function signature updates:
- Update `handle_rrcReestablishmentComplete()` to accept `gNB_DU_ue_id`
and `assoc_id` parameters, change return type from `int` to `void`
- Update `rrc_gNB_process_RRCReestablishmentComplete()` to accept
`assoc_id` parameter
- Update `rrc_gNB_decode_dcch()` to accept and forward `assoc_id` parameter
Re-establishment on different DU flow (TS 38.401 §8.7, steps 9-10):
1. UE sends RRCReestablishmentRequest to new DU
2. DU forwards to CU via UL RRC MESSAGE TRANSFER
3. CU detects different DU (`assoc_id != ue_data.du_assoc_id`):
- Stores `old_du_assoc_id = ue_data.du_assoc_id` (original DU)
- Updates `ue_data.du_assoc_id = assoc_id` (new DU)
4. CU sends RRCReestablishment to UE
5. UE sends RRCReestablishmentComplete to new DU
6. DU forwards to CU via UL RRC MESSAGE TRANSFER
7. CU detects different DU scenario (with old_du_assoc_id):
- Triggers UE Context Setup Request to new DU via `rrc_f1_ue_context_setup_for_target_du()`
8. DU receives UE Context Setup Request:
- Detects re-establishment (`UE->reestablish_rlc` flag)
- Calls `update_cellgroup_for_reestablishment()` to set reestablishRLC flags
- Encodes CellGroupConfig with reestablishRLC flags and sends to CU
9. CU receives UE Context Setup Response:
- Stores encoded CellGroupConfig
- Clears `old_du_assoc_id = 0`
10. CU sends RRC Reconfiguration with transparent CellGroupConfig to UE
This commit implements transparent forwarding of CellGroupConfig
as required by TS 38.473, eliminating CU-side decode/re-encode
cycles that violate transparency requirements.
Main Design Change:
- Before: CU decoded CellGroupConfig from DU, stored in the UE
context then re-encoded when sending to UE. CU constructed
new CellGroupConfig after RRCReestablishmentComplete.
- After: CU requests CellGroupConfig from DU via UE Context Modification
Request with `gNB_DU_Configuration_Query=true`, DU sends CellGroupConfig
which CU stores as encoded `byte_array_t` and forwards transparently
via reconfiguration without decode/re-encode cycles
To this purpose, all decode operations of CellGroupConfig were removed
from DU and all encode operations were removed from the CU.
Key Changes:
CU:
- Replace NR_CellGroupConfig_t* masterCellGroup with byte_array_t mcg in
gNB_RRC_UE_t for storing encoded CellGroupConfig
- Rename cell_group_config to cgc in nr_rrc_reconfig_param_t for brevity
- Implement transparent forwarding in build_RRCReconfiguration_IEs()
- Add helper functions:
- `store_cgc()` to store encoded bytes
- `get_meas_gap_config()`: Decode MeasGapConfig from DU to CU response
- `rrc_detect_reestablishment()` to detect re-establishment by decoding
temporarily (only for detection)
- Remove legacy decode/re-encode paths in RRC message generation
- Update all CellGroupConfig storage to use encoded bytes
- Update reconfiguration generation to accept is_reestablishment parameter
DU:
- Add `get_cellgroup_config()` to select source (CellGroup vs reconfigCellGroup)
based on re-establishment state
- Add re-establishment detection logic in `ue_context_modification_request()`
- Add `update_cellgroup_for_reestablishment()` to set reestablishRLC flags and
remove SRB1 from bearer list
- When `gNB_DU_Configuration_Query` is present and re-establishment detected:
- Clones from reconfigCellGroup (which contains spCellConfig) instead of
CellGroup (where spCellConfig was removed)
- Sets `reestablishRLC` flags for all bearers except SRB1
- Removes SRB1 from bearer list (already re-established)
Data Structure Changes:
- gNB_RRC_UE_t: Add byte_array_t mcg field
- nr_rrc_reconfig_param_t: Change cell_group_config to cgc (byte_array_t*)
- Remove masterCellGroup field usage in favor of encoded mcg
New re-establishment flow:
1. UE sends RRCReestablishmentRequest
2. CU processes -> sends RRCReestablishment
3. CU sends RRCReestablishmentComplete
4. CU sends UE Context Modification Request to DU with `gNB_DU_Configuration_Query=true`
5. DU detects re-establishment (`UE->reestablish_rlc && UE->reconfigCellGroup != NULL`):
- Clones `UE->reconfigCellGroup` -> `new_CellGroup` (contains spCellConfig)
- Sets `reestablishRLC` flags for all bearers except SRB1
- Removes SRB1 from bearer list (already re-established)
- Encodes `new_CellGroup` and sends to CU
6. CU receives encoded CellGroupConfig -> stores in `UE->mcg` via `store_cgc()`
7. CU detects re-establishment via `rrc_detect_reestablishment()`
8. CU calls `rrc_gNB_generate_dedicatedRRCReconfiguration()` with `is_reestablishment=true`:
- Creates SRB/DRB lists with re-establishment flags
- Generates RRC Reconfiguration with transparent CellGroupConfig
- Sends to UE
Why spCellConfig must be added in the DU in case of re-establishment:
With transparent forwarding, CU requests CellGroupConfig from DU instead
of constructing it. During re-establishment, DU's runtime CellGroup has
spCellConfig = NULL (removed per TS 38.331 §5.3.7.2). However, for the
gNB_DU_Configuration_Query response, DU must provide a complete CellGroupConfig
including spCellConfig. Therefore, DU restores spCellConfig by encoding
reconfigCellGroup (with the original spCellConfig) in CellGroupConfig.
In the old design CU constructed CellGroupConfig itself in
`rrc_gNB_process_RRCReestablishmentComplete()` and used `spCellConfig`
from its stored `masterCellGroup`.
Closes#837
Apply CGC encoding through GNB-DU Configuration Query. This applies to the
pdu session release path (rrc_gNB_send_f1_drb_release_request) and E1 bearer
mod / DRB add+release path (rrc_gNB_generate_UeContextModificationRequest).
This is necessary to implement 3GPP TS 38.473 requirement for
gNB-DU Configuration Query IE in UE Context Modification Request:
"If the GNB-DU Configuration Query IE is contained in the UE CONTEXT
MODIFICATION REQUEST message, gNB-DU shall include the CellGroupConfig
IE in the DU To CU RRC Information IE in the UE CONTEXT MODIFICATION
RESPONSE message."
i.e.: The DU sends the CGC only when this IE is enabled in the REQ
message from the CU. The only other scenario according to the same
specs is when the Full Configuration IE is present. Outside of these
two cases, CGC shall not be sent.
This field will be adopted to trigger cgc encoding at DU,
according to the specs (see subsequent commit for details).
Changes:
- Add gNB_DU_Configuration_Query field to f1ap_ue_context_mod_req_t
- Implement encoding/decoding
- Add to cp, eq, and free functions for the new field
- Update tests to include the new field
Issue: sometimes it happens that an ul failure occurs in the handover
pipeline, UE reconnects with different UE ID and fetch_du_by_ue_id fails.
- Modified fetch_du_by_ue_id in telnetsrv_ci.c to automatically find
the connected UE when no UE ID is provided, similar to other
telnet commands like rrc_gNB_trigger_f1_ho
- Updated test cases in container_sa_f1_ho_b210_quectel.xml to use
the improved command without hardcoded UE ID parameter
- This makes the command more robust and easier to use in CI tests
Add debugging utilities dump_cgc() and dump_mcg() to decode and
print CellGroupConfig in XER format when DEBUG_ASN1 flag is enabled.
This helps debug RRC Reconfiguration messages containing masterCellGroup.
Add intermediate fallback to rrc_gNB_get_ue_context_by_rnti_any_du() in
re-establishment request handling to better handle cases where UE
re-establishes on a different DU.
RNTI is NOT globally unique - different DUs can assign the same RNTI to
different UEs. The assoc_id check in rrc_gNB_get_ue_context_by_rnti()
disambiguates RNTI across DUs and prevents returning the wrong UE.
However, during re-establishment on a different DU, du_assoc_id hasn't
been updated yet (message comes from new DU, but ue_data.du_assoc_id
still points to old DU), causing the primary lookup to fail even though
the UE exists.
The lookup now uses a three-tier fallback:
1. Primary: rrc_gNB_get_ue_context_by_rnti() with assoc_id check
(normal case: same DU)
2. Fallback 1: rrc_gNB_get_ue_context_by_rnti_any_du() by RNTI only
(re-establishment on different DU)
3. Fallback 2: rrc_gNB_get_ue_context_source_cell() using physCellId
(handover scenarios)
- Remove unused masterCellGroup_from_DU parameter from rrc_gNB_generate_RRCReestablishment() as it is not used in the RRC
re-establishment generation, RRCReestablishment message does not contain CellGroupConfig which is obtained later via UE Context Modification Request/Response
- Update function documentation
- Initialize security_parameters struct to zero for safety
- Add check on ciphering and integrity algorithm ranges
When a UE re-establishes on a different DU, the physCellId in the
re-establishment request (from the old cell) will differ from the
new DU's physCellId. The previous check incorrectly treated this as
a "too fast movement" scenario and triggered fallback to RRC setup.
This fix distinguishes between two scenarios:
1. Different DU scenario: physCellId differs because UE is on a
different DU - this is legitimate and should be allowed. UE
Context Setup will be triggered at RRCReestablishmentComplete.
2. Same DU but different physCellId: "too fast movement" scenario
- fallback to RRC setup as before.
The fix checks if assoc_id != ue_data.du_assoc_id to detect a
different DU scenario and allows re-establishment in that case.
This addresses the issue where re-establishment on a different DU
was incorrectly rejected, preventing proper UE Context Setup per
TS 38.401 Section 8.7.
Handle target DU UE context setup when handover preparation info
is unavailable (i.e. re-establishment scenario) by retrieving
secondary UE ID from F1 UE data.
rrc_f1_ue_context_setup_for_target_du is either applying to
handover or re-establishment. In the latter scenario, populate
DU UE ID, which should be known.
semi-manual remove of not used #define commands
As i was upset to see all these #define with no code under, i made a
global pass to remove the obvious cases semi-manual remove of not used
bodies
manual script, then a lot of manual review
grep -IRs "#define" ../openair* ../common/* ../executables/ ../nfapi/ ../radio/ | \
fgrep -v '(' | fgrep -v '//' |awk '{print $2}' | egrep -v "#define *$n"| \
while read n ; do
grep -IRs $n ../openair* ../common/* ../executables/ ../nfapi/ ../radio/ | grep -v "#define *$n" | grep -q $n || echo $n;
done
will give a decent list of #define never used. Then, I think we should
keep lists of # define when it comes from standards, even if the code
doesn't use it right now
Add Ethernet PDU session support and make PDU session request configurable
This MR adds support for Ethernet PDU sessions, and makes PDU sessions
configurable: per-PDU session ID, type (IPv4/IPv4v6/IPv6/Ethernet [1]),
DNN, NSSAI.
Concretely, it adds a new configuration file section pdu_sessions below
uicc0 that looks like this if everything is specified (default values
are shown):
uicc0:
[...]
pdu_sessions:
- id: 1
type: "IPv4"
nssai_sst: 1
nssai_sd: 0xffffff
dnn: "oai"
It is possible to list multiple PDU sessions (add new line - id: 2 to
request a second PDU session). It is backwards-compatible to the current
PDU session configuration (uicc0.dnn/nssai_sst/etc), the idea being that
either legacy or new configuration could be used, but (1) if
pdu_sessions exist, it will overwrite the legacy configuration, and (2)
multiple PDU sessions, and type, can only be configured using the new
config. The old parameters --extra-pdu-id and --default-pdu-id are not
accepted anymore. Documentation has been added to the UE tutorial.
It is possible to test an Ethernet PDU session [1]. It is possible to
test the PDU session inside the UE by verifying it has an TAP interface
oaitap_ue1, and ARPing the data network (arping has been added to
oai-nr-ue container for that purpose):
ip addr add 192.168.72.140/26 dev oaitap_ue1 # same subnet as data network!
ip link set dev oaitap_ue1 up
arping -c 20 -I oaitap_ue1 192.168.72.135 # will send ARP request in Ethernet frame to get IP address of data network
[1] See description MR !3769 for more information. On the UE side, only
the type has to be changed to "Ethernet".
NR UE: add support for multiple RF frontends
This MR adds basic support for multiple RF-frontends at the UE.
There are multiple reasons why we might want this:
1. There might be different antennas needed for different bands (e.g. NTN or
TN antennas). These antennas might be connected to different RF-frontends.
In case of Handover, the UE needs to dynamically switch between these
RF-frontends.
2. Each rf-simulator connection carries baseband I/Q samples. To be able to
perform a handover between two cells at different frequencies, there must
be two rf-simulator connections, as the baseband channels should not
interfere and thus cannot simply be added.
3. When we want to support multiple UE simulation within one instance of
nr-uesoftmodem, and allow multiple cells and probably even handover between
these cells, we need either:
1. dedicated RF-frontends for each simulated UE, or
2. dedicated RF-frontends for each connected cell and dynamically assign
simulated UEs accordingly.
This MR implements what is needed for 1., 2. and 3.1.
Fix FFT size for xran_fh_tx_send_slot_BySymbol() and xran_fh_rx_read_slot_BySymbol()
This MR handles
- Fix FFT size for xran_fh_tx_send_slot_BySymbol() and
xran_fh_rx_read_slot_BySymbol() (!3809)
- Fix E release build
Create Debian and Redhat packages with CPack
Use CPack in CMakelists in order to create packages, creation command is
available in build_oai script and options description is available in
packages.md
Upon stopping the PNF, when sending the STOP.indication to the VNF, set pnf_p7->terminate to 1.
Add a check on the PNF P7 send functions to not send a message after pnf_p7->terminate is set
Even after this commit, we still have duplicated UL C-plane packets due to xran F release internal architecture.
Note: in E, all PRBs were in one section of one C-plane DL and UL. It is working even though the U-plane has "fragmented" packets.
Co-authored-by: Mario Joa-Ng <mario.joa-ng@openairinterface.com>
Previously, in F, only the following (subframe, slot, symbol) combinations were sent every frame:
(0, 0, 0)
(2, 1, 0)
(5, 0, 0)
(7, 1, 0)
Now, all the DL symbols are sent.
Notes:
In both E and F, the radio-transport fragmentation is not supported, and
all the "fragmented" (not seen as fragments in the xran, only as sections)
packets contain "E-bit" equal to 1.
Per spec, the value 1 for "E-bit" signifies the last fragment of one symbol.
For more info, please see "ecpriSeqid" section in the spec.
In E:
- nRBStart and nRBSize is updated according to the sent/received packet;
- max sections = 1.
In F:
- nRBStart and nRBSize is only used for C-plane messages;
- nPrbElm represents the number of sections for DL only;
- based on the nPrbElm, each section contains UP_nRBStart and UP_nRBSize parameters
which represent the start and number of PRBs in one section or one fragment.
Co-authored-by: Mario Joa-Ng <mario.joa-ng@openairinterface.com>
Packages must have a name, a version, a section, an architecture, a maintainer, a description (long and summary), dependencies
Shared libraries must be stripped, have soversion, version (debug symbols are found in separate packages), since MODULE is used instead of SHARED it works as a plugin library which is opened using dlopen-like functionality, see: https://cmake.org/cmake/help/latest/command/add_library.html
Packages must have postin and postun scripts
Since it is not recommended to modify CMAKE_EXE_LINKER_FLAGS, cmake's path variables are used : https://discourse.cmake.org/t/how-do-i-replace-the-compiler-options-for-one-target/7815/5
NGAP: improve error handling in RRCReconfiguration from Handover Command decoding
This MR refactors doRRCReconfiguration_from_HandoverCommand for consistency and
safety, and enables NGAP Handover Cancel encoding/decoding.
- Refactored doRRCReconfiguration_from_HandoverCommand function:
- Changed signature to return byte_array_t instead of taking a buffer parameter
- Prevents buffer overflow by auto-sizing memory with uper_encode_to_new_buffer
- Input validation
- HandoverCommand structure validation
- Error handling and cleanup for encode/decode failures
- ASN.1 structure cleanup on all error paths
- Updated caller in rrc_gNB_NGAP.c: use new byte_array_t return signature,
added buffer cleanup with free_byte_array(), sends Handover Cancel to AMF on
decoding failure (source gNB)
- Improved error logging
- NGAP Handover Cancel encoding/decoding support
- Added missing Handover Cancel ack case handler for
NGAP_ProcedureCode_id_HandoverCancel in ngap_gNB_decode_initiating_message()
to decode and log incoming Handover Cancel Ack message
- Added NGAP_ProcedureCode_id_HandoverCancel to the list of supported
initiating message procedure codes in ngap_gNB_encode_initiating() allowing
the gNB to encode and send Handover Cancel messages
Note: The Handover Cancel procedure is already implemented elsewhere in the NGAP
stack; these changes complete support by ensuring the procedure code is
recognized in both encoder and decoder.
Closes#1043
The CN team would like to test the ethernet PDU session capabilities of
the UPF. Install arping in the UE by default for ubuntu to help them
test the PDU session by pinging over ARP.
Look up the index of a PDU session in the list of PDU sessions upon
accept to determine if the PDU session is the default (first PDU
session) or not. If it is the default, it will not append a suffix to
the interface name (oaitun_ueY), otherwise append the PDU session ID
(e.g., for 5: oaitun_ueYp5).
Use the new PDU session configuration functionality of the parent
commit. It is now possible to request multiple PDU sessions, and to
request specific PDU session types. While the new uicc0.pdu_sessions is
preferred, it is still possible to use the "legacy"
uicc0.dnn/nssai_sst/nssai_sd.
The old parameters --default-pdu-id and --extra-pdu-id are not allowed
anymore, as it is possible to manually define this in the UE
configuration. Correspondingly, fix the use of those options, where
applicable.
Note: since the default_pdu_id is changed to -1, all interface names
will have pX to interface names appended (oaitun_ue1pX). The next commit
will correct this.
When writing dummy data or reading to trash, we don't need to allocate data buffers for each antenna.
We can allocate just for one antenna and use this buffer for each antenna.
This feature shall allow in future to simulate an arbitratry number of UEs connected to an other arbitrary number of cells.
Therefore each RF-frontend (also called RU) needs to be configured for one specific cell.
In case of handover of a UE from one cell to another cell, it needs to switch RUs accordingly (TODO).
There has to be a 1-to-1 mapping between RUs and cells.
Each UE will be assigned to one of the defined cells.
Initially all UEs are assigned to cell 0.
UE support to send CSI report on PUSCH
Earlier work on UCI on PUSCH implemented only ACK/NACK. This MR extends that
to send CSI report too.
This branch is verified with MATLAB implementation for multiplexing CSI part 1
and part 2 on PUSCH. It is also verified with srsRAN gNB which successfully
decodes CSI part 1 on PUSCH.
Fix RSRP overflow
If UE L1 measure an RSRP = 0 it would report to L2 and RSRP value of -INT_MAX
dBm causing overflow in the qsort to determine the best RSRPs
The global variable rx_gain_off was always 0.0, as it was not even modified by the NR UE command line parameter --ue-rxgain-off.
That command line parameter modified only a parameter in the struct nrUE_params_t, which was not used at all and is removed in this commit, too.
Also, the global variable rx_gain_off was just added to rx_total_gain_dB and subtracted from it again in nr_rf_card_config_gain().
So we simplify that function slightly, too.
Clear memory in shm_td_iq_channel after RX
Clear memory in shm_td_iq_channel after RX. This prevents the IQ
from being read twice. This can happen if the application crashes
and will keep the other side reading historical IQ samples.
Update vrtsim timing job thread
List of changes:
- avoid calculating accumulated rounding error by calculating absolute
sample index based on CLOCK_REALTIME every time.
- use threadCreate instead of plain pthread_create which assigns a unique
thread name and simplifies debugging
Use nr_get_csi_measurements() function to get CSI report for PUCCH and
UCI on PUSCH.
Harmonize filling csi report for UCI on PUSCH for periodic and aperiodic
CSI reports.
Extract the common RRC container handling logic from
ue_context_setup_request() and ue_context_modification_request() into
a new static function handle_ue_context_rrc_container().
This refactoring:
- Eliminates code duplication between the two functions
- Centralizes RRC container forwarding logic
- Improves code maintainability and consistency
Extract common CellGroupConfig encoding logic from
ue_context_setup_request() and ue_context_modification_request() into
encode_cellgroup_config().
Replace uper_encode_to_buffer() with uper_encode_to_new_buffer() to:
- Remove 1024-byte buffer size limit
- Automatically allocate correct buffer size
- Simplify code (no manual bit-to-byte conversion)
- Align with other protocol encoders
- Add function documentation blocks for `rrc_fill_f1_ue_context_setup`,
`rrc_f1_ue_context_setup_for_target_du`, and `rrc_f1_ue_context_setup_from_e1_response`
explaining their purpose, parameters, and usage scenarios
- Add inline comments throughout these functions
Improve maintainability by centralizing common F1AP UE context setup
logic into reusable helper functions, enabling consistent handling
and clear serving/target DU entry points for different scenarios.
Code duplication prevention is a beneficial side effect, since at
least one helper function is adopted in subsequent commits.
Major changes:
- Move DRB list filler from external file into rrc_gNB.c and rename
fill_drb_to_be_setup to rrc_fill_f1_drb_to_setup for naming
consistency
- Add static helper rrc_fill_f1_ue_context_setup to populate common
fields shared between serving DU and target DU scenarios:
- Rename rrc_gNB_generate_UeContextSetupRequest to
rrc_f1_ue_context_setup_from_e1_response to clarify it prepares
F1AP context setup from E1AP bearer setup response for serving DU
- Add rrc_f1_ue_context_setup_for_target_du (for target DU in
handover/reestablishment scenarios)
- Adopt helper rrc_fill_f1_ue_context_setup in both functions
When processing UL RRC messages from PDCP, the DU association ID (assoc_id)
was not being propagated to RRC, resulting in assoc_id being 0 in
rrc_gNB_decode_dcch.
Fix by setting originInstance in the ITTI message header to the stored
du_assoc_id from ue_data when PDCP creates the F1AP_UL_RRC_MESSAGE.
Integration `2026.w04`
* !3787 CI: disable aerial x86 build pipeline
* !3820 Integrate F1AP messages required for NRPPa
* !3789 fix A3 event configuration
* !3861 add a csv T tracer
* !3669 NR UE: add neighboring cell measurements and measurement report of event A3
* !3866 nr-softmodem: ensure RU is ready before L1 init in NFAPI PNF mode
* !3402 Test FDM PRACH in CI
* !3852 Cleanup nr_slot_fep_ul
* !3782 Improvements to support CSET0 multiplexing pattern 3 for FR2
* !3862 Check for PDSCH overlapping CORESET during RA
* !3430 NR gNB handling TCI state indication for beam switching
* !3872 Fix compilation issues with vrtsim taps client
* !3687 Standardize Documentation Formatting and Navigation for MkDocs
Closes#705
See merge request oai/openairinterface5g!3867
Standardize Documentation Formatting and Navigation for MkDocs
This merge request improves and organizes the documentation to align with MkDocs
requirements. The following guidelines have been applied:
Guidelines Followed
Fix Broken Links and Paths
- Updated all links with proper paths to ensure correct rendering in MkDocs.
Correct Headings
- Removed multiple H1 headings (#).
- Subheadings use H2–H6 (## to ######) for consistent structure.
Proper URL Formatting
- All URLs now follow standard Markdown syntax,
e.g., [Example](https://www.example.com).
Proper Syntax
- Tables, lists, and code blocks use standard Markdown formatting to ensure
correct rendering.
Remove HTML Formatting
- Removed unnecessary inline HTML styling from documents, retaining only the
content.
Notes and Warnings
- Converted notes and warnings into blockquote syntax (>).
This ensures the documentation is properly structured, consistent, and
MkDocs-friendly.
- Include functions/file_names in backticks for readability
- Include the images directly inside the document (rather than plain image file name)
- Give relevant spacing if required
- Remove multiple single top-level (# H1) headings per file
- Use (# H2 and ###### H6) sub-headings for consistency
- Remove any trailing # in the headings
- This ensures proper table of contents rendering in MkDocs.
- Also removed RUN_NR_multiple_BWPs.md as it is moved to MAC usage
- bold current status for clarity and add spacing for better readability
- Wrap processes in the test setup block inside code blocks as they were rendered as GitLab issues
- Remove extra spacing in the test setup block
- Give a line in between bullet points to reflect bullet points correctly
- Split long statement into bullet points for readability
- Format the document for proper rendering
- Fix table formatting
- Use standard TOC syntax in 5GNAS
- The parser was incorrectly interpreting `</` as the start of an HTML closing tag, leading to a crash in mkdocs
- Replace with HTML entity to ensure it is treated as a plain text.
NR gNB handling TCI state indication for beam switching
This MR implements the procedure to send in DLSCH MAC-CE for TCI state
indication to UE
- if new beam is reported via SSB RSRP, gNB allocates MAC-CE with TCI
indication
- DLSCH is scheduled to be transmitted with priority
- a timer is started when receiving ACK according to the delay mandated
by standard (8.10.3 of 38.133)
- at timer expiry the gNB switches beam
Check for PDSCH overlapping CORESET during RA
CORESET 0 is configured in the configuration file by
'initialDLBWPcontrolResourceSetZero' and PDSCH TDA list is configured based on
the current BWP size.
It may happen that the user configures a 2 symbol CORESET 0 for a BWP >= 48 PRBs
(which is a valid 3GPP configuration) but in function 'nr_rrc_config_dl_tda'
this scenario is not taken in account causing an overlap between PDSCH and PDCCH
symbols during RA.
This leads to very unreliable Msg2 and Msg4 decoding at the UE, but from time to
time it succeeds, which becomes hard to identify this issue.
closes#705
Fix two issues regarding vrtsims taps client implementation:
- Incorrect #define used to enable taps socket handling
- flatbuffers package name changing between ubuntu versions
Cleanup nr_slot_fep_ul
Rename nr_slot_fep_ul to nr_symbol_fep_ul to relfect its function
Simplify logic so that the function does not require RU context and
the implementation is not dependent on the implementation of RU buffer
management.
This makes the function easier to understand and moves the responsibility
to set the correct buffer offset on the caller.
nr-softmodem: ensure RU is ready before L1 init in NFAPI PNF mode
PROBLEM: In PNF mode, L1 is started from nfapi_pnf.c without verifying RU
readiness. The only gate is config_sync_var, but nr_softmodem.c sets this before
the RU (e.g., FHI-72) is actually started. As a result, START_REQUEST can
trigger L1 init while the RU is not yet ready -- this is an issue when using
FHI72 with DPDK BBDEV, where a pre-mature L1 init will crash the entire program
as DPDK BBDEV depends on xRAN's DPDK EAL. Note that this issue is more like a
"race" condition, so it may not always manifest, and happens at random.
FIX: Perform RU readiness checks before setting config_sync_var in NFAPI PNF mode.
This aligns PNF behavior with other modes and prevents L1 from starting before the
RU is operational.
SSB position in burst is set to 2 so only SSB index 1 is transmitted.
prach_msg1_FDM is set to 1 so there are two occasions per time slot.
All the UE connecting to gNB will receive SSB index 1 and trigger PRACH
in the second FDM prach occasion.
FHI 7.2 does not have a field for the number of RACH Occasions.
It seems this needs to be manually configured, and M plane has field
num-prach-re to set the number of frequency domain PRACH occasions.
Rename nr_slot_fep_ul to nr_symbol_fep_ul to relfect its function
Simplify logic so that the function does not require RU context and
the implementation is not dependent on the implementation of RU buffer management.
This makes the function easier to understand and moves the responsibility
to set the correct buffer offset on the caller.
Modify all functions to also handle TAP (where applicable). The actual
TAP interface code is not used in this commit, it will be used later.
To make the interface creation stand out, make "Interface XXX
successfully configured" a LOG_A.
Simplify interface handling by storing the name: this allows to simplify
to remove_ip_if(), which does not need to recreate a valid name, and
will simplify handling of ethernet PDU sessions with a possibly
different name.
Defacto, the PDU session ID for noS1 modes is already hardcoded, as
starting the nr-softmodem with --noS1 --default-pdu-id 1 leads to
Assertion (entity != ((void *)0)) failed!
In start_sdap_tun_gnb_first_ue_default_pdu_session() openair2/SDAP/nr_sdap/nr_sdap.c:163
Further, the --default-pdu-id parameter will be deactivated in a later
commit, and we cannot rely on it. Therefore:
- hardcode noS1 PDU ID (also used in --do-ra/--phy-test modes) to 10 and
use in gNB&UE
- pass the PDU session ID used in SDAP entity initialization down to
start_sdap_tun_gnb_first_ue_default_pdu_session() to always use the
correct one
For configuring a TAP interface, we need to set different options, which
is not easily feasible with the current change_interface_state() API (or
would make it more complex). To simplify while allowing to set flags
more flexibly, separate into two functions get/set_if_flags().
PROBLEM: In PNF mode, L1 is started from nfapi_pnf.c without verifying RU
readiness. The only gate is config_sync_var, but nr_softmodem.c sets this before
the RU (e.g., FHI-72) is actually started. As a result, START_REQUEST can
trigger L1 init while the RU is not yet ready -- this is an issue when using
FHI72 with DPDK BBDEV, where a pre-mature L1 init will crash the entire program
as DPDK BBDEV depends on xRAN's DPDK EAL.
FIX: Perform RU readiness checks before setting config_sync_var in NFAPI PNF mode.
This aligns PNF behavior with other modes and prevents L1 from starting before the
RU is operational.
NR UE: add neighboring cell measurements and measurement report of event A3
This is a rework of MR !2385 (closed), the goal is to add neighboring cell
measurements and measurement report of event A3 for NR UE.
This MR was tested with:
- 3rd-party gNB
- 2 OAI-gNB-DUs
The neighboring cell measurements and measurement report of event A3 for OAI-UE
are working as expected.
fix A3 event configuration
See commit message for more information.
As a reference, for comparison purpose, PCAPs and TXT files for various tests
done in develop and in this MR are available in the MR description.
Integrate F1AP messages required for NRPPa
This MR is one of the several MRs that will follow in the integration of NRPPa
protocol (!2437) required for positioning in 5G NR. We specifically introduce
encoding and decoding of several F1AP messages including unit tests for
verification in this MR.
The details of the F1AP messages introduced here can be seen below:
- POSITIONING INFORMATION REQUEST
- POSITIONING INFORMATION RESPONSE
- Supported optional field: SRS Configuration
- POSITIONING INFORMATION FAILURE
- POSITIONING INFORMATION UPDATE
- Supported optional field: SRS Configuration
- POSITIONING ACTIVATION REQUEST
- POSITIONING ACTIVATION RESPONSE
- POSITIONING ACTIVATION FAILURE
- POSITIONING DEACTIVATION
- TRP INFORMATION REQUEST
- TRP INFORMATION RESPONSE
- Supported : NR PCI, NG-RAN CGI, NR ARFCN, Geogarphical Coordinates
- TRP INFORMATION FAILURE
- POSITIONING MEASUREMENT REQUEST
- Supported optional field: SRS Configuration
- POSITIONING MEASUREMENT RESPONSE
- POSITIONING MEASUREMENT FAILURE
- POSITIONING MEASUREMENT REPORT
- POSITIONING MEASUREMENT ABORT
- POSITIONING MEASUREMENT FAILURE INDICATION
- POSITIONING MEASUREMENT UPDATE
- Supported optional field: SRS Configuration
The reference to these messages can be found in 3GPP 38.473 v16.21.0
CI: disable aerial x86 build pipeline
We use Aerial exclusively on ARM/gracehopper, so no need to build it on
x86. On this occasion, rename the "kind" (ID which images to build) to
x86 for clarity and align with the other "kinds" (build_cross_arm,
native_armv9, ...).
While testing the gNB with two hypotetical neighbors, some issues were found
with A3 event configuration.
The configuration of neighbors is:
neighbour_list = (
{
nr_cellid = 12345679L;
neighbour_cell_configuration = (
{
gNB_ID = 0xba0;
nr_cellid = 720898;
physical_cellId = 1;
absoluteFrequencySSB= 621312;
subcarrierSpacing = 1;
band = 78;
plmn = { mcc = 505; mnc = 01; mnc_length = 2 };
tracking_area_code = 1;
},
{
gNB_ID = 0xea0;
nr_cellid = 1345678L;
physical_cellId = 2;
absoluteFrequencySSB= 640000;
subcarrierSpacing = 1;
band = 78;
plmn = { mcc = 505; mnc = 01; mnc_length = 2 };
tracking_area_code = 1;
}
);
}
);
There were two problems.
The first problem is:
- when only default A3 event is configured, it is duplicated in the
RRC Reconfiguration Report Config To AddMod list with IDs 4 and 5
To test this case, the event configuration is:
nr_measurement_configuration = {
Periodical = {
enable = 1;
includeBeamMeasurements = 1;
maxNrofRS_IndexesToReport = 4;
};
A2 = {
enable = 1;
threshold = 60;
time_to_trigger = 1;
};
A3 = (
{
physCellId = -1;
offset = 15;
hysteresis = 2;
time_to_trigger = 3
}
);
};
The second problem is:
- when configuring an A3 event with an unknown physCellId, the gNB
does not include any A3 event in the RRC Reconfiguration Report
Config To AddMod list (which is correct), but configures some
meas ID with nonexistant Report Config IDs
To test this case, the event configuration is:
nr_measurement_configuration = {
Periodical = {
enable = 1;
includeBeamMeasurements = 1;
maxNrofRS_IndexesToReport = 4;
};
A2 = {
enable = 1;
threshold = 60;
time_to_trigger = 1;
};
A3 = (
{
physCellId = 10;
offset = 15;
hysteresis = 2;
time_to_trigger = 3
}
);
};
Reworking A3 event configuration as done in this commit solves both
issues.
CORESET 0 is configured in the configuration file by 'initialDLBWPcontrolResourceSetZero' and PDSCH TDA list is configured based on the current BWP size.
It may happen that the user configures a 2 symbol CORESET 0 for a BWP >= 48 PRBs (which is a valid 3GPP configuration) but in function 'nr_rrc_config_dl_tda' this scenario is not taken in account causing an overlap between PDSCH and PDCCH symbols.
This leads to very unreliable Msg2 and Msg4 decoding at the UE, but from time to time it succeeds, which becomes hard to identify this issue.
Correct how the slot for SIB1 is computed in case of MUX pattern 2 and 3.
Renamed n_0 to slot for clarity. n_c was never used outside of the function, so
remove it where it is not used.
We use Aerial exclusively on ARM/gracehopper, so no need to build it on
x86. On this occasion, rename the "kind" (ID which images to build) to
x86 for clarity and align with the other "kinds" (build_cross_arm,
native_armv9, ...).
Reference: 3GPP 38.473 v16.21.0
Mandatory fields:
Transaction ID (supported)
LMF Measurement ID (supported)
RAN Measurement ID (supported)
Add F1AP positioning measurement failure indication message enc/dec + test
Reference: 3GPP 38.473 v16.21.0
Mandatory fields:
Transaction ID (supported)
LMF Measurement ID (supported)
RAN Measurement ID (supported)
Cause (supported)
Reference: 3GPP 38.473 v16.21.0
Mandatory fields:
Transaction ID (supported)
LMF Measurement ID (supported)
RAN Measurement ID (supported)
Positioning Measurement Result List (range: 1)
> Positioning Measurement Result List Item (range: 1..64)
>> Positioning Measurement Result (supported)
>> TRP ID (supported)
Reference: 3GPP 38.473 v16.21.0
Mandatory fields:
Transaction ID (supported)
LMF Measurement ID (supported)
RAN Measurement ID (supported)
Cause (supported)
Optional fields:
Criticality Diagnostics (not supported)
Reference: 3GPP 38.473 v16.21.0
Mandatory fields:
Transcation ID (supported)
LMF Measurement ID (supported)
RAN Measurement ID (supported)
Positioning Measurement Result List (range: 0..1)
> Positioning Measurement Result List Item (range: 1..64)
>> Positioning Measurement Result (supported)
>> TRP ID (supported)
Optional fields:
Criticality Diagnostics (not supported)
Reference: 3GPP 38.473 v16.21.0
Mandatory fields:
Transcation ID (supported)
TRP Information List (range : 1)
> TRP Information Item (range : 1..65535)
>> TRP Information (supported)
Further details of TRP Information:
TRP ID
TRP Information Type Response List (range : 1)
> TRP Information Type Response Item (range : 1..64)
>> CHOICE TRP Information Type Response Item
>>> NR PCI (madatory : supported)
>>> NG-RAN CGI (madatory : supported)
>>> NR ARFCN (madatory : supported)
>>> PRS Configuration (madatory : not supported)
>>> SSB Information (madatory : not supported)
>>> SFN Initialisation Time (madatory : not supported)
>>> Spatial Direction Information (madatory : not supported)
>>> Geographical Coordinates (madatory : supported)
For now, we only use Geographical Coordinates.
Optional fields:
Criticality Diagnostics (not supported)
Reference: 3GPP 38.473 v16.21.0
Mandatory fields:
Transcation ID (supported)
TRP list (range : 0..1)
> TRP list Item (range : 1..65535)
>> TRP ID (supported)
TRP Information Type List (range : 1)
> TRP Information Type Item (range : 1..64)
>> TRP Information Type Item (supported)
While implementing NRPPA-related F1AP messages, we remarked that
extension field "UL-AoA-ExtIEs" needs to be OPTIONAL (e.g., in NRPPA it
is optional in the OAI-compiled version), but it was not marked as such.
This later version 16.21.0 fixes this.
Integration: `2026.w03`
* !3818 Update threadCreate
* !3845 Update physim timing thresholds in gNB-N300-Timing-Phytest-LDPC
* !3849 Make gpd config utility global
* !3812 Fix reestablishment after handover
* !3826 Define speed of light
* !3799 Fix for threadpool abort function
* !3791 fix array lenght errors, k variable wrapping threshold. Make the code smaller and more efficient
* !3718 Introduce SRS physical simulator and improvements
* !3857 Fix bug "no AMF for UE"
* !3858 remove function decode_cellGroupConfig
* !3668 Support beam index for LiteON FR2 RU that needs per symbol section in CP packets
* !3844 CI: Remove testcase ids from XML files
* !3620 update multi-RU 7.2 documentation for DAS scenario
* !3788 Fix handover documentation and configuration files for event configuration
See merge request oai/openairinterface5g!3854
- Refactor function to return byte_array_t instead of taking buffer
parameter for consistency with other encoding functions
(do_RRCReconfiguration, do_HO_RRCReconfiguration) and to prevent buffer
overflow issues since the memory size is determined automatically
- Add comprehensive error checking:
* Input validation
* Check return of each decode (HandoverCommand
and RRCReconfiguration)
* Validate HandoverCommand structure before access
* Validate OCTET_STRING before decoding RRCReconfiguration
* Error handling and cleanup for enc/dec failures
- Update caller in rrc_gNB_NGAP.c
* use new signature
* free buffer
* send HO Cancel on decoding failure (source gNB)
Closes#1043
This commit adds support for the Handover Cancel initiating message
procedure code (NGAP_ProcedureCode_id_HandoverCancel).
Changes:
- ngap_gNB_decoder.c: Added case handler for Handover Cancel in
ngap_gNB_decode_initiating_message() to properly decode and log
incoming Handover Cancel messages from the AMF.
- ngap_gNB_encoder.c: Added Handover Cancel to the list of supported
initiating message procedure codes in ngap_gNB_encode_initiating(),
allowing the gNB to encode and send Handover Cancel messages.
The Handover Cancel procedure is already implemented in other parts of
the NGAP stack, these changes were missing to complete the support
by ensuring the procedure code is properly recognized in both the encoder
and decoder switch statements, following the same pattern as other
procedure codes.
Support beam index for LiteON FR2 RU that needs per symbol section in CP packets
This branch supports beam index for LiteOn FR2 RU and others. It adds
the support of beam index for LiteOn RU that uses per-symbol CP packet
and is a sequel of MR !3605 (merged) that supports beam index for RU
that uses per-slot CP packets.
A. To support LiteOn FR2 RU, the following are needed.
a. Per symbol beamforming. Need separate section for each symbol on CP packet.
b. Handle these two bugs:
- section ID on UP packet is set wrongly to 13 for all sections
- prach eAxC offset starts from 0 instead of from last antenna port
number used by other channels.
B. Implementation
a. set fh_config->RunSlotPrbMapBySymbolEnable based on the setting in the configuration file
- if disable, the existing per-slot scheme is run on xran.
- if enable, RunSlotPrbMapBySymbolEnable mode is on in xran so that xran
will generate PrbElm per symbol (aka total of 14)and perform
per-symbol processing on the corresponding PrbElm.
b. set fh_config->LiteOnIgnoreUPSectionIdEnable based on the setting in
the configuration file if enable, handle 2 "features" of Liteon:
- To handle the section_id = 13 issue on Liteon where section ID is set
wrongly to 13 for all sections
- To handle the prach eAxC offset issue on Liteon where it starts from 0
instead of from the end of last antenna port number
c. if fh_config->RunSlotPrbMapBySymbolEnable, OAI FHI
- invoke xran_fh_rx_read_slot_BySymbol() instead of xran_fh_rx_read_slot()
- invoke xran_fh_tx_send_slot_BySymbol() instead of xran_fh_tx_send_slot()
C. Testing
a. Command to test benetel RU
sudo LD_LIBRARY_PATH=.:$DPDK_INST/lib/x86_64-linux-gnu/ ./nr-softmodem -O /etc/ran_development/CONFs/gnb.sa.band77.273prb.fhi72.4x4-benetel550_c0.conf --thread-pool 21,22,23,24,25,26,27,28
Results:
iperf UDP uplink
[ 5] 0.00-10.22 sec 87.3 MBytes 71.6 Mbits/sec 0.100 ms 370/63081 (0.59%) receiver
iperf UDP downlink
[ 5] 0.00-10.00 sec 796 MBytes 668 Mbits/sec 0.017 ms 1824/586404 (0.31%) receiver
b. Command to test LiteOn FR2 RU
sudo LD_LIBRARY_PATH=.:$DPDK_INST/lib/x86_64-linux-gnu/ ./nr-softmodem -O /etc/ran_development/CONFs/gnb.sa.band78.66prb.fhi72.2x2-liteon-F-Release.conf--thread-pool 21,22,23,24,25,26,27,28
Result:
iperf UDP uplink
[ 5] 0.00-10.20 sec 89.9 MBytes 73.9 Mbits/sec 0.156 ms 212/64848 (0.33%) receiver
iperf UDP downlink
[ 5] 0.00-10.00 sec 361 MBytes 303 Mbits/sec 0.077 ms 277662/542891 (51%) receiver
D. Difference between LiteOn FR2 E release configuration file and that for F release is
diff gnb.sa.band78.66prb.fhi72.2x2-liteon-KB.conf gnb.sa.band78.66prb.fhi72.2x2-liteon-F-Release.conf 39d38
< beam_weights = [1, 1];
225a225
> beam_weights = [1];
312c312,313
< mtu = 1500; # check if xran uses this properly
---
> #mtu = 1500; # check if xran uses this properly
> mtu = 9000; # check if xran uses this properly
313a315,316
> RunSlotPrbMapBySymbol = 1;
> LiteOnIgnoreUPSectionId = 1;
Add the F patch that work on both Benetel and LiteOn RU. support
fh_config parameters RunSlotPrbMapBySymbol and LiteOnIgnoreUPSectionId.
Change version number.
Fix bug "no AMF for UE"
It might happen that the RRC does not know the AMF UE NGAP ID, yet. Even
in that case, we should forward the release request to the NGAP module,
which can either forward a message to the AMF, or reply back to release
the UE. This avoids an error where the CU claims there was no AMF, when
there actually is.
One possible problematic behavior is if a UE disconnects before the gNB
receives an NGAP Initial Context Setup. In this case, the AMF UE NGAP ID
was not forwarded to the RRC (although it was known at NGAP), thus
blocking the release of the UE.
This is the main fix, the rest are minor fixes:
- store AMF UE NGAP ID as early as possible
- warn in MAC if UE unknown for UE context release command
- show TEIDs with correct endianness in GTP
- avoid NG Setup Failure+Setup log.
Introduce SRS physical simulator and improvements
This MR consists of two parts:
- Introduces SRS physical simulator to test different configurations of
SRS
- Improvements in the SRS channel estimation (Addressing the comments
from old, unfinished MR !2875)
- rewrite nr_srs_channel_estimation() to loop over rx antennas and
antenna ports to be able to parallelize
- Improvements in timing_advance_offset and timing_advance_offset_nsec
computation
- Introduce SRS multi-symbol channel estimation
- The channel impulse response is estimated from the averaged
channel frequency response over multiple symbols
- The channel frequency estimates are left as they are to be able to
estimate doppler in the future
- Simplify SRS channel estimation to handle memory alignment in the
case of different SRS configurations (eg: comboffset)
To use multiple symbols when running gNB, the following parameters needs
to be edited in the function get_srs_resource()
- srs_res->resourceMapping.startPosition with a range from {0,1,..,5}
corresponds to the start symbol {13, 12, .. 8} with in a slot
- srs_res->resourceMapping.nrofSymbols indicates the number of symbols
{n1, n2, and n4}
Make sure the that start symbol + number of symbols is < 14
The timing results for SRS in develop and srs_phy_simulator are as follows:
Command used: sudo ./nr_ulsim -n1000 -s50 -S50 -R273 -W2 -y2 -z2 -E 1 -P
develop
|__ RX SRS time 124.94 us (1000 trials) (124.94 total [ms])
|__ Generate SRS sequence time 0.05 us (1000 trials) ( 0.05 total [ms])
|__ Get SRS signal time 19.41 us (1000 trials) ( 19.41 total [ms])
|__ SRS channel estimation time 89.11 us (1000 trials) ( 89.11 total [ms])
|__ SRS timing advance estimation time 13.10 us (1000 trials) ( 13.10 total [ms])
|__ SRS report TLV build time 2.80 us (1000 trials) ( 2.80 total [ms])
|__ SRS beam report build time 0.00 us ( 0 trials)
|__ SRS IQ matrix build time 2.73 us (1000 trials)
srs_phy_simulator
|__ RX SRS time 211.93 us (1000 trials) (211.93 total [ms])
|__ Generate SRS sequence time 0.04 us (1000 trials) ( 0.04 total [ms])
|__ Get SRS signal time 19.55 us (1000 trials) ( 19.55 total [ms])
|__ SRS channel estimation time 152.05 us (1000 trials) (152.05 total [ms])
|__ SRS timing advance estimation time 36.67 us (1000 trials) ( 36.67 total [ms])
|__ SRS report TLV build time 2.96 us (1000 trials) ( 2.96 total [ms])
|__ SRS beam report build time 0.00 us ( 0 trials)
|__ SRS IQ matrix build time 2.88 us (1000 trials)
Note that in srs_phy_simulator, to compute timing offset ns, an
oversampling factor of 2 is performed. Also, for peak detection, we
average the channel estimates for every port.
fix array lenght errors, k variable wrapping threshold. Make the code smaller and more efficient
generate_nr_prach() has several errors coming from replace int16_t by
c16_t, and also older error in k wrapping at the end of the symbol
the code is also ridiculously complex, wasting memory and cpu time in
intermediate useless buffers and headache usage of memmove()
On NGSetupFailure, before moving, we might have
[NGAP] Received NG setup failure for AMF... please check your parameters
[NGAP] Received NGSetupResponse from AMF
In the Initial Context Setup message, the NGAP forwards the AMF UE ID,
but not in the DL NAS Message, although 38.413 says, in $8.3.1.2 either
> The NG-RAN node shall use the AMF UE NGAP ID IE and RAN UE NGAP ID IE
> received in the INITIAL CONTEXT SETUP REQUEST message as identification
> of the logical connection
or in $8.6.2.2
> The NG-RAN node shall use the AMF UE NGAP ID IE and RAN UE NGAP ID IE
> received in the DOWNLINK NAS TRANSPORT message as identification of the
> logical connection
So forward in both cases for harmonization.
It might happen that the RRC does not know the AMF UE NGAP ID, yet. Even
in that case, we should forward the release request to the NGAP module,
which can either forward a message to the AMF, or reply back to release
the UE.
Reported-By: Jegor Zelenjak <jzelenjak@proton.me>
Make gpd config utility global
Make gpd a global utility macro for reading config/command line
parameters. Add a corresponding function with full name for clarity,
keep the short name for the macro for backward compatibility and ease of
use.
The main benefit of gpd/config_get_paramdef_from_name macro/function is
that it does not require maintaining a separate parameter index list.
Update physim timing thresholds in gNB-N300-Timing-Phytest-LDPC
The lower bound for the tests are too tight and any slight improvement
in the timing can result in a test failure. For example, these tests
were failing due to the improvements from the MR !3718
Clear memory in shm_td_iq_channel after RX. This prevents the IQ
from being read twice. This can happen if the application crashes
and will keep the other side reading historical IQ samples.
The lower bound for the tests are too tight and any slight improvement in the timing can result in a test failure.
For example, these tests were failing due to the improvements from the MR 3718
- We use the same function at gNB and UE.
- We always use nb_antennas_tx to check the max possible number of ports (which is wrong).
- At gNB, we should use nb_antennas_rx and at the UE, we should use nb_antennas_tx.
The memory alignment is required to use c16multaddVectRealComplex
in SRS channel interpolation. With a change in SRS comb_offset, the
existing algorithm was giving segmentation fault.
The existing srs channel estimation required memory alignment at two
stages. 1. When k = 0 (the first srs subcarrier), 2. When subcarrier <
K_TC (wrapped around after ofdm_symbol_size). Thus two memory alignments
are required leading to complications.
The srs channel estimation is now simplified to do it linearly instead of
wrapping around. This simplified the memory alignment required only when
k = 0.
- Introduce signal energy and noise variance functions
- Combine rotation and OFDM modulation RX as a function
- Harmonize the use of number of antennas across the code
- Rename nr_ue_pusch_common_procedures() to nr_tx_rotation_and_ofdm_mod() to decribe the functionality better
Integration: `2026.w02`
* !3828 L2 UE files code cleanup for static functions
* !3839 Couple rfsim fixes
* !3835 Correctly include cblas include directories for RHEL
* !3840 Fix missing return statements in SIB1 TDA validation
* !3836 move NTN UE L1 functions to a new file
* !3793 CI: Remove redundant Jenkinsfiles
* !3770 RRC UE: Implement proper NH chain synchronization for RRC Reestablishment
* !3843 fix(documentation): issue 1042
* !3842 Remove unused cmake_targets files
* !3832 Remove global iq_txshift and iq_rxrescale
* !3847 Minor CI and nr_ulsim reporting adjustments
* !3838 NR NGAP (N2HO) : Fix Time UE Stayed in Cell IE type and calculation
* !3677 Support prach with start symbol of PRACH not at symbol 0
Closes#1042 and #857
See merge request oai/openairinterface5g!3841
List of changes:
- avoid calculating accumulated rounding error by calculating absolute
sample index based on CLOCK_REALTIME every time.
- use threadCreate instead of plain pthread_create which assigns a unique
thread name and simplifies debugging
Make gpd a global utility macro for reading config/command line parameters.
Add a corresponding function with full name for clarity, keep the short name
for the macro for backward compatibility and ease of use.
The main benefit of gpd/config_get_paramdef_from_name macro/function is that
it does not require maintaining a separate parameter index list.
Support prach with start symbol of PRACH not at symbol 0
The following PRACH indice have been tested.
index / format (nf mod x = y) / Subframe/ start_symbol /no_of_slot / occ / duration
152 B4 2 1 4,9 0 2 1 12
151 B4 2 1 4,9 2 1 1 12
157 B4 1 0 4 0 1 1 12
159 B4 1 0 9 0 1 1 12
NR NGAP (N2HO) : Fix Time UE Stayed in Cell IE type and calculation
According to 3GPP TS 38.413, the 'Time UE Stayed in Cell' IE is an
integer ranging from 0 to 4095. This patch updates the data structure
to reflect the correct bit width and implements the dynamic calculation
based on the UE's residence time.
- Change time_in_cell from long to uint16_t in ngap_messages_types.h.
- Replace dummy value with real-time calculation in rrc_gNB_NGAP.c.
- Implement a ceiling of 4095 to comply with the 12-bit protocol limit.
Ref: 3GPP TS 38.413 Section 9.3.1.97
Refactor key derivation logic to properly handle Next Hop (NH) chain
synchronization according to 3GPP TS 33.501 specifications for both RRC
Reestablishment and Master Key Update procedures.
Changes in rrc_gNB.c:
- Clarify key derivation in rrc_gNB_generate_RRCReestablishment by explicitly
selecting base key (NH or KgNB) based on nh_ncc value
- Add comment explaining vertical vs horizontal derivation logic
Changes in rrc_UE.c:
Refactored the NH chain synchronization and key derivation code to match
TS 33.501 terminology:
- nr_sync_nh_chain(): Common helper to synchronize NH parameter chain per
TS 33.501 Annex A.10, supporting both Master Key Update and RRC Reestablishment
procedures
- nr_derive_kgnb_horizontal(): Derive KNG-RAN* from current KgNB when NCC values
match (horizontal derivation per TS 33.501 A.11/A.12)
- nr_derive_kgnb_vertical(): Derive KNG-RAN* from synchronized NH after NH chain
sync (vertical derivation per TS 33.501 A.11/A.12)
- nr_update_kgnb_from_ncc(): Unified function implementing TS 33.501 6.9.2.3.4
logic for updating KgNB based on received nextHopChainingCount
- Refactor as_security_key_update(): Use new nr_update_kgnb_from_ncc() helper
function for cleaner, more maintainable code
- Fix nr_rrc_ue_process_rrcReestablishment(): Properly handle received
nextHopChainingCount and update KgNB using unified helper function
- Replaced the previous nr_rrc_nh_update() helper with these functions to
improve clarity and alignment with the specification.
- Add debug logging for key derivation process
Key NAS deriver utils:
- update derive_kgnb documentation and protect input keys with const attribute
Closes#857
These files are not used anywhere. The only remaining cmake find files
are:
- findarmral and findxran: used by FHI7.2 driver
- findsctp: used by top-level CMakeLists.txt
- findgnutls: NOT actually used but GnuTLS is a dependency of websrv, so
I leave it for the moment (should be removed if the webserver is
removed)
Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
There is no HSS/MME in this repository, which is the majority of this
file. Remove it, since it is outdated.
Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
Setup routes was added by the author of FlexRAN. The UEs always set up
routes automatically, and this file is therefore not needed.
See-also: 287c182925 ("Remove FlexRAN")
Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
According to 3GPP TS 38.413, the 'Time UE Stayed in Cell' IE is an
integer ranging from 0 to 4095. This patch updates the data structure
to reflect the correct bit width and implements the dynamic calculation
based on the UE's residence time.
- Change time_in_cell from long to uint16_t in ngap_messages_types.h.
- Replace dummy value with real-time calculation in rrc_gNB_NGAP.c.
- Implement a ceiling of 4095 to comply with the 12-bit protocol limit.
Ref: 3GPP TS 38.413 Section 9.3.1.97
RHEL uses a dedicated cblas include directory. Correctly include this
for the one target PHY_UE that relies on this.
Co-authored-by: Robert Schmidt <robert.schmidt@openairinterface.org>
Per TS 33.501 6.9.2.3.4 and Fig 6.9.2.1.1-1, when sending
RRCReestablishment with nextHopChainingCount, the gNB is staying at
the same NCC level (not advancing). Therefore, horizontal derivation
from the currently active KgNB must be used, not vertical derivation
from NH.
Vertical derivation (from NH) is only used when advancing to a new
NCC level, which happens during handover or masterKeyUpdate procedures.
The previous implementation incorrectly used vertical derivation from
NH whenever nh_ncc > 0, which caused key mismatch between gNB and UE
during reestablishment after handover, leading to integrity check
failures.
This fix ensures both gNB and UE use horizontal derivation when
nextHopChainingCount matches the current NCC level, aligning with the
specification's "virtual NH at NCC=0" model where:
- Horizontal derivation = derive KNG-RAN* from currently active KgNB
- Vertical derivation = derive KNG-RAN* from NH (only when advancing NCC)
During N2 handover, the UE receives reconfigurationWithSync which correctly
sets the target cell frequency in mac->phy_config.config_req.carrier_config
via config_common_ue() call.
However, when SIB1 is decoded after reconfiguration,
nr_rrc_mac_config_req_sib1() calls config_common_ue_sa() which unconditionally
overwrites the frequency with the command-line parameter (downlink_frequency),
which corresponds to the source cell frequency.
This causes a critical issue during RRC re-establishment:
- The UE uses the wrong frequency (source cell) for key derivation (kgnb*)
- The gNB uses the correct frequency (target cell) for key derivation
- This mismatch results in different kgnb* keys on UE and gNB
- Integrity check fails: "Integrity of RRCReestablishment failed, going to IDLE"
Root cause:
config_common_ue_sa() is used for SIB1 processing (initial cell selection) and
uses ServingCellConfigCommonSIB which doesn't contain absoluteFrequencyPointA.
It must derive frequency from command-line parameters. However, after handover,
the frequency has already been correctly set by config_common_ue() (used for
reconfigurationWithSync) which uses ServingCellConfigCommon with absolute
frequency information.
Solution:
Modify config_common_ue_sa() to preserve the existing frequency if it's already
initialized (non-zero). Only set frequency from command-line parameters during
initial cell selection when dl_frequency is 0. This ensures:
- Initial cell selection: frequency derived from command-line parameter, just once
- After handover: frequency preserved from reconfigurationWithSync
- MAC maintains its own frequency state independently
The fix applies to both DL and UL frequencies to maintain consistency.
There is probably room for more refactoring to the resync flow, since
the functionalities in config_common_ue and config_common_ue_sa are
partially overlapping and upon reconfigurationWithSync some other
configurations might be applied twice.
These logs are very helpful to identify cell configuration
changes in MAC/PHY, for monitoring purposes, and to rapidly
signal integrity failures during re-establishment.
The RNTI from the target context was not updated after HO acknowledge
this led to a failure in the first re-establishment after HO.
This commit is introducing the function nr_rrc_apply_target_context
in nr_rrc_n2_ho_acknowledge() and also updates the cell ID for
consistency.
Refactor handover target context application logic into a reusable
function nr_rrc_apply_target_context() that updates both F1AP
associations (secondary UE and DU association) and RNTI from the
target handover context.
And apply to rrc_CU_process_ue_context_modification_response()
Integration: `2025.w52`
* !3809 [FHI72] Fix the PRACH FFT size
* !3829 Hotfix for handling the case where the number of physical antennas is larger than the number of logical antennas
* !3663 NR UE: calculate DL and UL Doppler based on SIB19 information in NTN mode, fixing LEO reestablishment
* !3819 CORESET start multiple of 6 fix
* !3641 automatic selection of SIB1 TDA
* !3804 gNB: apply new NR_CellGroupConfig when RRCReconfiguration is acknowledged
* !3833 Add missing CMakeLists entries for test_nr_frame_params
* !3656 Rfsimulator beam reception/transmission
Closes#1037 and #1002
See merge request oai/openairinterface5g!3830
Rfsimulator beam reception/transmission
A simplified beam switching simulation for rfsimulator. This works
mainly in 1 gNB - N UEs scenarios. This is not a real beamformer with
antenna, channel and propagation model. The way it works is that the
peers inform each other about the beams they transmit in, and on
reception before channel modelling, the beam data is combined based on
preconfigured rx_beam/tx_beam gain matrix.
Usage:
- Add --rfsimulator.enable_beams to enable beam simulation
- Add --rfsimulator.beam_gains .
Example list: 0,-5,-10
Resulting matrix:
[[0, -5, -10] [-5, 0, -5]] [-10, -5, 0]]
- Add --telnetsrv if you want to control the beams manually. The command
in telnet is "rfsimu setbeam <beam_map>", where beam_map is a uint64_t
controling the reception beam and transmission beam. If the
application is switching the beams automatically the beams will be
overwritten as soon as the application chooses to switch beams.
Supports up to 64 concurrent TX and RX beams.
gNB: apply new NR_CellGroupConfig when RRCReconfiguration is acknowledged
Currently part of the NR_CellGroupConfig is already applied when the
RRCReconfiguration message is created. This is not correct and this MR
fixes this by applying it when the RRCReconfiguration message is
acknowledged.
With this fixed, we also move disabling the feedback (in case
disable_harq is used) from the RRCSetup message to the
RRCReconfiguration message.
Closes: #1002
Add CLI parameter rfsimulator.beam_ids which uses a list of beam ids instead of a
beam map. The beam map API is still present and can be used interchangably.
Add telnet command setbeamids which has similar semantics
Allow arbitrary order of beam ids in set_beams2 function. This
allows the application to select any arbitrary order of beam ids.
The underlying transport mechanism still uses beam_map so the beam_ids
are ordered before sending.
Also replaced tx_beam_map/rx_beam_map into beam_map.
Also fixed an issue where --rfsimulator.enable_beams required an argument.
- Added first beam optimization to combine_tx_buffers.
- Added first beam & first peer optimization to rfsimulator_read_internal
This results in significant speed up for the first rx beam, first tx
beam and first peer which is the base case with beam simulation disabled.
In rfsim, received packets are dynamically allocated and freed when no longer
needed, which is dependent on the channel model, packet timestamp and packet
size (number of samples carried).
This commit fixes the packet age check for channels with nonzero channel offset
(most notalby NTN channels).
Also present:
- extract the NTN satellite position update code to a separate function and
call it once per trx_read call instead of once per rx beam.
Add a set of macros with designated initializers to simplify using
paramdef_t arrays in C++ source code. Fix clang error with
RFSIMULATOR_PARAMS_DESC using mixed designated and non-designated
initializers.
- Received packets are dynamically allocated and kept in a
queue for as long as they are needed.
- The layout of the packets was changed from interleaved antennas
to non-interleaved antennas.
- Generate a contiguous buffer from saved packets as needed.
There is extra work caused by this change due to recv() call no
longer saving data directly into the circular buffer, however further
processing is easier due to contiguous nature of the tx antenna buffers
prepared. The impact on performance was not measured.
A simplified beam switching simulation for rfsimulator. This works
mainly in 1 gNB - N UEs scenarios. This is not a real beamformer with
antenna, channel and propagation model. The way it works is that the
peers inform each other about the beams they transmit in, and on
reception before channel modelling, the beam data is combined based on
preconfigured rx_beam/tx_beam gain matrix.
Usage:
- Add --rfsimulator.enable_beams to enable beam simulation
- Add --rfsimulator.beam_gains <comma separated Toepliz form matrix of gains in dB>.
Example list: 0,-5,-10
Resulting matrix:
[[0, -5, -10]
[-5, 0, -5]]
[-10, -5, 0]]
- Add --telnetsrv if you want to control the beams manually. The command in telnet
is "rfsimu setbeam <beam_map>", where beam_map is a uint64_t controling the
reception beam and transmission beam. If the application is switching the beams
automatically the beams will be overwritten as soon as the application chooses to
switch beams.
Co-authored-by: Laurent Thomas <laurent.thomas@open-cells.com>
CORESET start multiple of 6 fix
According to the standard any CORESET (except CSET0) would always start
from the first common resource block index which is multiple of 6 in the
BWP. This was not taken into account in the code. The BWP switch CI test
is modified to test a BWP start not multiple of 6.
An exception is the case where rb-Offset-r16 parameter is set, but can't
be used at gNB for FAPI compatibility.
Closes: #1037
[FHI72] Fix the PRACH FFT size
ru_config->fftSize is used for the C-plane Section Type 3 which is
dedicated for PRACH and mixed numerology. Previously, we assumed that
PRACH FFT size is equivalent to PxSCH FFT size, but should be based on
the PRACH format.
Tests with the following RUs:
- [x] Benetel v1.2.2 & v1.4.1
- [x] VVDN Gen 3
- [x] Liteon 02.00.10
- [x] Metanoia v2.2.8 (Jura)
Integration `2025.w51`
* !3816 Add two missing include guards
* !3715 Pass beam ID as per FAPI v222.10
* !3777 UE NTN : Fix in case SIB19 periodicity is greater than 2 secs
* !3813 Reset outdated PUCCHs to avoid Assertion caused by non-processed and active PUCCHs
* !3815 Remove phy_extern_nr_ue file
* !3824 CI: adjust UE attach timeout handling
* !3735 vrtsim: Optimize channel modelling
See merge request oai/openairinterface5g!3817
Per TS 33.501 6.9.2.3.4 and Fig 6.9.2.1.1-1, when sending
RRCReestablishment with nextHopChainingCount, the gNB is staying at
the same NCC level (not advancing). Therefore, horizontal derivation
from the currently active KgNB must be used, not vertical derivation
from NH.
Vertical derivation (from NH) is only used when advancing to a new
NCC level, which happens during handover or masterKeyUpdate procedures.
The previous implementation incorrectly used vertical derivation from
NH whenever nh_ncc > 0, which caused key mismatch between gNB and UE
during reestablishment after handover, leading to integrity check
failures.
This fix ensures both gNB and UE use horizontal derivation when
nextHopChainingCount matches the current NCC level, aligning with the
specification's "virtual NH at NCC=0" model where:
- Horizontal derivation = derive KNG-RAN* from currently active KgNB
- Vertical derivation = derive KNG-RAN* from NH (only when advancing NCC)
Refactor key derivation logic to properly handle Next Hop (NH) chain
synchronization according to 3GPP TS 33.501 specifications for both
RRC Reestablishment and Master Key Update procedures.
Changes in rrc_gNB.c:
- Clarify key derivation in rrc_gNB_generate_RRCReestablishment by
explicitly selecting base key (NH or KgNB) based on nh_ncc value
- Add comment explaining vertical vs horizontal derivation logic
Changes in rrc_UE.c:
- Add nr_sync_nh_chain(): Common helper to synchronize NH parameter
chain per TS 33.501 Annex A.10, supporting both Master Key Update
and RRC Reestablishment procedures
- Add nr_derive_kgnb_horizontal(): Derive KNG-RAN* from current KgNB
when NCC values match (horizontal derivation per TS 33.501 A.11/A.12)
- Add nr_derive_kgnb_vertical(): Derive KNG-RAN* from synchronized NH
after NH chain sync (vertical derivation per TS 33.501 A.11/A.12)
- Add nr_update_kgnb_from_ncc(): Unified function implementing TS 33.501
6.9.2.3.4 logic for updating KgNB based on received nextHopChainingCount
- Refactor as_security_key_update(): Use new nr_update_kgnb_from_ncc()
helper function for cleaner, more maintainable code
- Fix nr_rrc_ue_process_rrcReestablishment(): Properly handle received
nextHopChainingCount and update KgNB using unified helper function
- Add debug logging for key derivation process
Key NAS deriver utils:
- update derive_kgnb documentation and protect input keys with const attribute
Make sure to apply Doppler and TA not directly when receiving the target cell ntn_config,
but apply Doppler just before the initial sync, and the TA after the initial sync when
we have tha actuel cell frame and slot numbers.
We need the ntn_config when reconfiguring the PHY layer for a new initial sync,
e.g. for calculating the DL Doppler frequency.
As a dedicated scheduled_response dl_config PDU it reaches the PHY layer too late,
as part of the phy_config.config_req it reaches the PHY layer in time with the
other configuration values.
vrtsim: Optimize channel modelling
Optimization pass for channel modelling on transmission in vrtsim. This
comes from a requirement of O-RU to perform channel modelling with minimum
latency. The latency measured in O-RU 4TX 2RX on the UE is lowered from
~400 uS to ~100uS.
- Reduced MAX_CHANNEL_LENGTH to 200 and introduced SAVED_SAMPLES_LEN
- Refactored channel modelling actor allocation to parallelize work better
- Improved batching and task creation for channel modelling
- Replaced static global saved_samples with local static buffer in vrtsim_write_with_chanmod
Create a new CI pipeline for testing with vrtsim on Gracehopper:
https://jenkins-oai.eurecom.fr/job/RAN-VRT-Sim-Test-5G/
CI: adjust UE attach timeout handling
This modification addresses an issue in the RFSim-5G 2x2 test where the UE
often fails to attach within the initial 20s window. The timeout may cause
the UE to restart, which leads to two UEs appearing in the gNB log. By
increasing the initial timeout to 40s, we avoid unnecessary restarts.
- Set default attach_timeout to 40s
- Increase timeout only after failed attach attempts
This modification addresses an issue in the RFSim-5G 2x2 test where the UE
often fails to attach within the initial 20s window. The timeout may cause
the UE to restart, which leads to two UEs appearing in the gNB log. By
increasing the initial timeout to 40s, we avoid unnecessary restarts.
This function is to be called by the application to switch beams
on reception and transmission. When receiving new samples using
trx_read/trx_write the application is expected to be able to
determine which beam the samples belong to.
Reset outdated PUCCHs to avoid Assertion caused by non-processed and
active PUCCHs
When there is real-time issues in L1 it may happen that the scheduler
misses/skips some slots, thus, L2 not processing and not freeing some
structures like PUCCH. This commit avoids the Assertion by resetting
any Active outdated PUCCH
UE NTN : Fix in case SIB19 periodicity is greater than 2 secs
This was observed when testing OAI NTN UE against a third party gNB (UXM).
LEO SIB19 periodicity of > 2000 ms was used, in which case T430 timer expires
before SIB19 is re-read. This fix handles the case where SIB19 periodicity >
2secs, such that SIB19 is re-read in time and T430 timer does not expire.
Pass beam ID as per FAPI v222.10
This MR
1. Sets MSB of beam ID when passing beam ID to 7.2 radio
2. Modifies phytest scheduler to allocate SSBs on different beams
3. Introduce new MAC config parameter for beam mode to specify HiPHY or LoPHY
beamforming
In perfrom_channel_modelling, do convolution in batches which allows
vrtsim to write the channel samples as they are being produced instead
of waiting for the last sample in the slot to be ready.
Limit sample history to 256 samples and copy it into each channel modelling
task instead of relying on globally available buffer. This simplifies the code
and addressing into the saved samples buffer as well as enabling further
optimizations without sacrificing thread safety.
We assumed that PRACH FFT size is equivalent to PxSCH FFT size.
However, the parameter ru_config->fftSize is used for the C-plane Section Type 3
which is dedicated for PRACH and mixed numerology.
Based on the PRACH format, short or long, the PRACH values 256 or 1024
shall be filled.
Co-authored-by: knopp <raymond.knopp@eurecom.fr>
When doing analogue beamforming, the beam ID for a pre-defined beam
table is passed directly to RU and there is no need to store the beam
table in PHY.
When there is real-time issues in L1 it may happen that the scheduler misses/skips some slots, thus, L2 not processing and not freeing some structures like PUCCH.
This commit avoids the Assertion by resetting any Active outdated PUCCH
Integration `2025.w50`
* !3638 NR UE: calculate TA based on SIB19 information in NTN mode, if autonomous TA is not enabled
* !3624 NR UE: improve handling of Handover procedures
* !3807 doc: Update doc for IF setup
* !3741 Update documenation for handover
* !3798 Fix for computation of PRACH occasions and association period
* !3808 Add symbol timing functions for NR_DL_FRAME_PARMS + optimization for slot timing counterparts
Closes#981
See merge request oai/openairinterface5g!3806
Add symbol timing functions for NR_DL_FRAME_PARMS + optimization for slot timing
counterparts
Add two new functions for calculation symbol timestamp and symbol duration for
NR_DL_FRAME_PARMS. Also includes an optimization focused on removing
inefficiencies related slot-related counterparts.
1. Removed function pointers for functions get_samples_per_slot(),
get_samples_slot_timestamp() and get_slot_from_timestamp() as it does
not offer any advantage. The functions are now called directly from
everywhere.
2. Optimized these functions by removing loops where ever possible.
Update documenation for handover
Update documentation for handover to include the changes that were made after
upgrading the CI handover setup (attenuator, USRPs synchronization)
NR UE: calculate TA based on SIB19 information in NTN mode, if autonomous TA is not enabled
To achieve the goal, the hyper frame number (HFN) is introduced at the NR UE
PHY, MAC and RRC layers.
Besides this, we also implemented an orbit propagation to improve the accuracy
of N_UE_TA_adj, and a fix to keep the N_TA from RAR and MAC CE.
Fixes#981
Add two new functions for calculation symbol timestamp and symbol
duration for NR_DL_FRAME_PARMS. These functions are not using
the existing indirection mechanism via function pointers as this
prevents the compiler from properly optimizing the code.
Fixed an issue where if threadpool was aborted when some threads were in a running
state the threadpool would never exit. This was due to the fact that the thread
terminate task (func == NULL && args == NULL) could have been pushed to queues which
were inactive. This change adds a uint64_t mask of threads that have already exited
so whenever the terminate task is sent to another queue, it is ensured that the queue
used will wake up at least one tpool worker.
Also added pushTpool_mask which allows to specify a subset of threads to push the task
to but its only used internally.
Also added in this commit: A way to allocate thread-safe storage for thread pool
workers via get_tpool_worker_index. This index is unique to the thread pool worker
within one threadpool and can be used to access arrays in a thread-safe manner.
An example of such use was added in a testcase that was added which compares delay
between actors and threadpool workers.
Fix FAPI WLS timing, UL counter, doc
- Fix FAPI WLS timing
- Fix periodical PNF UL throughput logs
- Update documentation to better explain how to run WLS with radio (USRP
B210)
Fixes for BWP switching
This MR fixes some issues when performing BWP switching via
reconfiguration. It also adds a CI test for BWP switching. # Please
enter a commit message to explain why this merge is necessary,
In all cases (CFRA in SA for HO, or CFRA in NSA/do-ra for access), the
UE has the full configuration already. We can therefore directly switch
to a dedicated search space, as it is already known to the UE.
... so if we want to have 1 BWP configured at any given time we need to
reconfigure BWP 1 every time. This means that since the gNB has more
than 1 BWPs (for use for different UEs), that there is a "gNB BWP ID"
(as used by the gNB), which can be any BWP ID X, and one "UE BWP ID",
which is always 1. This commit implements this distinction.
Return from triggering reconfiguration with BWP switch if BWP is the
same as before the switch, and add check to verify if BWP triggered by
switch command exists
Current FAPI slot_ahead value for WLS is too low for UL, as we see these
errors:
[NR_MAC] Unexpected ULSCH HARQ PID 14 (have 3) for RNTI 0xa68e
[NR_MAC] UE a68e expected HARQ pid 3 feedback at 586. 7, but is at 587.17 instead (HARQ feedback is in the past)
Similarly to nFAPI, scale it by mu (for mu=1 => slot_ahead=2) to give
additional time, which removes these warnings at the VNF.
E2SM-RC RRC message forwarding (e.g., to signal a new UE, measurement
reports, ...) was broken since commit d6c29b2d2c, as we accidentally
removed the E2_AGENT compilation definition from RRC layer.
Although this commit fixes the mentioned issue, it also causes undefined
references to functions defined in ran_func_rc.c file. Therefore, we
add a hack that provides the definition, and abort if we ever hit these
functions, which in theory should not happen.
Future cleanup should avoid linking in RRC and other layers into
simulators.
Fixes: d6c29b2d2c ("Fix E2_AGENT linking w.r.t. simulators ")
Testing has revealed that if PDCP drops some packets, the scheduler
falls behind with handling Slot.indication. It could be that we don't
have enough cores, which was reduced previously (from total 8 -> 2).
Reincrease to four cores to have a bit more headroom.
See-also: a18a4888ec ("Change number of cores used for OAI gNB from 8 to 2")
The PDUSessionResourceReleaseResponse message was missing the mandatory
pDUSessionResourceReleaseResponseTransfer IE in each released PDU session item. This caused Open5GS to send an error indication.
Changes:
- Add encode_ngap_pdusession_release_response_transfer() function to
properly encode the transfer structure (empty since Secondary RAT Usage
Information is optional and not used, per 9.3.4.21)
- Always include the mandatory PDUSessionResourceReleasedListRelRes IE
- Always encode the pDUSessionResourceReleaseResponseTransfer for each
PDU session item
- Fix Release Command handler to decode and log Cause from command transfer:
instead of incorrectly copying command data to response: the 2 transfer
IEs in the Command and the Response messages are different and should
not be mixed
- Split Command/Response struct type definitions
- Add missing includes
1) Remove UE Context Release Response code: there is no
such thing in the specs, it is either UE Context Release Request
(NG-RAN node initiated) or UE Context Release (AMF initiated)
(3GPP TS 38.413). The former message has only the request, no
response is defined by the specs. The code in the stack had no
purpose at all and was removed.
2) The UE Context Release Request message only contains a PDU
Session Resource List (optional) of PDU Session IDs, therefore
the use of pdusession_release_t was wrong and was refactored
Add yq to edit yaml files and add yaml-dev library in containers missing it
- nr-cu-up and some containers were missing the yaml-config support
libraries
- yq tool is required to manipulate YAML files from within the container
for Helm charts
Consistently use OAI_RNGSEED env variable for RNG
use OAI_RNGSEED env variable everywhere. Hide normal table
initialization of Ziggurat generator from outside. Fix atoi() to use
stroul()
atoi() used previously does not capture all of unsigned long (so we
could not reproduce a high seed), and its use is discouraged as it does
not detect errors. Use strtoul() instead, which allows to also use other
bases (so we can e.g., write OAI_RNGSEED=0x1234)
Hide normal table initialization of Ziggurat generator from outside to
force the usage of randominit() for RNG initialization. In this step,
remove the randominit() seed parameter and only rely on OAI_RNGSEED for
a consistent RNG initialization, as this parameter was used differently
("0" as fixed number or to force a random seed).
Now, only use OAI_RNGSEED env variable to force the usage of a fixed
seed.
Integration `2025.w48`
* !3778 CI: Update IP addresses in Aerial gNB config files
* !3659 UE NTN - Epoch time handling for Target cell
* !3772 CI: Ensure EPC is always terminated in NSA-B200 pipeline
* !3773 Fix doc for UTC timestamp
* !3759 NR UE: fix bug for SRS generation when freqDomainShift (n_shift) is not 0
* !3774 Use UL functions for Qm/R determination
* !3767 Fix DRB integrity failures during handover and re-establishment
* !3764 Avoid measGap configuration on handover in intra-freq scenarios
* !3768 Fix MIB encoding in F1SetupRequest: use encode_MIB_NR_setup instead of encode_MIB_NR
* !3771 CI build analysis: print log file errors
* !3703 Taking into account UE capabilities for TBS_lbrm layers
* !3561 Implementation of STOP exchange
* !3776 Fix reestablishment after handover
* !3763 CI: Reduce the tries to attach the UE in CI runs
* !3761 fix(FHI 7.2): PRACH frame test
* !3616 [FHI72 M-plane] Update the M-plane support to v16.01
* !3790 Correctly copy nFAPI messages
* !3779 CFRA: mark RA complete when sending Msg2 - check CI
Closes#563 and #1034
See merge request oai/openairinterface5g!3775
CFRA: mark RA complete when sending Msg2
The current contention-free random access forces a "Msg3" (which does
not exist in CFRA) to be received by a UE. Sometimes, this "Msg3" is not
received (for whatever reason), and the MAC declare that RA failed.
This is problematic, as the spec says that RA is complete once Msg2 is
received by the UE. Since the gNB cannot know when this is, simply mark
it as complete once we sent Msg2.
We still send Msg3 in CFRA, which is explained further in the commits.
Also, improve logging and stabilize an RFsim test by reducing sl_ahead.
Correctly copy nFAPI messages
All nFAPI message have copy helpers, so use that for "loading" nFAPI
messages into the L1. This also fixes a bug/error message
2. 0 no corresponding tx_data.request for dl_tti.request index 11, dropping
because the loop over DL_tti.request assumed that all messages are PDSCH
PDUs, when we can have others such as PDCCH, etc. In other words, when
looking up indices ("11" in the example above), we were checking also
inside other messages for SSB, PDCCH, etc, which is of course wrong.
That loop was an attempt to validate matching PDSCH PDUs with
TX_data.requests. This check is already done inside
phy_procedures_gNB_TX() through an assert, but this commit replaces with
the equivalent check previously inside nr_pnf_p7_get_msgs(). This is ok,
as the L1 cannot trust the scheduler (in monolithic) to provide the
correct information, either.
Fixes: eefb9da6 ("Reimplement nFAPI message exchange after msgDataTx removal")
[FHI72 M-plane] Update the M-plane support to v16.01
- retrieve the additional hardware states (oper-state, admin-state,
availability-state) and update according to the received notifications
- properly configure MIMO mode if a RU supports
- update the yang models to v16.01
- tested with Benetel v1.4.1, and added an example run in the M-plane doc
Note: backwards compatible with M-plane v05.00
Also, memory leakages fixed cause by ru_session_list_t, and xml functions
xmlReadMemory() and xmlNodeGetContent().
fix(FHI 7.2): PRACH frame test
A test was missing in the PRACH RX function of the FHI 7.2 in order to know if
the frame had a PRACH occasion. This was leading to continuous warning messages
as PRACH RX was triggered on frames in which PRACH was not expected by the
scheduler.
CI: Reduce the tries to attach the UE in CI runs
The goal of this MR is to save time in CI runs by reducing the UE attach tries
to 3 instead of 4 and UE timeout to 20 seconds, which will be incremented after
each fail, instead of 60 seconds.
Since the parent commit, CFRA is inconditionally marked complete on Msg3
reception (successful or not). This works because the current
implementation still sends a UL grant (see parent commit for details).
In this commit, handle Msg3 if received in CFRA (notably for TA and
power). Note that since we declare RA complete, UE->ra does not exist
anymore, and so an intermediate variable is introduced to capture the
CFRA flag. The code should be such that if we are in CFRA, we never
access any UE->ra variable.
All nFAPI message have copy helpers, so use that for "loading" nFAPI
messages into the L1. This also fixes a bug/error message
2. 0 no corresponding tx_data.request for dl_tti.request index 11, dropping
because the loop over DL_tti.request assumed that all messages are PDSCH
PDUs, when we can have others such as PDCCH, etc. In other words, when
looking up indices ("11" in the example above), we were checking also
inside other messages for SSB, PDCCH, etc, which is of course wrong.
That loop was an attempt to validate matching PDSCH PDUs with
TX_data.requests. This check is already done inside
phy_procedures_gNB_TX() through an assert, but this commit replaces with
the equivalent check previously inside nr_pnf_p7_get_msgs(). This is ok,
as the L1 cannot trust the scheduler (in monolithic) to provide the
correct information, either.
Fixes: eefb9da69a ("Reimplement nFAPI message exchange after msgDataTx removal")
A test was missing in the PRACH RX function of the FHI 7.2 in order to
know if the frame had a PRACH occasion.
This was leading to continuous warning messages as PRACH RX was
triggered on frames in which PRACH was not expected by the scheduler.
The current contention-free random access forces a "Msg3" (which does
not exist in CFRA) to be received by a UE. Sometimes, this "Msg3" is not
received (for whatever reason), and the MAC declare that RA failed.
This is problematic, as the spec says that RA is complete once Msg2 is
received by the UE. To avoid this, inconditionally mark RA as complete
as soon as we receive an indication of Msg3 (DTX or not).
Note that after this change, we still send a UL grant in Msg2. This is
because 38.321 §5.1.4 is not clear to me whether we should send UL grant
(it does not explicitly exclude it), and it says
> 3> if the Random Access Response includes a MAC subPDU with RAPID only:
> [...]
> 4> indicate the reception of an acknowledgement for SI request to
> upper layers.
which is NOT the case (but then I don't know/think we can have CFRA for
SI request?). Since it also works with COTS UE, I leave Msg3 for the
moment.
The reason to not directly mark RA as complete when sending Msg2 is
because of possible retransmissions in do-ra mode. In fact, in do-ra,
there might already be data awaiting. In that case, the DLSCH scheduler
schedules data _in the same slot as Msg2_, which the UE does not decode,
leading to retransmissions.
Implementation of STOP exchange
This implements the STOP.request/indication for all 3 transport mechanisms, the
VNF will send the STOP.request to the PNF, indicating it will disconnect, and
await a STOP.indication from the PNF
The WLS VNF is reworked to be able to start before the PNF, by calling call
rte_eal_init and rte_dev_probe to determine if dpdk has been initialized
properly, before calling rte_eal_init in the intended process when it is
appropriate to do so
Fix reestablishment after handover
- fix reestablishment by not re-creating LCIDs with priority set to 0 (see first
commit for more details)
- cleanup code
CI build analysis: print log file errors
The generated HTML from CI builds so far only shows the number of errors, but
not the errors themselves. This is inconvenient, as this means that developers
have to go to the logs.
This commit modifies AnalyzeBuildLogs(), which already iterates the entire file,
to store the lines containing "error:" (as it would be emitted by a compiler).
The callers of AnalyzeBuildLogs() now also print the analysis outcome in a more
concise manner.
Also, change the return parameter of AnalyzeBuildLogs() to a tuple to make the
variable handling easier, and remove the unused warnings list.
The idea is to reestablish all RLC entities (it's a new UE, and we set
reestablishRLC on all bearerrs), so we should reestablish all RLC
entities on gNB side as well, without any additional loop.
Co-authored-by: Roberto Magueta <rmagueta@allbesmart.pt>
Move the file process_addmod_bearers_cellGroupConfig() to the file where
it is used. Correctly set priorities as requested in RLC bearer
configuration.
In all cases (NSA, HO), we create LCIDs before the UE triggers random
access. Hence, process_addmod_bearers_cellGroupConfig() is not
necessary, as it just tries to recreate an LCID.
Furthermore, it includes a bug, as this function does set a wrong
priority (0), so the sorting of LCIDs is not correct. This in turn
creates problems with reestablishment, as LCID 1/SRB1 is not in the
first position, making reestablishment fail (where we assume LCID 1 be
in first position).
The actual bug of setting priorities is fixed in the next commit.
Fix MIB encoding in F1SetupRequest: use encode_MIB_NR_setup instead of encode_MIB_NR
- The DU was using encode_MIB_NR() while constructing the GNB-DU System
Information for the F1SetupRequest.
- encode_MIB_NR() encodes a full NR_BCCH_BCH_Message_t, causing the MIB to be
wrapped in a BCH container.
- This results in incorrect MIB values in the F1SetupRequest PCAP (e.g., wrong
systemFrameNumber, SCS, DMRS position, cellBarred).
- According to 3GPP TS 38.473, the MIB carried in F1AP must be encoded as a raw
NR_MIB_t.
- The correct function encode_MIB_NR_setup() encodes MIB in the required format
but was not used.
- This patch replaces encode_MIB_NR() with encode_MIB_NR_setup() to ensure correct
and standards-compliant MIB encoding in the F1SetupRequest.
Closes issue #1034.
Fix DRB integrity failures during handover and re-establishment
This MR fixes DRB integrity protection failures that occur during N2 handover
and connection re-establishment scenarios. The issues were caused by incorrect
security key handling and ciphering configuration during these procedures with
DRB integity enabled.
See merge request !3767 for more details.
Avoid measGap configuration on handover in intra-freq scenarios
During the handover, we are incorrectly configuring the measGap, even though
neighboring cells are on the same frequency. Since gNB is not expecting this
measGap, the SRS scheduling is performed. Therefore, we are periodically
receiving these logs after the handover:
[NR_MAC] Invalid timing advance offset for RNTI 58e2
[NR_MAC] Invalid timing advance offset for RNTI 58e2
[NR_MAC] Invalid timing advance offset for RNTI 58e2
[NR_MAC] Invalid timing advance offset for RNTI 58e2
[NR_MAC] Invalid timing advance offset for RNTI 58e2
[NR_MAC] Invalid timing advance offset for RNTI 58e2
These logs occur at a time when UE is performing a MeasGap operation and not
sending the SRS, while gNB thinks it will receive the SRS, but will not receive
any SRS.
This MR resolves this issue, and after the handover, these logs no longer
appear.
CI: Update IP addresses in Aerial gNB config files
This MR updates the NG-AMF and NG-U IP addresses in both Aerial configuration
files (standard and UL-heavy) following the IP address change on GH1.
Use UL functions for Qm/R determination
During refactoring, the wrong functions and correspondingly tables have
been used to calculate UL TB size. Fix through correct functions.
This should fix these error messages:
3624774.778195 [MAC] E (nr_get_Qm_dl:2034) Invalid MCS table index 3 (expected in range [0,2])
3624774.778207 [MAC] E (nr_get_code_rate_dl:2066) Invalid MCS table index 3 (expected in range [0,2])
3624774.778211 [NR_MAC] E (nr_compute_tbs:63) Error in compute TBS with a NULL input, returning NULL TBS
Fixes: 9449f777 ("Remove TBS table and recompute on demand")
NR UE: fix bug for SRS generation when freqDomainShift (n_shift) is not 0
According to TS 38.211 section 6.4.1.4.3, the frequency domain shift value
n_shift is from higher-layer parameter freqDomainShift. The quantity n_RRC
is given by higher-layer parameter freqDomainPosition. Also corrected
k_0_overbar_p calculation formula to align with standard.
Fix doc for UTC timestamp
After merging !3751 (merged), the UTC timestamp now prints only the time.
Update the documentation to reflect this simplified format.
UE NTN - Epoch time handling for Target cell
In case of Handover, NTNconfig sent in RRCreconfiguration triggering handover
contains epoch time wrt timing of Target cell. NTNconfig in RRC needs to be
processed only after timing is acquired on the target cell.
In case of Target cell, epoch time is the sfn nearest to the frame timing of the
target cell.
During refactoring, the wrong functions and correspondingly tables have
been used to calculate UL TB size. Fix through correct functions.
This should fix these error messages:
3624774.778195 [MAC] E (nr_get_Qm_dl:2034) Invalid MCS table index 3 (expected in range [0,2])
3624774.778207 [MAC] E (nr_get_code_rate_dl:2066) Invalid MCS table index 3 (expected in range [0,2])
3624774.778211 [NR_MAC] E (nr_compute_tbs:63) Error in compute TBS with a NULL input, returning NULL TBS
Fixes: 9449f777cc ("Remove TBS table and recompute on demand")
This change updates the NSA-B200 CI pipeline to guarantee that the EPC is
properly terminated regardless of pipeline success or failure. This avoids
leaving EPC processes running after failed test.
The generated HTML from CI builds so far only shows the number of
errors, but not the errors themselves. This is inconvenient, as this
means that developers have to go to the logs.
This commit modifies AnalyzeBuildLogs(), which already iterates the
entire file, to store the lines containing "error:" (as it would be
emitted by a compiler). The callers of AnalyzeBuildLogs() now also print
the analysis outcome in a more concise manner.
Also, change the return parameter of AnalyzeBuildLogs() to a tuple to make
the variable handling easier, and remove the unused warnings list.
- The DU was using encode_MIB_NR() while constructing the GNB-DU System Information for the F1SetupRequest.
- encode_MIB_NR() encodes a full NR_BCCH_BCH_Message_t, causing the MIB to be wrapped in a BCH container.
- This results in incorrect MIB values in the F1SetupRequest PCAP (e.g., wrong systemFrameNumber, SCS, DMRS position, cellBarred).
- According to 3GPP TS 38.473, the MIB carried in F1AP must be encoded as a raw NR_MIB_t.
- The correct function encode_MIB_NR_setup() encodes MIB in the required format but was not used.
- This patch replaces encode_MIB_NR() with encode_MIB_NR_setup() to ensure correct and standards-compliant MIB encoding in the F1SetupRequest.
Closes issue #1034.
Problem:
During N2 handover with integrity protection (NIA1/NIA2), the target gNB
was disabling ciphering when configuring SRB1 security, while the UE
continued using the old security context from the source gNB until it
received and processed the RRC Reconfiguration with masterKeyUpdate. The
first PDUs sent after CFRA were still ciphered with the old keys, but the
target gNB had ciphering disabled, causing it to skip deciphering and
attempt integrity verification on ciphered data, leading to MAC-I
mismatches and integrity failures.
Specification Reference:
According to TS 33.501 section 6.11, "the UE shall keep the K gNB used in
the source cell until the handover or a connection re-establishment has been
completed successfully". This means the UE continues using the old security
context (old KRRCint, KRRCenc) until it receives and processes the RRC
Reconfiguration with masterKeyUpdate. The target gNB must therefore enable
ciphering during handover setup to correctly decipher and verify integrity
of PDUs sent with the old security context before the UE switches to the new
keys.
Root Cause:
The code was calling nr_rrc_pdcp_config_security(UE, false) during
handover setup, which disabled ciphering. This was incorrect because:
1. The UE already has security active from the source gNB
2. The UE continues using old ciphered keys until masterKeyUpdate
3. The UE sends ciphered PDUs immediately after CFRA succeeds
4. The target gNB must be able to decipher these PDUs to verify integrity
Why it only manifested when drb_integrity = "yes":
The bug was always present, but only caused visible failures when
integrity verification was enabled. When drb_integrity = "no", the config
typically also sets integrity_algorithms to only NIA0, resulting in
UE->integrity_algorithm = 0, which causes has_integrity = 0 for SRB1,
skipping integrity verification and hiding the underlying ciphering bug.
When drb_integrity = "yes", integrity_algorithms typically includes
NIA1/NIA2, resulting in has_integrity = 1 for SRB1, causing integrity
checks to run on ciphered data and fail.
Fix:
Change nr_rrc_pdcp_config_security(UE, false) to
nr_rrc_pdcp_config_security(UE, true) during handover setup to enable
ciphering immediately, allowing the target gNB to correctly decipher and
verify integrity of PDUs sent with the old security context.
Note: This fix is specific to handover. During initial context setup,
ciphering should remain disabled until SecurityModeComplete is received,
as the UE hasn't activated ciphering yet at that point.
During re-establishment, new KgNB* is derived, requiring new UP keys (KUPint,
KUPenc) to be sent to CU-UP. When do_drb_integrity = true, CU-UP needs the
updated integrity keys to verify DRB PDUs. Without this update, CU-UP uses
old keys while the UE uses new keys, causing integrity failures.
The fix ensures security info is always sent during re-establishment,
which is critical for DRB integrity.
Instead of using the projected velocity and acceleration vectors,
calculate vel_sat_gnb and acc_sat_gnb so the delay is correct for
epoch_time, epoch_time + 5 seconds and epoch_time + 10 seconds.
Separate timing_advance (N_TA) from timing_advance_ntn (N_common_TA_adj + N_UE_TA_adj)
to keep N_TA when updating N_common_TA_adj + N_UE_TA_adj.
Fixes#981
Instead of trying to estimate N_UE_TA_adj with a second degree polynomial,
we introduce orbit propagation to calculate N_UE_TA_adj with higher accuracy.
When we receive the satellite ephemeris data consisting of the satellite position vector
and the satellite velocity vector, we calculate parameters for orbit propagation, assuming
a circular orbit in the plane created by the satellite position vector and the satellite
velocity vector. This is done in the function prepare_ue_sat_ta().
Every millisecond, we use these parameters together with the time since epoch to calculate
the satellite position on that orbit and from this the reound-trip-time between UE and the
satellite, what corresponds to N_UE_TA_adj. This is done in the function apply_ntn_timing_advance().
In case of Handover, NTNconfig sent in RRCreconfiguration triggering handover contains epoch time wrt
timing of Target cell. NTNconfig in RRC needs to be processed only after timing is acquired on the target cell
In case of Target cell, epoch time is the sfn nearest to the frame timing of the target cell.
Integration `2025.w46`
* !3754 NR UE: correctly provide measured SSB SINR value from PHY to MAC
* !3666 NTN: Fixing variable ULDLduplex issue for NTN bands
* !3747 SDAP: guard RX header parsing with enable_sdap and init per-entity
* !3729 DCI 00 alt size fix
* !3753 gNB: fix MAC TA command scheduling if measurement gaps are configured
* !3722 [NGAP] Fix incorrect AMF Set ID type (uint8 → uint16) causing AMF lookup failure
* !3745 Collection of small fixes
* !3755 CI: Increase tested UL throughput on Aerial pipeline using 2L UL
* !3752 [MAC] Add UL total/used aggregated MAC stats; [E2 agent] Properly calculate used UE PRBs in KPM
* !3707 Cleanup phy_procedures_gNB_uespec_RX
* !3750 Handling newly opened UE issues
* !3751 Update log header format to align log output
* !3757 Remove schedule response and update L1 threading documentation
* !3748 Refactor imscope
* !3760 gNB: modify RLC configuration applied for SRB1 during RRCReestablishment
* !3684 PDU Session Release
Closes#867, #960, #1025, #1024, #1026, #1031, #1030, and #1012
See merge request oai/openairinterface5g!3756
PDU Session Release
This MR implements end-to-end PDU Session Release functionality
according to 3GPP TS 38.413 and TS 38.331 specifications.
Reason for Change Previous implementation had incomplete and wrongly
places tunnel cleanup during PDU session release. UP cleanup shall be
done at CUUP, RRCReconfiguration shall be sent after retrieval of
updated CellGroupConfig from the DU. This implies F1 and E1 exchanges
during PDU session release procedure.
Major Changes:
1. RRC PDU Session Release: DRBs and PDU session teardown in NGAP PDU
Session Release Response callback
- Helper Functions: Introduced rm_pduSession,
find_drb_by_pdusession_id and rm_drbs() helpers to locate and clean
up DRBs linked to a specific PDU session
- Targeted Cleanup: RRC PDU Session and per-session DRB removal in
rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE()
- Status Cleanup: Removed unused PDU_SESSION_STATUS_RELEASED status
2. RRC PDU Session Release: Refactor
rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND
- Any PDU session in the pdusession_release_params list that is
present in the RRC list can be set to release, regardless of its
status
- Function Signature Update: Updated function signature and other
minor changes
- Response Handling: rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE is
sent upon completion of RRCReconfiguration
3. RRC PDU Session Release: add missing procedures E1AP Integration:
- Populates E1AP Bearer Modification for each to be released session
- PDCP Enhancement: Added nr_pdcp_release_drbs() to remove all DRBs
linked to a given PDU session in CUUP
- GTP-U Cleanup: GTP tunnel teardown handled in CUUP
e1_bearer_context_modif() using correct F1 or N3 GTP instance
4. NR PDCP/GTP:
- Enhanced Tunnel Deletion Logic: Separate handling for N3 tunnels (1
per PDU session) and F1-U tunnels (1 per DRB)
- New PDCP API Function: Added nr_pdcp_get_drb_ids_for_pdusession()
function to retrieve all DRB IDs associated with a specific PDU
session
5. RRC PDU Session Release: F1AP-based UE Context Modification:
- Replaced direct RRC message transfer with F1AP UE Context
Modification Request for proper retrieval from DU
- Cell Group Configuration: handling of updated CellGroupConfig from
DU ensures DRB release at CU
6. Docs and testing:
- Added PDU session add/remove test cases to 25 PRB RFSIM pipeline
- Documentation: Added PDU Session Release sequence diagram
- Telnet Commands: Added ci command to trigger NGAP PDU Session
Release and ciUE command to trigger establishment of a new PDU
Session
7. Additional fixes:
- UE RLC Management: ensure release of RLC entities
- Unify NG delay control before calling the RRC NGAP handler, for both
Setup and Release
8. Code Cleanup: Cleaned up unused GTP teardown functions.
Closes#867
- Add delayed_action_state_t in the UE context for ongoing delayed action
- Move delay check and timer re-enqueue to rrc thread in rrc_gNB.c (rrc_delay_transaction)
- Call delay before NGAP setup/release handlers; remove local delay logic from rrc_gNB_NGAP.c
- Clear on RRCReconfigurationComplete (reset_delayed_action)
Closes#960
- Enable telnet server on VNF (gNB) and UE in docker-compose.yaml
- Add new test cases for PDU session management:
* Add PDU session via UE telnet
* Release PDU session via telnet
* Verify connectivity after PDU session release
- Integrate telnet commands into existing container_5g_rfsim_u0_25prb.xml pipeline
- Test cases added before undeploy step in proper execution order
This commit introduces a new telnet server command `pdu_session_release` to
manually trigger the NGAP PDU Session Release Command message from the telnet ci shell.
This is useful for integration testing of PDU session teardown behavior.
Details:
- Added `trigger_ngap_pdu_session_release()` to send NGAP_PDUSESSION_RELEASE_COMMAND
to the RRC task, targeting the specified `gNB_ue_ngap_id`.
- The command currently releases PDU session ID 10 (hardcoded).
- Hooked into telnet shell with command: `pdu_session_release [gNB_ue_ngap_id]`
Usage example:
telnet > pdu_session_release 1
We need to keep PDU sessions and DRBs in list until the NGAP PDU Session Release Response is sent.
* Introduced find_drb() and remove_drbs_by_pdu_session() helpers to locate
and clean up DRBs linked to a specific PDU session
* Targeted per-session DRB removal in rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE()
* Ensures DRBs for unaffected PDU sessions remain intact
* Remove unused PDU_SESSION_STATUS_RELEASED status: keeping this status is no longer relevant
since the PDU sessions are effectively removed from the RRC lists
Closes#867
Also, refactor rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND
3GPP TS 38.413 8.2.2 PDU Session Resource Release says:
> upon reception the NG-RAN node shall execute the release of the requested PDU sessions.
> For each PDU session to be released the NG-RAN node shall release the corresponding
> resources over Uu and over NG, if any.
Therefore, any PDU session in the pdusession_release_params list that is
also present in the RRC list can be set to release, regardless of its status.
The function signature was also updated along with other minor changes.
The partial-tunnel deletion API was buggy and redundant:
* e.g. It erased entries from globGtp.te2ue_mapping but never erases
the corresponding entries from inst->ue2te_mapping[ue].bearers
All current use cases are already covered by:
* newGtpuDeleteOneTunnel() for targeted deletion
* newGtpuDeleteAllTunnels() for full cleanup
Call sites should explicitly loop over newGtpuDeleteOneTunnel()
if multiple tunnels need removal.
This commit implements proper PDU Session Release handling across
RRC, PDCP, F1AP, E1AP to ensure clean resource cleanup when
a PDU session is terminated.
Key changes:
NGAP:
In `rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND()`:
* Populates E1AP Bearer Modification for each released session
* If a CU-UP is connected, triggers `bearer_context_mod()` for PDU teardown
PDCP:
* Added `nr_pdcp_release_drbs()` to remove all DRBs linked to a given PDU session
* Called from `e1_bearer_context_modif()` for correct clean-up during session release
F1AP UE Context Modification:
Replace direct RRC message transfer with F1AP UE Context Modification Request
to properly handle PDU session release according to 3GPP TS 38.331.
3GPP TS 38.331 `5.3.5.6.4 DRB release` says: whether or not the RLC and MAC entities associated
with a PDCP entity are reset or released is determined by the CellGroupConfig. Thus,
updated CellGroupConfig needs to be received by the UE. This has to be retrieved by CUCP
from the DU. Therefore:
After receiving an NGAP_PDUSESSION_RELEASE_COMMAND, the CUCP shall:
1) forward (store for later) the NAS PDU to the UE, if present as per 3GPP TS 38.413, and
2) send a UE Context Modification to the DU with the list of DRBs to release
and the RRC container (RRCReconfiguration with NAS PDU)
After reception of UE Context Modification Response, the list of drbs to release
is prepared based on PDU session status PDU_SESSION_STATUS_TORELEASE
in rrc_gNB_generate_dedicatedRRCReconfiguration and then encoded
in drb_ToReleaseList for a new RRCReconfiguration with the new cellGroupConfig.
Key changes:
* rrc_gNB_generate_dedicatedRRCReconfiguration_release() now uses F1AP UE Context
Modification Request instead of direct RRC transfer
* Only DRBs to be released are now added to the list.
* The ASN.1 memory allocation is entirely done in build_RRCReconfiguration_IEs
* No longer needed to store ASN1 struct in UE context
GTP-U:
* Previous implementation had incomplete tunnel cleanup during PDU session release
- Missing distinction between N3 (PDU session level) and F1-U (DRB level) tunnels
- Lack of proper DRB identification for F1-U tunnel deletion
Major Changes:
* GTP tunnel teardown now handled in `e1_bearer_context_modif()` using the correct
F1 or N3 GTP instance (`newGtpuDeleteOneTunnel()`)
* Enhanced Tunnel Deletion Logic (cucp_cuup_handler.c):
- Separate handling for N3 tunnels (1 per PDU session) and F1-U tunnels (1 per DRB)
- Added proper DRB identification for F1-U tunnel cleanup
- Improved error handling with detailed logging for each tunnel deletion
- Enhanced logging to distinguish between N3 and F1-U tunnel operations
* New PDCP API Function (nr_pdcp_oai_api.c/h):
- Added nr_pdcp_get_drb_ids_for_pdusession() function
- Enables retrieval of all DRB IDs associated with a specific PDU session
- Supports proper F1-U tunnel cleanup by providing DRB identifiers in CUUP
* Enhanced GTP Interface (gtp_itf.cpp/h):
- Modified newGtpuDeleteOneTunnel() to accept tunnel_type parameter
- Improved logging to distinguish between PDU session and DRB tunnel types
- Better error messages for tunnel deletion failures
- Enhanced debugging information for remaining tunnels
Clean-up:
* Ensured xid tracking works consistently between PDU Session Establishment (with NAS PDU)
and dedicated RRCReconfiguration
* Add function to release GTP-U tunnel in Bearer Context Modification Request handler
* Do not send rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE when no PDU session are to
be released: it is sent upon completion of the RRCReconfiguration and needs to contain
released PDU Sessions (mandatory IE), therefore it is no necessary to send it in case
there is no PDU session to release.
Related to #867
Co-authored-by: rmagueta <rmagueta@allbesmart.pt>
gNB: modify RLC configuration applied for SRB1 during RRCReestablishment
TS 38.331 clause 5.3.7.4 specifies to apply the configuration defined in
9.2.1 for SRB1 at UE side. This implies that the gNB also has to apply
sn_field_length = 12, but there are no implications on the other RLC
parameters.
As wrong timer values break SRB1 e.g. for long RTT NTN scenarios, this
commit switches to using the RLC timer values provided in the
configuration file. Currently we still set poll_pdu, poll_byte and
max_retx_threshold to the values defined in 9.2.1, but this can be
changed.
Refactor imscope
This MR refactors imscope by introducing changes to the default layout
in the config file imgui.ini. The global settings are moved to a new
menu item. This modified layout is intended as a suggestion subject to
change based on feedback. This MR also adds PDCCH LLR and IQ plots to
the UE scope and set axes to AutoFit by default.
The MR has a screenshot of the new layout.
Remove schedule response and update L1 threading documentation
This merge requests removes the somewhat superfluous "schedule response"
mechanism. "schedule response" was run after running the scheduler
itself and copied various FAPI messages into a global msgDataTx
structure from which the various TX/RX jobs were triggered. It is not
necessary, though, given that the scheduler is run inside the tx_func()
(running the TX jobs of the L1), and so the scheduler output FAPI
messages can directly be read into a variable of the existing
NR_Sched_Rsp_t type. This allows to delete a couple of hundred lines of
code (while retaining functionality), and simplifies the msgDataTx type
(which is still there to trigger TX job (including the scheduler) from
the ru thread).
In short, prior, there was this call chain:
- tx_func() calls run_scheduler_monolithic() (through fptr
NR_slot_indication())
- get some memory through allocate_sched_response() which has enough
space for NR_Sched_Rsp_t type variable
- call the scheduler and fill the variable
- call nr_schedule_response() (through fptr NR_schedule_response())
which copies into L1: to msgDataTx for TX, to separate structures
for RX
this is changed to
- tx_func() runs one message at a time, hence we can use memory in the
data segment for NR_Sched_Rsp_t. It calls run_scheduler_monolithic()
through the fptr
- pointers into NR_Sched_Rsp_t are passed to the scheduler, which
fills as before
- we return, memory is in its right place and does not need an extra
copy.
Additionally, this merge request updates documentation on threading and
cleans up some unused code along the way.
Update log header format to align log output
The new format:
- left-aligns the log header name and enforces a minimum width of 6 characters,
padding shorter names with spaces while allowing longer names to be printed in
full
- shortens UTC timestamp
- align function names to 32 characters
Example output:
[19:51:34.647930] [NGAP] I (ngap_gNB_decode_initiat:100) Handover Resource Allocation initiating message
[19:51:34.648539] [NGAP] D (decode_ng_handover_requ:267) AllowedNSSAI.list.count 2
[19:51:34.648586] [NGAP] I (ngap_gNB_handle_handove:728) Received NG Handover Request from AMF OAI-AMF (ID=1)
[19:51:34.648627] [NR_RRC] I (rrc_gNB_process_Handove:1199) Received Handover Request (on NR Cell ID=11111111, PCI=1)
[19:51:34.648647] [NR_RRC] A (rrc_gNB_create_ue_conte:230) [--] (cellID 0, UE ID 1 RNTI ffff) Create UE context: CU UE ID 1 DU UE ID 4294967295 (rnti: ffff, random ue id ffffffffffffffff)
[19:51:34.648659] [NR_RRC] A (set_UE_security_algos:692) [--] (cellID 0, UE ID 1 RNTI ffff) Selected security algorithms: ciphering 0, integrity 2
Reimplement nFAPI message exchange between L1 and L2 following the
changes in parent commit removing msgDataTx.
Avoid direct calls and use NR_IF_module fptrs to avoid linking problems.
allowing to remove some function definitions that are not needed.
Note: after this commit, monolithic works but nFAPI operation is broken
and fixed in the next commit, to keep the changes small(er). All
simulators work.
This commit removes the use of msgDataTx's intermediate buffers for FAPI
messages and the call of the "Schedule response". The latter incurs an
additional copy of FAPI messages for the TX chain (for the RX chain, it
is and will remain there) which we can avoid.
Instead, it uses an NR_Sched_Rsp_t-typed variable sched_response to
store the results of the scheduler when called from tx_func(). Thus, the
scheduler remains unchanged (it gets a pointer to where to put FAPI
messages), but we don't call nr_schedule_response() to then copy FAPI
messages into the L1, but have them in a local variable sched_response.
sched_response on on the data segment, as it is big and would overflow
the stack; at the same time, this is ok because only one tx_func() runs
at a time.
Since we don't use allocate_sched_response() anymore, we don't need
deref_sched_response().
clear_slot_beamid() is moved to tx_func(), as it was called in
nr_schedule_response().
Since the "intermediate" NR_gNB_DLSCH_t structure groups both the
DL_tti_pdsch and TX_data.req structures, a pointer has been created to
point to pdsch_pdu. This affects a number of simulators, as they have to
put some messages on the stack:
- nr_dlschsim: put the corresponding variable on the stack
- nr_pbchsim: a new array for the SSB PDUs has been introduced
Further, these changes are now necessary:
- nr_dlsim: there were variables "rel15" and "pdsch_pdu_rel15" that
point to the same PDSCH PDU. At least "rel15" would not exist, as the
corresponding pointer is now populated in phy_procedures_gNB_TX(), and
we therefore refer to the single PDSCH PDU variable with
"pdsch_pdu_rel15", but at the place where "rel15" used to be
initialized.
- nr_ulsim: use nr_save_ul_tti_req() to load PDUs into the RX chain
instead of nr_schedule_response(), which does not exist anymore.
The next commit will remove msgDataTx. We can therefore not use
msgDataTx to retain the PDSCH/DLSCH variables, and move them to the gNB.
Note that the only reason for NR_gNB_DLSCH_t after this commit is to
hold various large buffers (c, b, f). Future work could be done to
remove this, in which case the array inside PHY_VARS_gNB could be
deleted.
On this occasion, clean up the use of init_DLSCH_struct() and
reset_DLSCH_struct() (renamed destroy_DLSCH_struct()) and centralize
their call in phy_init_nr_gNB()/phy_free_nr_gNB(), and correct
simulators accordingly.
TS 38.331 clause 5.3.7.4 specifies to apply the configuration defined in 9.2.1 for SRB1 at UE side.
This implies that the gNB also has to apply sn_field_length = 12, but there are no implications on the other RLC parameters.
As wrong timer values break SRB1 e.g. for long RTT NTN scenarios, this commit switches to using the RLC timer values provided in the configuration file.
Currently we still set poll_pdu, poll_byte and max_retx_threshold to the values defined in 9.2.1, but this can be changed.
Cleanup phy_procedures_gNB_uespec_RX
phy_procedures_gNB_uespec_RX is too long function with too long lines of code,
this commit only shorten lines and improve a bit the readability
[MAC] Add UL total/used aggregated MAC stats; [E2 agent] Properly calculate
used UE PRBs in KPM; [CI] Simplify and improve the Undeploy_Object() and
implement Stop_Object()
- Create common dlul_mac_stats_t struct for both DL and UL total/used aggregated
PRBs
- Use correct unit [%] for RRU.PrbTotDl and RRU.PrbTotUl , instead of [PRBs]
- Use correct unit [Mb] for DRB.PdcpSduVolumeDL and DRB.PdcpSduVolumeUL [kb]
- Implement Stop_Object() (docker compose stop = SIGTERM)
- Simplify the Undeploy_Object() function
- Improve the logging for Deploy/Undeploy_Object() functions
- OAI-FlexRIC CI: properly stop all the containers (one by one or a subgroup of
running containers), and rename oai-flexric to nearRT-RIC container
CI: Increase tested UL throughput on Aerial pipeline using 2L UL
The goal of this MR is to activate the use of 2-layer uplink by enabling SRS
and to increase the tested UL throughput in CI.
The new format left-aligns the component name and enforces a minimum width
of 7 (log component) characters, padding shorter names with spaces after
the closing "]".
Example output:
[14:05:43.395376] [E1AP] I releasing UE 1
[14:05:43.395400] [GTPU] I [91] UE ID 1: Delete all tunnels (1 tunnels)
[14:05:43.395414] [NR_RRC] A [DL] (cellID bc614e, UE ID 1 RNTI 8e27) Send RRC Release
[14:05:43.395431] [RRC] I UE 1: received bearer release complete
[14:05:43.424551] [RLC] W Remove UE 36391
[14:05:43.424597] [NR_RRC] I removed UE CU UE ID 1/RNTI 8e27
[14:05:43.424773] [NR_RRC] A [--] (cellID bc614e, UE ID 1 RNTI 8e27) Remove UE context
[14:05:43.425205] [NR_MAC] I Remove NR rnti 0x8e27
[14:05:43.582158] [HW] W Lost socket
^C
** Caught SIGTERM, shutting down
Returned from ITTI signal handler
[14:05:43.948721] [GNB_APP] I stopping nr-softmodem
[14:05:43.948746] [PHY] I Killing gNB 0 processing threads
[14:05:44.574818] [PHY] I Stopping RU 0 processing threads
[14:05:44.575000] [PHY] I RU 0 RF device stopped
[14:05:44.575006] [GNB_APP] I turned off RU rfdevice
Prior to this change, when no "level" option is given to the logging
module, we see
[PHY] RU 0 RF started cpu_meas_enabled 0
[HW] No connected device, generating void samples...
with three spaces, which is too much. This change reduces the amount of
spaces to 1 without log level.
Co-authored-by: Robert Schmidt <robert.schmidt@openairinterface.org>
We probably almost never care about the date, but it takes a lot of
space. Remove it; if somebody needs the full time stamp including the
date, we could still add it with a new option.
1. Rename oai-flexric to nearRT-RIC. FlexRIC is a project combining nearRT-RIC, xApps, and E2 agent emulators.
2. Instead of undeploying all the containers at the same time, and not checking the logs for xApps and nearRT-RIC, do the following:
- Stop containers (docker compose stop) - one or subgroup of running containers in the following order:
a) xapp-kpm-moni
b) xapp-kpm-rc
c) xapp-gtp-mac-rlc-pdcp-moni
d) oai-nr-ue oai-nr-ue2
e) oai-gnb
f) nearRT-RIC
- Undeploy containers (docker compose down), collect and analyze all the logs.
For some test cases, we might want to stop a service earlier. This
functionality is done by StopObject().
Test log collection is still done by UndeployObject(), which will
collect the logs of all services (at that point, stopped or not).
GetRunningServices() was returning all services, running or stopped.
Hence, rename to reflect what this function does, and rewrite slightly
to better capture what is actually happening. Also, don't return the
container ID, as we don't use it.
Call stop on all services, as we will down the deployment right after.
The list of services is still used to retrieve logs.
Remove a stray "return False", which would sometimes prevent us from
seeing all error messages.
Collection of small fixes
A few fixes needed while testing FHI libraries
- set subcarrier spacing in PUSCH PDU in NRUE
- a set of two LOG_Ds that prints out the PUSCH allocation on gNB & UE
[NGAP] Fix incorrect AMF Set ID type (uint8 → uint16) causing AMF lookup failure
This PR fixes issue #1012 , a data type issue related to the AMF Set ID used
during UE RRC reestablishment. The AMF Set ID was mistakenly declared as uint8_t
instead of uint16_t, even though it is a 10-bit field as specified in 3GPP TS
23.003 section 2.10.1. As a result, AMF Set IDs greater than 255 were truncated,
leading to failed AMF lookups and the following warning: No matching AMF found
for PLMN (MCC=%03d MNC=%0*d) and AMF SetID=%u.
Verified reestablishment succeeds with AMF Set IDs >255.
DLSCH encoding is not concerned with HARQ processes directly. Instead,
it gets the redundancy version and encodes a specific redundancy version
for a given TB. The rest is up to the MAC, the L1 is stateless in that
regard. Hence, remove the HARQ type and put it into DLSCH, which also
simplifies the code elsewhere.
Similarly to the parent commit, simplify the array type to the FAPI PDU
towards further refactoring, and encapsulate the code in a function for
easier reuse in a later refactoring step.
Note on ZP-CSI: after this commit, we continue treating CSI PDUs. The
prior code was returning, which I think is wrong (as this information is
only for the currently treated CSI-RS PDU).
There is no point in tracking the "active" state: the SSB PDU will be
sent from MAC to L1, encoded, and then "discarded" (by marking the
number of SSB PDUs as 0). Hence, remove this intermediate type.
According to TS 38.211 section 6.4.1.4.3, the frequency domain shift value n_shift
is from higher-layer parameter freqDomainShift.
The quantity n_RRC is given by higher-layer parameter freqDomainPosition.
Also corrected k_0_overbar_p calculation formula to align with standard.
Problem:
- GTP-U logs showed negative TEID values (e.g., -1943516315) due to signed/unsigned
conversion. Due to wrong conversion from uint32_t to int and overflow caused negative values.
- TEID values were inconsistently formatted across different log statements, due to
mixed use of %d, %u, %x formats for TEID logging. Made debugging and troubleshooting difficult
Changes:
1. Fixed signed/unsigned conversion bug: use teid_t. Prevents overflow when TEID values exceed int range.
2. Standardized TEID logging format: all TEID values now use '0x%x' hexadecimal format.
Consistent 'TEID' capitalization throughout
According to TS 38.463 - clause 9.2.2.4 and 9.3.3.12.
Also, fix response message by encoding choice IE only
with presence of modified PDU sessions.
Co-authored-by: rmagueta <rmagueta@allbesmart.pt>
Both (DL) PDCCH and UL PDCCH PDU types are fundamentally of the same
type, so correct the array's type to facilitate refactoring later (a
later commit will reuse a single "generate DCI" function for both
cases).
gNB: fix MAC TA command scheduling if measurement gaps are configured
In the current implementation, if UE transmission is interrupted via
nr_mac_interrupt_ue_transmission(), UE_sched_ctrl.ta_frame is modified to be
the previous frame avoiding TA scheduling in the measurement gap. So the next
scheduled TA is shifted to be in 99 frames. As there are other measurement gaps
before that, the scheduled TA is always shifted, but actually never reached,
effectively disabling the MAC TA commands.
To fix this, UE_sched_ctrl.ta_frame is changed to not indicate the last TA
command transmission, but the next one. This allows to check in
nr_mac_interrupt_ue_transmission() if the next TA command transmission is within
the measurement gap and if so shift it to just after that gap.
DCI 00 alt size fix
DCI size for format 00 and 10 should be equal so we need to compute the size of
the alternative format when computing the size of DCIX0. There was a bug where
the alt_size input (0 in that case) was taken into account also when computing
that alternative size, resulting in an alt_size of 0. Possibly easier to
understand by looking at the code then reading this description.
For now, only DL/UL MAC stats.
This commit fixes the "RRU.PrbTotDl" and "RRU.PrbTotUl" measurement calculation
to align with the TS 28.552 specifications.
DL stats (aggregated total and used PRBs) previosuly used only for O1 interface,
now finds the purpose for E2 interface as well.
New UL stats (aggregated total and used PRBs) serve for E2 interface only.
Co-authored-by: Teodora Vladić <teodora.vladic@openairinterface.org>
SDAP: guard RX header parsing with enable_sdap and init per-entity
!3519 (merged) refactored the SDAP to use the QFI from the header rather than
pass it to the rx function and got rid of the initialization of QFI to -1.
However, entity roles are stored into the drb2qfi table, and the indexing
implies that the QFI is known.
While in TX it is not an issue since packets are forwarded based on the QFI,
in RX the QFI can only be parsed from the header, therefore if headers are
disabled (--enable_sdap) the QFI is not there and it is wrong to access the
header (buf[0]) and looking for it.
This commit adds enable_sdap to nr_sdap_entity_t and initialize it in
nr_sdap_add_entity() from sdap->role (disabled when NO_SDAP_HEADER).
In nr_sdap_rx_entity(), only parse buf[0] for QFI and derive sdap_ul_rx/
sdap_dl_rx when enable_sdap is true; otherwise, keep offset=0 and forward
payload unchanged.
NTN: Fixing variable ULDLduplex issue for NTN bands
- Duplex is assumed to be static but for NTN bands (and also for some non NTN
bands), it is not static.
- Tx-RX Duplex is defined in section 5.4.4 of 38.101-5 (for NTN) specs v1809
- For example: In NTN-OTA testing, the GEO satellite operator configured in
band 256 the DL, UL frequencies with duplex of 185Mhz.
Using nFAPI introduces additional delays. At the same time, RFsim does
not run in real-time, and we can allow a low sl_ahead, as RFsim will
"wait" for the gNB.
Therefore, reduce sl_ahead to ensure that the response window does not
run out during handling of RA in nFAPI.
In the current implementation, if UE transmission is interrupted via nr_mac_interrupt_ue_transmission(),
UE_sched_ctrl.ta_frame is modified to be the previous frame avoiding TA scheduling in the measurement gap.
So the next scheduled TA is shifted to be in 99 frames. As there are other measurement gaps before that,
the scheduled TA is always shifted, but actually never reached, effectively disabling the MAC TA commands.
To fix this, UE_sched_ctrl.ta_frame is changed to not indicate the last TA command transmission, but the
next one. This allows to check in nr_mac_interrupt_ue_transmission() if the next TA command transmission
is within the measurement gap and if so shift it to just after that gap.
!3519 refactored the SDAP to use the QFI from the header rather
than pass it to the rx function and got rid of the initialization
of QFI to -1.
However, entity roles are stored into the drb2qfi table, and the
indexing implies that the QFI is known. While in TX it is not an
issue since packets are forwarded based on the QFI, in RX the QFI
can only be parsed from the heaedr, therefore if headers are
disabled (--enable_sdap) the QFI is not there and it is wrong to
access the header (`buf[0]`) and looking for it.
This commit adds `enable_sdap` to `nr_sdap_entity_t` and initialize
it in `nr_sdap_add_entity()` from `sdap->role`
(disabled when `NO_SDAP_HEADER`). In `nr_sdap_rx_entity()`, only
parse `buf[0]` for QFI and derive `sdap_ul_rx`/`sdap_dl_rx` when
`enable_sdap` is true; otherwise, keep `offset=0` and forward
payload unchanged.
Integration `2025.w45`
* !3736 fix bugs in scope for pdcch, and optimize cpu cost of pdcch decoding
* !3743 NR UE: fix PDCCH LLR indexing for different search space RB sizes
* !3739 Bugfix: save old tunnel info to remain the user plane connection while rolling back to source DU due to handover failure
* !3742 Simplify node management in CI, handle SIGINT
* !3670 PRS bug fix and CI Integration
* !3746 Fix unsigned to signed decoding parameters to allow for 'no affinity'/'no pin' threads to CPUs
* !3738 CI: Add new Jenkinsfiles
Closes#984 and #1021
See merge request oai/openairinterface5g!3744
CI: Add unified Jenkinsfile for all test pipelines
This MR introduces a single Jenkinsfile to cover all current CI test pipelines
Improvements:
- correct reporting of the start timestamp in the HTML report
- harmonize log collection - always collect as test_logs_${env.BUILD_ID}.zip
Fix unsigned to signed decoding parameters to allow for 'no affinity'/'no pin'
threads to CPUs
By default, 'L1_rx_thread_core', 'L1_tx_thread_core', 'ru_thread_core' are set
to '-1' but the values were decoded from config file as unsigned instead of
signed types, thus, it was not allowing to set them with '-1' from config file.
PRS bug fix and CI Integration
- Fix the bug in PRS channel estimation while copying memory to compute the
impulse response
- Integrate PRS testing to CI
Simplify node management in CI, handle SIGINT
- Make a single <node> XML step entry common to all XML steps to harmonize code
- Handle SIGINT to make it possible to more easily stop the CI script.
Bugfix: save old tunnel info to remain the user plane connection while rolling
back to source DU due to handover failure
This MR closes issue #984 that UE lost the data plane connection while rolling
back to the source DU due to handover failure.
NR UE: fix PDCCH LLR indexing for different search space RB sizes
After !3603 (merged), when multiple search spaces have different CORESET
configurations (different number of RBs), the LLR buffer stride must be
calculated based on the maximum RB size across all search spaces, not the
current search space's RB size.
The LLR buffer is allocated with size based on get_pdcch_max_rbs(), but the
demapping function was using coreset_nbr_rb (current search space) for symbol
stride calculation, causing incorrect LLR extraction when search spaces have
different RB configurations.
This MR tries to fix it.
Closes#1021
Set the subcarrier_spacing field in nfapi_nr_ue_pusch_pdu_t from MAC
to PHY. This has no consequence for the NR UE Softmodem operation as this
field is never read, but prevents a potential future bug in case L1 was
modified to read it.
By default, 'L1_rx_thread_core', 'L1_tx_thread_core', 'ru_thread_core' are set to '-1' but the values were decoded from config file as unsigned instead of signed types, thus, it was not allowing to set them with '-1' from config file
This commit inputs several distances at once and obtain the summary of
successful and failed tests. We look for the number of successful tests
that are geater than 0. We do that here since we sometimes dont receive
a response for a telnet command from the rfsim although the command
is applied. This is related to the queing telnet commands in the rfsim.
The script for the distances 50, 100 and 150 are called as follows,
./set-and-verify-distance-prs.sh 50 100 150
The summary can be viewed as follows,
==================== SUMMARY ====================
Total tests run : 3
Successful tests: 3
Failed tests : 0
=================================================
Set RFsim (DL) distance and use PRS to estimate the new distance. This
is verified by comparing the distance set in RFsim with the distance
reported through ToA estimation at the UE.
Note that since RFsim telnet output is asynchronous (it uses a queue
internally), we use grep --max-count 1 to wait for the matching line,
together with ncat --idle 0.3 to keep ncat open for some time. The
--max-count option will terminate grep after the first occurrence. For
this to work reliably, we need to use grep <(echo | ncat) as opposod to
simply echo | ncat | grep, as the latter does not seem to reliably
make grep exit after the occurrence.
Co-authored-by: Robert Schmidt <robert.schmidt@openairinterface.org>
fix bugs in scope for pdcch, and optimize cpu cost of pdcch decoding
fix bugs in scope for pdcch, and optimize cpu cost of pdcch decoding by not
processing useless samples in one symbol
When multiple search spaces have different CORESET configurations
(different number of RBs), the LLR buffer stride must be calculated
based on the maximum RB size across all search spaces, not the
current search space's RB size.
The LLR buffer is allocated with size based on get_pdcch_max_rbs(),
but the demapping function was using coreset_nbr_rb (current search
space) for symbol stride calculation, causing incorrect LLR extraction
when search spaces have different RB configurations.
Handle SIGINT and mark any subsequent steps as failed. Receiving SIGINT
a second time will abort the script immediately (as is the case before
this commit).
Note that Python seems to relay the signal to the "controlled" process
(e.g., Ping), which would return immediately with an error. So some
steps like Ping will abort immediately, others (e.g., IdleSleep) will
finish their step, and then the present logic will mark subsequent steps
as failed.
Some CI tasks/commands like Iperf(), Ping() get multiple nodes (via XML
parameter "nodes") to potentially run UEs on different nodes (hosts) at
the same time. However, I argue that this is not good:
- we don't actually use this -- where we specify multiple UEs, it's
always "localhost localhost..."
- it is inconsistent, as we typically have a single "node", not nodes,
and there is a possibility to harmonize (see also next commit)
- if we needed it, there would be better ways to achieve the same.
First, for hardware-based UEs, the ci_infra.yaml can specify different
UEs. For simulated UEs, it would be feasible to have multiple XML
steps run in parallel, e.g., in the XML <parallel> tag, which would
clarify that multiple UEs on different hosts run in parallel
- it reduces code.
Hence, make a single <node> for these XML steps.
Created Jenkinsfiles:
- Jenkinsfile: for stadard test pipelines
- Jenkinsfile-oc: for deployments with OC
These 2 Jenkinsfiles covers all current test pipelines.
Previously, we were using int16_t for the variable ch_tmp which was later harmonized to use c16_t while leaving <<1. This introduced the bug while accessing the address of the element at first_half of the ch_tmp variable.
Integration `2025.w44`
* !3721 improvements in formatting and LOGs in DMRS common functions at MAC
* !3725 Handle GTP receiver errors, fix memory leaks, add CU-UP test
* !3726 fix for CSI payload sizes in PUCCH structure at UE
* CI: Adjust attenutation for HO setup
* !3728 Fix for scenario with no CSI report configured for CSI-RS
* !3731 CI: ensure clean iperf3 server startup
* !3592 Refactor PRACH handling at the gNB
* !3682 Refactor DLSCH scheduler
* !3733 Clarify whitespace
* !3706 Change registry name env var content
Closes#1015 and #1014
See merge request oai/openairinterface5g!3727
Change registry name env var content
Currently setting REGISTRY="" in a .env file results in docker failing to find
/image-name:tag. This corrects that, so it looks for local images named
image-name:tag.
Following the change to use:
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop}
the REGISTRY variable must now include the trailing slash.
Refactor DLSCH scheduler
Refactor the DLSCH post processor similarly to what has been done in
!3521 with the goal of saving an additional iteration through all UEs,
hopefully making the DLSCH scheduler faster.
It further includes changes to make working with and debugging multi-UE
operation easier:
- add some measurements in L1 (for total TX/RX time)
- a new option MACRLCs.[0].stats_max_ue to limit the number of UEs in
the periodic output (default: 8, 0=disable)
- avoid stack overflow in the MAC
- fix the writing of stats to nrMAC_stats.log and nrL1_stats.log when
the written output reduces by truncating the files
- avoid to schedule retransmission with 0 RBs.
This slightly speeds up the scheduler (it e.g., does not need to check
for UEs that have retransmissions), and harmonizes with pf_ul(), which
evaluates (UL) BSR at a similar place within the scheduler.
Check and return, if necessary, that we have enough resources to make
retransmissions. Without, we can asserts in L1, such as
Assertion (NPRB>0 && (NPRB + RBstart <= BWPsize)) failed!
In PRBalloc_to_locationandbandwidth0() openairinterface5g/common/utils/nr/nr_common.c:506
Illegal NPRB/RBstart Configuration (0,51) for BWPsize 51
which indicates that the scheduler requested a transmission with 0 PRBs,
which does not make sense.
Refactor PRACH handling at the gNB
- Remove race conditions by correctly setting mutexes
- Fix a bug when having multiple RACH occasions
- Reduce memory footprint by removing global memory, which should also
fix potential memory data races in FHI 7.2
- Additional fixes, see commit messages
a bit difficult to understand: sl_ahead=6 => we systematically miss the
rach detection in the scheduler because the scheduler runs more than 6
slots ahead the rx slot processing (here > 11 slots because 6 (DL and UL
slots) + 4 (RU_RX_SLOT_DEPTH, so UL only))
so, reducing sl_ahead works better than large sl_ahead because the idea
behind is: the scheduler of slot+sl_ahead will never create work to do
in a UL slot before slot+sl_ahead+X (as minimum k2 is X, in the 24PRB CI
test: 6)
saves about 600MB of memory allocation
Move the definition of PRACH items and the PRACH list to the
defs_nr_commons.h file.
Do not re-write the entire structure in nr_schedule_rx_prach(), as it is
quite large now.
Call the post-processor when the allocation is "fixed" (i.e., nothing
changes anymore), instead of having a final loop across all UEs that
might potentially be costly.
In order to calculate the PF metric, note that the statistics "reset" is
moved into pf_dl() instead of the post-processing loop, as it has to be
done on each slot.
See also: dd98030202 ("Refactor to call post-processor in place")
Similarly to parent commit(s), assign sched_pdsch in a single place
instead of relying on sched_ctrl. In a follow-up commit, the
post-processor will be called in a single place.
Similarly to parent commit(s), refactor the use of NR_sched_pdsch.
Instead of using nr_mac->sched_ctrlCommon, put the NR_sched_pdsch_t on
the stack.
This also refactors update_rb_mcs_tbs() to update the existing
NR_sched_pdsch instead of updating individual fields.
This also reduces the extend to which sched_ctrlCommon is used.
Assign NR_sched_pdsch to sched_ctrl->sched_pdsch in one place, where the
post-processing functionality will be called in a follow-up commit. This
should result in no functional change.
It seems to be assumed that curInfo actually has the currently active
number of layers/PMI. However, I am not sure this would always be true
(e.g., UE might not have been scheduled for some slots, but number of
layers decreased as reported by CSI). Instead, recalculate the info
from scratch when necessary.
PF uses MCS and average throughput to decide which UE to schedule. Thus,
the first loop decides on MCS, whereas the second does the "main UE
allocation" after sorting by the PF metric.
A follow-up commit will remove sched_pusch from NR_UE_sched_ctrl_t.
Thus, we cannot rely on sched_ctrl to store the MCS in the first loop,
and look it up from there in the second. Instead, store it as part of
the UE iterator data, and take it from there.
See also: f3068caa37 ("Store selected MCS in UE iterator", for UL)
Introduce a struct with information on FAPI structures to save resource
and data allocation into. It's in nr_mac_gNB.h because the next commits
will reuse this for all preprocessors.
Especially in pf_dl()/pf_ul(), we use a first loop using
UE_iterator(), then iterate over a subset of UEs. It has happened a
couple of times that I was using variable "UE" (from the iterator), when
it should only be used in the first UE_iterator() loop.
Rewrite UE_iterator() to effectively limit the scope of the iterator
variables to the body of the UE_iterator. This should also make it
possible to reuse multiple UE_iterator()s with the same variables in
sequence.
CI: ensure clean iperf3 server startup
- Resolves issue with iperf3 test failure in RFSim5G multiue test
- Minor fix of iperf3 test descriptions in RFSim5G pipeline
Fix for scenario with no CSI report configured for CSI-RS
After changes in !3714 (merged), if we select to measure RSRP on SSB and not
CSI-RS (default option) and there is a single antenna port (so no MIMO report
either) we won't schedule any CSI-RS measurements for the UE. In that case
ideally we shouldn't set do_CSIRS = 1 in configuration file but still the
option is possible. So the fix is to not perform any measurements at UE on
that CSI-RS but not asserting.
Closes#1015
1. Create a free_ru_session_list() function to free the memory allocated for the connected RUs
before closing the nr-softmodem.
2. xmlReadMemory() and xmlNodeGetContent() were causing serious memory leakages,
and now all is properly freed using xmlFreeDoc() and xmlFree().
This struct is used in multiple source files.
Previously, when stopping the nr-softmodem, the ru_session_list "disappears"
and the M-plane wasn't terminated properly (num_rus = 0 even though DU connected to at least one RU).
MIMO mode is defined by setting separate carriers to different antenna ports.
Benetel v1.2.2 does not support MIMO mode to be set via M-plane, and therefore
we only created one Tx and one Rx carrier.
Benetel v1.4.1 supports MIMO mode setting via M-plane.
Therefore, this commit introduces the adaptation based on the number of supported carriers by a DUT RU.
These 3 states: "oper-state", "admin-state", "availability-state" are optional,
but shall be checked in order to activate the carriers. If an O-RU doesn't support it,
we assume the expected values:
- "oper-state" = "enabled"
- "admin-state" = "unlocked"
- "availability-state" = "NORMAL"
Implement retrieval of the hardware states if O-RU supports, i.e. Benetel release v1.4.1.
Duplex is assumed to be static but for NTN bands, it is not static.
TxRX Duplex is defined in section 5.4.4 of 38.101-5 (for NTN) specs v1809
n256 190 MHz, 165 to 215 MHz
n255 -101.5 MHz, -72.5 to -130.5 MHz
n254 862 - 885 MHz
The function rx_nr_prach become autonomous, it doesn't read anymore global variables
So, it can become (later) a threadpool work, that will send a message when it finishes
rx_nr_prach_ru() still use some global variables, but it is executed in sequence, inside the ru main loop, that limits the probability of race conditions
Before starting a new iperf3 server instance in CI tests, explicitly kill any existing
iperf3 processes bound to the same port. This prevents conflicts or failures caused by
leftover iperf3 servers from previous runs that did not terminate properly or on time.
The cleanup is performed using `pkill` before launching the new server.
Handle GTP receiver errors, fix memory leaks, add CU-UP test
- Fix use-after-free bugs in GTP by properly stopping the receive thread(s)
- Fix a bug from !3519 (merged): QFI 0 is a valid QFI
- Fix multiple memory leaks in CU-UP, E1, CU-UP load tester, SCTP
- Add a (conservative) functional CU-UP test that verifies that the load tester
and CU-UP work. Test only a low throughput, as it will run in parallel with
other tests.
Use the CU-UP load tester to test the functionality of the CU-UP and
its loader tester. The requirements on this load test are intentionally
low, as it will be run with other unit tests in parallel, and should
still pass.
It uses an existing configuration file for the CU-UP. The test script
runs the CU-UP, runs the load tester, stops the CU-UP, and returns the
load tester return value as test result (which will be 0=success if all
packets have been received).
Note that this strdup has been intentioally created for debugging
purposes in core files.
See also: 1ab3b8dd8e ("add version signature in core files...")
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f7bc7ee68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x0000004abfa6 in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
#2 0x0000004abfa6 in decode_e1ap_cuup_setup_request /home/richie/oai/openair2/E1AP/lib/e1ap_interface_management.c:219
#3 0x00000046a9f5 in e1apCUCP_handle_SETUP_REQUEST /home/richie/oai/openair2/E1AP/e1ap.c:187
#4 0x000000470b35 in e1ap_handle_message /home/richie/oai/openair2/E1AP/e1ap.c:109
#5 0x000000470b35 in e1_task_handle_sctp_data_ind /home/richie/oai/openair2/E1AP/e1ap.c:120
#6 0x00000047717b in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:832
#7 0x7f7bc7e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
Direct leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f7bc7ee68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x0000004ac30c in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
#2 0x0000004ac30c in decode_e1ap_cuup_setup_request /home/richie/oai/openair2/E1AP/lib/e1ap_interface_management.c:194
#3 0x00000046a9f5 in e1apCUCP_handle_SETUP_REQUEST /home/richie/oai/openair2/E1AP/e1ap.c:187
#4 0x000000470b35 in e1ap_handle_message /home/richie/oai/openair2/E1AP/e1ap.c:109
#5 0x000000470b35 in e1_task_handle_sctp_data_ind /home/richie/oai/openair2/E1AP/e1ap.c:120
#6 0x00000047717b in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:832
#7 0x7f7bc7e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
Direct leak of 100 byte(s) in 1 object(s) allocated from:
#0 0x7f6585ee6f2b in malloc (/lib64/libasan.so.8+0xe6f2b) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x000000414a0d in malloc_or_fail /home/richie/oai/common/utils/utils.h:86
#2 0x0000004061c9 in main /home/richie/oai/tests/nr-cuup/nr-cuup-load-test.c:544
#3 0x7f6585211574 in __libc_start_call_main (/lib64/libc.so.6+0x3574) (BuildId: 48c4b9b1efb1df15da8e787f489128bf31893317)
#4 0x7f6585211627 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3627) (BuildId: 48c4b9b1efb1df15da8e787f489128bf31893317)
#5 0x000000413034 in _start (/home/richie/oai/build/tests/nr-cuup/nr-cuup-load-test+0x413034) (BuildId: 8af0132792b03fa12ba95b5623865c9a8a5625a3)
Direct leak of 100 byte(s) in 1 object(s) allocated from:
#0 0x7f6585ee6f2b in malloc (/lib64/libasan.so.8+0xe6f2b) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x000000414a0d in malloc_or_fail /home/richie/oai/common/utils/utils.h:86
#2 0x0000004061ff in main /home/richie/oai/tests/nr-cuup/nr-cuup-load-test.c:546
#3 0x7f6585211574 in __libc_start_call_main (/lib64/libc.so.6+0x3574) (BuildId: 48c4b9b1efb1df15da8e787f489128bf31893317)
#4 0x7f6585211627 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3627) (BuildId: 48c4b9b1efb1df15da8e787f489128bf31893317)
#5 0x000000413034 in _start (/home/richie/oai/build/tests/nr-cuup/nr-cuup-load-test+0x413034) (BuildId: 8af0132792b03fa12ba95b5623865c9a8a5625a3)
Free memory including the "base pointer". Fix two places in which it was
on the stack to harmonize. The only stack variable is in reception of
new E1 messages (e1ap_handle_message()), which uses
ASN_STRUCT_FREE_CONTENTS_ONLY().
This fixes bugs similar to these logs:
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f418f4e68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x00000049e367 in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
#2 0x00000049e367 in encode_e1_bearer_context_release_command /home/richie/oai/openair2/E1AP/lib/e1ap_bearer_context_management.c:1235
#3 0x000000482951 in e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND /home/richie/oai/openair2/E1AP/e1ap.c:546
#4 0x000000482951 in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:856
#5 0x7f418f428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f418f4e68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x00000049380a in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
#2 0x00000049380a in encode_E1_bearer_context_setup_request /home/richie/oai/openair2/E1AP/lib/e1ap_bearer_context_management.c:578
#3 0x00000047f6a2 in e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST /home/richie/oai/openair2/E1AP/e1ap.c:378
#4 0x0000004829f8 in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:846
#5 0x7f418f428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f418f4e68a3 in calloc (/lib64/libasan.so.8+0xe68a3) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x00000046ede7 in calloc_or_fail /home/richie/oai/common/utils/utils.h:74
#2 0x00000046ede7 in encode_e1ap_cuup_setup_response /home/richie/oai/openair2/E1AP/lib/e1ap_interface_management.c:305
#3 0x00000047e412 in e1ap_send_SETUP_RESPONSE /home/richie/oai/openair2/E1AP/e1ap.c:167
#4 0x000000482a68 in E1AP_CUCP_task /home/richie/oai/openair2/E1AP/e1ap.c:836
#5 0x7f418f428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
QFI 0 is a valid QFI: don't check for qfi <= 0, as uint8 cannot be
negative. Also, correctly use SDAP_MAP_RULE_EMPTY for a DRB ID (which
need to be larger than 0).
The gNB will stop the periodical logging of UEs in MAC Info level after
a configurable number of UEs have been printed, by default 8.
Set it to 17 in some CI tests to ensure we still get all UEs for the
time being, as the CI might depend on this.
improvements in formatting and LOGs in DMRS common functions at MAC
DMRS LOGs at MAC were misleading. This MR tried to improve them (and also
adds some formatting fix).
The call to snprintf() as was used is wrong: we use the return value to
advance output, but the man page says
> The functions snprintf() and vsnprintf() do not write more than size
> bytes (including the terminating null byte ('\0')). If the output was
> truncated due to this limit, then the return value is the number of
> characters (excluding the terminating null byte) which would have been
> written to the final string if enough space had been available.
> Thus, a return value of size or more means that the output was
> truncated.
Thus, output could go beyond end, and we get a stack overflow. Instead,
encapsulate the call to snprintf() checking this condition, and only
advancing output as intended, limiting to 0 if we are at the end of the
buffer. This avoids this error:
==964825==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7be799f51988 at pc 0x7fe7d66b0d39 bp 0x7be79b825ef0 sp 0x7be79b8256c0
WRITE of size 3 at 0x7be799f51988 thread T24
#0 0x7fe7d66b0d38 in vsnprintf (/lib64/libasan.so.8+0xb0d38) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x7fe7d66b2d44 in snprintf (/lib64/libasan.so.8+0xb2d44) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#2 0x0000008fe7c6 in dump_mac_stats /home/richie/w/refactor-dlsch/openair2/LAYER2/NR_MAC_gNB/main.c:183
#3 0x00000092071a in gNB_dlsch_ulsch_scheduler /home/richie/w/refactor-dlsch/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c:200
#4 0x0000008f8f78 in run_scheduler_monolithic /home/richie/w/refactor-dlsch/openair2/NR_PHY_INTERFACE/NR_IF_Module.c:399
There is the (global) sched_lock that prevents concurrent access. A
dedicated UE lock does not make sense in that case. Worse, this lock
does not prevent all concurrent UE accesses (e.g., there are many loops
over UEs that are not protected), so it's also wrong.
truncate resets the file size to 0. Without this, e.g., when
disconnecting a UE, the old UE remains at the end and is not
overwritten, which is confusing.
- Corrected AMF Set ID data type in ngap_gNB_nnsf_select_amf_by_amf_setid() from uint8_t to uint16_t.
- AMF Set ID is a 10-bit field as per 3GPP TS 38.413 §9.3.3.12.
- The incorrect data type caused truncation for AMF Set IDs >255, leading to lookup failures during RRC reestablishment.
- Verified successful reestablishment with large AMF Set IDs after the fix.
Reason for fix: AMF lookup using AMF Set ID was failing because the 10-bit AMF Set ID was truncated to 8 bits.
Closes#1012
Stop the receive thread before closing the socket, which avoids an error
message when stopping the GTP softmodem:
[GTPU] [91] Recvfrom failed (Bad file descriptor)
[GTPU] exiting thread
On error, exit the GTP thread after printing a diagnostic message. This
avoids also an error flagged by address sanitizer for use-after-free.
[GTPU] [91] Recvfrom failed (Bad file descriptor)
=================================================================
==285377==ERROR: AddressSanitizer: heap-use-after-free on address 0x7cd7b7fe5590 at pc 0x0000006a9e18 bp 0x7b97ad4e1d50 sp 0x7b97ad4e1d48
READ of size 4 at 0x7cd7b7fe5590 thread T8
=================================================================
==285377==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 160 byte(s) in 1 object(s) allocated from:
#0 0x0000006a9e17 in gtpv1uReceiver /home/richie/oai/openair3/ocp-gtpu/gtp_itf.cpp:1346
#1 0x7f97b9a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#2 0x7f97b8e7ff53 in start_thread (/lib64/libc.so.6+0x71f53) (BuildId: 48c4b9b1efb1df15da8e787f489128bf31893317)
#3 0x7f97b8f0332b in __clone3 (/lib64/libc.so.6+0xf532b) (BuildId: 48c4b9b1efb1df15da8e787f489128bf31893317)
#0 0x7f97b9ae60cb in memalign (/lib64/libasan.so.8+0xe60cb) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x000000471039 in newNotifiedFIFO_elt /home/richie/oai/common/utils/threadPool/notified_fifo.h:75
#2 0x000000471039 in tx_func /home/richie/oai/executables/nr-gnb.c:107
#3 0x000000471039 in L1_tx_thread /home/richie/oai/executables/nr-gnb.c:167
#4 0x7f97b9a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
0x7cd7b7fe5590 is located 336 bytes inside of 400-byte region [0x7cd7b7fe5440,0x7cd7b7fe55d0)
freed by thread T0 here:
SUMMARY: AddressSanitizer: 160 byte(s) leaked in 1 allocation(s).
Integration: `2025.w43`
* !3605 Support beam index in OAI 7.2 Fronthaul Interface
* !3709 Fixes for T-Tracer to work with NR-UE
* !3712 Restore UE Capability IE after RRCReestablishment
* !3716 Remove unused ULSCH measurements at gNB
* !3603 UE symbol based PDCCH receiver
* !3708 Add monolithic N2 handover test pipeline with B210 and Quectel
* !3719 Remove Benetel-specific radio drivers
* !3710 [CI] Update the Push to DockerHub Stage
* !3711 CI: Multiple adjustments
* !3717 Initialize NCC=0 on NGAP Initial Context Setup (3GPP TS 33.501 §6.9.2.1.1)
* !3720 fix direct bugs of not used RU_RX_SLOT_DEPTH defined constant
* !3714 Improve handling of selection of RSRP/SINR report via configuration file
* !3519 Refactor SDAP adaptation work for QoS
* !3698 Other CSI measurement fixes
* !3699 Updates for Feature Set
Closes#1008
See merge request oai/openairinterface5g!3713
Other CSI measurement fixes
Errors fixed in this MR:
- UE currently sends empty CSI measurement report resulting in invalid
cqi_idx 0, default to MCS 9 at gNB because mismanagement of new L1
measurement structure at MAC UE
- nrofReportedRS not updated after UE capability reception at gNB
- multiple RSRP reports multiplexed / de-multiplexed in wrong order
Refactor SDAP adaptation work for QoS
This MR is an adaptation of the code introduced in !2703.
The goal is a cleanup and functional refactor of the SDAP/PDCP
integration, that is:
- centralize SDAP configuration logic
- simplify entity creation
- improve robustness of role-based SDAP handling
- prepare the codebase for clean support of DRB reconfiguration and
teardown flows
More concretely:
1. New sdap_config_t and get_sdap_Config()
- Introduced an internal struct sdap_config_t to abstract SDAP config
input
- Centralized SDAP config parsing into new get_sdap_Config() function
that translates ASN.1 NR_SDAP_Config into this internal
representation. This is called during RRC triggered
(re)configuration procedures.
- Enable mapping of number of QoS flows > 1
2. Unified role handling with bitmasks
- Added a bitmask-based entity_role field to track SDAP directions:
SDAP_UL_RX, SDAP_UL_TX, SDAP_DL_RX, SDAP_DL_TX: header presence was
determined by simple direction (UE vs gNB) and individual
is_sdap_rx/tx() checks, however nr_sdap_rx_entity behaves
differently depending on the direction of the RX entity (DL/UL),
therefore this change can help enable a more accurate SDAP header
handling across directions and node types.
- Replaces old helpers is_sdap_rx() / is_sdap_tx() with internal
checks against the role bitfield
- QFI-to-DRB mapping is now annotated with direction for both data and
control PDUs
3. Simplified DRB and SDAP setup
- add_drb() in PDCP API now delegates SDAP config processing cleanly
- new_nr_sdap_entity() is used consistently to register a fresh SDAP
context for the UE and PDU session.
- Also, re-use and reconfigure existing SDAP entity if already
exists.
- logging has been added to trace mapped QFIs from RRC and resulting
table entries
4. Improved QFI-to-DRB management
- Refactored nr_sdap_qfi2drb_map_update() to register QFIs based on
parsed config
- Ensures control PDUs are correctly routed even after reconfiguration
- Extended nr_sdap_ue_qfi2drb_config: perform UL QoS flow to DRB
mapping configuration for a SDAP entity has already been established
according to TS 37.324, 5.3 QoS flow to DRB Mapping, 5.3.1
Configuration Procedures. Handle both UL QoS Flows mapping rules to
add and to remove. QFIs will now be properly unmapped if specified
via mappedQoS_FlowsToRelease, this might prevent stale QFI mappings
from being used incorrectly.
- nr_sdap_qfi2drb() and sdap_map_ctrl_pdu() now strictly fallback to
default_drb only if a QFI mapping is missing. Missing default DRB
now triggers LOG_E() (previously silent or misrouted to DRB 0).
5. Other cleanup
- Remove dependencies from legacy rb_id_t
Improve handling of selection of RSRP/SINR report via configuration file
In current develop, the selection of SSB or CRI RSRP depends on the
do_CSIRS flag being activated. That's not wanted. CRI report for now it
is never handled, while we need SSB RSRP report for beam switching
regardless of CSI-RS configuration.
This commit refactors the SDAP entity QoS flow to DRB mapping functionality
to improve code organization and enhance maintainability.
Key changes:
- Split nr_sdap_qfi2drb_map_update into focused functions:
* nr_sdap_add_qos_flows_to_drb: handles QFI addition to DRB
* nr_sdap_rm_qos_flows_from_drb: handles QFI removal from DRB
* nr_sdap_ue_control_pdu_config: handles UE control PDU generation
- Consolidate add/modify logic into reusable nr_sdap_addmod_entity function
- Remove entity existence checking and updating from new_nr_sdap_entity:
this function should only add SDAP entities
- Improve function separation of concerns: do SDAP entity add or update
separately and improve modularity by splitting operations in self
contained functions
- At SDAP creation, do only add of QFI to DRB mapping
- rename new_nr_sdap_entity to nr_sdap_add_entity for function naming consinstency
- Remove rb_id parameter from nr_sdap_tx_entity() function signature
- Update tx_entity function pointer
- Remove rb_id parameter from sdap_data_req() function signature
- Remove unused rb_id variable from sdap_tun_read_thread
The rb_id parameter was redundant since SDAP determines DRB ID
from QFI mapping via entity->qfi2drb_map(entity, qfi). This
simplifies the interface.
Each QFI should always be mapped to a DRB. If that is not the case, we
have an undefined behavior. This should not occur. This commit prints
an error in tx_entity and returns.
The TX/RX entity should have different behavior according to
5.2.1, 5.2.2, 3GPP TS 37.324, depending on whether it is UL and DL.
The gNB can play a role both as UL RX entity and DL TX entity, while
the UE can play a role both as UL TX entity and DL RX entity.
The goal of this commit is to extend the information stored in the
SDAP entity as the current code is just marking the entity as TX/RX.
The commit introduces a bitmap to store the role of the
entity, which can be DL RX, DL TX, UL RX and UL TX. Based on this
the TX SDAP entity knows whether a DL/UL PDU should be build, and
the RX SDAP entity knows whether a DL/UL PDU should be processed.
See also Figure 4.2.2-1.
SDAP headers are present only if enable_sdap option is used.
nr_sdap_qfi2drb_map_update function pointer should
process QFIs to add and release from the entity mapping, therefore
a new function pointer for QFIs to add was introduced and
the function pointer to release the QFIs was called in the same function.
Now the nr_sdap_qfi2drb_map_update is:
(1) looping through the QFIs to add/update and store in the qfi2drb_table
(2) looping through the QFIs to release and delete from qfi2drb_table
Also:
* Update the function signature to use sdap_config_t and nr_sdap_entity_t
* log error when the update fails
* limit the scope of the function
* clang-formatted
* removed limit on table entries set by AVLBL_DRB, replaced with MAX_DRBS_PER_UE
The function nr_sdap_ue_qfi2drb_config should do UL QoS flow to DRB mapping configuration
for a SDAP entity has already been established according to TS 37.324, 5.3 QoS flow to
DRB Mapping, 5.3.1 Configuration Procedures. It should handle both mapping rules to add and to remove.
To this purpose:
* Simplify function signature by passing the sdap config.
* Improve readability of the function.
* Move handling of sdap.mappedQFIs2ReleaseCount (in nr_reconfigure_sdap_entity)
inside the function.
* Simplify end-marker control PDU mapping function by removing unused
DRB ID input parameter (the function is fetching the DRB ID based on the input
map type)
* use int instead of legacy rb_id_t
* limit scope of functions whenever necessary
The goal of this function is to return the DRB ID mapped to the input QFI, for both DL and UL.
The function looks up the DRB that is mapped to the QFI, if no mapping rule exists
returns the default DRB. Returns 0 If no mapping and no default DRB exists for that QFI
The function should not update the stored mapping rules, that is done when receiving
a new SDAP configuration. In this function it was removed.
See TS 37.324, 5.2.1 Uplink
> If there is no stored QoS flow to DRB mapping rule for the QoS flow as specified in the subclause 5.3,
> map the SDAP SDU to the default DRB else, map the SDAP SDU to the DRB according to the stored QoS flow to DRB mapping rule.
* change function signature: pass the sdap_config_t
* update qfi2drb mapping when receiving a configuration for an already existing SDAP entity
* always update mapping rules, not only for default DRB
* use get_sdap_Config to process sdap_Config
* move SDAP config logic to the scope where it is relevant
* add SDAP entity direcly in RRC, not from PDCP
* replaced nr_pdcp_add_drbs with single add_drb call: it was no longer
efficient to keep it in the new logic. The addMod list can be looped directly in RRC.
* add specific function to add bearers from addMod list in E1, NSA, and UE
fix direct bugs of not used RU_RX_SLOT_DEPTH defined constant
with this commit, the gNB can work if we change RU_RX_SLOT_DEPTH to
another value than 4 but it remain not well designed
Initialize NCC=0 on NGAP Initial Context Setup (3GPP TS 33.501 §6.9.2.1.1)
The nhcc should be initialized to 0 upon Initial Context Setup.
Also, remove unused kgnb_ncc: nh_ncc is already there.
Closes#1008
[CI] Update the Push to DockerHub Stage
This MR addresses two cases:
1. Error Handling: Ensures subsequent Image Test Processes stages
continue to run even if the preceding Push to DockerHub stage fails
(applies when the condition is PUSH event and doBuild is true).
2. Introduces conditional logic to correctly handle multi-architecture
images: Images built for both AMD64 and Jetson ARMv8 (oai-gnb,
oai-nr-ue, oai-nr-cuup) use docker buildx imagetools for push to
DockerHub.
All other AMD64 images are pushed using standard Docker commands.
Related MR !3691
Add monolithic N2 handover test pipeline with B210 and Quectel
The goal of this MR is to provide an automated end-to-end N2 HO
validation with real RF (B210) and Quectel UE.
During the testing phase a post-HO assertion failure due to
uninitialized selected_plmn_identity was found: this was also fixed.
CI: Add monolithic N2 handover test pipeline (B210 + Quectel)
- New XML pipeline for N2 HO testing
- Docker Compose for two monolithic gNBs (gNB1/gNB2)
- Handover sequence: gNB1 → gNB2 → gNB1 with 5s controlled attenuation
(RC4DAT).
- Channel mapping: ch1-2 gNB1, ch3-4 gNB2
- Telnet server enabled for CI commands
- Clean-up/reset of attenuator state included
NGAP
- fix PLMN/cell location for Initial UE and Uplink NAS
- Prevents assertion in ngap_gNB_nas_uplink() due to uninitialized
selected_plmn_identity
- Initial UE Message: pass UE-selected PLMN and NR cell ID from RRC to
NGAP
- Uplink NAS Transport: use PLMN, TAC, and cell ID from the message
- Build NR CGI as gNB ID + cell ID
- Store UE-selected PLMN only in RRC UE context (for later NAS); stop
storing PLMN in NGAP UE context.
- PLMN validation when processing handover requests from the source gNB:
when PLMN validation fails, the target gNB now properly sends
NGAP_HANDOVER_FAILURE
- Store serving PLMN for later use in UE context
UE symbol based PDCCH receiver
This is a partial rebase/rewrite of !2895
The goal of this MR is to check how we can merge this.
The eventual result is stated in !2895. The way forward is to modify UE
RX procedures to work symbol by symbol by extracting the symbol loop out
of RX procedures. After all channels are modified this way, the main
thread can be modified to work symbol by symbol.
At this point only PDCCH was modified.
This change is needed due to the previous addition of the function nfapi_stop_l1() in gnb_config.c which in turn calls 2 functions that do not exist in the simulators, since they're not linked against the nfapi libraries
This implements the STOP.request/indication for all 3 transport mechanisms, the VNF will send the STOP.request to the PNF, indicating it will disconnect, and await a STOP.indication from the PNF
The WLS VNF is reworked to be able to start before the PNF, by calling call rte_eal_init and rte_dev_probe to determine if dpdk has been initialized properly, before calling rte_eal_init in the intended process when it is appropriate to do so
The WLS VNF is reworked to be able to start before the PNF, by calling call rte_eal_init and rte_dev_probe to determine if dpdk has been initialized properly, before calling rte_eal_init in the intended process when it is appropriate to do so
- Push both AMD64 & ARMv8 Jetson images together for images built on both using `docker buildx imagetools`
- Use standard 'docker pull and push' for images built only on AMD64.
This allows access to the VNF configuration in the various transport mechanisms straight from config, without this, the transport specific thread would cause a segmentation fault when trying to access the pack/unpack function pointers.
Add 2 functions to access the P5 and P7 VNF structures, to avoid having to always cast user_data and p7_vnfs
Prevent assertion in ngap_gNB_nas_uplink() due to uninitialized selected_plmn_identity:
the selected_plmn_identity field was not being set during N2 handover,
causing the assertion ((plmn->mnc_digit_length == 3) || (plmn->mnc_digit_length == 2))
to fail when processing subsequent NAS messages. The issue is that the Serving PLMN
is not stored by RRC. During N2 mobility, RRC can get this info from GUAMI.
When receiving the Handover Request the target gNB knows from GUAMI
which serving PLMN is the AMF belonging to. In current design, allowed PLMNs
are stored in rrc.configuration. The incoming PLMN needs to be validate
against the PLMNs in the list, then stored in the UE context as Serving PLMN.
This change adds PLMN validation when processing handover requests from the source gNB.
The validation is needed because:
- Target gNB must verify that the PLMN from the GUAMI in the handover request
is allowed by its configuration before accepting the handover to prevent handover
to unsupported PLMNs.
- When PLMN validation fails, the target gNB now properly sends NGAP_HANDOVER_FAILURE
- UE Context must store serving PLMN for later use
This commit is removing the storage of selected PLMN in NGAP UE context.
We store the Serving PLMN in the RRC UE context instead.
The Selected PLMN is the PLMN that the UE chose (or was directed to) for registration
and it is sent in the RRCSetupComplete. This is different from the selected
PLMN mentioned in the NG INITIAL UE MESSAGE for network sharing.
Selected PLMN: determines which core network and AMF the UE is registered with
GUAMI = Identifies the serving AMF and includes the PLMN of that AMF
Serving PLMN: the PLMN that is currently serving the UE (e.g. contained in GUAMI)
The AMF’s PLMN may match the selected PLMN, or not (especially in network sharing or roaming).
Regardless, the UE always have a Serving PLMN.
Initial UE message does not have a TAI IE per se, but TAI is a mandatory
member of the mandatory UserLocationInformation CHOICE.
NR CGI is also mandatory and carried inside UserLocationInformation:
in network sharing, the PLMN ID in TAI takes on additional
significance: RAN is shared but CN are different, so in this case PLMN in TAI is
needed for the AMF route the message to the correct operator’s core.
If network sharing applies (e.g., shared RAN between PLMN-A and PLMN-B):
the UE or network may select PLMN-B instead, and that PLMN identity
is included in the Initial UE Message’s TAI IE.
Conclusion:
1) UE always sends the selected PLMN during the registration,
regardless of whether it is shared or not.
2) Selected PLMN Identity is an actual IE sent in the RRCSetupComplete
while in NGAP there's no Selected PLMN Identity IE, only PLMN Identity
IEs in both TAI and NR CGI. It is a subtle difference.
3) The serving PLMN of the UE needs to be stored in RRC UE Context for
later use in NAS procedures. e.g. at initial registration it matches
the Selected PLMN
4) No need to store PLMN in NGAP UE Context, params are passed by RRC
5) TAI and NR CGI, which contain the PLMN identity, are mandatory in
UserLocationInformation IE CHOICE, and should reflect current status
Changes
- Initial UE Message: pass UE-selected PLMN and NR cell id from RRC to NGAP
- Uplink NAS Transport: use PLMN, TAC, and cell id provided by the message;
- Build NR CGI from gNB ID + cell id
- Store UE-selected PLMN only in RRC UE context at NAS_FIRST_REQ for later
Uplink NAS, stop storing PLMN in NGAP UE context
- Add XML pipeline for N2 handover testing
- Add Docker compose for two monolithic gNBs
- Features:
* Two monolithic gNBs (gNB1, gNB2) with proper CU+DU parameters
* Gradual attenuation control using RC4DAT attenuator (5s duration)
* N2 handover sequence: gNB1 → gNB2 → gNB1
* Proper channel mapping: ch1-2 for gNB1, ch3-4 for gNB2
* Telnet server configuration for CI commands
* Handover-specific neighbor configuration
* Clean test state management with attenuator reset
Update based on !3645
Note: For some test configurations we still need to provide
ra_ResponseWindow, for more details, check commit message of
41d14b571c
1. Refactor PDCCH PHY functions to take rxdataF of one OFDM symbol and
produce LLR for each search space. The modified functions take
rxdataF in a different format than that produced by nr_slot_fep(). So
for now a memcpy is used to change the array structure. Once
nr_slot_fep() is modified, this memcpy will no longer be needed and
will be removed.
2. Modify DCI functions to decode DCI in the last PDCCH symbol and
inidcate to MAC once.
3. Fix PDCCH monitoring for start symbol > 0.
4. Fix multiple PDCCH monitoring within slot.
Co-authored-by: Sakthivel Velumani <mail@sakthi.me>
1.Create new funtion nr_symbol_fep() to do OFDM demod of one symbol on
all antennas. This is called by nr_slot_fep() for now. In the
upcoming MR, this function will be called directly after reading
each OFDM symbol from the radio.
2.Removed redundant memory alignment. DFT function performs memory
alignment if the input memory is not aligned.
Fixes for T-Tracer to work with NR-UE
Fixes to align NR UE events with their definitions in T_messages.txt and
match the expected format in the tracer GUI parser.
Also fixes DL SNR to work in tracer GUI.
Support beam index in OAI 7.2 Fronthaul Interface
This branch supports beam index in OAI 7.2 Fronthaul Interface.
- For CP DL (PDSCH), nBeamIndex of the corresponding prbMapElm is set
when sending IQ data in oran_fh_if4p5_south_out. nBeamIndex of the
corresponding prbMapElm is set when sending IQ data in
oran_fh_if4p5_south_out.
- For CP UL (PUSCH and PRACH), nBeamIndex of the corresponding prbMapElm
is set in oran_fh_if4p5_south_out.
In addition, it fixes a couple of issues
- XRAN hardcodes nBeamIndex of PRACH to zero. Modify XRAN to support
setting of nBeamIndex of PRACH and update xran F release patch.
- Fix the bug in calculating fh_config->neAxc where num_beams_period is
multiplified twice
Testing methodology: Use Benetel O_RU for testing even though it does
not support beamforming. With successful registration and data transfer,
one could check the pcap on the fronthaul interface to see if CP packets
are with the right beam index.
Results:
1. Verified that CP-packets for SSB, DCI, PDSCH, PRACH, PDSCH, PUSCH,
CSI-RS and SRS are with the right beam index
2. Verified that there is no side-effect on Benetel O_RU. UE could
register properly.
3. Verified 4 SSB with ssb_PositionsInBurst_Bitmap = 85. Could see SSB
and PRACH with 4 different indices.
Handle CP UL packet at xran_fx_tx_send_slot() instead of
xran_fh_rx_read_slot(), as the latter would set this information too
late (on reception on samples, but it needs to be filled in the CP
packet prior to reception).
Initialize ru_info structure with beam information, and set beams on TX
direction. Initialize the number of antennas for both RX/TX in both
cases for completeness.
By configuring the Jenkins pythonExecutor to match the test machine, we can use
localhost as the node for running individual test cases. This change makes it
easy to move tests across machines, as the only adjustment needed is updating
the pythonExecutor in Jenkins.
By configuring the Jenkins pythonExecutor to match the test machine, we can use
localhost as the node for running individual test cases. This change makes it
easy to move tests across machines, as the only adjustment needed is updating
the pythonExecutor in Jenkins.
By configuring the Jenkins pythonExecutor to match the test machine, we can use
localhost as the node for running individual test cases. This change makes it
easy to move tests across machines, as the only adjustment needed is updating
the pythonExecutor in Jenkins.
1. Fix UE_PHY_PDSCH_IQ event
2. Fix UE_PHY_PDCCH_ENERGY event
3. Fix UE_PHY_PDSCH_ENERGY event
4. Fix UE_PHY_MEAS event
All fixes align NR UE events with their definitions in T_messages.txt and match the expected format in the tracer GUI parser.
Integration `2025.w42`
* !3623 Optimization of PDSCH precoding operation
* !3691 \[CI\] Ensure multi-arch DockerHub Push after successful image build
* !3696 asn1c doesn't follow c99 variables alias rules, it needs to be compiled this...
* !3685 Assign antenna ports correctly for 1 and 2 layers for aerial.
* !3495 Type0 PDSCH frequency allocation at L1 UE
* !3686 Remove NR L2 simulator code from UE
* !3693 Remove B200-specific clock-rate setting
* !3701 OAI UE: add shared RSRP Table 10.1.6.1-1 mapping function to helpers and adopt it RRC UE
* !3662 RRC UE file cleanup
* update doc/README.md
* !3608 use common scale channel functions for DLSCH and ULSCH
* !3694 fix non initialized DMRS port value in case of DCI00 at UE
* !3702 Extend F1 rfsim CI test
* !3704 remove unused global queues, dead code
* !3673 CI: Aerial: Add an UL-heavy pipeline test
* !3651 CI: Upgrade HO setup to use an attenuator
* !3695 CI: Upgrade Aerial setup to 25-2.1
Closes#940
See merge request oai/openairinterface5g!3700
CI: Upgrade Aerial setup to 25-2.1
The purpose of this MR is to upgrade the cuBB image in the Aerial setup to
release 25-2.1 and update the doc/Aerial_FAPI_Split_Tutorial.md accordingly.
CI: Upgrade HO setup to use an attenuator
The goal of this MR is to upgrade HO CI setup to include a digital attenuator
that will allow us to trigger handover by attenuating the signals on the DUs.
Doing this before using set_master_clock_rate() on the B200 seems to
invalidate synchronization setting.
[HW] USRP clock set to 1759836386.000000 sec
[...]
[HW] current pps at 3.286750, starting streaming at 4.286750
In other words, the current time setting was reset. With this change
now, we see
[HW] USRP clock set to 1759929873.000000 sec
[...]
[HW] current pps at 1759929873.000000, starting streaming at 1759929874.000000
This is because changing clock sources (I assume setting the master
clock rate impacts the clock) can result in changing the time. From the
documentation of [1]:
> Note: When changing clock sources, a previously set time will most
> likely be lost. It is recommended to set the time after changing the
> clock source. Otherwise, an unexpected time may line up with future PPS
> edges.
[1] https://files.ettus.com/manual/classuhd_1_1usrp_1_1multi__usrp.html#a99254abfa5259b70a020e667eee619b9
- main.py: replace %%workspace%% with CONTAINERS.eNBSourceCodePath in Custom_Command and Custom_Script
Co-authored-by: Guido Casati <hello@guidocasati.com>
- Add band mismatch check in valid_du_in_neighbour_configs function
- Ensures neighbor cell band matches serving cell band
- Prevents invalid neighbor configurations for handover
The code only checked that Msg3 would be scheduled during UL, but in
some combinations, e.g., with DSUUU, the current slot can very well be
UL as well => we would schedule DCI in UL slot.
Update cuBB image to cubb-build:25-2.1_srs-ul-heavy (release 25-2.1 with
changes in the L1 config to test heavy ul)
Co-authored-by: Reem Bahsoun <reem.bahsoun@openairinterface.org>
fix non initialized DMRS port value in case of DCI00 at UE
When transmitted PUSCH is neither scheduled by DCI format 0_1 with CRC
scrambled by C-RNTI, CS-RNTI, SP-CSI-RNTI or MCS-C-RNTI, nor
corresponding to a configured grant, the UE shall use [...] DM-RS port
0.
In UE code it was not set in case of DCI00 and that was leading to ULSCH
failures in some scenarios.
- Trigger handover
- IdleSleep 2s
- Ping ext-dn from NR-UE
- Verify UE(1) connected to DU-PCI1
Validate absence of heap-use-after-free ASAN error found in !3600.
Closes#940
OAI UE: add shared RSRP Table 10.1.6.1-1 mapping function to helpers and adopt
it RRC UE
- Add to common/utils/nr/nr_common remove from NR_MAC_UE/nr_ue_procedures.c
- Adopt in asn1_msg.c for MeasurementReport: this solves the following possible
assert:
Assertion (enc_rval.encoded > 0) failed!
In do_nrMeasurementReport_SA() /oai-ran/openair2/RRC/NR/MESSAGES/asn1_msg.c:898
ASN1 message encoding failed (MeasResultServMOList, 18446744073709551615)!
Motivation: unify RSRP-to-index mapping across layers and fix NR RRC
MeasurementReport encoding failures due to out-of-range values by reusing the
validated mapping.
Note: NR_RSRP-Range.c constraint: /* (0..127) */
Also refactored MeasurementReport to improve the code.
Remove B200-specific clock-rate setting
Avoid this clock-rate setting, as we already do it around usrp_lib.cpp:1121, so
it is superfluous. For instance, we also do not set a master clock rate for N3xx
either. This also enables us to synchronize B200 for handover settings,
e.g., for !3651.
See the commit message for more information about synchronization.
- Simplify do_nrMeasurementReport_SA API (encoder allocates local report)
- Adopt asn1cCalloc consistently
- Minor init cleanup for UL_DCCH message struct
- Add to common/utils/nr/nr_common remove from NR_MAC_UE/nr_ue_procedures.c
- Adopt in asn1_msg.c for MeasurementReport: this solves the following assert:
Assertion (enc_rval.encoded > 0) failed!
In do_nrMeasurementReport_SA() /oai-ran/openair2/RRC/NR/MESSAGES/asn1_msg.c:898
ASN1 message encoding failed (MeasResultServMOList, 18446744073709551615)!
Motivation: unify RSRP-to-index mapping across layers and fix NR RRC MeasurementReport
encoding failures due to out-of-range values by reusing the validated mapping.
Note NR_RSRP-Range.c constraint:
{ APC_CONSTRAINED, 7, 7, 0, 127 } /* (0..127) */
Remove NR L2 simulator code from UE
This MR removes NR (SA and NSA) L2 simulator from the codebase. The code, at
least at the UE side, was done at a time where there was no clear L2/L1 split
leading to a complex implementation that never worked as expected. The L2
simulator has been broken and removed from testing for long time and, once it
needs to be revived, it would require a complete new implementation.
Assign antenna ports correctly for 1 and 2 layers for aerial.
With this change aerial successfully decodes PUSCH with 2 UL layers.
The code should use sched_pusch->dmrs.num_dmrs_cdm_grps_no_data == 1 rather
than NFAPI_MODE != NFAPI_MODE_AERIAL, but that will make the changes a bit
more extensive.
Prior to this change, sending antenna_ports.val = 2 with rank 2 would tell
the UE to transmit on DMRS ports 2,3 rather than 0,1 causing it to not decode.
[CI] Ensure multi-arch DockerHub Push after successful image build
This merge request improves the CI script to ensure that the DockerHub-Push
stage executes whenever:
- All Image Build stages succeed &
- doBuild is true &
- The event is a PUSH
This behavior ensures that Docker images are published whenever the image build
stages succeed, regardless of any failures in the Image Test stages.
Jetson ARM64/V8 and AMD64 images will now be published on DockerHub under the
same tag (develop or WEEK_TAG) to provide multi-architecture images.
Optimization of PDSCH precoding operation
x86/aarch64 optimizations for precoding, more complete timing reporting in
nr_dlsim. Timing report in nr_dlsim now shows the total PDSCH generation time
and is broken down into Layer mapping, resource mapping and precoding.
The optimizations for x86 are basically reorganizing loops (for AVX512,AVX2,
NEON but not SSE2) to minimize repetitive instructions when formatting of the
precoder weights, and creation of inline functions for complex multiply-add.
AVX512 optimization was added. requiring AVX512BW. Detection of up to 4 PRBs
with common PMI for efficiency with AVX512 (was 2 in develop for AVX2).
For aarch64, native coding of the precoder to avoid inefficient SIMDe
translations for this operation.
nr_dlsim now uses default precoding indices depending on the scenario instead
of 0 which doesn't do precoding at all.
See merge request description for nr_dlsim test results.
- On PUSH events, if image build stages succeed, trigger DockerHub push stage
- Build the images, then trigger the Push to DockerHub stage
- Publish Jetson (ARM64/v8) and AMD64 images under the same tag on DockerHub
Doing this before using set_master_clock_rate() on the B200 seems to
invalidate clock settings:
[HW] USRP clock set to 1759836386.000000 sec
[...]
[HW] current pps at 3.286750, starting streaming at 4.286750
In other words, the current time setting was reset. With this change
now, we see
[HW] USRP clock set to 1759929873.000000 sec
[...]
[HW] current pps at 1759929873.000000, starting streaming at 1759929874.000000
This is because changing clock sources (I assume setting the master
clock rate impacts the clock) can result in changing the time. From the
documentation of set_time_next_pps() [1]:
> Note: When changing clock sources, a previously set time will most
> likely be lost. It is recommended to set the time after changing the
> clock source. Otherwise, an unexpected time may line up with future PPS
> edges.
[1] https://files.ettus.com/manual/classuhd_1_1usrp_1_1multi__usrp.html#a75b1c5375549e6a446d686ee7d9b4e14
The next commit introduces an "UL-heavy" configuration to be tested with
Aerial. To avoid waiting for the CN, start&stop it once at the beginning
of the CI run.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.