Compare commits

...

138 Commits

Author SHA1 Message Date
ndomingues
26956bf8e1 Create CI test for 2-Step RA
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:25:01 +01:00
ndomingues
3a8e3b9408 Demote sharedROs Assert Fatal to LOG_E to get RA 2-Step working
sharedROs feature to be implemented in the future

Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:49 +01:00
ndomingues
c9461ac4d4 Improve LOGs to better handle RA 2-Step
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:40 +01:00
ndomingues
d95d911e96 For RA 2-Step consider RA failed if MsgA-PUSCH not detected
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:26 +01:00
ndomingues
97ac8a5cd1 Implementation of the response window timer for 2-Step RA
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:16 +01:00
ndomingues
778fb90f44 Update prach_ConfigurationIndex to get more reliable PRACH detection with USRPs
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:23:46 +01:00
ndomingues
80735e2b39 Schedule MsgA-PUSCH even if there are UEs connected
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:22:45 +01:00
ndomingues
ed53bd8f95 Increase RA frame buffer size for 2-step RA to avoid MsgA-PUSCH and ACK/NACK collision
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:22:26 +01:00
ndomingues
ea35109ba2 Improve find_ra_UE function to return UE identified by RA-RNTI required for MsgA-PUSCH
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:22:05 +01:00
Robert Schmidt
6fc2d06077 Merge branch 'integration_2026_w20' into 'develop'
Integration `2026.w20`

- !4110 T-tracer: fix UE_PHY_PDSCH_IQ event fields
- !4114 nrUE: fix noise_power_dB field name in config
- !4109 prepare FAPI PUCCH PDU for MSG4 ACK in advance
- !4115 gNB specific RC
- !4042 Fix Wt (orthogonal code) multiplication for PUSCH DMRS length 2 and noise power estimation
- !4101 bug: LTE: avoid RRC use-after-free, NR: gNB-DU config update: verify cell's origin DU
- ci: skip merge commits when validating Signed-off-by
- !4047 XNAP: add encode/decode, helpers, and unit test for Xn Handover Request
- !4119 Remove PUCCH formar limitation in PRB size function
- !4083 nr_rate_matching: replace byte-by-byte repetition loop with memcpy chunks
- !4121 Collect iperf logs if command fails
- !4116 CI: Cleanup of parameters, change of branch and image naming, remove BuildProxy
- CI: Adjust RAN-PhySim-GraceHopper-5G timing thresholds

Closes #1082, #1081, #1087, and #1077

See merge request oai/openairinterface5g!4111
2026-05-16 09:12:55 +00:00
Jaroslava Fiedlerova
428ed54db4 CI: Adjust RAN-PhySim-GraceHopper-5G timing thresholds
!4083 improved encoding time in some nr_dlsim tests running in
RAN-PhySim-GraceHopper-5G pipeline. Update the timing thresholds
accordingly.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-16 10:20:24 +02:00
Jaroslava Fiedlerova
a2719bd9d7 Merge remote-tracking branch 'origin/ci-clone-repo-1' into integration_2026_w20 (!4116)
CI: Cleanup of parameters, change of branch and image naming, remove BuildProxy

MR Summary:

1. Remove merge step from Jenkinsfile-GitLab-Container

Removes the manual git merge step that was previously performed inside
the `RAN-Container-Parent` pipeline before running CI. The
`doGitLabMerge.sh` call and its merge-conflict failure handler are
dropped from the init stage. The `RAN-Local-Repo-Push` stage no longer
wraps triggerSlaveJob in catchError, instead, its failure posts an MR
comment directly on GitLab to report the issue, and abort the follow-up
test stages.

2. Switch to full commit IDs for image and branch naming

Replaces abbreviated 8-character commit hashes with full commit IDs
everywhere they are used to construct Docker image tags and CI branch
names in internal git repository.

3. Remove L2sim proxy build support

For the `RAN-L2-Sim-Test-4G`, the CI now assumes that the required proxy
image is already present on the testing machine. Build proxy step is no
longer needed, since there haven't been any recent updates in the proxy
repo, and the proxyCommit we currently use is outdated anyway.

4. Rename and clean up parameters in Python scripts

Renames legacy ran* / eNB* prefixed attributes to generic names across
all CI Python classes. Also removes duplicate and unused legacy CLI
argument aliases (--eNBRepository, --eNBBranch, --eNBIPAddress, etc.)
from args_parse.py.

|Old name	 |New name        |
|----------------|----------------|
|ranRepository	 |repository      |
|ranBranch	 |branch          |
|ranCommitID	 |commitID        |
|ranAllowMerge	 |merge           |
|ranTargetBranch |targetBranch    |
|eNBSourceCodePath|workspace      |

Reviewed-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-15 14:57:18 +02:00
Jaroslava Fiedlerova
5f4aff8a1d Merge remote-tracking branch 'origin/ci-iperf-fail-logs' into integration_2026_w20 (!4121)
Collect iperf logs if command fails

The Iperf_Module() checks that the iperf3 command succeeds successfully,
but in case of failure, does not collect the actual logs. Thus, only a
somewhat unhelpful

  Iperf client command failed on X -> Y (return code: ZZZ)

is logged, and it might not be clear why it fails. In this command,
always try to collect the logs, which might contain the actual error.

Fixes: f02c84fc ("CI: enable PCF-based dual-DNN multi-QoS in 25PRB
RFSim")

Reviewed-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-15 14:54:50 +02:00
Jaroslava Fiedlerova
9e4308030b CI: Rename and cleanup parameters inside python
isMergeRequest     --> merge
eNB_SourceCodePath --> workspace
ranBranch          --> branch
ranCommitID        --> commitID
ranTargetBranch    --> targetBranch
ranRepository      --> repository

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-15 14:11:00 +02:00
Jaroslava Fiedlerova
228dad1ec2 CI: Remove L2sim proxy build support
Remove the `BuildProxy` method, `Build_Proxy` action, `proxyCommit`
attribute, and all associated XML configuration and unit tests.

The oai-lte-5g-multi-ue-proxy repository has not received any updates
in over two years, and the proxy commit currently used for the build
is outdated as well. Although the proxy image is still required by
RAN-L2-Sim-Test-4G and must remain available on the test machine,
building it as part of the CI pipeline is dropped in this commit.

Instead, the CI will now assume that the corresponding proxy image is
already present as an external dependency, similarly to how CN images
are handled.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-15 14:11:00 +02:00
Jaroslava Fiedlerova
d39a40dba2 CI: Switch to full commit IDs for image naming
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-15 14:11:00 +02:00
Jaroslava Fiedlerova
181b5d89f8 CI: Switch to full commit IDs for branch naming
Simplify branch handling in CI by removing reliance on shortened commit
hashes and using full commit IDs. This allows to specify branch during
SCM checkout in Jenkins pipeline.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-15 14:11:00 +02:00
Jaroslava Fiedlerova
870454d13d CI: Remove merge step from Jenkinsfile-GitLab-Container
The RAN-Container-Parent pipeline retrieves the Jenkinsfile-GitLab-Container
from the develop branch (or from the branch specified for SCM checkout).

The only potential impact of this change concerns modifications to
ci-scripts/checkGitLabMergeRequestLabels.sh. In such cases, updates from the
source branch would not be considered, and the version from develop would be
used instead. This limitation is acceptable, as this script is going to be
removed in the future.

Merge conflict checks are handled in the Local-Repo-Push stage, where the
source branch is merged with the target branch, and the resulting testing
branch is pushed to the internal repository.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-15 14:11:00 +02:00
Robert Schmidt
dd424a2e0c Collect iperf logs if command fails
The Iperf_Module() checks that the iperf3 command succeeds successfully,
but in case of failure, does not collect the actual logs. Thus, only a
somewhat unhelpful

    Iperf client command failed on X -> Y (return code: ZZZ)

is logged, and it might not be clear why it fails. In this commit,
always try to collect the logs, which might contain the actual error,
and only add the diagnostic message at the end of the Iperf report
message.

Fixes: f02c84fcfc ("CI: enable PCF-based dual-DNN multi-QoS in 25PRB
    RFSim")

Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-15 13:28:36 +02:00
Robert Schmidt
e83867a505 Merge remote-tracking branch 'origin/rate-matching-memcpy' into integration_2026_w20 (!4083)
nr_rate_matching: replace byte-by-byte repetition loop with memcpy chunks

Currently, in the rate matching, in the low MCS case, we copy byte by
byte which is slow and causes jitter with high number of UEs.

This replaces the loop with chunked memcpy

Here is a benchmark with 128 UEs (done with the tool of !4028 adapted to
work with !3902)

Before:

    === Results: 128 UEs, 273 RBs, MCS 28, 10000 slots (warmup 5) ===
      Avg PDSCH/slot: 1.1 / 128 UEs
      Slot budget: 500 us (mu=1)

      Phase            mean      p50      p90      p99      max
                       (us)     (us)     (us)     (us)     (us)
      ------------------------------------------------------------------
      Scheduler        56.4     47.3     97.9    133.1    274.7
      PHY TX           53.3     47.9     72.9     87.6    320.3
      Total           109.7     97.1    142.6    187.3    435.8
      ------------------------------------------------------------------
      Max total 435.8 us at iter 8528

      Breakdown                            /slot     /call       max   calls
                                            (us)      (us)      (us)
      ---------------------------------------------------------------------------
      Scheduler:
        Total                               60.6      48.5     223.5   12498
          RA scheduling                        -           -           -       0
          UL scheduling                      0.0       0.0       0.1   12498
          DL scheduling (PDCCH+PDSCH)       41.4      33.1     111.4   12498
            RLC data req                     0.8       0.9       6.9    9150
      PHY TX:
        Total                                  -           -           -       0
          DCI generation                       -           -           -       0
          DLSCH encoding                    24.2      24.2     289.2   10000
            segmentation                     0.2       0.2       0.8   11440
            rate matching                   10.5       9.2     275.5   11440
            scrambling                       0.8       0.7      16.5   11440
          DLSCH modulation                   2.9       2.6       9.0   11440
          layer mapping                      6.3       5.5       8.2   11440
          precoding                          6.6       0.5       1.0   138760
          resource mapping                   2.2       0.2       3.0   138760
          phase compensation                 3.3       3.3       3.5   10000
      ---------------------------------------------------------------------------

After:

    === Results: 128 UEs, 273 RBs, MCS 28, 10000 slots (warmup 5) ===
      Avg PDSCH/slot: 1.1 / 128 UEs
      Slot budget: 500 us (mu=1)

      Phase            mean      p50      p90      p99      max
                       (us)     (us)     (us)     (us)     (us)
      ------------------------------------------------------------------
      Scheduler        57.9     48.4    100.4    134.2    462.5
      PHY TX           53.7     48.3     73.3     87.9    131.9
      Total           111.6     99.0    145.9    189.0    512.4
      ------------------------------------------------------------------
      Max total 512.4 us at iter 8367
      WARNING: max total (512 us) exceeds slot budget (500 us)!

      Breakdown                            /slot     /call       max   calls
                                            (us)      (us)      (us)
      ---------------------------------------------------------------------------
      Scheduler:
        Total                               62.3      49.8     226.3   12498
          RA scheduling                        -           -           -       0
          UL scheduling                      0.0       0.0       0.1   12498
          DL scheduling (PDCCH+PDSCH)       42.3      33.8     111.4   12498
            RLC data req                     0.8       0.8       6.6    9150
      PHY TX:
        Total                                  -           -           -       0
          DCI generation                       -           -           -       0
          DLSCH encoding                    24.3      24.3      86.8   10000
            segmentation                     0.2       0.2       0.8   11440
            rate matching                   10.5       9.2      22.0   11440
            scrambling                       0.8       0.7      15.2   11440
          DLSCH modulation                   3.0       2.6       9.6   11440
          layer mapping                      6.4       5.6       8.3   11440
          precoding                          6.6       0.5       1.0   138760
          resource mapping                   2.2       0.2       3.1   138760
          phase compensation                 3.3       3.3       3.5   10000
      ---------------------------------------------------------------------------

Reviewed-By: Francesco Mani <email@francescomani.it>
2026-05-15 08:48:07 +02:00
Robert Schmidt
76b7972bc0 Merge remote-tracking branch 'origin/issue_1077' into integration_2026_w20 (!4119)
Remove PUCCH formar limitation in PRB size function

F3 can be handled same way as F2 according to 9.2.5.2 of 38.213

Closes #1077

Reviewed-By: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
2026-05-15 08:41:06 +02:00
Robert Schmidt
782ede870e Merge remote-tracking branch 'origin/xn-encdec-handover-messages' into integration_2026_w20 (!4047)
XNAP: add encode/decode, helpers, and unit test for Xn Handover Request

- Add Xn Handover Request message type definitions.
- Implement encoder and decoder for Xn Handover Request. Xn Handover
  Request (3GPP TS 38.423 v16.2.0 §9.1.1.1)
  * Source NG-RAN node UE XnAP ID (M)
  * Cause (M)
  * Target Cell Global ID (M)
  * GUAMI (M)
  * UE Context Information (M)
  * UE History Information (M)
* Add equality check and memory management helpers.
* Extend XNAP library unit tests to cover Handover Request encode/decode
* Add required ASN.1 includes.
* Add utility conversions for:
  * KGNB* handling.
  * BIT_STRING_TO_NR_CELL_IDENTITY (modified to avoid upperbound overflow).

Reviewed-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-14 19:32:44 +02:00
francescomani
9d35b9028c remove format limitation in compute_pucch_prb_size
F3 can be handled same way as F2 according to 9.2.5.2 of 38.213

Signed-off-by: francescomani <email@francescomani.it>
2026-05-14 15:23:07 +02:00
Rakesh BB
8a0be83745 XNAP: add Xn Handover Request enc-dec+unit_test
- Add Xn Handover Request message type definitions.
- Implement encoder and decoder for Xn Handover Request.
  Xn Handover Request (3GPP TS 38.423 v16.2.0 §9.1.1.1)
  - Source NG-RAN node UE XnAP ID (M)
  - Cause (M)
  - Target Cell Global ID (M)
  - GUAMI (M)
  - UE Context Information (M)
  - UE History Information (M)
- Add equality check and memory management helpers.
- Extend XNAP library unit tests to cover Handover Request encode/decode
- Add required ASN.1 includes.
- Add utility conversions for:
  - KGNB* handling.
2026-05-13 16:12:57 +00:00
Rakesh BB
7c29d27487 fix: cast buf bytes to uint64_t before shifting in BIT_STRING_TO_NR_CELL_IDENTITY
Without explicit casts, each buf byte was promoted to a 32-bit signed
int before shifting. For NR Cell Identity (36-bit, per 3GPP TS 38.423
§9.2.2.9), this causes two problems:

  - Shifting buf[0] left by 28 can push bits into or past the sign bit,
    producing undefined/implementation-defined behavior.
  - The 32-bit intermediate result is too narrow to hold a 36-bit value,
    causing silent truncation before the OR-reduction.

Fix by casting each byte to uint64_t prior to the shift, ensuring all
intermediate expressions are evaluated in a 64-bit unsigned domain and
all 36 bits are preserved without overflow.
2026-05-13 15:14:24 +00:00
Shubhika Garg
5fd1f07e7e ci: skip merge commits when validating Signed-off-by
Signed-off-by: Shubhika Garg <shubhika.garg@openairinterface.org>
2026-05-13 13:58:35 +02:00
Jaroslava Fiedlerova
c0835cca75 CI: remove unused parameters from args_parse.py
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-13 12:17:16 +02:00
Jaroslava Fiedlerova
f39fb4a84b Merge remote-tracking branch 'origin/lte-nr-fixes' into integration_2026_w20 (!4101)
bug: LTE: avoid RRC use-after-free, NR: gNB-DU config update: verify
cell's origin DU

See commits for more details

Reviewed-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-13 11:45:10 +02:00
Jaroslava Fiedlerova
2d9ed6adc4 Merge remote-tracking branch 'origin/pusch_dmrs_bug_fix' into integration_2026_w20 (!4042)
Fix Wt (orthogonal code) multiplication for PUSCH DMRS length 2 and
noise power estimation

This MR:
- Introduce PUSCH DMRS length as a configurable parameter in nr_ulsim.
- Fix bugs related to the use of PUSCH DMRS length 2.
- Fix the noise power estimation.

Note:
- Still cannot validate PUSCH DMRS length 4, since we need more than 5
  layers (DMRS type 1) / 6 layers (DMRS type 2) to test the orthogonal
  spreading over time.
- Yet to implement time domain averaging for PUSCH DMRS length 2 to
  separate orthogonally over time.
- The main bug here is the noise power estimation (removes the duplicate
  division with the number of antennas).

    Reviewed-by: Roberto Louro Magueta <rmagueta@allbesmart.pt>
2026-05-13 11:44:32 +02:00
Jaroslava Fiedlerova
b5c460b17f Merge remote-tracking branch 'origin/gnb_ran_context' into integration_2026_w20 (!4115)
gNB specific RC

This is the framework of #1065 towards remove LTE cross compilation in
NR

Reviewed-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-13 11:43:57 +02:00
Jaroslava Fiedlerova
2214ecd81a Merge remote-tracking branch 'origin/issue_1087' into integration_2026_w20 (!4109)
prepare FAPI PUCCH PDU for MSG4 ACK in advance

Closes #1087

Reviewed-by: Sakthivel Velumani <s.velumani@northeastern.edu>
2026-05-13 11:43:21 +02:00
Jaroslava Fiedlerova
c555682fdc Merge remote-tracking branch 'origin/fix-typo-config' into integration_2026_w20 (!4114)
nrUE: fix `noise_power_dB` field name in config

Fixes 0b684732 (!2869)

Reviewed-by: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
2026-05-13 11:42:26 +02:00
Jaroslava Fiedlerova
c89fe9737f Merge remote-tracking branch 'origin/fix-ue-t-tracer' into integration_2026_w20 (!4110)
T-tracer: fix UE_PHY_PDSCH_IQ event fields

1. The field was named N_RB_UL and used fp->N_RB_UL in both LTE and NR
   demodulation code, but it should use N_RB_DL for PDSCH
2. The tracer ue.c referenced the wrong buffer field name "pusch_comp"
   instead of "pdsch_comp", causing a crash on startup

Reviewed-by: Cedric Roux <cedric.roux@eurecom.fr>
2026-05-13 11:41:27 +02:00
francescomani
36ed4d9ff1 get gnb ownership of RC to avoid compiling ENB_APP_SRC in NR
Signed-off-by: francescomani <email@francescomani.it>
2026-05-12 18:42:58 +02:00
Shubhika Garg
04a9145fe1 nrue: fix noise_power_dB field in config file
- Fixes 0b684732ee ("YAML as a drop-in replacement for libconfig")

Signed-off-by: Shubhika Garg <shubhika.garg@openairinterface.org>
2026-05-12 10:52:03 +02:00
Alex Jiao
7026366b5d T-tracer: fix UE_PHY_PDSCH_IQ event fields
1. The field was named N_RB_UL and used fp->N_RB_UL in both LTE and NR
  demodulation code, but it should use N_RB_DL for PDSCH
2. The tracer ue.c referenced the wrong buffer field name "pusch_comp"
  instead of "pdsch_comp", causing a crash on startup

Signed-off-by: Alex Jiao <alex.jiao@keysight.com>
2026-05-11 11:15:35 +08:00
francescomani
b29e7bc2c6 prepare FAPI PUCCH PDU for MSG4 ACK in advance
Signed-off-by: francescomani <email@francescomani.it>
2026-05-10 10:33:11 +02:00
Rakesh Mundlamuri
4e6e0e529d Minor fixes and harmonize maximum number of segments for DL and UL
Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-09 12:24:03 +05:30
Jaroslava Fiedlerova
d191447a01 Merge branch 'integration_2026_w19' into 'develop'
Integration `2026.w19`

* ci: post MR validation comments only on warnings or errors in pre-ci-check
* ci: skip merge-commit validation for integration branches
* !4088 fixing wrong logic for SIMO and MISO AWGN channels
* !4052 Add OAI - WNC gNB config file
* !4091 Fix build with unit tests, build all in CI
* !4089 Fixing broken nr-cu-nrppa-test simulator and nr-ue-nas-simualtor
* !4099 Allow control signal level at input of OFDM modulator
* !4092 Remove more unused parameters
* !4102 nr-cuup-load-test: avoid unaligned memory access
* !4077 Update microamp FR2 doc for firmware 0.1.174
* !3960 fix: issue 1054 - Config: Creating New Array members via command line arguments
* !3810 UE symbol based PBCH, PSBCH receiver
* !4103 Update CN5G images to stable release `v2.2.1`
* !3814 Multi-QoS Handling and PDU Session Modify
* !4064 FAPI: fix UCI payload byte length for bit_len multiples of 8
* !4078 [M-plane] Improvements, fixes + Add CI M-plane pipeline

Closes #1054, #1075, and #541

See merge request oai/openairinterface5g!4095
2026-05-07 19:07:13 +00:00
Rakesh Mundlamuri
5fcf815c56 Fix time domain averaging to average over number of layers
Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-07 22:20:52 +05:30
Rakesh Mundlamuri
e557ffdc57 Fix Wt (orthogonal code) multiplication for PUSCH DMRS length 2
Also fixes noise power computation removing the duplicate division over
number of antennas

Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-07 22:20:50 +05:30
Jaroslava Fiedlerova
328c4bc5fa Merge remote-tracking branch 'origin/ci-test-mplane' into integration_2026_w19 (!4078)
[M-plane] Improvements, fixes + Add CI M-plane pipeline

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-07 15:28:57 +02:00
Jaroslava Fiedlerova
58942c31a5 Merge remote-tracking branch 'origin/cubb_rusim_uci_unpack' into integration_2026_w19 (!4064)
FAPI: fix UCI payload byte length for bit_len multiples of 8

Problem
When testing with cuBB as the FAPI PNF (L1) and ruSIM, the VNF (OAI L2)
was consistently failing to unpack UCI.indication messages containing
PUCCH format 2/3/4 PDUs with CSI-1 reports:

  vnf_handle_nr_uci_indication: Failed to unpack message
  pullarray8: pullarray8 no space in buffer

Root cause
All variable-length payload fields in the UCI pack/unpack functions
(HARQ, SR, CSI-1, CSI-2) computed their byte length as:
  const uint16_t csi_len = bit_len / 8 + 1;
This formula seems wrong for any bit_len that is an exact multiple of 8.
For example, bit_len=8 gives csi_len=2, but 8 bits fit in exactly 1
byte. The correct ceiling division is (bit_len + 7) / 8.
cuBB packs CSI-1 payload bytes using the correct formula, so for an
8-bit CSI codebook it sends 1 byte. OAI's unpacker computed csi_len=2
and called pullarray8 requesting 2 bytes from a buffer with only 1
remaining, triggering the error.
The failure was also specific to PUCCH 2/3/4 (and would affect PUSCH
UCI) because PUCCH 0/1 carries no variable-length byte arrays — its HARQ
payload is packed as individual uint8 values per ACK bit, so pullarray8
is never called.

Diagnosis
Added NFAPI_TRACE_NOTE logging throughout the unpack chain (enabled via
NFAPI_TRACE_LEVEL=note) to trace PDU type, bitmap, computed lengths, and
buffer remaining bytes at each branch. The following sequence confirmed
the exact failure site:

  [N] unpack_nr_uci_indication: sfn=592 slot=9 num_ucis=1 buf_remaining=21
  [N] unpack_nr_uci_indication: unpacking UCI[0/1] buf_remaining=21
  [N] unpack_nr_uci_indication_body: pdu_type=2 pdu_size=21 buf_remaining=17
  [N] unpack_nr_uci_pucch_2_3_4: PUCCH-2/3/4 rnti=0x5c2d pucch_format=0 pduBitmap=0x04 buf_remaining=4
  [N] unpack_nr_uci_pucch_2_3_4: PUCCH-2/3/4 CSI-1 csi_part1_bit_len=8 csi_len=2 buf_remaining=1
  [N] unpack_nr_uci_pucch_2_3_4: PUCCH-2/3/4 CSI-1 about to pullarray8 csi_len=2 buf_remaining=1
  [E] pullarray8: pullarray8 no space in buffer

This was also cross-checked against a pcap capture of the nvipc
interface, which confirmed cuBB sends PDUSize=21 with 1 byte for the
8-bit CSI-1 payload — consistent with (8+7)/8 = 1.

Tentative Fix
Replace bit_len / 8 + 1 with (bit_len + 7) / 8 at all 14 affected sites
across both pack and unpack functions for PUSCH, PUCCH 0/1 (SR/HARQ),
and PUCCH 2/3/4 (SR, HARQ, CSI-1, CSI-2) in nr_fapi_p7.c.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Rúben Soares Silva <rsilva@allbesmart.pt>
2026-05-07 15:03:21 +02:00
Jaroslava Fiedlerova
3b8f5c7191 Merge remote-tracking branch 'origin/rrc-qos-handling' into integration_2026_w19 (!3810)
Multi-QoS Handling and PDU Session Modify

This MR implements comprehensive QoS flows handling and PDU Session
Modify procedures in the RRC layer, enabling full support for multiple
QoS flows per DRB and dynamic QoS management per 3GPP specs. Key
changes:

1. Multi-QoS Flows Support

- Multiple QoS flows per DRB: Support for multiple QoS flows mapped to a
  single DRB
- Intelligent QoS-to-DRB mapping: Implements resource-type-aware
  multiplexing based on 3GPP TS 23.501 Table 5.7.4-1
  - DC-GBR flows (5QI 82-90): Dedicated DRB, max 1 flow per DRB
  - GBR flows (5QI 1-4, 65-67, 71-76): Max 2 flows per DRB
  - Non-GBR flows (5QI 5-11, 69-70, 79-80): Max 5 flows per DRB
  - Aggregate cap: Maximum 5 flows per DRB
- 5QI validation: Early validation of standardized 5QI values (1-9,
  65-90) during QoS flow setup/modify

2. PDU Session Modify Procedures

- Complete E1AP/RRC integration: Full Bearer Context Modification
  support with DRB lifecycle management
  - DRB To Setup/Modify/Remove lists: Complete support for all DRB
    operations in Bearer Context Modification
- QoS flow operations: Support for QoS flow add, modify, and release
  operations
  - QoS flow mapping: Proper handling of QoS flow modifications in
    DRB To Modify List
- Automatic DRB management: DRB setup, modification, and removal
  based on QoS flow changes. Reuse existing DRBs if the incoming QoS
  flow is compatible.
- Delayed transactions: PDU Session Modify added to delayed
  transactions list for proper sequencing

3. GTP-U Tunnel Refactoring

- Architecture alignment:
  - N3 tunnels: 1 per PDU session with QFI marking, container for
    multiple bearers, supporting multiple QoS flows
  - F1-U tunnels: 1 per DRB without QFI marking
- SDAP ownership of QoS: move QoS management to be fully owned by
  SDAP

4. QoS Enhancements

- Dynamic5QI support: Full support for Dynamic5QI with packet delay
  budget and packet error rate
- GBR QoS flows: Support for Guaranteed Bit Rate QoS flows with
  GFBR/MFBR parameters
- DRB QoS aggregation: DRB-level QoS computed from all mapped QoS
  flows using ARP priority (not 5QI priority)
- QoS priority level refactoring: Proper type definitions per 3GPP
  TS 23.501 (QoS Priority Level: 1-127, ARP Priority Level: 1-15)

Technical Changes

RRC Layer

- Refactored `nr_rrc_add_bearers()` to support intelligent QoS-to-DRB
  mapping
- Added `nr_rrc_update_qos()` for QoS flow add/modify with automatic DRB
  assignment
- Implemented `nr_rrc_update_pdusession()` for QoS flow release and DRB
  cleanup
- Consolidated F1 UE Context Modification Request handling
- Simplified PDU status tracking by removing intermediate states
- Added QoS flow and DRB removal utilities
- Updated RRC bearers tests with comprehensive multi-QoS testing
- Adapted `nr-cuup-load-test.c` to new GTP design

NGAP Layer

- Extended PDU Session Resource Modify Request Transfer with QoS
  add/modify/release lists
- Added proper type definitions (`pdusession_mod_req_transfer_t`,
  `qos_flow_to_release_t`)
- Fixed NGAP PDU Session Modify transfer encoding

GTP-U Layer

- Refactored tunnel creation API: scalar fields instead of arrays
- Split tunnel creation into `n3_gtpu_create()` and
  `f1_drb_gtpu_create()`
- Added bearer-to-QFI mapping structure (`gtpv1u_rb_t`)
- Implemented QFI de-duplication and one-to-one QFI-to-bearer mapping
- Reduced inter-dependencies between LTE and NR

SDAP Layer

- Fixed default DRB tracking: Only one default DRB per SDAP entity per
  PDU session (TS 37.324)
- Set default DRB to first DRB added when creating bearers

F1AP Layer

- Added GBR QoS Flow Information IE handling in CU
- Implemented DRB QoS aggregation from multiple QoS flows
- Extended F1AP test cases to support multiple QoS flows

Code Quality Improvements

- Improved error handling throughout the stack
- Enhanced logging and debugging capabilities
- Added comprehensive unit tests for multi-QoS scenarios
- Improved type safety and validation

Testing

The code was validated with Open5gs v2.7.6, OAI CN5G and COTS UE.

How to reproduce with Open5gs:

1. Start Open5gs
2. From the Open5gs web UI: add multiple QFIs to the same DNN.
3. Restart Open5gs
4. Run gNB and UE

The user will see the following:

1. QoS flows arrive via NGAP PDU Session Setup/Modify requests, each
   with a QFI and 5QI.
2. The gNB assigns each flow to a DRB, creating a new DRB or reusing an
   existing one based on 5QI compatibility (compatible flows, i.e. same
   5QI characteristics, share a DRB)
3. At the SDAP layer, packets are tagged with QFI headers; at the GTP-U
   layer, uplink packets include QFI in the PDU Session Container for
   core network mapping.

Documentation

- Added comprehensive QoS flows handling documentation with 3GPP
  standards references
- Updated PDU Session Modify sequence diagrams

Note

* This implementation aligns with:
  - 3GPP TS 23.501 (QoS framework)
  - 3GPP TS 38.413 (NGAP)
  - 3GPP TS 37.324 (SDAP)
  - 3GPP TS 38.463 (F1AP)
  - 3GPP TS 29.281 (GTP-U)
  - 3GPP TS 38.331 (RRC)
* Multi-QoS and PDU Session Modify are both added to this MR since QoS
  flows update is triggered by PDU Session Modify in some scenarios
  (e.g. with Open5gs, used for validation).
* Core functional changes introduced by commits with prefix "QoS
  Handling" or "PDU Session Modify"
* This MR replaces the old !2703.
* This MR adopts relevant CU changes from !2836, namely:
  * Adds new shared QoS types
  * Add standardized 5QI table and helper
  * Dynamic5QI support + validation
  * Computation of DRB QoS (aggregate QoS) and priority/GBR
  * F1AP DRB-level QoS
* Closes #541 (5QI validation)
* Closes #1075 (Optional NAS-PDU in PDU Session Setup Request)

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-07 14:52:10 +02:00
Jaroslava Fiedlerova
c42928773b CI: Add RAN-SA-FHI72-MPLANE-CN5G into CI doc
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 14:05:31 +02:00
Jaroslava Fiedlerova
439d0d9d8d CI: Add RAN-SA-FHI72-MPLANE-CN5G into parent CI pipeline
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 14:05:31 +02:00
Teodora Vladić
695cdb4b38 Update RU FW versions
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 14:05:31 +02:00
Teodora Vladić
9050b3eb3c Update Benetel FW to the latest stable
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-07 14:05:31 +02:00
Jaroslava Fiedlerova
7827ac38b0 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 14:01:48 +02:00
Teodora Vladić
4ab102c680 [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 14:00:09 +02:00
Jaroslava Fiedlerova
4f74b2c7eb CI: Increase service deployment timeout
Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 14:00:09 +02:00
Jaroslava Fiedlerova
3959e80f4e 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 14:00:09 +02:00
Jaroslava Fiedlerova
8d6e3e4387 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 14:00:09 +02:00
Jaroslava Fiedlerova
df21063668 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 14:00:09 +02:00
Jaroslava Fiedlerova
73d2b9c7e2 Merge remote-tracking branch 'origin/update-cn5g' into integration_2026_w19 (!4103)
Update CN5G images to stable release `v2.2.1`

- Updated CN5G image tags to a stable release v2.2.1
- Upgrade MySQL image to 9.6
- Updated image oaisoftwarealliance/trf-gen-cn5g to latest tag
  supporting multi-architecture platforms

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-07 10:07:36 +02:00
Guido Casati
51c773f411 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 10:02:02 +02:00
Guido Casati
4a325ccf09 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 10:02:02 +02:00
Guido Casati
f02c84fcfc 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 10:02:02 +02:00
Jaroslava Fiedlerova
b11cf166af Merge remote-tracking branch 'origin/ue-pbch-symbol-rx' into integration_2026_w19 (!3810)
UE symbol based PBCH, PSBCH receiver

This is a subset of !2895 with PBCH & PSBCH refactoring to process
symbol by symbol.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
2026-05-07 09:38:57 +02:00
Jaroslava Fiedlerova
ea1376a5c1 Merge remote-tracking branch 'origin/issue-1054-fix' into integration_2026_w19 (!3960)
fix: issue 1054 - 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 needed. If so, it matches with the list of parameters
first, then the highest index is found for that parameter using the
strtol,

"--rfsimulator.[0].serveraddr",
"--rfsimulator.[2].serveraddr",

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 needed. If so, it matches with the list of parameters
first, then the highest index is found for that parameter using the
strtol,

"--rfsimulator.[0].serveraddr",
"--rfsimulator.[2].serveraddr",
"--rfsimulator.[4].serverport",
"--rfsimulator.[1].serveraddr",

It sets the index as 4, allocates 4 slots, memory is managed via
standard functions then it fills the gap of all the indices.

this closes #1054

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
2026-05-07 09:36:58 +02:00
Jaroslava Fiedlerova
00d6cc034d Merge remote-tracking branch 'origin/microamp_update_doc' into integration_2026_w19 (!4077)
Update microamp FR2 doc for firmware 0.1.174

MR updates the documentation of the Microamp FR2 unit with firmware
0.1.174 or later.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Sagar Arora <sagar.arora@openairinterface.org>
2026-05-07 09:31:06 +02:00
karim
5eb2480122 Update microamp FR2 doc for firmware 0.1.174
Signed-off-by: karim <karim.boutiba@openairinterface.org>
2026-05-06 16:40:35 +02:00
Gabriele Gemmi
80088121d3 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-06 13:15:23 +00:00
Shubhika Garg
e95992927c 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-06 14:56:47 +02:00
Jaroslava Fiedlerova
04e9fcbef9 Merge remote-tracking branch 'origin/ubsan-load-test' into integration_2026_w19 (!4102)
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: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-06 12:16:19 +02:00
Jaroslava Fiedlerova
22bc4f690a Merge remote-tracking branch 'origin/moreunused' into integration_2026_w19 (!4092)
Remove more unused parameters

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-06 12:13:32 +02:00
Robert Schmidt
4103703f56 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-06 09:07:32 +02:00
Teodora Vladić
d843877123 [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-05 16:50:32 +02:00
Teodora Vladić
3c4081489a [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-05 16:50:32 +02:00
Teodora Vladić
188d186ef9 [M-plane] Extract the current running U-plane configuration
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-05 16:50:27 +02:00
Jaroslava Fiedlerova
1b1b5397c1 Merge remote-tracking branch 'origin/fix_test_simulators' into integration_2026_w19 (!4089)
Fix broken nr-cu-nrppa-test simulator and nr-ue-nas-simualtor

This MR fixes the simulators broken due to the changes from !3993 and
!4010. The changes were related to storing service network name in nas
and routing indicator in uicc

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-05 14:01:36 +02:00
Jaroslava Fiedlerova
1df35d7994 Merge remote-tracking branch 'origin/dlsim_tx_amp' into integration_2026_w19 (!4099)
Allow control signal level at input of OFDM modulator

This simple fix removes an error floor in nr_dlsim tests with 256QAM. It
adds -Q to nr_dlsim to control gNB TX amplitude (like tx_backoff_dB in
gNB RU section). With

./nr_dlsim -R273 -b273 -s30 -e27 -I10 -q1 -n100 -Q30

has 0 errors. The default in nr_dlsim remains -36 dBFs.

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-05 14:00:28 +02:00
Jaroslava Fiedlerova
9e95495c36 Merge remote-tracking branch 'origin/fix-build-unit-test-all' into integration_2026_w19 (!4091)
Fix build with unit tests, build all in CI

- Fix a build error when ENABLE_TESTS=ON
- Build everything in unit test build

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-05 13:59:19 +02:00
Jaroslava Fiedlerova
3016ada216 Merge remote-tracking branch 'origin/oai-wnc' into integration_2026_w19 (!4052)
Add OAI - WNC gNB config file

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
2026-05-05 13:58:07 +02:00
Robert Schmidt
30bd2c183b gNB-DU config update: Verify cell's origin DU
Verify that a given cell's assoc_id (i.e., it's "host DU") is the
assoc_id of the currently treated DU to avoid treating a config update
of another (potentially malicious) DU.

Closes: #1081
Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-05 12:26:04 +02:00
Robert Schmidt
e17823649a Avoid LTE RRC use-after-free
rrc_eNB_free_UE() frees all memory, so set any house-keeping before.

Closes: #1082
Signed-off-by: Robert Schmidt <robert.schmidt@openairinterface.org>
2026-05-05 12:19:07 +02:00
Reem Bahsoun
0a58095692 Add WNC RU configuration section to FHI 7.2 tutorial.
Signed-off-by: Reem Bahsoun <reem.bahsoun@openairinterface.org>
2026-05-05 12:08:16 +02:00
Teodora Vladić
8097b4a479 [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-05 11:23:24 +02:00
Teodora
275afe7d16 [M-plane] Set variable PRACH offset for Benetel RU
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-05 11:23:24 +02:00
Teodora
89deb54384 [M-plane] Hack 2x2 mode to use every other antenna
Signed-off-by: Teodora Vladić <teodora.vladic@openairinterface.org>
2026-05-05 11:23:19 +02:00
Reem Bahsoun
12d6f6eccd Add a OAI-WNC config file in targets.
Signed-off-by: Reem Bahsoun <reem.bahsoun@openairinterface.org>
2026-05-05 11:15:21 +02:00
Rakesh Mundlamuri
c9587a8876 Modify nr-cu-nrppa-test simulator to use UE data from config file
Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-05 10:18:43 +05:30
Raymond Knopp
12ac3ace12 add -Q to nr_dlsim to control gNB TX amplitude (tx_backoff_dB). with -Q30
./nr_dlsim -R273 -b273 -s30 -e27 -I10 -q1 -n100 -Q30

has 0 errors.
2026-05-04 21:09:57 +02:00
Jaroslava Fiedlerova
534ec1755f Merge remote-tracking branch 'origin/hotfix_SIMO' into integration_2026_w19 (!4088)
fixing wrong logic for SIMO and MISO AWGN channels

Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
Reviewed-by: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
2026-05-04 16:50:25 +02:00
Shubhika Garg
084b02a38b 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-04 16:49:20 +02:00
Shubhika Garg
95a9438d44 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-04 16:49:12 +02:00
Guido Casati
5a1af1a7db 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-04 12:03:28 +02:00
Guido Casati
5f0f68caf8 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-04 12:03:28 +02:00
Guido Casati
3ad1b5c701 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-04 12:03:28 +02:00
Guido Casati
74decfcf30 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-04 12:03:28 +02:00
Guido Casati
8125f8a2eb 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-04 12:03:28 +02:00
Guido Casati
652a9e455b 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-04 12:03:27 +02:00
Guido Casati
c8b99ce011 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-04 12:03:27 +02:00
Guido Casati
6786df3102 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-04 12:03:27 +02:00
Guido Casati
17ff43168f 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-04 12:03:27 +02:00
Guido Casati
ef971849bd 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-04 12:03:27 +02:00
Guido Casati
4ad557a0e3 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-04 12:03:27 +02:00
Guido Casati
e041a2a078 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-04 12:03:27 +02:00
Guido Casati
04126759aa 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-04 12:03:27 +02:00
Guido Casati
8ceb7ec37b 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-04 12:03:27 +02:00
Guido Casati
302c1c0450 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-04 12:03:27 +02:00
Guido Casati
773e62077b 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-04 12:03:27 +02:00
Guido Casati
f17b2bb805 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-04 12:03:27 +02:00
Guido Casati
f1b8d45bf9 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-04 12:03:27 +02:00
Guido Casati
43ec237a4f 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-04 12:03:27 +02:00
Guido Casati
428859f218 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-04 12:03:27 +02:00
Guido Casati
c97820622a 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-04 12:03:27 +02:00
Guido Casati
77aff40af7 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-04 12:03:27 +02:00
Guido Casati
835c80b39d 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-04 12:03:27 +02:00
Guido Casati
522fb88c6e 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-04 12:03:27 +02:00
Guido Casati
971436030d 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-04 12:03:27 +02:00
Guido Casati
d085bb0ba0 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-04 12:03:27 +02:00
Guido Casati
ab00b2ff94 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-04 12:03:27 +02:00
Guido Casati
24dd7b5b9e 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-04 12:03:27 +02:00
Guido Casati
d4c1731e97 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-04 12:03:27 +02:00
Guido Casati
6560403d3c 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-04 12:03:27 +02:00
Guido Casati
4b5d5c1ae6 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-04 12:03:27 +02:00
Guido Casati
67e646aa7c RRC: remove warning when UP params are missing
Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
2026-05-04 12:03:27 +02:00
Guido Casati
9327b4be6b 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-04 12:03:27 +02:00
Guido Casati
01add4ab43 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-04 12:03:27 +02:00
Guido Casati
7f13e04f75 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-04 12:03:27 +02:00
Guido Casati
226266743c 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-04 12:03:27 +02:00
Guido Casati
ef505b55d7 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-04 12:03:27 +02:00
Guido Casati
89c9e89a9d 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-04 12:03:27 +02:00
Rakesh Mundlamuri
fa4bb92d03 Fixing broken nr-cu-nrppa-test simulator and nr-ue-nas-simualtor
Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-03 19:26:13 +05:30
Rakesh Mundlamuri
116c893d45 Introduce PUSCH DMRS length as a configurable parameter
Signed-off-by: Rakesh Mundlamuri <rakesh.mundlamuri@openairinterface.org>
2026-05-03 19:04:04 +05:30
Sakthivel Velumani
f9b0dd6af3 fix: perform FFT only on PBCH symbols
Signed-off-by: Sakthivel Velumani <s.velumani@northeastern.edu>
2026-05-03 01:55:44 +00:00
Sakthivel Velumani
4b85b71523 log: fix debug logging
Signed-off-by: Sakthivel Velumani <s.velumani@northeastern.edu>
2026-05-03 01:55:43 +00:00
Sakthivel Velumani
e4b2125f1e 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-03 01:55:32 +00:00
francescomani
d5c0e580ab removed few more unused parameters
Signed-off-by: francescomani <email@francescomani.it>
2026-05-01 14:29:58 +02:00
francescomani
c307e20ab9 remove unnecessary rrc_enb_process_msg hack in nr-uesoftmodem
Signed-off-by: francescomani <email@francescomani.it>
2026-05-01 14:27:26 +02:00
francescomani
6c39ea2b0b remove unnecessary pdcp_run hack in nr-softmodem
Signed-off-by: francescomani <email@francescomani.it>
2026-05-01 13:54:33 +02:00
francescomani
7e9d3cc328 remove unused dump_uci_stats
Signed-off-by: francescomani <email@francescomani.it>
2026-05-01 13:23:06 +02:00
Robert Schmidt
4ab525aca1 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-04-30 19:56:18 +02:00
Robert Schmidt
d8962fa270 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-04-30 19:55:09 +02:00
Florian Kaltenberger
d1b777e0a5 fixing wrong logic for SIMO and MISO AWGN channels
Signed-off-by: Florian Kaltenberger <florian.kaltenberger@eurecom.fr>
2026-04-30 10:59:17 +02:00
Maxime
683d1b594f nr_rate_matching: replace byte-by-byte repetition loop with memcpy chunks 2026-04-29 12:33:55 -04:00
Aswanth KC
ef0b4460b6 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.
2026-04-23 17:45:34 +00:00
194 changed files with 10721 additions and 2872 deletions

View File

@@ -1136,12 +1136,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 +1193,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 +1229,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 +1373,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()
@@ -1372,7 +1381,6 @@ endif()
add_library(L2_LTE_NR
# temporary solution until 4G/5G code completely untangled (as evidenced by deletion of the following file)
${MAC_DIR}/dummy_functions.c
${ENB_APP_SRC}
)
target_link_libraries(L2_LTE_NR PRIVATE f1ap s1ap nr_rrc)
@@ -1898,7 +1906,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 +1917,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

@@ -87,9 +87,6 @@ pipeline {
// since a bit, in push events, gitlabUserEmail is not populated
gitCommitAuthorEmailAddr = env.gitlabUserEmail
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
// GitLab-Jenkins plugin integration is lacking to perform the merge by itself
// Doing it manually --> it may have merge conflicts
// Validate MR commits: checks for missing Signed-off-by and merge commits
def mrValidationLog = "signedCommit_${env.BUILD_NUMBER}.log"
def mrValidationExitCode = sh(
@@ -98,11 +95,12 @@ pipeline {
)
def mrValidationMessage = readFile(mrValidationLog).trim()
sh "rm -f ${mrValidationLog}"
addGitLabMRComment comment: "${mrValidationMessage}"
if (mrValidationExitCode >= 1) {
addGitLabMRComment comment: "${mrValidationMessage}"
}
if (mrValidationExitCode >= 2) {
error("${mrValidationMessage}")
}
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
} else {
echo "Git Branch is ${GIT_BRANCH}"
echo "Git Commit is ${GIT_COMMIT}"
@@ -113,29 +111,19 @@ pipeline {
}
}
}
post {
failure {
script {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI"
addGitLabMRComment comment: message
currentBuild.result = 'FAILURE'
}
}
}
}
stage ("Local-Repo-Push") {
steps {
script {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
triggerSlaveJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
}
triggerSlaveJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
}
}
post {
failure {
script {
echo "Push to local repository KO"
failingStages += '\n * RAN-Local-Repo-Push'
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Cannot perform CI - merge validation failed (merge conflict, git operation failure, or internal CI error)."
addGitLabMRComment comment: message
currentBuild.result = 'FAILURE'
}
}
}
@@ -761,6 +749,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 {
@@ -889,14 +900,13 @@ def triggerSlaveJob (jobName, gitlabStatusName) {
def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
if ("MERGE".equals(env.gitlabActionType)) {
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.gitlabMergeRequestLastCommit
shortenShaOne = shortenShaOne.trim()
branchName = env.gitlabSourceBranch.replaceAll("/", "-").trim()
fullRanTag = OAI_Registry + '/oai-gnb:' + env.gitlabSourceBranch + '-' + shortenShaOne
shaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%H" ' + env.gitlabMergeRequestLastCommit
shaOne = shaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:' + env.gitlabSourceBranch + '-' + shaOne
} else {
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.GIT_COMMIT
shortenShaOne = shortenShaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + shortenShaOne
shaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%H" ' + env.GIT_COMMIT
shaOne = shaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + shaOne
}
// Workaround for the "cancelled" GitLab pipeline notification
// The slave job is triggered with the propagate false so the following commands are executed

View File

@@ -67,8 +67,7 @@ pipeline {
stage('Create temporary branch for CI') {
steps {
script {
def shortCommit = params.eNB_CommitID.take(8)
env.NEW_BRANCH = "${params.eNB_Branch}-${shortCommit}"
env.NEW_BRANCH = "${params.eNB_Branch}-${params.eNB_CommitID}"
echo "New branch: ${env.NEW_BRANCH}"
}
sh """

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
# Python for CI testing
#
# Required Python Version
# Python 3.x
@@ -44,74 +44,46 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,CLUSTER):
elif re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE)
mode = matchReg.group(1)
elif re.match(r'^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.ranRepository = matchReg.group(1)
RAN.ranRepository=matchReg.group(1)
HTML.ranRepository=matchReg.group(1)
CONTAINERS.ranRepository=matchReg.group(1)
CLUSTER.ranRepository=matchReg.group(1)
elif re.match(r'^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE)
elif re.match(r'^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.repository = matchReg.group(1)
RAN.repository=matchReg.group(1)
HTML.repository=matchReg.group(1)
CONTAINERS.repository=matchReg.group(1)
CLUSTER.repository=matchReg.group(1)
elif re.match(r'^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE)
doMerge = matchReg.group(1)
if ((doMerge == 'true') or (doMerge == 'True')):
CiTestObj.ranAllowMerge = True
RAN.ranAllowMerge=True
HTML.ranAllowMerge=True
CONTAINERS.ranAllowMerge=True
CLUSTER.ranAllowMerge=True
elif re.match(r'^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.ranBranch = matchReg.group(1)
RAN.ranBranch=matchReg.group(1)
HTML.ranBranch=matchReg.group(1)
CONTAINERS.ranBranch=matchReg.group(1)
CLUSTER.ranBranch=matchReg.group(1)
elif re.match(r'^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE)
CiTestObj.ranCommitID = matchReg.group(1)
RAN.ranCommitID=matchReg.group(1)
HTML.ranCommitID=matchReg.group(1)
CONTAINERS.ranCommitID=matchReg.group(1)
CLUSTER.ranCommitID=matchReg.group(1)
elif re.match(r'^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE)
CiTestObj.ranTargetBranch = matchReg.group(1)
RAN.ranTargetBranch=matchReg.group(1)
HTML.ranTargetBranch=matchReg.group(1)
CONTAINERS.ranTargetBranch=matchReg.group(1)
CLUSTER.ranTargetBranch=matchReg.group(1)
elif re.match(r'^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE):
print("parameters --eNB*IPAddress ignored")
elif re.match(r'^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE):
print("parameters --eNB*UserName ignored")
elif re.match(r'^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE):
print("parameter --eNB*Password ignored")
RAN.merge=True
HTML.merge=True
CONTAINERS.merge=True
CLUSTER.merge=True
elif re.match(r'^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.branch = matchReg.group(1)
RAN.branch=matchReg.group(1)
HTML.branch=matchReg.group(1)
CONTAINERS.branch=matchReg.group(1)
CLUSTER.branch=matchReg.group(1)
elif re.match(r'^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE)
RAN.commitID=matchReg.group(1)
HTML.commitID=matchReg.group(1)
CONTAINERS.commitID=matchReg.group(1)
CLUSTER.commitID=matchReg.group(1)
elif re.match(r'^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE)
RAN.targetBranch=matchReg.group(1)
HTML.targetBranch=matchReg.group(1)
CONTAINERS.targetBranch=matchReg.group(1)
CLUSTER.targetBranch=matchReg.group(1)
elif re.match(r'^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
RAN.eNBSourceCodePath=matchReg.group(1)
CONTAINERS.eNBSourceCodePath=matchReg.group(1)
CLUSTER.eNBSourceCodePath=matchReg.group(1)
elif re.match(r'^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
print("parameter --eNB1SourceCodePath ignored")
elif re.match(r'^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
print("parameter --eNB2SourceCodePath ignored")
RAN.workspace=matchReg.group(1)
CONTAINERS.workspace=matchReg.group(1)
CLUSTER.workspace=matchReg.group(1)
elif re.match(r'^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.testXMLfiles.append(matchReg.group(1))

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

@@ -50,17 +50,17 @@ def OC_logout(cmd):
class Cluster:
def __init__(self):
self.eNBSourceCodePath = ""
self.workspace = ""
self.OCUserName = ""
self.OCPassword = ""
self.OCProjectName = ""
self.OCUrl = OCUrl
self.OCRegistry = OCRegistry
self.ranRepository = ""
self.ranBranch = ""
self.ranCommitID = ""
self.ranAllowMerge = False
self.ranTargetBranch = ""
self.repository = ""
self.branch = ""
self.commitID = ""
self.merge = False
self.targetBranch = ""
self.cmd = None
def _recreate_entitlements(self):
@@ -101,7 +101,7 @@ class Cluster:
def _start_build(self, name):
# will return "immediately" but build runs in background
# if multiple builds are started at the same time, this can take some time, however
ret = self.cmd.run(f'oc start-build {name} --from-dir={self.eNBSourceCodePath} --exclude=""')
ret = self.cmd.run(f'oc start-build {name} --from-dir={self.workspace} --exclude=""')
regres = re.search(r'build.build.openshift.io/(?P<jobname>[a-zA-Z0-9\-]+) started', ret.stdout)
if ret.returncode != 0 or ret.stdout.count('Uploading finished') != 1 or regres is None:
logging.error(f"error during oc start-build: {ret.stdout}")
@@ -157,7 +157,7 @@ class Cluster:
OC_logout(cmd)
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
return False
tag = cls_containerize.CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
tag = cls_containerize.CreateTag(self.commitID, self.branch, self.merge)
registry = f'{self.OCRegistry}/{CI_OC_RAN_NAMESPACE}'
success, msg = cls_containerize.Containerize.Pull_Image(cmd, images, tag, tag_prefix, registry, None, None)
OC_logout(cmd)
@@ -174,12 +174,12 @@ class Cluster:
return (image, archiveArtifact(self.cmd, ctx, fn))
def BuildClusterImage(self, ctx, node, HTML):
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
if self.repository == '' or self.branch == '' or self.commitID == '':
HELP.GenericHelp(CONST.Version)
raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {ranBranch} ranCommitID {self.ranCommitID}')
lSourcePath = self.eNBSourceCodePath
raise ValueError(f'Insufficient Parameter: repository {self.repository} branch {self.branch} commitID {self.commitID}')
lSourcePath = self.workspace
if node == '' or lSourcePath == '':
raise ValueError('Insufficient Parameter: eNBSourceCodePath missing')
raise ValueError('Insufficient Parameter: workspace missing')
ocUserName = self.OCUserName
ocPassword = self.OCPassword
ocProjectName = self.OCProjectName
@@ -200,22 +200,22 @@ class Cluster:
baseTag = 'develop'
forceBaseImageBuild = False
if self.ranAllowMerge: # merging MR branch into develop -> temporary image
branchName = self.ranBranch.replace('/','-')
imageTag = f'{branchName}-{self.ranCommitID[0:8]}'
if self.ranTargetBranch == 'develop':
if self.merge: # merging MR branch into develop -> temporary image
branchName = self.branch.replace('/','-')
imageTag = f'{branchName}-{self.commitID}'
if self.targetBranch == 'develop':
ret = self.cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.rhel9 | grep --colour=never -i INDEX')
result = re.search('index', ret.stdout)
if result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
# if the branch name contains integration_20xx_wyy, let rebuild ran-base
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.ranBranch)
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.branch)
if not forceBaseImageBuild and result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
else:
imageTag = f'develop-{self.ranCommitID[0:8]}'
imageTag = f'develop-{self.commitID}'
forceBaseImageBuild = True
# logging to OC Cluster and then switch to corresponding project

View File

@@ -32,33 +32,32 @@ from cls_ci_helper import archiveArtifact
IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-enb-asan', 'oai-gnb-asan', 'oai-lte-ue-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan', 'oai-gnb-aerial', 'oai-gnb-fhi72']
DEFAULT_REGISTRY = "gracehopper3-oai.sboai.cs.eurecom.fr"
def CreateWorkspace(host, sourcePath, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge):
if ranCommitID == '':
logging.error('need ranCommitID in CreateWorkspace()')
raise ValueError('Insufficient Parameter in CreateWorkspace(): need ranCommitID')
def CreateWorkspace(host, sourcePath, repository, commitID, targetBranch, merge):
if commitID == '':
logging.error('need commitID in CreateWorkspace()')
raise ValueError('Insufficient Parameter in CreateWorkspace(): need commitID')
script = "scripts/create_workspace.sh"
options = f"{sourcePath} {ranRepository} {ranCommitID}"
if ranAllowMerge:
if ranTargetBranch == '':
ranTargetBranch = 'develop'
options += f" {ranTargetBranch}"
options = f"{sourcePath} {repository} {commitID}"
if merge:
if targetBranch == '':
targetBranch = 'develop'
options += f" {targetBranch}"
logging.info(f'execute "{script}" with options "{options}" on node {host}')
with cls_cmd.getConnection(host) as c:
ret = c.exec_script(script, 90, options)
logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}')
return ret.returncode == 0
def CreateTag(ranCommitID, ranBranch, ranAllowMerge):
if ranCommitID == 'develop':
def CreateTag(commitID, branch, merge):
if commitID == 'develop':
return 'develop'
shortCommit = ranCommitID[0:8]
if ranAllowMerge:
if merge:
# Allowing contributor to have a name/branchName format
branchName = ranBranch.replace('/','-')
tagToUse = f'{branchName}-{shortCommit}'
branchName = branch.replace('/','-')
tagToUse = f'{branchName}-{commitID}'
else:
tagToUse = f'develop-{shortCommit}'
tagToUse = f'develop-{commitID}'
return tagToUse
def AnalyzeBuildLogs(image, lf):
@@ -172,14 +171,13 @@ class Containerize():
def __init__(self):
self.ranRepository = ''
self.ranBranch = ''
self.ranAllowMerge = False
self.ranCommitID = ''
self.ranTargetBranch = ''
self.eNBSourceCodePath = ''
self.repository = ''
self.branch = ''
self.merge = False
self.commitID = ''
self.targetBranch = ''
self.workspace = ''
self.imageKind = ''
self.proxyCommit = None
self.yamlPath = ''
self.services = ''
self.deploymentTag = ''
@@ -193,7 +191,7 @@ class Containerize():
#-----------------------------------------------------------
def BuildImage(self, ctx, node, HTML):
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
log_files = []
@@ -249,16 +247,16 @@ class Containerize():
baseTag = 'develop'
forceBaseImageBuild = False
imageTag = 'develop'
if (self.ranAllowMerge):
if (self.merge):
imageTag = 'ci-temp'
if self.ranTargetBranch == 'develop':
if self.targetBranch == 'develop':
cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{dockerfileprefix} | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
# if the branch name contains integration_20xx_wyy, let rebuild ran-base
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.ranBranch)
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.branch)
if not forceBaseImageBuild and result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
@@ -376,90 +374,8 @@ class Containerize():
logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
return status
def BuildProxy(self, ctx, node, HTML):
lSourcePath = self.eNBSourceCodePath
logging.debug('Building on server: ' + node)
ssh = cls_cmd.getConnection(node)
oldRanCommidID = self.ranCommitID
oldRanRepository = self.ranRepository
oldRanAllowMerge = self.ranAllowMerge
oldRanTargetBranch = self.ranTargetBranch
self.ranCommitID = self.proxyCommit
self.ranRepository = 'https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy.git'
self.ranAllowMerge = False
self.ranTargetBranch = 'master'
# Let's remove any previous run artifacts if still there
ssh.run('docker image prune --force')
# Remove any previous proxy image
ssh.run('docker image rm oai-lte-multi-ue-proxy:latest')
tag = self.proxyCommit
logging.debug('building L2sim proxy image for tag ' + tag)
# check if the corresponding proxy image with tag exists. If not, build it
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
buildProxy = ret.returncode != 0 # if no image, build new proxy
if buildProxy:
ssh.run(f'rm -Rf {lSourcePath}')
success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
if not success:
raise Exception("could not clone proxy repository")
fullpath = f'{lSourcePath}/proxy_build.log'
ssh.run(f'docker build --target oai-lte-multi-ue-proxy --tag proxy:{tag} --file {lSourcePath}/docker/Dockerfile.ubuntu18.04 {lSourcePath} > {fullpath} 2>&1')
archiveArtifact(ssh, ctx, fullpath)
ssh.run('docker image prune --force')
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
if ret.returncode != 0:
logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m')
ssh.close()
HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK)
return False
else:
logging.debug('L2sim proxy image for tag ' + tag + ' already exists, skipping build')
# retag the build images to that we pick it up later
ssh.run(f'docker image tag proxy:{tag} oai-lte-multi-ue-proxy:latest')
# we assume that the host on which this is built will also run the proxy. The proxy
# currently requires the following command, and the docker-compose up mechanism of
# the CI does not allow to run arbitrary commands. Note that the following actually
# belongs to the deployment, not the build of the proxy...
logging.warning('the following command belongs to deployment, but no mechanism exists to exec it there!')
ssh.run('sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up')
# to prevent accidentally overwriting data that might be used later
self.ranCommitID = oldRanCommidID
self.ranRepository = oldRanRepository
self.ranAllowMerge = oldRanAllowMerge
self.ranTargetBranch = oldRanTargetBranch
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
result = re.search(r'Size *= *(?P<size>[0-9\-]+) *bytes', ret.stdout)
# Cleaning any created tmp volume
ssh.run('docker volume prune --force')
ssh.close()
allImagesSize = {}
if result is not None:
imageSize = float(result.group('size')) / 1000000
logging.debug('\u001B[1m proxy size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m')
allImagesSize['proxy'] = str(round(imageSize,1)) + ' Mbytes'
logging.info('\u001B[1m Building L2sim Proxy Image Pass\u001B[0m')
HTML.CreateHtmlTestRow('commit ' + tag, 'OK', CONST.ALL_PROCESSES_OK)
return True
else:
logging.error('proxy size is unknown')
allImagesSize['proxy'] = 'unknown'
logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m')
HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK)
return False
def BuildRunTests(self, ctx, node, dockerfile, runtime_opt, ctest_opt, HTML):
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
cmd.cd(lSourcePath)
@@ -467,8 +383,8 @@ class Containerize():
# check that ran-base image exists as we expect it
baseImage = 'ran-base'
baseTag = 'develop'
if self.ranAllowMerge:
if self.ranTargetBranch == 'develop':
if self.merge:
if self.targetBranch == 'develop':
cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.ubuntu | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
@@ -511,7 +427,7 @@ class Containerize():
return False
def Push_Image_to_Local_Registry(self, node, HTML, tag_prefix=""):
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
logging.debug('Pushing images to server: ' + node)
ssh = cls_cmd.getConnection(node)
imagePrefix = DEFAULT_REGISTRY
@@ -524,10 +440,10 @@ class Containerize():
return False
orgTag = 'develop'
if self.ranAllowMerge:
if self.merge:
orgTag = 'ci-temp'
for image in IMAGES:
tagToUse = tag_prefix + CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
tagToUse = tag_prefix + CreateTag(self.commitID, self.branch, self.merge)
imageTag = f"{image}:{tagToUse}"
ret = ssh.run(f'docker image tag {image}:{orgTag} {imagePrefix}/{imageTag}')
if ret.returncode != 0:
@@ -540,7 +456,7 @@ class Containerize():
HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK)
return False
# Creating a develop tag on the local private registry
if not self.ranAllowMerge:
if not self.merge:
devTag = f"{tag_prefix}develop"
ssh.run(f'docker image tag {image}:{orgTag} {imagePrefix}/{image}:{devTag}')
ssh.run(f'docker push {imagePrefix}/{image}:{devTag}')
@@ -588,7 +504,7 @@ class Containerize():
def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry=DEFAULT_REGISTRY, username="oaicicd", password="oaicicd"):
logging.debug(f'\u001B[1m Pulling image(s) on server: {node}\u001B[0m')
if not tag:
tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
tag = CreateTag(self.commitID, self.branch, self.merge)
with cls_cmd.getConnection(node) as cmd:
success, msg = Containerize.Pull_Image(cmd, images, tag, tag_prefix, registry, username, password)
param = f"on node {node}"
@@ -601,7 +517,7 @@ class Containerize():
def Clean_Test_Server_Images(self, HTML, node, images, tag=None):
logging.debug(f'\u001B[1m Cleaning image(s) from server: {node}\u001B[0m')
if not tag:
tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
tag = CreateTag(self.commitID, self.branch, self.merge)
status = True
with cls_cmd.getConnection(node) as myCmd:
@@ -620,8 +536,8 @@ class Containerize():
return status
def Create_Workspace(self, node, HTML):
lSourcePath = self.eNBSourceCodePath
success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
lSourcePath = self.workspace
success = CreateWorkspace(node, lSourcePath, self.repository, self.commitID, self.targetBranch, self.merge)
if success:
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {lSourcePath}"])
else:
@@ -630,7 +546,7 @@ class Containerize():
def DeployObject(self, ctx, node, HTML):
num_attempts = self.num_attempts
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
@@ -648,7 +564,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:
@@ -674,7 +590,7 @@ class Containerize():
return deployed
def StopObject(self, ctx, node, HTML):
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
if not self.services:
raise ValueError(f'no services provided')
logging.info(f'\u001B[1m Stopping objects "{self.services}" from server: {node}\u001B[0m')
@@ -703,7 +619,7 @@ class Containerize():
return success
def UndeployObject(self, ctx, node, HTML, to_analyze):
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
logging.info(f'\u001B[1m Undeploying all objects from server {node}\u001B[0m')
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
@@ -741,7 +657,7 @@ class Containerize():
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None):
logging.info(f'Analyzing realtime stats from server: {node}')
yaml = self.yamlPath.strip('/')
wd = f'{self.eNBSourceCodePath}/{yaml}'
wd = f'{self.workspace}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as cmd:

View File

@@ -33,11 +33,11 @@ class HTMLManagement():
self.htmlHeaderCreated = False
self.htmlFooterCreated = False
self.ranRepository = ''
self.ranBranch = ''
self.ranCommitID = ''
self.ranAllowMerge = False
self.ranTargetBranch = ''
self.repository = ''
self.branch = ''
self.commitID = ''
self.merge = False
self.targetBranch = ''
self.nbTestXMLfiles = 0
self.htmlTabRefs = []
@@ -96,46 +96,46 @@ class HTMLManagement():
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-cloud-upload"></span> GIT Repository </td>\n')
self.htmlFile.write(' <td><a href="' + self.ranRepository + '">' + self.ranRepository + '</a></td>\n')
self.htmlFile.write(' <td><a href="' + self.repository + '">' + self.repository + '</a></td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-wrench"></span> Job Trigger </td>\n')
if (self.ranAllowMerge):
if (self.merge):
self.htmlFile.write(' <td>Merge-Request</td>\n')
else:
self.htmlFile.write(' <td>Push to Branch</td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' <tr>\n')
if (self.ranAllowMerge):
if (self.merge):
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Source Branch </td>\n')
else:
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tree-deciduous"></span> Branch</td>\n')
self.htmlFile.write(' <td>' + self.ranBranch + '</td>\n')
self.htmlFile.write(' <td>' + self.branch + '</td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' <tr>\n')
if (self.ranAllowMerge):
if (self.merge):
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Source Commit ID </td>\n')
else:
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Commit ID </td>\n')
self.htmlFile.write(' <td>' + self.ranCommitID + '</td>\n')
self.htmlFile.write(' <td>' + self.commitID + '</td>\n')
self.htmlFile.write(' </tr>\n')
if self.ranAllowMerge != '' and self.ranCommitID != 'develop':
commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True)
if self.merge != '' and self.commitID != 'develop':
commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.commitID, shell=True, universal_newlines=True)
commit_message = commit_message.strip()
self.htmlFile.write(' <tr>\n')
if (self.ranAllowMerge):
if (self.merge):
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Source Commit Message </td>\n')
else:
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Commit Message </td>\n')
self.htmlFile.write(' <td>' + commit_message + '</td>\n')
self.htmlFile.write(' </tr>\n')
if (self.ranAllowMerge):
if (self.merge):
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
if (self.ranTargetBranch == ''):
if (self.targetBranch == ''):
self.htmlFile.write(' <td>develop</td>\n')
else:
self.htmlFile.write(' <td>' + self.ranTargetBranch + '</td>\n')
self.htmlFile.write(' <td>' + self.targetBranch + '</td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' </table>\n')

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':
@@ -265,12 +282,8 @@ def Deploy_Physim(ctx, HTML, node, workdir, script, options):
class OaiCiTest():
def __init__(self):
self.ranRepository = ''
self.ranBranch = ''
self.ranCommitID = ''
self.ranAllowMerge = False
self.ranTargetBranch = ''
self.repository = ''
self.branch = ''
self.testXMLfiles = []
self.ping_args = ''
self.ping_packetloss_threshold = ''
@@ -457,7 +470,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 +483,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 +498,7 @@ 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)
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)
@@ -495,6 +507,10 @@ class OaiCiTest():
else:
status, msg = Iperf_analyzeV3TCPJson(dest_filename, self.iperf_tcp_rate_target)
# add some diagnostic messages if the actual iperf command returned non-zero
if client_ret.returncode != 0:
msg = f'{msg}\nIperf client command failed on {bindIP} -> {svrIP}:{port} (return code: {client_ret.returncode})'
return (status, f'{ue_header}\n{msg}')
def Iperf(self, ctx, node, HTML, infra_file="ci_infra.yaml"):

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,271 @@
# 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 = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 12345678L;
////////// Physical parameters:
do_CSIRS = 1;
do_SRS = 1;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
absoluteFrequencySSB = 641280;
dl_frequencyBand = 78;
# this is 3600 MHz
dl_absoluteFrequencyPointA = 640008;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 106;
#initialDownlinkBWP
#genericParameters
# this is RBstart=27,L=48 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 12;
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 = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 28875;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 148;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 13;
preambleReceivedTargetPower = -96;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 10;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 1;
#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 = 14;
#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,
msg3_DeltaPreamble = 1;
p0_NominalWithGrant =-90;
# 0=sl1, 1=sl2, 2=sl4, 3=sl8, 4=sl10, 5=sl20, 6=sl40, 7=sl80, 8=sl160, 9=sl320
msgB_ResponseWindow_r16 = 5;
msgA_RSRP_Threshold_r16 = 19;
msgA_CB_PreamblesPerSSB_PerSharedRO_r16 = 1;
msgA_MCS_r16 = 2;
nrofSlotsMsgA_PUSCH_r16 = 1;
# 0=one, 1=two, 2=three, 3=six
nrofMsgA_PO_PerSlot_r16 = 0;
msgA_PUSCH_TimeDomainOffset_r16 = 8;
startSymbolAndLengthMsgA_PO_r16 = 38;
mappingTypeMsgA_PUSCH_r16 = 0;
guardBandMsgA_PUSCH_r16 = 0;
frequencyStartMsgA_PUSCH_r16 = 0;
nrofPRBs_PerMsgA_PO_r16 = 8;
# 0=one, 1=two, 2=four, 3=eight
nrofMsgA_PO_FDM_r16 = 0;
msgA_PUSCH_NrofPorts_r16 = 1;
nrofDMRS_Sequences_r16 = 1;
# 0=enabled, 1=disabled
msgA_TransformPrecoder_r16 = 1;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 40;
p0_nominal = -90;
ssb_PositionsInBurst_Bitmap = 1;
# 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 = 6;
nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -25;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "192.168.71.132"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/24";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 150;
pucch_TargetSNRx10 = 200;
}
);
L1s = (
{
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
pucch0_dtx_threshold = 100;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 12;
att_rx = 12;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 114;
eNB_instances = [0];
clock_src = "internal";
}
);
rfsimulator :
{
serveraddr = "server";
serverport = 4043;
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
IQfile = "/tmp/rfsimulator.iqs";
};
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 ="debug";
f1ap_log_level ="debug";
};
e2_agent = {
near_ric_ip_addr = "127.0.0.1";
#sm_dir = "/path/where/the/SMs/are/located/"
sm_dir = "/usr/local/lib/flexric/"
};

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

@@ -30,7 +30,7 @@ channelmod:
- model_name: rfsimu_channel_ue0
type: AWGN
ploss_dB: 20
nose_power_dB: -2
noise_power_dB: -2
forgetfact: 0
offset: 0
ds_tdl: 0

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

@@ -65,21 +65,16 @@ def ExecuteActionWithParam(action, ctx, node):
global HTML
global CONTAINERS
global CLUSTER
if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests":
if action == 'Build_eNB' or action == 'Build_Image' or action == "Build_Cluster_Image" or action == "Build_Run_Tests":
RAN.Build_eNB_args=test.findtext('Build_eNB_args')
CONTAINERS.imageKind=test.findtext('kind')
proxy_commit = test.findtext('proxy_commit')
dockerfile = test.findtext('dockerfile') or ''
runtime_opt = test.findtext('runtime-opt') or ''
ctest_opt = test.findtext('ctest-opt') or ''
if proxy_commit is not None:
CONTAINERS.proxyCommit = proxy_commit
if action == 'Build_eNB':
success = cls_native.Native.Build(ctx, node, HTML, RAN.eNBSourceCodePath, RAN.Build_eNB_args)
success = cls_native.Native.Build(ctx, node, HTML, RAN.workspace, RAN.Build_eNB_args)
elif action == 'Build_Image':
success = CONTAINERS.BuildImage(ctx, node, HTML)
elif action == 'Build_Proxy':
success = CONTAINERS.BuildProxy(ctx, node, HTML)
elif action == 'Build_Cluster_Image':
success = CLUSTER.BuildClusterImage(ctx, node, HTML)
elif action == 'Build_Run_Tests':
@@ -153,16 +148,16 @@ def ExecuteActionWithParam(action, ctx, node):
elif action == 'Deploy_Run_OC_PhySim':
oc_release = test.findtext('oc_release')
script = "scripts/oc-deploy-physims.sh"
image_tag = cls_containerize.CreateTag(CLUSTER.ranCommitID, CLUSTER.ranBranch, CLUSTER.ranAllowMerge)
options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.eNBSourceCodePath}"
workdir = CLUSTER.eNBSourceCodePath
image_tag = cls_containerize.CreateTag(CLUSTER.commitID, CLUSTER.branch, CLUSTER.merge)
options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.workspace}"
workdir = CLUSTER.workspace
success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options)
elif action == 'Build_Deploy_PhySim':
ctest_opt = test.findtext('ctest-opt') or ''
script = test.findtext('script')
options = f"{CONTAINERS.eNBSourceCodePath} {ctest_opt}"
workdir = CONTAINERS.eNBSourceCodePath
options = f"{CONTAINERS.workspace} {ctest_opt}"
workdir = CONTAINERS.workspace
success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options)
elif action == 'DeployCoreNetwork' or action == 'UndeployCoreNetwork':
@@ -174,7 +169,7 @@ def ExecuteActionWithParam(action, ctx, node):
CONTAINERS.yamlPath = test.findtext('yaml_path')
CONTAINERS.services = test.findtext('services')
CONTAINERS.num_attempts = int(test.findtext('num_attempts') or 1)
CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge)
CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.commitID, CONTAINERS.branch, CONTAINERS.merge)
if action == 'Deploy_Object':
success = CONTAINERS.DeployObject(ctx, node, HTML)
elif action == 'Stop_Object':
@@ -195,7 +190,7 @@ def ExecuteActionWithParam(action, ctx, node):
success = CONTAINERS.Create_Workspace(node, HTML)
elif action == 'LicenceAndFormattingCheck':
success = SCA.StaticCodeAnalysis.LicenceAndFormattingCheck(ctx, node, HTML, RAN.eNBSourceCodePath, RAN.ranBranch, RAN.ranAllowMerge, RAN.ranTargetBranch)
success = SCA.StaticCodeAnalysis.LicenceAndFormattingCheck(ctx, node, HTML, RAN.workspace, RAN.branch, RAN.merge, RAN.targetBranch)
elif action == 'Push_Local_Registry':
tag_prefix = test.findtext('tag_prefix') or ""
@@ -219,14 +214,14 @@ def ExecuteActionWithParam(action, ctx, node):
elif action == 'Custom_Command':
command = test.findtext('command')
# Allow referencing repository workspace path in XML via %%workspace%%
command = command.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath)
command = command.replace("%%workspace%%", CONTAINERS.workspace)
success = cls_oaicitest.Custom_Command(HTML, node, command)
elif action == 'Custom_Script':
script = test.findtext('script')
args = test.findtext('args')
# Allow referencing repository workspace path in XML via %%workspace%%
script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath)
script = script.replace("%%workspace%%", CONTAINERS.workspace)
success = cls_oaicitest.Custom_Script(HTML, node, script, args)
elif action == 'Pull_Cluster_Image':
@@ -370,15 +365,15 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
logging.info('\u001B[1m Starting Scenario: ' + CiTestObj.testXMLfiles[0] + '\u001B[0m')
logging.info('\u001B[1m----------------------------------------\u001B[0m')
if re.match('^TesteNB$', mode, re.IGNORECASE):
if RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBSourceCodePath == '':
if RAN.repository == '' or RAN.branch == '' or RAN.workspace == '':
HELP.GenericHelp(CONST.Version)
if RAN.ranRepository == '':
HELP.GitSrvHelp(RAN.ranRepository, RAN.ranBranch, RAN.ranCommitID, RAN.ranAllowMerge, RAN.ranTargetBranch)
if RAN.eNBSourceCodePath == '':
HELP.eNBSrvHelp(RAN.eNBSourceCodePath)
if RAN.repository == '':
HELP.GitSrvHelp(RAN.repository, RAN.branch, RAN.commitID, RAN.merge, RAN.targetBranch)
if RAN.workspace == '':
HELP.eNBSrvHelp(RAN.workspace)
sys.exit('Insufficient Parameter')
else:
if CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '':
if CiTestObj.repository == '' or CiTestObj.branch == '':
HELP.GenericHelp(CONST.Version)
sys.exit('UE: Insufficient Parameter')

View File

@@ -58,18 +58,20 @@ 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
# ----------------------------
# Check unsigned commits
# ----------------------------
unsignedCommits=$(
for c in $(git rev-list "$TARGET_BRANCH".."$SOURCE_BRANCH"); do
for c in $(git rev-list "$TARGET_BRANCH".."$SOURCE_BRANCH" --no-merges); do
if ! git log -1 --format=%B "$c" | grep -q "Signed-off-by:"; then
git log -1 --format='%h' "$c"
fi

View File

@@ -32,12 +32,12 @@ class RANManagement():
def __init__(self):
self.ranRepository = ''
self.ranBranch = ''
self.ranAllowMerge = False
self.ranCommitID = ''
self.ranTargetBranch = ''
self.eNBSourceCodePath = ''
self.repository = ''
self.branch = ''
self.merge = False
self.commitID = ''
self.targetBranch = ''
self.workspace = ''
self.Initialize_eNB_args = ''
self.imageKind = ''
self.eNBOptions = ['', '', '']
@@ -57,7 +57,7 @@ class RANManagement():
raise ValueError(f"{node=}")
logging.debug('Starting eNB/gNB on server: ' + node)
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
cmd = cls_cmd.getConnection(node)
# Initialize_eNB_args usually start with -O and followed by the location in repository
@@ -103,7 +103,7 @@ class RANManagement():
def TerminateeNB(self, ctx, node, HTML, to_analyze):
logging.debug('Stopping eNB/gNB on server: ' + node)
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
cmd = cls_cmd.getConnection(node)
ret = cmd.run('ps -aux | grep --color=never -e softmodem | grep -v grep')
result = re.search('-softmodem', ret.stdout)
@@ -138,7 +138,7 @@ class RANManagement():
def AnalyzeRTStats(self, HTML, node, ctx, thresholds):
logging.info(f'Analyzing realtime stats from server: {node}')
lSourcePath = self.eNBSourceCodePath
lSourcePath = self.workspace
logdir = f'{lSourcePath}/cmake_targets'
with cls_cmd.getConnection(node) as cmd:

View File

@@ -24,7 +24,7 @@ class TestBuild(unittest.TestCase):
self._d = tempfile.mkdtemp()
logging.warning(f"temporary directory: {self._d}")
self.node = 'localhost'
self.cont.eNBSourceCodePath = self._d
self.cont.workspace = self._d
self.ctx = TestCaseCtx.Default(tempfile.mkdtemp())
def tearDown(self):
@@ -33,10 +33,5 @@ class TestBuild(unittest.TestCase):
cmd.run(f"rm -rf {self._d}")
cmd.run(f'rm -rf {self.ctx.logPath}')
def test_build_proxy(self):
self.cont.proxyCommit = "b64d9bce986b38ca59e8582864ade3fcdd05c0dc"
success = self.cont.BuildProxy(self.ctx, self.node, self.html)
self.assertTrue(success)
if __name__ == '__main__':
unittest.main()

View File

@@ -41,10 +41,10 @@ class TestDeploymentMethods(unittest.TestCase):
self.ci = cls_oaicitest.OaiCiTest()
self.cont = cls_containerize.Containerize()
self.cont.yamlPath = ''
self.cont.ranAllowMerge = True
self.cont.ranBranch = ''
self.cont.ranCommitID = ''
self.cont.eNBSourceCodePath = os.getcwd()
self.cont.merge = True
self.cont.branch = ''
self.cont.commitID = ''
self.cont.workspace = os.getcwd()
self.cont.num_attempts = 3
self.node = 'localhost'
self.ctx = TestCaseCtx.Default(tempfile.mkdtemp())
@@ -136,13 +136,13 @@ class TestDeploymentMethods(unittest.TestCase):
self.assertTrue(undeploy)
def test_create_workspace(self):
self.cont.eNBSourceCodePath = tempfile.mkdtemp()
self.cont.ranRepository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git"
self.cont.ranCommitID = "05f9c975eeecbca1bdff5940affad44465f1301f"
self.cont.ranBranch = "develop"
self.cont.workspace = tempfile.mkdtemp()
self.cont.repository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git"
self.cont.commitID = "05f9c975eeecbca1bdff5940affad44465f1301f"
self.cont.branch = "develop"
ws = self.cont.Create_Workspace(self.node, self.html)
with cls_cmd.LocalCmd() as cmd:
cmd.run(f"rm -rf {self.cont.eNBSourceCodePath}")
cmd.run(f"rm -rf {self.cont.workspace}")
self.assertTrue(ws)
def test_undeploy_loganalysis(self):

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

@@ -22,7 +22,7 @@ class TestDeploymentMethods(unittest.TestCase):
self.html = cls_oai_html.HTMLManagement()
self.html.testCaseId = "000000"
self.cont = cls_containerize.Containerize()
self.cont.eNBSourceCodePath = os.getcwd()
self.cont.workspace = os.getcwd()
def test_pull_clean_local_reg(self):
# the pull function has the authentication at the internal cluster hardcoded

View File

@@ -1,5 +1,4 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
- Build_Proxy
- Build_Cluster_Image
- Pull_Cluster_Image
- Build_eNB

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

@@ -1,15 +0,0 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>l2sim-4glte-5gnr-proxy-build</htmlTabRef>
<htmlTabName>Build L2sim proxy image</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<testCase>
<class>Build_Proxy</class>
<desc>Build L2sim Proxy Image</desc>
<node>localhost</node>
<proxy_commit>b64d9bce986b38ca59e8582864ade3fcdd05c0dc</proxy_commit>
</testCase>
</testCaseList>

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

@@ -0,0 +1,85 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>monolithic_2step_ra_gnb_rfsim</htmlTabRef>
<htmlTabName>Monolithic 2-Step RA gNB rfsim</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>localhost</node>
<images>oai-gnb-asan oai-nr-ue-asan</images>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<node>localhost</node>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy OAI gNB</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
<services>mysql oai-amf oai-smf oai-upf oai-ext-dn</services>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy OAI NR-UE</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
<services>oai-gnb oai-nr-ue</services>
</testCase>
<testCase>
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
<id>rfsim5g_ue</id>
<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 -i0.2</ping_args>
<ping_packetloss_threshold>0</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 -i0.2</ping_args>
<ping_packetloss_threshold>0</ping_packetloss_threshold>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
<analysis>
<services>oai-gnb=RetxCheck=10,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>localhost</node>
<images>oai-gnb-asan oai-nr-ue-asan</images>
</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,162 @@
# SPDX-License-Identifier: MIT
services:
mysql:
container_name: "rfsim5g-mysql"
image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
environment:
- TZ=Europe/Paris
- MYSQL_DATABASE=oai_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=linux
healthcheck:
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 30
networks:
public_net:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml
depends_on:
- mysql
networks:
public_net:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
depends_on:
- oai-amf
networks:
public_net:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml
depends_on:
- oai-smf
cap_add:
- NET_ADMIN
- SYS_ADMIN
cap_drop:
- ALL
privileged: true
networks:
public_net:
ipv4_address: 192.168.71.134
interface_name: eth0
traffic_net:
ipv4_address: 192.168.72.134
interface_name: eth1
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
image: oaisoftwarealliance/trf-gen-cn5g:latest
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"
depends_on:
- oai-upf
networks:
traffic_net:
ipv4_address: 192.168.72.135
healthcheck:
test: /bin/bash -c "ping -c 2 192.168.72.134"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 5
oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop}
container_name: rfsim5g-oai-gnb
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
ASAN_OPTIONS: detect_leaks=0
networks:
public_net:
ipv4_address: 192.168.71.140
volumes:
- ../../conf_files/gnb.sa.band78.106prb.usrpb210.RA_2-Step.conf:/opt/oai-gnb/etc/gnb.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 5
oai-nr-ue:
image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
container_name: rfsim5g-oai-nr-ue
cap_drop:
- ALL
cap_add:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS: --rfsim
--rfsimulator.[0].serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
-C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78
ASAN_OPTIONS: detect_leaks=0
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf
depends_on:
- oai-gnb
networks:
public_net:
ipv4_address: 192.168.71.150
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
driver: bridge
name: rfsim5g-oai-public-net
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-public"
traffic_net:
driver: bridge
name: rfsim5g-oai-traffic-net
ipam:
config:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-traffic"

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

@@ -1454,7 +1454,7 @@ ID = UE_PHY_PDCCH_ENERGY
ID = UE_PHY_PDSCH_IQ
DESC = UE PDSCH received IQ data
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pdsch_comp
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_DL : int,symbols_per_tti : buffer,pdsch_comp
ID = UE_PHY_PDSCH_ENERGY
DESC = UE PDSCH 1 energy and threshold
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE

View File

@@ -229,8 +229,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
e->pdsch_iq_ue_xy_plot = w;
widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, -500, 500, -500, 500);
l = new_iqlog(h, database, "UE_PHY_PDSCH_IQ", "nb_rb",
"N_RB_UL", "symbols_per_tti", "pusch_comp");
l = new_iqlog(h, database, "UE_PHY_PDSCH_IQ", "nb_rb", "N_RB_DL", "symbols_per_tti", "pdsch_comp");
v = new_view_xy(100*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
logger_add_view(l, v);
e->pdsch_iq_ue_logger = l;

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

@@ -71,7 +71,9 @@ static inline const char *rnti_types(nr_rnti_type_t rr)
#define MAX_GSCN_BAND 620 // n78 has the highest GSCN range of 619
#define NR_SYMBOLS_PER_SLOT 14
#define NR_SYMBOLS_PER_SLOT_EXTENDED_CP 12
#define NR_MAX_NB_LAYERS 4 // 8
#define NR_MAX_NB_LAYERS 4
#define MAX_NUM_NR_DLSCH_SEGMENTS (MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS)
#define MAX_NUM_NR_ULSCH_SEGMENTS (MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS)
#define NR_MAX_CSI_PORTS 12
// Since the IQ samples are represented by SQ15 R+I (see https://en.wikipedia.org/wiki/Q_(number_format)) we need to compensate when

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
@@ -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:

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

@@ -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);
@@ -1011,7 +1011,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 +1020,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

@@ -70,6 +70,7 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "openair1/SCHED_NR/sched_nr.h"
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
RAN_CONTEXT_t RC;
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
@@ -100,13 +101,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 +437,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 +653,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

@@ -100,7 +100,7 @@ one_measurement_t test_ldpc(short max_iterations,
double sigma;
sigma = 1.0 / sqrt(2 * SNR);
cpu_meas_enabled = 1;
uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS];
uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS];
uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][Kprime];
memset(estimated_output, 0, sizeof(estimated_output));
uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS];

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

@@ -577,16 +577,20 @@ int nr_rate_matching_ldpc(uint32_t Tbslbrm,
}
while (k < E) { // case where we do repetitions (low mcs)
for (ind = 0; (ind < Ncb) && (k < E); ind++) {
#ifdef RM_DEBUG
printf("RM_TX k%u Ind: %u (%d)\n", k, ind, d[ind]);
#endif
if (ind == Foffset)
ind = F + Foffset; // skip filler bits
e[k++] = d[ind];
// chunk before filler: d[0 .. Foffset)
if (Foffset > 0) {
uint32_t n = min(Foffset, E - k);
memcpy(e + k, d, n);
k += n;
if (k >= E)
break;
}
// chunk after filler: d[Foffset+F .. Ncb)
uint32_t after = Ncb - Foffset - F;
if (after > 0) {
uint32_t n = min(after, E - k);
memcpy(e + k, d + Foffset + F, n);
k += n;
}
}

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

@@ -102,7 +102,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
int Ptx = cfg->carrier_config.num_tx_ant.value;
int Prx = cfg->carrier_config.num_rx_ant.value;
int max_ul_mimo_layers = 4;
int max_ul_mimo_layers = NR_MAX_NB_LAYERS;
AssertFatal(Ptx > 0 && Ptx < 9,"Ptx %d is not supported\n", Ptx);
AssertFatal(Prx > 0 && Prx < 9,"Prx %d is not supported\n", Prx);
@@ -198,7 +198,7 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
{
const int Ptx = gNB->gNB_config.carrier_config.num_tx_ant.value;
const int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value;
const int max_ul_mimo_layers = 4; // taken from phy_init_nr_gNB()
const int max_ul_mimo_layers = NR_MAX_NB_LAYERS;
const int n_buf = Prx * max_ul_mimo_layers;
PHY_MEASUREMENTS_gNB *meas = &gNB->measurements;

View File

@@ -321,7 +321,7 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue)
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_HARQ_PROCESSES], int number_of_processes, int num_rb)
{
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS;
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS;
if (num_rb != 273) {
a_segments = a_segments*num_rb;
a_segments = (a_segments/273)+1;
@@ -343,7 +343,7 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_HARQ_PROCESSES], int
void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_HARQ_PROCESSES], int number_of_processes, int num_rb, int num_ant_tx)
{
int max_layers = (num_ant_tx < NR_MAX_NB_LAYERS) ? num_ant_tx : NR_MAX_NB_LAYERS;
int max_layers = min(num_ant_tx, NR_MAX_NB_LAYERS);
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*max_layers; //number of segments to be allocated
if (num_rb != 273) {
@@ -374,7 +374,7 @@ void term_nr_ue_transport(PHY_VARS_NR_UE *ue)
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_HARQ_PROCESSES], int number_of_processes, int num_rb)
{
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; // number of segments to be allocated
if (num_rb != 273) {
a_segments = a_segments*num_rb;
a_segments = (a_segments/273)+1;
@@ -402,7 +402,7 @@ void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_HARQ_PROCESSE
void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t harq_list[NR_MAX_HARQ_PROCESSES], int number_of_processes, int num_rb, int num_ant_tx)
{
int max_layers = (num_ant_tx < NR_MAX_NB_LAYERS) ? num_ant_tx : NR_MAX_NB_LAYERS;
int max_layers = min(num_ant_tx, NR_MAX_NB_LAYERS);
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*max_layers; //number of segments to be allocated
if (num_rb != 273) {

View File

@@ -1466,11 +1466,14 @@ int rx_pdsch(PHY_VARS_UE *ue,
}
#endif
T(T_UE_PHY_PDSCH_IQ, T_INT(eNB_id), T_INT(frame%1024),
T_INT(subframe), T_INT(nb_rb),
T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_tti),
T_BUFFER(&pdsch_vars[eNB_id]->rxdataF_comp0[eNB_id][0],
2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_tti*2));
T(T_UE_PHY_PDSCH_IQ,
T_INT(eNB_id),
T_INT(frame % 1024),
T_INT(subframe),
T_INT(nb_rb),
T_INT(frame_parms->N_RB_DL),
T_INT(frame_parms->symbols_per_tti),
T_BUFFER(&pdsch_vars[eNB_id]->rxdataF_comp0[eNB_id][0], 2 * frame_parms->N_RB_DL * 12 * frame_parms->symbols_per_tti * 2));
return 0;
}

View File

@@ -446,11 +446,11 @@ static void nr_pusch_antenna_processing(void *arg)
completed_task_ans(rdata->ans);
}
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
unsigned char Ns,
int nl,
unsigned short p,
uint8_t lp,
unsigned char symbol,
NR_gNB_PUSCH *pusch_vars,
int beam_nb,
@@ -486,7 +486,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
gold,
pilot,
(1000 + p),
0,
lp % 2,
nb_rb_pusch,
(pusch_pdu->bwp_start + pusch_pdu->rb_start) * NR_NB_SC_PER_RB,
pusch_pdu->dmrs_config_type,
@@ -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

@@ -28,6 +28,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
unsigned char Ns,
int nl,
unsigned short p,
uint8_t lp,
unsigned char symbol,
NR_gNB_PUSCH *pusch_vars,
int beam_nb,
@@ -70,8 +71,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

@@ -241,7 +241,8 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
uint8_t num_symbols,
uint8_t start_symbol,
uint16_t dmrs_bitmap,
uint16_t num_rbs)
uint16_t num_rbs,
uint8_t nb_layers)
{
simde__m128i *ul_ch128_0;
simde__m128i *ul_ch128_1;
@@ -250,64 +251,68 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
int num_dmrs_symb = count_bits64_with_mask(dmrs_bitmap, start_symbol, total_symbols);
int first_dmrs_symb = get_next_dmrs_symbol_in_slot(dmrs_bitmap, start_symbol, total_symbols);
AssertFatal(first_dmrs_symb > -1, "No DMRS symbol present in this slot\n");
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
for (int symb = first_dmrs_symb+1; symb < total_symbols; symb++) {
ul_ch128_0 = (simde__m128i *)&ch_estimates[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
if ((dmrs_bitmap >> symb) & 0x01) {
ul_ch128_1 = (simde__m128i *)&ch_estimates[aarx][symb*frame_parms->ofdm_symbol_size];
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = simde_mm_adds_epi16(ul_ch128_0[0], ul_ch128_1[0]);
ul_ch128_0[1] = simde_mm_adds_epi16(ul_ch128_0[1], ul_ch128_1[1]);
ul_ch128_0[2] = simde_mm_adds_epi16(ul_ch128_0[2], ul_ch128_1[2]);
ul_ch128_0 += 3;
ul_ch128_1 += 3;
for (int nl = 0; nl < nb_layers; nl++) {
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
int ch_offset = nl * frame_parms->nb_antennas_rx + aarx;
for (int symb = first_dmrs_symb + 1; symb < total_symbols; symb++) {
ul_ch128_0 = (simde__m128i *)&ch_estimates[ch_offset][first_dmrs_symb * frame_parms->ofdm_symbol_size];
if ((dmrs_bitmap >> symb) & 0x01) {
ul_ch128_1 = (simde__m128i *)&ch_estimates[ch_offset][symb * frame_parms->ofdm_symbol_size];
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = simde_mm_adds_epi16(ul_ch128_0[0], ul_ch128_1[0]);
ul_ch128_0[1] = simde_mm_adds_epi16(ul_ch128_0[1], ul_ch128_1[1]);
ul_ch128_0[2] = simde_mm_adds_epi16(ul_ch128_0[2], ul_ch128_1[2]);
ul_ch128_0 += 3;
ul_ch128_1 += 3;
}
}
}
ul_ch128_0 = (simde__m128i *)&ch_estimates[ch_offset][first_dmrs_symb * frame_parms->ofdm_symbol_size];
if (num_dmrs_symb == 2) {
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = simde_mm_srai_epi16(ul_ch128_0[0], 1);
ul_ch128_0[1] = simde_mm_srai_epi16(ul_ch128_0[1], 1);
ul_ch128_0[2] = simde_mm_srai_epi16(ul_ch128_0[2], 1);
ul_ch128_0 += 3;
}
} else if (num_dmrs_symb == 4) {
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = simde_mm_srai_epi16(ul_ch128_0[0], 2);
ul_ch128_0[1] = simde_mm_srai_epi16(ul_ch128_0[1], 2);
ul_ch128_0[2] = simde_mm_srai_epi16(ul_ch128_0[2], 2);
ul_ch128_0 += 3;
}
} else if (num_dmrs_symb == 3) {
ul_ch16_0 = (int16_t *)&ch_estimates[ch_offset][first_dmrs_symb * frame_parms->ofdm_symbol_size];
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch16_0[0] /= 3;
ul_ch16_0[1] /= 3;
ul_ch16_0[2] /= 3;
ul_ch16_0[3] /= 3;
ul_ch16_0[4] /= 3;
ul_ch16_0[5] /= 3;
ul_ch16_0[6] /= 3;
ul_ch16_0[7] /= 3;
ul_ch16_0[8] /= 3;
ul_ch16_0[9] /= 3;
ul_ch16_0[10] /= 3;
ul_ch16_0[11] /= 3;
ul_ch16_0[12] /= 3;
ul_ch16_0[13] /= 3;
ul_ch16_0[14] /= 3;
ul_ch16_0[15] /= 3;
ul_ch16_0[16] /= 3;
ul_ch16_0[17] /= 3;
ul_ch16_0[18] /= 3;
ul_ch16_0[19] /= 3;
ul_ch16_0[20] /= 3;
ul_ch16_0[21] /= 3;
ul_ch16_0[22] /= 3;
ul_ch16_0[23] /= 3;
ul_ch16_0 += 24;
}
} else
AssertFatal((num_dmrs_symb < 5) && (num_dmrs_symb > 0), "Illegal number of DMRS symbols in the slot\n");
}
ul_ch128_0 = (simde__m128i *)&ch_estimates[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
if (num_dmrs_symb == 2) {
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = simde_mm_srai_epi16(ul_ch128_0[0], 1);
ul_ch128_0[1] = simde_mm_srai_epi16(ul_ch128_0[1], 1);
ul_ch128_0[2] = simde_mm_srai_epi16(ul_ch128_0[2], 1);
ul_ch128_0 += 3;
}
} else if (num_dmrs_symb == 4) {
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch128_0[0] = simde_mm_srai_epi16(ul_ch128_0[0], 2);
ul_ch128_0[1] = simde_mm_srai_epi16(ul_ch128_0[1], 2);
ul_ch128_0[2] = simde_mm_srai_epi16(ul_ch128_0[2], 2);
ul_ch128_0 += 3;
}
} else if (num_dmrs_symb == 3) {
ul_ch16_0 = (int16_t *)&ch_estimates[aarx][first_dmrs_symb*frame_parms->ofdm_symbol_size];
for (int rbIdx = 0; rbIdx < num_rbs; rbIdx++) {
ul_ch16_0[0] /= 3;
ul_ch16_0[1] /= 3;
ul_ch16_0[2] /= 3;
ul_ch16_0[3] /= 3;
ul_ch16_0[4] /= 3;
ul_ch16_0[5] /= 3;
ul_ch16_0[6] /= 3;
ul_ch16_0[7] /= 3;
ul_ch16_0[8] /= 3;
ul_ch16_0[9] /= 3;
ul_ch16_0[10] /= 3;
ul_ch16_0[11] /= 3;
ul_ch16_0[12] /= 3;
ul_ch16_0[13] /= 3;
ul_ch16_0[14] /= 3;
ul_ch16_0[15] /= 3;
ul_ch16_0[16] /= 3;
ul_ch16_0[17] /= 3;
ul_ch16_0[18] /= 3;
ul_ch16_0[19] /= 3;
ul_ch16_0[20] /= 3;
ul_ch16_0[21] /= 3;
ul_ch16_0[22] /= 3;
ul_ch16_0[23] /= 3;
ul_ch16_0 += 24;
}
} else AssertFatal((num_dmrs_symb < 5) && (num_dmrs_symb > 0), "Illegal number of DMRS symbols in the slot\n");
}
}

View File

@@ -37,7 +37,8 @@ void nr_chest_time_domain_avg(NR_DL_FRAME_PARMS *frame_parms,
uint8_t num_symbols,
uint8_t start_symbol,
uint16_t dmrs_bitmap,
uint16_t num_rbs);
uint16_t num_rbs,
uint8_t nb_layers);
int8_t get_num_dmrs_re_per_rb(const uint8_t dmrs_type, const uint8_t num_cdm_grp_no_data);

View File

@@ -69,7 +69,7 @@ int nr_pusch_dmrs_rx(nr_prefix_type_t Ncp,
#ifdef DEBUG_PUSCH
printf("nr_pusch_dmrs_rx dmrs config type %d port %d nb_pusch_rb %d\n", dmrs_type, p, nb_pusch_rb);
printf("wf[%d] = %d wt[%d]= %d\n", i&1, wf[p-1000][i&1], lp, wt[p-1000][lp]);
printf("i %d idx %d pusch mod_dmrs %d %d\n", i, idx, output[k].r, output[k].i);
printf("i %d k %d pusch mod_dmrs %d %d\n", i, k, output[k].r, output[k].i);
#endif
}
} else {

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

@@ -25,7 +25,7 @@
void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARMS *frame_parms)
{
int max_layers = (frame_parms->nb_antennas_tx < NR_MAX_NB_LAYERS) ? frame_parms->nb_antennas_tx : NR_MAX_NB_LAYERS;
int max_layers = min(frame_parms->nb_antennas_tx, NR_MAX_NB_LAYERS);
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * max_layers;
if (N_RB != 273) {
@@ -50,7 +50,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM
NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB)
{
int max_layers = (frame_parms->nb_antennas_tx < NR_MAX_NB_LAYERS) ? frame_parms->nb_antennas_tx : NR_MAX_NB_LAYERS;
int max_layers = min(frame_parms->nb_antennas_tx, NR_MAX_NB_LAYERS);
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * max_layers; // number of segments to be allocated
if (N_RB != 273) {

View File

@@ -35,7 +35,7 @@
void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL)
{
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS; // number of segments to be allocated
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS; // number of segments to be allocated
if (N_RB_UL != 273) {
a_segments = a_segments * N_RB_UL;
@@ -61,7 +61,7 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL)
NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
{
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS; // number of segments to be allocated
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS; // number of segments to be allocated
if (N_RB_UL != 273) {
a_segments = a_segments * N_RB_UL;

View File

@@ -164,16 +164,14 @@ static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, const nfapi_nr_pusch
{
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
if (dmrs_symbol_flag == 1) {
if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01)
AssertFatal(1==0,"Double DMRS configuration is not yet supported\n");
if (rel15_ul->dmrs_config_type == 0) {
// if no data in dmrs cdm group is 1 only even REs have no data
// if no data in dmrs cdm group is 2 both odd and even REs have no data
return(rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6)));
}
else return(rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4)));
} else return(rel15_ul->rb_size * NR_NB_SC_PER_RB);
} else
return (rel15_ul->rb_size * NR_NB_SC_PER_RB);
}
static void nr_ulsch_channel_compensation(uint32_t buffer_length,
@@ -702,7 +700,7 @@ static uint8_t nr_ulsch_mmse_2layers(c16_t **rxdataF_comp,
// Add noise_var such that: H^h * H + noise_var * I
if (noise_var != 0) {
simde__m128i nvar_128i = simde_mm_set1_epi32(noise_var);
simde__m128i nvar_128i = simde_mm_set1_epi32(noise_var >> shift);
simde__m128i *af_mf_00_128i = (simde__m128i *)af_mf_00;
simde__m128i *af_mf_11_128i = (simde__m128i *)af_mf_11;
for (int k = 0; k < 3 * nb_rb_0; k++) {
@@ -914,9 +912,9 @@ static void inner_rx(PHY_VARS_gNB *gNB,
}
}
c16_t rho[nb_layer][nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_maga [nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_magb [nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_magc [nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_maga[nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_magb[nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_magc[nb_layer][buffer_length] __attribute__((aligned(32)));
memset(rho, 0, sizeof(rho));
memset(rxF_ch_maga, 0, sizeof(rxF_ch_maga));
@@ -1152,6 +1150,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
int max_ch = 0;
uint32_t nvar = 0;
int end_symbol = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
uint8_t dmrs_symb_idx = 0;
for (uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol++) {
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag);
@@ -1163,6 +1162,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
slot,
nl,
get_dmrs_port(nl, rel15_ul->dmrs_ports),
dmrs_symb_idx,
symbol,
pusch_vars,
beam_nb,
@@ -1174,10 +1174,12 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
pusch_ch_est_dmrs_pos_slot_mem);
nvar += nvar_tmp;
}
dmrs_symb_idx++;
}
}
nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx);
if (dmrs_symb_idx > 0)
nvar /= (dmrs_symb_idx * rel15_ul->nrOfLayers);
allocCast2D(n0_subband_power,
unsigned int,
@@ -1229,7 +1231,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
rel15_ul->nr_of_symbols,
rel15_ul->start_symbol_index,
rel15_ul->ul_dmrs_symb_pos,
rel15_ul->rb_size);
rel15_ul->rb_size,
rel15_ul->nrOfLayers);
stop_meas(&gNB->ulsch_channel_estimation_stats);

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)
{
@@ -986,7 +985,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL;
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
if (NR_MAX_NB_LAYERS>4)
if (NR_MAX_NB_LAYERS > 4)
dlsch1_harq = &ue->dl_harq_processes[1][harq_pid];
if (dlsch0_harq && dlsch1_harq){
@@ -1404,9 +1403,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
T_INT(frame % 1024),
T_INT(nr_slot_rx),
T_INT(nb_rb_pdsch),
T_INT(fp->N_RB_UL),
T_INT(fp->N_RB_DL),
T_INT(fp->symbols_per_slot),
T_BUFFER(&rxdataF_comp[gNB_id][0], 2 * fp->N_RB_UL * 12 * fp->symbols_per_slot * 2));
T_BUFFER(&rxdataF_comp[gNB_id][0], 2 * fp->N_RB_DL * 12 * fp->symbols_per_slot * 2));
#endif
if (ue->phy_sim_pdsch_rxdataF_comp)

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

@@ -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

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