Compare commits

...

98 Commits

Author SHA1 Message Date
Raymond Knopp
ef9144060d fix after merge
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:28:35 +02:00
Raymond Knopp
1ce192841d again to trigger CI
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:06:27 +02:00
Raymond Knopp
58ce14d33a small change to trigger CI
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:06:27 +02:00
Raymond Knopp
cbbfd63203 fix for TX amp in nr_dlsim
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:06:15 +02:00
Raymond Knopp
499ee93f8b testing x86
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:06:15 +02:00
Raymond Knopp
56c86fb036 Add signal power measurement for better processing in int16
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:06:15 +02:00
Jaroslava Fiedlerova
b758c862b8 CI: Add RAN-SA-FHI72-MPLANE-CN5G into CI doc
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 23:06:15 +02:00
Jaroslava Fiedlerova
28919a4555 CI: Add RAN-SA-FHI72-MPLANE-CN5G into parent CI pipeline
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 23:06:15 +02:00
Teodora Vladić
a42af09cae Update RU FW versions
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:15 +02:00
Teodora Vladić
20ec54b7cd Update Benetel FW to the latest stable
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:15 +02:00
Jaroslava Fiedlerova
0105a60115 CI: Test with AmariUE in RAN-SA-FHI72-MPLANE-CN5G pipeline
- new configuration for PLMN 00105, 40MHz and 100 MHz added on AmariUE
- helm charts for OC CN with PLMN 00105 added to cacofonix, new CN added
  to ci_infra.yaml, IP address range of the new CN: 172.21.6.116-118
- test with 1 AmariUE (to be extended in future MR), with SISO

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 23:06:15 +02:00
Teodora Vladić
79d0582704 [M-plane] Add new Benetel FW supported and reference the new CI pipeline
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:15 +02:00
Jaroslava Fiedlerova
659b73e205 CI: Increase service deployment timeout
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 23:06:15 +02:00
Jaroslava Fiedlerova
3cb29be587 CI: add configs for 4x4 40 MHz test with M-plane
Running container in privileged mode and host network mode is needed
for running fhi72 gNB with M-plane

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 23:06:15 +02:00
Jaroslava Fiedlerova
1a405266f8 CI: add configs for 2x2 100 MHz test with M-plane
Running container in privileged mode and host network mode is needed
for running fhi72 gNB with M-plane

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 23:06:15 +02:00
Jaroslava Fiedlerova
56f2d4a90e docker: enable FHI72 mplane build
- Build and install libyang (v2.1.111) and libnetconf2 (v2.1.37) from source.
- Build ran-build-fhi72 image with M-plane enabled
- Copy YANG models required for M-plane operation into the container.
- Update gNB Dockerfile to work without M-plane

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 23:06:14 +02:00
Teodora Vladić
beec03fcd1 [M-plane] FFT offset is a positive value in [Ts]
In the future, adapt to long PRACH format.

Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:14 +02:00
Teodora Vladić
a2d53415e9 [M-plane] Get the right interface name
A RU can have multiple interfaces but for the M-plane purposes,
we need the ethernet interface.

Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:14 +02:00
Teodora Vladić
b7712fcc50 [M-plane] Extract the current running U-plane configuration
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:14 +02:00
Teodora Vladić
43931cfd4c [M-plane] Pass the default operation for <edit-config> RPC
Possible options:
```bash
typedef enum {
    NC_RPC_EDIT_DFLTOP_UNKNOWN = 0, /**< unknown default operation */
    NC_RPC_EDIT_DFLTOP_MERGE,       /**< default operation merge */
    NC_RPC_EDIT_DFLTOP_REPLACE,     /**< default operation replace */
    NC_RPC_EDIT_DFLTOP_NONE         /**< default operation none */
} NC_RPC_EDIT_DFLTOP;
```

Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:14 +02:00
Teodora
3d358f8484 [M-plane] Set variable PRACH offset for Benetel RU
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:14 +02:00
Teodora
1040b35625 [M-plane] Hack 2x2 mode to use every other antenna
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 23:06:14 +02:00
Gabriele Gemmi
0da290b2fe nfapi: fix UCI payload byte length for bit_len multiples of 8
bit_len / 8 + 1 overcounts by 1 when bit_len is an exact multiple of 8.
Replace with (bit_len + 7) / 8 across all pack/unpack sites for PUSCH
and PUCCH 2/3/4 SR/HARQ/CSI payloads, and in the utility functions
(eq, copy, size calculator, dump) and unit test fill functions.

Fixes UCI.indication unpack failure against cuBB when CSI-1 report
is 8 bits.

Signed-off-by: Gabriele Gemmi <g.gemmi@northeastern.edu>
2026-05-07 23:06:14 +02:00
Guido Casati
9f604b5e91 CI (n2-ho): ping ext-DN from NR-UE before ext-DN toward UE
After attach, run UL ping so N3 UL traffic hits the UPF
before the first DL ping. That triggers UL PDR classification
in the UPF and avoids DL GTP-U using the default QFI.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
7fe28185d2 RRC: add UE ID to QoS-related logs and fix LOG_W in Modify transaction
Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
68db1628ee CI: enable PCF-based dual-DNN multi-QoS in 25PRB RFSim
Expand the 25PRB RFSim CI scenario to validate two PDU sessions with
PCF-driven QoS rules and deterministic per-flow traffic ports. Update
iperf execution to use `-B`/`-p` from test args.

Changes:
- Update `container_5g_rfsim_u0_25prb.xml` to add dual-session
  validation steps, routing setup, and multi-flow UDP iperf
  for UL/DL with explicit bind/port arguments.
- Change `cls_oaicitest.py` to parse bind/port from
  `iperf_args`, and return a clear error when the iperf client exits non-zero.
- Update `nrue.uicc.2pdu.conf` to configure
  session 2 on `openairinterface` with distinct `nssai_sd` values.
- Extend `5g_rfsimulator/mini_nonrf_config.yaml`
  with PCF endpoints, dual slices, dual DNN entries, and PCF policy paths,
  and disable local PCC rules in SMF.
- Update `5g_rfsimulator_u0_25prb/docker-compose.yaml`
  to add the `oai-pcf` service, mount policy directories, and add ext-dn
  route for the second UE subnet.
- Add PCF policy data files for this scenario, in :
  `policies/policy_decisions/policy_decision.yaml`
  `policies/pcc_rules/pcc_rules.yaml`
  `policies/qos_data/qos_data.yaml`

About the ci-scripts:

Co-authored-by: Robert Schmidt <robert.schmidt@openairinterface.org>

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
bc06c62e2d doc: add QoS flows handling and PDU Session Modify documentation
Also, move PDU Session Release diagram to new PDU Session Management section in rrc-dev.md.

Changes:

PDU Session Modify:
- Update PDU session modification sequence diagram
- Add DRB-To-Remove/To-Modify/To-Setup list handling
- Document E1AP Bearer Context Modification flow
- Add RRC reconfiguration trigger after E1AP response

QoS Flows Handling:

- Complete overview with 3GPP standards references (TS 23.501, 37.324, 38.463, 29.281, 38.331)
- Comprehensive Mermaid sequence diagram covering control and data plane

Technical details:
- Multiple QoS flows per DRB supported
- QFI to DRB mapping at RRC and SDAP layer
- F1-U tunnels: 1 per DRB, no QFI marking
- N3 tunnels: 1 per PDU session, with QFI marking

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
dce9fcbbb1 PDU Session Modify: list only add/modify QFIs in NGAP modify response
Issue:

With a commercial UE, NGAP traces showed the PDU Session Resource Modify
Response carrying a QoSFlowAddOrModifyResponseList that did not match the
preceding Modify Request: the gNB listed every QoS flow already stored on the
PDU session instead of only the flows present in QoS Flow Add or Modify Request
List for that modify.

e.g. QoSFlowAddOrModifyResponseList including QFI 1,2
QoSFlowAddOrModifyRequestList QFI 2
AMF ErrorIndication with semantic_error after modify

That breaks the intended semantics in TS 38.413, which
expects QoSFlowAddOrModifyResponseList to carry the QFIs from this
procedure’s QoS Flow Add or Modify Request List only.

Changes:

Add a per-flow ngap_pending flag set in nr_rrc_update_qos when a request
item is applied, clear it before each new modify, and build the response
from marked flows only.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
f1deaef332 PDU Session Modify: add PDU Session Modify to the delayed transactions list
* Extend delay_transaction() and rrc_delay_transaction() to support NGAP_PDUSESSION_MODIFY_REQ

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
b5e618f261 PDU Session Modify: complete E1AP/RRC integration with DRB lifecycle management
This commit extends PDU Session Modify handling with E1AP Bearer Context
Modification integration for QoS flow add/modify/release and DRB lifecycle
updates (setup, modification, removal).

E1AP Bearer Context Modification - DRB Setup Support:
- Extend CU-UP handler (e1_bearer_context_modif) to process DRBs to setup/to remove:
  create F1-U tunnels, create/release PDCP-SDAP resources, and update QoS flow mappings
- Extend CU-CP response handler to process DRBs to setup: save F1-U tunnel info,
  mark PDU sessions for RRC reconfiguration, and trigger F1 UE Context
  Modification Request with both setup and release DRBs
- Update rrc_gNB_process_e1_bearer_context_modif_resp to collect DRBs to
  setup/release from E1 response, send F1 UE Context Modification when needed,
  and otherwise trigger direct RRC reconfiguration or NGAP modify response.
- Populate the E1AP Bearer Context Modification request with DRB-To-Setup and
  DRB-To-Modify lists derived from QoS flow processing. For CP->UP E1 Bearer
  Context Modification, Flow Mapping Information in DRB-To-Modify carries
  the QoS Flow QoS Parameters List for that DRB: per TS 38.463, when present,
  CU-UP replaces the previous mapping for that DRB, and this behavior is now enforced.

RRC PDU Session Modify - QoS and DRB Management:
- Add nr_rrc_apply_qos_add_modify() to process QoS add/modify and map flows to
  existing or new DRBs
- Add nr_rrc_apply_qos_release() and nr_rrc_apply_pdusession_modify() to
  process QoS release, build E1 DRB setup/modify/remove lists, and prepare
  bearer-context modification.
- Refactor nr_rrc_update_qos() processing for QoS add/modify,
  with DRB mapping to existing or new DRBs through the modify path helpers
- Extend nr_rrc_update_pdusession() with helpers for QoS
  add/modify/release, building E1 DRB modify/setup/remove lists, and
  sending bearer-context modification.
- Integrate E1 Bearer Context Modification into PDU Session Modify flow to
  propagate DRB changes to CU-UP
- Update default DRB in SDAP configuration after QoS changes
- Add `nr_sdap_entity_update_qos_flows` to replace DRB flow
  mappings from E1 flow information and clear stale SDAP role/mapping
  state when QFIs are removed.

Code Refactoring:
- Add find_or_add_pdu_session_mod() to create/reuse session entries
  in the E1 Bearer Context Modification request while building message.
- Add nr_rrc_send_e1_after_qos_update() to detect DRBs left without mapped
  QoS flows, remove them from UE state, and append them to E1 DRBs-to-remove.
- Use rrc_gNB_generate_dedicatedRRCReconfiguration instead of
  rrc_gNB_modify_dedicatedRRCReconfiguration, drop the old function

End-to-End PDU Session Modify Flow:

1. AMF -> CU-CP: NGAP PDU Session Resource Modify Request (QoS add/modify/release)
2. CU-CP (RRC): Process QoS flows -> map to DRBs (reuse existing or create new) ->
   populate E1AP Bearer Context Modification Request (DRBs to setup/modify/remove)
3. CU-CP -> CU-UP: E1AP Bearer Context Modification Request
4. CU-UP: Create F1-U tunnels for new DRBs -> create/release PDCP-SDAP
   resources -> update DRB/QFI mapping information
5. CU-UP -> CU-CP: E1AP Bearer Context Modification Response (F1-U tunnel info)
6. CU-CP: If DRB setup/release exists, send F1 UE Context Modification Request
7. CU-CP: Else if QoS/NAS requires it, send direct RRC Reconfiguration
8. CU-CP: Else complete modify directly with NGAP PDU Session Resource Modify Response
9. UE -> CU-CP: RRC Reconfiguration Complete
10. CU-CP -> AMF: NGAP PDU Session Resource Modify Response

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
ba22dc040d PDU Session Modify: extend PDU Session Modify Transfer (NGAP/RRC) with QoS add/modify/release
This commit extends the PDU Session Resource Modify Request handling (within
PDU Session Modify) to fully support QoS Flow add/modify and release operations
(3GPP TS 38.413 section 9.3.4.3) via the Transfer IE. This is propagated to
RRC which performs PDU Session update, which occurs upon PDU Session Modify.

Refactoring was necessary since type `pdusession_transfer_t` and
`pdusession_resource_item_t` both for setup, were inaccurately used for the modify procedure.

The implementation adds proper type definitions, decoding logic,
and error handling for QoS flow management during PDU session modification transfer,
namely:
- Adds QoS add/modify and release lists to the NGAP Modify Request Transfer type
- Introduces QoS Flow With Cause IE
- Decode new IEs and propagate QoS changes to RRC session state

NGAP PDU Session Modify Request Transfer:
- Add qos_flow_to_release_t structure to represent QoS Flow to Release Items IE
  with QFI and release cause (per 3GPP TS 38.413 section 9.3.1.13)
- Introduce pdusession_mod_req_transfer_t structure to properly represent
  PDU Session Resource Modify Request Transfer IEs:
  * QoS Flow Add or Modify Request List (mandatory)
  * QoS Flow to Release List (optional)
- Add pdusession_resource_mod_item_t structure for PDU Session Resource
  Modify Request Items, replacing pdusession_resource_item_t, which is for setup
- Update ngap_pdusession_modify_req_t to use the new type-specific structure
- Refactor decodePDUSessionResourceModify() to return
  pdusession_mod_req_transfer_t instead of pdusession_transfer_t
  - Implement proper decoding of QosFlowAddOrModifyRequestList IE
  - Add decoding support for QosFlowToReleaseList (QosFlowListWithCause) IE:
    * Extract QFI and cause for each QoS flow to be released
- Improve error handling throughout

ngap_msg_includes.h:
- Add includes for NGAP_QosFlowListWithCause.h and
  NGAP_QosFlowWithCauseItem.h to support QoS flow release decoding

NGAP/RRC:
- Update nr_rrc_update_pdusession() function signature to accept
  pdusession_resource_mod_item_t instead of pdusession_resource_item_t
- Remove references to unnecessary pdu_session_type and n3_incoming
  fields that are not part of the Modify Request Transfer structure
- Update QoS flow update logic to use nb_qos_to_add_modify and
  qos_to_add_modify fields from the new transfer structure

This implementation aligns NGAP with 3GPP TS 38.413 specifications
and provides a foundation for handling QoS flow modifications and releases
during PDU session resource modification procedures.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
5c790a46c2 QoS Handling: add multi-QoS unit tests
- Update F1AP test cases to support multiple QoS flows
- Extend RRC bearers test with comprehensive multi-QoS testing
- Extend PDU sessions test to 2 PDU sessions per test
- Introduce template helpers to minimize duplicated code

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
0c6c4a589d GTPU: move QFI handling to send path and update tunnel API usage
Refactor GTP-U tunnel and send APIs so QFI is handled when sending packets,
not stored in tunnel creation state. Update SDAP and CU-UP integration to
use PDU-session keyed N3 mappings and explicit QFI-marked sends.

This commit clarifies layering ownership: GTP-U stays transport-only (TEID
lookup, decapsulation, extension parsing, callback dispatch), while SDAP
owns QoS semantics (QFI handling, QoS-flow-to-DRB policy, default DRB behavior,
and mapping updates); GTP-U does not perform runtime QFI-to-DRB mapping or
synthesize QFI.

Changes:
- remove `outgoing_qfi` from `gtpv1u_gnb_create_tunnel_req_t` and stop storing
  QFI as tunnel creation metadata; `newGtpuCreateTunnel(...)` now carries only
  transport/tunnel identity parameters (incoming_bearer_id, outgoing_bearer_id,
  outgoing_teid, remote address, callbacks)
- add `gtpv1uSendDirectWithQFI()` and pass QFI into `_gtpv1uSendDirect`
  to build UL PDU Session Container extensions
- shift QFI handling from tunnel provisioning to per-packet TX APIs: QFI is passed
  explicitly only when sending (`gtpv1uSendDirectWithQFI(...)`) and is absent from
  non-SDAP/F1 sends (`gtpv1uSendDirect(...)`)
- align N3 tunnel request semantics with session-level keys by setting incoming_rb_id
  to PDU session ID on N3 paths, while F1 paths keep DRB ID
- keep `gtpv1uSendDirect()` and `gtpv1uSendDirectWithNRUSeqNum()` on
  `NO_QFI`, and enforce non-SDAP RX callback path only when QFI is absent
- update `nr_sdap_rx_entity` to extract/validate QFI from SDAP UL headers,
  send UL data with `gtpv1uSendDirectWithQFI`, and use non-QFI send when
  SDAP header is disabled
- add disabled-SDAP safety checks in SDAP entity setup/mapping to enforce
  single-DRB and single-flow constraints per PDU session
- extend `test_gtp.cpp` with a `multi_qos_flows` scenario and QFI-aware send calls
- update `nr-cuup-load-test.c` bearer setup fields and tunnel creation calls
  to match the new API
- update tests/nr-cuup/nr-cuup-load-test.c to set explicit PDU session and
  QoS/SDAP parameters (sessionType, qosFlows[0], SDAP header flags), and to
  migrate both N3 and F1 tunnel creation calls to the new newGtpuCreateTunnel(...)
  signature (without outgoing_qfi)

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:14 +02:00
Guido Casati
fd54b116ab QoS handling: add F1 QoS Flow Information IE (GBR) handling in the CU
GBR information is optional in F1AP and is only present for GBR flows
(5QI < 5 for NonDynamic5QI, or Dynamic5QI flows with GBR characteristics).

Changes:

- Add optional gbr_qos_flow_information field to f1ap_qos_flow_param_t
  structure to propagate NGAP GBR QoS parameters to the DU, for scheduling
  resource allocation via nr_rrc_get_f1_qos_flow_param.

- Add GBR QoS flow information IE enc/dec in F1AP lib:
  - update encode_qos_flow_param() and decode_qos_flow_param()
  - update cp/eq/free
  - add GBR tests to f1ap_lib_test.c

This commit is a refactoring of commit 398ae02ab9 from !2836

Co-authored-by: Sriharsha Korada <sriharsha.korada@iis.fraunhofer.de>

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
f2151bf2c9 QoS handling: add GBR QoS flow information decoding from NGAP QoS Flow Setup Request List
Implement GBR (Guaranteed Bit Rate) QoS flow information extraction from NGAP.
This enables handling in CU of GBR QoS flows
(e.g., voice, video) that require guaranteed and maximum bit rates.

Changes:
- Define qos_bitrate_t structure to encapsulate GFBR and MFBR
- Define gbr_qos_flow_information_t structure for GBR QoS parameters
- Add optional gbr_qos_flow_information field to pdusession_level_qos_parameter_t
- Extract GBR information from NGAP_QosFlowLevelQosParameters in fill_qos()
- Add NGAP_GBR-QosInformation.h include to ngap_msg_includes.h

GBR information is optional in NGAP and is only present for GBR flows
(5QI < 5 for NonDynamic5QI, or Dynamic5QI flows with GBR characteristics).
Bit rates are in kbps.

This commit is a refactoring of commit 398ae02ab9 from !2836

Co-authored-by: Sriharsha Korada <sriharsha.korada@iis.fraunhofer.de>

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
16055e7939 QoS handling: add Dynamic5QI QoS support/validation, split QoS characteristics by 5QI type
Model non-dynamic vs dynamic 5QI characteristics explicitly and propagate the
new layout through NGAP decode and RRC bearer/QoS handling.

Changes:
- Define `non_dynamic_5qi_t`/`dynamic_5qi_t`, PER/PDB bounds, and embed a
  `qos_characteristics` union in `pdusession_level_qos_parameter_t`
- Populate the new QoS structures in `fill_qos()`, including optional
  allocations for Dynamic 5QI `fiveQI` and NonDynamic `priorityLevelQos`
- Map QoS params to F1AP with `nr_rrc_get_f1_qos_flow_param()` and add range
  validation for dynamic priority/PDB/PER and non-dynamic 5QI
- Populate E1 QoS characteristics from the new layout and update QoS modify
  handling to manage optional pointer fields (`openair2/RRC/NR/rrc_gNB_NGAP.c`)
- Derive a numeric 5QI via `get_qos_fiveqi()`, handle missing-5QI dynamic flows
  conservatively, and extend dedicated-DRB decisions to fall back to dynamic
  characteristics
- Add a 5QI range assert in F1AP QoS encoding and extend bearer tests with a
  Dynamic 5QI flow

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
59190571e4 QoS handling: add F1AP DRB QoS (IE) aggregation
DRB QoS IE (mandatory in DRB-Information IE) represents the DRB level QoS,
which shall be computed from multiple QoS flows mapped to the DRB instead
of using only the first QoS flow.

ARP is for admission control/preemption (1-15, 1 = highest priority) and
DRB-level QoS selection should use ARP for admission control decisions.

Changes:
- Use ARP priority (not 5QI priority) for selection (admission control decision)
- Iterate through all flows to find the flow with highest ARP priority (lowest ARP priority_level value
- Add fill_f1_drb_qos to return DRB QoS by value, i.e. QoS characteristics (5QI, priority, delay budget, error rate)
- Replace 'drb.nr.drb_qos = drb.nr.flows[0].param' with proper aggregation

Example: DRB with Flow1 (ARP=10) and Flow2 (ARP=5)
- Old: Would incorrectly use Flow1's QoS
- New: Correctly uses Flow2 (ARP=5) which has higher priority

This commit is a refactoring of commit 398ae02ab9 from !2836

Co-authored-by: Sriharsha Korada <sriharsha.korada@iis.fraunhofer.de>

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
5a1dd490b8 QoS Handling: set default DRB in SDAP entity to first DRB added
According to 3GPP TS 37.324, there shall be only one default DRB per
SDAP entity (per PDU session). The previous implementation incorrectly
marked all DRBs as default, violating this requirement.

Changes:
- Add default_drb field to nr_sdap_configuration_t to track the default
  DRB ID per PDU session
- Arbitrary set default DRB to the first DRB added when creating bearers in a
  PDU session
- Update nr_rrc_build_sdap_config_ie() to accept defaultDRB (bool) parameter
  instead of hardcoding true
- Use tracked default_drb value when building RRC SDAP Config IE
- Use tracked default_drb value when building E1AP DRB setup structure

Also:
- Fix include style in nr_sdap_configuration.h (<stdbool.h> instead of
  "stdbool.h")

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
3fb7516ab6 QoS handling: add 5QI validation during QoS flow setup/modify
Move 5QI validation from RRC reconfiguration message generation to
where QoS flows are actually added/updated, ensuring validation
happens early in the process.

Changes:
- Remove redundant 5QI validation from rrc_gNB_modify_dedicatedRRCReconfiguration():
  that was checking values right before RRC message generation
- Add 5QI validation in add_qos() to reject unsupported 5QI values
  during PDU session setup
- Add 5QI validation in nr_rrc_update_qos to skip unsupported 5QI
  values during PDU session modify (continues to next flow)
- Add is_5qi_supported() function in rrc_gNB_radio_bearers.c:
  validates standardized 5QI values (1-9, 65-90) per 3GPP TS 23.501
  Table 5.7.4-1 and checks against the classification map

Also, remove remaining limit to 1 QoS flow per DRB.

Closes #541

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
08f699a121 QoS Handling: implement intelligent QoS-to-DRB mapping based on 3GPP TS 23.501
Implement QoS flow multiplexing logic that optimizes DRB usage by classifying
5QI values per 3GPP TS 23.501 Table 5.7.4-1 and applying resource-type-aware
multiplexing limits. The changes are adopted in nr_rrc_add_bearers, which
is the RRC function responsible for adding PDU Sessions and DRBs in RRC.

Key features:
- Classify 5QI by resource type (DC-GBR, GBR, Non-GBR)
- Reuse existing DRBs when QoS characteristics are compatible
- Dedicated DRBs for DC-GBR (5QI 82-90) and high-priority services
- Per-type multiplexing limits: DC-GBR=1, GBR=2, Non-GBR=5
- Aggregate cap: max 5 flows per DRB

Implementation:
- nr_rrc_get_5qi_resource_type():
  Maps 5QI values to resource types using lookup table.
  DC-GBR: 5QI 82-90, GBR: 5QI 1-4,65-67,71-76, Non-GBR: 5QI 5-11,69-70,79-80.
  Unknown 5QIs default to Non-GBR with warning.

- nr_rrc_qos_dedicated_drb():
  Identifies 5QIs requiring isolated DRBs (high priority, low-PER).
  Includes: DC-GBR: 5QI 82-90, 5QI 4,6-10 (video), 5QI 70 (mission-critical),
  5QI 71-73 (live streaming), 5QI 80 (low-latency).

- nr_rrc_count_qos_flows_by_type():
  Counts QoS flows mapped to a specific DRB, grouped by resource type.
  Used to check capacity and enforce multiplexing limits.

- nr_rrc_find_suitable_drb_for_qos():
  Searches existing DRBs in the same PDU session for available capacity.
  Checks resource type compatibility, per-type limits, and aggregate cap.
  Returns DRB ID if suitable, -1 if new DRB needed.
  DC-GBR flows always return -1 (require dedicated DRB).

- nr_rrc_assign_drb_to_qos_flow(), which either reuses a DRB
  selected by nr_rrc_find_suitable_drb_for_qos() or creates a new DRB via
  nr_rrc_add_drb, assigns its ID to the QoS flow

Note: this commit is multi-QoS ready.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
021ef0ef36 CU-UP: refactor DRB to be setup logic (E1 bearer context) into reusable helper functions
The new bearer context setup logic is looping through the PDU sessions
to be setup list first and then through the DRB to be setup list.
The function has still room for improvement since e1_bearer_context_setup
is calling a getter for NR_DRB_ToAddModList_t which has another nested
DRB loop. The goal of this commit is to further simplify the logic
by minimizing unnecessary nested loops, improving clarity and preparing
for reuse in Bearer Context Modification.

Main changes:

- Build DRB_ToAddMod list in the DRBs loop and centralize SDAP/PDCP configuration
- Add helpers to fill DRB to be setup and QoS flow handling, to improve organization
  and enable reuse in bearer context modification procedures.

Implementation:
- Replace fill_DRB_configList_e1() with fill_rrc_drb_to_addmod()
  * Build one NR_DRB_ToAddMod item per DRB from E1 DRB_nGRAN_to_setup
  * Accumulate all DRBs into a single NR_DRB_ToAddModList_t per PDU session
- Call e1_add_bearers() once per PDU session with the aggregated list,
- Introduce fill_e1_qos_flows_setup() to populate DRB_nGRAN_setup_t
  * Iterate E1AP QoS flows and copy QFIs into the E1 response
- Introduce fill_e1_drb_setup() to encapsulate DRB_nGRAN_setup_t filling
  via fill_rrc_drb_to_addmod()
- Refactor e1_bearer_context_setup() to use new helper functions

Note: supports multiple QoS flows per DRB (TS 38.331 compliant)
  * Move security parameters setup to caller scope
  * Simplify DRB loop logic for better readability

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
6a133e3d28 GTPU: refactor tunnel creation API for N3 (per PDU session) and F1-U (per DRB)
Refactor GTP-U tunnel creation to align for 3GPP architecture where N3
tunnels are created per PDU session (supporting multiple QoS flows) and
F1-U tunnels are created per DRB. This change simplifies the API and
prepares the codebase for supporting multiple DRBs and QoS flows per
PDU session.

This is the first step of a final design that will consist of:
- 1 GTP-U tunnel create call for each PDU session, each with a DRB mapping
- 1 GTP-U tunnel create call for each DRB (i.e. no QFI, no internal mapping)

API Changes:
- Convert gtpv1u_gnb_create_tunnel_req_t and gtpv1u_gnb_create_tunnel_resp_t
  from array-based to scalar fields
  * Remove num_tunnels field and array fields (outgoing_teid[], pdusession_id[], etc.)
  * Use scalar fields: outgoing_teid, pdusession_id, incoming_rb_id, etc.
- Simplify gtpv1u_create_ngu_tunnel() to handle single tunnel per call
  * Remove internal loop that processed multiple tunnels
  * Call newGtpuCreateTunnel() once per invocation
  * Update response handling to fill single tunnel response

Function Refactoring:
- Split generic drb_gtpu_create() into specialized functions:
  * n3_gtpu_create(): Creates N3 tunnel (CU-UP to UPF/core network)
    - callback assigned internally: nr_pdcp_data_req_drb, sdap_data_req
    - One tunnel per PDU session
    - QFI marking
    - Supports multiple QoS flows per PDU session
  * f1_drb_gtpu_create(): Creates F1-U tunnel (CU-UP to DU or DU side)
    - callback assigned internally (cu_f1u_data_req or DURecvCb)
    - One tunnel per DRB
    - No QFI marking (QFI not used in F1-U)
    - Each DRB can carry multiple QoS flows
- Update e1_bearer_context_setup() to loop over DRBs per PDU session
  Each item in the PDU Session list contains a list of DRBs, thus
  the function helper was adjusted to reflect that:
  * Move DRB loop inside PDU session loop
  * Create F1-U tunnel for each DRB individually
  * Create single N3 tunnel per PDU session (outside DRB loop, with DRB mapping)

Also:
- Add comments to document and improve log messages for clarity
- Consistent error handling with AssertFatal checks
- Update NSA code path (rrc_gNB_nsa.c) to use new scalar API

Note: this commit is already taking into account the multi-QoS flows design

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
b6445d2dc4 GTPU: reduce inter-dependencies between LTE and NR in GTP-U header
This header is pulled by both LTE and NR libraries, therefore is
advised to minimise cross dependencies in LTE/NR. With this change
the only include is common/platform_types.h

Also, remove redundant comments.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
b39c78f6dd fix (nas): call set_qfi before PDU session interface setup on Session Accept
Apply QoS flow id as soon as the accept message is parsed, before interface
setup and before any code path that starts the per-session interface thread,
so the first SDUs are not sent with the default 0-initialized QFI 0.

Changes:
- In handle_pdu_session_accept, move set_qfi(...) to immediately before
  interface setup.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
f253b0195b fix (NGAP): encode optional QoS list when not empty
Only build QoSFlowAddOrModifyResponseList when at least one QFI is present
and fail fast if PDUSessionResourceModifyResponseTransfer encoding does not
produce a valid buffer. This avoids sending malformed modify responses and
makes encoding failures explicit in the NGAP modify response path.

Changes:
- do QoS add/modify response list allocation when nb_of_qos_flow > 0
- add ASN.1 encode result validation

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
36890bd876 fix (NGAP): decode PDUSessionResourceHandoverList with correct IE id
Use the PDUSessionResourceHandoverList protocol IE identifier when
decoding HandoverCommand optional session resources.

Changes:
- replace IE lookup id_HandoverType with
  id_PDUSessionResourceHandoverList in decode_ng_handover_command()

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
3d37d77518 fix (NGAP): guard optional PDUSessionNAS-PDU in PDU Session Setup Request handler
Avoid NULL dereference when AMF omits the optional pDUSessionNAS-PDU
IE in PDUSessionResourceSetupRequest.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
73d2824876 fic (NGAP): double allocation and ASN free in PDU Session Modify Response
Remove redundant allocation and duplicate add for AMF_UE_NGAP_ID (asn1cSequenceAdd
already allocates), fixing encoding failure and leak. Fix ASN_STRUCT_FREE_CONTENTS_ONLY
in the unsuccessful-transfer path to free the correct struct.

Changes:
- In ngap_gNB_pdusession_modify_resp(), for AMF_UE_NGAP_ID IE: remove redundant
  calloc() and duplicate asn1cSeqAdd() after asn1cSequenceAdd (avoids uninitialized
  list element, encoding assertion, and leak).
- In PDU Session Resource Modify Unsuccessful Transfer handling: pass
  &pdusessionTransfer to ASN_STRUCT_FREE_CONTENTS_ONLY instead of the unused
  NULL pointer pdusessionTransfer_p;

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
8b65fc65e0 SDAP: fix PDU session ID range validation logic
Replace incorrect mathematical range check with explicit bounds
validation in nr_sdap_delete_entity(). The previous condition
(pdusession_id) * (pdusession_id - NR_MAX_NB_PDU_SESSIONS) > 0
was mathematically incorrect and could fail to properly validate
PDU session IDs.

PDU session ID validation now correctly rejects values outside
the valid range [0, NR_MAX_NB_PDU_SESSIONS]

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
0f0f989be2 E1AP: make ActivityNotificationLevel configurable in Bearer Context Setup
This is a mandatory IE.

Replace hardcoded ActivityNotificationLevel value with configurable field
in e1ap_bearer_setup_req_t structure, enabling proper encoding/decoding
and testability of different notification levels. ActivityNotificationLevel
is now properly encoded from message structure instead of hardcoded value,
enabling different notification levels (DRB, PDU Session, UE) to be
specified per bearer setup request.

Changes:
- Add activity_notification_level_t enum with values: drb, pdu_session, ue
- Add anl field to e1ap_bearer_setup_req_s structure
- Replace hardcoded E1AP_ActivityNotificationLevel_pdu_session with
  dynamic value from msg->anl in encode_E1_bearer_context_setup_request
- Add ActivityNotificationLevel IE dec/eq/cp
- Update test and RRC call sites to initialize anl field
- Add E1AP_ActivityNotificationLevel.h include to e1ap_lib_includes.h

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
7e8744927b E1AP: convert PDU session arrays to dynamic allocation
Replace fixed-size PDU session arrays with dynamically allocated
pointers in E1AP bearer context request/response types to reduce
memory footprint and improve scalability.

Memory usage is now proportional to actual PDU session count
instead of always allocating for maximum capacity.

Impact:
- Callers must allocate and free PDU session arrays; E1AP decode/cp
  allocate, free_e1ap_context_setup_request/mod_request free them.

Major changes:
- Request/response types (e1ap_messages_types.h): pduSession, pduSessionMod,
  pduSessionRem as pointers in setup/mod request and setup/modif response structs.
- E1AP lib: decode allocates with bounds check; cp/eq/free handle pointer members;
  e1ap.c frees setup request after handling.
- CU-UP (cucp_cuup_handler): allocate resp.pduSession and modif.pduSessionMod.
- CU-CP side (cuup_cucp_direct, rrc_gNB, rrc_gNB_NGAP): allocate at E1 request
  build and call free after send where needed; rrc_gNB_NGAP includes E1AP free decls.
- Tests (e1ap_lib_test, nr-cuup-load-test): allocate PDU session arrays in helpers.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
837c7fd516 fix (E1AP): allocate DRB-To-Modify list once in PDU session encode
When building E1AP PDU Session Resource To Modify items, create
dRB_To_Modify_List_NG_RAN only once if there are DRBs to modify, and add
modify items to that list.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
c83b0afd2d fic (E1AP): remove single-DRB limit in PDU session DRB setup list decode (PDU session setup/modify)
Decode paths for PDU Session Resource To Setup and To Setup/Modify must
accept multiple DRB list entries, aligned with multi-DRB RRC behaviour.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:13 +02:00
Guido Casati
79bcc68e53 fix (E1AP): iterate DRB Setup List by numDRBSetup in mod response
Fix wrong bound in the setup list loop: Bearer Context Modification
Response encoding must populate dRB_Setup_List_NG_RAN from
DRBnGRanSetupList[0..numDRBSetup), not numDRBModified.

In encode_E1_bearer_context_mod_response(), change the DRB Setup List
encoding loop from pdu->numDRBModified to pdu->numDRBSetup.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
d311e718fa Platform types (QoS): refactor QoS Priority Level type per 3GPP TS 23.501
QoS Priority Level range is 1-127, fits in uint8_t (3GPP TS 23.501 §5.7.3.3).

Refactor qos_priority field in pdusession_level_qos_parameter_t to use
qos_priority_level_t typedef (uint8_t) instead of uint64_t. Also,
improve documentation.

Changes:
- Add qos_priority_level_t typedef (uint8_t), more efficient than uint64_t
- Change pdusession_level_qos_parameter_t.qos_priority from uint64_t
  to qos_priority_level_t
- Add MIN_QOS_PRIORITY_LEVEL (1) and MAX_QOS_PRIORITY_LEVEL (127)
  defines for range checks

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
3fdc262c3f Platform types (QoS): refactor ARP priority level type
Since qos_priority_t reprensents the ARP priority level, an integer
(1..15), this commit is renaming it to qos_arp_priority_level_t
typedef (uint8_t) for better clarity and cleaning up unnecessary enum definition.

Changes:
- Rename qos_priority_t to qos_arp_priority_level_t (uint8_t typedef)
  for type safety and semantic meaning
- Remove enum with 15 explicit values (not needed, matches spec as integer)
- Add MIN_QOS_ARP_PRIORITY_LEVEL (1) and MAX_QOS_ARP_PRIORITY_LEVEL (15) defines
  for bound checks, simpler and more efficient
- Update qos_arp_t struct to use new typedef

References:
- 3GPP TS 23.501 §5.7.2.2!

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
dff73e9bdd Platform constants: consolidate PDU session limit constants
Replace NGAP_MAX_PDU_SESSION and E1AP_MAX_NUM_PDU_SESSIONS with
shared NR_MAX_NB_PDU_SESSIONS constant. The value (256) is consistent
with both TS 38.331, TS 38.413 and TS 38.463

All protocol layers (NGAP, E1AP, RRC, SDAP) now use a single
shared constant for maximum PDU sessions per UE, ensuring
consistency across the codebase

E1AP_MAX_NUM_PDU_SESSIONS (was 4) is removed from e1ap_messages_types.h

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
2879141485 RRC: remove warning when UP params are missing
Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
378c132f3a RRC: simplify PDU session status tracking, remove intermediate states
- Remove PDU_SESSION_STATUS_DONE and PDU_SESSION_STATUS_REESTABLISHED
  from enum and from get_pdusession_status_text().
- Add rrc_gNB_action_from_pdusession_status(): sets xid for all PDU
  sessions and derives RRC transaction action from session status
  (NEW, TOMODIFY, TORELEASE) or reestablishment. Add macro
  ASSERT_PDU_ACTION_SINGLE to enforce at most one active status
  (or reestablishment) per transaction.
- rrc_gNB_generate_dedicatedRRCReconfiguration: replace inline loop
  and xid/action logic with a single call to the new helper; stop
  transitioning NEW to DONE here.
- rrc_gNB_modify_dedicatedRRCReconfiguration: set xid at loop start;
  bypass sessions with status != TOMODIFY (instead of >= DONE); remove
  FAILED handling and DONE/xid assignments from loop; add xid to log.
- NGAP: INITIAL_CONTEXT_SETUP_RESP and PDUSESSION_SETUP_RESP check
  NEW (not DONE) and set ESTABLISHED when reporting success;
  PDUSESSION_MODIFY_REQ sets TOMODIFY (not NEW); PDUSESSION_MODIFY_RESP
  checks TOMODIFY (not DONE), drops NEW/ESTABLISHED branch, improves
  warning text; HANDOVER_REQUIRED considers only ESTABLISHED (drop DONE).

PDU sessions now move directly from NEW or TOMODIFY to ESTABLISHED in
the NGAP response handlers. One RRC reconfiguration corresponds to one
NGAP procedure (single active PDU session status per transaction).
rrc_gNB_modify_dedicatedRRCReconfiguration remains the separate
entry point for PDU Session Modify.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
87af95a9b0 RRC: rrc_gNB_radio_bearers.c - add QoS flow and DRB removal utilities
PDU Session Modify procedures enable the teardown of a subset of DRBs
and, together with multi-QoS handling, of a subset of QoS flows.
Thus, it is necessary to introduce (1) `rm_qos` to remove a specific QFI
from the RRC list of QoS flows and (2) `nr_rrc_remove_drb_by_id`
to remove a specific DRB by ID, upon successful retrieval of the pointer
to its RRC list item.

- Add rm_qos() to remove QoS flows by QFI from PDU session QoS list
- Add nr_rrc_remove_drb_by_id() to remove DRBs by ID from UE DRB list
- Export find_drb_by_pdusession_id() as public functions for reuse
  in PDU session modify procedures

These utilities enable QoS flow release and DRB cleanup operations
required for PDU Session Resource Modify Request handling.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
199d814d54 RRC: consolidate F1 UE Context Modification Request handling
UE Context Modification Request can be triggered by either DRB setup
(from either PDU Session Setup or Modify) or modify (setup/release in PDU Session Modify).
The goal of this commit is to refactor the handling of UE Context Modification Request
messages by improving clarity and reducing code duplication.

Changes:

- Remove overlapping DRB release function `rrc_gNB_send_f1_drb_release_request` and replace with
  unified `rrc_send_f1_ue_context_modification_request` that handles both DRB setup and release.
- Remove inefficient `rrc_gNB_generate_UeContextModificationRequest` and inline
  its logic into callers using the new unified helper.
- Fix type safety in DRB release handling: change from `int *drb_to_release` to
  `f1ap_drb_to_release_t *rel_drbs` to use proper struct type instead of raw int array.
- `rrc_send_f1_ue_context_modification_request` copies DRB arrays internally before freeing,
   allowing safe use of stack-allocated arrays by callers.
- Update `rrc_gNB_process_e1_bearer_context_setup_resp` to use unified helper for DRB setup
  when F1 context is already active.
- Update `rrc_gNB_process_e1_bearer_context_modif_resp` to DRB release in a single F1 UE
  Context Modification Request call (will be later used for DRB setup, improving efficiency)
- Replace magic number `32` with `E1AP_MAX_NUM_DRBS` constant for better maintainability.
- Update E1AP procedures documentation to reflect unified function name.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
f146feef50 RRC: refactor trigger_bearer_setup to split RRC bearers lists setup from E1 trigger
The current trigger_bearer_setup is mixing 2 functionalities: (1) setting up
RRC lists in the UE context (e.g. PDU Sessions, DRBs) (2) filling the E1AP
message to trigger Bearer Context Setup.

This commit is separating the two functionalities.
This is necessary to improve the readability of the code flow supporting
the setup of new bearers before the upcoming QoS-related changes.

* Introduce nr_rrc_add_bearers(rrc, UE, n, sessions) to populate UE context
  lists (PDU Sessions, one DRB per session, one QoS per DRB).
* Early CU-UP rejection: apply early is_cuup_associated(rrc) checks at call
  sites to fail fast before mutating UE context (this check is the reason
  why the original function was a bool).
* trigger_bearer_setup goal is to fill Bearer Context setup message upon reception
  of PDU sessions to setup, therefore it was changed to fill the bearer context setup
  for all PDU session with status PDU_SESSION_STATUS_NEW.
  Signature was changed to return void and read the lists from UE context.
  The function is also deriving UP keys and building PDU Session and DRB items
  to setup via helpers (e.g. fill_e1_pdusession_to_setup to fill PDU Session to
  setup items).
* Enforce single DRB per PDU Session, will be updated in a later commit.

Impact
* Each function has now limited and self-conteined scope:
  nr_rrc_add_bearers is responsible for update of RRC lists in the UE context.
  trigger_bearer_setup is responsible for preparing the E1 Bearer Context message.
* E1 Bearer Context Setup construction is centralized and clearer.
* The flow is now following these steps:
  1) receive NG request to setup PDU Sessions
  2) check CUUP association first, early failure if check fails
  3) add PDU Session and DRBs to UE context lists
  4) trigger Bearer Context Setup Request

The same flow applies to PDU Sessions from the Initial Context Setup (initial_PDUs)
with the only difference that those are stored in a separate list (legacy behavior)
and to NG Handover Request processing.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
e0840ffed8 fix (RRC): include NR ASN constants in DU SIB builder
Include NR_asn_constant.h in rrc_gNB_du.c so NR_maxCellIntra and NR_maxCellInter
are defined during compilation.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Guido Casati
46694b7425 PDCP build: exclude CU-CP/CU-UP from UE, guard E1 init for gNB only
- Common source in NR_PDCP_SRC and derive NR_PDCP_SRC_GNB (gNB) and
  NR_PDCP_SRC_UE from it; UE no longer compiles cucp_cuup_handler,
  cuup_cucp_if, cuup_cucp_direct, cuup_cucp_e1ap.
- NR_L2_SRC_UE uses NR_PDCP_SRC_UE so UE links only common PDCP sources.
- Add L2_NR compile definition PDCP_CUCP_CUUP; wrap nr_pdcp_e1_if_init
  call in nr_pdcp_oai_api.c with #ifdef PDCP_CUCP_CUUP so UE does not
  reference it.

UE build no longer depends on E1/CU-CP/CU-UP code or symbols; gNB
keeps full PDCP and E1 interface init.

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-07 23:06:12 +02:00
Shubhika Garg
c049ae4b7e chore: replace cn5g images with latest stable release v2.2.1
- upgrade MySQL image to 9.6
    - Update trf-gen-cn5g Docker images to latest tag

Signed-off-by: Shubhika Garg <shubhika.garg@openairinterface.org>
2026-05-07 23:06:12 +02:00
Sakthivel Velumani
4ff9f3f756 fix: perform FFT only on PBCH symbols
Signed-off-by: Sakthivel Velumani <s.velumani@northeastern.edu>
2026-05-07 23:06:12 +02:00
Sakthivel Velumani
b57d1f215f log: fix debug logging
Signed-off-by: Sakthivel Velumani <s.velumani@northeastern.edu>
2026-05-07 23:06:12 +02:00
Sakthivel Velumani
44f5adc828 Refactor PBCH & PSBCH UE procedures
1. Refactor channel estimation and freq domain data extraction functions
   to take rxdataF of only one symbol.
2. Split the PBCH and PSBCH decoding into two parts. Fisrt part is
   called for every symbol and generates LLRs of each symbol. Second
   part is called in the last PBCH/PSBCH symbol to decode and send the
   payload to MAC.
3. In channel estimation, the loop around rx antennas is taken out to
   make the code more modular.

Signed-off-by: Sakthivel Velumani <s.velumani@northeastern.edu>
2026-05-07 23:06:12 +02:00
Aswanth KC
01ad6950c6 Config: Creating New Array members via command line arguments
Before this change, if you wanted to use --rfsimulator.[0].serveraddr server
on the command line but if you had no rfsimulator block in your config file,
it would just ignore it and print:
[CONFIG] unknown option: --rfsimulator.[0].serveraddr
[CONFIG] unknown option: server

This is because the config module only processes array members that already
exist in the config file. If the array is empty, the command args are never checked.

What I changed is, in config_getlist() in config_userapi.c, after it finishes
processing existing array parameters, it checks whether a new parameter is given
in CLI.

The array number in the parameter(num) should match with the valid index of
that specific array

--cfg.[0].value 1 creates one array with one element
valid_index = num = 1

--cfg.[0].value 1 --cfg.[0].value 2 creates an array with two elements
if the previous CLI number repeats increments the "num"
valid_index = num = 2

--cfg.[1].value 1 --cfg.[0].value 2 error
valid_index < num, expects 0.

Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:06:12 +02:00
karim
a4e34a14e6 Update microamp FR2 doc for firmware 0.1.174
Signed-off-by: karim <karim.boutiba@openairinterface.org>
2026-05-07 23:06:12 +02:00
Robert Schmidt
40cc218001 nr-cuup-load-test: avoid unaligned memory access
Use memcpy() instead of unaligned pointer access

    tests/nr-cuup/nr-cuup-load-test.c:431:16: runtime error: store to misaligned address 0x756d02eca1a2 for type 'uint32_t', which requires 4 byte alignment
    tests/nr-cuup/nr-cuup-load-test.c:267:14: runtime error: load of misaligned address 0x756d095edcf6 for type 'uint32_t', which requires 4 byte alignment

Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-07 23:06:12 +02:00
francescomani
51028c3522 removed few more unused parameters
Signed-off-by: francescomani <email@francescomani.it>
2026-05-07 23:06:11 +02:00
francescomani
ab22ec4777 remove unnecessary rrc_enb_process_msg hack in nr-uesoftmodem
Signed-off-by: francescomani <email@francescomani.it>
2026-05-07 23:06:11 +02:00
francescomani
fd3b5ce8c4 remove unnecessary pdcp_run hack in nr-softmodem
Signed-off-by: francescomani <email@francescomani.it>
2026-05-07 23:06:11 +02:00
francescomani
b019c6d553 remove unused dump_uci_stats
Signed-off-by: francescomani <email@francescomani.it>
2026-05-07 23:06:11 +02:00
Rakesh Mundlamuri
58bbc10415 Modify nr-cu-nrppa-test simulator to use UE data from config file
Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-07 23:06:11 +02:00
Rakesh Mundlamuri
2d4b0f0e4d Fixing broken nr-cu-nrppa-test simulator and nr-ue-nas-simualtor
Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-07 23:06:11 +02:00
Robert Schmidt
9bdb8ac1b2 unit test: build everything
The previous commit is only necessary because not everything is built in
unit tests...

Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-07 23:06:11 +02:00
Robert Schmidt
d846e7c4f8 spsc_q: fix call to spsc_q_alloc() in benchmark
Fixes: 4d67a6e513 ("spsc_q: make compile on older compilers")

Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-07 23:06:11 +02:00
Reem Bahsoun
e27a8947be Add WNC RU configuration section to FHI 7.2 tutorial.
Signed-off-by: Reem Bahsoun <reem.bahsoun@openairinterface.org>
2026-05-07 23:06:11 +02:00
Reem Bahsoun
742c946858 Add a OAI-WNC config file in targets.
Signed-off-by: Reem Bahsoun <reem.bahsoun@openairinterface.org>
2026-05-07 23:06:11 +02:00
Florian Kaltenberger
d5f53bf32f fixing wrong logic for SIMO and MISO AWGN channels
Signed-off-by: Florian Kaltenberger <florian.kaltenberger@eurecom.fr>
2026-05-07 23:06:11 +02:00
Shubhika Garg
47b6d2a88b ci: skip merge-commit validation for integration branches
- use regex to match integration_YYYY_wWW branches

Signed-off-by: Shubhika Garg <shubhika.garg@openairinterface.org>
2026-05-07 23:06:11 +02:00
Shubhika Garg
50a9ebd5d2 ci: post MR validation comments only on warnings or errors in pre-ci-check
Signed-off-by: Shubhika Garg <shubhika.garg@openairinterface.org>
2026-05-07 23:06:11 +02:00
Raymond Knopp
8961e71697 small change for incorrect check on idft768 for aarch64
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-07 23:06:11 +02:00
Raymond Knopp
1cd2e46a5b small changes to scaling schedule for dft4096/dft2048 while testing on aarch64
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 14:09:51 +02:00
Raymond Knopp
bae93e84ce first change from codex
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 14:08:28 +02:00
Raymond Knopp
35e4a0fd11 AArch64 NEON: use vpaddq_s32 + vmull_high_s16 in complex multiply primitives
Replace ARM32-compatible pairwise-add patterns in cmult/cmultc/cmac/cmacc/
packed_cmult2 with AArch64-native vpaddq_s32 and vmull_high_s16, which
process the full 128-bit register in one step without extracting halves.
Also replace vzipq_s32 (struct return) in cpack with vzip1q/vzip2q
(single-register returns) to avoid potential register spilling.

ARM32 fallback paths are preserved under #else.

Measured 21-28% speedup across all DFT sizes (128 to 49152 points)
with identical numerical accuracy (SQNR unchanged).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 14:08:10 +02:00
Raymond Knopp
e57cb9ddd1 compiler option
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 14:06:21 +02:00
Raymond Knopp
1c8912800b optimizations from Codex
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 14:05:27 +02:00
Raymond Knopp
5e9507053f prototype for write_matlab
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:59:24 +02:00
Laurent THOMAS
a8c7226f20 change (i)DFT interface to handle strong or weak signals with better precision
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:53:03 +02:00
Laurent THOMAS
22813be341 move a unused static function in the test #if zone
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:42:27 +02:00
Laurent THOMAS
74f71e2b27 move idft16 in the unitary test section because it is no more used in regular code, so it generate a warning, and petantic compiler options turn it in error
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:42:27 +02:00
Laurent THOMAS
b83f9aad83 one pass of code cleaning in dft
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:42:27 +02:00
Laurent THOMAS
057c25e748 change (i)DFT interface to handle strong or weak signals with better precision
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:42:26 +02:00
Laurent THOMAS
9763daa9cc Add signal power measurement for better processing in int16
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:40:28 +02:00
Laurent THOMAS
ac84fb740b add trivial DFT implementation on double float for reference testing
Signed-off-by: Raymond Knopp <raymond.knopp@eurecom.fr>
2026-05-06 13:40:28 +02:00
180 changed files with 13285 additions and 5816 deletions

View File

@@ -162,7 +162,7 @@ if (CROSS_COMPILE)
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
# The following intrinsics are assumed to be available on any x86 system
# (avx, f16c, fma, gnfi, mmx, pclmul, sse, sse2, sse3, xop)
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_F16C_NATIVE -DSIMDE_X86_FMA_NATIVE -DSIMDE_X86_GFNI_NATIVE -DSIMDE_X86_MMX_NATIVE -DSIMDE_X86_PCLMUL_NATIVE -DSIMDE_X86_SSE2_NATIVE -DSIMDE_X86_SSE3_NATIVE -DSIMDE_X86_SSE_NATIVE -DSIMDE_X86_XOP_HAVE_COM_ -DSIMDE_X86_XOP_NATIVE")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_F16C_NATIVE -DSIMDE_X86_FMA_NATIVE -DSIMDE_X86_MMX_NATIVE -DSIMDE_X86_PCLMUL_NATIVE -DSIMDE_X86_SSE2_NATIVE -DSIMDE_X86_SSE3_NATIVE -DSIMDE_X86_SSE_NATIVE -DSIMDE_X86_XOP_HAVE_COM_ -DSIMDE_X86_XOP_NATIVE")
message(STATUS "AVX512 intrinsics are ${AVX512}")
if(${AVX512})
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX512BW_NATIVE -DSIMDE_X86_AVX512F_NATIVE -DSIMDE_X86_AVX512VL_NATIVE -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512")
@@ -842,6 +842,7 @@ set(PHY_NRLDPC_CODINGIF
)
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
target_compile_options(dfts PRIVATE -fno-semantic-interposition)
set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
@@ -1136,12 +1137,20 @@ set(NR_PDCP_SRC
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
)
# gNB: PDCP + CU-CP/CU-UP interface
set(NR_PDCP_SRC_GNB
${NR_PDCP_SRC}
openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c
openair2/LAYER2/nr_pdcp/cuup_cucp_if.c
openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c
openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c
)
# UE build: PDCP only; CU-CP/CU-UP interface is gNB-only.
set(NR_PDCP_SRC_UE ${NR_PDCP_SRC})
set(NR_SDAP_SRC
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap.c
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_entity.c
@@ -1185,7 +1194,7 @@ set(L2_LTE_SRC
)
set(L2_NR_SRC
${NR_PDCP_SRC}
${NR_PDCP_SRC_GNB}
${NR_SDAP_SRC}
${NR_RRC_DIR}/rrc_gNB.c
${NR_RRC_DIR}/mac_rrc_dl_direct.c
@@ -1221,7 +1230,7 @@ set(L2_RRC_SRC_UE
)
set(NR_L2_SRC_UE
${NR_PDCP_SRC}
${NR_PDCP_SRC_UE}
${NR_SDAP_SRC}
${NR_UE_RRC_DIR}/L2_interface_ue.c
${NR_UE_RRC_DIR}/main_ue.c
@@ -1365,6 +1374,7 @@ add_library(e1_if
target_link_libraries(e1_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap SECURITY ${OPENSSL_LIBRARIES} e1ap GTPV1U)
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc nr_common)
target_compile_definitions(L2_NR PRIVATE PDCP_CUCP_CUUP)
if(OAI_AERIAL)
target_compile_definitions(L2_NR PRIVATE ENABLE_AERIAL)
endif()
@@ -1898,7 +1908,7 @@ add_executable(nr-cuup
executables/nr-cuup.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${OPENAIR2_DIR}/E1AP/e1ap_setup.c
${NR_PDCP_SRC}
${NR_PDCP_SRC_GNB}
${NR_SDAP_SRC}
)
@@ -1909,6 +1919,7 @@ target_link_libraries(nr-cuup PRIVATE
alg
dl pthread ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
target_compile_definitions(nr-cuup PRIVATE PDCP_CUCP_CUUP)
if(E2_AGENT)
target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup)
target_compile_definitions(nr-cuup PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)

View File

@@ -98,7 +98,9 @@ pipeline {
)
def mrValidationMessage = readFile(mrValidationLog).trim()
sh "rm -f ${mrValidationLog}"
addGitLabMRComment comment: "${mrValidationMessage}"
if (mrValidationExitCode >= 1) {
addGitLabMRComment comment: "${mrValidationMessage}"
}
if (mrValidationExitCode >= 2) {
error("${mrValidationMessage}")
}
@@ -761,6 +763,29 @@ pipeline {
}
}
}
stage ("SA-FHI72-MPLANE-CN5G") {
when { expression {do5Gtest} }
steps {
script {
triggerSlaveJob ('RAN-SA-FHI72-MPLANE-CN5G', 'SA-FHI72-MPLANE-CN5G')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
saFHI72MplaneStatus = finalizeSlaveJob('RAN-SA-FHI72-MPLANE-CN5G')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += saFHI72MplaneStatus
}
}
}
}
stage ("SA-Handover-CN5G") {
when { expression {do5Gtest} }
steps {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -85,6 +85,14 @@ oc-cn5g-20897:
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2026-apr oaicicd-core-for-fhi72"
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2026-apr oaicicd-core-for-fhi72 %%log_dir%%"
oc-cn5g-00105:
Host: cacofonix
NetworkScript: echo "inet 172.21.6.118"
RunIperf3Server: False
Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2026-apr-00105 oaicicd-core-for-fhi72"
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2026-apr-00105 oaicicd-core-for-fhi72"
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2026-apr-00105 oaicicd-core-for-fhi72 %%log_dir%%"
oc-cn5g-00103-ho:
Host: groot
NetworkScript: echo "inet 172.21.6.111"
@@ -183,6 +191,16 @@ amarisoft_ue_2x2:
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_2x2/aw2s-multi-00102-2x2-v2.cfg &
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
NetworkScript: ip netns exec ue1 ip a show dev pdn0
amarisoft_00105_40MHz:
Host: amariue
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_fhi72_mplane_40MHz/multi-00105-40.cfg &
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
NetworkScript: ip netns exec ue1 ip a show dev pdn0
amarisoft_00105_100MHz:
Host: amariue
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_fhi72_mplane_100MHz/multi-00105-100.cfg &
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
NetworkScript: ip netns exec ue1 ip a show dev pdn0
amarisoft_ue_1:
Host: amariue
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}'

View File

@@ -648,7 +648,7 @@ class Containerize():
raise ValueError(f'Invalid value for num_attempts: {num_attempts}, must be greater than 0')
for attempt in range(num_attempts):
logging.info(f'will start services {services}')
status = ssh.run(f'docker compose -f {wd_yaml} up -d --wait --wait-timeout 60 -- {services}')
status = ssh.run(f'docker compose -f {wd_yaml} up -d --wait --wait-timeout 120 -- {services}')
info = ssh.run(f"docker compose -f {wd_yaml} ps --all --format=\'table {{{{.Service}}}} [{{{{.Image}}}}] {{{{.Status}}}}\' -- {services} | column -t")
deployed = status.returncode == 0
if not deployed:

View File

@@ -65,6 +65,23 @@ def Iperf_ComputeTime(args):
raise Exception('Iperf time not found!')
return int(result.group('iperf_time'))
def Iperf_UpdateBindPort(opts, ueIP, idx):
# search if bind address present. Extract if yes, add if no.
bind_m = re.search(r'(-B|--bind)\s+(?P<ip>\d+\.\d+\.\d+\.\d+)', opts)
if bind_m:
bindIP = bind_m.group('ip')
else:
bindIP = ueIP
opts += f" -B {ueIP}"
# search if port present. Extract if yes, add if no.
port_m = re.search(r'(-p|--port)\s+(?P<port>\d+)', opts)
if port_m:
port = port_m.group('port')
else:
port = 5002 + idx
opts += f" -p {port}"
return bindIP, port, opts
def convert_to_mbps(value, magnitude):
value = float(value)
if magnitude == 'K' or magnitude == 'k':
@@ -457,7 +474,6 @@ class OaiCiTest():
svrIP = cn.getIP()
if not svrIP:
return (False, f"Iperf server {cn.getName()} has no IP address")
iperf_opt = self.iperf_args
jsonReport = "--json"
serverReport = ""
@@ -471,11 +487,11 @@ class OaiCiTest():
# note: enable server report collection on the UE side, no need to store and collect server report separately on the server side
serverReport = "--get-server-output"
iperf_time = Iperf_ComputeTime(self.iperf_args)
bindIP, port, iperf_opt = Iperf_UpdateBindPort(iperf_opt, ueIP, idx)
# hack: the ADB UEs don't have iperf in $PATH, so we need to hardcode for the moment
iperf_ue = '/data/local/tmp/iperf3' if re.search('adb', ue.getName()) else 'iperf3'
ue_header = f'UE {ue.getName()} ({ueIP})'
ue_header = f'UE {ue.getName()} ({bindIP})'
with cls_cmd.getConnection(ue.getHost()) as cmd_ue, cls_cmd.getConnection(cn.getHost()) as cmd_svr:
port = 5002 + idx
# note: some core setups start an iperf3 server automatically, indicated in ci_infra by runIperf3Server: False`
t = iperf_time * 2.5
cmd_ue.run(f'rm {client_filename}', reportNonZero=False, silent=True)
@@ -486,7 +502,9 @@ class OaiCiTest():
if ret.returncode == 0:
logging.warning(f'Iperf3 server on port {port} detected and terminated')
cmd_svr.run(f'{cn.getCmdPrefix()} timeout -vk3 {t} iperf3 -s -B {svrIP} -p {port} -1 {jsonReport} >> /dev/null &', timeout=t)
cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -B {ueIP} -c {svrIP} -p {port} {iperf_opt} {jsonReport} {serverReport} -O 5 >> {client_filename}', timeout=t)
client_ret = cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -c {svrIP} {iperf_opt} {jsonReport} {serverReport} -O 5 >> {client_filename}', timeout=t, reportNonZero=False)
if client_ret.returncode != 0:
return (False, f'{ue_header}\nIperf client command failed on {bindIP} -> {svrIP}:{port} (return code: {client_ret.returncode})')
dest_filename = archiveArtifact(cmd_ue, ctx, client_filename)
if udpIperf:
status, msg = Iperf_analyzeV3UDP(dest_filename, self.iperf_bitrate_threshold, self.iperf_packetloss_threshold, target_bitrate)

View File

@@ -0,0 +1,262 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 05; mnc_length = 2; snssaiList = ( { sst = 1; }); });
nr_cellid = 1;
////////// Physical parameters:
pdsch_AntennaPorts_XP = 2;
pdsch_AntennaPorts_N1 = 2;
maxMIMO_layers = 4;
pusch_AntennaPorts = 4;
do_CSIRS = 1;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# center frequency = 3350.01 MHz
# selected SSB frequency = 3349.92 MHz
absoluteFrequencySSB = 623328;
dl_frequencyBand = 78;
# frequency point A = 3330.93 MHz
dl_absoluteFrequencyPointA = 622062;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 106;
#initialDownlinkBWP
#genericParameters
initialDLBWPlocationAndBandwidth = 28875; #38.101-1 Table 5.3.2-1
#
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 11;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 78;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 1;
ul_carrierBandwidth = 106;
pMax = 23;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 28875;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 152;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 0;
preambleReceivedTargetPower = -100;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 8;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 3;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
#one (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 1,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB
msg3_DeltaPreamble = 2;
p0_NominalWithGrant = -96;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 0;
p0_nominal = -96;
ssb_PositionsInBurst_Bitmap = 0x1;
# ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 2;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 1;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 1;
# pattern1
# dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 5;
nrofDownlinkSlots = 3;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 1;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -10;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "172.21.6.116"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.150";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.150";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 250;
pucch_TargetSNRx10 = 200;
pusch_FailureThres = 1000;
}
);
L1s = (
{
tr_n_preference = "local_mac";
prach_dtx_threshold = 100;
pucch0_dtx_threshold = 10;
pusch_dtx_threshold = 10;
max_ldpc_iterations = 15;
tx_amp_backoff_dB = 12; # needs to match O-RU configuration
L1_rx_thread_core = 3;
L1_tx_thread_core = 4;
phase_compensation = 0; # needs to match O-RU configuration
}
);
RUs = (
{
local_rf = "no";
nb_tx = 4;
nb_rx = 4;
att_tx = 24;
att_rx = 0;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
sf_extension = 0;
eNB_instances = [0];
ru_thread_core = 5;
sl_ahead = 10;
tr_preference = "raw_if4p5"; # important: activate FHI7.2
do_precoding = 0; # needs to match O-RU configuration
}
);
security = {
# preferred ciphering algorithms
# the first one of the list that an UE supports in chosen
# valid values: nea0, nea1, nea2, nea3
ciphering_algorithms = ( "nea0" );
# preferred integrity algorithms
# the first one of the list that an UE supports in chosen
# valid values: nia0, nia1, nia2, nia3
integrity_algorithms = ( "nia2", "nia0" );
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
drb_ciphering = "yes";
drb_integrity = "no";
};
log_config :
{
global_log_level = "info";
hw_log_level = "info";
phy_log_level = "info";
mac_log_level = "info";
rlc_log_level = "info";
pdcp_log_level = "info";
rrc_log_level = "info";
ngap_log_level = "info";
f1ap_log_level = "info";
};
fhi_72 = {
dpdk_devices = ("0000:c3:11.0"); # one VF can be used as well
system_core = 0;
io_core = 1;
worker_cores = (2);
du_key_pair = ("/opt/oai-gnb/etc/id_rsa.pub", "/opt/oai-gnb/etc/id_rsa");
du_addr = ("00:11:22:33:44:66");
vlan_tag = (3); # only one needed if one VF configured
ru_username = ("oranbenetel");
ru_ip_addr = ("192.168.81.4");
fh_config = ({
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
Ta4 = (0, 200);
});
};

View File

@@ -0,0 +1,260 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 05; mnc_length = 2; snssaiList = ( { sst = 1; }); });
nr_cellid = 1;
////////// Physical parameters:
pdsch_AntennaPorts_XP = 2;
pusch_AntennaPorts = 2;
do_CSIRS = 1;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# center frequency = 3350.01 MHz
# selected SSB frequency = 3349.92 MHz
absoluteFrequencySSB = 623328;
dl_frequencyBand = 78;
# frequency point A = 3300.87 MHz
dl_absoluteFrequencyPointA = 620058;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 273;
#initialDownlinkBWP
#genericParameters
initialDLBWPlocationAndBandwidth = 1099; #38.101-1 Table 5.3.2-1
#
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 11;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 78;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 1;
ul_carrierBandwidth = 273;
pMax = 23;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 1099;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 152;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 0;
preambleReceivedTargetPower = -100;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 8;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 3;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
#one (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 1,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB
msg3_DeltaPreamble = 2;
p0_NominalWithGrant = -96;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 0;
p0_nominal = -96;
ssb_PositionsInBurst_Bitmap = 0x1;
# ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 2;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 1;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 1;
# pattern1
# dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 5;
nrofDownlinkSlots = 3;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 1;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -11;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "172.21.6.116"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.150";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.150";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
pusch_FailureThres = 1000;
}
);
L1s = (
{
tr_n_preference = "local_mac";
prach_dtx_threshold = 100;
pucch0_dtx_threshold = 10;
pusch_dtx_threshold = 10;
max_ldpc_iterations = 15;
tx_amp_backoff_dB = 12; # needs to match O-RU configuration
L1_rx_thread_core = 3;
L1_tx_thread_core = 4;
phase_compensation = 0; # needs to match O-RU configuration
}
);
RUs = (
{
local_rf = "no";
nb_tx = 2;
nb_rx = 2;
att_tx = 24;
att_rx = 0;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
sf_extension = 0;
eNB_instances = [0];
ru_thread_core = 5;
sl_ahead = 10;
tr_preference = "raw_if4p5"; # important: activate FHI7.2
do_precoding = 0; # needs to match O-RU configuration
}
);
security = {
# preferred ciphering algorithms
# the first one of the list that an UE supports in chosen
# valid values: nea0, nea1, nea2, nea3
ciphering_algorithms = ( "nea0" );
# preferred integrity algorithms
# the first one of the list that an UE supports in chosen
# valid values: nia0, nia1, nia2, nia3
integrity_algorithms = ( "nia2", "nia0" );
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
drb_ciphering = "yes";
drb_integrity = "no";
};
log_config :
{
global_log_level = "info";
hw_log_level = "info";
phy_log_level = "info";
mac_log_level = "info";
rlc_log_level = "info";
pdcp_log_level = "info";
rrc_log_level = "info";
ngap_log_level = "info";
f1ap_log_level = "info";
};
fhi_72 = {
dpdk_devices = ("0000:c3:11.0"); # one VF can be used as well
system_core = 0;
io_core = 1;
worker_cores = (2);
du_key_pair = ("/opt/oai-gnb/etc/id_rsa.pub", "/opt/oai-gnb/etc/id_rsa");
du_addr = ("00:11:22:33:44:66");
vlan_tag = (3); # only one needed if one VF configured
ru_username = ("oranbenetel");
ru_ip_addr = ("192.168.81.4");
fh_config = ({
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
Ta4 = (0, 200);
});
};

View File

@@ -5,8 +5,8 @@ uicc0 = {
key = "fec86ba6eb707ed08905757b1bb44b8f";
opc= "C42449363BBAD02B66D16BC975D77CC1";
pdu_sessions = (
{ id = 1; dnn = "oai"; nssai_sst = 1; },
{ id = 2; dnn = "oai"; nssai_sst = 1; }
{ id = 1; dnn = "oai"; nssai_sst = 1; nssai_sd = 0xFFFFFF; },
{ id = 2; dnn = "openairinterface"; nssai_sst = 1; nssai_sd = 0x123456; }
)
}

View File

@@ -21,4 +21,4 @@ WORKDIR /oai-ran
COPY . .
WORKDIR /oai-ran/build
RUN cmake -GNinja -DENABLE_TESTS=ON -DOAI_ZMQ=ON -DCMAKE_BUILD_TYPE=Debug -DSANITIZE_ADDRESS=True .. && ninja tests
RUN cmake -GNinja -DENABLE_TESTS=ON -DOAI_ZMQ=ON -DCMAKE_BUILD_TYPE=Debug -DSANITIZE_ADDRESS=True .. && ninja

View File

@@ -58,11 +58,13 @@ done
# Merged commits
# ----------------------------
mergeCommits=$(git rev-list --merges --abbrev-commit "$TARGET_BRANCH".."$SOURCE_BRANCH")
if [[ -n "$mergeCommits" ]]; then
message="> ERROR: Following merge commits are found in the source branch history. Please rebase your branch.\n>\n"
message+="> $(echo "$mergeCommits" | paste -sd ',' -)\n"
echo -e "$message"
exit 3
if [[ ! "$SOURCE_BRANCH" =~ ^(origin/)?integration_[0-9]{4}_w[0-9]{2}$ ]]; then
if [[ -n "$mergeCommits" ]]; then
message="> ERROR: Following merge commits are found in the source branch history. Please rebase your branch.\n>\n"
message+="> $(echo "$mergeCommits" | paste -sd ',' -)\n"
echo -e "$message"
exit 3
fi
fi
# ----------------------------

View File

@@ -82,5 +82,17 @@ class TestPingIperf(unittest.TestCase):
success = self.ci.Iperf(self.ctx, self.node, self.html, infra_file=infra_file)
self.assertTrue(success)
def test_iperf_new_bindport(self):
self.ci.iperf_args = "-u -t 5 -b 22M -O 0 -p 10000 -B 127.0.0.3"
self.ci.svr_id = "test"
self.ci.svr_node = "localhost"
self.ci.iperf_packetloss_threshold = "0"
self.ci.iperf_bitrate_threshold = "0"
self.ci.iperf_profile = "balanced"
infra_file = "tests/config/infra_ping_iperf.yaml"
# TODO Should need nothing but options and UE(s) to use
success = self.ci.Iperf(self.ctx, self.node, self.html, infra_file=infra_file)
self.assertTrue(success)
if __name__ == '__main__':
unittest.main()

View File

@@ -41,6 +41,17 @@
<node>localhost</node>
</testCase>
<testCase>
<class>Ping</class>
<desc>UL ping ext-dn from NR-UE</desc>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<ping_args>-c 20 -i0.5</ping_args>
<ping_packetloss_threshold>80</ping_packetloss_threshold>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping NR-UE from ext-dn</desc>

View File

@@ -23,7 +23,7 @@
<desc>Deploy OAI 5G CoreNetwork</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
<services>mysql oai-amf oai-smf oai-upf oai-ext-dn</services>
<services>mysql oai-amf oai-smf oai-pcf oai-upf oai-ext-dn</services>
</testCase>
<testCase>
@@ -41,28 +41,6 @@
<node>localhost</node>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping ext-dn from NR-UE</desc>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping NR-UE from ext-dn</desc>
<id>rfsim5g_ext_dn</id>
<node>localhost</node>
<svr_id>rfsim5g_ue</svr_id>
<svr_node>localhost</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase>
<class>Attach_UE</class>
<desc>Verify 2nd PDU session is up</desc>
@@ -71,14 +49,109 @@
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping ext-dn from NR-UE on PDU session ID 2</desc>
<class>Custom_Command</class>
<desc>Configure policy routing for PDU2 source IP</desc>
<may_fail>true</may_fail>
<node>localhost</node>
<command>docker exec rfsim5g-oai-nr-ue sh -c "ip rule add from 12.1.2.2/32 table 1002 prio 1002; ip route replace default dev oaitun_ue1p2 src 12.1.2.2 table 1002"</command>
</testCase>
<testCase>
<class>Custom_Command</class>
<desc>Ping ext-dn from UE PDU session 1 interface</desc>
<node>localhost</node>
<command>docker exec rfsim5g-oai-nr-ue ping -I oaitun_ue1 -c 10 192.168.72.135</command>
</testCase>
<testCase>
<class>Custom_Command</class>
<desc>Ping ext-dn from UE PDU session 2 interface</desc>
<node>localhost</node>
<command>docker exec rfsim5g-oai-nr-ue ping -I oaitun_ue1p2 -c 10 192.168.72.135</command>
</testCase>
<testCase>
<class>Iperf</class>
<desc>Iperf (UL/1Mbps/UDP)(6 sec) QFI 1 (default) flow on PDU session 1 (port 5201)</desc>
<iperf_args>-u -b 1M -t 6 -B 12.1.1.2 -p 5201</iperf_args>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>10</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>Iperf (UL/1Mbps/UDP)(6 sec) QFI 2 flow on PDU session 1 (port 52080)</desc>
<iperf_args>-u -b 1M -t 6 -B 12.1.1.2 -p 52080</iperf_args>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>10</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>Iperf (UL/1Mbps/UDP)(6 sec) QFI 3 flow on PDU session 1 (port 52081)</desc>
<iperf_args>-u -b 1M -t 6 -B 12.1.1.2 -p 52081</iperf_args>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>10</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>Iperf (UL/1Mbps/UDP)(6 sec) default flow on PDU session 2 (port 5201)</desc>
<iperf_args>-u -b 1M -t 6 -B 12.1.2.2 -p 5201</iperf_args>
<id>rfsim5g_ue_pdu_2</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>10</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>Iperf (DL/1Mbps/UDP)(6 sec) QFI 1 (default) flow on PDU session 1 (port 5201)</desc>
<iperf_args>-u -b 1M -t 6 -R -B 12.1.1.2 -p 5201</iperf_args>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>10</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>Iperf (DL/1Mbps/UDP)(6 sec) QFI 2 flow on PDU session 1 (port 52080)</desc>
<iperf_args>-u -b 1M -t 6 -R -B 12.1.1.2 -p 52080</iperf_args>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>10</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>Iperf (DL/1Mbps/UDP)(6 sec) QFI 3 flow on PDU session 1 (port 52081)</desc>
<iperf_args>-u -b 1M -t 6 -R -B 12.1.1.2 -p 52081</iperf_args>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>10</iperf_bitrate_threshold>
</testCase>
<testCase>

View File

@@ -0,0 +1,149 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>test-5g-fhi72-benetel-2x2-100MHz-9b-mplane</htmlTabRef>
<htmlTabName>100 MHz 2x2 9b TDD SA Benetel M-plane</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<testCase>
<class>DeployCoreNetwork</class>
<desc>Initialize 5G Core</desc>
<cn_id>oc-cn5g-00105</cn_id>
</testCase>
<testCase>
<class>Custom_Script</class>
<desc>Configure system for low-latency RT performance</desc>
<node>cacofonix</node>
<script>yaml_files/sa_fhi_7.2_benetel550_2x2_100MHz_9b_mplane_gnb/setup_config.sh</script>
</testCase>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>Initialize_UE</class>
<desc>Initialize Amarisoft UE</desc>
<id>amarisoft_00105_100MHz</id>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace for server 0</desc>
<node>cacofonix</node>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy gNB (TDD/Band78/100MHz/Benetel) in a container</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_benetel550_2x2_100MHz_9b_mplane_gnb</yaml_path>
</testCase>
<testCase>
<class>Attach_UE</class>
<desc>Attach UE</desc>
<id>amarisoft_ue_1</id>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping: 100 pings in 10 sec</desc>
<id>amarisoft_ue_1</id>
<svr_id>oc-cn5g-00105</svr_id>
<ping_args>-c 100 -i 0.1</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_rttavg_threshold>15</ping_rttavg_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/250Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 250M -t 30 -R</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/35Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 35M -t 30</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/TCP)(30 sec)</desc>
<iperf_args>-t 30 -R</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_tcp_rate_target>40</iperf_tcp_rate_target>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/TCP)(30 sec)</desc>
<iperf_args>-t 30</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_tcp_rate_target>10</iperf_tcp_rate_target>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Detach_UE</class>
<always_exec>true</always_exec>
<desc>Detach UE</desc>
<id>amarisoft_ue_1</id>
</testCase>
<testCase>
<class>Terminate_UE</class>
<always_exec>true</always_exec>
<desc>Terminate UE</desc>
<id>amarisoft_00105_100MHz</id>
</testCase>
<testCase>
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy gNB</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_benetel550_2x2_100MHz_9b_mplane_gnb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>UndeployCoreNetwork</class>
<always_exec>true</always_exec>
<desc>Terminate 5G Core</desc>
<cn_id>oc-cn5g-00105</cn_id>
</testCase>
</testCaseList>

View File

@@ -0,0 +1,149 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>test-5g-fhi72-benetel-40Mhz-4x4-9b-mplane</htmlTabRef>
<htmlTabName>40MHz 4x4 9b TDD SA Benetel M-plane</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<testCase>
<class>DeployCoreNetwork</class>
<desc>Initialize 5G Core</desc>
<cn_id>oc-cn5g-00105</cn_id>
</testCase>
<testCase>
<class>Custom_Script</class>
<desc>Configure system for low-latency RT performance</desc>
<node>cacofonix</node>
<script>yaml_files/sa_fhi_7.2_benetel550_4x4_40MHz_9b_mplane_gnb/setup_config.sh</script>
</testCase>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>Initialize_UE</class>
<desc>Initialize Amarisoft UE</desc>
<id>amarisoft_00105_40MHz</id>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace for server 0</desc>
<node>cacofonix</node>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy gNB (TDD/Band78/100MHz/Benetel) in a container</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_benetel550_4x4_40MHz_9b_mplane_gnb</yaml_path>
</testCase>
<testCase>
<class>Attach_UE</class>
<desc>Attach UE</desc>
<id>amarisoft_ue_1</id>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping: 100 pings in 10 sec</desc>
<id>amarisoft_ue_1</id>
<svr_id>oc-cn5g-00105</svr_id>
<ping_args>-c 100 -i 0.1</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_rttavg_threshold>15</ping_rttavg_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/130Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 130M -t 30 -R</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/15Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 15M -t 30</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/TCP)(30 sec)</desc>
<iperf_args>-t 30 -R</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_tcp_rate_target>40</iperf_tcp_rate_target>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/TCP)(30 sec)</desc>
<iperf_args>-t 30</iperf_args>
<id>amarisoft_ue_1</id>
<iperf_tcp_rate_target>10</iperf_tcp_rate_target>
<svr_id>oc-cn5g-00105</svr_id>
</testCase>
<testCase>
<class>Detach_UE</class>
<always_exec>true</always_exec>
<desc>Detach UE</desc>
<id>amarisoft_ue_1</id>
</testCase>
<testCase>
<class>Terminate_UE</class>
<always_exec>true</always_exec>
<desc>Terminate UE</desc>
<id>amarisoft_00105_40MHz</id>
</testCase>
<testCase>
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy gNB</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_benetel550_4x4_40MHz_9b_mplane_gnb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>UndeployCoreNetwork</class>
<desc>Terminate 5G Core</desc>
<always_exec>true</always_exec>
<cn_id>oc-cn5g-00105</cn_id>
</testCase>
</testCaseList>

View File

@@ -43,6 +43,12 @@ nfs:
n4:
interface_name: eth0
port: 8805
pcf:
host: oai-pcf
sbi:
port: 8080
api_version: v1
interface_name: eth0
upf:
host: oai-upf
@@ -77,6 +83,10 @@ database:
snssais:
- &embb_slice1
sst: 1
sd: "FFFFFF"
- &embb_slice2
sst: 1
sd: "123456"
############## NF-specific configuration
amf:
@@ -103,6 +113,7 @@ amf:
tac: 0x0001
nssai:
- *embb_slice1
- *embb_slice2
supported_integrity_algorithms:
- "NIA0"
- "NIA1"
@@ -116,7 +127,7 @@ smf:
ue_mtu: 1500
support_features:
use_local_subscription_info: yes # Use infos from local_subscription_info or from UDM
use_local_pcc_rules: yes # Use infos from local_pcc_rules or from PCF
use_local_pcc_rules: no # Enforce PCC rules from PCF
upfs:
- host: oai-upf
port: 8805
@@ -144,6 +155,9 @@ smf:
- sNssai: *embb_slice1
dnnSmfInfoList:
- dnn: "oai"
- sNssai: *embb_slice2
dnnSmfInfoList:
- dnn: "openairinterface"
local_subscription_infos:
- single_nssai: *embb_slice1
dnn: "oai"
@@ -151,6 +165,19 @@ smf:
5qi: 9
session_ambr_ul: "200Mbps"
session_ambr_dl: "400Mbps"
- single_nssai: *embb_slice2
dnn: "openairinterface"
qos_profile:
5qi: 9
session_ambr_ul: "200Mbps"
session_ambr_dl: "400Mbps"
pcf:
local_policy:
policy_decisions_path: /openair-pcf/policies/policy_decisions
pcc_rules_path: /openair-pcf/policies/pcc_rules
traffic_rules_path: /openair-pcf/policies/traffic_rules
qos_data_path: /openair-pcf/policies/qos_data
upf:
support_features:
@@ -162,9 +189,15 @@ upf:
- sNssai: *embb_slice1
dnnUpfInfoList:
- dnn: "oai"
- sNssai: *embb_slice2
dnnUpfInfoList:
- dnn: "openairinterface"
## DNN configuration
dnns:
- dnn: "oai"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.1.0/24"
- dnn: "openairinterface"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.2.0/24"

View File

@@ -45,9 +45,26 @@ services:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
depends_on:
- oai-amf
- oai-pcf
networks:
public_net:
ipv4_address: 192.168.71.133
oai-pcf:
container_name: "rfsim5g-oai-pcf"
image: oaisoftwarealliance/oai-pcf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-pcf/etc/config.yaml
- ./policies/policy_decisions:/openair-pcf/policies/policy_decisions
- ./policies/pcc_rules:/openair-pcf/policies/pcc_rules
- ./policies/traffic_rules:/openair-pcf/policies/traffic_rules
- ./policies/qos_data:/openair-pcf/policies/qos_data
depends_on:
- oai-amf
networks:
public_net:
ipv4_address: 192.168.71.142
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.2.1
@@ -78,7 +95,8 @@ services:
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0;"\
"ip route add 12.1.2.0/24 via 192.168.72.134 dev eth0; sleep infinity"
depends_on:
- oai-upf
networks:

View File

@@ -0,0 +1,29 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
gbr-rule-default-3mbps:
flowInfos:
- flowDescription: permit out ip from any to assigned
packetFilterUsage: true
precedence: 10
refQosData:
- gbr-qos-default-3mbps
gbr-rule-52080:
flowInfos:
- flowDescription: permit out ip from any to assigned 52080
packetFilterUsage: true
- flowDescription: permit in ip from assigned 52080 to any
packetFilterUsage: true
precedence: 7
refQosData:
- gbr-qos-52080-20mbps
gbr-rule-52081:
flowInfos:
- flowDescription: permit out ip from any to assigned 52081
packetFilterUsage: true
- flowDescription: permit in ip from assigned 52081 to any
packetFilterUsage: true
precedence: 8
refQosData:
- gbr-qos-52081-10mbps

View File

@@ -0,0 +1,35 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
decision_default:
default: true
pcc_rules:
- gbr-rule-default-3mbps
decision_dnn_oai:
dnn: oai
pcc_rules:
- gbr-rule-default-3mbps
- gbr-rule-52080
- gbr-rule-52081
decision_dnn_openairinterface:
dnn: openairinterface
pcc_rules:
- gbr-rule-default-3mbps
decision_supi2:
pcc_rules:
- gbr-rule-default-3mbps
supi_imsi: 001010000059450
decision_supi3:
pcc_rules:
- gbr-rule-default-3mbps
supi_imsi: 001010000059451
decision_supi4:
pcc_rules:
- gbr-rule-default-3mbps
supi_imsi: 001010000059452
decision_supi5:
pcc_rules:
- gbr-rule-default-3mbps
supi_imsi: 001010000059453

View File

@@ -0,0 +1,37 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
gbr-qos-default-3mbps:
5qi: 9
maxbrUl: 1000 Mbps
maxbrDl: 1000 Mbps
gbrUl: 3 Mbps
gbrDl: 3 Mbps
arp:
priorityLevel: 8
preemptCap: NOT_PREEMPT
preemptVuln: NOT_PREEMPTABLE
priorityLevel: 50
gbr-qos-52080-20mbps:
5qi: 67
maxbrUl: 1000 Mbps
maxbrDl: 1000 Mbps
gbrUl: 20 Mbps
gbrDl: 20 Mbps
arp:
priorityLevel: 8
preemptCap: NOT_PREEMPT
preemptVuln: NOT_PREEMPTABLE
priorityLevel: 30
gbr-qos-52081-10mbps:
5qi: 69
maxbrUl: 1000 Mbps
maxbrDl: 1000 Mbps
gbrUl: 10 Mbps
gbrDl: 10 Mbps
arp:
priorityLevel: 8
preemptCap: NOT_PREEMPT
preemptVuln: NOT_PREEMPTABLE
priorityLevel: 40

View File

@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
image: mysql:8.0
image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oaisoftwarealliance/oai-amf:v2.1.10
image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oaisoftwarealliance/oai-smf:v2.1.10
image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.1.10
image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
image: oaisoftwarealliance/trf-gen-cn5g:focal
image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\

View File

@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
image: mysql:8.0
image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oaisoftwarealliance/oai-amf:v2.1.10
image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oaisoftwarealliance/oai-smf:v2.1.10
image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.1.10
image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
image: oaisoftwarealliance/trf-gen-cn5g:focal
image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\

View File

@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
image: mysql:8.0
image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oaisoftwarealliance/oai-amf:v2.1.10
image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oaisoftwarealliance/oai-smf:v2.1.10
image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.1.10
image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
image: oaisoftwarealliance/trf-gen-cn5g:focal
image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\

View File

@@ -0,0 +1,42 @@
# SPDX-License-Identifier: MIT
services:
dpdk-init:
image: docker.io/library/oai-dpdk-init:latest
network_mode: host
container_name: dpdk-init
entrypoint: "/tmp/setup_sriov.sh"
privileged: true
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ./setup_sriov_benetel.sh:/tmp/setup_sriov.sh
- /lib/modules:/lib/modules
- /usr/lib/modules:/usr/lib/modules
oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop}
privileged: true
network_mode: "host"
container_name: oai-gnb
environment:
TZ: Europe/Paris
USE_ADDITIONAL_OPTIONS: --thread-pool 7,8,9,10,11,12 --device.name oran_fhlib_5g_mplane --log_config.global_log_options level,nocolor,time,line_num,function
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ../../conf_files/gnb.sa.band78.273prb.fhi72.2x2-benetel550-9b-mplane.conf:/opt/oai-gnb/etc/gnb.conf
- /dev/hugepages:/dev/hugepages
- /home/oaicicd/.ssh/id_rsa.pub:/opt/oai-gnb/etc/id_rsa.pub
- /home/oaicicd/.ssh/id_rsa:/opt/oai-gnb/etc/id_rsa
# Please change these values based on your system
cpuset: "0-12"
depends_on:
dpdk-init:
condition: service_completed_successfully
healthcheck:
test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh"
start_period: 60s
start_interval: 500ms
interval: 5s
timeout: 5s
retries: 10

View File

@@ -0,0 +1,7 @@
# SPDX-License-Identifier: MIT
set -e
sudo cpupower idle-set -E > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=950000
sudo sysctl kernel.timer_migration=1
exit 0

View File

@@ -0,0 +1,6 @@
# SPDX-License-Identifier: MIT
set -e
sudo cpupower idle-set -D 0 > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=-1
sudo sysctl kernel.timer_migration=0

View File

@@ -0,0 +1,39 @@
#!/bin/sh
# SPDX-License-Identifier: MIT
set -eu
pci_addr()
{
PF_IF=$1
VF_INDEX=$2
SYSFS_PATH="/sys/class/net/${PF_IF}/device/virtfn${VF_INDEX}"
if [ ! -e "$SYSFS_PATH" ]; then
echo "VF $VF_INDEX not found for interface $PF_IF"
exit 1
fi
PCI_ADDR=$(basename "$(readlink "$SYSFS_PATH")")
echo "$PCI_ADDR"
}
IF_NAME=ens7f1
## O-DU C Plane MAC ADDR and VLAN
C_U_PLANE_MAC_ADD=00:11:22:33:44:66
C_U_PLANE_VLAN=3
MTU=9000
DPDK_DEVBIND_PREFIX=/usr/local/bin
NUM_VFs=1
ethtool -G $IF_NAME rx 8160 tx 8160
sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs"
sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs"
C_U_PLANE_PCI=$(pci_addr $IF_NAME 0)
# this next 2 lines is for C/U planes
ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU
sleep 1
modprobe iavf
${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI
modprobe vfio-pci
${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI
echo "Successfully configured C-PLANE and U-PLANE:
- C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI"
exit 0

View File

@@ -0,0 +1,42 @@
# SPDX-License-Identifier: MIT
services:
dpdk-init:
image: docker.io/library/oai-dpdk-init:latest
network_mode: host
container_name: dpdk-init
entrypoint: "/tmp/setup_sriov.sh"
privileged: true
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ./setup_sriov_benetel.sh:/tmp/setup_sriov.sh
- /lib/modules:/lib/modules
- /usr/lib/modules:/usr/lib/modules
oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop}
privileged: true
network_mode: "host"
container_name: oai-gnb
environment:
TZ: Europe/Paris
USE_ADDITIONAL_OPTIONS: --thread-pool 7,8,9,10,11,12 --device.name oran_fhlib_5g_mplane --log_config.global_log_options level,nocolor,time,line_num,function
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ../../conf_files/gnb.sa.band78.106prb.fhi72.4x4-benetel550-9b-mplane.conf:/opt/oai-gnb/etc/gnb.conf
- /dev/hugepages:/dev/hugepages
- /home/oaicicd/.ssh/id_rsa.pub:/opt/oai-gnb/etc/id_rsa.pub
- /home/oaicicd/.ssh/id_rsa:/opt/oai-gnb/etc/id_rsa
# Please change these values based on your system
cpuset: "0-12"
depends_on:
dpdk-init:
condition: service_completed_successfully
healthcheck:
test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh"
start_period: 60s
start_interval: 500ms
interval: 5s
timeout: 5s
retries: 10

View File

@@ -0,0 +1,7 @@
# SPDX-License-Identifier: MIT
set -e
sudo cpupower idle-set -E > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=950000
sudo sysctl kernel.timer_migration=1
exit 0

View File

@@ -0,0 +1,6 @@
# SPDX-License-Identifier: MIT
set -e
sudo cpupower idle-set -D 0 > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=-1
sudo sysctl kernel.timer_migration=0

View File

@@ -0,0 +1,39 @@
#!/bin/sh
# SPDX-License-Identifier: MIT
set -eu
pci_addr()
{
PF_IF=$1
VF_INDEX=$2
SYSFS_PATH="/sys/class/net/${PF_IF}/device/virtfn${VF_INDEX}"
if [ ! -e "$SYSFS_PATH" ]; then
echo "VF $VF_INDEX not found for interface $PF_IF"
exit 1
fi
PCI_ADDR=$(basename "$(readlink "$SYSFS_PATH")")
echo "$PCI_ADDR"
}
IF_NAME=ens7f1
## O-DU C Plane MAC ADDR and VLAN
C_U_PLANE_MAC_ADD=00:11:22:33:44:66
C_U_PLANE_VLAN=3
MTU=9000
DPDK_DEVBIND_PREFIX=/usr/local/bin
NUM_VFs=1
ethtool -G $IF_NAME rx 8160 tx 8160
sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs"
sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs"
C_U_PLANE_PCI=$(pci_addr $IF_NAME 0)
# this next 2 lines is for C/U planes
ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU
sleep 1
modprobe iavf
${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI
modprobe vfio-pci
${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI
echo "Successfully configured C-PLANE and U-PLANE:
- C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI"
exit 0

View File

@@ -36,25 +36,23 @@ typedef enum {
typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t;
/* QoS Priority Level */
typedef enum {
QOS_PRIORITY_SPARE = 0,
QOS_PRIORITY_HIGHEST,
QOS_PRIORITY_2,
QOS_PRIORITY_3,
QOS_PRIORITY_4,
QOS_PRIORITY_5,
QOS_PRIORITY_6,
QOS_PRIORITY_7,
QOS_PRIORITY_8,
QOS_PRIORITY_9,
QOS_PRIORITY_10,
QOS_PRIORITY_11,
QOS_PRIORITY_12,
QOS_PRIORITY_13,
QOS_PRIORITY_LOWEST,
QOS_NO_PRIORITY
} qos_priority_t;
/* 5QI (5G QoS Identifier) - 3GPP TS 23.501 §5.7.2.1
* Range: 0..255
* - Standardized 5QI values: have one-to-one mapping to standardized 5G QoS characteristics (Table 5.7.4-1)
* - Pre-configured 5QI values: pre-configured in the AN
* - Dynamically assigned 5QI values: require signaling of QoS characteristics as part of QoS profile */
#define MIN_FIVEQI 0
#define MAX_STANDARDIZED_FIVEQI 90
#define MAX_FIVEQI 255
/* ARP Priority Level - 3GPP TS 23.501 §5.7.2.2
* The ARP priority level defines the relative importance of a QoS Flow.
* Range: 1 to 15, with 1 as the highest priority.
* ARP priority levels 1-8: authorized by serving network (prioritized treatment)
* ARP priority levels 9-15: authorized by home network (roaming scenarios) */
typedef uint8_t qos_arp_priority_level_t;
#define MIN_QOS_ARP_PRIORITY_LEVEL 1 // highest priority
#define MAX_QOS_ARP_PRIORITY_LEVEL 15 // lowest priority
/* Pre-emption Capability */
typedef enum {
@@ -70,19 +68,101 @@ typedef enum {
PEV_MAX,
} qos_pev_t;
/* Allocation Retention Priority */
/* Allocation and Retention Priority (ARP) - 3GPP TS 23.501 §5.7.2.2
* Contains information about priority level, pre-emption capability and vulnerability.
* Used for admission control of GBR traffic and pre-emption decisions. */
typedef struct {
qos_priority_t priority_level;
// ARP priority level (1-15, 1 = highest)
qos_arp_priority_level_t priority_level;
qos_pec_t pre_emp_capability;
qos_pev_t pre_emp_vulnerability;
} qos_arp_t;
/* QoS Priority Level - 3GPP TS 23.501 §5.7.3.3
* The Priority Level associated with 5G QoS characteristics indicates a priority
* in scheduling resources among QoS Flows. The lowest Priority Level value
* corresponds to the highest priority.
* Range: 1 to 127, with 1 as the highest priority and 127 as the lowest priority.
* Used for scheduling resources among QoS Flows (different from ARP priority level
* which is used for admission control/preemption).
* Every standardized 5QI is associated with a default Priority Level value. */
typedef uint8_t qos_priority_level_t;
#define MIN_QOS_PRIORITY_LEVEL 1 // highest priority
#define MAX_QOS_PRIORITY_LEVEL 127 // lowest priority
/* Packet Delay Budget (PDB) - 3GPP TS 23.501 §5.7.3.4
* Upper bound for packet delay between UE and UPF N6 termination point (0..1023 ms).
* Used for scheduling and link layer configuration (e.g. HARQ target operating points).
* For Delay-critical GBR flows, packets delayed more than PDB are counted as lost. */
#define MIN_PACKET_DELAY_BUDGET 0
#define MAX_PACKET_DELAY_BUDGET 1023
/* Packet Error Rate (PER) - 3GPP TS 23.501 §5.7.3.5
* Upper bound for rate of non-congestion related packet losses (0..9 for scalar/exponent).
* Used for link layer protocol configuration (e.g. RLC, HARQ).
* PER = Scalar * 10^(-Exponent) */
#define MIN_PACKET_ERROR_RATE_SCALAR 0
#define MAX_PACKET_ERROR_RATE_SCALAR 9
#define MIN_PACKET_ERROR_RATE_EXPONENT 0
#define MAX_PACKET_ERROR_RATE_EXPONENT 9
typedef struct {
// Packet Error Rate Scalar (0..9)
uint8_t scalar;
// Packet Error Rate Exponent (0..9)
uint8_t exponent;
} qos_per_t;
/** QoS Characteristics for a standardized or
* pre-configured 5QI for downlink and uplink*/
typedef struct {
uint16_t fiveQI;
qos_priority_level_t *qos_priority;
} non_dynamic_5qi_t;
/** QoS Characteristics for a Non-standardised or
* not pre-configured 5QI for downlink and uplink. */
typedef struct {
uint16_t *fiveQI;
qos_priority_level_t qos_priority;
// Packet Delay Budget (0..1023 ms)
int packet_delay_budget;
// Packet Error Rate (0..9 for scalar/exponent)
qos_per_t per;
} dynamic_5qi_t;
/* Bit Rate (kbps) - 3GPP TS 38.413 */
typedef struct qos_bitrate_s {
// Guaranteed Flow Bit Rate (GFBR) (kbps)
uint64_t guaranteedFlowBitRate;
// Maximum Flow Bit Rate (MFBR) (kbps)
uint64_t maximumFlowBitRate;
} qos_bitrate_t;
/* GBR QoS Flow Information - 3GPP TS 23.501 §5.7.1.2, TS 38.413 §9.3.1.19
* Present only for GBR QoS flows (5QI < 5 for NonDynamic5QI, or Dynamic5QI with GBR).
* For GBR QoS Flow only, the QoS profile SHALL include for DL and UL:
* - Guaranteed Flow Bit Rate (GFBR)
* - Maximum Flow Bit Rate (MFBR) */
typedef struct gbr_qos_flow_information_s {
// Downlink bit rates (kbps)
qos_bitrate_t dl;
// Uplink bit rates (kbps)
qos_bitrate_t ul;
} gbr_qos_flow_information_t;
typedef struct pdusession_level_qos_parameter_s {
uint8_t qfi;
uint64_t fiveQI;
uint64_t qos_priority;
// QoS Characteristics
fiveQI_t fiveQI_type;
union {
non_dynamic_5qi_t non_dynamic;
dynamic_5qi_t dynamic;
} qos_characteristics;
// NG-RAN Allocation and Retention Priority
qos_arp_t arp;
/* GBR QoS Flow Information (optional - only for GBR flows) */
gbr_qos_flow_information_t *gbr_qos_flow_information;
} pdusession_level_qos_parameter_t;
#endif

View File

@@ -126,37 +126,97 @@ int config_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, pa
}
const int ret = cfg->getlist(cfg, ParamList, params, numparams, prefix);
if (ret >= 0 && params) {
char *newprefix;
if (prefix) {
int rc = asprintf(&newprefix, "%s.%s", prefix, ParamList->listname);
if (rc < 0) newprefix = NULL;
} else {
newprefix = ParamList->listname;
}
char cfgpath[MAX_OPTNAME_SIZE*2 + 6]; /* prefix.listname.[listindex] */
for (int i = 0; i < ParamList->numelt; ++i) {
// TODO config_process_cmdline?
sprintf(cfgpath, "%s.[%i]", newprefix, i);
config_process_cmdline(cfg, ParamList->paramarray[i], numparams, cfgpath);
if (cfg->rtflags & CONFIG_SAVERUNCFG) {
cfg->set(ParamList->paramarray[i], numparams, cfgpath);
}
config_execcheck(cfg, ParamList->paramarray[i], numparams, cfgpath);
}
if (prefix)
free(newprefix);
/* build newprefix OUTSIDE the params check so we can use it below too */
char *newprefix = NULL;
if (prefix) {
int rc = asprintf(&newprefix, "%s.%s", prefix, ParamList->listname);
if (rc < 0)
newprefix = NULL;
} else {
newprefix = ParamList->listname;
}
return ret;
char cfgpath[MAX_OPTNAME_SIZE * 2 + 6]; /* prefix.listname.[listindex] */
if (ret >= 0 && params) {
for (int i = 0; i < ParamList->numelt; ++i) {
sprintf(cfgpath, "%s.[%i]", newprefix, i);
config_process_cmdline(cfg, ParamList->paramarray[i], numparams, cfgpath);
if (cfg->rtflags & CONFIG_SAVERUNCFG)
cfg->set(ParamList->paramarray[i], numparams, cfgpath);
config_execcheck(cfg, ParamList->paramarray[i], numparams, cfgpath);
}
}
if (params && newprefix && (ret >= 0 || ParamList->numelt == 0)) {
sprintf(cfgpath, "%s", newprefix);
char searchstr[MAX_OPTNAME_SIZE * 2 + 10];
snprintf(searchstr, sizeof(searchstr), "--%s.", cfgpath);
char *endptr;
int valid_idx = ParamList->numelt;
for (int i = 1; i < cfg->argc; i++) {
char *res = strstr(cfg->argv[i], searchstr);
if (res != NULL) {
char *bracket = strchr(res + strlen(searchstr), '[');
bracket++;
long num = strtol(bracket, &endptr, 10);
if (num < valid_idx)
continue;
if (valid_idx == num) {
valid_idx++;
} else if (num > valid_idx) {
LOG_E(HW, "Out of Order Element Creation\n index: %s, valid_idx: %d, num: %ld\n", cfg->argv[i], valid_idx, num);
return -1;
} else {
LOG_E(HW, "[CONFIG] Invalid Configuration\n index: %s, valid_idx: %d, num: %ld\n", cfg->argv[i], valid_idx, num);
return -1;
}
}
}
while (ParamList->numelt < valid_idx) {
int new_idx = ParamList->numelt;
sprintf(cfgpath, "%s.[%i]", newprefix, new_idx);
paramdef_t **old = ParamList->paramarray;
ParamList->paramarray = config_allocate_new(cfg, (new_idx + 1) * sizeof(paramdef_t *), true);
memcpy(ParamList->paramarray, old, new_idx * sizeof(paramdef_t *));
ParamList->paramarray[new_idx] = config_allocate_new(cfg, numparams * sizeof(paramdef_t), true);
memcpy(ParamList->paramarray[new_idx], params, sizeof(paramdef_t) * numparams);
for (int p = 0; p < numparams; p++) {
ParamList->paramarray[new_idx][p].voidptr = NULL;
}
ParamList->numelt++;
fprintf(stderr, "[CONFIG] Created new array parameter %s.[%d]\n", newprefix, new_idx);
config_process_cmdline(cfg, ParamList->paramarray[new_idx], numparams, cfgpath);
for (int p = 0; p < numparams; p++) {
paramdef_t *pd = &ParamList->paramarray[new_idx][p];
if (pd->paramflags & PARAMFLAG_PARAMSET)
continue;
config_common_getdefault(cfg, pd, cfgpath);
}
config_execcheck(cfg, ParamList->paramarray[new_idx], numparams, cfgpath);
for (int p = 0; p < numparams; p++) {
if (ParamList->paramarray[new_idx][p].paramflags & PARAMFLAG_PARAMSET)
fprintf(stderr, "[CONFIG] New parameter set: %s\n", ParamList->paramarray[new_idx][p].optname);
}
}
}
if (prefix)
free(newprefix);
/* when added parameters via CLI, return numelt instead of original ret */
return (ParamList->numelt > 0) ? (int)ParamList->numelt : ret;
}
int config_isparamset(paramdef_t *params,int paramidx) {
int config_isparamset(paramdef_t *params, int paramidx)
{
if ((params[paramidx].paramflags & PARAMFLAG_PARAMSET) != 0) {
return 1;
} else {

View File

@@ -43,7 +43,7 @@
#define NB_RB_MAX (11 + 3) /* LTE_maxDRB from LTE_asn_constant.h + 3 SRBs */
#define NR_NB_RB_MAX (29 + 3) /* NR_maxDRB from NR_asn_constant.hm + 3 SRBs */
#define NGAP_MAX_PDU_SESSION (256) /* As defined in TS 38.413 9.2.1.1 Range Bound for PDU Sessions. */
#define NR_MAX_NB_PDU_SESSIONS (256)
#define MAX_DRBS_PER_UE (32) /* Maximum number of Data Radio Bearers per UE
* defined for NGAP in TS 38.413 - maxnoofDRBs */

View File

@@ -40,9 +40,9 @@ static void *consumer(void *arg)
static void run_test(int range, int q_size)
{
q_args_t args = {
.q = spsc_q_alloc(q_size, sizeof(int)),
.range = range,
};
spsc_q_alloc(&args.q, q_size, sizeof(int));
pthread_t p, c;
int ret;

View File

@@ -301,7 +301,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu
ERROR_MSG_RET("Missing input. Usage: trigger_pdu_session_release [ue_id=gNB_ue_ngap_id(int,opt)],pdusession_id(int)[,pdusession_id(int)...]\n");
}
char *tokens[NGAP_MAX_PDU_SESSION + 1];
char *tokens[NR_MAX_NB_PDU_SESSIONS + 1];
int count = 0;
for (char *tok = strtok(buf, ","); tok != NULL && count < (int)sizeofArray(tokens); tok = strtok(NULL, ",")) {

View File

@@ -65,36 +65,3 @@ sequenceDiagram
u->>c: BEARER CONTEXT MODIFICATION RESPONSE
Note over c: e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE
```
## PDU Session Release
```mermaid
sequenceDiagram
participant AMF
participant CUCP
participant CUUP
participant DU
participant UE
AMF->>CUCP: NG PDU SESSION RESOURCE RELEASE COMMAND
Note over CUCP: ngap_gNB_handle_pdusession_release_command
CUCP->>CUCP: rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND
Note over CUCP: set status PDU_SESSION_STATUS_TORELEASE
CUCP->>CUUP: E1 Bearer Context Modification Request
Note over CUUP: release_gtpu_tunnel (GTP tunnel, PDCP, SDAP)
CUUP->>CUCP: E1 Bearer Context Modification Response
Note over CUCP: rrc_gNB_send_f1_drb_release_request
CUCP->>DU: F1 UE Context Modification Request
Note over DU: handle_ue_context_drbs_release (release in MAC/RLC)
DU->>CUCP: F1 UE Context Modification Response
Note over CUCP: rrc_CU_process_ue_context_modification_response
Note over CUCP: replace existing CellGroupConfig
Note over CUCP: rrc_gNB_generate_dedicatedRRCReconfiguration
CUCP->>UE: RRCReconfiguration (DRB release list, NAS PDU)
UE->>CUCP: RRCReconfigurationComplete
Note over CUCP: handle_rrcReconfigurationComplete
Note over CUCP: rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE
CUCP->>AMF: NG PDU SESSION RESOURCE RELEASE RESPONSE
Note over CUCP: rm_drbs_by_pdusession (from stored RRC list)
Note over CUCP: rm_pduSession (from stored RRC list)
```

View File

@@ -62,10 +62,13 @@ We tested the category A radio units listed below.
|Vendor |Software Version |
|-----------------|---------------------------------------------|
|VVDN LPRU |03-v3.0.5 |
|LiteON RU |01.00.08/02.00.03/02.00.10 |
|Benetel 650 |RAN650-1v1.0.4-dda1bf5/RAN650-1v1.2.2-2fa04bc/RAN650-1v1.4.2-NM-c48047d|
|Benetel 550 |RAN550-1v1.0.4-605a25a/RAN550-1v1.2.2-2fa04bc/RAN550-1v1.4.1-M-25fa970/RAN550-1v2.0.5-M-92a9d2c|
|LiteON RU FR1 |01.00.08/02.00.03/02.00.10 |
|LiteON RU FR2 |02.00.07 |
|Metanoia RU FR1 |2.0.6 |
|Benetel 650 |RAN650-1v2.1.0-M-0820797 |
|Benetel 550 |RAN550-1v2.1.0-M-0820797 |
|Foxconn RPQN |v3.1.15q.551_rc10 |
|Microamp RU |0.1.174 |
Tested libxran releases:
@@ -630,82 +633,481 @@ eAXC_id 0 1 # set PRACH eAxC IDs
...
```
#### MICROAMP FR2
#### Microamp FR2
#### Firmware starting from 0.1.174
Requirements:
- sshpass:
```bash
#RHEL
sudo dnf install sshpass -y
#Ubuntu
sudo apt install sshpass -y
```
To check PTP status, you can use the following command:
```bash
sshpass -p microampcfg ssh remctl@<RU_IP_ADDR> "logs-ptp"
```
<details>
<summary>PTP output will be similar to:</summary>
```
Apr 27 11:58:35 bbv1 ptp4l[74545]: ptp4l[357120.237]: rms 8 max 16 freq -100 +/- 142 delay 1183 +/- 0
Apr 27 11:58:34 bbv1 ptp4l[74545]: ptp4l[357119.114]: rms 1 max 1 freq +189 +/- 25 delay 1183 +/- 0
Apr 27 11:58:33 bbv1 ptp4l[74545]: ptp4l[357117.991]: rms 1 max 1 freq +99 +/- 30 delay 1183 +/- 0
Apr 27 11:58:32 bbv1 ptp4l[74545]: ptp4l[357116.869]: rms 1 max 1 freq +22 +/- 18 delay 1183 +/- 0
Apr 27 11:58:31 bbv1 ptp4l[74545]: ptp4l[357115.746]: rms 1 max 1 freq -51 +/- 20 delay 1183 +/- 0
Apr 27 11:58:30 bbv1 ptp4l[74545]: ptp4l[357114.624]: rms 1 max 2 freq -126 +/- 29 delay 1183 +/- 0
Apr 27 11:58:29 bbv1 ptp4l[74545]: ptp4l[357113.501]: rms 8 max 16 freq -16 +/- 200 delay 1184 +/- 0
Apr 27 11:58:28 bbv1 ptp4l[74545]: ptp4l[357112.378]: rms 1 max 2 freq +164 +/- 29 delay 1183 +/- 0
Apr 27 11:58:26 bbv1 ptp4l[74545]: ptp4l[357111.256]: rms 1 max 2 freq +54 +/- 39 delay 1183 +/- 0
Apr 27 11:58:25 bbv1 ptp4l[74545]: ptp4l[357110.133]: rms 1 max 2 freq -34 +/- 19 delay 1183 +/- 0
Apr 27 11:58:24 bbv1 ptp4l[74545]: ptp4l[357109.010]: rms 1 max 2 freq -112 +/- 26 delay 1183 +/- 0
Apr 27 11:58:23 bbv1 ptp4l[74545]: ptp4l[357107.888]: rms 8 max 16 freq -48 +/- 174 delay 1183 +/- 0
Apr 27 11:58:22 bbv1 ptp4l[74545]: ptp4l[357106.766]: rms 1 max 1 freq +197 +/- 25 delay 1183 +/- 0
Apr 27 11:58:21 bbv1 ptp4l[74545]: ptp4l[357105.642]: rms 1 max 2 freq +149 +/- 26 delay 1183 +/- 0
Apr 27 11:58:20 bbv1 ptp4l[74545]: ptp4l[357104.519]: rms 1 max 2 freq +66 +/- 27 delay 1183 +/- 0
Apr 27 11:58:19 bbv1 ptp4l[74545]: ptp4l[357103.396]: rms 1 max 2 freq -17 +/- 24 delay 1183 +/- 0
Apr 27 11:58:17 bbv1 ptp4l[74545]: ptp4l[357102.273]: rms 1 max 1 freq -94 +/- 23 delay 1183 +/- 0
Apr 27 11:58:16 bbv1 ptp4l[74545]: ptp4l[357101.150]: rms 7 max 16 freq +107 +/- 180 delay 1183 +/- 0
Apr 27 11:58:15 bbv1 ptp4l[74545]: ptp4l[357100.027]: rms 1 max 2 freq +166 +/- 11 delay 1184 +/- 0
Apr 27 11:58:14 bbv1 ptp4l[74545]: ptp4l[357098.906]: rms 1 max 1 freq +140 +/- 21 delay 1183 +/- 0
```
</details>
###### RU configuration
You can use the following command to display the current RU configuration:
```bash
sshpass -p microampcfg ssh remctl@<RU_IP_ADDR> get-cfg
```
<details>
<summary>
The OAI configuration file [`gnb.sa.band257.132prb.fhi72.2x2-microamp.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.132prb.fhi72.2x2-microamp.conf) corresponds to the following RU configuration:
</summary>
```
PRACH0 CC ID: 0
PRACH0 RU port ID: 0
PRACH1 CC ID: 1
PRACH1 RU port ID: 1
Bandwidth: 200M [Hz]
Carrier frequency: 28049280000.0 [Hz]
Compression enable: True
TDD config: DDDSU
eCPRI VLAN support enable: True
eCPRI VLAN tag: 600
MAC address: 10:70:fd:b8:86:02
VLAN PTP status: ENABLED
VLAN MGMT enabled: ENABLED
State: ENABLED_WITH_VLAN
Dynamic beamforming with mirrored beams
PL MAC address:
RU MAC: 10-70-FD-B8-86-02
DU MAC: 50-7C-6F-31-00-61
RF Power level: -5 dB - relative to maximum
```
</details>
Execute the following command to check how to configure the RU:
```bash
sshpass -p microampcfg ssh remctl@<RU_IP_ADDR> "help"
```
<details>
<summary>Help output will be similar to:</summary>
```
Usage: remctl <subcommand> [options]
Allowed Subcommands:
set-cfg, get-cfg, stat, logs-ptp, reboot, set-power, help, clear-cfg
Allowed 'set-cfg' options:
--bandwidth
--tdd-cfg
--compression-enable
--compression-disable
--ecpri-vlan-tag
--ecpri-vlan-support-enable
--ecpri-vlan-support-disable
--ru-mac
--du-mac
--beamforming
--carrier-freq
--eth-ipv4
--prach0-cc-id
--prach0-ru-port-id
--prach1-cc-id
--prach1-ru-port-id
```
</details>
You can also execute the following command to show fronthaul statistics including on-time/late packet' counters:
```bash
sshpass -p microampcfg ssh remctl@<RU_IP_ADDR> "stat"
```
<details>
<summary>Statistics output will be similar to:</summary>
```
ORAN RX C-plane on time: 71645874
ORAN RX C-plane early: 0
ORAN RX C-plane late: 16
ORAN TX U-plane: 229686268
ORAN RX DL C-plane on time: 53987559
ORAN RX DL C-plane early: 0
ORAN RX DL C-plane late: 12
ORAN RX DL U-plane on time: 701836967
ORAN RX DL U-plane early: 0
ORAN RX DL U-plane late: 52
ORAN RX UL C-plane on time: 17658315
ORAN RX UL C-plane early: 0
ORAN RX UL C-plane late: 4
CLASSIFIER LLC: overflow protection: 0
CLASSIFIER LLC: frame err: 28
CLASSIFIER LLC: packet too long: 0
CLASSIFIER LLC: dropped: 28
CLASSIFIER LLC: passed: 804719078
CLASSIFIER ETH: dst MAC addr err: 0
CLASSIFIER ETH: VLAN LEGACY: 275571
CLASSIFIER ETH: VLAN Dot1Q: 804443507
CLASSIFIER ETH: VLAN Dot1AD: 0
CLASSIFIER ETH: VLAN Tag ID pass: 773482909
CLASSIFIER ETH: VLAN Tag ID error: 0
CLASSIFIER ETH: multicast: 31233828
CLASSIFIER ETH: PTP: 29502626
CLASSIFIER ETH: eCPRI: 773482909
CLASSIFIER ETH: to OS: 31236169
CLASSIFIER ETH: dropped: 0
CLASSIFIER ETH: passed: 804719078
CLASSIFIER ECPRI: prot rev unsupported: 0
CLASSIFIER ECPRI: concat unsupported: 0
CLASSIFIER ECPRI: msg type unsupported: 0
CLASSIFIER ECPRI: pld size err: 0
CLASSIFIER ECPRI: U-Plane: 701837019
CLASSIFIER ECPRI: C-Plane: 71645890
CLASSIFIER ECPRI: delay: 0
CLASSIFIER ECPRI: dropped: 0
CLASSIFIER ECPRI: passed: 773482909
CPLANE PARSER: ul early: 0
CPLANE PARSER: ul late: 4
CPLANE PARSER: ul on time: 17658315
CPLANE PARSER: dl early: 0
CPLANE PARSER: dl late: 12
CPLANE PARSER: dl on time: 53987559
CPLANE PARSER: timing dropped: 16
CPLANE PARSER: timing passed: 71645874
CPLANE PARSER: bad du port id: 0
CPLANE PARSER: bad bandsector id: 0
CPLANE PARSER: bad cc id: 663059
CPLANE PARSER: bad ru port id: 2794
CPLANE PARSER: bad sequence id: 0
CPLANE PARSER: bad e bit: 0
CPLANE PARSER: bad subsequence id: 0
CPLANE PARSER: ecpri transport header dropped: 665623
CPLANE PARSER: ecpri transport header passed: 70980251
CPLANE PARSER: bad payloadversion: 0
CPLANE PARSER: bad filterindex: 0
CPLANE PARSER: bad subframeid: 0
CPLANE PARSER: bad slotid: 0
CPLANE PARSER: bad startsymbolid: 0
CPLANE PARSER: bad numberofsections: 0
CPLANE PARSER: bad sectiontype: 0
CPLANE PARSER: bad timeoffset: 0
CPLANE PARSER: bad fftsize: 0
CPLANE PARSER: bad subcarrierspacing: 0
CPLANE PARSER: bad cplength: 0
CPLANE PARSER: bad udiqwidth: 0
CPLANE PARSER: radio aplication header dropped: 0
CPLANE PARSER: radio aplication header passed: 70980251
CPLANE PARSER: bad rb: 0
CPLANE PARSER: bad startprbc: 0
CPLANE PARSER: bad numprbc: 0
CPLANE PARSER: bad remask: 0
CPLANE PARSER: bad numsymbol: 0
CPLANE PARSER: bad ef: 0
CPLANE PARSER: bad freqoffset: 0
CPLANE PARSER: common section fields dropped: 0
CPLANE PARSER: common section fields passed: 70980251
CPLANE PARSER: bad section to symbol map: 0
CPLANE PARSER: dropped: 0
CPLANE PARSER: passed: 70980251
CPLANE PARSER: expected uplanes number: 701813698
UPLANE PARSER: sequence ID err: 0
UPLANE PARSER: IQ pld size err: 0
UPLANE PARSER: C-Plane match err: 114225
UPLANE PARSER: eAxC ID unsupported: 24631
UPLANE PARSER: any value unsupported: 24631
UPLANE PARSER: dropped: 138886
UPLANE PARSER: passed: 701698133
UPLANE ENCAPSULATOR 0: false drop error: 0
UPLANE ENCAPSULATOR 0: passed: 94598642
UPLANE ENCAPSULATOR 1: false drop error: 0
UPLANE ENCAPSULATOR 1: passed: 94598642
UPLANE ENCAPSULATOR 2: false drop error: 0
UPLANE ENCAPSULATOR 2: passed: 0
UPLANE ENCAPSULATOR 3: false drop error: 0
UPLANE ENCAPSULATOR 3: passed: 0
COMMON COMMON: symbol counter: 57757250505
DSP CHAIN 0: dl fft overflow: 0
DSP CHAIN 0: ul fft overflow: 0
DSP CHAIN 1: dl fft overflow: 0
DSP CHAIN 1: ul fft overflow: 0
```
</details>
##### Firmware older than 0.1.174
Interaction with RU is performed using `rucfg` utility provided by Microamp.
To check PTP status, you can use `rucfg ptp`. the output should be similar to:
```bash
[INFO] Check if RU is available
[INFO] RU available
[INFO] Check SSH to RU available
[INFO] SSH to RU available
[INFO] Getting PTP status
[INFO] ptp4l status =
{
Feb 12 16:26:02 bbv1 ptp4l[23822]: ptp4l[6280.658]: rms 0 max 1 freq +2 +/- 7 delay 1184 +/- 0
Feb 12 16:26:00 bbv1 ptp4l[23822]: ptp4l[6279.535]: rms 0 max 1 freq -8 +/- 13 delay 1184 +/- 0
Feb 12 16:25:59 bbv1 ptp4l[23822]: ptp4l[6278.413]: rms 1 max 1 freq -35 +/- 13 delay 1184 +/- 0
Feb 12 16:25:58 bbv1 ptp4l[23822]: ptp4l[6277.290]: rms 0 max 1 freq -68 +/- 9 delay 1184 +/- 0
Feb 12 16:25:57 bbv1 ptp4l[23822]: ptp4l[6276.167]: rms 1 max 1 freq -69 +/- 10 delay 1184 +/- 0
Feb 12 16:25:56 bbv1 ptp4l[23822]: ptp4l[6275.044]: rms 0 max 1 freq -46 +/- 9 delay 1184 +/- 0
Feb 12 16:25:55 bbv1 ptp4l[23822]: ptp4l[6273.921]: rms 1 max 1 freq -65 +/- 10 delay 1184 +/- 0
Feb 12 16:25:54 bbv1 ptp4l[23822]: ptp4l[6272.800]: rms 0 max 1 freq -91 +/- 6 delay 1184 +/- 0
Feb 12 16:25:53 bbv1 ptp4l[23822]: ptp4l[6271.677]: rms 4 max 17 freq -107 +/- 48 delay 1184 +/- 0
Feb 12 16:25:52 bbv1 ptp4l[23822]: ptp4l[6270.554]: rms 6 max 17 freq +179 +/- 106 delay 1184 +/- 0
Feb 12 16:25:50 bbv1 ptp4l[23822]: ptp4l[6269.431]: rms 1 max 2 freq +191 +/- 12 delay 1184 +/- 0
Feb 12 16:25:49 bbv1 ptp4l[23822]: ptp4l[6268.308]: rms 1 max 1 freq +119 +/- 21 delay 1184 +/- 0
Feb 12 16:25:48 bbv1 ptp4l[23822]: ptp4l[6267.186]: rms 1 max 1 freq +103 +/- 13 delay 1184 +/- 0
Feb 12 16:25:47 bbv1 ptp4l[23822]: ptp4l[6266.063]: rms 7 max 17 freq -101 +/- 160 delay 1184 +/- 0
Feb 12 16:25:46 bbv1 ptp4l[23822]: ptp4l[6264.940]: rms 7 max 17 freq -65 +/- 154 delay 1184 +/- 0
Feb 12 16:25:45 bbv1 ptp4l[23822]: ptp4l[6263.817]: rms 1 max 2 freq +176 +/- 33 delay 1183 +/- 0
Feb 12 16:25:44 bbv1 ptp4l[23822]: ptp4l[6262.695]: rms 0 max 1 freq +100 +/- 7 delay 1184 +/- 0
Feb 12 16:25:43 bbv1 ptp4l[23822]: ptp4l[6261.572]: rms 1 max 2 freq +56 +/- 34 delay 1184 +/- 0
Feb 12 16:25:41 bbv1 ptp4l[23822]: ptp4l[6260.449]: rms 1 max 1 freq -37 +/- 14 delay 1184 +/- 0
Feb 12 16:25:40 bbv1 ptp4l[23822]: ptp4l[6259.326]: rms 7 max 16 freq +114 +/- 149 delay 1183 +/- 0
}
To check PTP status, you can use `rucfg ptp`.
```
##### RU configuration
<details>
<summary>PTP output will be similar to:</summary>
You can use `rucfg show` to display the current RU configuration.
```
[INFO] Check if RU is available
[INFO] RU available
[INFO] Check SSH to RU available
[INFO] SSH to RU available
[INFO] Getting PTP status
[INFO] ptp4l status =
{
Feb 12 16:26:02 bbv1 ptp4l[23822]: ptp4l[6280.658]: rms 0 max 1 freq +2 +/- 7 delay 1184 +/- 0
Feb 12 16:26:00 bbv1 ptp4l[23822]: ptp4l[6279.535]: rms 0 max 1 freq -8 +/- 13 delay 1184 +/- 0
Feb 12 16:25:59 bbv1 ptp4l[23822]: ptp4l[6278.413]: rms 1 max 1 freq -35 +/- 13 delay 1184 +/- 0
Feb 12 16:25:58 bbv1 ptp4l[23822]: ptp4l[6277.290]: rms 0 max 1 freq -68 +/- 9 delay 1184 +/- 0
Feb 12 16:25:57 bbv1 ptp4l[23822]: ptp4l[6276.167]: rms 1 max 1 freq -69 +/- 10 delay 1184 +/- 0
Feb 12 16:25:56 bbv1 ptp4l[23822]: ptp4l[6275.044]: rms 0 max 1 freq -46 +/- 9 delay 1184 +/- 0
Feb 12 16:25:55 bbv1 ptp4l[23822]: ptp4l[6273.921]: rms 1 max 1 freq -65 +/- 10 delay 1184 +/- 0
Feb 12 16:25:54 bbv1 ptp4l[23822]: ptp4l[6272.800]: rms 0 max 1 freq -91 +/- 6 delay 1184 +/- 0
Feb 12 16:25:53 bbv1 ptp4l[23822]: ptp4l[6271.677]: rms 4 max 17 freq -107 +/- 48 delay 1184 +/- 0
Feb 12 16:25:52 bbv1 ptp4l[23822]: ptp4l[6270.554]: rms 6 max 17 freq +179 +/- 106 delay 1184 +/- 0
Feb 12 16:25:50 bbv1 ptp4l[23822]: ptp4l[6269.431]: rms 1 max 2 freq +191 +/- 12 delay 1184 +/- 0
Feb 12 16:25:49 bbv1 ptp4l[23822]: ptp4l[6268.308]: rms 1 max 1 freq +119 +/- 21 delay 1184 +/- 0
Feb 12 16:25:48 bbv1 ptp4l[23822]: ptp4l[6267.186]: rms 1 max 1 freq +103 +/- 13 delay 1184 +/- 0
Feb 12 16:25:47 bbv1 ptp4l[23822]: ptp4l[6266.063]: rms 7 max 17 freq -101 +/- 160 delay 1184 +/- 0
Feb 12 16:25:46 bbv1 ptp4l[23822]: ptp4l[6264.940]: rms 7 max 17 freq -65 +/- 154 delay 1184 +/- 0
Feb 12 16:25:45 bbv1 ptp4l[23822]: ptp4l[6263.817]: rms 1 max 2 freq +176 +/- 33 delay 1183 +/- 0
Feb 12 16:25:44 bbv1 ptp4l[23822]: ptp4l[6262.695]: rms 0 max 1 freq +100 +/- 7 delay 1184 +/- 0
Feb 12 16:25:43 bbv1 ptp4l[23822]: ptp4l[6261.572]: rms 1 max 2 freq +56 +/- 34 delay 1184 +/- 0
Feb 12 16:25:41 bbv1 ptp4l[23822]: ptp4l[6260.449]: rms 1 max 1 freq -37 +/- 14 delay 1184 +/- 0
Feb 12 16:25:40 bbv1 ptp4l[23822]: ptp4l[6259.326]: rms 7 max 16 freq +114 +/- 149 delay 1183 +/- 0
}
```
The OAI configuration file [`gnb.sa.band257.132prb.fhi72.2x2-microamp.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.132prb.fhi72.2x2-microamp.conf) corresponds to the following RU configuration:
</details>
###### RU configuration
You can use `rucfg show` command to display the current RU configuration.
<details>
<summary>
The OAI configuration file [`gnb.sa.band257.132prb.fhi72.2x2-microamp.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.132prb.fhi72.2x2-microamp.conf) corresponds to the following RU configuration:
</summary>
```
[INFO] Check if RU is available
[INFO] RU available
[INFO] Check SSH to RU available
[INFO] SSH to RU available
[INFO] Downloading oran_autostart
[INFO] Downloading ructl_config.sh
[INFO] Downloading udc_pll_configurator_startup
[INFO] Downloaded Cellbox config =
{
eCPRI Compression: True
RF Bandwidth: 200MHz
CC Bandwidth: 200MHz
CCs: 1
LO frequency: 7.91642667e9
UL compensation frequency: 28.04928e9
DL compensation frequency: -28.04928e9
RU MAC: 10:70:FD:B8:86:02
DU MAC: 50:7C:6F:31:00:61
TDD config: dddsu
RF Power level: -5 dB - relative to maximum
VLAN ORAN: Enabled, tag: 600
VLAN PTP: Enabled, tag: 1
VLAN MGMT: False
Beamforming: dynamic-mirrored-beam
}
```
</details>
```bash
[INFO] Check if RU is available
[INFO] RU available
[INFO] Check SSH to RU available
[INFO] SSH to RU available
[INFO] Downloading oran_autostart
[INFO] Downloading ructl_config.sh
[INFO] Downloading udc_pll_configurator_startup
[INFO] Downloaded Cellbox config =
{
eCPRI Compression: True
RF Bandwidth: 200MHz
CC Bandwidth: 200MHz
CCs: 1
LO frequency: 7.91642667e9
UL compensation frequency: 28.04928e9
DL compensation frequency: -28.04928e9
RU MAC: 10:70:FD:B8:86:02
DU MAC: 50:7C:6F:31:00:61
TDD config: dddsu
RF Power level: -5 dB - relative to maximum
VLAN ORAN: Enabled, tag: 600
VLAN PTP: Enabled, tag: 1
VLAN MGMT: False
Beamforming: dynamic-mirrored-beam
}
```
Execute `rucfg config -h` to check how to configure the RU.
<details>
<summary>Help output will be similar to:</summary>
```
usage: rucfg config [-h] [-f frequency] [-b bandwidth] [-t TDD pattern] [-p RU Power]
[--cc carrier components] [--compression compression] [--vlan-oran vlan-oran]
[--vlan-ptp vlan-ptp] [--mac DU MAC address]
options:
-h, --help show this help message and exit
-f frequency, --freq frequency
Sets the 5G NR frequency. Allowed range: 24.0-29.9 GHz, default: <no conf
change>
-b bandwidth, --bandwidth bandwidth
Sets RF bandwidth 100/200 [MHz] per CC, default: <no conf change>
-t TDD pattern, --tdd TDD pattern
Sets TDD pattern DDDSU/DDSUU/DSUUU, default: <no conf change>
-p RU Power, --power RU Power
Sets Power in (0-100), default: <no conf change>
--cc carrier components
Sets number of carrier components 1/2, default: <no conf change>
--compression compression
Sets eCPRI compression True/False, default: <no conf change>
--vlan-oran vlan-oran
Sets ORAN VLAN to None or <TAG>, default: <no conf change>
--vlan-ptp vlan-ptp Sets PTP VLAN to None or <TAG>, default: <no conf change>
--mac DU MAC address Sets DU MAC address (where RU sends eCPRI packets), format
AA:BB:CC:DD:EE:FF, default: <no conf change>
```
</details>
You can also execute `rucfg stats` to show fronthaul statistics including on-time/late packet' counters.
<details>
<summary>Statistics output will be similar to:</summary>
```
[INFO] Check if RU is available
[INFO] RU available
[INFO] Check SSH to RU available
[INFO] SSH to RU available
[INFO] Getting RU stats
[WARN] Received non-zero rc from ructl: 255
[INFO] ru stats =
{
Preaccumulator overflow detected
ORAN RX C-plane on time: 5442384
ORAN RX C-plane early: 0
ORAN RX C-plane late: 4
ORAN TX U-plane: 15908424
ORAN RX DL C-plane on time: 3349166
ORAN RX DL C-plane early: 0
ORAN RX DL C-plane late: 0
ORAN RX DL U-plane on time: 43538742
ORAN RX DL U-plane early: 0
ORAN RX DL U-plane late: 93
ORAN RX UL C-plane on time: 2093218
ORAN RX UL C-plane early: 0
ORAN RX UL C-plane late: 4
CLASSIFIER LLC: overflow protection: 0
CLASSIFIER LLC: frame err: 0
CLASSIFIER LLC: packet too long: 0
CLASSIFIER LLC: dropped: 0
CLASSIFIER LLC: passed: 49044133
CLASSIFIER ETH: dst MAC addr err: 0
CLASSIFIER ETH: VLAN LEGACY: 1524
CLASSIFIER ETH: VLAN Dot1Q: 49042609
CLASSIFIER ETH: VLAN Dot1AD: 0
CLASSIFIER ETH: VLAN Tag ID pass: 48981223
CLASSIFIER ETH: VLAN Tag ID error: 0
CLASSIFIER ETH: multicast: 60260
CLASSIFIER ETH: PTP: 56086
CLASSIFIER ETH: eCPRI: 48981223
CLASSIFIER ETH: to OS: 62910
CLASSIFIER ETH: dropped: 0
CLASSIFIER ETH: passed: 49044133
CLASSIFIER ECPRI: prot rev unsupported: 0
CLASSIFIER ECPRI: concat unsupported: 0
CLASSIFIER ECPRI: msg type unsupported: 0
CLASSIFIER ECPRI: pld size err: 0
CLASSIFIER ECPRI: U-Plane: 43538835
CLASSIFIER ECPRI: C-Plane: 5442388
CLASSIFIER ECPRI: delay: 0
CLASSIFIER ECPRI: dropped: 0
CLASSIFIER ECPRI: passed: 48981223
CPLANE PARSER: ul early: 0
CPLANE PARSER: ul late: 4
CPLANE PARSER: ul on time: 2093218
CPLANE PARSER: dl early: 0
CPLANE PARSER: dl late: 0
CPLANE PARSER: dl on time: 3349166
CPLANE PARSER: timing dropped: 4
CPLANE PARSER: timing passed: 5442384
CPLANE PARSER: bad du port id: 0
CPLANE PARSER: bad bandsector id: 0
CPLANE PARSER: bad cc id: 0
CPLANE PARSER: bad ru port id: 0
CPLANE PARSER: bad sequence id: 0
CPLANE PARSER: bad e bit: 0
CPLANE PARSER: bad subsequence id: 0
CPLANE PARSER: ecpri transport header dropped: 0
CPLANE PARSER: ecpri transport header passed: 5442384
CPLANE PARSER: bad payloadversion: 0
CPLANE PARSER: bad filterindex: 0
CPLANE PARSER: bad subframeid: 0
CPLANE PARSER: bad slotid: 0
CPLANE PARSER: bad startsymbolid: 0
CPLANE PARSER: bad numberofsections: 0
CPLANE PARSER: bad sectiontype: 0
CPLANE PARSER: bad timeoffset: 0
CPLANE PARSER: bad fftsize: 0
CPLANE PARSER: bad subcarrierspacing: 0
CPLANE PARSER: bad cplength: 0
CPLANE PARSER: bad udiqwidth: 0
CPLANE PARSER: radio aplication header dropped: 0
CPLANE PARSER: radio aplication header passed: 5442384
CPLANE PARSER: bad rb: 0
CPLANE PARSER: bad startprbc: 0
CPLANE PARSER: bad numprbc: 0
CPLANE PARSER: bad remask: 0
CPLANE PARSER: bad numsymbol: 0
CPLANE PARSER: bad ef: 0
CPLANE PARSER: bad freqoffset: 0
CPLANE PARSER: common section fields dropped: 0
CPLANE PARSER: common section fields passed: 5442384
CPLANE PARSER: bad section to symbol map: 0
CPLANE PARSER: dropped: 0
CPLANE PARSER: passed: 5442384
UPLANE PARSER: sequence ID err: 0
UPLANE PARSER: IQ pld size err: 0
UPLANE PARSER: C-Plane match err: 7138
UPLANE PARSER: eAxC ID unsupported: 0
UPLANE PARSER: any value unsupported: 0
UPLANE PARSER: dropped: 7231
UPLANE PARSER: passed: 43531604
UPLANE ENCAPSULATOR 0: false drop error: 0
UPLANE ENCAPSULATOR 0: passed: 6698292
UPLANE ENCAPSULATOR 1: false drop error: 0
UPLANE ENCAPSULATOR 1: passed: 6698292
UPLANE ENCAPSULATOR 2: false drop error: 0
UPLANE ENCAPSULATOR 2: passed: 0
UPLANE ENCAPSULATOR 3: false drop error: 0
UPLANE ENCAPSULATOR 3: passed: 0
COMMON COMMON: symbol counter: 111095058
}
```
</details>
#### VVDN LPRU
**Version 3.x**
@@ -844,6 +1246,42 @@ sudo ./ru_emulator -c <path-to/protoru-OAI-B210-TDD-n78-40MHz-1x1-30kHz.yml>
Finally, start the OAI gNB.
#### WNC R1220
**Version 1.9.0**
The OAI configuration file [gnb.sa.band77.273prb.fhi72.4x4-wnc.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-wnc.conf) corresponds to:
- TDD pattern `DDDDDDSUUU`, 5ms
- Bandwidth 100MHz
- 4TX4R
##### RU configuration
After switching on or rebooting the RU, you can check the RU PTP status with `show ptp clock` to make sure it's locked and run `show running-config` to check the current configuration.
To enable RU transmission, use the `radio enable` command. Then verify the configuration with `show running-config`, which should reflect the enabled state:
```
radio 1
no shutdown
```
The required parameters to configure are:
1. `center-frequency` → 3849990
2. `transmit-power` → 24
3. `lna-shutdown`**disabled**
4. `transport-interface` → configure the sub-interface (VLAN ID is defined during sub-interface creation)
5. `transport-peer-mac` → must match the DU MAC address
6. `phase-compensation`**enabled**
7. `bandwidth` → 100
8. `sub-carrier` → 30
9. `compress-oran-compliant`**enabled**
**Note**
* Ensure that the VLAN configuration and MAC addressing are consistent with the DU setup.
* The RU must be PTP synchronized before starting the gNB.
* After reboot, the RU loads its `startup-config`. To save the current configuration, use `copy running-config startup-config`.
## Configure Network Interfaces and DPDK VFs
The 7.2 fronthaul uses the xran library, which requires DPDK. In this step, we
@@ -854,7 +1292,7 @@ to create one or multiple virtual functions (VFs) through which Control plane (C
plane) and User plane (U plane) traffic will flow. The following commands are
not persistant, and have to be repeated after reboot.
In the following, we will use these short hands:
In the following, we will use the follwing shorthand notation:
- `IF_NAME`: Physical network interface through which you can access the RU
- `VLAN`: the VLAN tag as recommended by the RU vendor
@@ -1495,7 +1933,9 @@ sudo ldconfig
If you would like to install these libraries in the custom path, please replace `/usr/local` default path to e.g. `/opt/mplane-v2`.
## Benetel O-RU
Note: RAN550/650 v1.2.2 and v1.4.1 have been successfully tested.
Note: RAN550-1v2.1.0-M-0820797 has been successfully tested.
We added a [CI M-plane pipeline](https://jenkins-oai.eurecom.fr/job/RAN-SA-FHI72-MPLANE-CN5G/) showcasing the M-plane integration.
#### One time steps
Connect to the RU as user `root`, enable the mplane service, and reboot:
@@ -3238,4 +3678,5 @@ Your email should contain below information:
- RU Vendor and Version.
- In case your question is related to performance, include a small description of the machine (CPU, RAM and networking card) and diagram of your testing environment.
- If you have any issues related to PTP or synchronization, then first check the section "Debugging PTP issues". Then share your problem with PTP version you are using, switch details and master clock.
- Known/open issues are present on [GitLab](https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues), so keep checking.
- Known/open issues are present on [GitLab](https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues), so keep checking.

View File

@@ -247,6 +247,242 @@ RRCReestablishmentRequest), the CU updates `du_assoc_id` and sets
`f1_ue_context_active` is false, the CU triggers UE Context Setup on the new
DU per TS 38.401 §8.7.
### PDU Session Management
#### PDU Session Modification
```mermaid
sequenceDiagram
participant UE
participant DU
participant CUCP as CU-CP
participant CUUP as CU-UP
participant AMF
AMF->>CUCP: PDUSessionResourceModifyRequest
Note over CUCP: ngap_gNB_handle_pdusession_modify_request
CUCP->>CUCP: decodePDUSessionResourceModify
CUCP->>CUCP: NGAP_PDUSESSION_MODIFY_REQ
CUCP->>CUCP: rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ
opt UE not found or AMF_UE_ID mismatch
CUCP->>AMF: NGAP_PDUSESSION_MODIFY_RESP (Failed PDU Session)
Note over CUCP: stop further processing
end
loop nb_pdusessions_tomodify
CUCP->>CUCP: Update PDU session DRB/QoS configuration<br/>(add/modify/release)
end
alt !all_failed
Note over CUCP: Pre-RRC step: E1/F1 updates
Note over CUCP: Build E1AP DRB-To-Remove/To-Modify/To-Setup lists<br/>(populated during nr_rrc_update_pdusession)
CUCP->>CUUP: E1 BEARER CONTEXT MOD REQUEST (DRB-To-Remove/To-Modify/To-Setup)
Note over CUUP: e1_bearer_context_modif()<br/>Process DRB modifications, removals, and setups<br/>Update PDCP/SDAP entities, GTP tunnels
CUUP->>CUCP: E1 BEARER CONTEXT MOD RESPONSE
Note over CUCP: rrc_gNB_process_e1_bearer_context_modif_resp<br/>Save F1-U tunnel info for new DRBs<br/>Mark PDU sessions with new DRBs as PDU_SESSION_STATUS_NEW
Note over CUCP, DU: F1-U tunnel changes (new DRBs or DRB releases)
CUCP->>DU: F1 UE Context Modification Request
Note over DU: handle_ue_context_drbs_setup/release
DU->>CUCP: F1 UE Context Modification Response
Note over CUCP: rrc_CU_process_ue_context_modification_response
CUCP->>CUCP: rrc_gNB_generate_dedicatedRRCReconfiguration
Note over CUCP: <br/>Attach DRB_ToReleaseList (if any)<br/>Set transaction ID to RRC_PDUSESSION_MODIFY
CUCP->>DU: rrc_deliver_dl_rrc_message
DU->>UE: RRCReconfiguration (DCCH)
UE->>DU: RRCReconfigurationComplete
DU->>CUCP: F1AP_UL_RRC_MESSAGE
Note over CUCP: rrc_gNB_decode_dcch
Note over CUCP: handle_rrcReconfigurationComplete<br/>Calls rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP<br/>(DRBs already removed earlier in nr_rrc_update_pdusession)
CUCP->>CUCP: rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP
loop UE->pduSessions (matching transaction ID)
alt ESTABLISHED
Note over CUCP: Update status to ESTABLISHED<br/>Fill NGAP message (modified)<br/>Include QoS flow list
else PDU_SESSION_STATUS_FAILED
Note over CUCP: Fill NGAP message (failed to modify)<br/>Include cause
end
end
CUCP->>AMF: NGAP_PDUSESSION_MODIFY_RESP
else msg->nb_of_pdusessions_failed > 0
Note over CUCP: PDU Session failed to modify
CUCP->>AMF: NGAP_PDUSESSION_MODIFY_RESP
end
```
#### PDU Session Release
```mermaid
sequenceDiagram
participant AMF
participant CUCP
participant CUUP
participant DU
participant UE
AMF->>CUCP: NG PDU SESSION RESOURCE RELEASE COMMAND
Note over CUCP: ngap_gNB_handle_pdusession_release_command
CUCP->>CUCP: rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND
Note over CUCP: set status PDU_SESSION_STATUS_TORELEASE
CUCP->>CUUP: E1 Bearer Context Modification Request
Note over CUUP: release_gtpu_tunnel (GTP tunnel, PDCP, SDAP)
CUUP->>CUCP: E1 Bearer Context Modification Response
Note over CUCP: rrc_send_f1_ue_context_modification_request
CUCP->>DU: F1 UE Context Modification Request
Note over DU: handle_ue_context_drbs_release (release in MAC/RLC)
DU->>CUCP: F1 UE Context Modification Response
Note over CUCP: rrc_CU_process_ue_context_modification_response
Note over CUCP: replace existing CellGroupConfig
Note over CUCP: rrc_gNB_generate_dedicatedRRCReconfiguration
CUCP->>UE: RRCReconfiguration (DRB release list, NAS PDU)
UE->>CUCP: RRCReconfigurationComplete
Note over CUCP: handle_rrcReconfigurationComplete
Note over CUCP: rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE
CUCP->>AMF: NG PDU SESSION RESOURCE RELEASE RESPONSE
Note over CUCP: rm_drbs_by_pdusession (from stored RRC list)
Note over CUCP: rm_pduSession (from stored RRC list)
```
### QoS Flows Handling
This section describes the end-to-end handling of QoS flows in the OAI 5G SA implementation. QoS flows are
the finest granularity of QoS differentiation in 5G systems. According to 3GPP specs, each PDU session can
contain multiple QoS flows (maximum 64). Each QoS flow is mapped to exactly one Data Radio Bearer (DRB)
within the gNB, but multiple QoS flows can be mapped to the same DRB. The mapping is determined by the
CU-CP and configured in the CU-UP via E1AP, and in the UE via RRC signaling. Each PDU session is mapped
to a SDAP entity and can contain multiple DRBs, each of which may carry multiple QoS flows.
Key Standards:
- 3GPP TS 23.501: 5G System Architecture (6.2.5, Quality of service)
- 3GPP TS 37.324: SDAP Protocol (QoS flow to DRB mapping, 5.3)
- 3GPP TS 38.463: E1AP (Bearer Context Management with QoS flows)
- 3GPP TS 29.281: GTP-U (QFI marking)
- 3GPP TS 38.331: RRC (Radio Bearer Configuration)
Trigger: PDU Session Establishment or Modification from 5G Core (AMF/SMF)
The PDU session setup flow in OAI begins when the gNB receives an NGAP PDU Session Resource Setup Request
from the AMF, containing session parameters and QoS flow information. These flows are stored in the UE
context and passed to the RRC layer, which maps each QoS flow to a DRB and prepares the E1AP Bearer
Context Setup Request for the CU-UP. The CU-UP then creates the corresponding PDCP and SDAP bearers,
establishes F1-U and N3 GTP-U tunnels, and returns a Bearer Context Setup Response. The GTP-U layer stores
QFI-to-DRB mappings for tunnel management, while the SDAP layer maintains QFI-to-DRB tables for both
uplink and downlink packet routing.
During data transfer, uplink packets are demultiplexed using the QFI from the GTP-U header, and downlink
packets are marked with their QFI before being sent to the UPF, ensuring consistent QoS-based traffic
handling end-to-end.
#### CU-CP QoS-flow to DRB mapping
The QoS-flow-to-DRB algorithm runs in the CU-CP (RRC) when flows are added or updated (for example
`nr_rrc_add_bearers`, `nr_rrc_assign_drb_to_qos_flow`, and `nr_rrc_find_suitable_drb_for_qos` in
`openair2/RRC/NR/rrc_gNB_radio_bearers.c`). E1AP does not implement this policy: Bearer Context
Setup/Modification simply carries the resulting PDU sessions, DRB lists, and QoS flows per DRB that RRC
already chose.
The mapping is OAI-specific (3GPP defines that the gNB may map multiple QoS flows to one DRB but does
not mandate these numeric caps).
DRB assignment uses a QoS-aware multiplexing strategy from standardized 5QI where available:
- Dedicated DRBs (one QoS flow per DRB in practice for these classes):
- Delay-critical GBR (5QI 8290): each such flow triggers a new DRB, existing DRBs that already carry
DC-GBR are not reused for other flows.
- Other flows treated as isolated: 5QI 4, 6, 7, 8, 9, 10, 70, 80, and 71-73.
- Multiplexed DRBs (when the new flow is not in the dedicated set, and reuse is allowed on a PDU session):
- Non-delay-critical GBR flows: up to 2 QoS flows per DRB.
- Non-GBR flows: up to 5 QoS flows per DRB.
- Aggregate cap: at most 5 QoS flows per DRB in total (mixed GBR/non-GBR counts).
Per-DRB counting uses resource-type buckets (DC-GBR, GBR, non-GBR) derived from 3GPP TS 23.501
table 5.7.4-1 (standardized 5QI).
Dynamic 5QI without a numeric 5QI: OAI uses a conservative heuristic (packet delay budget, packet
error rate, and QoS priority thresholds) to decide whether the flow must use a new dedicated DRB or
may share an existing DRB. That path is independent of the static 5QI lists above.
#### Sequence Diagram
```mermaid
sequenceDiagram
participant UE
participant DU
participant CUCP as CU-CP
participant CUUP as CU-UP
participant AMF
participant UPF
AMF->>CUCP: NGAP PDU Session Resource Setup Request
Note over CUCP: QoS flows, QoS profile (e.g. 5QI, ARP, GFBR/MFBR)<br/>and N3 UP tunnel info
Note over CUCP: ngap_gNB_handle_pdusession_setup_request<br/>ITTI to RRC
CUCP->>CUCP: rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ
CUCP->>CUCP: nr_rrc_add_bearers
Note over CUCP: QoS-flow-to-DRB mapping
CUCP->>CUCP: trigger_bearer_setup
Note over CUCP: fill_e1_pdusession_to_setup / fill_e1_drb_to_setup<br/>per DRB (QoS flows, SDAP/PDCP)
Note over CUCP,CUUP: BEARER CONTEXT SETUP
CUCP->>CUUP: E1AP Bearer Context Setup Request
Note over CUUP: e1_bearer_context_setup()
loop Per PDU session
loop Each DRB to setup
CUUP->>CUUP: fill_e1_drb_setup
CUUP->>CUUP: fill_e1_qos_flows_setup
Note over CUUP: Copy QFIs from E1 request into E1 setup response
Note over CUUP: f1_drb_gtpu_create<br/>gtpv1u_create_ngu_tunnel<br/>no QFI in F1-U GTP, one tunnel per DRB
end
CUUP->>CUUP: e1_add_bearers
Note over CUUP: nr_sdap_addmod_entity, nr_pdcp_add_drb<br/>SDAP qfi2drb mapping
CUUP->>CUUP: n3_gtpu_create
Note over CUUP: gtpv1u_create_ngu_tunnel<br/>newGtpuCreateTunnel<br/>one N3 tunnel per PDU session
end
CUUP->>CUCP: E1AP Bearer Context Setup Response
Note over CUCP,CUUP: F1-U TEID/addr per DRB
Note over CUUP: N3 TEID (CU-UP) per PDU session
CUCP->>CUCP: rrc_gNB_process_e1_bearer_context_setup_resp
alt First F1 UE context (!f1_ue_context_active)
CUCP->>DU: F1 UE Context Setup Request
Note over CUCP: rrc_f1_ue_context_setup_from_e1_response
else F1 context already active
CUCP->>DU: F1 UE Context Modification Request
Note over CUCP: rrc_send_f1_ue_context_modification_request
end
Note over DU: handle_ue_context_drbs_setup<br/>QoS from F1 flows -> MAC logical channel config
DU->>CUCP: F1 UE Context Setup or Modification Response
CUCP->>CUCP: rrc_gNB_generate_dedicatedRRCReconfiguration
Note over CUCP: DRB-ToAddModList, SDAP-Config (QFI mapping)
CUCP->>DU: rrc_deliver_dl_rrc_message / DL RRC Message Transfer
DU->>UE: RRCReconfiguration (DCCH)
UE->>DU: RRCReconfigurationComplete
DU->>CUCP: UL RRC Message Transfer (F1AP)
Note over CUCP: rrc_gNB_decode_dcch, handle_rrcReconfigurationComplete
CUCP->>AMF: NGAP PDU Session Resource Setup Response
Note over UPF,UE: ===== Data Plane Active ===== (N3/F1-U)
Note over UPF,UE: DOWNLINK (N3 -> CU-UP)
UPF->>CUUP: GTP-U with PDU Session Container (QFI)
Note over CUUP: Gtpv1uHandleGpdu<br/>parse ext hdr -> QFI
Note over CUUP: sdap_data_req<br/>SDAP qfi2drb_table -> DRB
Note over CUUP: nr_pdcp_data_req_drb
CUUP->>DU: F1-U GTP-U (no PDU Session Container / QFI marking)
DU->>UE: DRB
Note over UE,UPF: UPLINK (CU-UP -> N3 UPF)
UE->>DU: DRB
DU->>CUUP: F1-U GTP-U (no QFI marking)
Note over CUUP: PDCP -> SDAP UL RX
Note over CUUP: QFI from SDAP UL header if configured<br/>else gtpv1uSendDirect (no QFI in GTP ext hdr)
Note over CUUP: nr_sdap / gtpv1uSendDirectWithQFI<br/>bearer_id = PDU session id (N3 tunnel key)
CUUP->>UPF: GTP-U PDU Session Container (UL PDU Session Info, QFI)
```
### Inter-DU Handover (F1)
The basic handover (HO) structure is as follows. In order to support various

View File

@@ -241,6 +241,12 @@ information on how the images are built.
~5G-NR ~nrUE
- 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on gracehopper1-oai + WNC RU, OAIUE on jetson1-oai + B210, OAI CN5G
- OpenShift cluster for CN deployment and container images for gNB and UE deployment
- [RAN-SA-FHI72-MPLANE-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-FHI72-MPLANE-CN5G/)
~5G-NR
- cacofonix + FHI72 + Benetel550 (gNB), AmarisoftUE, OAI CN5G
- OpenShift cluster for CN deployment
- FHI 7.2 testing with 40 MHz, 4x4 MIMO configuration and 100 MHz, 2x2 MIMO configuration
- FHI 7.2 Configuration and Performance Management via NETCONF session of an O-RU
### RAN-CI-NSA-Trigger

View File

@@ -36,7 +36,7 @@ services:
ipv4_address: 192.168.70.139
oai-udr:
container_name: "oai-udr"
image: oaisoftwarealliance/oai-udr:develop
image: oaisoftwarealliance/oai-udr:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -52,7 +52,7 @@ services:
ipv4_address: 192.168.70.136
oai-udm:
container_name: "oai-udm"
image: oaisoftwarealliance/oai-udm:develop
image: oaisoftwarealliance/oai-udm:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -67,7 +67,7 @@ services:
ipv4_address: 192.168.70.137
oai-ausf:
container_name: "oai-ausf"
image: oaisoftwarealliance/oai-ausf:develop
image: oaisoftwarealliance/oai-ausf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -82,7 +82,7 @@ services:
ipv4_address: 192.168.70.138
oai-nrf:
container_name: "oai-nrf"
image: oaisoftwarealliance/oai-nrf:develop
image: oaisoftwarealliance/oai-nrf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -95,7 +95,7 @@ services:
ipv4_address: 192.168.70.130
oai-amf:
container_name: "oai-amf"
image: oaisoftwarealliance/oai-amf:develop
image: oaisoftwarealliance/oai-amf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -113,8 +113,8 @@ services:
ipv4_address: 192.168.70.132
oai-lmf:
container_name: "oai-lmf"
image: oaisoftwarealliance/oai-lmf:develop
#image: oai-lmf:psoElementwiseTdoAmeanVarTDoAfilter
image: oaisoftwarealliance/oai-lmf:v2.2.1
#image: oai-lmf:psoElementwiseTdoAmeanVarTDoAfilter
expose:
- 80/tcp
- 8080/tcp
@@ -131,7 +131,7 @@ services:
ipv4_address: 192.168.70.141
oai-smf:
container_name: "oai-smf"
image: oaisoftwarealliance/oai-smf:develop
image: oaisoftwarealliance/oai-smf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -148,7 +148,7 @@ services:
ipv4_address: 192.168.70.133
oai-upf:
container_name: "oai-upf"
image: oaisoftwarealliance/oai-upf:develop
image: oaisoftwarealliance/oai-upf:v2.2.1
expose:
- 2152/udp
- 8805/udp

View File

@@ -36,7 +36,7 @@ services:
ipv4_address: 192.168.70.139
oai-udr:
container_name: "oai-udr"
image: oaisoftwarealliance/oai-udr:develop
image: oaisoftwarealliance/oai-udr:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -52,7 +52,7 @@ services:
ipv4_address: 192.168.70.136
oai-udm:
container_name: "oai-udm"
image: oaisoftwarealliance/oai-udm:develop
image: oaisoftwarealliance/oai-udm:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -67,7 +67,7 @@ services:
ipv4_address: 192.168.70.137
oai-ausf:
container_name: "oai-ausf"
image: oaisoftwarealliance/oai-ausf:develop
image: oaisoftwarealliance/oai-ausf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -82,7 +82,7 @@ services:
ipv4_address: 192.168.70.138
oai-nrf:
container_name: "oai-nrf"
image: oaisoftwarealliance/oai-nrf:develop
image: oaisoftwarealliance/oai-nrf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -95,7 +95,7 @@ services:
ipv4_address: 192.168.70.130
oai-amf:
container_name: "oai-amf"
image: oaisoftwarealliance/oai-amf:develop
image: oaisoftwarealliance/oai-amf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -113,7 +113,7 @@ services:
ipv4_address: 192.168.70.132
oai-smf:
container_name: "oai-smf"
image: oaisoftwarealliance/oai-smf:develop
image: oaisoftwarealliance/oai-smf:v2.2.1
expose:
- 80/tcp
- 8080/tcp
@@ -130,7 +130,7 @@ services:
ipv4_address: 192.168.70.133
oai-upf:
container_name: "oai-upf"
image: oaisoftwarealliance/oai-upf:develop
image: oaisoftwarealliance/oai-upf:v2.2.1
expose:
- 2152/udp
- 8805/udp

View File

@@ -22,13 +22,50 @@ RUN apt-get update && \
xz-utils \
pkg-config \
libnuma-dev \
python3-pyelftools && \
python3-pyelftools \
libpcre3-dev \
libssh-dev \
libxml2-dev \
libpam0g \
libnuma-dev && \
rm -rf /var/lib/apt/lists/*
RUN rm -Rf /oai-ran
WORKDIR /oai-ran
COPY . .
RUN git clone https://github.com/CESNET/libyang.git && \
cd libyang && \
git checkout v2.1.111 && \
mkdir build && cd build && \
cmake -DENABLE_TESTS=OFF \
-DENABLE_VALGRIND_TESTS=OFF \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_INSTALL_RPATH=/usr/local/lib \
-DPLUGINS_DIR=/usr/local/lib/libyang \
-DPLUGINS_DIR_EXTENSIONS=/usr/local/lib/libyang/extensions \
-DPLUGINS_DIR_TYPES=/usr/local/lib/libyang/types \
-DYANG_MODULE_DIR=/usr/local/share/yang/modules/libyang .. && \
make && \
make install
RUN git clone https://github.com/CESNET/libnetconf2.git && \
cd libnetconf2 && \
git checkout v2.1.37 && \
mkdir build && cd build && \
cmake -DENABLE_TESTS=OFF \
-DENABLE_EXAMPLES=OFF \
-DENABLE_VALGRIND_TESTS=OFF \
-DCLIENT_SEARCH_DIR=/usr/local/share/yang/modules \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_INSTALL_RPATH=/usr/local/lib \
-DLIBYANG_INCLUDE_DIR=/usr/local/include \
-DLIBYANG_LIBRARY=/usr/local/lib/libyang.so \
-DLY_VERSION_PATH=/usr/local/include \
-DYANG_MODULE_DIR=/usr/local/share/yang/modules/libnetconf2 .. && \
make && \
make install
## Download and build DPDK
RUN wget --no-verbose http://fast.dpdk.org/rel/dpdk-24.11.4.tar.xz && \
tar -xf dpdk-24.11.4.tar.xz && \
@@ -53,7 +90,7 @@ RUN /bin/sh oaienv && \
./build_oai \
--ninja --gNB --nrRU \
--build-lib "telnetsrv enbscope uescope nrscope" \
-t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \
-t oran_fhlib_5g_mplane --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION && \
# Mainly to see if the sanitize option was perfectly executed
ldd ran_build/build/nr-softmodem && \

View File

@@ -57,7 +57,8 @@ COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
/oai-ran/cmake_targets/ran_build/build/liboai_transpro.so \
/oai-ran/cmake_targets/ran_build/build/liboran_fhlib_5g.so \
/oai-ran/cmake_targets/ran_build/build/liboran_fhlib_5g_mplane.so \
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
@@ -65,7 +66,16 @@ COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
/usr/local/lib/
/usr/local/lib/libnetconf2.so \
/usr/local/lib/libyang.so \
/usr/local/lib
# default is CUS (no M plane)
RUN ln -s /usr/local/lib/liboran_fhlib_5g.so /usr/local/lib/liboai_transpro.so
COPY --from=gnb-build \
/oai-ran/radio/fhi_72/mplane/yang/models/ \
/oai-ran/radio/fhi_72/mplane/yang/models/
## Libxran library
COPY --from=gnb-build \

View File

@@ -1705,6 +1705,12 @@ static void *ru_thread( void *param ) {
// do RX front-end processing (frequency-shift, dft) if needed
if (ru->feprx) ru->feprx(ru, proc->tti_rx);
if (ru->dft_in_levdB == -1) {
int sigenergy = 0;
for (int aa = 0; aa < ru->nb_rx; aa++)
sigenergy += signal_energy(ru->common.rxdata[aa] + proc->tti_rx * ru->frame_parms->samples_per_tti, 2048);
ru->dft_in_levdB = dB_fixed(sigenergy) + 30;
}
// wakeup all eNB processes waiting for this RU
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_eNBs))==0,"mutex_lock returns %d\n",ret);

View File

@@ -859,7 +859,7 @@ void *ru_thread(void *param)
}
LOG_I(PHY, "Starting IF interface for RU %d, nb_rx %d\n", ru->idx, ru->nb_rx);
AssertFatal(ru->nr_start_if(ru, NULL) == 0, "Could not start the IF device\n");
AssertFatal(ru->nr_start_if(ru) == 0, "Could not start the IF device\n");
} else if (ru->if_south == LOCAL_RF) { // configure RF parameters only
ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
@@ -964,6 +964,12 @@ void *ru_thread(void *param)
break; // nothing to wait for: we have to stop
if (ru->feprx) {
ru->feprx(ru,proc->tti_rx);
if (ru->dft_in_levdB == -1) {
int sigenergy = 0;
for (int aa = 0; aa < ru->nb_rx; aa++)
sigenergy += signal_energy(ru->common.rxdata[aa] + get_samples_slot_timestamp(fp, proc->tti_rx), 2048);
ru->dft_in_levdB = dB_fixed(sigenergy) + 40;
}
LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH);
//LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1);
LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx);
@@ -1011,7 +1017,8 @@ int start_streaming(RU_t *ru) {
return ru->ifdevice.thirdparty_startstreaming(&ru->ifdevice);
}
int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) {
int nr_start_if(struct RU_t_s *ru)
{
if (ru->if_south <= REMOTE_IF5)
for (int i = 0; i < ru->nb_rx; i++)
ru->openair0_cfg.rxbase[i] = ru->common.rxdata[i];
@@ -1019,11 +1026,13 @@ int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) {
return ru->ifdevice.trx_start_func(&ru->ifdevice);
}
int start_rf(RU_t *ru) {
int start_rf(RU_t *ru)
{
return(ru->rfdevice.trx_start_func(&ru->rfdevice));
}
int stop_rf(RU_t *ru) {
int stop_rf(RU_t *ru)
{
if (ru->rfdevice.trx_get_stats_func) {
ru->rfdevice.trx_get_stats_func(&ru->rfdevice);
}

View File

@@ -100,13 +100,6 @@ int chain_offset = 0;
int numerology = 0;
double cpuf;
/* hack: pdcp_run() is required by 4G scheduler which is compiled into
* nr-softmodem because of linker issues */
void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
{
abort();
}
/*------------------------------------------------------------------------*/
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
@@ -443,7 +436,7 @@ int start_L1L2(module_id_t gnb_id)
return 0;
}
static void wait_nfapi_init(char *thread_name)
static void wait_nfapi_init()
{
pthread_mutex_lock( &nfapi_sync_mutex );
@@ -659,7 +652,7 @@ int main( int argc, char **argv ) {
RC.gNB[idx]->if_inst->sl_ahead = sl_ahead;
if (NFAPI_MODE==NFAPI_MODE_PNF) {
wait_nfapi_init("main?");
wait_nfapi_init();
}
if (IS_SOFTMODEM_IMSCOPE_ENABLED || IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) {

View File

@@ -186,11 +186,6 @@ static void set_fp_options(int cell_id, int ru_id)
LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ofdm_offset_divisor %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ofdm_offset_divisor);
}
// Stupid function addition because UE itti messages queues definition is common with eNB
void *rrc_enb_process_msg(void *notUsed) {
return NULL;
}
static bool stop_immediately = false;
static void trigger_stop(int sig)
{

View File

@@ -155,7 +155,8 @@ void softmodem_verify_mode(const softmodem_params_t *p)
AssertFatal(num_modes == 1, "--phy-test, --do-ra, and --nsa are mutually exclusive\n");
}
void softmodem_printresources(int sig, telnet_printfunc_t pf) {
static void softmodem_printresources(telnet_printfunc_t pf)
{
struct rusage usage;
struct timespec stop;
@@ -163,7 +164,6 @@ void softmodem_printresources(int sig, telnet_printfunc_t pf) {
uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds
int st = getrusage(RUSAGE_SELF,&usage);
if (!st) {
pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600)));
@@ -195,7 +195,7 @@ void signal_handler(int sig) {
exit(-1);
} else {
if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL)
softmodem_printresources(sig,(telnet_printfunc_t)printf);
softmodem_printresources((telnet_printfunc_t)printf);
if (sig != SOFTMODEM_RTSIGNAL) {
printf("Linux signal %s...\n",strsignal(sig));
exit_function(__FILE__, __FUNCTION__, __LINE__, "softmodem starting exit procedure\n", OAI_EXIT_NORMAL);

View File

@@ -8,6 +8,12 @@
#include "stdint.h"
#include "nfapi/open-nFAPI/fapi/inc/nr_fapi.h"
/* Number of bytes needed to hold n bits (ceiling division). */
static inline uint16_t nr_bits_to_bytes(uint16_t bits)
{
return (bits + 7) / 8;
}
bool eq_dl_tti_request(const nfapi_nr_dl_tti_request_t *a, const nfapi_nr_dl_tti_request_t *b);
bool eq_ul_tti_request(const nfapi_nr_ul_tti_request_t *a, const nfapi_nr_ul_tti_request_t *b);
bool eq_slot_indication(const nfapi_nr_slot_indication_scf_t *a, const nfapi_nr_slot_indication_scf_t *b);

View File

@@ -3,6 +3,7 @@
*/
#include "nr_fapi.h"
#include "nr_fapi_p7.h"
#include "nr_fapi_p7_utils.h"
#include "nr_nfapi_p7.h"
#include "debug.h"
@@ -1805,7 +1806,7 @@ static uint8_t pack_nr_uci_pusch(void *tlv, uint8_t **ppWritePackedMsg, uint8_t
return 0;
if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end))
return 0;
const uint16_t harq_len = (value->harq.harq_bit_len / 8) + 1;
const uint16_t harq_len = nr_bits_to_bytes(value->harq.harq_bit_len);
if (!pusharray8(value->harq.harq_payload, harq_len, harq_len, ppWritePackedMsg, end))
return 0;
}
@@ -1815,7 +1816,7 @@ static uint8_t pack_nr_uci_pusch(void *tlv, uint8_t **ppWritePackedMsg, uint8_t
return 0;
if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end))
return 0;
const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part1.csi_part1_bit_len);
if (!pusharray8(value->csi_part1.csi_part1_payload, csi_len, csi_len, ppWritePackedMsg, end))
return 0;
}
@@ -1825,7 +1826,7 @@ static uint8_t pack_nr_uci_pusch(void *tlv, uint8_t **ppWritePackedMsg, uint8_t
return 0;
if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end))
return 0;
const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part2.csi_part2_bit_len);
if (!pusharray8(value->csi_part2.csi_part2_payload, csi_len, csi_len, ppWritePackedMsg, end))
return 0;
}
@@ -1894,7 +1895,7 @@ static uint8_t pack_nr_uci_pucch_2_3_4(void *tlv, uint8_t **ppWritePackedMsg, ui
if (value->pduBitmap & 0x01) { // SR
if (!push16(value->sr.sr_bit_len, ppWritePackedMsg, end))
return 0;
const uint16_t sr_len = value->sr.sr_bit_len / 8 + 1;
const uint16_t sr_len = nr_bits_to_bytes(value->sr.sr_bit_len);
if (!pusharray8(value->sr.sr_payload, sr_len, sr_len, ppWritePackedMsg, end))
return 0;
}
@@ -1904,7 +1905,7 @@ static uint8_t pack_nr_uci_pucch_2_3_4(void *tlv, uint8_t **ppWritePackedMsg, ui
return 0;
if (!push16(value->harq.harq_bit_len, ppWritePackedMsg, end))
return 0;
const uint16_t harq_len = value->harq.harq_bit_len / 8 + 1;
const uint16_t harq_len = nr_bits_to_bytes(value->harq.harq_bit_len);
if (!pusharray8(value->harq.harq_payload, harq_len, harq_len, ppWritePackedMsg, end))
return 0;
}
@@ -1914,7 +1915,7 @@ static uint8_t pack_nr_uci_pucch_2_3_4(void *tlv, uint8_t **ppWritePackedMsg, ui
return 0;
if (!push16(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end))
return 0;
const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part1.csi_part1_bit_len);
if (!pusharray8(value->csi_part1.csi_part1_payload, csi_len, csi_len, ppWritePackedMsg, end))
return 0;
}
@@ -1924,7 +1925,7 @@ static uint8_t pack_nr_uci_pucch_2_3_4(void *tlv, uint8_t **ppWritePackedMsg, ui
return 0;
if (!push16(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end))
return 0;
const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part2.csi_part2_bit_len);
if (!pusharray8(value->csi_part2.csi_part2_payload, csi_len, csi_len, ppWritePackedMsg, end))
return 0;
}
@@ -2005,7 +2006,7 @@ static uint8_t unpack_nr_uci_pusch(nfapi_nr_uci_pusch_pdu_t *value, uint8_t **pp
return 0;
if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end))
return 0;
const uint16_t harq_len = value->harq.harq_bit_len / 8 + 1;
const uint16_t harq_len = nr_bits_to_bytes(value->harq.harq_bit_len);
value->harq.harq_payload = calloc(harq_len, sizeof(*value->harq.harq_payload));
if (value->harq.harq_payload == NULL) {
@@ -2022,7 +2023,7 @@ static uint8_t unpack_nr_uci_pusch(nfapi_nr_uci_pusch_pdu_t *value, uint8_t **pp
return 0;
if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end))
return 0;
const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part1.csi_part1_bit_len);
value->csi_part1.csi_part1_payload = calloc(csi_len, sizeof(*value->csi_part1.csi_part1_payload));
if (value->csi_part1.csi_part1_payload == NULL) {
@@ -2039,7 +2040,7 @@ static uint8_t unpack_nr_uci_pusch(nfapi_nr_uci_pusch_pdu_t *value, uint8_t **pp
return 0;
if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end))
return 0;
const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part2.csi_part2_bit_len);
value->csi_part2.csi_part2_payload = calloc(csi_len, sizeof(*value->csi_part2.csi_part2_payload));
if (value->csi_part2.csi_part2_payload == NULL) {
@@ -2061,13 +2062,13 @@ static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t *valu
&& pull8(ppReadPackedMsg, &value->ul_cqi, end) && pull16(ppReadPackedMsg, &value->timing_advance, end)
&& pull16(ppReadPackedMsg, &value->rssi, end)))
return 0;
if (value->pduBitmap & 0x01) { // SR
if (!(pull8(ppReadPackedMsg, &value->sr.sr_indication, end) && pull8(ppReadPackedMsg, &value->sr.sr_confidence_level, end)))
return 0;
}
if (((value->pduBitmap >> 1) & 0x01)) { // HARQ
if (!(pull8(ppReadPackedMsg, &value->harq.num_harq, end) && pull8(ppReadPackedMsg, &value->harq.harq_confidence_level, end)))
return 0;
if (value->harq.num_harq > 0) {
@@ -2102,7 +2103,7 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *
if (value->pduBitmap & 0x01) { // SR
if (!pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end))
return 0;
const uint16_t sr_len = value->sr.sr_bit_len / 8 + 1;
const uint16_t sr_len = nr_bits_to_bytes(value->sr.sr_bit_len);
value->sr.sr_payload = calloc(sr_len, sizeof(*value->sr.sr_payload));
if (value->sr.sr_payload == NULL) {
@@ -2119,7 +2120,7 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *
return 0;
if (!pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end))
return 0;
const uint16_t harq_len = value->harq.harq_bit_len / 8 + 1;
const uint16_t harq_len = nr_bits_to_bytes(value->harq.harq_bit_len);
value->harq.harq_payload = calloc(harq_len, sizeof(*value->harq.harq_payload));
if (value->harq.harq_payload == NULL) {
@@ -2136,7 +2137,7 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *
return 0;
if (!pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end))
return 0;
const uint16_t csi_len = value->csi_part1.csi_part1_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part1.csi_part1_bit_len);
value->csi_part1.csi_part1_payload = calloc(csi_len, sizeof(*value->csi_part1.csi_part1_payload));
if (value->csi_part1.csi_part1_payload == NULL) {
@@ -2153,7 +2154,7 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *
return 0;
if (!pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end))
return 0;
const uint16_t csi_len = value->csi_part2.csi_part2_bit_len / 8 + 1;
const uint16_t csi_len = nr_bits_to_bytes(value->csi_part2.csi_part2_bit_len);
value->csi_part2.csi_part2_payload = calloc(csi_len, sizeof(*value->csi_part2.csi_part2_payload));
if (value->csi_part2.csi_part2_payload == NULL) {

View File

@@ -585,7 +585,7 @@ bool eq_crc_indication_CRC(const nfapi_nr_crc_t *a, const nfapi_nr_crc_t *b)
EQ(a->tb_crc_status, b->tb_crc_status);
EQ(a->num_cb, b->num_cb);
if (a->num_cb > 0) {
for (int cb = 0; cb < (a->num_cb / 8) + 1; ++cb) {
for (int cb = 0; cb < nr_bits_to_bytes(a->num_cb); ++cb) {
EQ(a->cb_crc_status[cb], b->cb_crc_status[cb]);
}
}
@@ -618,7 +618,7 @@ bool eq_uci_indication_sr_pdu_0_1(const nfapi_nr_sr_pdu_0_1_t *a, const nfapi_nr
bool eq_uci_indication_sr_pdu_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *a, const nfapi_nr_sr_pdu_2_3_4_t *b)
{
EQ(a->sr_bit_len, b->sr_bit_len);
for (int i = 0; i < (a->sr_bit_len / 8) + 1; ++i) {
for (int i = 0; i < nr_bits_to_bytes(a->sr_bit_len); ++i) {
EQ(a->sr_payload[i], b->sr_payload[i]);
}
return true;
@@ -638,7 +638,7 @@ bool eq_uci_indication_harq_pdu_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *a, const
{
EQ(a->harq_crc, b->harq_crc);
EQ(a->harq_bit_len, b->harq_bit_len);
for (int i = 0; i < (a->harq_bit_len / 8) + 1; ++i) {
for (int i = 0; i < nr_bits_to_bytes(a->harq_bit_len); ++i) {
EQ(a->harq_payload[i], b->harq_payload[i]);
}
return true;
@@ -648,7 +648,7 @@ bool eq_uci_indication_csi_part1(const nfapi_nr_csi_part1_pdu_t *a, const nfapi_
{
EQ(a->csi_part1_crc, b->csi_part1_crc);
EQ(a->csi_part1_bit_len, b->csi_part1_bit_len);
for (int i = 0; i < (a->csi_part1_bit_len / 8) + 1; ++i) {
for (int i = 0; i < nr_bits_to_bytes(a->csi_part1_bit_len); ++i) {
EQ(a->csi_part1_payload[i], b->csi_part1_payload[i]);
}
return true;
@@ -658,7 +658,7 @@ bool eq_uci_indication_csi_part2(const nfapi_nr_csi_part2_pdu_t *a, const nfapi_
{
EQ(a->csi_part2_crc, b->csi_part2_crc);
EQ(a->csi_part2_bit_len, b->csi_part2_bit_len);
for (int i = 0; i < (a->csi_part2_bit_len / 8) + 1; ++i) {
for (int i = 0; i < nr_bits_to_bytes(a->csi_part2_bit_len); ++i) {
EQ(a->csi_part2_payload[i], b->csi_part2_payload[i]);
}
return true;
@@ -1583,7 +1583,7 @@ void copy_crc_indication_CRC(const nfapi_nr_crc_t *src, nfapi_nr_crc_t *dst)
dst->tb_crc_status = src->tb_crc_status;
dst->num_cb = src->num_cb;
if (dst->num_cb > 0) {
const uint16_t cb_len = (dst->num_cb / 8) + 1;
const uint16_t cb_len = nr_bits_to_bytes(dst->num_cb);
dst->cb_crc_status = calloc(cb_len, sizeof(uint8_t));
for (int cb = 0; cb < cb_len; ++cb) {
dst->cb_crc_status[cb] = src->cb_crc_status[cb];
@@ -1641,7 +1641,7 @@ void copy_uci_indication_sr_pdu_0_1(const nfapi_nr_sr_pdu_0_1_t *src, nfapi_nr_s
void copy_uci_indication_sr_pdu_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *src, nfapi_nr_sr_pdu_2_3_4_t *dst)
{
dst->sr_bit_len = src->sr_bit_len;
const uint16_t sr_len = (dst->sr_bit_len / 8) + 1;
const uint16_t sr_len = nr_bits_to_bytes(dst->sr_bit_len);
dst->sr_payload = calloc(sr_len, sizeof(*dst->sr_payload));
for (int i = 0; i < sr_len; ++i) {
dst->sr_payload[i] = src->sr_payload[i];
@@ -1661,7 +1661,7 @@ void copy_uci_indication_harq_pdu_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *src, nf
{
dst->harq_crc = src->harq_crc;
dst->harq_bit_len = src->harq_bit_len;
const uint16_t harq_length = (dst->harq_bit_len / 8) + 1;
const uint16_t harq_length = nr_bits_to_bytes(dst->harq_bit_len);
dst->harq_payload = calloc(harq_length, sizeof(*dst->harq_payload));
for (int i = 0; i < harq_length; ++i) {
dst->harq_payload[i] = src->harq_payload[i];
@@ -1672,7 +1672,7 @@ void copy_uci_indication_csi_part1(const nfapi_nr_csi_part1_pdu_t *src, nfapi_nr
{
dst->csi_part1_crc = src->csi_part1_crc;
dst->csi_part1_bit_len = src->csi_part1_bit_len;
const uint16_t payload_length = (dst->csi_part1_bit_len / 8) + 1;
const uint16_t payload_length = nr_bits_to_bytes(dst->csi_part1_bit_len);
dst->csi_part1_payload = calloc(payload_length, sizeof(*dst->csi_part1_payload));
for (int i = 0; i < payload_length; ++i) {
dst->csi_part1_payload[i] = src->csi_part1_payload[i];
@@ -1683,7 +1683,7 @@ void copy_uci_indication_csi_part2(const nfapi_nr_csi_part2_pdu_t *src, nfapi_nr
{
dst->csi_part2_crc = src->csi_part2_crc;
dst->csi_part2_bit_len = src->csi_part2_bit_len;
const uint16_t payload_length = (dst->csi_part2_bit_len / 8) + 1;
const uint16_t payload_length = nr_bits_to_bytes(dst->csi_part2_bit_len);
dst->csi_part2_payload = calloc(payload_length, sizeof(*dst->csi_part2_payload));
for (int i = 0; i < payload_length; ++i) {
dst->csi_part2_payload[i] = src->csi_part2_payload[i];
@@ -1818,13 +1818,13 @@ size_t get_uci_indication_size(const nfapi_nr_uci_indication_t *msg)
// HARQ payload, CSI Part 1 and 2 are conditionally allocated
if ((uci_pdu->pusch_pdu.pduBitmap >> 1) & 0x01) {
total_size += uci_pdu->pusch_pdu.harq.harq_bit_len / 8 + 1;
total_size += nr_bits_to_bytes(uci_pdu->pusch_pdu.harq.harq_bit_len);
}
if ((uci_pdu->pusch_pdu.pduBitmap >> 2) & 0x01) {
total_size += uci_pdu->pusch_pdu.csi_part1.csi_part1_bit_len / 8 + 1;
total_size += nr_bits_to_bytes(uci_pdu->pusch_pdu.csi_part1.csi_part1_bit_len);
}
if ((uci_pdu->pusch_pdu.pduBitmap >> 3) & 0x01) {
total_size += uci_pdu->pusch_pdu.csi_part2.csi_part2_bit_len / 8 + 1;
total_size += nr_bits_to_bytes(uci_pdu->pusch_pdu.csi_part2.csi_part2_bit_len);
}
break;
@@ -1838,16 +1838,16 @@ size_t get_uci_indication_size(const nfapi_nr_uci_indication_t *msg)
// SR, HARQ, CSI Part 1, and CSI Part 2 are conditionally allocated
if (uci_pdu->pucch_pdu_format_2_3_4.pduBitmap & 0x01) {
total_size += uci_pdu->pucch_pdu_format_2_3_4.sr.sr_bit_len / 8 + 1;
total_size += nr_bits_to_bytes(uci_pdu->pucch_pdu_format_2_3_4.sr.sr_bit_len);
}
if ((uci_pdu->pucch_pdu_format_2_3_4.pduBitmap >> 1) & 0x01) {
total_size += uci_pdu->pucch_pdu_format_2_3_4.harq.harq_bit_len / 8 + 1;
total_size += nr_bits_to_bytes(uci_pdu->pucch_pdu_format_2_3_4.harq.harq_bit_len);
}
if ((uci_pdu->pucch_pdu_format_2_3_4.pduBitmap >> 2) & 0x01) {
total_size += uci_pdu->pucch_pdu_format_2_3_4.csi_part1.csi_part1_bit_len / 8 + 1;
total_size += nr_bits_to_bytes(uci_pdu->pucch_pdu_format_2_3_4.csi_part1.csi_part1_bit_len);
}
if ((uci_pdu->pucch_pdu_format_2_3_4.pduBitmap >> 3) & 0x01) {
total_size += uci_pdu->pucch_pdu_format_2_3_4.csi_part2.csi_part2_bit_len / 8 + 1;
total_size += nr_bits_to_bytes(uci_pdu->pucch_pdu_format_2_3_4.csi_part2.csi_part2_bit_len);
}
break;
@@ -1993,7 +1993,7 @@ static void dump_dl_dci_pdu(const nfapi_nr_dl_dci_pdu_t *pdu, int depth)
INDENTED_PRINTF("powerControlOffsetSS = %d\n", pdu->powerControlOffsetSS);
INDENTED_PRINTF("PayloadSizeBits = %d\n", pdu->PayloadSizeBits);
INDENTED_PRINTF("Payload = ");
for (int i = 0; i < (pdu->PayloadSizeBits + 7) / 8; ++i) {
for (int i = 0; i < nr_bits_to_bytes(pdu->PayloadSizeBits); ++i) {
printf("0x%02x ", pdu->Payload[i]);
}
printf("\n");
@@ -2632,7 +2632,7 @@ void dump_crc_indication(const nfapi_nr_crc_indication_t *msg)
INDENTED_PRINTF("HarqID = 0x%02x\n", crc->harq_id);
INDENTED_PRINTF("TbCrcStatus = 0x%02x\n", crc->tb_crc_status);
INDENTED_PRINTF("NumCb = 0x%02x\n", crc->num_cb);
const uint16_t cb_len = (crc->num_cb / 8) + 1; // length is ceil(NumCb/8)
const uint16_t cb_len = nr_bits_to_bytes(crc->num_cb); // length is ceil(NumCb/8)
INDENTED_PRINTF("CbCrcStatus =\n");
for (int j = 0; j < cb_len; j++) {
printf("%02x ", crc->cb_crc_status[j]);
@@ -2650,7 +2650,7 @@ static void dump_harq_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *harq, int depth)
INDENTED_PRINTF("HARQ CRC = %01x\n", harq->harq_crc);
INDENTED_PRINTF("HARQ Bit Length = %d\n", harq->harq_bit_len);
INDENTED_PRINTF("HARQ Payload = ");
for (int i = 0; i < harq->harq_bit_len / 8 + 1; i++) {
for (int i = 0; i < nr_bits_to_bytes(harq->harq_bit_len); i++) {
printf("%x ", harq->harq_payload[i]);
}
printf("\n");
@@ -2661,7 +2661,7 @@ static void dump_csi_part_1(const nfapi_nr_csi_part1_pdu_t *csi, int depth)
INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part1_crc);
INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part1_bit_len);
INDENTED_PRINTF("CSI Part 1 Payload = ");
for (int i = 0; i < csi->csi_part1_bit_len / 8 + 1; i++) {
for (int i = 0; i < nr_bits_to_bytes(csi->csi_part1_bit_len); i++) {
printf("%x ", csi->csi_part1_payload[i]);
}
printf("\n");
@@ -2672,7 +2672,7 @@ static void dump_csi_part_2(const nfapi_nr_csi_part2_pdu_t *csi, int depth)
INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part2_crc);
INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part2_bit_len);
INDENTED_PRINTF("CSI Part 1 Payload = ");
for (int i = 0; i < csi->csi_part2_bit_len / 8 + 1; i++) {
for (int i = 0; i < nr_bits_to_bytes(csi->csi_part2_bit_len); i++) {
printf("%x ", csi->csi_part2_payload[i]);
}
printf("\n");
@@ -2740,7 +2740,7 @@ static void dump_sr_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *sr, int depth)
{
INDENTED_PRINTF("SR Bit Length = %d\n", sr->sr_bit_len);
INDENTED_PRINTF("SR Payload ");
for (int i = 0; i < sr->sr_bit_len / 8 + 1; i++) {
for (int i = 0; i < nr_bits_to_bytes(sr->sr_bit_len); i++) {
printf("%x ", sr->sr_payload[i]);
}
printf("\n");

View File

@@ -14,8 +14,8 @@ static void fill_uci_indication_sr_pdu_0_1(nfapi_nr_sr_pdu_0_1_t *pdu)
static void fill_uci_indication_sr_pdu_2_3_4(nfapi_nr_sr_pdu_2_3_4_t *pdu)
{
pdu->sr_bit_len = rand16_range(1, 8);
pdu->sr_payload = calloc(((pdu->sr_bit_len / 8) + 1), sizeof(*pdu->sr_payload));
for (int i = 0; i < (pdu->sr_bit_len / 8) + 1; ++i) {
pdu->sr_payload = calloc(nr_bits_to_bytes(pdu->sr_bit_len), sizeof(*pdu->sr_payload));
for (int i = 0; i < nr_bits_to_bytes(pdu->sr_bit_len); ++i) {
pdu->sr_payload[i] = rand8();
}
}
@@ -33,8 +33,8 @@ static void fill_uci_indication_harq_pdu_2_3_4(nfapi_nr_harq_pdu_2_3_4_t *pdu)
{
pdu->harq_crc = rand8_range(0, 2);
pdu->harq_bit_len = rand16_range(1, 1706);
pdu->harq_payload = calloc(((pdu->harq_bit_len / 8) + 1), sizeof(*pdu->harq_payload));
for (int i = 0; i < (pdu->harq_bit_len / 8) + 1; ++i) {
pdu->harq_payload = calloc(nr_bits_to_bytes(pdu->harq_bit_len), sizeof(*pdu->harq_payload));
for (int i = 0; i < nr_bits_to_bytes(pdu->harq_bit_len); ++i) {
pdu->harq_payload[i] = rand8();
}
}
@@ -43,8 +43,8 @@ static void fill_uci_indication_csi_part1(nfapi_nr_csi_part1_pdu_t *pdu)
{
pdu->csi_part1_crc = rand8_range(0, 2);
pdu->csi_part1_bit_len = rand16_range(1, 1706);
pdu->csi_part1_payload = calloc(((pdu->csi_part1_bit_len / 8) + 1), sizeof(*pdu->csi_part1_payload));
for (int i = 0; i < (pdu->csi_part1_bit_len / 8) + 1; ++i) {
pdu->csi_part1_payload = calloc(nr_bits_to_bytes(pdu->csi_part1_bit_len), sizeof(*pdu->csi_part1_payload));
for (int i = 0; i < nr_bits_to_bytes(pdu->csi_part1_bit_len); ++i) {
pdu->csi_part1_payload[i] = rand8();
}
}
@@ -53,8 +53,8 @@ static void fill_uci_indication_csi_part2(nfapi_nr_csi_part2_pdu_t *pdu)
{
pdu->csi_part2_crc = rand8_range(0, 2);
pdu->csi_part2_bit_len = rand16_range(1, 1706);
pdu->csi_part2_payload = calloc(((pdu->csi_part2_bit_len / 8) + 1), sizeof(*pdu->csi_part2_payload));
for (int i = 0; i < (pdu->csi_part2_bit_len / 8) + 1; ++i) {
pdu->csi_part2_payload = calloc(nr_bits_to_bytes(pdu->csi_part2_bit_len), sizeof(*pdu->csi_part2_payload));
for (int i = 0; i < nr_bits_to_bytes(pdu->csi_part2_bit_len); ++i) {
pdu->csi_part2_payload[i] = rand8();
}
}

View File

@@ -29,7 +29,6 @@
* \param f2 input interleaved segment, 8 bits from 8 segments per byte
* interleaved with E2 if there was a E shift in the segment group
* \param E2 number of bits per segment in f2
* \param Eshift flag indicating if there was a E shift within the segment group
* \param E2_first_segment index of the first segment of size E2 if there is a E shift in the segment group
* \param nb_segments number of segments in the group
* \param output nrLDPC_coding_segment_encoder with concatenated segments and packed bits
@@ -39,7 +38,6 @@ static void write_task_output(uint8_t *f,
uint32_t E,
uint8_t *f2,
uint32_t E2,
bool Eshift,
uint32_t E2_first_segment,
uint32_t nb_segments,
uint8_t *output,
@@ -173,9 +171,7 @@ static void write_task_output(uint8_t *f,
Eoffset2 += E2;
}
output_p++;
}
}
#endif
}
@@ -441,12 +437,10 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
unsigned int macro_segment_end = (C > macro_segment + 8) ? macro_segment + 8 : C;
const uint32_t E = nrLDPC_TB_encoding_parameters->segments[macro_segment].E;
uint32_t E2 = E, E2_first_segment = macro_segment_end - macro_segment;
bool Eshift = false;
uint32_t Emax = E;
for (int s = macro_segment; s < macro_segment_end; s++) {
if (nrLDPC_TB_encoding_parameters->segments[s].E != E) {
E2 = nrLDPC_TB_encoding_parameters->segments[s].E;
Eshift = true;
E2_first_segment = s-macro_segment;
if(E2 > Emax)
Emax = E2;
@@ -464,7 +458,6 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
E,
&f2[nbTasks + j][0],
E2,
Eshift,
E2_first_segment,
macro_segment_end - macro_segment,
nrLDPC_TB_encoding_parameters->output,

View File

@@ -80,7 +80,7 @@
#include "ldpc_BG2_Zc80_byte.c"
#include "ldpc_BG2_Zc72_byte.c"
static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG,short Zc,short Kb, int simd_size, int ncols)
static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG, short Zc, int simd_size, int ncols)
{
unsigned char c[2 * 22 * Zc * simd_size] __attribute__((aligned(64))); //double size matrix of c
for (int i1 = 0; i1 < ncols; i1++) {
@@ -198,6 +198,3 @@ static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG,sho
} else
AssertFatal(false, "BG %d is not supported\n", BG);
}

View File

@@ -175,7 +175,7 @@ int LDPCencoder(uint8_t **input, uint8_t *output, encoder_implemparams_t *impp)
if(impp->tprep != NULL) stop_meas(impp->tprep);
//parity check part
if(impp->tparity != NULL) start_meas(impp->tparity);
encode_parity_check_part_optim(cc, dd, BG, Zc, Kb, simd_size, ncols);
encode_parity_check_part_optim(cc, dd, BG, Zc, simd_size, ncols);
if(impp->tparity != NULL) stop_meas(impp->tparity);
}
else {

View File

@@ -164,6 +164,7 @@ int phy_init_RU(RU_t *ru) {
} // !=IF5
ru->common.sync_corr = (uint32_t *)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_tti );
ru->dft_in_levdB = -1;
return(0);
}

View File

@@ -102,6 +102,7 @@ void nr_phy_init_RU(RU_t *ru)
LOG_D(PHY, "[INIT] %s() ru->num_gNB:%d \n", __FUNCTION__, ru->num_gNB);
} // !=IF5
ru->dft_in_levdB = -1;
}
void nr_phy_free_RU(RU_t *ru)

View File

@@ -52,7 +52,10 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms,
break;
}
if (len)
dft(get_dft(len), (int16_t *)lte_eNB_srs->srs_ch_estimates[aa], (int16_t *)lte_eNB_srs->srs_ch_estimates_time[aa], 1);
dft(get_dft(len),
(int16_t *)lte_eNB_srs->srs_ch_estimates[aa],
(int16_t *)lte_eNB_srs->srs_ch_estimates_time[aa],
get_dft_scaling(len, 0));
#ifdef DEBUG_PHY
sprintf(fname,"srs_ch_estimates_time_%d%d.m",ind,aa);
sprintf(vname,"srs_time_%d%d",ind,aa);

View File

@@ -393,7 +393,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue,
idft(get_idft(s),
(int16_t *)&dl_ch_estimates[(p << 1) + aarx][8],
(int16_t *)vars->dl_ch_estimates_time[eNB_offset][(p << 1) + aarx],
1);
get_idft_scaling(s, 1));
}
}
}

View File

@@ -727,7 +727,7 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *ue,
(int16_t *)&tmp[8],
(int16_t *)ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]]
.dl_ch_estimates_time[eNB_offset][aa],
1);
get_idft_scaling(len, 1));
}
}
return(0);
@@ -838,7 +838,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue,
idft(get_idft(len),
(int16_t *)&tmp[8],
(int16_t *)ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[0][aa],
1);
get_idft_scaling(len, 1));
}
}
return(0);

View File

@@ -39,7 +39,7 @@ static void doIdft(int size, short *in, short *out) {
LOG_E(PHY, "Unknown N_RB_DL %d\n", size);
return;
}
idft(get_idft(len), in, out, 1);
idft(get_idft(len), in, out, get_idft_scaling(len, 0));
}
static void copyPrimary( c16_t *out, struct complex16 *in, int ofdmSize) {
@@ -185,8 +185,10 @@ int ru_sync_time_init(RU_t *ru) { // LTE_UE_COMMON *common_vars
LOG_E(PHY, "Unknown N_RB_DL %d\n", ru->frame_parms->N_RB_DL);
return -1;
}
idft(get_idft(len), (int16_t *)&dmrsp[0][3 * ru->frame_parms->ofdm_symbol_size], ru->dmrssync,
1); /// complex output
idft(get_idft(len),
(int16_t *)&dmrsp[0][3 * ru->frame_parms->ofdm_symbol_size],
ru->dmrssync,
get_idft_scaling(len, 0)); /// complex output
return(0);
}

View File

@@ -50,9 +50,7 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq)
while (1) {
//compute frequency-domain representation of 6144-sample chunk
dft(DFT_6144,(int16_t *)rxp,
sp,1);
dft(DFT_6144, (int16_t *)rxp, sp, get_dft_scaling(6144, 0));
/*
printf("i %d: sp %p\n",i,sp);
@@ -196,7 +194,7 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq)
}
// ifft, accumulate energy over two half-frames
idft(IDFT_256,(int16_t*)autocorr0,(int16_t*)tmp_t,1);
idft(IDFT_256, (int16_t *)autocorr0, (int16_t *)tmp_t, get_idft_scaling(256, 1));
/*
if (i==12288) {
sprintf(fname,"corr256F_%d.m",abs(f));
@@ -214,12 +212,12 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq)
for (re=0; re<(256/4); re++)
autocorr0_t[re] = simde_mm_add_epi32(autocorr0_t[re], simde_mm_madd_epi16(tmp_t[re], tmp_t[re]));
idft(IDFT_256,(int16_t*)autocorr1,(int16_t*)tmp_t,1);
idft(IDFT_256, (int16_t *)autocorr1, (int16_t *)tmp_t, get_idft_scaling(256, 1));
for (re=0; re<(256/4); re++)
autocorr1_t[re] = simde_mm_add_epi32(autocorr1_t[re], simde_mm_madd_epi16(tmp_t[re], tmp_t[re]));
idft(IDFT_256,(int16_t*)autocorr2,(int16_t*)tmp_t,1);
idft(IDFT_256, (int16_t *)autocorr2, (int16_t *)tmp_t, get_idft_scaling(256, 1));
for (re=0; re<(256/4); re++)
autocorr2_t[re] = simde_mm_add_epi32(autocorr2_t[re], simde_mm_madd_epi16(tmp_t[re], tmp_t[re]));

View File

@@ -169,7 +169,7 @@ int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
LOG_E(PHY, "Unknown N_RB_DL %d\n", frame_parms->N_RB_DL);
return -1;
}
idft(get_idft(len), (int16_t *)temp_in_ifft_0, (int16_t *)ul_ch_estimates_time[aa], 1);
idft(get_idft(len), (int16_t *)temp_in_ifft_0, (int16_t *)ul_ch_estimates_time[aa], get_idft_scaling(len, 1));
#if T_TRACER
if (aa == 0)
@@ -380,7 +380,7 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
LOG_E(PHY, "Unknown N_RB_DL %d\n", frame_parms->N_RB_DL);
return -1;
}
idft(get_idft(len), (int16_t *)temp_in_ifft_0, (int16_t *)ul_ch_estimates_time[aa], 1);
idft(get_idft(len), (int16_t *)temp_in_ifft_0, (int16_t *)ul_ch_estimates_time[aa], get_idft_scaling(len, 1));
#if T_TRACER
if (aa == 0)

View File

@@ -296,9 +296,9 @@ void rx_prach0(PHY_VARS_eNB *eNB,
break;
}
dft(get_dft(fft_size), prach2, rxsigF[aa], 1);
dft(get_dft(fft_size), prach2, rxsigF[aa], get_dft_scaling(fft_size, ru->dft_in_levdB));
if (prach_fmt > 1 && prach_fmt != 4)
dft(get_dft(fft_size), prach2 + 2 * fft_size, rxsigF[aa] + 2 * fft_size, 1);
dft(get_dft(fft_size), prach2 + 2 * fft_size, rxsigF[aa] + 2 * fft_size, get_dft_scaling(fft_size, ru->dft_in_levdB));
k = (12*n_ra_prb) - 6*fp->N_RB_UL;
@@ -516,13 +516,13 @@ void rx_prach0(PHY_VARS_eNB *eNB,
// Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139)
if (N_ZC == 839) {
log2_ifft_size = 10;
idft(IDFT_1024,(int16_t*)prachF,prach_ifft_tmp,1);
idft(IDFT_1024, (int16_t *)prachF, prach_ifft_tmp, get_idft_scaling(1024, 1));
// compute energy and accumulate over receive antennas and repetitions for BR
for (i=0; i<2048; i++)
prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[i<<1] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>9;
} else {
idft(IDFT_256,(int16_t*)prachF,prach_ifft_tmp,1);
idft(IDFT_256, (int16_t *)prachF, prach_ifft_tmp, get_idft_scaling(256, 1));
log2_ifft_size = 8;
// compute energy and accumulate over receive antennas and repetitions for BR

View File

@@ -104,9 +104,9 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) {
dft_size_idx_t dftsize = get_dft(Msc_PUSCH);
switch (Msc_PUSCH) {
case 12:
dft(dftsize, (int16_t *)idft_in0, (int16_t *)idft_out0, 0);
dft(dftsize, (int16_t *)idft_in1, (int16_t *)idft_out1, 0);
dft(dftsize, (int16_t *)idft_in2, (int16_t *)idft_out2, 0);
dft(dftsize, (int16_t *)idft_in0, (int16_t *)idft_out0, (uint32_t *)0);
dft(dftsize, (int16_t *)idft_in1, (int16_t *)idft_out1, (uint32_t *)0);
dft(dftsize, (int16_t *)idft_in2, (int16_t *)idft_out2, (uint32_t *)0);
norm128 = simde_mm_set1_epi16(9459);
for (i=0; i<12; i++) {
@@ -118,9 +118,9 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) {
break;
default:
dft(dftsize, idft_in0, idft_out0, 1);
dft(dftsize, idft_in1, idft_out1, 1);
dft(dftsize, idft_in2, idft_out2, 1);
dft(dftsize, idft_in0, idft_out0, (uint32_t *)1);
dft(dftsize, idft_in1, idft_out1, (uint32_t *)1);
dft(dftsize, idft_in2, idft_out2, (uint32_t *)1);
}
for (i=0,ip=0; i<Msc_PUSCH; i++,ip+=4) {

View File

@@ -319,12 +319,12 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
break;
}
if (prach_fmt == 4) {
idft(get_idft(len), prachF, prach2, 1);
idft(get_idft(len), prachF, prach2, get_idft_scaling(len, 0));
// TODO: account for repeated format in dft output
memmove(prach, prach + 2 * len, Ncp << 2);
prach_len = len + Ncp;
} else {
idft(get_idft(len), prachF, prach2, 1);
idft(get_idft(len), prachF, prach2, get_idft_scaling(len, 0));
memmove(prach, prach + 2 * len, Ncp << 2);
prach_len = len + Ncp;
if (prach_fmt > 1) {

View File

@@ -76,9 +76,9 @@ void dft_lte(int32_t *z,struct complex16 *input, int32_t Msc_PUSCH, uint8_t Nsym
switch (Msc_PUSCH) {
case 12:
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, 0);
dft(dftsize, (int16_t *)dft_in1, (int16_t *)dft_out1, 0);
dft(dftsize, (int16_t *)dft_in2, (int16_t *)dft_out2, 0);
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, (uint32_t *)0);
dft(dftsize, (int16_t *)dft_in1, (int16_t *)dft_out1, (uint32_t *)0);
dft(dftsize, (int16_t *)dft_in2, (int16_t *)dft_out2, (uint32_t *)0);
norm128 = simde_mm_set1_epi16(9459);
for (i = 0; i < 12; i++) {
((simde__m128i *)dft_out0)[i] = simde_mm_slli_epi16(simde_mm_mulhi_epi16(((simde__m128i *)dft_out0)[i], norm128), 1);
@@ -89,9 +89,9 @@ void dft_lte(int32_t *z,struct complex16 *input, int32_t Msc_PUSCH, uint8_t Nsym
break;
default:
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, 1);
dft(dftsize, (int16_t *)dft_in1, (int16_t *)dft_out1, 1);
dft(dftsize, (int16_t *)dft_in2, (int16_t *)dft_out2, 1);
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, (uint32_t *)1);
dft(dftsize, (int16_t *)dft_in1, (int16_t *)dft_out1, (uint32_t *)1);
dft(dftsize, (int16_t *)dft_in2, (int16_t *)dft_out2, (uint32_t *)1);
break;
}

View File

@@ -555,7 +555,7 @@ void nr_dft(c16_t *z, c16_t *d, uint32_t Msc_PUSCH)
dft_size_idx_t dftsize = get_dft(Msc_PUSCH);
switch (Msc_PUSCH) {
case 12:
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, 0);
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, (uint32_t *)0);
norm128 = simde_mm_set1_epi16(9459);
for (i = 0; i < 12; i++) {
((simde__m128i *)dft_out0)[i] = simde_mm_slli_epi16(simde_mm_mulhi_epi16(((simde__m128i *)dft_out0)[i], norm128), 1);
@@ -563,7 +563,7 @@ void nr_dft(c16_t *z, c16_t *d, uint32_t Msc_PUSCH)
break;
default:
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, 1);
dft(dftsize, (int16_t *)dft_in0, (int16_t *)dft_out0, (uint32_t *)1);
break;
}

View File

@@ -65,7 +65,8 @@ int nr_symbol_fep_ul(const NR_DL_FRAME_PARMS *fp,
c16_t *rxdataF,
unsigned char symbol,
unsigned char slot,
int sample_offset);
int sample_offset,
uint32_t levdB);
/*!
\brief This function implements the dft transform precoding in PUSCH

View File

@@ -144,6 +144,7 @@ void PHY_ofdm_mod(const int *input, /// pointer to complex input
return;
idft_size_idx_t idft_size = get_idft(fftsize);
const uint32_t *scaling_sched = get_idft_scaling(fftsize, 0);
#ifdef DEBUG_OFDM_MOD
printf("[PHY] OFDM mod (size %d,prefix %d) Symbols %d, input %p, output %p\n",
@@ -176,11 +177,11 @@ void PHY_ofdm_mod(const int *input, /// pointer to complex input
// Current idft implementation uses AVX-256: Check if buffer is already aligned to 256 bits (32 bytes)
if ((uintptr_t)output_ptr % 32 == 0) {
// output ptr is aligned, do ifft inplace
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)output_ptr, 1);
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)output_ptr, scaling_sched);
} else {
// output ptr is not aligned, needs an extra memcpy
c16_t temp[fftsize] __attribute__((aligned(IDFT_OUTPUT_BUFFER_ALIGNMENT)));
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, 1);
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, scaling_sched);
memcpy((void *)output_ptr, (void *)temp, sizeof(temp));
}
// perform cyclic prefix insertion
@@ -191,7 +192,7 @@ void PHY_ofdm_mod(const int *input, /// pointer to complex input
case CYCLIC_SUFFIX: {
// Use alignment of 64 bytes
c16_t temp[fftsize] __attribute__((aligned(IDFT_OUTPUT_BUFFER_ALIGNMENT)));
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, 1);
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, scaling_sched);
int *output_ptr = &output[(i * fftsize) + (i * nb_prefix_samples)];
memcpy(output_ptr, temp, sizeof(temp));
memcpy(&output_ptr[fftsize], temp, nb_prefix_samples * sizeof(c16_t));
@@ -204,7 +205,7 @@ void PHY_ofdm_mod(const int *input, /// pointer to complex input
case NONE: {
c16_t temp[fftsize] __attribute__((aligned(IDFT_OUTPUT_BUFFER_ALIGNMENT)));
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, 1);
idft(idft_size, (int16_t *)&input[i * fftsize], (int16_t *)temp, scaling_sched);
int *output_ptr = &output[i * fftsize];
memcpy(output_ptr, temp, sizeof(temp));
break;

View File

@@ -57,6 +57,7 @@ int slot_fep(PHY_VARS_UE *ue,
return(-1);
}
uint32_t sigenergy_avg = 0;
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int));
rx_offset = sample_offset + slot_offset + nb_prefix_samples0 + subframe_offset - SOFFSET;
@@ -68,17 +69,31 @@ int slot_fep(PHY_VARS_UE *ue,
memcpy((short *)&common_vars->rxdata[aa][frame_length_samples],
(short *)&common_vars->rxdata[aa][0],
frame_parms->ofdm_symbol_size*sizeof(int));
uint32_t sigenergy = 0;
int dft_in_levdB;
if (ue->dft_in_levdB < 0) {
sigenergy = signal_energy((int32_t *)&common_vars->rxdata[aa][rx_offset & frame_length_samples],
frame_parms->ofdm_symbol_size * sizeof(int));
dft_in_levdB = dB_fixed(sigenergy);
sigenergy_avg += (sigenergy / frame_parms->nb_antennas_rx);
} else
dft_in_levdB = ue->dft_in_levdB;
if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs
memcpy((void *)tmp_dft_in,
(void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples],
frame_parms->ofdm_symbol_size*sizeof(int));
dft(dftsizeidx,(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns >> 1]]
.rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, dft_in_levdB));
} else { // use dft input from RX buffer directly
start_UE_TIMING(ue->rx_dft_stats);
dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns >> 1]]
.rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, dft_in_levdB));
stop_UE_TIMING(ue->rx_dft_stats);
}
} else {
@@ -102,16 +117,23 @@ int slot_fep(PHY_VARS_UE *ue,
memcpy((void *)tmp_dft_in,
(void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
frame_parms->ofdm_symbol_size*sizeof(int));
dft(dftsizeidx,(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns >> 1]]
.rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, ue->dft_in_levdB));
} else { // use dft input from RX buffer directly
dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns >> 1]]
.rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, ue->dft_in_levdB));
}
stop_UE_TIMING(ue->rx_dft_stats);
}
if (ue->dft_in_levdB < 0)
ue->dft_in_levdB = dB_fixed(sigenergy_avg) + 20;
#ifdef DEBUG_FEP
// if (ue->frame <100)
@@ -231,12 +253,16 @@ int front_end_fft(PHY_VARS_UE *ue,
memcpy((void *)tmp_dft_in,
(void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples],
frame_parms->ofdm_symbol_size*sizeof(int));
dft(dftsizeidx,(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, ue->dft_in_levdB));
} else { // use dft input from RX buffer directly
start_meas(&ue->rx_dft_stats);
dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, ue->dft_in_levdB));
stop_meas(&ue->rx_dft_stats);
}
} else {
@@ -261,11 +287,15 @@ int front_end_fft(PHY_VARS_UE *ue,
memcpy((void *)tmp_dft_in,
(void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
frame_parms->ofdm_symbol_size*sizeof(int));
dft(dftsizeidx,(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, ue->dft_in_levdB));
} else { // use dft input from RX buffer directly
dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
dft(dftsizeidx,
(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size * symbol],
get_dft_scaling(s, ue->dft_in_levdB));
}
stop_meas(&ue->rx_dft_stats);

View File

@@ -63,11 +63,12 @@ int slot_fep_mbsfn(PHY_VARS_UE *ue,
if (l==0) {
start_UE_TIMING(ue->rx_dft_stats);
dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(sample_offset +
nb_prefix_samples0 +
subframe_offset -
SOFFSET) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[aa][frame_parms->ofdm_symbol_size*l],1);
dft(dftsizeidx,
(int16_t *)&common_vars
->rxdata[aa][(sample_offset + nb_prefix_samples0 + subframe_offset - SOFFSET) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]]
.rxdataF[aa][frame_parms->ofdm_symbol_size * l],
get_dft_scaling(s, ue->dft_in_levdB));
stop_UE_TIMING(ue->rx_dft_stats);
} else {
if ((sample_offset +
@@ -80,12 +81,14 @@ int slot_fep_mbsfn(PHY_VARS_UE *ue,
frame_parms->ofdm_symbol_size*sizeof(int));
start_UE_TIMING(ue->rx_dft_stats);
dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(sample_offset +
(frame_parms->ofdm_symbol_size+nb_prefix_samples0+nb_prefix_samples) +
(frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1) +
subframe_offset-
SOFFSET) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[aa][frame_parms->ofdm_symbol_size*l],1);
dft(dftsizeidx,
(int16_t *)&common_vars
->rxdata[aa][(sample_offset + (frame_parms->ofdm_symbol_size + nb_prefix_samples0 + nb_prefix_samples)
+ (frame_parms->ofdm_symbol_size + nb_prefix_samples) * (l - 1) + subframe_offset - SOFFSET)
% frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]]
.rxdataF[aa][frame_parms->ofdm_symbol_size * l],
get_dft_scaling(s, ue->dft_in_levdB));
stop_UE_TIMING(ue->rx_dft_stats);
}
}
@@ -202,11 +205,10 @@ int slot_fep_mbsfn_khz_1dot25(PHY_VARS_UE *ue,
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[aa][0],0,ofdm_symbol_size*sizeof(int));
start_UE_TIMING(ue->rx_dft_stats);
dft(get_dft(ofdm_symbol_size),(int16_t *)&common_vars->rxdata[aa][(sample_offset +
nb_prefix_samples +
subframe_offset -
SOFFSET) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[aa][0],1);
dft(get_dft(ofdm_symbol_size),
(int16_t *)&common_vars->rxdata[aa][(sample_offset + nb_prefix_samples + subframe_offset - SOFFSET) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[aa][0],
get_dft_scaling(ofdm_symbol_size, ue->dft_in_levdB));
stop_UE_TIMING(ue->rx_dft_stats);
}

View File

@@ -27,7 +27,7 @@ void nr_symbol_fep(const NR_DL_FRAME_PARMS *frame_parms,
dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size);
for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
if (dft_stats) start_meas(dft_stats);
dft(dftsize, (int16_t *)rxdata[aa], (int16_t *)rxdataF[aa], 1);
dft(dftsize, (int16_t *)rxdata[aa], (int16_t *)rxdataF[aa], get_dft_scaling(frame_parms->ofdm_symbol_size,1));
if (dft_stats) stop_meas(dft_stats);
const bool is_sl = (link_type == link_type_sl);
@@ -122,9 +122,11 @@ int nr_symbol_fep_ul(const NR_DL_FRAME_PARMS *fp,
c16_t *rxdataF,
unsigned char symbol,
unsigned char slot,
int sample_offset)
int sample_offset,
uint32_t levdB)
{
dft_size_idx_t dftsize = get_dft(fp->ofdm_symbol_size);
const uint32_t *scaling_sched = get_dft_scaling(fp->ofdm_symbol_size, levdB);
// This is for misalignment issues
int32_t tmp_dft_in[fp->ofdm_symbol_size] __attribute__((aligned(32)));
@@ -154,7 +156,7 @@ int nr_symbol_fep_ul(const NR_DL_FRAME_PARMS *fp,
rxdata_ptr = (int16_t *)&rxdata[rxdata_offset];
}
dft(dftsize, rxdata_ptr, (int16_t *)rxdataF, 1);
dft(dftsize, rxdata_ptr, (int16_t *)rxdataF, scaling_sched);
return 0;
}
@@ -203,6 +205,7 @@ void apply_nr_rotation_symbol_RX(const NR_DL_FRAME_PARMS *frame_parms,
}
}
// this function is only for phy simulators
void nr_ofdm_demod_and_rx_rotation(c16_t **rxdata,
c16_t **rxdataF,
const NR_DL_FRAME_PARMS *fp,
@@ -215,7 +218,7 @@ void nr_ofdm_demod_and_rx_rotation(c16_t **rxdata,
for (int aa = 0; aa < nb_antennas; aa++) {
for (uint8_t symbol = 0; symbol < fp->symbols_per_slot; symbol++) {
if (was_symbol_used[symbol] == true) {
nr_symbol_fep_ul(fp, &rxdata[aa][0], &rxdataF[aa][slot_offsetF + symbol * fp->ofdm_symbol_size], symbol, slot, 0);
nr_symbol_fep_ul(fp, &rxdata[aa][0], &rxdataF[aa][slot_offsetF + symbol * fp->ofdm_symbol_size], symbol, slot, 0, 0);
apply_nr_rotation_symbol_RX(fp,
&rxdataF[aa][slot_offsetF + symbol * fp->ofdm_symbol_size],
fp->symbol_rotation[linktype],

View File

@@ -63,10 +63,10 @@ int slot_fep_ul(RU_t *ru,
LOG_D(PHY,"slot_fep: symbol 0 %d dB\n",
dB_fixed(signal_energy(&common->rxdata_7_5kHz[aa][rx_offset],fp->ofdm_symbol_size)));
#endif
dft( dftsize,(int16_t *)&common->rxdata_7_5kHz[aa][rx_offset],
(int16_t *)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol],
1
);
dft(dftsize,
(int16_t *)&common->rxdata_7_5kHz[aa][rx_offset],
(int16_t *)&common->rxdataF[aa][fp->ofdm_symbol_size * symbol],
get_dft_scaling(s, ru->dft_in_levdB));
} else {
rx_offset += (fp->ofdm_symbol_size+nb_prefix_samples)*l;
@@ -75,16 +75,16 @@ int slot_fep_ul(RU_t *ru,
memcpy((void *)&tmp_dft_in,
(void *)&common->rxdata_7_5kHz[aa][(rx_offset % frame_length_samples)],
fp->ofdm_symbol_size*sizeof(int));
dft( dftsize,(short *) tmp_dft_in,
(short*) &common->rxdataF[aa][fp->ofdm_symbol_size*symbol],
1
);
dft(dftsize,
(short *)tmp_dft_in,
(short *)&common->rxdataF[aa][fp->ofdm_symbol_size * symbol],
get_dft_scaling(s, ru->dft_in_levdB));
}
else{
dft( dftsize,(short *)&common->rxdata_7_5kHz[aa][rx_offset],
(short*)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol],
1
);
dft(dftsize,
(short *)&common->rxdata_7_5kHz[aa][rx_offset],
(short *)&common->rxdataF[aa][fp->ofdm_symbol_size * symbol],
get_dft_scaling(s, ru->dft_in_levdB));
}
}
}

View File

@@ -900,8 +900,7 @@ void nr_srs_noise_power_estimation(uint16_t ofdm_symbol_size,
#endif
}
int nr_srs_channel_interpolation(int ant,
int p_index,
int nr_srs_channel_interpolation(int p_index,
uint16_t ofdm_symbol_size,
uint16_t first_carrier_offset,
uint8_t N_symb_SRS,
@@ -933,7 +932,7 @@ int nr_srs_channel_interpolation(int ant,
uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size;
#ifdef SRS_DEBUG
LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant);
LOG_I(NR_PHY, "============================== UE port %d ====================================\n", p_index);
LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb);
#endif

View File

@@ -70,8 +70,7 @@ int nr_srs_ls_channel_estimation(int ant,
c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS],
delay_t *delay);
int nr_srs_channel_interpolation(int ant,
int p_index,
int nr_srs_channel_interpolation(int p_index,
uint16_t ofdm_symbol_size,
uint16_t first_carrier_offset,
uint8_t N_symb_SRS,

View File

@@ -55,6 +55,6 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
int32_t *tot_metric,
uint8_t *phase_max,
int *freq_offset_sss,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP]);
c16_t rxdataF[NR_N_SYMBOLS_SSB][frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size]);
#endif /* SSS_NR_H */

View File

@@ -112,7 +112,8 @@ static void rx_nr_prach_ru_internal(prach_item_t *p,
int prachOccasion,
int32_t **rxdata,
NR_DL_FRAME_PARMS *fp,
int N_TA_offset)
int N_TA_offset,
int dft_in_levdB)
{
int sample_offset_slot;
const int sum = fp->ofdm_symbol_size + fp->nb_prefix_samples;
@@ -319,6 +320,7 @@ static void rx_nr_prach_ru_internal(prach_item_t *p,
}
const dft_size_idx_t dftsize = get_dft(dftlen);
const uint32_t *scaling_sched = get_dft_scaling(dftlen, dft_in_levdB);
// Do forward transform
if (LOG_DEBUGFLAG(DEBUG_PRACH)) {
@@ -350,10 +352,10 @@ static void rx_nr_prach_ru_internal(prach_item_t *p,
memset(rxsigF_tmp, 0, sizeof(rxsigF_tmp));
for (int i = 0; i < reps; i++, prach2 += dftlen) {
c16_t tmp[dftlen] __attribute__((aligned(32)));
dft(dftsize, (int16_t *)prach2, (int16_t *)tmp, 1);
// Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH)
LOG_D(PHY, "Doing PRACH combining of %d reptitions N_ZC %d\n", reps, N_ZC);
// if (k+N_ZC > dftlen) { // PRACH signal is split around DC
dft(dftsize, (int16_t *)prach2, (int16_t *)tmp, scaling_sched);
//Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH)
LOG_D(PHY,"Doing PRACH combining of %d reptitions N_ZC %d\n",reps,N_ZC);
// if (k+N_ZC > dftlen) { // PRACH signal is split around DC
int k2 = k;
for (int j = 0; j < N_ZC; j++, k2++) {
if (k2 == dftlen)
@@ -365,7 +367,7 @@ static void rx_nr_prach_ru_internal(prach_item_t *p,
}
}
void rx_nr_prach_ru(prach_item_t *p, int32_t **rxdata, NR_DL_FRAME_PARMS *fp, int N_TA_offset)
void rx_nr_prach_ru(prach_item_t *p, int32_t **rxdata, NR_DL_FRAME_PARMS *fp, int N_TA_offset, int dft_in_levdB)
{
int N_dur = get_nr_prach_duration(p->pdu.prach_format);
LOG_D(NR_PHY_RACH, "%d.%d try to decode %d occasions \n", p->frame, p->slot, p->pdu.num_prach_ocas);
@@ -375,7 +377,7 @@ void rx_nr_prach_ru(prach_item_t *p, int32_t **rxdata, NR_DL_FRAME_PARMS *fp, in
// comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is
// given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots
// where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
rx_nr_prach_ru_internal(p, beam_id, prachStartSymbol, prach_oc, rxdata, fp, N_TA_offset);
rx_nr_prach_ru_internal(p, beam_id, prachStartSymbol, prach_oc, rxdata, fp, N_TA_offset, dft_in_levdB);
}
}
@@ -542,7 +544,7 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion)
memset(prachF + N_ZC, 0, sizeof(*prachF) * (dft_sz - N_ZC));
// Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139)
c16_t prach_ifft_tmp[dft_sz] __attribute__((aligned(32)));
idft(get_idft(dft_sz), (int16_t *)prachF, (int16_t *)prach_ifft_tmp, 1);
idft(get_idft(dft_sz), (int16_t *)prachF, (int16_t *)prach_ifft_tmp, get_idft_scaling(256, 0));
// compute energy and accumulate over receive antennas
for (int i = 0; i < dft_sz; i++)
prach_ifft[i] += squaredMod(prach_ifft_tmp[i]);

View File

@@ -177,7 +177,7 @@ typedef struct rx_prach_out {
} rx_prach_out_t;
rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion);
void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset);
void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset, int dft_in_levdB);
void nr_fill_pucch(PHY_VARS_gNB *gNB,
int frame,

View File

@@ -48,7 +48,7 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
dft_size_idx_t dftsize = get_dft(Msc_PUSCH);
switch (Msc_PUSCH) {
case 12:
dft(dftsize, (int16_t *)idft_in0, (int16_t *)idft_out0, 0);
dft(dftsize, (int16_t *)idft_in0, (int16_t *)idft_out0, (uint32_t *)0);
norm128 = simde_mm_set1_epi16(9459);
@@ -58,7 +58,7 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
break;
default:
dft(dftsize, idft_in0, idft_out0, 1);
dft(dftsize, idft_in0, idft_out0, (uint32_t *)1);
break;
}

View File

@@ -1584,68 +1584,3 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
uci_pdu->pduBitmap |= 8;
}
}
void nr_dump_uci_stats(FILE *fd, PHY_VARS_gNB *gNB, int frame)
{
int strpos = 0;
char output[16384];
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
NR_gNB_PHY_STATS_t *stats = &gNB->phy_stats[i];
if (!stats->active)
return;
NR_gNB_UCI_STATS_t *uci_stats = &stats->uci_stats;
if (uci_stats->pucch0_sr_trials > 0)
strpos += sprintf(output + strpos,
"UCI %d RNTI %x: pucch0_sr_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_sr_thres %d dB, current "
"pucch1_stat0 %d dB, current pucch1_stat1 %d dB, positive SR count %d\n",
i,
stats->rnti,
uci_stats->pucch0_sr_trials,
uci_stats->pucch0_n00,
uci_stats->pucch0_n01,
uci_stats->pucch0_sr_thres,
dB_fixed(uci_stats->current_pucch0_sr_stat0),
dB_fixed(uci_stats->current_pucch0_sr_stat1),
uci_stats->pucch0_positive_SR);
if (uci_stats->pucch01_trials > 0)
strpos += sprintf(output + strpos,
"UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current "
"pucch0_stat0 %d dB, current pucch1_stat1 %d dB, pucch01_DTX %d\n",
i,
stats->rnti,
uci_stats->pucch01_trials,
uci_stats->pucch0_n01,
uci_stats->pucch0_n01,
uci_stats->pucch0_thres,
dB_fixed(uci_stats->current_pucch0_stat0),
dB_fixed(uci_stats->current_pucch0_stat1),
uci_stats->pucch01_DTX);
if (uci_stats->pucch02_trials > 0)
strpos += sprintf(output + strpos,
"UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current "
"pucch0_stat0 %d dB, current pucch0_stat1 %d dB, pucch01_DTX %d\n",
i,
stats->rnti,
uci_stats->pucch02_trials,
uci_stats->pucch0_n00,
uci_stats->pucch0_n01,
uci_stats->pucch0_thres,
dB_fixed(uci_stats->current_pucch0_stat0),
dB_fixed(uci_stats->current_pucch0_stat1),
uci_stats->pucch02_DTX);
if (uci_stats->pucch2_trials > 0)
strpos += sprintf(output + strpos,
"UCI %d RNTI %x: pucch2_trials %d, pucch2_DTX %d\n",
i,
stats->rnti,
uci_stats->pucch2_trials,
uci_stats->pucch2_DTX);
}
if (fd)
fprintf(fd, "%s", output);
else
printf("%s", output);
}

View File

@@ -12,10 +12,9 @@
// The adjustment is performed once per frame based on the
// last channel estimate of the receiver
int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
int nr_adjust_synch_ue(const NR_DL_FRAME_PARMS *frame_parms,
PHY_VARS_NR_UE *ue,
const int estimateSz,
struct complex16 dl_ch_estimates_time[][estimateSz],
const c16_t dl_ch_estimates_time[][frame_parms->ofdm_symbol_size],
uint8_t frame,
uint8_t slot,
short coef)

View File

@@ -522,7 +522,7 @@ c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
const int Nid_cell,
const int ssb_start_subcarrier,
const uint32_t nr_gold_pbch[NR_PBCH_DMRS_LENGTH_DWORD],
const c16_t rxdataF[][fp->samples_per_slot_wCP])
const c16_t rxdataF[fp->nb_antennas_rx][fp->ofdm_symbol_size])
{
AssertFatal(dmrss >= 0 && dmrss < 3, "symbol %d is illegal for PBCH DM-RS \n", dmrss);
@@ -530,8 +530,6 @@ c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
if (ssb_offset >= fp->ofdm_symbol_size)
ssb_offset -= fp->ofdm_symbol_size;
int symbol_offset = fp->ofdm_symbol_size * symbol;
unsigned int k = Nid_cell % 4;
DEBUG_PBCH("PBCH DMRS Correlation : OFDM size %d, Ncp=%d, k=%u symbol %d\n",
@@ -548,7 +546,7 @@ c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
int re_offset = ssb_offset;
c16_t *pil = pilot;
const c16_t *rxF = &rxdataF[aarx][symbol_offset + k];
const c16_t *rxF = &rxdataF[aarx][k];
DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", fp->N_RB_DL);
DEBUG_PBCH("k %u, first_carrier %d\n", k, fp->first_carrier_offset);
@@ -603,25 +601,21 @@ c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
const sl_nr_ue_phy_params_t *sl_phy_params,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
c16_t dl_ch_estimates[fp->ofdm_symbol_size],
const UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
int dmrss,
uint ssb_index,
uint n_hf,
int ssb_start_subcarrier,
const c16_t rxdataF[][fp->samples_per_slot_wCP],
const c16_t rxdataF[fp->ofdm_symbol_size],
bool sidelink,
uint Nid)
{
TracyCZone(ctx, true);
int Ns = proc->nr_slot_rx;
c16_t pilot[200] __attribute__((aligned(16)));
//int slot_pbch;
uint8_t nushift = 0, lastsymbol = 0, num_rbs = 0;
uint8_t nushift = 0, num_rbs = 0;
const uint32_t *gold_seq = NULL;
if (sidelink) {
@@ -630,7 +624,6 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
LOG_D(PHY, "PSBCH Channel Estimation SLSSID:%d\n", Nid);
gold_seq = sl_phy_params->init_params.psbch_dmrs_gold_sequences[Nid];
lastsymbol = 12;
num_rbs = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL;
} else {
@@ -639,7 +632,6 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
AssertFatal(dmrss >= 0 && dmrss < 3, "symbol %d is illegal for PBCH DM-RS \n", dmrss);
gold_seq = nr_gold_pbch(fp->Lmax, Nid, n_hf, ssb_index);
lastsymbol = 2;
num_rbs = 20;
}
@@ -647,18 +639,14 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
if (ssb_offset >= fp->ofdm_symbol_size)
ssb_offset -= fp->ofdm_symbol_size;
const int ch_offset = fp->ofdm_symbol_size * symbol;
const int symbol_offset = fp->ofdm_symbol_size * symbol;
const int k = nushift;
DEBUG_PBCH("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",
DEBUG_PBCH("PBCH Channel Estimation : gNB_id %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d\n",
proc->gNB_id,
ch_offset,
fp->ofdm_symbol_size,
fp->Ncp,
Ns,
k,
symbol);
proc->nr_slot_rx,
k);
const int16_t *fl, *fm, *fr;
@@ -695,98 +683,89 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
// generate pilot
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
nr_pbch_dmrs_rx(dmrss, gold_seq, &pilot[0], sidelink);
nr_pbch_dmrs_rx(dmrss, gold_seq, pilot, sidelink);
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
int re_offset = ssb_offset;
c16_t *pil = pilot;
const c16_t *rxF = &rxdataF[aarx][symbol_offset + k];
c16_t *dl_ch = &dl_ch_estimates[aarx][ch_offset];
int re_offset = ssb_offset;
const c16_t *pil = pilot;
const c16_t *rxF = rxdataF + k;
c16_t *dl_ch = dl_ch_estimates;
memset(dl_ch, 0, sizeof(c16_t) * fp->ofdm_symbol_size);
memset(dl_ch, 0, sizeof(c16_t) * fp->ofdm_symbol_size);
DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", fp->N_RB_DL);
DEBUG_PBCH("k %d, first_carrier %d\n", k, fp->first_carrier_offset);
DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", fp->N_RB_DL);
DEBUG_PBCH("k %d, first_carrier %d\n", k, fp->first_carrier_offset);
// Treat first 2 pilots specially (left edge)
c16_t ch;
// Treat first 2 pilots specially (left edge)
c16_t ch;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 0: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
multadd_real_vector_complex_scalar(fl, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 1: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
multadd_real_vector_complex_scalar(fm, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 2: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
multadd_real_vector_complex_scalar(fr, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
dl_ch += 12;
for (int pilot_cnt = 3; pilot_cnt < (3 * num_rbs); pilot_cnt += 3) {
// if (pilot_cnt == 30)
// rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)];
// in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS)
if (dmrss == 1 && pilot_cnt == 12) {
pilot_cnt = 48;
re_offset = (re_offset + 144) % fp->ofdm_symbol_size;
dl_ch += 144;
}
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 0: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt,
rxF[re_offset].r,
rxF[re_offset].i,
ch.r,
ch.i,
pil->r,
pil->i);
multadd_real_vector_complex_scalar(fl, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 1: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt + 1,
rxF[re_offset].r,
rxF[re_offset].i,
ch.r,
ch.i,
pil->r,
pil->i);
multadd_real_vector_complex_scalar(fm, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 2: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt + 2,
rxF[re_offset].r,
rxF[re_offset].i,
ch.r,
ch.i,
pil->r,
pil->i);
multadd_real_vector_complex_scalar(fr, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
dl_ch += 12;
for (int pilot_cnt = 3; pilot_cnt < (3 * num_rbs); pilot_cnt += 3) {
// if (pilot_cnt == 30)
// rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)];
// in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS)
if (dmrss == 1 && pilot_cnt == 12) {
pilot_cnt=48;
re_offset = (re_offset + 144) % fp->ofdm_symbol_size;
dl_ch += 144;
}
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt,
rxF[re_offset].r,
rxF[re_offset].i,
ch.r,
ch.i,
pil->r,
pil->i);
multadd_real_vector_complex_scalar(fl, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt + 1,
rxF[re_offset].r,
rxF[re_offset].i,
ch.r,
ch.i,
pil->r,
pil->i);
multadd_real_vector_complex_scalar(fm, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt + 2,
rxF[re_offset].r,
rxF[re_offset].i,
ch.r,
ch.i,
pil->r,
pil->i);
multadd_real_vector_complex_scalar(fr, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
dl_ch += 12;
}
if (dmrss == lastsymbol) // update time statistics for last PBCH symbol
{
// do ifft of channel estimate
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
freq2time(fp->ofdm_symbol_size, (int16_t *)&dl_ch_estimates[aarx][ch_offset], (int16_t *)&dl_ch_estimates_time[aarx]);
}
}
TracyCZoneEnd(ctx);
@@ -906,7 +885,6 @@ static void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
c16_t *dl_ch,
unsigned short bwp_start_subcarrier,
const freq_alloc_bitmap_t *freq_alloc,
int nb_rb_pdsch,
int bwpsize,
delay_t *delay,
uint32_t *nvar)
@@ -1075,7 +1053,6 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
c16_t *dl_ch,
unsigned short bwp_start_subcarrier,
const freq_alloc_bitmap_t *freq_alloc,
int nb_rb_pdsch,
int bwpsize,
delay_t *delay,
uint32_t *nvar)
@@ -1304,7 +1281,6 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
bwp_start_subcarrier,
freq_alloc,
nb_rb_pdsch,
dlsch->BWPSize,
&delay,
nvar);
@@ -1316,7 +1292,6 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
bwp_start_subcarrier,
freq_alloc,
nb_rb_pdsch,
dlsch->BWPSize,
&delay,
nvar);

View File

@@ -44,20 +44,17 @@ c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
const int Nid_cell,
const int ssb_start_subcarrier,
const uint32_t nr_gold_pbch[NR_PBCH_DMRS_LENGTH_DWORD],
const c16_t rxdataF[][fp->samples_per_slot_wCP]);
const c16_t rxdataF[fp->nb_antennas_rx][fp->ofdm_symbol_size]);
int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
const sl_nr_ue_phy_params_t *sl_phy_params,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
c16_t dl_ch_estimates[fp->ofdm_symbol_size],
const UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
int dmrss,
uint ssb_index,
uint n_hf,
int ssb_start_subcarrier,
const c16_t rxdataF[][fp->samples_per_slot_wCP],
const c16_t rxdataF[fp->ofdm_symbol_size],
bool sidelink,
uint Nid);
@@ -74,12 +71,11 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
c16_t rxdataF[][rxdataFsize],
uint32_t *nvar);
int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
int nr_adjust_synch_ue(const NR_DL_FRAME_PARMS *frame_parms,
PHY_VARS_NR_UE *ue,
int estimateSz,
struct complex16 dl_ch_estimates_time[][estimateSz],
const c16_t dl_ch_estimates_time[][frame_parms->ofdm_symbol_size],
uint8_t frame,
uint8_t subframe,
uint8_t slot,
short coef);
void nr_ue_measurements(PHY_VARS_NR_UE *ue,
@@ -89,14 +85,13 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue,
int32_t dl_ch_estimates[][pdsch_est_size]);
uint32_t nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp,
const c16_t rxdataF[][fp->samples_per_slot_wCP],
int symbol_offset,
const c16_t rxdataF[][fp->ofdm_symbol_size],
int ssb_start_subcarrier);
void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
int ssb_index,
const UE_nr_rxtx_proc_t *proc,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
const c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]);
// Structure to pass data to neighboring cell measurement task
typedef struct {
@@ -113,7 +108,7 @@ void do_neighboring_cell_measurements(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *u
void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
const c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]);
void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue,
uint32_t rx_power_fil_dB,
@@ -136,8 +131,9 @@ void nr_pdsch_ptrs_processing(int nbRx,
int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue,
sl_nr_ue_phy_params_t *sl_phy_params,
NR_DL_FRAME_PARMS *fp,
c16_t rxdataF[][fp->samples_per_slot_wCP],
const NR_DL_FRAME_PARMS *fp,
const int symbol,
const c16_t rxdataF[][fp->ofdm_symbol_size],
bool use_SSS);
/** @}*/
#endif

View File

@@ -119,20 +119,17 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue,
// This function calculates:
// - SS reference signal received digital power in dB/RE
uint32_t nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp,
const c16_t rxdataF[][fp->samples_per_slot_wCP],
int symbol_offset,
const c16_t rxdataF[][fp->ofdm_symbol_size],
int ssb_start_subcarrier)
{
const int k_start = 56;
const int k_end = 183;
const unsigned int ssb_offset = fp->first_carrier_offset + ssb_start_subcarrier;
const uint8_t l_sss = (symbol_offset + 2) % fp->symbols_per_slot;
uint32_t rsrp = 0;
LOG_D(PHY, "In %s: l_sss %d ssb_offset %d\n", __FUNCTION__, l_sss, ssb_offset);
int nb_re = 0;
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
const c16_t *rxF_sss = &rxdataF[aarx][l_sss * fp->ofdm_symbol_size];
const c16_t *rxF_sss = rxdataF[aarx];
for(int k = k_start; k < k_end; k++){
int re = (ssb_offset + k) % fp->ofdm_symbol_size;
rsrp += squaredMod(rxF_sss[re]);
@@ -185,16 +182,11 @@ static void send_ssb_rsrp_meas(PHY_VARS_NR_UE *ue,
void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
int ssb_index,
const UE_nr_rxtx_proc_t *proc,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
const c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size])
{
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
const NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
int symbol_offset = nr_get_ssb_start_symbol(fp, ssb_index);
if (fp->half_frame_bit)
symbol_offset += (fp->slots_per_frame >> 1) * fp->symbols_per_slot;
uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(fp, rxdataF, symbol_offset, fp->ssb_start_subcarrier);
uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(fp, rxdataF, fp->ssb_start_subcarrier);
float rsrp_db_per_re = 10 * log10(rsrp_avg);
openair0_config_t *cfg0 = &openair0_cfg[ue->rf_map.card];
@@ -234,8 +226,7 @@ static bool search_neighboring_cell(NR_DL_FRAME_PARMS *frame_parms,
neighboring_cell_info_t *neighboring_cell_info,
c16_t **rxdata,
uint32_t rxdata_size,
uint32_t rxdataF_sz,
c16_t rxdataF[][rxdataF_sz],
c16_t rxdataF[][frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size],
c16_t pssTime[][frame_parms->ofdm_symbol_size])
{
int detected_nid_cell = -1;
@@ -293,8 +284,7 @@ static bool validate_known_pci(NR_DL_FRAME_PARMS *frame_parms,
fapi_nr_neighboring_cell_t *nr_neighboring_cell,
neighboring_cell_info_t *neighboring_cell_info,
c16_t **rxdata,
uint32_t rxdataF_sz,
c16_t rxdataF[][rxdataF_sz],
c16_t rxdataF[][frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size],
c16_t pssTime[][frame_parms->ofdm_symbol_size])
{
int known_pci = nr_neighboring_cell->Nid_cell;
@@ -335,9 +325,18 @@ static bool validate_known_pci(NR_DL_FRAME_PARMS *frame_parms,
int ssb_offset = peak_position - frame_parms->nb_prefix_samples;
__attribute__((aligned(32))) c16_t rxdataF_tmp[frame_parms->nb_antennas_rx][frame_parms->samples_per_slot_wCP];
uint8_t sss_symbol = SSS_SYMBOL_NB - PSS_SYMBOL_NB;
nr_slot_fep(NULL, frame_parms, 0, 0, rxdataF, link_type_dl, ssb_offset, (c16_t **)rxdata);
nr_slot_fep(NULL, frame_parms, 0, sss_symbol, rxdataF, link_type_dl, ssb_offset, (c16_t **)rxdata);
nr_slot_fep(NULL, frame_parms, 0, 0, rxdataF_tmp, link_type_dl, ssb_offset, (c16_t **)rxdata);
nr_slot_fep(NULL, frame_parms, 0, sss_symbol, rxdataF_tmp, link_type_dl, ssb_offset, (c16_t **)rxdata);
/* TODO: Once symbol based PDSCH proc is imeplemented, nr_slot_fep() will use
the new rxdataF buffer format so the following memcpy can be removed. */
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
memcpy(rxdataF[0][aarx], &rxdataF_tmp[aarx][0], sizeof(c16_t) * frame_parms->ofdm_symbol_size);
memcpy(rxdataF[sss_symbol][aarx],
&rxdataF_tmp[aarx][sss_symbol * frame_parms->ofdm_symbol_size],
sizeof(c16_t) * frame_parms->ofdm_symbol_size);
}
int detected_nid_cell = -1;
int32_t sss_metric = 0;
@@ -378,7 +377,7 @@ void do_neighboring_cell_measurements(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *u
{
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
const uint32_t rxdataF_sz = frame_parms->ofdm_symbol_size;
// Generate PSS time-domain sequences once for all neighbor cells
__attribute__((aligned(32))) c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size];
@@ -386,7 +385,7 @@ void do_neighboring_cell_measurements(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *u
generate_pss_nr_time(frame_parms, nid2_idx, frame_parms->ssb_start_subcarrier, pssTime[nid2_idx]);
}
__attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
__attribute__((aligned(32))) c16_t rxdataF[NR_N_SYMBOLS_SSB][frame_parms->nb_antennas_rx][rxdataF_sz];
for (int cell_idx = 0; cell_idx < NUMBER_OF_NEIGHBORING_CELLS_MAX; cell_idx++) {
fapi_nr_neighboring_cell_t *neighbor_cell = &ue->nrUE_config.meas_config.nr_neighboring_cell[cell_idx];
@@ -416,18 +415,11 @@ void do_neighboring_cell_measurements(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *u
neighbor_cell->active);
if (is_blind_search) {
if (!search_neighboring_cell(frame_parms,
neighbor_cell,
neighboring_cell_info,
rxdata,
rxdata_size,
rxdataF_sz,
rxdataF,
pssTime)) {
if (!search_neighboring_cell(frame_parms, neighbor_cell, neighboring_cell_info, rxdata, rxdata_size, rxdataF, pssTime)) {
continue;
}
} else {
if (!validate_known_pci(frame_parms, neighbor_cell, neighboring_cell_info, rxdata, rxdataF_sz, rxdataF, pssTime)) {
if (!validate_known_pci(frame_parms, neighbor_cell, neighboring_cell_info, rxdata, rxdataF, pssTime)) {
if (neighboring_cell_info->consec_fail >= NEIGHBOR_CELL_MAX_CONSECUTIVE_FAILURES) {
LOG_D(NR_PHY, "Max consecutive failures reached for PCI=%d, resetting to full search\n", neighbor_cell->Nid_cell);
neighboring_cell_info->pss_search_start = 0;
@@ -441,7 +433,8 @@ void do_neighboring_cell_measurements(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *u
}
// RSRP measurements
neighboring_cell_info->ssb_rsrp = nr_ue_calculate_ssb_rsrp(frame_parms, rxdataF, 0, frame_parms->ssb_start_subcarrier);
uint8_t sss_symbol = SSS_SYMBOL_NB - PSS_SYMBOL_NB;
neighboring_cell_info->ssb_rsrp = nr_ue_calculate_ssb_rsrp(frame_parms, rxdataF[sss_symbol], frame_parms->ssb_start_subcarrier);
neighboring_cell_info->ssb_rsrp_dBm =
10 * log10(neighboring_cell_info->ssb_rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB
@@ -468,32 +461,27 @@ void nr_ue_meas_neighboring_cell(void *arg)
// - psd_awgn (AWGN power spectral density): dBm/Hz
void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
const c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size])
{
uint8_t k;
int slot = proc->nr_slot_rx;
int aarx;
int16_t *rxF_sss;
const int16_t *rxF_sss;
const uint8_t k_left = 48;
const uint8_t k_right = 183;
const uint8_t k_length = 8;
uint8_t l_sss = (ue->symbol_offset + 2) % ue->frame_parms.symbols_per_slot;
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
double rx_gain = openair0_cfg[ue->rf_map.card].rx_gain[0];
double rx_gain_offset = openair0_cfg[ue->rf_map.card].rx_gain_offset[0];
ue->measurements.n0_power_tot = 0;
LOG_D(PHY, "In %s doing measurements for ssb_offset %d l_sss %d \n", __FUNCTION__, ssb_offset, l_sss);
for (aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
LOG_D(PHY, "In %s doing measurements for ssb_offset %d \n", __FUNCTION__, ssb_offset);
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
uint32_t n0_power = 0;
rxF_sss = (int16_t *)&rxdataF[aarx][l_sss*ue->frame_parms.ofdm_symbol_size];
rxF_sss = (int16_t *)rxdataF[aarx];
//-ve spectrum from SSS
for(k = k_left; k < k_left + k_length; k++){
for (int k = k_left; k < k_left + k_length; k++) {
int re = (ssb_offset + k) % ue->frame_parms.ofdm_symbol_size;
#ifdef DEBUG_MEAS_RRC
@@ -504,8 +492,7 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
}
//+ve spectrum from SSS
for(k = k_right; k < k_right + k_length; k++){
for (int k = k_right; k < k_right + k_length; k++) {
int re = (ssb_offset + k) % ue->frame_parms.ofdm_symbol_size;
#ifdef DEBUG_MEAS_RRC
@@ -547,12 +534,14 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
// returns RXgain to be adjusted based on target rx power (50db) - received digital power in db/RE
int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue,
sl_nr_ue_phy_params_t *sl_phy_params,
NR_DL_FRAME_PARMS *fp,
c16_t rxdataF[][fp->samples_per_slot_wCP],
const NR_DL_FRAME_PARMS *fp,
const int symbol,
const c16_t rxdataF[][fp->ofdm_symbol_size],
bool use_SSS)
{
SL_NR_UE_PSBCH_t *psbch_rx = &sl_phy_params->psbch;
uint8_t numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP : SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
uint8_t maxsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP : SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
uint8_t numsym = (fp->Ncp) ? 8 : 10;
uint32_t re_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
uint32_t rsrp = 0, num_re = 0;
@@ -560,18 +549,15 @@ int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue,
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
// Calculate PSBCH RSRP based from DMRS REs
for (uint8_t symbol = 0; symbol < numsym;) {
struct complex16 *rxF = &rxdataF[aarx][symbol * fp->ofdm_symbol_size];
const struct complex16 *rxF = rxdataF[aarx];
for (int re = 0; re < SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL; re++) {
if (re % 4 == 0) { // DMRS RE
uint16_t offset = (re_offset + re) % fp->ofdm_symbol_size;
for (int re = 0; re < SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL; re++) {
if (re % 4 == 0) { // DMRS RE
uint16_t offset = (re_offset + re) % fp->ofdm_symbol_size;
rsrp += c16amp2(rxF[offset]);
num_re++;
}
rsrp += c16amp2(rxF[offset]);
num_re++;
}
symbol = (symbol == 0) ? 5 : symbol + 1;
}
}
@@ -581,20 +567,33 @@ int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue,
// If needed this can be implemented. Reference Spec 38.215
}
psbch_rx->rsrp_dB_per_RE = 10 * log10(rsrp / num_re);
psbch_rx->rsrp_dBm_per_RE =
psbch_rx->rsrp_dB_per_RE + 30 - SQ15_SQUARED_NORM_FACTOR_DB
- ((int)openair0_cfg[ue->rf_map.card].rx_gain[0] - (int)openair0_cfg[ue->rf_map.card].rx_gain_offset[0])
- dB_fixed(fp->ofdm_symbol_size);
// Reset values
if (symbol == 0) {
psbch_rx->rsrp_dB_per_RE = 0;
psbch_rx->rsrp_dBm_per_RE = 0;
psbch_rx->rsrp_sum = 0;
psbch_rx->rsrp_re_sum = 0;
}
// Sum uptill symbol
psbch_rx->rsrp_sum += rsrp;
psbch_rx->rsrp_re_sum += num_re;
int adjust_rxgain = TARGET_RX_POWER - psbch_rx->rsrp_dB_per_RE;
LOG_D(PHY,
"PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE, adjust_rxgain:%d dB\n",
num_re,
psbch_rx->rsrp_dB_per_RE,
psbch_rx->rsrp_dBm_per_RE,
adjust_rxgain);
int adjust_rxgain = 0;
// Average of all REs in slot
if (symbol == maxsym - 1) {
psbch_rx->rsrp_dB_per_RE = 10 * log10(psbch_rx->rsrp_sum / psbch_rx->rsrp_re_sum);
psbch_rx->rsrp_dBm_per_RE =
psbch_rx->rsrp_dB_per_RE + 30 - SQ15_SQUARED_NORM_FACTOR_DB
- ((int)openair0_cfg[ue->rf_map.card].rx_gain[0] - (int)openair0_cfg[ue->rf_map.card].rx_gain_offset[0])
- dB_fixed(fp->ofdm_symbol_size);
adjust_rxgain = TARGET_RX_POWER - psbch_rx->rsrp_dB_per_RE;
LOG_D(PHY,
"PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE, adjust_rxgain:%d dB\n",
psbch_rx->rsrp_re_sum,
psbch_rx->rsrp_dB_per_RE,
psbch_rx->rsrp_dBm_per_RE,
adjust_rxgain);
}
return adjust_rxgain;
}

View File

@@ -962,7 +962,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
int G,
uint32_t nvar,
pdsch_scope_req_t *scope_req)
{

View File

@@ -45,7 +45,7 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
int *ssb_index,
int *symbol_offset,
fapiPbch_t *result,
const c16_t rxdataF[][frame_parms->samples_per_slot_wCP])
const c16_t rxdataF[NR_N_SYMBOLS_SSB][frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size])
{
const int N_L = (frame_parms->Lmax == 4) ? 4 : 8;
const int N_hf = (frame_parms->Lmax == 4) ? 2 : 1;
@@ -63,7 +63,7 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
Nid_cell,
ssb_start_subcarrier,
nr_gold_pbch(frame_parms->Lmax, Nid_cell, hf, l),
rxdataF);
rxdataF[i]);
csum(cumul, cumul, meas);
}
*current_ssb = (NR_UE_SSB){.i_ssb = l, .n_hf = hf, .metric = squaredMod(cumul)};
@@ -73,53 +73,54 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
qsort(best_ssb, N_L * N_hf, sizeof(NR_UE_SSB), ssb_sort);
const int nb_ant = frame_parms->nb_antennas_rx;
const int estimateSz = frame_parms->ofdm_symbol_size;
for (NR_UE_SSB *ssb = best_ssb; ssb < best_ssb + N_L * N_hf; ssb++) {
// computing channel estimation for selected best ssb
const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
__attribute__((aligned(32))) c16_t dl_ch_estimates[nb_ant][estimateSz];
__attribute__((aligned(32))) c16_t dl_ch_estimates_time[nb_ant][frame_parms->ofdm_symbol_size];
int16_t pbch_e_rx[NR_POLAR_PBCH_E];
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
nr_pbch_channel_estimation(frame_parms,
NULL,
estimateSz,
dl_ch_estimates,
dl_ch_estimates_time,
proc,
i,
i - pbch_initial_symbol,
ssb->i_ssb,
ssb->n_hf,
ssb_start_subcarrier,
rxdataF,
false,
Nid_cell);
for (int i = pbch_initial_symbol; i < pbch_initial_symbol + 3; i++) {
__attribute__((aligned(32))) c16_t dl_ch_estimates[nb_ant][estimateSz];
for (int aarx = 0; aarx < nb_ant; aarx++) {
nr_pbch_channel_estimation(frame_parms,
NULL,
dl_ch_estimates[aarx],
proc,
i - pbch_initial_symbol,
ssb->i_ssb,
ssb->n_hf,
ssb_start_subcarrier,
rxdataF[i][aarx],
false,
Nid_cell);
}
if (DUMP_PBCH_CH_ESTIMATES) {
char varName[30] = "";
snprintf(varName, sizeof(varName), "pbch_ch_estimates_symbol_%d", i);
LOG_MM("pbch_ch_estimates", varName, dl_ch_estimates, nb_ant * estimateSz, 1, 1);
}
nr_generate_pbch_llr(NULL,
proc,
frame_parms,
i,
ssb->i_ssb,
Nid_cell,
ssb_start_subcarrier,
rxdataF[i],
dl_ch_estimates,
pbch_e_rx);
}
if (0
== nr_rx_pbch(NULL,
proc,
false,
estimateSz,
dl_ch_estimates,
frame_parms,
ssb->i_ssb,
ssb_start_subcarrier,
Nid_cell,
result,
half_frame_bit,
ssb_index,
symbol_offset,
frame_parms->samples_per_frame_wCP,
rxdataF)) {
if (DUMP_PBCH_CH_ESTIMATES) {
write_output("pbch_ch_estimates.m", "pbch_ch_estimates", dl_ch_estimates, nb_ant * estimateSz, 1, 1);
write_output("pbch_ch_estimates_time.m",
"pbch_ch_estimates_time",
dl_ch_estimates_time,
nb_ant * frame_parms->ofdm_symbol_size,
1,
1);
}
== nr_pbch_decode(NULL,
frame_parms,
proc,
ssb->i_ssb,
Nid_cell,
pbch_e_rx,
half_frame_bit,
ssb_index,
symbol_offset,
result)) {
LOG_A(PHY, "Initial sync: pbch decoded sucessfully, ssb index %d\n", *ssb_index);
return true;
}
@@ -206,11 +207,17 @@ bool nr_search_ssb_common(nr_ssb_search_params_t *params)
// Extract SSB symbols to frequency domain
// Symbol ordering: 0=PSS, 1=PBCH, 2=SSS, 3=PBCH
const uint32_t rxdataF_sz = fp->samples_per_slot_wCP;
c16_t(*rxdataF)[rxdataF_sz] = (c16_t(*)[rxdataF_sz])params->rxdataF;
const int sample_offset = params->search_frame_id * fp->samples_per_frame + ssb_offset;
c16_t(*rxdataF)[NR_N_SYMBOLS_SSB][fp->nb_antennas_rx][fp->ofdm_symbol_size] =
(c16_t(*)[NR_N_SYMBOLS_SSB][fp->nb_antennas_rx][fp->ofdm_symbol_size])params->rxdataF;
__attribute__((aligned(32))) c16_t rxdataF_tmp[fp->nb_antennas_rx][fp->samples_per_slot_wCP];
for (int i = 0; i < NR_N_SYMBOLS_SSB; i++) {
nr_slot_fep(NULL, fp, 0, i, rxdataF, link_type_dl, sample_offset, (c16_t **)params->rxdata);
const int sample_offset = params->search_frame_id * fp->samples_per_frame + ssb_offset;
nr_slot_fep(NULL, fp, 0, i, rxdataF_tmp, link_type_dl, sample_offset, (c16_t **)params->rxdata);
// TODO: In later commit, call the modified symbol demod function and remove the following memcpy.
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++)
memcpy((*rxdataF)[i][aarx], &rxdataF_tmp[aarx][i * fp->ofdm_symbol_size], sizeof(c16_t) * fp->ofdm_symbol_size);
}
// Perform SSS detection
@@ -228,7 +235,7 @@ bool nr_search_ssb_common(nr_ssb_search_params_t *params)
&sss_metric,
&sss_phase,
&freq_offset_sss,
rxdataF);
*rxdataF);
if (params->sss_metric)
*params->sss_metric = sss_metric;
@@ -277,8 +284,7 @@ void nr_scan_ssb(void *arg)
for (int nid2 = 0; nid2 < pss_sequence; nid2++)
generate_pss_nr_time(fp, nid2, ssbInfo->gscnInfo.ssbFirstSC, pssTime[nid2]);
const uint32_t rxdataF_sz = fp->samples_per_slot_wCP;
__attribute__((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz];
__attribute__((aligned(32))) c16_t rxdataF[NR_N_SYMBOLS_SSB][fp->nb_antennas_rx][fp->ofdm_symbol_size];
// initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame
// only one frame is used for simulation tools
@@ -348,7 +354,7 @@ void nr_scan_ssb(void *arg)
&ssbInfo->pbchResult,
rxdataF); // start pbch detection at first symbol after pss
if (ssbInfo->syncRes.cell_detected) {
uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(ssbInfo->fp, rxdataF, 0, ssbInfo->gscnInfo.ssbFirstSC);
uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(ssbInfo->fp, rxdataF[2], ssbInfo->gscnInfo.ssbFirstSC);
int rsrp_db_per_re = 10 * log10(rsrp_avg);
ssbInfo->adjust_rxgain = TARGET_RX_POWER - rsrp_db_per_re;
LOG_I(PHY, "pbch rx ok. rsrp:%d dB/RE, adjust_rxgain:%d dB\n", rsrp_db_per_re, ssbInfo->adjust_rxgain);

View File

@@ -432,6 +432,10 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc,
__attribute__((aligned(32))) c16_t rxdataF[frame_parms->nb_antennas_rx][rxdataF_sz];
/* In order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2] = {0};
int16_t psbch_unClipped[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2] = {0};
int psbch_e_rx_offset = 0;
for (int symbol = 0; symbol < SL_NR_NUMSYM_SLSS_NORMAL_CP; symbol++) {
nr_slot_fep(UE,
frame_parms,
@@ -443,39 +447,50 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc,
UE->common_vars.rxdata);
}
/* TODO: change this function to use new rxdataF format */
sl_nr_extract_sss(UE, &metric_tdd_ncp, &phase_tdd_ncp, rxdataF);
// save detected cell id to psbch
rx_slss_id = UE->SL_UE_PHY_PARAMS.sync_params.N_sl_id;
__attribute__((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][rxdataF_sz];
__attribute__((
aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
uint8_t decoded_output[4];
for (int symbol = 0; symbol < SL_NR_NUMSYM_SLSS_NORMAL_CP - 1;) {
nr_pbch_channel_estimation(frame_parms,
&UE->SL_UE_PHY_PARAMS,
rxdataF_sz,
dl_ch_estimates,
dl_ch_estimates_time,
proc,
symbol,
symbol,
0,
0,
frame_parms->ssb_start_subcarrier,
rxdataF,
1,
rx_slss_id);
__attribute__((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
__attribute__((aligned(32))) c16_t rxdataF_symb[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
/* TODO: Change sl sss extract to follow the new rxdataF format */
memcpy(rxdataF_symb[aarx],
&rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size],
sizeof(c16_t) * frame_parms->ofdm_symbol_size);
nr_pbch_channel_estimation(frame_parms,
&UE->SL_UE_PHY_PARAMS,
dl_ch_estimates[aarx],
proc,
symbol,
0,
0,
frame_parms->ssb_start_subcarrier,
rxdataF_symb[aarx],
true,
rx_slss_id);
}
nr_generate_psbch_llr(frame_parms,
rxdataF_symb,
dl_ch_estimates,
symbol,
&psbch_e_rx_offset,
psbch_e_rx,
psbch_unClipped);
UE->adjust_rxgain = nr_sl_psbch_rsrp_measurements(UE, sl_ue, frame_parms, symbol, rxdataF, false);
symbol = (symbol == 0) ? 5 : symbol + 1;
}
ret = nr_rx_psbch(UE, proc, rxdataF_sz, dl_ch_estimates, frame_parms, decoded_output, rxdataF, rx_slss_id);
ret = nr_psbch_decode(UE, psbch_e_rx, proc, psbch_e_rx_offset, rx_slss_id, NULL, decoded_output);
result.cell_detected = (ret == 0) ? true : false;
result.cell_detected = (ret == 0);
if (result.cell_detected) { // Check this later TBD
// sync at symbol ue->symbol_offset
@@ -504,8 +519,6 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc,
sync_params->DFN,
sync_params->slot_offset);
UE->adjust_rxgain = nr_sl_psbch_rsrp_measurements(UE, sl_ue, frame_parms, rxdataF, false);
UE->init_sync_frame = sync_params->remaining_frames;
result.rx_offset = sync_params->rx_offset;

View File

@@ -23,16 +23,14 @@
#define PBCH_MAX_RE (PBCH_MAX_RE_PER_SYMBOL*4)
#define print_shorts(s,x) printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s,((int16_t*)x)[0],((int16_t*)x)[1],((int16_t*)x)[2],((int16_t*)x)[3],((int16_t*)x)[4],((int16_t*)x)[5],((int16_t*)x)[6],((int16_t*)x)[7])
static uint16_t nr_pbch_extract(uint32_t rxdataF_sz,
const c16_t rxdataF[][rxdataF_sz],
const int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
static uint16_t nr_pbch_extract(const NR_DL_FRAME_PARMS *frame_parms,
const c16_t rxdataF[][frame_parms->ofdm_symbol_size],
const c16_t dl_ch_estimates[][frame_parms->ofdm_symbol_size],
struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
uint32_t symbol,
uint32_t s_offset,
int ssb_start_subcarrier,
const NR_DL_FRAME_PARMS *frame_parms,
int nid)
{
uint16_t rb;
@@ -45,7 +43,7 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz,
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
unsigned int rx_offset = frame_parms->first_carrier_offset + ssb_start_subcarrier;
rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size);
const struct complex16 *rxF = &rxdataF[aarx][(symbol + s_offset) * frame_parms->ofdm_symbol_size];
const struct complex16 *rxF = rxdataF[aarx];
struct complex16 *rxF_ext = rxdataF_ext[aarx];
#ifdef DEBUG_PBCH
printf("extract_rbs (nushift %d): rx_offset=%d, symbol %u\n",
@@ -117,7 +115,7 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz,
}
}
struct complex16 *dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))];
const struct complex16 *dl_ch0 = dl_ch_estimates[aarx];
//printf("dl_ch0 addr %p\n",dl_ch0);
struct complex16 *dl_ch0_ext = dl_ch_estimates_ext[aarx];
@@ -178,8 +176,8 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz,
return(0);
}
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
void nr_pbch_channel_compensation(const struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
const struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
int nb_re,
struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL],
const NR_DL_FRAME_PARMS *frame_parms,
@@ -257,7 +255,7 @@ void nr_pbch_unscrambling(int16_t *demod_pbch_e,
}
}
void nr_pbch_quantize(int16_t *pbch_llr8, int16_t *pbch_llr, uint16_t len)
void nr_pbch_quantize(int16_t *pbch_llr8, const int16_t *pbch_llr, const uint16_t len)
{
for (int i=0; i<len; i++) {
if (pbch_llr[i]>31)
@@ -277,124 +275,127 @@ unsigned char sign(int8_t x) {
const uint8_t pbch_deinterleaving_pattern[32] = {28, 0, 31, 30, 7, 29, 25, 27, 5, 8, 24, 9, 10, 11, 12, 13,
1, 4, 3, 14, 15, 16, 17, 2, 26, 18, 19, 20, 21, 22, 6, 23};
int nr_rx_pbch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
bool is_synchronized,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
const NR_DL_FRAME_PARMS *frame_parms,
uint8_t i_ssb,
int ssb_start_subcarrier,
int Nid_cell,
fapiPbch_t *result,
int *half_frame_bit,
int *ssb_index,
int *ret_symbol_offset,
int rxdataFSize,
const struct complex16 rxdataF[][rxdataFSize])
void nr_generate_pbch_llr(const PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
const NR_DL_FRAME_PARMS *frame_parms,
const int symbolSSB,
const int i_ssb,
const int nid,
const int ssb_start_subcarrier,
const c16_t rxdataF[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size],
const c16_t dl_ch_estimates[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size],
int16_t pbch_e_rx[NR_POLAR_PBCH_E])
{
TracyCZone(ctx, true);
int symbol;
uint8_t Lmax=frame_parms->Lmax;
int M = NR_POLAR_PBCH_E;
int nushift = (Lmax == 4) ? i_ssb & 3 : i_ssb & 7;
int16_t pbch_e_rx[960]= {0}; //Fixme: previous version erase only NR_POLAR_PBCH_E bytes
int16_t pbch_unClipped[960]= {0};
int pbch_e_rx_idx=0;
int symbol_offset=1;
const int symbol_offset = nr_get_ssb_start_symbol(frame_parms, i_ssb) % (NR_SYMBOLS_PER_SLOT);
const int nb_re = (symbolSSB == 2) ? 72 : 180;
if (is_synchronized)
symbol_offset=nr_get_ssb_start_symbol(frame_parms, i_ssb)%(frame_parms->symbols_per_slot);
else
symbol_offset=0;
__attribute__((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
__attribute__((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
memset(dl_ch_estimates_ext, 0, sizeof dl_ch_estimates_ext);
nr_pbch_extract(frame_parms,
rxdataF,
dl_ch_estimates,
rxdataF_ext,
dl_ch_estimates_ext,
symbolSSB,
symbol_offset,
ssb_start_subcarrier,
nid);
#ifdef DEBUG_PBCH
//printf("address dataf %p",nr_ue_common_vars->rxdataF);
write_output("rxdataF0_pbch.m","rxF0pbch",
&rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1);
LOG_I(PHY, "[PHY] PBCH Symbol %d ofdm size %d\n", symbolSSB, frame_parms->ofdm_symbol_size);
LOG_I(PHY, "[PHY] PBCH starting channel_level\n");
#endif
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
double log2_maxh = 0;
for (symbol=1; symbol<4; symbol++) {
const uint16_t nb_re=symbol == 2 ? 72 : 180;
__attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
nr_pbch_extract(frame_parms->samples_per_slot_wCP,
rxdataF,
estimateSz,
dl_ch_estimates,
rxdataF_ext,
dl_ch_estimates_ext,
symbol,
symbol_offset,
ssb_start_subcarrier,
frame_parms,
Nid_cell);
#ifdef DEBUG_PBCH
LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size);
LOG_I(PHY,"[PHY] PBCH starting channel_level\n");
#endif
int max_h = 0;
if (symbol == 1) {
int avg[frame_parms->nb_antennas_rx];
nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re);
max_h = avg[0];
for (int i = 1; i < frame_parms->nb_antennas_rx; i++)
max_h = cmax(avg[i], max_h);
log2_maxh = 3 + (log2_approx(max_h) / 2);
}
#ifdef DEBUG_PBCH
LOG_I(PHY,"[PHY] PBCH log2_maxh = %f (%d)\n", log2_maxh, max_h);
#endif
__attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
nr_pbch_channel_compensation(rxdataF_ext,
dl_ch_estimates_ext,
nb_re,
rxdataF_comp,
frame_parms,
log2_maxh); // log2_maxh+I0_shift
/*if (frame_parms->nb_antennas_rx > 1)
pbch_detection_mrc(frame_parms,
rxdataF_comp,
symbol);*/
int nb=symbol==2 ? 144 : 360;
nr_pbch_quantize(pbch_e_rx+pbch_e_rx_idx,
(short *)rxdataF_comp[0],
nb);
memcpy(pbch_unClipped+pbch_e_rx_idx, rxdataF_comp[0], nb*sizeof(int16_t));
pbch_e_rx_idx+=nb;
uint32_t max_h = 0;
if (symbolSSB == 1) {
int avg[frame_parms->nb_antennas_rx];
nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re);
max_h = avg[0];
for (int i = 1; i < frame_parms->nb_antennas_rx; i++)
max_h = cmax(avg[i], max_h);
log2_maxh = 3 + (log2_approx(max_h) / 2);
}
#ifdef DEBUG_PBCH
LOG_I(PHY, "[PHY] PBCH log2_maxh = %f (%d)\n", log2_maxh, max_h);
#endif
__attribute__((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
nr_pbch_channel_compensation(rxdataF_ext, dl_ch_estimates_ext, nb_re, rxdataF_comp, frame_parms,
log2_maxh); // log2_maxh+I0_shift
/*if (frame_parms->nb_antennas_rx > 1)
pbch_detection_mrc(frame_parms,
rxdataF_comp,
symbol);*/
/*
if (mimo_mode == ALAMOUTI) {
nr_pbch_alamouti(frame_parms,rxdataF_comp,symbol);
} else if (mimo_mode != SISO) {
LOG_I(PHY,"[PBCH][RX] Unsupported MIMO mode\n");
return(-1);
}
*/
int pbch_e_rx_idx = 0;
if (symbolSSB == 1) {
pbch_e_rx_idx = 0;
} else if (symbolSSB == 2) {
pbch_e_rx_idx = 360;
} else if (symbolSSB == 3) {
pbch_e_rx_idx = 360 + 144;
}
// legacy code use int16, but it is complex16
if (ue) {
metadata meta = {.slot = proc->nr_slot_rx, .frame = proc->frame_rx};
UEscopeCopyWithMetadata(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx / 2, 0, &meta);
UEscopeCopyWithMetadata(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx, 0, &meta);
UEscopeCopyWithMetadata(ue, pbchRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), 1, nb_re, pbch_e_rx_idx / 2, &meta);
}
const int nb = (symbolSSB == 2) ? 144 : 360;
nr_pbch_quantize(pbch_e_rx + pbch_e_rx_idx, (short *)rxdataF_comp[0], nb);
#ifdef DEBUG_PBCH
char fname[50];
sprintf(fname, "rxdataF_comp_%d.m", symbolSSB);
write_output(fname, "rxFcomp", rxdataF[0], 240, 1, 1);
for (int cnt = 0; cnt < 864 ; cnt++)
printf("pbch rx llr %d\n", *(pbch_e_rx + cnt));
#endif
}
int nr_pbch_decode(PHY_VARS_NR_UE *ue,
const NR_DL_FRAME_PARMS *frame_parms,
const UE_nr_rxtx_proc_t *proc,
const int i_ssb,
const int Nid_cell,
int16_t pbch_e_rx[NR_POLAR_PBCH_E],
int *half_frame_bit,
int *ssb_index,
int *ret_symbol_offset,
fapiPbch_t *result)
{
if (ue) {
UEscopeCopy(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, NR_POLAR_PBCH_E, 0);
}
// un-scrambling
uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041;
uint32_t pbch_a_interleaved=0;
uint32_t pbch_a_prime=0;
nr_pbch_unscrambling(pbch_e_rx, Nid_cell, nushift, M, NR_POLAR_PBCH_E,
0, 0, pbch_a_prime, &pbch_a_interleaved);
const uint8_t Lmax = frame_parms->Lmax;
const int unscrambling_mask = (Lmax == 64) ? 0x100006D : 0x1000041;
unsigned int pbch_a_interleaved = 0;
int pbch_a_prime = 0;
int M = NR_POLAR_PBCH_E;
int nushift = (Lmax == 4) ? i_ssb & 3 : i_ssb & 7;
nr_pbch_unscrambling(pbch_e_rx, Nid_cell, nushift, M, NR_POLAR_PBCH_E, 0, 0, pbch_a_prime, &pbch_a_interleaved);
//polar decoding de-rate matching
uint64_t tmp=0;
const uint32_t decoderState = polar_decoder_int16(pbch_e_rx,
(uint64_t *)&tmp,
0,
NR_POLAR_PBCH_MESSAGE_TYPE,
NR_POLAR_PBCH_PAYLOAD_BITS,
NR_POLAR_PBCH_AGGREGATION_LEVEL);
uint64_t tmp = 0;
const int decoderState = polar_decoder_int16(pbch_e_rx,
(uint64_t *)&tmp,
0,
NR_POLAR_PBCH_MESSAGE_TYPE,
NR_POLAR_PBCH_PAYLOAD_BITS,
NR_POLAR_PBCH_AGGREGATION_LEVEL);
pbch_a_prime = tmp;
nr_downlink_indication_t dl_indication;
@@ -453,7 +454,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
*ret_symbol_offset += (frame_parms->slots_per_frame >> 1) * frame_parms->symbols_per_slot;
#ifdef DEBUG_PBCH
printf("xtra_byte %x payload %x\n", result->xtra_byte, payload);
printf("xtra_byte %x payload %lx\n", result->xtra_byte, payload);
for (int i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++) {
// printf("unscrambling pbch_a[%d] = %x \n", i,pbch_a[i]);
@@ -475,14 +476,10 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
}
double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms,
int estimateSz,
const c16_t dl_ch_estimates[][estimateSz])
const c16_t dl_ch_est_symb1[NR_PBCH_NUM_RB * NR_NB_SC_PER_RB],
const c16_t dl_ch_est_symb3[NR_PBCH_NUM_RB * NR_NB_SC_PER_RB])
{
const int i_ssb = frame_parms->ssb_index;
const int symbol_offset = nr_get_ssb_start_symbol(frame_parms, i_ssb) % frame_parms->symbols_per_slot;
const c16_t *dl_ch_est_symb1 = &dl_ch_estimates[0][(symbol_offset + 1) * frame_parms->ofdm_symbol_size];
const c16_t *dl_ch_est_symb3 = &dl_ch_estimates[0][(symbol_offset + 3) * frame_parms->ofdm_symbol_size];
const int nb_re = 240;
const int nb_re = NR_PBCH_NUM_RB * NR_NB_SC_PER_RB;
const c32_t dot_prod_res = dot_product(dl_ch_est_symb1, dl_ch_est_symb3, nb_re, 8);
const double res_phase = atan2(dot_prod_res.i, dot_prod_res.r);
const int samples_per_symbol = frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples;

View File

@@ -327,7 +327,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
// This is after cyclic prefix
const idft_size_idx_t idft_size = get_idft(dftlen);
idft(idft_size, (int16_t *)prachF, (int16_t *)prach, 1);
idft(idft_size, (int16_t *)prachF, (int16_t *)prach, get_idft_scaling(dftlen, 0));
}
c16_t *out = txData[0] + prach_start;

View File

@@ -12,18 +12,17 @@
// #define DEBUG_PSBCH
static void nr_psbch_extract(uint32_t rxdataF_sz,
c16_t rxdataF[][rxdataF_sz],
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
static void nr_psbch_extract(uint32_t dataF_sz,
const c16_t rxdataF[][dataF_sz],
const struct complex16 dl_ch_estimates[][dataF_sz],
struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
uint32_t symbol,
NR_DL_FRAME_PARMS *frame_params)
const NR_DL_FRAME_PARMS *frame_params)
{
uint16_t rb;
uint8_t i, j, aarx;
struct complex16 *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext;
struct complex16 *dl_ch0_ext, *rxF_ext;
const uint8_t nb_rb = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL;
AssertFatal((symbol == 0 || symbol >= 5), "SIDELINK: PSBCH DMRS not contained in symbol %d \n", symbol);
@@ -32,11 +31,11 @@ static void nr_psbch_extract(uint32_t rxdataF_sz,
unsigned int rx_offset = frame_params->first_carrier_offset + frame_params->ssb_start_subcarrier;
rx_offset = rx_offset % frame_params->ofdm_symbol_size;
rxF = &rxdataF[aarx][symbol * frame_params->ofdm_symbol_size];
rxF_ext = &rxdataF_ext[aarx][0];
const c16_t *rxF = rxdataF[aarx];
rxF_ext = rxdataF_ext[aarx];
dl_ch0 = &dl_ch_estimates[aarx][symbol * frame_params->ofdm_symbol_size];
dl_ch0_ext = &dl_ch_estimates_ext[aarx][0];
const c16_t *dl_ch0 = dl_ch_estimates[aarx];
dl_ch0_ext = dl_ch_estimates_ext[aarx];
#ifdef DEBUG_PSBCH
LOG_I(PHY, "extract_rbs: rx_offset=%d, symbol %u\n", (rx_offset + (symbol * frame_params->ofdm_symbol_size)), symbol);
@@ -93,105 +92,66 @@ static void nr_psbch_extract(uint32_t rxdataF_sz,
return;
}
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t *decoded_output,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
uint16_t slss_id)
void nr_generate_psbch_llr(const NR_DL_FRAME_PARMS *frame_parms,
const c16_t rxdataF[][frame_parms->ofdm_symbol_size],
const c16_t dl_ch_estimates[][frame_parms->ofdm_symbol_size],
int symbol,
int *psbch_e_rx_offset,
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2],
int16_t psbch_unClipped[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2])
{
uint32_t decoderState = 0;
int psbch_e_rx_idx = 0;
// Extra 2 bits needed as polar decoder expects a multiple of 4 as encoder length
// If these 2 bits are not added, runs compiled with --sanitize will fail.
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2] = {0};
int16_t psbch_unClipped[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2] = {0};
const uint16_t nb_re = SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL;
__attribute__((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][nb_re + 1];
__attribute__((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][nb_re + 1];
// memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
nr_psbch_extract(frame_parms->ofdm_symbol_size, rxdataF, dl_ch_estimates, rxdataF_ext, dl_ch_estimates_ext, symbol, frame_parms);
#ifdef DEBUG_PSBCH
write_output("psbch_rxdataF.m",
"psbchrxF",
&rxdataF[0][0],
frame_parms->ofdm_symbol_size * SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP,
1,
1);
LOG_I(PHY, "PSBCH RX Symbol %d ofdm size %d\n", symbol, frame_parms->ofdm_symbol_size);
#endif
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
double log2_maxh = 0;
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
const int numsym = (frame_parms->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP : SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
for (int symbol = 0; symbol < numsym;) {
const uint16_t nb_re = SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL;
__attribute__((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][nb_re + 1];
__attribute__((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][nb_re + 1];
// memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
nr_psbch_extract(frame_parms->samples_per_slot_wCP,
rxdataF,
estimateSz,
dl_ch_estimates,
rxdataF_ext,
dl_ch_estimates_ext,
symbol,
frame_parms);
#ifdef DEBUG_PSBCH
LOG_I(PHY, "PSBCH RX Symbol %d ofdm size %d\n", symbol, frame_parms->ofdm_symbol_size);
#endif
int max_h = 0;
if (symbol == 0) {
int avg[frame_parms->nb_antennas_rx];
nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re);
max_h = avg[0];
for (int i = 1; i < frame_parms->nb_antennas_rx; i++)
max_h = cmax(avg[i], max_h);
log2_maxh = 5 + (log2_approx(max_h) / 2); // LLR32 crc error. LLR 16 CRC works
}
#ifdef DEBUG_PSBCH
LOG_I(PHY, "PSBCH RX log2_maxh = %f (%d)\n", log2_maxh, max_h);
#endif
__attribute__((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][nb_re + 1];
nr_pbch_channel_compensation(rxdataF_ext,
dl_ch_estimates_ext,
nb_re,
rxdataF_comp,
frame_parms,
log2_maxh); // log2_maxh+I0_shift
nr_pbch_quantize(psbch_e_rx + psbch_e_rx_idx, (short *)rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL);
if (ue->scopeData)
memcpy(psbch_unClipped + psbch_e_rx_idx, rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL * sizeof(int16_t));
psbch_e_rx_idx += SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL;
// SKIP 2 SL-PSS AND 2 SL-SSS symbols
// Symbols carrying PSBCH 0, 5-12
symbol = (symbol == 0) ? 5 : symbol + 1;
int max_h = 0;
if (symbol == 0) {
int avg[frame_parms->nb_antennas_rx];
nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re);
max_h = avg[0];
for (int i = 1; i < frame_parms->nb_antennas_rx; i++)
max_h = cmax(avg[i], max_h);
log2_maxh = 5 + (log2_approx(max_h) / 2); // LLR32 crc error. LLR 16 CRC works
}
UEscopeCopy(ue, psbchRxdataF_comp, psbch_unClipped, sizeof(c16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx / 2, 0);
UEscopeCopy(ue, psbchLlr, psbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx, 0);
#ifdef DEBUG_PSBCH
write_output("psbch_rxdataFcomp.m", "psbch_rxFcomp", psbch_unClipped, SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS, 1, 1);
LOG_I(PHY, "PSBCH RX log2_maxh = %f (%d)\n", log2_maxh, max_h);
#endif
// un-scrambling
LOG_D(PHY, "PSBCH RX POLAR DECODING: total PSBCH bits:%d, rx_slss_id:%d\n", psbch_e_rx_idx, slss_id);
__attribute__((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][nb_re + 1];
nr_pbch_channel_compensation(rxdataF_ext, dl_ch_estimates_ext, nb_re, rxdataF_comp, frame_parms,
log2_maxh); // log2_maxh+I0_shift
nr_pbch_unscrambling(psbch_e_rx, slss_id, 0, 0, psbch_e_rx_idx, 0, 0, 0, NULL);
nr_pbch_quantize(psbch_e_rx + *psbch_e_rx_offset, (short *)rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL);
memcpy(psbch_unClipped + *psbch_e_rx_offset, (short *)rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL);
*psbch_e_rx_offset += SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL;
}
int nr_psbch_decode(PHY_VARS_NR_UE *ue,
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2],
const UE_nr_rxtx_proc_t *proc,
int psbch_e_rx_len,
int slss_id,
nr_phy_data_t *phy_data,
uint8_t decoded_pdu[4])
{
// un-scrambling
LOG_D(PHY, "PSBCH RX POLAR DECODING: total PSBCH bits:%d, rx_slss_id:%d\n", psbch_e_rx_len, slss_id);
nr_pbch_unscrambling(psbch_e_rx, slss_id, 0, 0, psbch_e_rx_len, 0, 0, 0, NULL);
// polar decoding de-rate matching
uint64_t tmp = 0;
decoderState = polar_decoder_int16(psbch_e_rx,
(uint64_t *)&tmp,
0,
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
const uint32_t decoderState = polar_decoder_int16(psbch_e_rx,
(uint64_t *)&tmp,
0,
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
uint32_t psbch_payload = tmp;
@@ -208,11 +168,11 @@ int nr_rx_psbch(PHY_VARS_NR_UE *ue,
psbch_payload = a_reversed;
*((uint32_t *)decoded_output) = psbch_payload;
*((uint32_t *)decoded_pdu) = psbch_payload;
#ifdef DEBUG_PSBCH
for (int i = 0; i < 4; i++) {
LOG_I(PHY, "decoded_output[%d]:%x\n", i, decoded_output[i]);
LOG_I(PHY, "decoded_output[%d]:%x\n", i, decoded_pdu[i]);
}
#endif
@@ -223,7 +183,30 @@ int nr_rx_psbch(PHY_VARS_NR_UE *ue,
DFN = (((psbch_payload & 0x0700) >> 1) | ((psbch_payload & 0xFE0000) >> 17));
slot_offset = (((psbch_payload & 0x010000) >> 10) | ((psbch_payload & 0xFC000000) >> 26));
LOG_D(PHY, "PSBCH RX SL-MIB:%x, decoded DFN:slot %d:%d, %x\n", psbch_payload, DFN, slot_offset, *(uint32_t *)decoded_output);
LOG_D(PHY, "PSBCH RX SL-MIB:%x, decoded DFN:slot %d:%d, %x\n", psbch_payload, DFN, slot_offset, *(uint32_t *)decoded_pdu);
nr_sidelink_indication_t sl_indication;
sl_nr_rx_indication_t rx_ind = {0};
uint16_t number_pdus = 1;
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
uint16_t rx_slss_id = sl_phy_params->sl_config.sl_sync_source.rx_slss_id;
uint8_t *result = NULL;
result = decoded_pdu;
sl_phy_params->psbch.rx_ok++;
LOG_I(NR_PHY,
"[UE%d] %d:%d PSBCH RX:OK. RSRP: %d dB/RE\n",
ue->Mod_id,
proc->frame_rx,
proc->nr_slot_rx,
sl_phy_params->psbch.rsrp_dB_per_RE);
nr_fill_sl_indication(&sl_indication, &rx_ind, NULL, proc, ue, phy_data);
nr_fill_sl_rx_indication(&rx_ind, SL_NR_RX_PDU_TYPE_SSB, ue, number_pdus, (void *)result, rx_slss_id);
if (ue->if_inst && ue->if_inst->sl_indication)
ue->if_inst->sl_indication(&sl_indication);
return 0;
}

View File

@@ -12,6 +12,7 @@
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include <math.h>
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
#define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1
#define NR_PUSCH_y 3 // UCI placeholder bit
@@ -178,25 +179,9 @@ int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uin
\returns number of tx antennas or -1 if error
*/
int nr_rx_pbch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
bool is_synchronized,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
const NR_DL_FRAME_PARMS *frame_parms,
uint8_t i_ssb,
int ssb_start_subcarrier,
int Nid_cell,
fapiPbch_t *result,
int *half_frame_bit,
int *ssb_index,
int *ret_symbol_offset,
int rxdataFSize,
const struct complex16 rxdataF[][rxdataFSize]);
double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms,
int estimateSz,
const c16_t dl_ch_estimates[][estimateSz]);
const c16_t dl_ch_est_symb1[NR_PBCH_NUM_RB * NR_NB_SC_PER_RB],
const c16_t dl_ch_est_symb3[NR_PBCH_NUM_RB * NR_NB_SC_PER_RB]);
#ifndef modOrder
#define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS
@@ -297,7 +282,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
int G,
uint32_t nvar,
pdsch_scope_req_t *scope_req);
@@ -316,36 +300,63 @@ void apply_ntn_timing_advance_and_doppler(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_
void dump_nrdlsch(PHY_VARS_NR_UE *ue,uint8_t gNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid);
void nr_a_sum_b(c16_t *input_x, c16_t *input_y, unsigned short nb_rb);
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t *decoded_output,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
uint16_t slss_id);
void nr_generate_psbch_llr(const NR_DL_FRAME_PARMS *frame_parms,
const c16_t rxdataF[][frame_parms->ofdm_symbol_size],
const c16_t dl_ch_estimates[][frame_parms->ofdm_symbol_size],
int symbol,
int *psbch_e_rx_offset,
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2],
int16_t psbch_unClipped[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2]);
int nr_psbch_decode(PHY_VARS_NR_UE *ue,
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP + 2],
const UE_nr_rxtx_proc_t *proc,
int psbch_e_rx_len,
int slss_id,
nr_phy_data_t *phy_data,
uint8_t decoded_pdu[4]);
void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx, sl_nr_tx_config_psbch_pdu_t *psbch_vars, c16_t **txdataF);
nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames);
// Reuse already existing PBCH functions
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
void nr_pbch_channel_compensation(const struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
const struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
int nb_re,
struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL],
const NR_DL_FRAME_PARMS *frame_parms,
uint8_t output_shift);
const uint8_t output_shift);
void nr_pbch_unscrambling(int16_t *demod_pbch_e,
uint16_t Nid,
uint8_t nushift,
uint16_t M,
uint16_t length,
uint8_t bitwise,
uint32_t unscrambling_mask,
uint32_t pbch_a_prime,
const uint16_t Nid,
const uint8_t nushift,
const uint16_t M,
const uint16_t length,
const uint8_t bitwise,
const uint32_t unscrambling_mask,
const uint32_t pbch_a_prime,
uint32_t *pbch_a_interleaved);
void nr_pbch_quantize(int16_t *pbch_llr8, int16_t *pbch_llr, uint16_t len);
void nr_pbch_quantize(int16_t *pbch_llr8, const int16_t *pbch_llr, const uint16_t len);
void nr_generate_pbch_llr(const PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
const NR_DL_FRAME_PARMS *frame_parms,
const int symbolSSB,
const int i_ssb,
const int nid,
const int ssb_start_subcarrier,
const c16_t rxdataF[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size],
const c16_t dl_ch_estimates[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size],
int16_t pbch_e_rx[NR_POLAR_PBCH_E]);
int nr_pbch_decode(PHY_VARS_NR_UE *ue,
const NR_DL_FRAME_PARMS *frame_parms,
const UE_nr_rxtx_proc_t *proc,
const int i_ssb,
const int Nid_cell,
int16_t pbch_e_rx[NR_POLAR_PBCH_E],
int *half_frame_bit,
int *ssb_index,
int *ret_symbol_offset,
fapiPbch_t *result);
/**@}*/
#endif

View File

@@ -131,7 +131,7 @@ void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssb
idft((int16_t)get_idft(fp->ofdm_symbol_size),
(int16_t *)synchroF_tmp, /* complex input but legacy type is wrong*/
(int16_t *)pssTime, /* complex output */
1); /* scaling factor */
get_idft_scaling(fp->ofdm_symbol_size, 1)); /* scaling factor */
#ifdef DBG_PSS_NR
@@ -621,7 +621,7 @@ void sl_generate_pss_ifft_samples(sl_nr_ue_phy_params_t *sl_ue_params, SL_NR_UE_
idft((int16_t)get_idft(sl_fp->ofdm_symbol_size),
(int16_t *)&pss_F[0], /* complex input */
(int16_t *)&pss_T[0], /* complex output */
1); /* scaling factor */
get_idft_scaling(sl_fp->ofdm_symbol_size, 1)); /* scaling factor */
}
#ifdef SL_DUMP_PSBCH_TX_SAMPLES

View File

@@ -144,22 +144,22 @@ static void pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms,
* DESCRIPTION : it allows extracting sss from samples buffer
*
*********************************************************************/
static void pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR],
int ssb_start_subcarrier,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both
static void pss_sss_extract_nr(
const NR_DL_FRAME_PARMS *frame_parms,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR],
int ssb_start_subcarrier,
const c16_t rxdataF[NR_N_SYMBOLS_SSB][frame_parms->nb_antennas_rx]
[frame_parms->ofdm_symbol_size]) // add flag to indicate extracting only PSS, only SSS, or both
{
AssertFatal(frame_parms->nb_antennas_rx > 0, "nb antennas as sss_ext is not set to any value\n");
const unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
const int pss_symbol = 0;
const int sss_symbol =
get_softmodem_params()->sl_mode == 0 ? (SSS_SYMBOL_NB - PSS_SYMBOL_NB) : (SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB);
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
c16_t *pss_rxF = rxdataF[aarx] + pss_symbol * ofdm_symbol_size;
c16_t *sss_rxF = rxdataF[aarx] + sss_symbol * ofdm_symbol_size;
const c16_t *pss_rxF = rxdataF[pss_symbol][aarx];
const c16_t *sss_rxF = rxdataF[sss_symbol][aarx];
c16_t *pss_rxF_ext = pss_ext[aarx];
c16_t *sss_rxF_ext = sss_ext[aarx];
unsigned int k = frame_parms->first_carrier_offset + ssb_start_subcarrier
@@ -196,7 +196,7 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
int32_t *tot_metric,
uint8_t *phase_max,
int *freq_offset_sss,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP])
c16_t rxdataF[NR_N_SYMBOLS_SSB][frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size])
{
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR];
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR];

View File

@@ -1,14 +1,16 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
oai_dfts_sse4: oai_dfts.c
gcc -O3 -std=gnu99 -msse4.1 -o oai_dfts_sse4 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS
gcc -O3 -std=gnu99 -msse4.1 -o oai_dfts_sse4 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -DNB_ANTENNAS_TX=1 -lm -lpthread # -DD256STATS #-DD64STATS
oai_dfts_avx2: oai_dfts.c
gcc -O2 -std=gnu99 -mavx2 -g -ggdb -o oai_dfts_avx2 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS
oai_dfts_avx2: oai_dfts.c fft_double.c
gcc -O2 -std=gnu99 -mavx2 -fno-semantic-interposition -g -ggdb -o oai_dfts_avx2 fft_double.c oai_dfts.c ../../../common/utils/time_meas.c ../../SIMULATION/TOOLS/taus.c ../../SIMULATION/TOOLS/rangen_double.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -I$$OPENAIR_HOME/executables -DMR_MAIN -DNB_ANTENNAS_RX=1 -DNB_ANTENNAS_TX=1 -DMAX_NUM_CCs=1 -lm -lpthread # -DD256STATS #-DD64STATS
oai_dfts_avx2.s: oai_dfts.c
gcc -O2 -std=gnu99 -mavx2 -S oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS
oai_dfts_avx512: oai_dfts.c fft_double.c
gcc -O2 -std=gnu99 -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512 -fno-semantic-interposition -g -ggdb -o oai_dfts_avx512 fft_double.c oai_dfts.c ../../../common/utils/time_meas.c ../../SIMULATION/TOOLS/taus.c ../../SIMULATION/TOOLS/rangen_double.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -I$$OPENAIR_HOME/executables -DMR_MAIN -DNB_ANTENNAS_RX=1 -DNB_ANTENNAS_TX=1 -DMAX_NUM_CCs=1 -lm -lpthread # -DD256STATS #-DD64STATS
oai_dfts_sse4.s: oai_dfts.c
gcc -O2 -std=gnu99 -msse4.1 -S oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS
@@ -17,5 +19,5 @@ oai_dfts_sse4.s: oai_dfts.c
dft_cycles_avx2: oai_dfts_avx2
./oai_dfts_avx2 | grep -E cycles
oai_dfts_aarch64: oai_dfts_neon.c
gcc -O2 -std=gnu99 -gdwarf-2 -lgcc -lrt -g -ggdb -o oai_dfts_neon oai_dfts_neon.c ../../../common/utils/time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/LOG/log.c ../../SIMULATION/TOOLS/rangen_double.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -DNB_ANTENNAS_TX=1 -DMAX_NUM_CCs=1 -lm -lpthread
oai_dfts_aarch64: oai_dfts_neon.c fft_double.c
gcc -O2 -std=gnu99 -gdwarf-2 -lgcc -lrt -g -ggdb -fno-semantic-interposition -o oai_dfts_neon fft_double.c oai_dfts_neon.c ../../../common/utils/time_meas.c ../../SIMULATION/TOOLS/taus.c ../../SIMULATION/TOOLS/rangen_double.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_HOME/radio/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -I$$OPENAIR_HOME/executables -DMR_MAIN -DNB_ANTENNAS_RX=1 -DNB_ANTENNAS_TX=1 -DMAX_NUM_CCs=1 -lm -lpthread

View File

@@ -12,8 +12,8 @@
#include "assertions.h"
#include "common/utils/LOG/log.h"
#include "tools_defs.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
/* function description array, to be used when loading the dfts/idfts lib */

View File

@@ -0,0 +1,89 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "tools_defs.h"
void twiddle(cd_t *W, int N, double stuff)
{
W->r=cos(stuff*2.0*M_PI/(double)N);
W->i=-sin(stuff*2.0*M_PI/(double)N);
}
int bitrev64[64] = {0,32,16,48,8,40,24,56,4,36,20,52,12,44,28,60,2,34,18,50,10,42,26,58,
6,38,22,54,14,46,30,62,1,33,17,49,9,41,25,57,5,37,21,53,13,45,29,61,
3,35,19,51,11,43,27,59,7,39,23,55,15,47,31,63};
int bitrev128[128];
int bitrev256[256];
int bitrev512[512];
int bitrev1024[1024];
int bitrev2048[2048];
int bitrev4096[4096];
void init_bitrev() {
// 128
for (int i=0;i<64;i++) { bitrev128[i]=2*bitrev64[i]; bitrev128[i+64]=1+bitrev128[i]; }
// 256
for (int i=0;i<128;i++) { bitrev256[i]=2*bitrev128[i]; bitrev256[i+128]=1+bitrev256[i]; }
// 512
for (int i=0;i<256;i++) { bitrev512[i]=2*bitrev256[i]; bitrev512[i+256]=1+bitrev512[i]; }
// 1024
for (int i=0;i<512;i++) { bitrev1024[i]=2*bitrev512[i]; bitrev1024[i+512]=1+bitrev1024[i]; }
// 2048
for (int i=0;i<1024;i++) { bitrev2048[i]=2*bitrev1024[i]; bitrev2048[i+1024]=1+bitrev2048[i]; }
// 4096
for (int i=0;i<2048;i++) { bitrev4096[i]=2*bitrev2048[i]; bitrev4096[i+2048]=1+bitrev4096[i]; }
}
/** RADIX-2 FFT ALGORITHM */
/* Double precision*/
void radix2(cd_t *x, int N)
{
int n2, k1, N1, N2;
cd_t W, bfly[2];
N1=2;
N2=N/2;
/** Do 2 Point DFT */
for (n2=0; n2<N2; n2++)
{
/** Radix 2 butterfly */
bfly[0].r = (x[n2].r + x[N2 + n2].r);
bfly[0].i = (x[n2].i + x[N2 + n2].i);
bfly[1].r = (x[n2].r - x[N2 + n2].r);
bfly[1].i = (x[n2].i - x[N2 + n2].i);
twiddle(&W, N, (double)n2);
x[n2].r = bfly[0].r;
x[n2].i = bfly[0].i;
x[n2 + N2].r = bfly[1].r*W.r - bfly[1].i*W.i;
x[n2 + N2].i = bfly[1].i*W.r + bfly[1].r*W.i;
}
/** Don't recurse if we're down to one butterfly */
if (N2!=1) {
radix2(&x[0], N2);
radix2(&x[N2], N2);
}
}
void normalize(cd_t *x,cd_t *y, int *bitrev, int N) {
for (int i=0;i<N;i++) {
y[i].r = x[bitrev[i]].r / sqrt((double)N);
y[i].i = x[bitrev[i]].i / sqrt((double)N);
}
}

Some files were not shown because too many files have changed in this diff Show More