Compare commits

...

152 Commits

Author SHA1 Message Date
Bartosz Podrygajlo
fe7bad3c35 Use cmake to enable a C/C++ compiler warning in a subdirectory 2026-03-03 18:16:53 +01:00
Robert Schmidt
46b7670672 Merge branch 'integration_2026_w09' into 'develop'
Integration `2026.w09`

* !3944 Fail early if configuration module can not initialize properly
* !3945 gNB: Reset NDI only after usage in case of disable HARQ
* !3822 NR UE: fix PRACH k1 calculation at MAC when handover
* !3874 print better message for rsrp: invalid doesn't mean it is not measures, it...
* !3928 NR UE: correctly compute writeTimestamp for SCS > 30 kHz with rf-simulator
* !3949 fix: removed the nssai_sd parameter in the ue.conf file
* !3897 Change Aerial config file in targets to match Nvidia's CI setup
* !3951 Fix handling of IPv4v6 PDU sessions
* !3940 IPV6 support for telnet socket binding
* !3947 Add missing packing for CONFIG.request parameter BetaPSS
* !3871 Support for up to 12 ports in NR gNB
* !3943 Remove L1 dependence from NR band number
* !3892 Synchronize multiple gNBs by aliging their the slot boundaries
* !3952 Fixes for Initial UE Context Setup
* !3953 Improvements in compilation dependence
* change dl_absoluteFrequencyPointA in targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf to 640032
* !3900 [CI] Pull Ubuntu base image from internal registry
* !3910 GPU Channel Simulation: nr_dlsim/nr_ulsim Integration + CI Test
* !3942 CI: rework log analysis to simplify and allow new use cases
* !3870 Configure CSI-RS according to beam_id used by UE

Closes #897 and #834

See merge request oai/openairinterface5g!3950
2026-02-27 08:41:22 +00:00
Jaroslava Fiedlerova
6f9e624193 Merge remote-tracking branch 'origin/config_csi_beam' into integration_2026_w09 (!3870)
Configure CSI-RS according to beam_id used by UE

This MR is to configure CSI-RS according to beam_id used by UE and
reconfigure upon beam change.

It has been tested with RFSIM, Liteon and Microamp under multiple beams.
2026-02-26 22:43:19 +01:00
Jaroslava Fiedlerova
f12b8cb44d Merge remote-tracking branch 'origin/ci-rework-logs' into integration_2026_w09 (!3942)
CI: rework log analysis to simplify and allow new use cases

The CI has some log analysis, but it is unmaintainable (huge functions
that mix eNB/gNB or lteUE/nrUE, are not tested, most of it is not used
or useful...) or limited to specific use cases (the timing-phytest time
analysis is hardcoded to source builds instead of also handling analysis
when running from docker images). This MR reimplements both functions.
For the log analysis, the CI team decided to throw away the old
analysis, and reimplement a mechanism that checks the couple of things
we care for.

- Allow to analyze phy-test timing analysis from docker files, and add a
  unit test
- Rework existing log analysis to remove useless checks, and make it
  more composable
  * The undeployment steps (Undeploy_Object(), Terminate_eNB()) take an
    <analysis> XML object which then either has a <services> subelement
    with check that are whitespace delimited (similar to how other xml
    task steps have <services>). For checks that contain whitespace,
    they can use <service> (singular) that encodes a single check, such
    that e.g., arguments could include spaces.
  * Each check is of form service=check[=arguments], where service is
    the docker services, check is a checking function (implemented as a
    class with run(file, options) function inside cls_loganalysis.py,
    and options arguments after the second = that is to be read by run()
    (basically, options will contain arguments that can be freeform)
  * these definitions can occur multiple times, e.g., it could be
    serviceA=Check1 and serviceA=Check2=Args and it will execute both
    Check1 and Check2
  * if a service is declared, it will execute alse the Default check
    which currently checks for an assertion
  * Implemented (and inspired from the existing CI analysis) are:
    - Default check to check for assertions (will be extended, to e.g.,
      address/undefined behavior sanitizer analysis)
    - RetxCheck: retransmission check as used in the CI
    - LastLineContains to check the last line containes a specific
      string
    - ContainsString to check a specific string appears in logs
    - EndsWithBye: check that towards the end (but not necessarily the
      last line), there is a Bye. string (a workaround since we don't
      always terminate with 0)
- There is a plan to use return codes after stopping in docker, but most
  executables do not end with 0 most of the time, such that we needed to
  abandon this plan.
- Additional fixes (see commit messages) and delete unused code
2026-02-26 22:39:29 +01:00
Jaroslava Fiedlerova
3eabd5363a Merge remote-tracking branch 'origin/multipath-testing-ci-physim' into integration_2026_w09 (!3910)
GPU Channel Simulation: nr_dlsim/nr_ulsim Integration + CI Test

This MR is a follow-up to !3886 (merged) and extends CUDA-based channel
simulation support to nr_dlsim and nr_ulsim, together with the
corresponding CI tests.

The MR incorporates:

- Cherry-picked commits e0c204f7 and 5f344876 from !3588
- Integration of new CI physim tests using GPU-accelerated channel
simulation in nr_dlsim and nr_ulsim tests, see commit c727b3bb

New CI job: RAN-Channel-Simulation
https://jenkins-oai.eurecom.fr/job/RAN-Channel-Simulation/
2026-02-26 22:38:15 +01:00
Jaroslava Fiedlerova
da28708459 CI: Add config files for phytest with 7.2 2026-02-26 17:34:07 +00:00
Mario Joa-Ng
f51f5d1f6e Get ssb_index using UE_beam_index under different beam_mode correctly. 2026-02-26 18:20:58 +01:00
Mario Joa-Ng
a77ba75b10 Configure CSI-RS according to beam_id used by UE and reconfigure upon beam change.
No need to call get_config_srs() anymore in update_cellGroupConfig_for_BWP_switch().
2026-02-26 18:20:25 +01:00
Jaroslava Fiedlerova
0a437db57c CI: Add physim tests with CUDA channel simulation 2026-02-26 17:03:54 +00:00
Robert Schmidt
e7360679f4 Merge remote-tracking branch 'origin/pull-noble-internal' into integration_2026_w09 (!3900)
[CI] Pull Ubuntu base image from internal registry

This MR updates the Docker build process for OAI images to use a private
registry for the Ubuntu base image ubuntu:noble. This will reduce the
possibility for CI disruption if no internet connection exists.

  - Replace FROM ubuntu:noble with FROM <DEFAULT_REGISTRY>/ubuntu:noble in Ubuntu Dockerfiles

This change overcomes the pull rate limit issues from DockerHub in the
CI.

The <DEFAULT_REGISTRY> contains a multi-architecture image (arm64 and
amd64)

    $ docker buildx imagetools inspect gracehopper3-oai.sboai.cs.eurecom.fr/ubuntu:noble | grep Platform
      Platform:  linux/amd64
      Platform:  linux/arm64

- The scripts run from the jenkins server everyday using a crontab.
- It pulls the AMD and ARM ubuntu:noble image on respective servers and
  checks if the internal registry is in sync.
- If not, it pushes the ubuntu:noble image to the registry to remain in
  sync with dockerhub.
2026-02-26 16:52:44 +01:00
Robert Schmidt
af19e6bce8 Fix dl_absoluteFrequencyPointA in config file
Analogously to other files under ci-scripts/.
2026-02-26 16:51:58 +01:00
Robert Schmidt
378d3a7a6b Add AnalyzeRTStatsObject() XML step 2026-02-26 14:17:28 +01:00
Robert Schmidt
c6bb50edb1 Add LogAnalysis in all XML files
I try to retain/match the previous log checks, without adding new
checks.
2026-02-26 14:17:28 +01:00
Robert Schmidt
5165834051 Introduce EndsWithBye log analysis check
It was initially foreseen to just check the program exit code, but most
executables don't return with 0 (so the CI would always fail). Add a
separate check that will check for the Bye., only going through the last
X lines instead of the entire file.
2026-02-26 14:17:28 +01:00
Robert Schmidt
735058f5c4 New log-analysis checker LastLineContains 2026-02-26 14:17:28 +01:00
Robert Schmidt
366df408a1 Default checker: check for assertions 2026-02-26 14:17:28 +01:00
Robert Schmidt
30a27432f0 Remove unused logging and unused imports 2026-02-26 14:17:28 +01:00
Robert Schmidt
707cb560d5 Implement retransmission checker, include unit test 2026-02-26 14:17:28 +01:00
Robert Schmidt
fe464ec6d0 Initial code for log analysis
- we agreed to basically throw away the old log checker (as it is
  unmaintainable)
- now: provide list of analysis to do
  * all checkers in cls_log_analysis, can be unit tested (see also next
    commit)
  * looked up dynamically to simplify adding of new tests + config
  * configured with

      <analysis>
        <services>DESCRIPTION [DESCRIPTION...]</services>
        <service>DESCRIPTION</service>
        ...
      </analysis>

    where DESCRIPTION follows service=func[=options]:
    - service is name of service to check
    - func is function to call, which receives filename
    - option are arbitary options to pass to func
    <services> is whitespace delimited (so can take multiple service
    analysis definitions)
    <service> exists to allow service definitions with whitespace
    changes that would not work in <services>
- I initially planned to check return code, but most softmodems actually
  exit with non-zero return code, so this is still TODO
- Default analyzer (checking for assertions, ...) is always run if a
  service is listed
- checks for file size
- add unit tests
2026-02-26 14:17:28 +01:00
Robert Schmidt
03f56c10e7 GetDeployedServices(): return container ID
will be relevant to get the return code in the next commit.
2026-02-26 13:39:39 +01:00
Robert Schmidt
2e85f67646 Remove air_interface: it's not used 2026-02-26 13:39:39 +01:00
Robert Schmidt
9e35799ca6 Remove X2HO eNBmbmsEnables variables
- it is spaghetti code: difficult to understand which code paths are
  taken
- the only effect seems to be in the UE log analysis function: it might
  make the log fail. However, we test that iperf is successful
  (Iperf2_Unidir()), and would detect before the log analysis if MBMS
  traffic does not work
- the rest is only messages that likely nobody reads

The real reason for this change is to reduce the number of class members
in the ran.py class, to simplify the functioning of the eNB analysis
function (no self) to reduce dependencies on the ran.py class.
2026-02-26 13:39:39 +01:00
Robert Schmidt
65dab3e027 Add unit test phytest analysis 2026-02-26 13:39:39 +01:00
Robert Schmidt
e809841aea Move Real-Time Stats Analysis to separate step
Factor out to make existing log analysis simpler. It will also allow to
more easily port this functionality to docker-based setups.
2026-02-26 13:39:39 +01:00
Robert Schmidt
41a6188c04 Change bash set options to improve run_locally.sh
set -e makes the script exit on error. However, there is code to handle
a non-zero return code of the script, and -e prevents from writing the
footer.

add set -x to see all the commands that are being executed.
2026-02-26 13:39:39 +01:00
Robert Schmidt
44ad255195 Remove unused USRP_IPAddress 2026-02-26 13:39:39 +01:00
Robert Schmidt
92997fba2b Update tests/README.md 2026-02-26 13:39:39 +01:00
Robert Schmidt
4a2f6cd823 Remove unused docker file 2026-02-26 13:39:39 +01:00
Robert Schmidt
84a49886d8 Move unused configs to untested 2026-02-26 13:39:39 +01:00
Robert Schmidt
cc1d663190 Remove unused code in args_parse.py 2026-02-26 13:39:39 +01:00
Robert Schmidt
7fe3183d1e Remove dead code 2026-02-26 13:39:39 +01:00
Robert Schmidt
0b219bf443 Fix invalid escape sequences
Use a raw string as suggested:

    ci-scripts/cls_static_code_analysis.py:93: SyntaxWarning: invalid escape sequence '\:'
      result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
    ci-scripts/cls_static_code_analysis.py:125: SyntaxWarning: invalid escape sequence '\.'
      ret = re.search('cppcheck version="(?P<version>[0-9\.]+)"', str(line))
    ci-scripts/cls_oai_html.py:221: SyntaxWarning: invalid escape sequence '\/'
      cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
    ci-scripts/ran.py:428: SyntaxWarning: "\[" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\["? A raw string is also an option.
      result = re.search('\[gNB [0-9]+\]\[RAPROC\] PUSCH with TC_RNTI 0x[0-9a-fA-F]+ received correctly, adding UE MAC Context RNTI 0x[0-9a-fA-F]+', str(line))
    ci-scripts/ran.py:457: SyntaxWarning: "\[" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\["? A raw string is also an option.
      result = re.search('\[PHY\]\s+problem receiving samples', str(line))
    ci-scripts/ran.py:461: SyntaxWarning: "\[" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\["? A raw string is also an option.
      result = re.search('\[MAC\]\s+Removing UE', str(line))
2026-02-26 13:39:39 +01:00
Robert Schmidt
3a9fdb674a Shorten logging output to time
I am not sure we ever need the millisecond output. The date is typically
also clear from the output (we could print the date at the beginning,
once, instead, but this is not done here. Finally, in Jenkins, we
typically get time stamps. Thus, it's not necessary to print this by
default.

On the other hand, since it might be useful when running locally, make
time stamps in logs configurable.
2026-02-26 13:39:39 +01:00
Robert Schmidt
e1b7e91f8a Use nocolor in various CI pipelines 2026-02-26 13:39:39 +01:00
Jaroslava Fiedlerova
a6bf72e895 Fix compilation
Fix compilation error:
/oai-ran/openair1/SIMULATION/NR_PHY/dlsim.c:932:42: error: variable 'h_channel_coeffs' set but not used [-Werror,-Wunused-but-set-variable]
  932 |                                   float *h_channel_coeffs = NULL;
      |                                          ^
2026-02-26 11:32:14 +00:00
Jaroslava Fiedlerova
c32d881be8 doc: Add instructions about dlsim/ulsim with cuda channel simulation 2026-02-26 11:32:14 +00:00
Jaroslava Fiedlerova
864d378a25 nr_ulsim: add -f option to support feature flags (e.g. CUDA)
- Introduce usage of the -f option in ulsim to allow enabling specific
  feature flags at runtime.
- Add support for the "cuda" flag to enable CUDA channel simulation when
  compiled with CUDA support. If an unsupported flag is provided, nr_ulsim
  reports an error.
2026-02-26 11:32:13 +00:00
Nika Ghaderi
afc52abb8a Integrate CUDA Channel Pipeline into UL Simulator
This commit integrates the GPU-based channel simulation pipeline into
the ulsim.

A `--cuda` command-line flag is added to enable the GPU path at
runtime. When activated, the simulator will:
- Allocate all necessary GPU and pinned host memory via the
  `init_cuda_chsim_buffers` helper function.
- In the main simulation loop, call the `run_channel_pipeline_cuda`
  function to perform the channel simulation on the GPU, bypassing the
  CPU-based functions.
- Clean up all CUDA resources on exit using the
  `free_cuda_chsim_buffers` helper.
The cpu path is also updated to use multipath_channel_float and add_noise_float.
2026-02-26 11:32:13 +00:00
Jaroslava Fiedlerova
de3dfee0c2 nr_dlsim: add -f feature flag support and remove unused SCG handling
- Replace previous handling of -f with a generic feature flag option.
- Add support for the "cuda" flag to enable CUDA channel simulation when
  compiled with ENABLE_CUDA.
- Remove unused SCGroupConfig file handling (scg_fd) and related code.
- Clean up deprecated code and variables associated with SCG reading - not
  required anymore after b232be94ed
2026-02-26 11:32:09 +00:00
Robert Schmidt
96a465c02b Merge remote-tracking branch 'origin/compil_improv' into integration_2026_w09 (!3953)
Improvements in compilation dependence

Once more I ended up in a long trip inside OAI intricate compilation
2026-02-26 11:01:24 +01:00
Robert Schmidt
10c26a79a5 Link log_headers to ldpc_aal to also force build of T headers 2026-02-26 11:00:37 +01:00
francescomani
e9cef10491 other small minor cleanup 2026-02-26 11:00:37 +01:00
francescomani
fd69dc0823 include license header in nr_prs.c 2026-02-26 11:00:37 +01:00
francescomani
a35c272e04 improvements in NR_REFSIG headers 2026-02-26 11:00:37 +01:00
francescomani
8c4fe047d0 remove some LTE dependence in NR files 2026-02-26 11:00:37 +01:00
francescomani
d6759b35d2 remove unnecessary gNB DLSCH header in UE dlsch demodulation 2026-02-26 11:00:37 +01:00
francescomani
96bc3a0ee9 remove unnecessary defs_gNB from LTE files 2026-02-26 11:00:37 +01:00
francescomani
4447d67650 remove unnecessary gNB header dependence in coding files 2026-02-26 11:00:37 +01:00
Robert Schmidt
4f7cd88e4c Merge remote-tracking branch 'origin/fixes-initial-context-setup' into integration_2026_w09 (!3952)
Fixes for Initial UE Context Setup

This MR fixes DRB aggregation from E1 so DRBs from multiple PDU sessions
are appended correctly into the F1 DRB array instead of overwriting
existing entries. It also makes NGAP Initial Context Setup skip PDU
sessions that are already established for the UE, only setting up new
sessions.

DRB aggregation from E1: Adjust fill_drb_to_be_setup_from_e1_resp to
pass &drbs[nb_drb] into fill_f1_drbs_from_e1, ensuring DRBs from later
PDU sessions are appended after the current count.

Duplicate PDU sessions in NGAP Initial Context Setup: In
rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ, detect requested PDU
session IDs that already exist with PDU_SESSION_STATUS_ESTABLISHED, log
a warning, and skip them so they are not added to UE->initial_pdus.
2026-02-26 10:59:54 +01:00
Robert Schmidt
433bd7be3f Merge remote-tracking branch 'origin/multi_gNB_sync' into integration_2026_w09 (!3892)
Synchronize multiple gNBs by aligning the slot boundaries

Currently, we derive frame and slot number based on proc->timestamp_rx
using

    proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
    proc->tti_rx = get_slot_from_timestamp(proc->timestamp_rx, fp);

This ignores the samples

    proc->timestamp_rx % fp->samples_per_frame

while computing the frame and slot number creating a mis-alignment with
the slot boundaries. A detailed description of the slot misalignment
in a pictorial representation can be seen in an attachment in the MR [1].

We fix this alignment issue by compensating these samples during the
first reception.

We can test the synchronization of the multiple gNBs from the estimated
ToAs from the PRS in the Downlink and the estimated ToAs from the SRS in
the Uplink using rfsim.

In order to test this, make sure you build gNB and nrUE along with the
telnetsrv flag using the option --build-lib telnetsrv.

Also, enable the following log in the function
nr_est_srs_timing_advance_offset() in
openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c to observe SRS ToAs

    LOG_I(NR_PHY, "SRS estimatd ToA %d [RX ant %d]: TA offset %d, TA offset ns %d (max_val %ld, mean_val %ld, max_idx %d)\n", srs_toa, ant, *ta_offset, *ta_offset_nsec, max_val, mean_val, max_idx);

Furthermore, update the option Active_gNBs = 2; in
targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf to enable
decoding PRS transmitted from two gNBs

To run:

nrUE:

    sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --uicc0.imsi 001010000000001 --rfsim --phy-test -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.nr.prs.fr1.106prb.conf --rfsimulator.serveraddr server

gNB 0:

    sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb0.prs.band78.fr1.106PRB.usrpx310.conf --gNBs.[0].min_rxtxtime 6 --rfsim --phy-test --rfsimulator.[0].serveraddr 127.0.0.1 --rfsimulator.[0].options chanmod --rfsimulator.[0].modelname AWGN --telnetsrv

gNB 1:

    sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb1.prs.band78.fr1.106PRB.usrpx310.conf --gNBs.[0].min_rxtxtime 6 --rfsim --phy-test --rfsimulator.[0].serveraddr 127.0.0.1 --rfsimulator.[0].options chanmod --rfsimulator.[0].modelname AWGN --telnetsrv

When we run the nrUE, gNB0 and gNB1, we can see the following logs

nrUE:

    [PHY] [gNB 0][rsc 0][Rx 0][sfn 976][slot 2] DL PRS ToA ==> 0.0 / 2048 samples, peak channel power -16.4 dBm, SNR +4.0 dB, rsrp -42.2 dBm
    [PHY] [gNB 1][rsc 0][Rx 0][sfn 976][slot 3] DL PRS ToA ==> 0.0 / 2048 samples, peak channel power -16.4 dBm, SNR +4.0 dB, rsrp -42.2 dBm

gNB 0:

    [NR_PHY] SRS estimatd ToA 0 [RX ant 0]: TA offset 31, TA offset ns 0 (max_val 99820162, mean_val 80176, max_idx 0)

gNB 1:

    [NR_PHY] SRS estimatd ToA 0 [RX ant 0]: TA offset 31, TA offset ns 0 (max_val 98784562, mean_val 79369, max_idx 0)

From the above logs, when we run the rfsim and when no delays introduced, we can observe the following results

In the Downlink at the UE, the estimated ToAs using PRS from both gNB0
and gNB1 are 0 and in the uplink, the ToA estimated from the SRS
transmitted by the UE at both the gNBs are also 0. This indicates that
both the gNBs are synchronized along with their slot boundaries. We also
highlight that this is not the case in the current develop branch since
the slot boundaries are not aligned.

We also can test the multi gNB synchronization by introducing delays
using telnet as follows,

Introduce new_offset (delay) of 4 samples to the gNB 0 from UE in the
uplink as follows,

    openairinterface5g$ echo rfsimu setdistance rfsimu_channel_enB0 20 | ncat --idle 1 127.0.0.80 9080
    softmodem_gnb> rfsimu_setdistance_cmd: new_offset 4, new (exact) distance 19.518 m, new delay 0.000065 ms
    Ncat: Idle timeout expired (1000 ms).

We can oberve this delay of 4 samples being reflected in the estimated
SRS ToAs at gNB 0 while not changing the ToA in gNB 1

    [NR_PHY] SRS estimatd ToA 4 [RX ant 0]: TA offset 31, TA offset ns 65 (max_val 98803636, mean_val 79430, max_idx 8)

similarly, Introduce new_offset (delay) of 2 samples to the gNB 1 from
UE in the uplink as follows,

    openairinterface5g$ echo rfsimu setdistance rfsimu_channel_enB0 10 | ncat --idle 1 127.0.0.81 9081
    softmodem_gnb> rfsimu_setdistance_cmd: new_offset 2, new (exact) distance 9.759 m, new delay 0.000033 ms
    Ncat: Idle timeout expired (1000 ms).

We can oberve this delay of 2 samples being reflected in the estimated
SRS ToAs at gNB 1 while not changing the ToA in gNB 0

    [NR_PHY] SRS estimatd ToA 2 [RX ant 0]: TA offset 31, TA offset ns 32 (max_val 98962768, mean_val 79552, max_idx 4)

Closes #897

[1] https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/3892
2026-02-26 08:42:47 +01:00
Robert Schmidt
6715464b3a Merge remote-tracking branch 'origin/band_number_improv' into integration_2026_w09 (!3943)
Remove L1 dependence from NR band number

L1 band information relied on get_band function that couldn't provide an
unambiguous result. Also there is no SCF compliant parameter for L1 and
generally we don't really need that information in L1.

The MR also remove a RU section that used nr_band but was never really
accessed in NR.
2026-02-26 08:42:16 +01:00
Robert Schmidt
d81bda5760 Merge remote-tracking branch 'origin/NR_more_than_4_antennas' into integration_2026_w09 (!3871)
Support for up to 12 ports in NR gNB
2026-02-26 08:41:16 +01:00
Robert Schmidt
d3f851127e Merge remote-tracking branch 'origin/fix_config_request_beta_pss_tlv' into integration_2026_w09 (!3947)
Add missing packing for CONFIG.request parameter BetaPSS

Adds the packing procedure for the parameter BetaPSS, as well as adding this
parameter to the utility functions where it is missing
2026-02-26 08:40:49 +01:00
Robert Schmidt
6dc7c4fe60 Merge remote-tracking branch 'mahmoudb/telnet-IPV6-support' into integration_2026_w09 (!3940)
IPV6 support for telnet socket binding

Now, the listening telnet socket is only bound to the dedicated interface IPs in
config file, both for V4 and V6

Closes #834
2026-02-26 08:40:19 +01:00
Jaroslava Fiedlerova
cde53141be Merge remote-tracking branch 'origin/fix-handling-ipv4v6-pdu-sess' into integration_2026_w09 (!3951)
Fix handling of IPv4v6 PDU sessions

The code previously checked that the supplied PDU sessions's type is
exactly what we requested. However, at least OAI 5GC will only give us
an IPv4 PDU session if we request IPv4v6 (so the check would fail).

Extend the validation to either check exact match, or, if IPv4v6
requested, that it is either IPv4 or IPv6.
2026-02-25 18:50:33 +01:00
francescomani
2bd3685d6b add check for input number of antennas to be compliant with NB_ANTENNAS_TX and NB_ANTENNAS_RX 2026-02-25 16:26:21 +01:00
Robert Schmidt
cdfe069c34 Remove unused cmake macros 2026-02-25 16:26:21 +01:00
Robert Schmidt
bb72c4d057 Fix alignment problem in nr_dlsim
Fix error

    openair1/SIMULATION/NR_PHY/dlsim.c:1057:37: runtime error: member access within misaligned address 0x7f8a67e01010 for type 'struct NR_Sched_Rsp_t', which requires 32 byte alignment
2026-02-25 16:26:21 +01:00
Robert Schmidt
1b619bed03 Remove unused sched_response_id 2026-02-25 16:26:21 +01:00
Robert Schmidt
5b9d4550ba Remove unused defines 2026-02-25 16:26:21 +01:00
Robert Schmidt
0ea119ec39 Align t_nrPolar_params allocation to 32 bytes 2026-02-25 16:26:21 +01:00
Robert Schmidt
448f273248 Write NB_ANTENNAS_RX/TX to header file and use in stack
Prior to this commit, constants NB_ANTENNAS_RX/TX are provided on the
command line to each compiler invocation. This has the drawback (1) that
also files that don't need that get the constants, and (2) it is not
easy to find them using ctags or similar, as the only definition is in
CMakeLists.txt (where it is not found).

In this commit, use cmake configure_file() to write a header file with
these constants. The file will be generated during cmake invocation, and
written to <build-dir>/common/cmake_defs.h. The relevant files that
need this definition will pick it from the header.

This has been used previously also in a commit to write git information.

See-also: 8bffd1666d ("Avoid complete rebuild on cmake run with git info change")
2026-02-25 16:26:21 +01:00
francescomani
0a79dce24b configuration of PUCCH2 PRB number depending on antenna ports 2026-02-25 16:26:07 +01:00
Behrad Mahmoudi
7f8e0b2cd5 Now, the listening telnet socket is only bound to the dedicated interface IPs in config file, both for V4 and V6 2026-02-25 14:53:32 +01:00
francescomani
862f84bb68 remove band from frame parameters and get_band function not used anymore 2026-02-25 14:32:03 +01:00
francescomani
3c2853e1c0 remove RU functios gated by has_ctrl_prt parameter never set in NR code 2026-02-25 14:32:03 +01:00
francescomani
8180a5db03 remove L1 nr_band dependence in frame parameters 2026-02-25 14:31:58 +01:00
Jaroslava Fiedlerova
68ecf9f860 Merge remote-tracking branch 'origin/aerial-targets-config' into integration_2026_w09 (!3897)
Change Aerial config file in targets to match Nvidia's CI setup and modify tutorial
2026-02-25 14:12:13 +01:00
francescomani
5ed309166b use FAPI field to set SSB case from upper layers 2026-02-25 12:43:10 +01:00
Rúben Soares Silva
f66a7b2108 Add SSB Case V3 vendor extension TLV to CONFIG.request pack/unpack and to utility functions 2026-02-25 12:43:10 +01:00
Robert Schmidt
0219e4d3c7 Remove band number from openair0_config_t 2026-02-25 12:43:10 +01:00
francescomani
530b692208 simplified version of to_nrarfcn function to remove not necessary checks for band consistency 2026-02-25 12:43:07 +01:00
Guido Casati
3f4b72df67 Handle duplicate PDU sessions in NGAP InitialContextSetup
Ensure the CU-CP only sets up PDU sessions that are not already
established for the UE, skipping duplicates while keeping the NG UE
context valid. This aligns with 3GPP TS 38.413 PDU Session setup
semantics for duplicate session IDs

Changes:
- Change rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ to scan requested
  PDU sessions and detect IDs that already exist in UE->pduSessions with
  PDU_SESSION_STATUS_ESTABLISHED
- Log a warning and skip already established PDU session IDs so they are
  not added to UE->initial_pdus
- Collect only non-established PDU sessions into a temporary stack array,
  allocate UE->initial_pdus with the exact count, copy them in, update
  UE->n_initial_pdu, and only refresh UE AMBR when there is at least one
  session to set up
2026-02-25 09:50:27 +01:00
Rakesh Mundlamuri
af438ef5e5 Handover doc: mention ssb_PositionsInBurst_Bitmap config 2026-02-25 08:58:33 +01:00
Robert Schmidt
4e9a853696 Fix ssb_PositionsInBurst_Bitmap to work with slot-synchronization
Since the grand-parent commit, if possible, the gNBs synchronize on a
slot-level boundary. Some configuration files/command line overrides
left the same SSB position for two DUs in RFsim-based handover
scenarios, which then makes that the UE cannot decode the SSB.

This commit changes the positions such that this is possible again. In
the F1 HO docker-compose
(ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml), we set it
to 2 to send only one SSB (not 2 with bitmap 3).
2026-02-25 07:58:57 +01:00
Guido Casati
dae251ddcb Fix DRB array offset when aggregating E1 DRBs
Ensure DRBs from multiple PDU sessions are appended into the F1 DRB array
without overwriting previously filled entries.

Update fill_drb_to_be_setup_from_e1_resp to call fill_f1_drbs_from_e1
with &drbs[nb_drb] so each PDU session’s DRBs are written after the
current count
2026-02-24 12:55:24 +01:00
Jaroslava Fiedlerova
800b238492 Merge remote-tracking branch 'origin/fix-ueconf-nssaisd' into integration_2026_w09 (!3949)
fix: removed the nssai_sd parameter in the ue.conf file

Following the tutorial in the RF simulator, the PDU session cannot
be established because the  Slice Differentiator to request(nssai_sd)
parameter in the ue.conf file is 1(integer) but in the documentation
the default value of the nssai_sd is 0xFFFFF(meaning "no SD")

Now the nssai_sd parameter is removed in the ue.conf to establish the
PDU session.
2026-02-24 10:44:56 +01:00
Jaroslava Fiedlerova
71041877fd Merge remote-tracking branch 'origin/nrue_write_timestamp_fix' into integration_2026_w09 (!3928)
NR UE: correctly compute writeTimestamp for SCS > 30 kHz with rf-simulator

Contains also two minor cleanups for nr-ue.c:
- make fp point to constant NR_DL_FRAME_PARMS where possible
- use c16_t type for I/Q sample arrays
2026-02-24 10:43:58 +01:00
Jaroslava Fiedlerova
b8ac4869c5 Merge remote-tracking branch 'origin/fix-rsrp-range' into integration_2026_w09 (!3874)
print better message for rsrp: invalid doesn't mean it is not measured

print better message for rsrp: invalid doesn't mean it is not measured,
it means it is out of usable range
2026-02-24 10:40:55 +01:00
Jaroslava Fiedlerova
a628cd9602 Merge remote-tracking branch 'origin/fix-ue-ho-msg1fdm' into integration_2026_w09 (!3822)
NR UE: fix PRACH k1 calculation at MAC when handover

The k1 for PRACH calculation in config_common_ue() should be the same as in
config_common_ue_sa(), otherwise k1 is wrong when handover to target cell if
msg1-FDM not 0 in reconfigurationWithSync.

Verified with 3rd-party gNB.
2026-02-24 10:39:51 +01:00
Robert Schmidt
933984fab1 Fix handling of IPv4v6 PDU sessions
The code previously checked that the supplied PDU sessions's type is
exactly what we requested. However, at least OAI 5GC will only give us
an IPv4 PDU session if we request IPv4v6 (so the check would fail).

Extend the validation to either check exact match, or, if IPv4v6
requested, that it is either IPv4 or IPv6.
2026-02-24 08:37:36 +01:00
Robert Schmidt
90bf723eae nr-uesoftmodem: end with Bye.
Similarly to gNB, eNB, lteUE, end with a "Bye." that the CI (will) check
for.

The right way to do this would be to use the exit code, but most
executables do not actually end with 0, such that we need to check for
this. Thus, this commit is only to harmonize with other executables.
2026-02-24 08:24:02 +01:00
aswanthkc
ac9232d6fc fix: updated the nssai_sd paramter in the ue.conf file
Following the tutorial in the RF simulator, the PDU session cannot
be established because the  Slice Differentiator to request(nssai_sd)
parameter in the ue.conf file is 1(integer) but in the documentation
the default value of the nssai_sd is 0xFFFFF(meaning "no SD")

Now the nssai_sd parameter is removed in the ue.conf to establish the
PDU session.
2026-02-23 10:36:52 -05:00
Shubhika Garg
0a9c3a07eb ci: Pull ubuntu:noble image from our internal docker registry to build ubuntu images
- This is to overcome the issue of pull rate limits from DockerHub
        - Make Ubuntu base image configurable via build-arg
2026-02-23 16:34:06 +01:00
Nika Ghaderi
5fb9a9c665 Integrate CUDA Channel Pipeline into DL Simulator
This commit integrates the CUDA-based channel simulation pipeline into
the nr_dlsim.

A new `--cuda` command-line flag is added to enable the GPU path at
runtime. When activated, the simulator will:
- Allocate all necessary GPU and pinned host memory via the new
  `init_cuda_chsim_buffers` helper function.
- In the main simulation loop, call the `run_channel_pipeline_cuda`
  function to perform the channel simulation on the GPU, bypassing the
  CPU-based functions.
- Clean up all CUDA resources on exit using the
  `free_cuda_chsim_buffers` helper.
Additionally, dlsim is now using the float version of channel_multipath and add_noise functions.
Also, The input data is formatted as interleaved IQ, with separate antennas to ensure a fair comparison with the GPU operation.
2026-02-23 13:14:26 +00:00
Laurent THOMAS
59aed14153 print better message for rsrp: invalid doesn't mean it is not measures, it means it is out of usable range 2026-02-23 13:00:09 +01:00
Laurent THOMAS
66efe92551 separate report list from each report as a table of struct instead of a struct of tables 2026-02-23 13:00:09 +01:00
Jaroslava Fiedlerova
b5634c6615 Merge remote-tracking branch 'origin/NR_fix_ndi_reset' into integration_2026_w09 (!3945)
gNB: Reset NDI only after usage in case of disable HARQ

Solves this warnings seen in the UE trace:
NDI indicates re-transmission but computed TBS 3968 doesn't match with what previously stored 3368

Issue happens only if feature disable_harq is enabled. GNB resets the harq
process (including NDI) as PUCCH will not be sent for this harq process, but
before the harq process is used in DCI payload preparation.

Fix is to reset the harq process after harq process in case of no PUCCH.
2026-02-23 10:19:53 +01:00
Jaroslava Fiedlerova
10ac7a2711 Merge remote-tracking branch 'origin/fail-early-no-config' into integration_2026_w09 (!3944)
Fail early if configuration module can not initialize properly

In the case that the config module cannot load the driver for libconfig or yaml,
currently, there might be a cascade of errors that are difficult for users to
understand. For instance (partially redacted for clarity):

[CONFIG] Error calling dlopen(libparams_libconfig.so): libparams_libconfig.so: cannot open shared object file: No such file or directory
[CONFIG] config module "libconfig" couldn't be loaded
[CONFIG] config_get, section log_config skipped, config module not properly initialized
[LOG] init aborted, configuration couldn't be performed
[CONFIG] config_get, section (null) skipped, config module not properly initialized
[CONFIG] /home/francesco/openairinterface5g/common/config/config_userapi.c 68 nfapi has no processed integer availablle
[CONFIG] config_get, section (null) skipped, config module not properly initialized

Assertion (get_softmodem_params()->default_pdu_session_id == -1) failed!
In get_common_options() /home/francesco/openairinterface5g/executables/softmodem-common.c:161
Use uicc0.pdu_sessions.[0].id to change the requested PDU session ID (is 0)

Here, the error is the missing shared object, but a user is more likely to look
at the last error instead of the first.

This commit addresses it by checking early for CONFIG_ISFLAGSET(CONFIG_ABORT),
and stopping if it is set. Additionally changes include making functions static,
removing late CONFIG_ISFLAGSET() checks, and the CONFIG_ISFLAGSET() in
load_configmodule(), because at that time "uniqCfg" is not set yet and thus does
not do anything (this is likely a regression of an earlier cleanup).

See-also: f50d5f5a ("make multiple config instead of one implicit global")
2026-02-23 10:17:01 +01:00
Rúben Soares Silva
46d4659706 Add missing packing for CONFIG.request parameter BetaPSS
Adds the packing procedure for the parameter BetaPSS, as well as adding this parameter to the utility functions where it is missing
2026-02-20 13:29:57 +00:00
francescomani
db2bcf0eee preventing include of log.h in nr_common.h by moving function in nr_common.c 2026-02-20 11:05:43 +01:00
francescomani
7a59f28ae3 RRC CSI-RS config for 8 and 12 ports 2026-02-20 11:05:43 +01:00
francescomani
b53f4a6e37 using constants for FAPI precoding weigths instead of hardcoded values 2026-02-20 11:05:43 +01:00
Thomas Schlichter
f7265977ad NR UE: when compensating for large timing_advance changes, set writeBlockSize to 0 instead of 1 2026-02-20 09:59:54 +01:00
Thomas Schlichter
ba0ead6809 NR UE: correctly compute the writeBlockSize in readFrame() and the writeTimestamp in syncInFrame() 2026-02-20 09:59:54 +01:00
Thomas Schlichter
09b3fc03c7 NR UE: make RX and TX pointer arrays of type c16_t instead of void in nr-ue.c 2026-02-20 09:52:42 +01:00
Thomas Schlichter
1707aafc2c NR UE: make fp pointer to a _constant_ NR_DL_FRAME_PARMS in nr-ue.c 2026-02-20 09:52:42 +01:00
Rakesh Mundlamuri
5e0e359dd6 Update PRS configuration files to test multi gNB synchronization 2026-02-20 13:27:26 +05:30
Rakesh Mundlamuri
b1f32ea049 Synchronize multiple gNBs by aliging to the slot boundary
Currently, we derive frame and slot number based on `proc->timestamp_rx`
using
`proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;` and
`proc->tti_rx = get_slot_from_timestamp(proc->timestamp_rx, fp);`

This ignores the samples `proc->timestamp_rx % fp->samples_per_frame`
while computing the frame and slot number creating a mis-alignment with the slot boundaries.
We fix this alignment by compensating these samples during the first reception.
2026-02-20 13:27:26 +05:30
Robert Schmidt
520360a629 Merge branch 'integration_2026_w08' into 'develop'
Integration: `2026.w08`

* !3934 Fix Ubuntu build: reinstate -Werror
* !3803 remove cblas and atlas dependancy
* !3918 Add a simple GTP unit test
* !3924 T: macpdu2wireshark: gentle exit (and some other minor work in the T tracer)
* !3925 Fix race condition on double RA during RRC reestablishment
* !3930 bugfix: add PCell to serving_cells in fallback path and refactor update logic
* !3936 [FHI72] Remove support for xran E release
* !3893 NR Paging on CU

See merge request oai/openairinterface5g!3939
2026-02-20 06:46:39 +00:00
Raghavendra Dinavahi
e129fd0ede GNB: RESET NDI only after usage in case of disable HARQ
solves this warnings seen in the trace
NDI indicates re-transmission but computed TBS 3968 doesn't match with what previously stored 3368
2026-02-19 19:37:54 +01:00
Robert Schmidt
82315ead3e Fail early if configuration module can not initialize properly
In the case that the config module cannot load the driver for libconfig
or yaml, currently, there might be a cascade of errors that are
difficult for users to understand. For instance (partially redacted for
clarity):

    [CONFIG] Error calling dlopen(libparams_libconfig.so): libparams_libconfig.so: cannot open shared object file: No such file or directory
    [CONFIG] config module "libconfig" couldn't be loaded
    [CONFIG] config_get, section log_config skipped, config module not properly initialized
    [LOG] init aborted, configuration couldn't be performed
    [CONFIG] config_get, section (null) skipped, config module not properly initialized
    [CONFIG] /home/francesco/openairinterface5g/common/config/config_userapi.c 68 nfapi has no processed integer availablle
    [CONFIG] config_get, section (null) skipped, config module not properly initialized

    Assertion (get_softmodem_params()->default_pdu_session_id == -1) failed!
    In get_common_options() /home/francesco/openairinterface5g/executables/softmodem-common.c:161
    Use uicc0.pdu_sessions.[0].id to change the requested PDU session ID (is 0)

Here, the error is the missing shared object, but a user is more likely
to look at the last error instead of the first.

This commit addresses it by checking early for
CONFIG_ISFLAGSET(CONFIG_ABORT), and stopping if it is set. Additionally
changes include making functions static, removing late
CONFIG_ISFLAGSET() checks, and the CONFIG_ISFLAGSET() in
load_configmodule(), because at that time "uniqCfg" is not set yet and
thus does not do anything (this is likely a regression of an earlier
cleanup).

See-also: f50d5f5a9b ("make multiple config instead of one implicit
  global")
2026-02-19 17:06:29 +01:00
Robert Schmidt
90c6bbce65 Merge remote-tracking branch 'origin/nr-paging-cu' into integration_2026_w08 (!3893)
NR Paging on CU

Implements the NR paging path on the CU:

- NGAP Paging is decoded and passed to RRC
- RRC builds F1AP Paging, and distributes it to DUs via F1 callback

Changes:

- Refactor and extend F1AP Paging encode/decode libraries
  * add missing enc/dec/eq/cp functions
  * add unit test
  * IEs: CN UE 5G-S-TMSI, RAN UE I-RNTI; optional DRX/priority/origin)
- Refactor CU callback CU_send_Paging
- Refactor DU handler DU_handle_Paging
- Refactor old F1 callback for Paging indication, extend it and align
  with existing F1 callbacks in stack
- Refactor and extend NGAP Paging encode/decode lib
  * add missing enc/dec/eq/cp functions
  * add unit test
  * Fixes NGAP paging to accept Paging only on SCTP stream 0 per TS
    38.412
- Includes supporting refactors (PDU session split, shared 5G-S-TMSI
  helpers, NGAP/F1AP cleanups)

Testing

- NGAP and F1AP Paging lib unit tests (enc/dec)
- Stream-0 fix validated with Open5GS AMF

This MR does not address the DU changes besides the F1 handler. F1AP
Paging does not have an RRC container to pass the PCCH message to the
DU, and F1 DL RRC Message Transfer does not apply to PCCH. PCCH-Message
shall be built at DU per TS 38.331 §5.3.2, with padding as per §8.5 and
delivered as RLC SDU per §8.2. For each cell in Paging Cell List that
belongs to this DU, queue for MAC. MAC schedules at PF/PO per TS 38.304
§7.

Refs:

- F1AP 3GPP TS 38.473 version 16.21.0 Release 16
- NGAP 3GPP TS 38.413 version 16.17.0 Release 16
2026-02-18 16:06:09 +01:00
Jaroslava Fiedlerova
e2f20eea8a Merge remote-tracking branch 'origin/remove-xran-e' into integration_2026_w08 (!3936)
[FHI72] Remove support for xran E release

All the use cases we tested with E release are working end-to-end with F release.
The near future plan is to support K release which is ongoing in the MR !3444.
2026-02-18 15:03:58 +01:00
Robert Schmidt
2b7f3e2f72 Merge remote-tracking branch 'origin/rrc-fix-rrcsetup-fallback' into integration_2026_w08 (!3930)
bugfix: add PCell to serving_cells in fallback path and refactor update logic

Fix assertion failure in rrc_gNB_send_NGAP_NAS_FIRST_REQ() when RRC
Reestablishment falls back to RRC Setup. The fallback path was not
adding the PCell to the UE's serving_cells array, causing
rrc_get_pcell_for_ue() to return NULL.

Major changes:

- Add rrc_update_ue_pcell() helper function that handles PCell updates
  for both new UEs (fallback) and existing UEs (normal reestablishment)
- Refactor normal reestablishment path to use rrc_update_ue_pcell()
  helper instead of manual cleanup + add sequence
- Add PCell update to fallback_rrc_setup path using the same helper
- Move C-RNTI validation after current_cell fetch to ensure current_cell
  is initialized before fallback_rrc_setup label
- Change error handling: return instead of fallback when PCell add fails
  in normal reestablishment path

Fixes CI failure in !3908
2026-02-18 10:44:38 +01:00
Teodora
5a339d66f2 Use the same pattern for checking the existance of F_RELEASE definition
In general, `#ifdef` and `#if defined` are the same.

Note: `#elif` is not the same as `#elif defined`.
2026-02-18 09:46:27 +01:00
Teodora
c68068f144 Remove support for xran E release
All the use cases we tested so far, are supported with xran F release.
Therefore, we can proceed with removing the support with E release.

In addition, our plan is to bring the support for K release which is ongoing activity in
the MR https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/3444.
2026-02-18 09:44:08 +01:00
Robert Schmidt
3520eb3c0d Merge remote-tracking branch 'origin/rrc-race-condition' into integration_2026_w08 (!3925)
Fix race condition on double RA during RRC reestablishment

Sometimes, especially in poor channel conditions, a UE can trigger
multiple RA procedures during RRC reestablishment, causing
reconfigCellGroup to be overwritten with a CellGroup that already has
spCellConfig removed, leading to an assertion failure in
update_cellgroup_for_reestablishment(). See logs below

    [NR_MAC]  456.13 UE 991d: Received Ack of Msg4. CBRA procedure succeeded (UE Connected)
    [NR_MAC] Adding new UE context with RNTI 0x991d
    [NR_PHY] [RAPROC] 461.9 Initiating RA procedure with preamble 8, energy 48.0 dB (I0 274, thres 130), delay 21 start symbol 2 freq index 0
    [NR_MAC] 461.9 UE RA-RNTI 0081 TC-RNTI ecd8: initiating RA procedure
    [NR_MAC] UE ecd8: Sync beam index 0
    [NR_MAC] UE ecd8: Msg3 scheduled at 462.3 (461.18 TDA 2) start 0 RBs 8
    [NR_MAC] UE ecd8: 461.18 Generating RA-Msg2 DCI, RA RNTI 0x81, state 1, preamble_index(RAPID) 8, timing_offset = 21 (estimated distance 820.3 [m])
    [NR_MAC]  462. 3 PUSCH with TC_RNTI 0xecd8 received correctly
    [NR_MAC] Received a MAC CE for C-RNTI with 991d
    [NR_MAC] Remove NR rnti 0xecd8
    [NR_MAC]  462. 3 RA with C-RNTI 991d complete
    [NR_PHY] [RAPROC] 471.19 Initiating RA procedure with preamble 6, energy 51.0 dB (I0 276, thres 130), delay 21 start symbol 2 freq index 0
    [NR_MAC] 471.19 UE RA-RNTI 010d TC-RNTI 022d: initiating RA procedure
    [NR_MAC] UE 022d: Sync beam index 0
    [NR_MAC] UE 022d: Msg3 scheduled at 472.13 (472.8 TDA 2) start 0 RBs 8
    [NR_MAC] UE 022d: 472.8 Generating RA-Msg2 DCI, RA RNTI 0x10d, state 1, preamble_index(RAPID) 6, timing_offset = 21 (estimated distance 820.3 [m])
    [NR_MAC]  472.13 PUSCH with TC_RNTI 0x022d received correctly
    [NR_MAC] Received a MAC CE for C-RNTI with 991d
    [NR_MAC] Remove NR rnti 0x022d
    [NR_MAC]  472.13 RA with C-RNTI 991d complete
    [NR_RRC] [UL] (cellID 1, UE ID 1 RNTI 991d) Received RRCReestablishmentComplete
    [NR_RRC] UE 1 Processing NR_RRCReestablishmentComplete from UE
    [NR_MAC] UE 991d: gNB-DU Configuration Query received, will include CellGroupConfig in response

    Assertion (new_CellGroup->spCellConfig) failed!
    In update_cellgroup_for_reestablishment() /phy/openairinterface5g/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:666

This MR solves it by skipping the reconfigCellGroup overwrite when it
already holds a valid config with spCellConfig, and by replacing the
fatal assertion on missing spCellConfig with an early return.
2026-02-17 18:16:27 +01:00
Robert Schmidt
a264937825 Merge remote-tracking branch 'origin/T-macpdu-fix' into integration_2026_w08 (!3924)
T: macpdu2wireshark: gentle exit (and some other minor work in the T tracer)

When outputting to a file, typing ctrl+c exits the program without
calling fclose(), leading to loss of traces in the output file.

Let's intercept ctrl+c and exit gently, calling fclose().

Also include a small fix for compilation of _check_vcd, some work on
extract and hacks/plot-ofdm, minor stuff.
2026-02-17 18:10:59 +01:00
Robert Schmidt
8abb535481 Merge remote-tracking branch 'origin/gtp-unit-test' into integration_2026_w08 (!3918)
Add a simple GTP unit test

Add a simple unit test for GTP that as of now tests the main
functionality, i.e., for a single UE, set up a bearer between two
endpoints and checking that traffic sending works. This is a start to
extend it further, e.g., with API changes, extensions to support new
functionality such as IPv6, and refactorings.

A number of supporting cleanup has been done as well.
2026-02-17 18:10:04 +01:00
Robert Schmidt
3671a47a7d Merge remote-tracking branch 'origin/remove-blas-atlas-dep' into integration_2026_w08 (!3803)
remove cblas and atlas dependancy

With new Fedora, we have again the cblas.h place not working

cblas+atlas dependancy is annoying for years

i start this MR to remove this dependancy

first commit: only cleaning: remove dead code, make static functions,
simplify code

after this commit, we see we use blas only in: conjugate_transpose()
that is a quite trivial function H_hermH_plus_sigma2I() a bit more
complex, but still possible to recode mutl_matrix_matrix_col_based() i
think we have the same elsewhere in OAI

atlas is used only in: lin_eq_solver() in don't know if replacement is
hard

We can observe all is related to MMSE, that is also coded in OAI 5G, so
maybe the solution is to use 5G code in 4G

Since nothing seems to be used, we can remove it.
2026-02-17 18:09:09 +01:00
alexjiao
9e7822cf1c NR UE: fix PRACH k1 calculation at MAC when handover
The k1 for PRACH calculation in config_common_ue() should be the same as in config_common_ue_sa(),
otherwise k1 is wrong when handover to target cell if msg1-FDM not 0 in reconfigurationWithSync.
2026-02-17 17:46:18 +01:00
Robert Schmidt
2a925d6cd4 GTP: add second test for tunnels without QFI 2026-02-17 13:56:07 +01:00
Robert Schmidt
d6c7321077 Implement removal of endpoint
For unit testing, allow to remove endpoints such that we could reuse a
port/IP combination.

The function does not take care of endpoints that are still "dangling",
it is the user's responsibility to remove all existing TEIDs.
2026-02-17 13:52:32 +01:00
Robert Schmidt
d290850e59 Add basic GTP unit test
Add a simple unit test that tests sending unidirectional traffic. So
far, it merely replicates what is already in nr-cuup-load-test, but it's
a single executable (so easier to handle), and could be more easily
extended to further tests (e.g., IPv6).

A couple of ideas for refactoring/improvements have been added in
comments in the test.
2026-02-17 13:52:32 +01:00
Guido Casati
df11c946f9 Paging (NGAP): fix stream handling to comply with TS 38.412
Paging messages are classified as non-UE-associated signalling per
3GPP TS 38.412 clause 7 (TL), which requires them to be sent on
stream 0 (or a reserved stream pair).

Paging message is received when UE is in RRC_IDLE or RRC_INACTIVE
state, as the RAN has no active UE context and paging targets the
UE by 5G-S-TMSI rather than RAN-UE-NGAP-ID.

The previous implementation incorrectly rejected paging messages
received on stream 0, causing paging failures when using Open5GS AMF.

Changes:
- Accept paging on stream 0 (non-UE-associated signalling)
- Reject paging on non-zero streams (UE-associated streams)
- Add documentation
2026-02-17 12:25:58 +01:00
Guido Casati
8209dcb5d9 Paging (RRC): refactor NGAP Paging handler in CUCP
RRC now builds F1AP paging messages directly by calling F1AP/direct
callbacks and aligning the CU/DU intergace with the F1AP design in the CU.
Messages are forwarded based on TAI-based cell matching across DUs.

- Remove F1AP_PAGING_IND message def and f1ap_paging_ind_t.
  RRC no longer sends ITTI F1AP_PAGING_IND; it builds f1ap_paging_t
  and passes it to the DU path.

- rrc_gNB_process_PAGING_IND: new signature (rrc, instance, msg)
  with const where appropriate; call in rrc_gnb_task() updated.

- NGAP handler logic: For each TAI, match (PLMN + TAC) to
  rrc->configuration; collect matching TAIs. Build one f1ap_paging_t
  (5G-S-TMSI via nr_construct_5g_s_tmsi(), identity type
  F1AP_PAGING_IDENTITY_CN_UE, optional drx/priority/origin copied
  from ngap_paging_ind_t), call rrc_send_paging_to_dus(), then
  free_f1ap_paging(). Remove the previous AssertFatal stub, CC loop,
  NODE_IS_CU branch, and UE lookup logic: it is now handled by
  F1AP/direct CU callbacks.

- rrc_gNB_du: Add rrc_send_paging_to_dus(rrc, tais, n_tai, msg).
  Iterate DUs with RB_FOREACH; for each DU, fill msg->cells from
  du->cells whose (PLMN + TAC) matches any requested TAI, set
  n_cells, then call rrc->mac_rrc.paging_transfer(du->assoc_id,
  msg). Skip DUs with no matching cells. Prevents duplicate paging
  when multiple TAIs map to the same PLMN.
2026-02-17 12:25:58 +01:00
Guido Casati
6022ac8bf1 Paging (F1AP): wire paging through mac_rrc_dl and use F1AP free/decoding lib on CU/DU
Introduce paging_transfer in the mac_rrc_dl interface so the CU can pass
paging to the DU (F1 or direct). Use the F1AP paging lib on both CU and DU
for decode/free and to avoid leaking the message after send.

- Add f1_paging_transfer_func_t and paging_transfer to nr_mac_rrc_dl_if_s
  (mac_rrc_dl.h, nr_rrc_defs.h).
- F1AP path: paging_f1ap() allocates F1AP_PAGING, copies with cp_f1ap_paging(),
  sends via ITTI to TASK_CU_F1. Direct path: f1_paging_transfer_direct() stub
- CU task: call free_f1ap_paging() after CU_send_Paging() to release the message.
- DU: DU_handle_Paging() uses decode_f1ap_paging()/free_f1ap_paging() from lib,
  returns on decode failure; remove inline ASN.1 IE parsing.
- cleanup outdated header comments in header files
- Left a TODO not in DU code to build PCCH (in F1 and direct paths)
2026-02-17 12:25:58 +01:00
Guido Casati
cf7879f038 Paging (F1AP): refactor CU_send_Paging() to use PAGING message
- Add F1AP_PAGING message type and macro; F1AP defines Paging, not
  Paging Indication. CU task now handles F1AP_PAGING instead of
  F1AP_PAGING_IND.
- In CU_send_Paging(): take const f1ap_paging_t *; replace inline
  ASN.1 encoding with encode_f1ap_paging(); refine memory management;
  clean up in the process

Note: F1AP_PAGING_IND definitions left in place and still used in the
RRC callback - to be removed in a follow-up commit.
2026-02-17 12:25:58 +01:00
Guido Casati
08f0f9369c Paging (F1AP): add F1 paging library (9.2.6.1 3GPP TS 38.473)
Add F1AP Paging library and new message type to follow the existing F1AP
library pattern and to support multi-cell paging and both RAN UE (I-RNTI)
and CN UE (5G-S-TMSI) paging identities at the library level per TS 38.473.

* New library (f1ap_paging.c/h, f1ap_lib_includes.h, CMakeLists.txt)
  - Implement encode/decode/copy/eq/free for F1AP Paging (procedure 9.2.6).
  - Add ASN.1 includes for Paging, PagingIdentity, CN/RAN UE identities.
  - Enables unit testing of Paging enc/dec in f1ap_lib_test.c.

* New types in f1ap_messages_types.h (existing f1ap_paging_ind_t unchanged)
  - f1ap_paging_t: UE Identity Index, paging identity (union + type enum),
    optional paging_drx, paging_priority, paging_origin, and paging_cells[].
  - f1ap_paging_cell_item_t, f1ap_paging_identity_type_t, f1ap_paging_identity_t
    for multi-cell list and RAN/CN identity discrimination.
  - Paging Origin IE is optional per F1AP 8.7.1.2.

Tests: test_f1ap_paging() roundtrip and copy for CN UE (5G-S-TMSI) and
RAN UE (I-RNTI) cases, with optional IEs.
2026-02-17 12:25:58 +01:00
Guido Casati
b026e6b4ee Paging (NGAP): add paging encode/decode library and unit tests (3GPP TS 38.413)
- Refactor ngap_paging_ind_t (openair2/COMMON/ngap_messages_types.h):
  - optional paging_drx and paging_priority as pointers
  - TAI list as tai_list[] and n_tai
  - add optional IEs: Paging Origin, Paging Attempt Information,
    UE Radio Capability for Paging.
  - Introduce nr_tai_t, ngap_paging_attempt_info_t, ngap_paging_origin_t;
  - generate paging enums via FOREACH macros.
- Add NGAP Paging encode/decode/eq/free in openair3/NGAP/ngap_gNB_paging.c
  (encode_ng_paging, decode_ng_paging, eq_ng_paging, free_ng_paging).
- Replace inline Paging decode in ngap_gNB_handle_paging() with
  decode_ng_paging() and add error handling; add eq_ngap_plmn() in
  ngap_common.
- Update rrc_gNB_NGAP.c to use tai_list/n_tai and optional paging_drx
  when forwarding paging to F1AP.
- Add ASN.1 includes for Paging in ngap_msg_includes.h; register
  ngap_gNB_paging.c in root CMakeLists.txt.
- Add NGAP unit test (openair3/NGAP/tests/ngap_lib_test.c): encode/decode
  roundtrip for Paging; tests subdirectory and executable under
  ENABLE_TESTS in openair3/NGAP/CMakeLists.txt.
2026-02-17 12:25:58 +01:00
Guido Casati
41942c96d2 Refactor (NGAP): split out NGAP utilities from common lib
ngap_common.h is for common IEs enc/dec functions, utilities
should go into a separate file. Changes in this commit:

* Add ngap_utils.h (utilities)
* Move helper macros (NGAP_ERROR, NGAP_DEBUG, NGAP_FIND_PROTOCOLIE_BY_ID, etc.) to ngap_utils.h
* Move equality check macros (_NGAP_EQ_CHECK_*) to ngap_utils.h
* Clean up includes

This change is preparatory to the introduction the paging lib with unit
tests, with the goal of reducing the inter-dependency between concurrent
NGAP libs.
2026-02-17 12:25:58 +01:00
Guido Casati
c436f05ea9 Refactor (NGAP): adopt TO_ENUM/TO_TEXT pattern for NGAP enums
TO_ENUM/TO_TEXT are already used in NAS, and can be adopted in NGAP.
To avoid duplication, the following changes are introduced:

* Move text_info_t, TO_ENUM, TO_TEXT to common/utils/utils.h
* Include utils.h include to ngap_messages_types.h, fgs_nas_utils.h, and fgmm_lib.h
* RRC establishment cause: refactor to FOREACH_RRC_ESTABLISHMENT_CAUSE macro
* Cause Group: refactor to FOREACH_CAUSE_GROUP macro
* Radio Network Cause: refactor to FOREACH_CAUSE_RADIO_NETWORK macro
* Protocol Cause: refactor to FOREACH_CAUSE_PROTOCOL macro

This change is preparatory to the introduction the paging lib with unit
tests, with the goal of reducing the inter-dependency between concurrent
NGAP libs.
2026-02-17 12:25:58 +01:00
Guido Casati
3dc8647a58 Refactor (NGAP): add conversion functions to ngap_common.c
These conversion functions will be needed across different
NGAP libraries upon refactoring: tnl_to_bitstring, bitstring_to_tnl
Therefore, they are moved to the common lib.
2026-02-17 12:25:58 +01:00
Guido Casati
e062f40137 Refactor (NGAP): extract PDU session management procedures to dedicated library
PDU session related NGAP messages do not belong to NAS procedures lib.

* Create ngap_gNB_pdu_session_management.c and .h
* Move out ngap_gNB_pdusession_setup_resp, ngap_gNB_pdusession_modify_resp,
  ngap_gNB_pdusession_release_resp from ngap_gNB_nas_procedures.c
* Move encode_ngap_pdusession_setup_response_transfer to ngap_common.c:
  this transfer IE is common used both in PDU Session Management and
  Initial Context Setup, so it's moved to the common lib
* Add ngap_gNB_pdu_session_management.c to CMakeLists.txt
2026-02-17 12:25:58 +01:00
Guido Casati
563a0cfa61 Refactor: unify equality-check macros across protocol libs
This commit centralizes equality-check behavior and removes duplicated
macro implementations across protocol stacks.

Major changes:
- add `common/utils/eq_check.h` with shared `_EQ_CHECK_*`,
  `EQ_CHECK_GENERIC`, and optional-IE pointer helpers
- replace E1AP/F1AP/NAS local equality macros and call sites with
  the shared helpers
- remove duplicated layer-specific error/equality macro definitions from
  common headers and switch includes to `eq_check.h`
- update CMake test flags to define `ENABLE_TESTS` for `e1ap_lib`,
  and 5GS NAS libraries; drop `E1AP_LOG_ERRORS` - equality-check/error
  printing is now consistently controlled by `ENABLE_TESTS`
2026-02-17 12:25:58 +01:00
Guido Casati
f295252b2e Refactor 5G-S-TMSI: harmonize 5G-S-TMSI handling with centralized helpers
Centralizes 5G-S-TMSI bit manipulation logic for consistency and
maintainability. All manual bit operations replaced with documented
helper functions following TS 23.003 bit layout specification.

- Add helper functions for 5G-S-TMSI operations:

  * nr_construct_5g_s_tmsi_part1: 5G-S-TMSI construction is defined
    in 3GPP TS 23.003 and relevant at both gNB and UE side
    * Add helper functions to be later used in NG Paging
    * Adopt in NAS UE
  * nr_extract_5g_s_tmsi_part1() - extract Part1 (39 bits) from full
  * nr_extract_5g_s_tmsi_part2() - extract Part2 (9 bits) from full
  * nr_build_full_5g_s_tmsi() - reconstruct full from Part1+Part2
  * nr_deconstruct_5g_s_tmsi() - deconstruct into components
- Refactor manual bit manipulation to use helper functions:
  * asn1_msg.c: use nr_extract_5g_s_tmsi_part1() in RRCSetupRequest
  * asn1_msg.c: use nr_extract_5g_s_tmsi_part2() in RRCSetupComplete
  * rrc_gNB.c: use nr_build_full_5g_s_tmsi() when reconstructing from parts
  * rrc_gNB.c: use nr_deconstruct_5g_s_tmsi() when extracting components
- Optimize nr_construct_5g_s_tmsi_part1() to reuse extract function
2026-02-17 12:25:58 +01:00
Guido Casati
3c164ef138 Minor (NGAP): clarify ngap_register_gnb_req_t actually refers to NG SETUP REQUEST
There is no such thing as NG Register message, the naming is
inaccurate, however the goal of this commit is only to clarify that
and major refactoring is not yet carried out.
2026-02-17 12:25:58 +01:00
Guido Casati
b27833fbd2 Cleanup (NGAP): remove unused message definitions
* NGAP_PATH_SWITCH_REQ_LOG, NGAP_PATH_SWITCH_REQ_ACK_LOG
* NGAP_UE_CTXT_MODIFICATION_RESP, NGAP_UE_CTXT_MODIFICATION_FAIL, NGAP_UE_CTXT_MODIFICATION_REQ
2026-02-17 12:25:58 +01:00
Guido Casati
2da094dd66 Cleanup (NGAP): remove NR_HandoverPreparationInformation.h from NGAP includes
this is not an NGAP header and does not belong to ngap_msg_includes.h
2026-02-17 12:25:58 +01:00
Guido Casati
372f121cf6 Refactor (RRC): extract rrc_update_ue_pcell() to public API and adopt consistently
Move rrc_update_ue_pcell() from static function in rrc_gNB.c to public
function in rrc_cell_management.c, making it reusable across RRC code
paths. Replace duplicate PCell addition logic in handover paths
(intra-CU and inter-CU) and RRCSetup path with calls to this shared
function.

This eliminates code duplication between handover and RRCSetup paths,
centralizes PCell update logic (including cleanup of old PCell's DU
serving cells) in a single reusable function and makes the function
available for future use in other RRC procedures
2026-02-17 11:36:25 +01:00
Guido Casati
f247a6cc2e fix(RRC): add PCell to serving_cells in fallback path and refactor update logic
Fix assertion failure in rrc_gNB_send_NGAP_NAS_FIRST_REQ() when RRC
Reestablishment falls back to RRC Setup. The fallback path was not
adding the PCell to the UE's serving_cells array, causing
rrc_get_pcell_for_ue() to return NULL.

Major changes:
- Add rrc_update_ue_pcell() helper function that handles PCell updates
  for both new UEs (fallback) and existing UEs (normal reestablishment)
- Refactor normal reestablishment path to use rrc_update_ue_pcell()
  helper instead of manual cleanup + add sequence
- Add PCell update to fallback_rrc_setup path using the same helper
- Move C-RNTI validation after current_cell fetch to ensure current_cell
  is initialized before fallback_rrc_setup label
- Change error handling: return instead of fallback when PCell add fails
  in normal reestablishment path
2026-02-17 11:36:25 +01:00
Cedric Roux
c1f41caa8d T: hacks: plot-ofdm: handle more skipped samples 2026-02-17 11:18:37 +01:00
Cedric Roux
61bdee3e61 T: extract: extract all traces by default 2026-02-17 11:18:37 +01:00
Cedric Roux
0c4655448f T: minor: fix compilation of _check_vcd
"make _check_vcd" was failing.
2026-02-17 11:18:37 +01:00
Cedric Roux
7e74d4c43e T: macpdu2wireshark: gentle exit
When outputting to a file, typing ctrl+c exits the program without calling
fclose(), leading to loss of traces in the output file.

Let's intercept ctrl+c and exit gently, calling fclose().
2026-02-17 11:18:37 +01:00
Teodora
dcfd16bd83 Remove useless definitions for E&F releases in _BySymbol() functions
Those functions are already encapsulated in #ifdef F_RELEASE condition.
2026-02-17 09:58:24 +01:00
Robert Schmidt
8925654c07 Remove unused 4G MMSE code
Since the parent commit, USE_MMSE is not defined. Thus, the
corresponding code is commented out. Since there are no linker problems,
it is obvious that this code is never called, and we can remove it.
2026-02-16 20:05:05 +01:00
Laurent THOMAS
da7897be04 remove cblas and lapack dependency, as the calling code can't be called in present master branch (likely never worked/fished code 2026-02-16 20:05:04 +01:00
Laurent THOMAS
345b44d9b3 re-order the functions to have them in natural C order (function implemented before call). Add a #if to be able to disable never called code, but the flag is not activated in this commit 2026-02-16 20:04:29 +01:00
Laurent THOMAS
b6171949cd only cleaning: remove dead code, make static functions, simplify code 2026-02-16 20:04:29 +01:00
Robert Schmidt
40e61d59a6 Merge branch 'fix-ubuntu-build' into 'develop' (!3934)
Fix Ubuntu build: reinstate -Werror

See merge request oai/openairinterface5g!3934
2026-02-16 14:31:23 +00:00
Robert Schmidt
a159f1b78a Revert "Compile everything in Ubuntu builder"
This reverts commit 16c333b1a3.

I tried to build everything in Ubuntu images, but

- this introduced a regression (ignores $BUILD_OPTION)
- made that we don't use -Werror (when we should)

I tried to fix the use of the first, but it would involve more changes
than I prefer. On the second, we cannot enable -Werror, as FlexRIC does
not build warning-free (in Release mode). We thus have to build only the
targets that we require, and therefore we can keep using build_oai,
which is the simplest option (cf. the first point).
2026-02-16 11:04:11 +01:00
Robert Schmidt
9c1603cfbb Remove BUILD_ARG: Will never build sanitize
xran does not work with Address Sanitizer. Thus, there is no reason to
keep these build arguments.
2026-02-16 11:01:37 +01:00
Maxime
37cb854319 Fix crash on double reestablishment: guard reconfigCellGroup overwrite 2026-02-12 11:03:23 -05:00
Reem Bahsoun
8f9abfb7f4 Tutorial improvement 2026-02-12 14:37:56 +01:00
Robert Schmidt
be4461ccca Move GTPV1U cmake code to subdirectory
Move the module cmake code to its subdirectory for better organization,
and  remove superfluous include_directories() that are not recommended
to be used (as it populates all other targets with those directories,
most of which don't need it anyway).

Slightly clean up the module by removing headers to unused dependencies.
The GTP module has a dependency to 4G and 5G RLC, which should not exist
(the RLC modules have a dependency on GTP, not the other way around),
but in this commit, make as little modifications as possible.
2026-02-12 06:48:52 +01:00
Robert Schmidt
11c2791527 Remove 5G code from LTE RRC 2026-02-12 06:14:49 +01:00
Robert Schmidt
9a248b4411 Move rrc_eNB_GTPV1U.c from GTP to LTE RRC module in cmake 2026-02-12 06:14:35 +01:00
Robert Schmidt
d9d18f07fd Remove unused functions 2026-02-12 06:06:19 +01:00
Robert Schmidt
40cfe2e5f2 Remove unused GTP types 2026-02-12 06:02:59 +01:00
Reem Bahsoun
b285f91968 Change Aerial config file in targets to match Nvidia's CI setup 2026-02-05 10:13:01 +01:00
361 changed files with 7358 additions and 8290 deletions

View File

@@ -434,7 +434,9 @@ add_library(ngap
${NGAP_DIR}/ngap_gNB_handlers.c
${NGAP_DIR}/ngap_gNB_itti_messaging.c
${NGAP_DIR}/ngap_gNB_management_procedures.c
${NGAP_DIR}/ngap_gNB_paging.c
${NGAP_DIR}/ngap_gNB_nas_procedures.c
${NGAP_DIR}/ngap_gNB_pdu_session_management.c
${NGAP_DIR}/ngap_gNB_nnsf.c
${NGAP_DIR}/ngap_gNB_overload.c
${NGAP_DIR}/ngap_gNB_trace.c
@@ -442,6 +444,9 @@ add_library(ngap
)
target_link_libraries(ngap PUBLIC asn1_ngap)
target_link_libraries(ngap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(ENABLE_TESTS)
target_compile_definitions(ngap PRIVATE ENABLE_TESTS)
endif()
#M2AP
##############
@@ -544,8 +549,10 @@ endif()
# Hardware dependant options
###################################
add_list1_option(NB_ANTENNAS_RX "4" "Number of antennas in reception" "1" "2" "4")
add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4")
set(NB_ANTENNAS_RX "4" CACHE STRING "Number of antennas in reception")
set_property(CACHE NB_ANTENNAS_RX PROPERTY STRINGS "1" "2" "4" "8")
set(NB_ANTENNAS_TX "4" CACHE STRING "Number of antennas in transmission")
set_property(CACHE NB_ANTENNAS_TX PROPERTY STRINGS "1" "2" "4" "8")
set (CONFIG_ROOTDIR ${OPENAIR_DIR}/common/config)
add_library(config_internals OBJECT
@@ -648,7 +655,6 @@ include_directories("${OPENAIR3_DIR}/S1AP")
include_directories("${OPENAIR2_DIR}/X2AP")
include_directories("${OPENAIR2_DIR}/M2AP")
include_directories("${OPENAIR2_DIR}/F1AP")
include_directories("${OPENAIR3_DIR}/ocp-gtpu")
include_directories("${OPENAIR3_DIR}/M3AP")
include_directories("${OPENAIR3_DIR}/MME_APP")
include_directories("${OPENAIR_DIR}/radio/COMMON")
@@ -926,7 +932,6 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss_gen.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/uci_tools_ue.c
@@ -1072,16 +1077,8 @@ add_dependencies(PHY_COMMON dfts)
add_library(PHY ${PHY_SRC})
target_link_libraries(PHY PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
pkg_check_modules(blas REQUIRED blas)
pkg_check_modules(lapacke REQUIRED lapacke)
add_library(PHY_UE ${PHY_SRC_UE})
target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
# RHEL needs also cblas, but Ubuntu does not have it. So `cblas_LIBRARIES` and
# `cblas_INCLUDE_DIRS` will be empty for Ubuntu, a no-op
pkg_check_modules(cblas cblas)
target_link_libraries(PHY_UE PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES})
target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${cblas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS})
add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
@@ -1158,7 +1155,7 @@ set(L2_SRC
${RRC_DIR}/rrc_eNB_S1AP.c
${RRC_DIR}/rrc_eNB_M2AP.c
${RRC_DIR}/rrc_eNB_UE_context.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${RRC_DIR}/rrc_eNB_GTPV1U.c
${RRC_DIR}/rrc_common.c
${RRC_DIR}/L2_interface.c
${RRC_DIR}/L2_interface_common.c
@@ -1405,15 +1402,6 @@ include_directories("${OPENAIR1_DIR}/SCHED_NR_UE")
# CN libs
##########################
add_library (GTPV1U
${RRC_DIR}/rrc_eNB_GTPV1U.c
${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp
${OPENAIR3_DIR}/ocp-gtpu/gtpu_extensions.c
)
target_link_libraries(GTPV1U PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(GTPV1U PRIVATE SIMU ds)
include_directories(${OPENAIR3_DIR}/ocp-gtp)
set (MME_APP_SRC
${OPENAIR3_DIR}/MME_APP/mme_app.c
${OPENAIR3_DIR}/MME_APP/mme_config.c
@@ -1773,7 +1761,6 @@ target_link_libraries(lte-softmodem PRIVATE
target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(lte-softmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES} ${lapack_LIBRARIES})
if(E2_AGENT)
target_link_libraries(lte-softmodem PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup)
@@ -1824,7 +1811,6 @@ target_link_libraries(lte-uesoftmodem PRIVATE
target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB})
target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(lte-uesoftmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES} ${lapack_LIBRARIES})
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries(lte-uesoftmodem PRIVATE

View File

@@ -33,7 +33,6 @@
#-----------------------------------------------------------
import sys # arg
import re # reg
import yaml
import constants as CONST
#-----------------------------------------------------------
@@ -44,6 +43,7 @@ import constants as CONST
def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
force_local = False
date_fmt = None
while len(argvs) > 1:
myArgv = argvs.pop(1) # 0th is this file's name
@@ -56,6 +56,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
#consider inline parameters
elif re.match(r'^\-\-datefmt=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-datefmt=(.+)$', myArgv, re.IGNORECASE)
date_fmt = matchReg.group(1)
elif re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE)
mode = matchReg.group(1)
@@ -158,9 +161,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
elif re.match(r'^\-\-OCRegistry=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-OCRegistry=(.+)$', myArgv, re.IGNORECASE)
CLUSTER.OCRegistry = matchReg.group(1)
elif re.match(r'^\-\-BuildId=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-BuildId=(.+)$', myArgv, re.IGNORECASE)
RAN.BuildId = matchReg.group(1)
elif re.match(r'^\-\-FlexRicTag=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-FlexRicTag=(.+)$', myArgv, re.IGNORECASE)
CONTAINERS.flexricTag = matchReg.group(1)
@@ -168,4 +168,4 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
HELP.GenericHelp(CONST.Version)
sys.exit('Invalid Parameter: ' + myArgv)
return mode, force_local
return mode, force_local, date_fmt

View File

@@ -22,10 +22,15 @@
import re
import os
import logging
import yaml
import signal
import xml.etree.ElementTree as ET
import json
import importlib, inspect
class Analysis():
def _get_test_description(properties):
@@ -109,3 +114,134 @@ class Analysis():
test_summary['Nbpass'] = nb_tests - nb_failed
test_summary['Nbfail'] = nb_failed
return nb_failed == 0, test_summary, test_result
def analyze_rt_stats(thresholds, L1_stats, MAC_stats):
with open(thresholds, 'r') as f:
datalog_rt_stats = yaml.load(f, Loader=yaml.FullLoader)
rt_keys = datalog_rt_stats['Ref']
real_time_stats = {}
for sf in [L1_stats, MAC_stats]:
with open(sf, 'r') as f:
for line in f.readlines():
for k in rt_keys:
result = re.search(k, line)
if result is not None:
tmp = re.match(rf'^.*?(\b{k}\b.*)', line.rstrip())
if tmp is not None:
real_time_stats[k] = tmp.group(1)
# datalog_rt_stats format must align with HTML.CreateHtmlDataLogTable()
datalog_rt_stats['Data']={}
for k in real_time_stats:
tmp = re.match(r'^(?P<metric>.*):\s+(?P<avg>\d+\.\d+) us;\s+(?P<count>\d+);\s+(?P<max>\d+\.\d+) us;', real_time_stats[k])
if tmp is not None:
metric = tmp.group('metric')
avg = float(tmp.group('avg'))
max = float(tmp.group('max'))
count = int(tmp.group('count'))
datalog_rt_stats['Data'][metric] = ["{:.0f}".format(avg),"{:.0f}".format(max),"{:d}".format(count),"{:.2f}".format(avg / datalog_rt_stats['Ref'][metric])]
success = True
for k in datalog_rt_stats['Data']:
valnorm = float(datalog_rt_stats['Data'][k][3])
dev = datalog_rt_stats['DeviationThreshold'][k]
if valnorm > 1.0 + dev or valnorm < 1.0 - dev: # condition for fail: avg/ref deviates by more than "deviation threshold"
logging.debug(f'\u001B[1;30;43m normalized metric {k}={valnorm} deviates by more than {dev}\u001B[0m')
success = False
return success, datalog_rt_stats
# returns tuple of (service, analyzer, option string)
def _lookupServiceAnalyzerOpt(s, analyzers):
res = s.split("=", 2)
name = res[0]
if len(res) == 1:
return res[0], analyzers["Default"], None
opt = res[2] if len(res) > 2 else None
func = res[1]
a = analyzers[func] if func in analyzers else None
return name, a, opt
# groups requested service analysis (service=func[=option]) on per service
# basis and looks up analyzer func. If log analysis is requested, will always
# run Default log analysis
def _groupServices(to_analyze):
req_analysis = {}
# get content of cls_loganalysis module, then get all analyzers (classes) in this module
mod = importlib.import_module("cls_loganalysis")
analyzers = {name:cl for name, cl in inspect.getmembers(mod, inspect.isclass)}
for req in to_analyze:
s, func, opt = _lookupServiceAnalyzerOpt(req, analyzers)
logging.debug(f"requested check '{req}' => service {s}, function {func.__name__}, options '{opt}'")
# always put default analyzer first
l = req_analysis[s] if s in req_analysis else [(analyzers["Default"], None, "default")]
if func is not analyzers["Default"]:
l.append((func, opt, req))
req_analysis[s] = l
return req_analysis
def _describe_exit_code(code):
if code > 128:
sig = code - 128
try:
return f"terminated by signal {sig} ({signal.Signals(sig).name})"
except ValueError:
return f"terminated by unknown signal {sig}"
else:
return f"custom exit code"
def AnalyzeServices(HTML, service_desc, to_analyze):
success = True
# hack: we want to give as a description "log analysis", but the description
# is set outside, so retain what was set before
orig_html_desc = HTML.desc
# group analysis on a per-service basis, then iterate
for serv, list_analysis in _groupServices(to_analyze).items():
HTML.desc = f"Log analysis for service {serv}"
if serv not in service_desc:
success = False
logging.error(f"requested service {serv} not in list of services")
HTML.CreateHtmlTestRowQueue("N/A", 'KO', ["service not detected"])
continue
# pre-initialize with return code
rc = service_desc[serv]["returncode"]
logging.info(f"analyze service {serv}: return code {rc}")
service_success = True # TODO rc == 0: too many functions (eNB, lteUE, RIC, nrUE) fail non-zero
logs = []
if rc != 0:
logs.append(f"=> return code {rc}, likely " + _describe_exit_code(rc) + " [ignored by CI]")
# skip if the file is too big
logfile = service_desc[serv]["logfile"]
filename = os.path.basename(logfile)
b = os.path.getsize(logfile)
logging.debug(f"using logfile {logfile} of size {b} bytes")
if b > 10 * 1024 * 1024:
success = False
logs.append(f"logfile too big (>10MB)")
logging.error(logs)
HTML.CreateHtmlTestRowQueue(filename, 'KO', ["\n".join(logs)])
continue
# run each analyzer with its options on the logfile
for (func, opt, desc) in list_analysis:
if func is None:
service_success = False
logging.error(f"request analysis function for desc {desc} not found")
HTML.CreateHtmlTestRowQueue(serv, 'KO', [f"no analysis function for {desc}"])
continue
result, l = func.run(logfile, opt)
logging.info(f"service {serv}: analysis with func {func}, result {result}, logs '{l}'")
service_success = service_success and result
if not result:
logs.append(f"=> {func.__name__} check (options '{opt}') FAILED")
logs.append(l)
logs = '\n'.join(logs)
if not service_success:
logging.error(l)
else:
logging.info(l)
all_funcs = ", ".join([f.__name__ for (f, _, _) in list_analysis])
HTML.CreateHtmlTestRowQueue(f"Check {all_funcs} on {filename}", 'OK' if service_success else 'KO', [logs])
success = success and service_success
HTML.desc = orig_html_desc
return success

View File

@@ -31,23 +31,17 @@
#-----------------------------------------------------------
# Import
#-----------------------------------------------------------
import sys # arg
import re # reg
import logging
import os
import shutil
import time
from zipfile import ZipFile
#-----------------------------------------------------------
# OAI Testing modules
#-----------------------------------------------------------
import cls_cmd
import helpreadme as HELP
import constants as CONST
import cls_oaicitest
import cls_analysis
from cls_ci_helper import archiveArtifact
from collections import deque
#-----------------------------------------------------------
# Helper functions used here and in other classes
@@ -186,62 +180,9 @@ def GetDeployedServices(ssh, file):
else:
c = ret.stdout
logging.info(f'service {s} with container id {c}')
deployed_services.append(s)
deployed_services.append((s, c))
return deployed_services
def CheckLogs(self, filename, HTML, RAN):
success = True
name = os.path.basename(filename)
if (any(sub in name for sub in ['oai_ue','oai-nr-ue','lte_ue'])):
logging.debug(f'\u001B[1m Analyzing UE logfile {filename} \u001B[0m')
logStatus = cls_oaicitest.OaiCiTest().AnalyzeLogFile_UE(filename, HTML, RAN)
opt = f"UE log analysis ({name})"
# usage of htmlUEFailureMsg/htmleNBFailureMsg is because Analyze log files
# abuse HTML to store their reports, and we here want to put custom options,
# which is not possible with CreateHtmlTestRow
# solution: use HTML templates, where we don't need different HTML write funcs
if (logStatus < 0):
HTML.CreateHtmlTestRowQueue(opt, 'KO', [HTML.htmlUEFailureMsg])
success = False
else:
HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmlUEFailureMsg])
HTML.htmlUEFailureMsg = ""
elif 'nv-cubb' in name:
msg = 'Undeploy PNF/Nvidia CUBB'
HTML.CreateHtmlTestRow(msg, 'OK', CONST.ALL_PROCESSES_OK)
elif (any(sub in name for sub in ['enb','rru','rcc','cu','du','gnb','vnf'])):
logging.debug(f'\u001B[1m Analyzing XnB logfile {filename}\u001B[0m')
logStatus = RAN.AnalyzeLogFile_eNB(filename, HTML, self.ran_checkers)
opt = f"xNB log analysis ({name})"
if (logStatus < 0):
HTML.CreateHtmlTestRowQueue(opt, 'KO', [HTML.htmleNBFailureMsg])
success = False
else:
HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmleNBFailureMsg])
HTML.htmleNBFailureMsg = ""
elif 'xapp' in name:
opt = f"Undeploy {name}"
with open(f'{filename}', "r") as f:
last_line = deque(f, maxlen=1).pop()
if ('Test xApp run SUCCESSFULLY' in last_line):
HTML.CreateHtmlTestRowQueue(opt, 'OK', ["xApp run successfully"])
else:
HTML.CreateHtmlTestRowQueue(opt, 'KO', ["xApp didn't run successfully"])
success = False
elif 'RIC' in name:
opt = f"Undeploy {name}"
with open(f'{filename}', 'r') as f:
last_line = deque(f, maxlen=1).pop()
if ('Removing E2 Node' in last_line):
HTML.CreateHtmlTestRowQueue(opt, 'OK', ["nearRT-RIC run successfully"])
else:
HTML.CreateHtmlTestRowQueue(opt, 'KO', ["nearRT-RIC didn't run successfully"])
success = False
else:
logging.info(f"Skipping analysis of log '{filename}': no submatch for xNB/UE")
logging.debug(f"log check: file {filename} passed analysis {success}")
return success
#-----------------------------------------------------------
# Class Declaration
#-----------------------------------------------------------
@@ -266,8 +207,6 @@ class Containerize():
self.dockerfileprefix = ''
self.host = ''
#checkers from xml
self.ran_checkers={}
self.num_attempts = 1
self.flexricTag = ''
@@ -372,12 +311,16 @@ class Containerize():
for image,pattern,name,option in imageNames:
cmd.run(f"{self.cli} image rm {name}:{imageTag}", reportNonZero=False)
cmd.run(f'docker login -u oaicicd -p oaicicd {DEFAULT_REGISTRY}')
ubuntuImage = "ubuntu:noble"
# Build the base image only on Push Events (not on Merge Requests)
# On when the base image docker file is being modified.
if forceBaseImageBuild:
cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}")
logfile = f'{lSourcePath}/cmake_targets/log/ran-base.docker.log'
cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} . &> {logfile}", timeout=1600)
if self.host == 'Ubuntu':
option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} {option} . &> {logfile}", timeout=1600)
t = ("ran-base", archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
@@ -420,6 +363,8 @@ class Containerize():
if image == 'oai-gnb-aerial':
cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2026.01.07.tar.gz .')
logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log'
if self.host == 'Ubuntu':
option = option + f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200)
t = (name, archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
@@ -446,7 +391,7 @@ class Containerize():
allImagesSize[name] = 'unknown'
# Now pruning dangling images in between target builds
cmd.run(f"{self.cli} image prune --force")
cmd.run(f'docker logout {DEFAULT_REGISTRY}')
# Remove all intermediate build images and clean up
cmd.run(f"{self.cli} image rm ran-build:{imageTag} ran-build-asan:{imageTag} ran-build-fhi72:{imageTag} || true")
cmd.run(f"{self.cli} volume prune --force")
@@ -790,7 +735,7 @@ class Containerize():
wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as ssh:
ExistEnvFilePrint(ssh, wd)
services = GetDeployedServices(ssh, wd_yaml)
services = [s for s, _ in GetDeployedServices(ssh, wd_yaml)]
success = []
fail = []
for s in reqServices:
@@ -808,7 +753,7 @@ class Containerize():
HTML.CreateHtmlTestRowQueue(self.services, 'KO', [f'Failed stopping {" ".join(fail)}, succeeded {" ".join(success)}'])
return success
def UndeployObject(self, ctx, node, HTML, RAN):
def UndeployObject(self, ctx, node, HTML, to_analyze):
lSourcePath = self.eNBSourceCodePath
logging.info(f'\u001B[1m Undeploying all objects from server {node}\u001B[0m')
yaml = self.yamlPath.strip('/')
@@ -817,23 +762,49 @@ class Containerize():
with cls_cmd.getConnection(node) as ssh:
ExistEnvFilePrint(ssh, wd)
services = GetDeployedServices(ssh, wd_yaml)
copyin_res = None
all_logs = True
ssh.run(f'docker compose -f {wd_yaml} stop')
if services is not None:
copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, wd_yaml, ctx) for s in services]
service_desc = {}
for s, c in services:
ret = ssh.run(f'docker inspect {c} --format="{{{{.State.ExitCode}}}}"')
rc = int(ret.stdout.strip())
f = CopyinServiceLog(ssh, lSourcePath, s, wd_yaml, ctx)
all_logs = all_logs and f is not None
service_desc[s] = {'returncode': rc, 'logfile': f}
else:
logging.warning('could not identify services to stop => no log file')
ssh.run(f'docker compose -f {wd_yaml} down -v')
HTML.CreateHtmlTestRowQueue(node, 'OK', ['Undeployment successful'])
ssh.run(f'rm {wd}/.env')
if not copyin_res:
if not all_logs:
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['Could not copy logfile(s)'])
logging.error(f"could not copy all files: {copyin_res=} {services=}")
logging.error(f"could not copy all files: {all_logs=} {services=}")
success = False
else:
log_results = [CheckLogs(self, f, HTML, RAN) for f in copyin_res]
success = all(log_results)
success = cls_analysis.AnalyzeServices(HTML, service_desc, to_analyze)
if success:
logging.info('\u001B[1m Undeploying objects Pass\u001B[0m')
else:
logging.error('\u001B[1m Undeploying objects Failed\u001B[0m')
return success
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds):
logging.info(f'Analyzing realtime stats from server: {node}')
yaml = self.yamlPath.strip('/')
wd = f'{self.eNBSourceCodePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as cmd:
services = GetDeployedServices(cmd, wd_yaml)
s, _ = services[0] # we simply assume something is deployed, if not Exception will report
# similar to BuildRunTests(), use docker cp to avoid problems with permissions
cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrL1_stats.log {wd}/')
l1_file = archiveArtifact(cmd, ctx, f"{wd}/nrL1_stats.log")
cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrMAC_stats.log {wd}/')
mac_file = archiveArtifact(cmd, ctx, f"{wd}/nrMAC_stats.log")
logging.info(f"check against thresholds from {thresholds}")
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, l1_file, mac_file)
HTML.CreateHtmlDataLogTable(datalog_rt_stats)
return success

View File

@@ -0,0 +1,161 @@
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
# * this work for additional information regarding copyright ownership.
# * The OpenAirInterface Software Alliance licenses this file to You under
# * the OAI Public License, Version 1.1 (the "License"); you may not use this file
# * except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.openairinterface.org/?page_id=698
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *-------------------------------------------------------------------------------
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# * contact@openairinterface.org
# */
#---------------------------------------------------------------------
import re
import os
import logging
from collections import deque
class Default:
def run(file, opt=None):
success = True
logs = []
with open(file, "r") as f:
for line in f.readlines():
result = re.search('[Aa]ssertion', line)
if result:
logs.append(line)
success = False
return success, "\n".join(logs)
class ContainsString:
def run(file, needle):
with open(file, "r") as f:
for line in f.readlines():
if re.search(needle, line):
return True, ""
return False, f"could not find '{needle}' in logs"
class LastLineContains:
def run(file, string):
with open(file, "r") as f:
last_line = deque(f, maxlen=1).pop()
success = string in last_line
log = "" if success else f"could not find '{string}' in last line"
return success, log
class EndsWithBye:
def run(file, option):
# no option: we ignore any
with open(file, "r") as f:
n = 0
for line in reversed(f.readlines()):
if re.search(r'^Bye.\n', line, re.MULTILINE) is not None:
return True, ""
n = n + 1
if n > 50: # if not found in last 50 lines, assume it does not exist
break
return False, "No Bye. message found, did not stop properly"
class RetxCheck():
def _parseList(s):
if not s:
return []
return [int(n) for n in s.split(",")]
def _get_ul_dl(s):
dl, ul = (None, None)
for o in s.split(";", 1):
if o.startswith("dl="):
dl = o[3:]
elif o.startswith("ul="):
ul = o[3:]
else:
raise ValueError(f"unrecognized option {s}: needs format '[ul=,dl=]X,Y,...[;ul=Z,V,...]'")
return dl, ul
def _parseRetxCheckers(options):
if not "=" in options:
dlul = RetxCheck._parseList(options)
return dlul, dlul
dl, ul = RetxCheck._get_ul_dl(options)
return RetxCheck._parseList(dl), RetxCheck._parseList(ul)
def _analyzeUeRetx(rounds, checkers, regex):
perc = list(0 for i in checkers) # results in %
stats = list(False for i in checkers) # status if succeeded
tmp = re.match(regex, rounds)
if tmp is None:
logging.error('_analyzeUeRetx: did not match regex for DL retx analysis')
return stats
retx_data = [float(x) for x in tmp.groups()]
for i in range(0, len(perc)):
#case where numerator > denumerator with denum ==0 is disregarded, cannot hapen in principle, will lead to 0%
perc[i] = 0 if (retx_data[i] == 0) else 100 * retx_data[i + 1] / retx_data[i]
#treating % > 100 , % > requirement
stats[i] = perc[i] <= 100 and perc[i] <= checkers[i]
return stats
def _filter_retx_rounds(l):
# map to round number if False, else None
l = [i+1 if x is False else None for i, x in enumerate(l)]
# filter out None
return [x for x in l if x is not None]
def run(file, options):
# aggregate statistics per UE
dlsch_ulsch_stats = {}
status = True
with open(file, "r") as f:
for line in f.readlines():
keys = {'dlsch_rounds','ulsch_rounds'}
for k in keys:
result = re.search(k, line)
if result is None:
continue
result = re.search('UE (?:RNTI )?([0-9a-f]{4})', line)
if result is None:
logging.error(f'did not find RNTI while matching key {k}')
status = False
continue
rnti = result.group(1)
if not rnti in dlsch_ulsch_stats:
dlsch_ulsch_stats[rnti] = {}
dlsch_ulsch_stats[rnti][k]=re.sub(r'^.*\]\s+', r'' , line.rstrip())
dl, ul = RetxCheck._parseRetxCheckers(options)
msgs = []
for ue in dlsch_ulsch_stats:
dlulstat = dlsch_ulsch_stats[ue]
for key in dlulstat:
msgs.append(dlulstat[key])
retx_dl = RetxCheck._analyzeUeRetx(dlulstat['dlsch_rounds'], dl, r'^.*dlsch_rounds\s+(\d+)\/(\d+)\/(\d+)\/(\d+),\s+dlsch_errors\s+(\d+)')
retx_ul = RetxCheck._analyzeUeRetx(dlulstat['ulsch_rounds'], ul, r'^.*ulsch_rounds\s+(\d+)\/(\d+)\/(\d+)\/(\d+),\s+ulsch_errors\s+(\d+)')
if False in retx_dl or False in retx_ul:
dlstr = RetxCheck._filter_retx_rounds(retx_dl)
ulstr = RetxCheck._filter_retx_rounds(retx_ul)
msg = f"UE {ue}: retx rounds"
if dlstr:
msg = f"{msg} DL {dlstr}"
if ulstr:
msg = f"{msg} UL {ulstr}"
msg = f"{msg} exceeded threshold"
msgs.append('!!! Failure: ' + msg)
logging.error(f'\u001B[1;37;41m {msg}\u001B[0m')
status = False
else:
msg = f"UE {ue} retransmissions within bounds"
logging.debug(msg)
return status, "\n".join(msgs)

View File

@@ -218,7 +218,7 @@ class HTMLManagement():
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html"
subprocess.run(cmd, shell=True)
else:
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + r"__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
subprocess.run(cmd, shell=True)
self.htmlFooterCreated = False

View File

@@ -32,7 +32,6 @@
#-----------------------------------------------------------
# Import Libs
#-----------------------------------------------------------
import sys # arg
import re # reg
import time # sleep
import os
@@ -41,7 +40,6 @@ import concurrent.futures
import json
#import our libs
import helpreadme as HELP
import constants as CONST
import cls_module
@@ -301,7 +299,6 @@ class OaiCiTest():
self.iperf_profile = ''
self.iperf_tcp_rate_target = ''
self.finalStatus = False
self.air_interface=''
self.ue_ids = []
self.svr_node = None
self.svr_id = None
@@ -579,277 +576,6 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', [f'{ue_header}\n{msg}'])
return success
def AnalyzeLogFile_UE(self, UElogFile,HTML,RAN):
if (not os.path.isfile(f'{UElogFile}')):
return -1
ue_log_file = open(f'{UElogFile}', 'r')
exitSignalReceived = False
foundAssertion = False
msgAssertion = ''
msgLine = 0
foundSegFault = False
foundRealTimeIssue = False
uciStatMsgCount = 0
pdcpDataReqFailedCount = 0
badDciCount = 0
f1aRetransmissionCount = 0
fatalErrorCount = 0
macBsrTimerExpiredCount = 0
rrcConnectionRecfgComplete = 0
no_cell_sync_found = False
mib_found = False
frequency_found = False
plmn_found = False
nrUEFlag = False
nrDecodeMib = 0
nrFoundDCI = 0
nrCRCOK = 0
mbms_messages = 0
nbPduSessAccept = 0
nbPduDiscard = 0
HTML.htmlUEFailureMsg=''
global_status = CONST.ALL_PROCESSES_OK
for line in ue_log_file.readlines():
result = re.search('nr_synchro_time|Starting NR UE soft modem', str(line))
sidelink = re.search('sl-mode', str(line))
if result is not None:
nrUEFlag = True
if sidelink is not None:
nrUEFlag = False
if nrUEFlag:
result = re.search('decode mib', str(line))
if result is not None:
nrDecodeMib += 1
result = re.search('found 1 DCIs', str(line))
if result is not None:
nrFoundDCI += 1
result = re.search('CRC OK', str(line))
if result is not None:
nrCRCOK += 1
result = re.search('Received PDU Session Establishment Accept', str(line))
if result is not None:
nbPduSessAccept += 1
result = re.search('warning: discard PDU, sn out of window', str(line))
if result is not None:
nbPduDiscard += 1
result = re.search('--nfapi STANDALONE_PNF --node-number 2', str(line))
if result is not None:
frequency_found = True
result = re.search('Exiting OAI softmodem', str(line))
if result is not None:
exitSignalReceived = True
result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line))
if result is not None and not exitSignalReceived:
foundSegFault = True
result = re.search('[Cc]ore [dD]ump', str(line))
if result is not None and not exitSignalReceived:
foundSegFault = True
result = re.search('[Aa]ssertion', str(line))
if result is not None and not exitSignalReceived:
foundAssertion = True
result = re.search('LLL', str(line))
if result is not None and not exitSignalReceived:
foundRealTimeIssue = True
if foundAssertion and (msgLine < 3):
msgLine += 1
msgAssertion += str(line)
result = re.search('uci->stat', str(line))
if result is not None and not exitSignalReceived:
uciStatMsgCount += 1
result = re.search('PDCP data request failed', str(line))
if result is not None and not exitSignalReceived:
pdcpDataReqFailedCount += 1
result = re.search('bad DCI 1', str(line))
if result is not None and not exitSignalReceived:
badDciCount += 1
result = re.search('Format1A Retransmission but TBS are different', str(line))
if result is not None and not exitSignalReceived:
f1aRetransmissionCount += 1
result = re.search('FATAL ERROR', str(line))
if result is not None and not exitSignalReceived:
fatalErrorCount += 1
result = re.search('MAC BSR Triggered ReTxBSR Timer expiry', str(line))
if result is not None and not exitSignalReceived:
macBsrTimerExpiredCount += 1
result = re.search('Generating RRCConnectionReconfigurationComplete', str(line))
if result is not None:
rrcConnectionRecfgComplete += 1
# No cell synchronization found, abandoning
result = re.search('No cell synchronization found, abandoning', str(line))
if result is not None:
no_cell_sync_found = True
if RAN.eNBmbmsEnables[0]:
result = re.search('TRIED TO PUSH MBMS DATA', str(line))
if result is not None:
mbms_messages += 1
result = re.search(r"MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P<nidcell>\d{1,3}), N_RB_DL (?P<n_rb_dl>\d{1,3}), PHICH DURATION (?P<phich_duration>\d), PHICH RESOURCE (?P<phich_resource>.{1,4}), TX_ANT (?P<tx_ant>\d)", str(line))
if result is not None and (not mib_found):
try:
mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2)
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n'
logging.debug(f'\033[94m{mibMsg}\033[0m')
mibMsg = " nidcell = " + result.group('nidcell')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg
logging.debug(f'\033[94m{mibMsg}\033[0m')
mibMsg = " n_rb_dl = " + result.group('n_rb_dl')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n'
logging.debug(f'\033[94m{mibMsg}\033[0m')
mibMsg = " phich_duration = " + result.group('phich_duration')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg
logging.debug(f'\033[94m{mibMsg}\033[0m')
mibMsg = " phich_resource = " + result.group('phich_resource')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n'
logging.debug(f'\033[94m{mibMsg}\033[0m')
mibMsg = " tx_ant = " + result.group('tx_ant')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n'
logging.debug(f'\033[94m{mibMsg}\033[0m')
mib_found = True
except Exception as e:
logging.error(f'\033[91m MIB marker was not found \033[0m')
result = re.search("Initial sync: pbch decoded sucessfully", str(line))
if result is not None and (not frequency_found):
try:
mibMsg = f"UE decoded PBCH successfully"
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n'
logging.debug(f'\033[94m{mibMsg}\033[0m')
frequency_found = True
except Exception as e:
logging.error(f'\033[91m UE did not find PBCH\033[0m')
result = re.search(r"PLMN MCC (?P<mcc>\d{1,3}), MNC (?P<mnc>\d{1,3}), TAC", str(line))
if result is not None and (not plmn_found):
try:
mibMsg = f"PLMN MCC = {result.group('mcc')} MNC = {result.group('mnc')}"
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n'
logging.debug(f'\033[94m{mibMsg}\033[0m')
plmn_found = True
except Exception as e:
logging.error(f'\033[91m PLMN not found \033[0m')
result = re.search(r"Found (?P<operator>[\w,\s]{1,15}) \(name from internal table\)", str(line))
if result is not None:
try:
mibMsg = f"The operator is: {result.group('operator')}"
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n'
logging.debug(f'\033[94m{mibMsg}\033[0m')
except Exception as e:
logging.error(f'\033[91m Operator name not found \033[0m')
result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line))
if result is not None:
try:
mibMsg = f'SIB5 InterFreqCarrierFreq element {result.group(1)}/{result.group(2)}'
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + ' -> '
logging.debug(f'\033[94m{mibMsg}\033[0m')
except Exception as e:
logging.error(f'\033[91m SIB5 InterFreqCarrierFreq element not found \033[0m')
result = re.search(r"DL Carrier Frequency/ARFCN : \-*(?P<carrier_frequency>\d{1,15}/\d{1,4})", str(line))
if result is not None:
try:
freq = result.group('carrier_frequency')
new_freq = re.sub('/[0-9]+','',freq)
float_freq = float(new_freq) / 1000000
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz'
logging.debug(f'\033[94m DL Carrier Frequency is: {freq}\033[0m')
except Exception as e:
logging.error(f'\033[91m DL Carrier Frequency not found \033[0m')
result = re.search(r"AllowedMeasBandwidth : (?P<allowed_bandwidth>\d{1,7})", str(line))
if result is not None:
try:
prb = result.group('allowed_bandwidth')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + ' -- PRB: ' + prb + '\n'
logging.debug(f'\033[94m AllowedMeasBandwidth: {prb}\033[0m')
except Exception as e:
logging.error(f'\033[91m AllowedMeasBandwidth not found \033[0m')
ue_log_file.close()
if rrcConnectionRecfgComplete > 0:
statMsg = f'UE connected to eNB ({rrcConnectionRecfgComplete}) RRCConnectionReconfigurationComplete message(s) generated)'
logging.debug(f'\033[94m{statMsg}\033[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if nrUEFlag:
if nrDecodeMib > 0:
statMsg = f'UE showed {nrDecodeMib} "MIB decode" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if nrFoundDCI > 0:
statMsg = f'UE showed {nrFoundDCI} "DCI found" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if nrCRCOK > 0:
statMsg = f'UE showed {nrCRCOK} "PDSCH decoding" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if not frequency_found:
statMsg = 'NR-UE could NOT synch!'
logging.error(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if nbPduSessAccept > 0:
statMsg = f'UE showed {nbPduSessAccept} "Received PDU Session Establishment Accept" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if nbPduDiscard > 0:
statMsg = f'UE showed {nbPduDiscard} "warning: discard PDU, sn out of window" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if uciStatMsgCount > 0:
statMsg = f'UE showed {uciStatMsgCount} "uci->stat" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if pdcpDataReqFailedCount > 0:
statMsg = f'UE showed {pdcpDataReqFailedCount} "PDCP data request failed" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if badDciCount > 0:
statMsg = f'UE showed {badDciCount} "bad DCI 1(A)" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if f1aRetransmissionCount > 0:
statMsg = f'UE showed {f1aRetransmissionCount} "Format1A Retransmission but TBS are different" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if fatalErrorCount > 0:
statMsg = f'UE showed {fatalErrorCount} "FATAL ERROR:" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if macBsrTimerExpiredCount > 0:
statMsg = f'UE showed {fatalErrorCount} "MAC BSR Triggered ReTxBSR Timer expiry" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if RAN.eNBmbmsEnables[0]:
if mbms_messages > 0:
statMsg = f'UE showed {mbms_messages} "TRIED TO PUSH MBMS DATA" message(s)'
logging.debug(f'\u001B[1;30;43m{statMsg}\u001B[0m')
else:
statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)'
logging.debug(f'\u001B[1;30;41m{statMsg}\u001B[0m')
global_status = CONST.OAI_UE_PROCESS_NO_MBMS_MSGS
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n'
if foundSegFault:
logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m')
if not nrUEFlag:
global_status = CONST.OAI_UE_PROCESS_SEG_FAULT
else:
if not frequency_found:
global_status = CONST.OAI_UE_PROCESS_SEG_FAULT
if foundAssertion:
logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE showed an assertion!\n'
if not nrUEFlag:
if not mib_found or not frequency_found:
global_status = CONST.OAI_UE_PROCESS_ASSERTION
else:
if not frequency_found:
global_status = CONST.OAI_UE_PROCESS_ASSERTION
if foundRealTimeIssue:
logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE faced real time issues!\n'
if nrUEFlag:
if not frequency_found:
global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC
else:
if no_cell_sync_found and not mib_found:
logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m')
HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE could not synchronize!\n'
global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC
return global_status
def TerminateUE(self, ctx, node, HTML):
ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids]
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:

View File

@@ -89,7 +89,7 @@ class StaticCodeAnalysis():
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
# on RedHat/CentOS .git extension is mandatory
result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
result = re.search(r'([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
if result is not None:
full_ran_repo_name = self.ranRepository.replace('git/', 'git')
else:
@@ -121,7 +121,7 @@ class StaticCodeAnalysis():
xmlStart = False
with open(filename, 'r') as logfile:
for line in logfile:
ret = re.search('cppcheck version="(?P<version>[0-9\.]+)"', str(line))
ret = re.search(r'cppcheck version="(?P<version>[0-9\.]+)"', str(line))
if ret is not None:
CCR.versions[vId] = ret.group('version')
if re.search('RUN cat cmake_targets/log/cppcheck.xml', str(line)) is not None:

View File

@@ -0,0 +1,266 @@
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 = 208; mnc = 99; 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 = 0;
do_SRS = 0;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# center frequency = 4049.76 MHz
# selected SSB frequency = 4049.76 MHz
absoluteFrequencySSB = 668640; #669984;
dl_frequencyBand = 77;
# frequency point A = 4000.62 MHz
dl_absoluteFrequencyPointA = 666708;
#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 = 77;
#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 = 159;
#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 = 7;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 2;
#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 = -100;
# 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.5"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.209";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.209";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 220;
pucch_TargetSNRx10 = 220;
pusch_FailureThres = 100;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120
pucch0_dtx_threshold = 80;
pusch_dtx_threshold = -100;
tx_amp_backoff_dB = 3;
L1_rx_thread_core = 8;
L1_tx_thread_core = 9;
max_ldpc_iterations = 20;
phase_compensation = 0; # needs to match O-RU configuration
}
);
RUs = (
{
local_rf = "no";
nb_tx = 4;
nb_rx = 4;
att_tx = 0;
att_rx = 0;
bands = [77];
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
sf_extension = 0;
eNB_instances = [0];
ru_thread_core = 10;
sl_ahead = 5;
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:01:01.0");
dpdk_iova_mode = "VA";
system_core = 11;
io_core = 12;
worker_cores = (13);
ru_addr = ("98:ae:71:04:83:e3");
mtu = 9600;
fh_config = ({
T1a_cp_dl = (285, 470);
T1a_cp_ul = (285, 429);
T1a_up = (125, 350);
Ta4 = (110, 180);
ru_config = {
iq_width = 9;
iq_width_prach = 9;
};
});
};

View File

@@ -0,0 +1,28 @@
#this is a configuration file
#used to build real time processing statistics
#for 5G NR phy test (gNB terminate)
Title : Processing Time (us) from datalog_rt_stats.4x4.fhi72.yaml
ColNames :
- Metric
- Average; Max; Count
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
Ref :
tx_fhaul : 40.2
feptx_prec (per port, half_slot) : 12.3
L1 Tx processing : 221.0
DLSCH encoding : 141.0
L1 Rx processing : 332.5
UL segments decoding : 55.2
UL Indication : 0.4
Slot Indication : 14.3
PUSCH inner-receiver : 421.4
DeviationThreshold :
tx_fhaul : 0.25
feptx_prec (per port, half_slot) : 0.25
L1 Tx processing : 0.25
DLSCH encoding : 0.25
L1 Rx processing : 0.25
UL segments decoding : 0.25
UL Indication : 1.00
Slot Indication : 0.50
PUSCH inner-receiver : 0.25

View File

@@ -0,0 +1,52 @@
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
# * this work for additional information regarding copyright ownership.
# * The OpenAirInterface Software Alliance licenses this file to You under
# * the OAI Public License, Version 1.1 (the "License"); you may not use this file
# * except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.openairinterface.org/?page_id=698
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *-------------------------------------------------------------------------------
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# * contact@openairinterface.org
# */
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 24.04
#
#---------------------------------------------------------------------
FROM nvidia/cuda:12.9.1-devel-ubuntu22.04 AS cuda-image
FROM ran-base:develop AS ran-tests
RUN rm -Rf /oai-ran
COPY --from=cuda-image /usr/local/cuda/ /usr/local/cuda/
# Set the LD_LIBRARY_PATH to ensure the system can find the copied libraries.
# This is crucial for applications that use CUDA.
ENV LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/local/cuda/targets/sbsa-linux/lib
ENV PATH=/usr/local/cuda/bin:$PATH
ENV C_INCLUDE_PATH=/usr/local/cuda/include
WORKDIR /oai-ran
COPY . .
WORKDIR /oai-ran/build
RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON -DENABLE_TESTS=ON \
-DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \
-DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \
-DPHYSIM_CHECK_FILES="ThresholdsCuda.cmake" \
-DCUDA_ENABLE=ON \
-DUSE_UNIFIED_MEMORY=ON \
-DUSE_ATS_MEMORY=OFF \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \
.. && \
ninja nr_ulsim nr_dlsim

View File

@@ -62,13 +62,6 @@ import lxml.etree as ET
import logging
import signal
import traceback
logging.basicConfig(
level=logging.DEBUG,
stream=sys.stdout,
format="[%(asctime)s] %(levelname)8s: %(message)s"
)
#-----------------------------------------------------------
@@ -109,41 +102,20 @@ def ExecuteActionWithParam(action, ctx, node):
success = CONTAINERS.BuildRunTests(ctx, node, HTML)
elif action == 'Initialize_eNB':
datalog_rt_stats_file=test.findtext('rt_stats_cfg')
if datalog_rt_stats_file is None:
RAN.datalog_rt_stats_file='datalog_rt_stats.default.yaml'
else:
RAN.datalog_rt_stats_file=datalog_rt_stats_file
RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args')
USRPIPAddress = test.findtext('USRP_IPAddress') or ''
#local variable air_interface
air_interface = test.findtext('air_interface')
if (air_interface is None) or (air_interface.lower() not in ['nr','lte']):
RAN.air_interface = 'lte-softmodem'
else:
RAN.air_interface = air_interface.lower() +'-softmodem'
cmd_prefix = test.findtext('cmd_prefix')
if cmd_prefix is not None: RAN.cmd_prefix = cmd_prefix
success = RAN.InitializeeNB(ctx, node, HTML)
elif action == 'Terminate_eNB':
#retx checkers
string_field = test.findtext('d_retx_th')
if (string_field is not None):
RAN.ran_checkers['d_retx_th'] = [float(x) for x in string_field.split(',')]
string_field=test.findtext('u_retx_th')
if (string_field is not None):
RAN.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')]
#local variable air_interface
air_interface = test.findtext('air_interface')
if (air_interface is None) or (air_interface.lower() not in ['nr','lte']):
RAN.air_interface = 'lte-softmodem'
else:
RAN.air_interface = air_interface.lower() +'-softmodem'
success = RAN.TerminateeNB(ctx, node, HTML)
services = []
analysis = test.find("analysis")
if analysis is not None:
# services: multiple services to analyse, separated by whitespace
services = analysis.findtext("services", default="").split()
# service: individual services to analyze, in case they have whitespace
services = services + [s.text for s in analysis.findall("service")]
success = RAN.TerminateeNB(ctx, node, HTML, services)
elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE':
CiTestObj.ue_ids = test.findtext('id').split(' ')
@@ -216,12 +188,6 @@ def ExecuteActionWithParam(action, ctx, node):
elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace" or action == "Stop_Object":
CONTAINERS.yamlPath = test.findtext('yaml_path')
string_field=test.findtext('d_retx_th')
if (string_field is not None):
CONTAINERS.ran_checkers['d_retx_th'] = [float(x) for x in string_field.split(',')]
string_field=test.findtext('u_retx_th')
if (string_field is not None):
CONTAINERS.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')]
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)
@@ -230,7 +196,14 @@ def ExecuteActionWithParam(action, ctx, node):
elif action == 'Stop_Object':
success = CONTAINERS.StopObject(ctx, node, HTML)
elif action == 'Undeploy_Object':
success = CONTAINERS.UndeployObject(ctx, node, HTML, RAN)
analysis = test.find("analysis")
services = []
if analysis is not None:
# services: multiple services to analyse, separated by whitespace
services = analysis.findtext("services", default="").split()
# service: individual services to analyze, in case they have whitespace
services = services + [s.text for s in analysis.findall("service")]
success = CONTAINERS.UndeployObject(ctx, node, HTML, services)
elif action == 'Create_Workspace':
if force_local:
# Do not create a working directory when running locally. Current repo directory will be used
@@ -280,21 +253,20 @@ def ExecuteActionWithParam(action, ctx, node):
images = test.findtext('images').split()
success = CLUSTER.PullClusterImage(HTML, node, images, tag_prefix=tag_prefix)
elif action == 'AnalyzeRTStats':
yaml = test.findtext('stats_cfg')
success = RAN.AnalyzeRTStats(HTML, node, ctx, yaml)
elif action == 'AnalyzeRTStats_Object':
yaml = test.findtext('stats_cfg')
success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml)
else:
logging.warning(f"unknown action {action}, skip step")
success = True # by default, we skip the step and print a warning
return success
#check if given test is in list
#it is in list if one of the strings in 'list' is at the beginning of 'test'
def test_in_list(test, list):
for check in list:
check=check.replace('+','')
if (test.startswith(check)):
return True
return False
test_runner_abort = False
def receive_signal(signum, frame):
global test_runner_abort
@@ -349,7 +321,12 @@ CLUSTER = cls_cluster.Cluster()
import args_parse
# Force local execution, move all execution targets to localhost
force_local = False
mode, force_local = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER)
mode, force_local, date_fmt = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER)
fmt = "%(levelname)8s: %(message)s"
if date_fmt:
fmt = "[%(asctime)s] %(levelname)s %(message)s"
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout, format=fmt, datefmt=date_fmt,)
#-----------------------------------------------------------
# mode amd XML class (action) analysis
@@ -367,18 +344,7 @@ elif re.match('^TerminateSPGW$', mode, re.IGNORECASE):
elif re.match('^LogCollectBuild$', mode, re.IGNORECASE):
logging.warning("Option LogCollectBuild ignored")
elif re.match('^LogCollecteNB$', mode, re.IGNORECASE):
if RAN.eNBSourceCodePath == '':
HELP.GenericHelp(CONST.Version)
sys.exit('Insufficient Parameter')
if os.path.isdir('cmake_targets/log'):
cmd = 'zip -r enb.log.' + RAN.BuildId + '.zip cmake_targets/log'
logging.info(cmd)
try:
zipStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=60)
except subprocess.CalledProcessError as e:
logging.error("Command '{}' returned non-zero exit status {}.".format(e.cmd, e.returncode))
logging.error("Error output:\n{}".format(e.output))
sys.exit(0)
logging.warning("Option LogCollecteNB ignored")
elif re.match('^LogCollectHSS$', mode, re.IGNORECASE):
logging.warning("Option LogCollectHSS ignored")
elif re.match('^LogCollectMME$', mode, re.IGNORECASE):

View File

@@ -31,21 +31,16 @@
#-----------------------------------------------------------
# Import
#-----------------------------------------------------------
import sys # arg
import re # reg
import logging
import os
import time
import yaml
import cls_cmd
#-----------------------------------------------------------
# OAI Testing modules
#-----------------------------------------------------------
import cls_cmd
import helpreadme as HELP
import constants as CONST
import cls_analysis
from cls_ci_helper import archiveArtifact
#-----------------------------------------------------------
@@ -63,16 +58,9 @@ class RANManagement():
self.eNBSourceCodePath = ''
self.Initialize_eNB_args = ''
self.imageKind = ''
self.air_interface = ''
self.eNBOptions = ['', '', '']
self.eNBmbmsEnables = [False, False, False]
self.eNBstatuses = [-1, -1, -1]
self.runtime_stats= ''
self.datalog_rt_stats={}
self.datalog_rt_stats_file='datalog_rt_stats.default.yaml'
self.USRPIPAddress = ''
#checkers from xml
self.ran_checkers={}
self.cmd_prefix = '' # prefix before {lte,nr}-softmodem
self.node = ''
self.command = ''
@@ -102,7 +90,7 @@ class RANManagement():
logfile = f'{lSourcePath}/cmake_targets/enb.log'
cmd.cd(f"{lSourcePath}/cmake_targets/") # important: set wd so nrL1_stats.log etc are logged here
cmd.run(f'sudo -E stdbuf -o0 {self.cmd_prefix} {lSourcePath}/cmake_targets/ran_build/build/{self.air_interface} -O {lSourcePath}/{full_config_file} {extra_options} > {logfile} 2>&1 &')
cmd.run(f'sudo -E stdbuf -o0 {self.cmd_prefix} {lSourcePath}/cmake_targets/ran_build/build/nr-softmodem -O {lSourcePath}/{full_config_file} {extra_options} > {logfile} 2>&1 &')
if extra_options != '':
self.eNBOptions = extra_options
@@ -116,12 +104,12 @@ class RANManagement():
enbDidSync = True
break
if not enbDidSync:
cmd.run(f'sudo killall -9 {self.air_interface}') # in case it did not stop automatically
cmd.run(f'sudo killall -9 nr-softmodem') # in case it did not stop automatically
archiveArtifact(cmd, ctx, logfile)
cmd.close()
msg = f'{self.cmd_prefix} {self.air_interface} -O {config_file} {extra_options}'
msg = f'{self.cmd_prefix} nr-softmodem -O {config_file} {extra_options}'
if enbDidSync:
logging.debug('\u001B[1m Initialize eNB/gNB Completed\u001B[0m')
HTML.CreateHtmlTestRowQueue(msg, 'OK', [])
@@ -131,7 +119,7 @@ class RANManagement():
return enbDidSync
def TerminateeNB(self, ctx, node, HTML):
def TerminateeNB(self, ctx, node, HTML, to_analyze):
logging.debug('Stopping eNB/gNB on server: ' + node)
lSourcePath = self.eNBSourceCodePath
cmd = cls_cmd.getConnection(node)
@@ -146,14 +134,13 @@ class RANManagement():
if result is not None:
cmd.run('sudo -S killall --signal SIGKILL -r .*-softmodem')
time.sleep(5)
HTML.CreateHtmlTestRowQueue(node, 'OK', ['Undeployment successful'])
# see InitializeeNB()
logfile = f'{lSourcePath}/cmake_targets/enb.log'
logdir = os.path.dirname(logfile)
file = archiveArtifact(cmd, ctx, logfile)
archiveArtifact(cmd, ctx, f"{logdir}/nrL1_stats.log")
archiveArtifact(cmd, ctx, f"{logdir}/nrMAC_stats.log")
cmd.close()
if file is None:
logging.debug('\u001B[1;37;41m Could not copy xNB logfile to analyze it! \u001B[0m')
@@ -162,633 +149,21 @@ class RANManagement():
return False
logging.debug('\u001B[1m Analyzing xNB logfile \u001B[0m ' + file)
logStatus = self.AnalyzeLogFile_eNB(file, HTML, self.ran_checkers)
if logStatus < 0:
HTML.CreateHtmlTestRow('N/A', 'KO', logStatus)
else:
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
service_desc = {}
service_desc["nr-softmodem"] = {'returncode': 0, 'logfile': file}
success = cls_analysis.AnalyzeServices(HTML, service_desc, to_analyze)
return success
#display rt stats for gNB only
if len(self.datalog_rt_stats) != 0:
HTML.CreateHtmlDataLogTable(self.datalog_rt_stats)
def AnalyzeRTStats(self, HTML, node, ctx, thresholds):
logging.info(f'Analyzing realtime stats from server: {node}')
lSourcePath = self.eNBSourceCodePath
return logStatus >= 0
logdir = f'{lSourcePath}/cmake_targets'
with cls_cmd.getConnection(node) as cmd:
l1_file = archiveArtifact(cmd, ctx, f"{logdir}/nrL1_stats.log")
mac_file = archiveArtifact(cmd, ctx, f"{logdir}/nrMAC_stats.log")
def _analyzeUeRetx(self, rounds, checkers, regex):
if len(rounds) == 0 or len(checkers) == 0:
logging.warning(f'warning: rounds={rounds} checkers={checkers}')
return []
perc = list(0 for i in checkers) # results in %
stats = list(False for i in checkers) # status if succeeded
tmp = re.match(regex, rounds)
if tmp is None:
logging.error('_analyzeUeRetx: did not match regex for DL retx analysis')
return stats
retx_data = [float(x) for x in tmp.groups()]
for i in range(0, len(perc)):
#case where numerator > denumerator with denum ==0 is disregarded, cannot hapen in principle, will lead to 0%
perc[i] = 0 if (retx_data[i] == 0) else 100 * retx_data[i + 1] / retx_data[i]
#treating % > 100 , % > requirement
stats[i] = perc[i] <= 100 and perc[i] <= checkers[i]
return stats
def AnalyzeLogFile_eNB(self, eNBlogFile, HTML, checkers={}):
if (not os.path.isfile(eNBlogFile)):
return -1
enb_log_file = open(eNBlogFile, 'r')
exitSignalReceived = False
foundAssertion = False
msgAssertion = ''
msgLine = 0
foundSegFault = False
foundRealTimeIssue = False
foundRealTimeIssue_cnt = 0
rrcSetupComplete = 0
rrcReleaseRequest = 0
rrcReconfigRequest = 0
rrcReconfigComplete = 0
rrcReestablishRequest = 0
rrcReestablishComplete = 0
rrcReestablishReject = 0
rlcDiscardBuffer = 0
rachCanceledProcedure = 0
uciStatMsgCount = 0
pdcpFailure = 0
ulschFailure = 0
ulschAllocateCCEerror = 0
uplinkSegmentsAborted = 0
ulschReceiveOK = 0
gnbRxTxWakeUpFailure = 0
gnbTxWriteThreadEnabled = False
cdrxActivationMessageCount = 0
dropNotEnoughRBs = 0
mbmsRequestMsg = 0
htmleNBFailureMsg = ''
isRRU = False
isSlave = False
slaveReceivesFrameResyncCmd = False
X2HO_state = CONST.X2_HO_REQ_STATE__IDLE
X2HO_inNbProcedures = 0
X2HO_outNbProcedures = 0
global_status = CONST.ALL_PROCESSES_OK
# Runtime statistics
runTime = ''
userTime = ''
systemTime = ''
maxPhyMemUsage = ''
nbContextSwitches = ''
#NSA FR1 check
NSA_RAPROC_PUSCH_check = 0
#dlsch and ulsch statistics (dictionary)
dlsch_ulsch_stats = {}
#real time statistics (dictionary)
real_time_stats = {}
#count "problem receiving samples" msg
pb_receiving_samples_cnt = 0
#count "removing UE" msg
removing_ue = 0
#count"X2AP-PDU"
x2ap_pdu = 0
#gnb specific log markers
gnb_markers ={'SgNBReleaseRequestAcknowledge': [],'FAILURE': [], 'scgFailureInformationNR-r15': [], 'SgNBReleaseRequest': [], 'Detected UL Failure on PUSCH':[]}
nodeB_prefix_found = False
RealTimeProcessingIssue = False
retx_status = {}
nrRrcRcfgComplete = 0
harqFeedbackPast = 0
showedByeMsg = False # last line is Bye. -> stopped properly
line_cnt=0 #log file line counter
for line in enb_log_file.readlines():
line_cnt+=1
# Detection of eNB/gNB from a container log
result = re.search('Starting eNB soft modem', str(line))
if result is not None:
nodeB_prefix_found = True
nodeB_prefix = 'e'
result = re.search('Starting gNB soft modem', str(line))
if result is not None:
nodeB_prefix_found = True
nodeB_prefix = 'g'
result = re.search('Run time:' ,str(line))
# Runtime statistics
result = re.search('Run time:' ,str(line))
if result is not None:
runTime = str(line).strip()
if runTime != '':
result = re.search('Time executing user inst', str(line))
if result is not None:
fields=line.split(':')
userTime = 'userTime : ' + fields[1].replace('\n','')
result = re.search('Time executing system inst', str(line))
if result is not None:
fields=line.split(':')
systemTime = 'systemTime : ' + fields[1].replace('\n','')
result = re.search('Max. Phy. memory usage:', str(line))
if result is not None:
fields=line.split(':')
maxPhyMemUsage = 'maxPhyMemUsage : ' + fields[1].replace('\n','')
result = re.search('Number of context switch.*process origin', str(line))
if result is not None:
fields=line.split(':')
nbContextSwitches = 'nbContextSwitches : ' + fields[1].replace('\n','')
if X2HO_state == CONST.X2_HO_REQ_STATE__IDLE:
result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line))
if result is not None:
X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ
result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line))
if result is not None:
X2HO_state = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK
if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ:
result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line))
if result is not None:
X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE
if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE:
result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line))
if result is not None:
X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ
if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ:
result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line))
if result is not None:
X2HO_state = CONST.X2_HO_REQ_STATE__IDLE
X2HO_inNbProcedures += 1
if X2HO_state == CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK:
result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line))
if result is not None:
X2HO_state = CONST.X2_HO_REQ_STATE__IDLE
X2HO_outNbProcedures += 1
if self.eNBOptions[0] != '':
res1 = re.search('max_rxgain (?P<requested_option>[0-9]+)', self.eNBOptions[0])
res2 = re.search('max_rxgain (?P<applied_option>[0-9]+)', str(line))
if res1 is not None and res2 is not None:
requested_option = int(res1.group('requested_option'))
applied_option = int(res2.group('applied_option'))
if requested_option == applied_option:
htmleNBFailureMsg += '<span class="glyphicon glyphicon-ok-circle"></span> Command line option(s) correctly applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.eNBOptions[0] + '\n\n'
else:
htmleNBFailureMsg += '<span class="glyphicon glyphicon-ban-circle"></span> Command line option(s) NOT applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.eNBOptions[0] + '\n\n'
result = re.search('Exiting OAI softmodem|Caught SIGTERM, shutting down', str(line))
if result is not None:
exitSignalReceived = True
result = re.search('[Ss]egmentation [Ff]ault', str(line))
if result is not None and not exitSignalReceived:
foundSegFault = True
result = re.search('[Cc]ore [dD]ump', str(line))
if result is not None and not exitSignalReceived:
foundSegFault = True
result = re.search('[Aa]ssertion', str(line))
if result is not None and not exitSignalReceived:
foundAssertion = True
result = re.search('LLL', str(line))
if result is not None and not exitSignalReceived:
foundRealTimeIssue = True
foundRealTimeIssue_cnt += 1
if foundAssertion and (msgLine < 3):
msgLine += 1
msgAssertion += str(line)
result = re.search('Setting function for RU', str(line))
if result is not None:
isRRU = True
if isRRU:
result = re.search('RU 0 is_slave=yes', str(line))
if result is not None:
isSlave = True
if isSlave:
result = re.search('Received RRU_frame_resynch command', str(line))
if result is not None:
slaveReceivesFrameResyncCmd = True
result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line))
if result is not None:
rrcSetupComplete += 1
result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line))
if result is not None: rrcReleaseRequest += 1
result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line))
if result is not None:
rrcReconfigRequest += 1
result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line))
if result is not None:
rrcReconfigComplete += 1
result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line))
if result is not None:
rrcReestablishRequest += 1
result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line))
if result is not None:
rrcReestablishComplete += 1
result = re.search('LTE_RRCConnectionReestablishmentReject', str(line))
if result is not None:
rrcReestablishReject += 1
result = re.search('CDRX configuration activated after RRC Connection', str(line))
if result is not None:
cdrxActivationMessageCount += 1
result = re.search('uci->stat', str(line))
if result is not None:
uciStatMsgCount += 1
result = re.search('PDCP.*Out of Resources.*reason', str(line))
if result is not None:
pdcpFailure += 1
result = re.search('could not wakeup gNB rxtx process', str(line))
if result is not None:
gnbRxTxWakeUpFailure += 1
result = re.search('tx write thread ready', str(line))
if result is not None:
gnbTxWriteThreadEnabled = True
result = re.search('ULSCH in error in round|ULSCH 0 in error', str(line))
if result is not None:
ulschFailure += 1
result = re.search('ERROR ALLOCATING CCEs', str(line))
if result is not None:
ulschAllocateCCEerror += 1
result = re.search('uplink segment error.*aborted [1-9] segments', str(line))
if result is not None:
uplinkSegmentsAborted += 1
result = re.search('ULSCH received ok', str(line))
if result is not None:
ulschReceiveOK += 1
result = re.search('BAD all_segments_received', str(line))
if result is not None:
rlcDiscardBuffer += 1
result = re.search('Canceled RA procedure for UE rnti', str(line))
if result is not None:
rachCanceledProcedure += 1
result = re.search('dropping, not enough RBs', str(line))
if result is not None:
dropNotEnoughRBs += 1
if self.eNBmbmsEnables[0]:
result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line))
if result is not None:
mbmsRequestMsg += 1
#FR1 NSA test : add new markers to make sure gNB is used
result = re.search('\[gNB [0-9]+\]\[RAPROC\] PUSCH with TC_RNTI 0x[0-9a-fA-F]+ received correctly, adding UE MAC Context RNTI 0x[0-9a-fA-F]+', str(line))
if result is not None:
NSA_RAPROC_PUSCH_check = 1
# Collect information on UE DLSCH and ULSCH statistics
keys = {'dlsch_rounds','ulsch_rounds'}
for k in keys:
result = re.search(k, line)
if result is None:
continue
result = re.search('UE (?:RNTI )?([0-9a-f]{4})', line)
if result is None:
logging.error(f'did not find RNTI while matching key {k}')
continue
rnti = result.group(1)
#remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char
if not rnti in dlsch_ulsch_stats: dlsch_ulsch_stats[rnti] = {}
dlsch_ulsch_stats[rnti][k]=re.sub(r'^.*\]\s+', r'' , line.rstrip())
result = re.search('Received NR_RRCReconfigurationComplete from UE', str(line))
if result is not None:
nrRrcRcfgComplete += 1
result = re.search('HARQ feedback is in the past', str(line))
if result is not None:
harqFeedbackPast += 1
#count "problem receiving samples" msg
result = re.search('\[PHY\]\s+problem receiving samples', str(line))
if result is not None:
pb_receiving_samples_cnt += 1
#count "Removing UE" msg
result = re.search('\[MAC\]\s+Removing UE', str(line))
if result is not None:
removing_ue += 1
#count "X2AP-PDU"
result = re.search('X2AP-PDU', str(line))
if result is not None:
x2ap_pdu += 1
#gnb markers logging
for k in gnb_markers:
result = re.search(k, line)
if result is not None:
gnb_markers[k].append(line_cnt)
# check whether e/gNB log finishes with "Bye." message
showedByeMsg |= re.search(r'^Bye.\n', str(line), re.MULTILINE) is not None
enb_log_file.close()
#the following part takes the *_stats.log files as source (not the stdout log file)
#the datalog config file has to be loaded
datalog_rt_stats_file=self.datalog_rt_stats_file
if (os.path.isfile(datalog_rt_stats_file)):
yaml_file=datalog_rt_stats_file
elif (os.path.isfile('ci-scripts/'+datalog_rt_stats_file)):
yaml_file='ci-scripts/'+datalog_rt_stats_file
else:
logging.error("Datalog RT stats yaml file cannot be found")
sys.exit("Datalog RT stats yaml file cannot be found")
with open(yaml_file,'r') as f:
datalog_rt_stats = yaml.load(f,Loader=yaml.FullLoader)
rt_keys = datalog_rt_stats['Ref'] #we use the keys from the Ref field
# nrL1_stats.log/nrMAC_stats.log should be in the same directory as main log file
# currently the link is only implicit as below based on pattern matching
# I will rework this to give the file explicitly
l1_stats_fn = re.sub(r'-enb.log$', '-nrL1_stats.log', eNBlogFile)
mac_stats_fn = re.sub(r'-enb.log$', '-nrMAC_stats.log', eNBlogFile)
if os.path.isfile(l1_stats_fn) and os.path.isfile(mac_stats_fn):
# don't use CI-nrL1_stats.log, as this will increase the processing time for
# no reason, we just need the last occurence
nrL1_stats = open(l1_stats_fn, 'r')
nrMAC_stats = open(mac_stats_fn, 'r')
for line in nrL1_stats.readlines():
for k in rt_keys:
result = re.search(k, line)
if result is not None:
#remove 1- all useless char before relevant info 2- trailing char
tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex
if tmp!=None:
real_time_stats[k]=tmp.group(1)
for line in nrMAC_stats.readlines():
for k in rt_keys:
result = re.search(k, line)
if result is not None:
#remove 1- all useless char before relevant info 2- trailing char
tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex
if tmp!=None:
real_time_stats[k]=tmp.group(1)
nrL1_stats.close()
nrMAC_stats.close()
else:
logging.debug(f"NR Stats files for RT analysis not found: {l1_stats_fn}, {mac_stats_fn}")
#stdout log file and stat log files analysis completed
logging.debug(' File analysis (stdout, stats) completed')
#post processing depending on the node type
if not nodeB_prefix_found:
if self.air_interface == 'lte-softmodem':
nodeB_prefix = 'e'
else:
nodeB_prefix = 'g'
if nodeB_prefix == 'g':
if ulschReceiveOK > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(ulschReceiveOK) + ' "ULSCH received ok" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if gnbRxTxWakeUpFailure > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(gnbRxTxWakeUpFailure) + ' "could not wakeup gNB rxtx process" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if gnbTxWriteThreadEnabled:
statMsg = nodeB_prefix + 'NB ran with TX Write thread enabled'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if nrRrcRcfgComplete > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(nrRrcRcfgComplete) + ' "Received NR_RRCReconfigurationComplete from UE" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if harqFeedbackPast > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(harqFeedbackPast) + ' "HARQ feedback is in the past" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
#FR1 NSA test : add new markers to make sure gNB is used
if NSA_RAPROC_PUSCH_check:
statMsg = '[RAPROC] PUSCH with TC_RNTI message check for ' + nodeB_prefix + 'NB : PASS '
htmlMsg = statMsg+'\n'
else:
statMsg = '[RAPROC] PUSCH with TC_RNTI message check for ' + nodeB_prefix + 'NB : FAIL or not relevant'
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
#problem receiving samples log
statMsg = '[PHY] problem receiving samples msg count = '+str(pb_receiving_samples_cnt)
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
#gnb markers
statMsg = 'logfile line count = ' + str(line_cnt)
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
if len(gnb_markers['SgNBReleaseRequestAcknowledge'])!=0:
statMsg = 'SgNBReleaseRequestAcknowledge = ' + str(len(gnb_markers['SgNBReleaseRequestAcknowledge'])) + ' occurences , starting line ' + str(gnb_markers['SgNBReleaseRequestAcknowledge'][0])
else:
statMsg = 'SgNBReleaseRequestAcknowledge = ' + str(len(gnb_markers['SgNBReleaseRequestAcknowledge'])) + ' occurences'
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
statMsg = 'FAILURE = ' + str(len(gnb_markers['FAILURE'])) + ' occurences'
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
statMsg = 'Detected UL Failure on PUSCH = ' + str(len(gnb_markers['Detected UL Failure on PUSCH'])) + ' occurences'
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
#ulsch and dlsch statistics and checkers
for ue in dlsch_ulsch_stats:
dlulstat = dlsch_ulsch_stats[ue]
#print statistics into html
statMsg=''
for key in dlulstat:
statMsg += dlulstat[key] + '\n'
logging.debug(dlulstat[key])
htmleNBFailureMsg += statMsg
retx_status[ue] = {}
dlcheckers = [] if 'd_retx_th' not in checkers else checkers['d_retx_th']
retx_status[ue]['dl'] = self._analyzeUeRetx(dlulstat['dlsch_rounds'], dlcheckers, r'^.*dlsch_rounds\s+(\d+)\/(\d+)\/(\d+)\/(\d+),\s+dlsch_errors\s+(\d+)')
ulcheckers = [] if 'u_retx_th' not in checkers else checkers['u_retx_th']
retx_status[ue]['ul'] = self._analyzeUeRetx(dlulstat['ulsch_rounds'], ulcheckers, r'^.*ulsch_rounds\s+(\d+)\/(\d+)\/(\d+)\/(\d+),\s+ulsch_errors\s+(\d+)')
#real time statistics
datalog_rt_stats['Data']={}
if len(real_time_stats)!=0: #check if dictionary is not empty
for k in real_time_stats:
tmp=re.match(r'^(?P<metric>.*):\s+(?P<avg>\d+\.\d+) us;\s+(?P<count>\d+);\s+(?P<max>\d+\.\d+) us;',real_time_stats[k])
if tmp is not None:
metric=tmp.group('metric')
avg=float(tmp.group('avg'))
max=float(tmp.group('max'))
count=int(tmp.group('count'))
datalog_rt_stats['Data'][metric]=["{:.0f}".format(avg),"{:.0f}".format(max),"{:d}".format(count),"{:.2f}".format(avg/datalog_rt_stats['Ref'][metric])]
#once all metrics are collected, store the data as a class attribute to build a dedicated HTML table afterward
self.datalog_rt_stats=datalog_rt_stats
#check if there is a fail => will render the test as failed
for k in datalog_rt_stats['Data']:
valnorm = float(datalog_rt_stats['Data'][k][3])
dev = datalog_rt_stats['DeviationThreshold'][k]
if valnorm > 1.0 + dev or valnorm < 1.0 - dev: # condition for fail : avg/ref deviates by more than "deviation threshold"
logging.debug(f'\u001B[1;30;43m normalized datalog_rt_stats metric {k}={valnorm} deviates by more than {dev}\u001B[0m')
RealTimeProcessingIssue = True
else:
statMsg = 'No real time stats found in the log file\n'
logging.debug('No real time stats found in the log file')
htmleNBFailureMsg += statMsg
if not showedByeMsg:
logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB did not show "Bye." message at end, it likely did not stop properly! \u001B[0m')
htmleNBFailureMsg += 'No Bye. message found, did not stop properly\n'
global_status = CONST.ENB_SHUTDOWN_NO_BYE
else:
logging.debug('"Bye." message found at end.')
else:
#Removing UE log
statMsg = '[MAC] Removing UE msg count = '+str(removing_ue)
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
#X2AP-PDU log
statMsg = 'X2AP-PDU msg count = '+str(x2ap_pdu)
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
#nsa markers
statMsg = 'logfile line count = ' + str(line_cnt)
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
if len(gnb_markers['SgNBReleaseRequest'])!=0:
statMsg = 'SgNBReleaseRequest = ' + str(len(gnb_markers['SgNBReleaseRequest'])) + ' occurences , starting line ' + str(gnb_markers['SgNBReleaseRequest'][0])
else:
statMsg = 'SgNBReleaseRequest = ' + str(len(gnb_markers['SgNBReleaseRequest'])) + ' occurences'
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
statMsg = 'scgFailureInformationNR-r15 = ' + str(len(gnb_markers['scgFailureInformationNR-r15'])) + ' occurences'
htmlMsg = statMsg+'\n'
logging.debug(statMsg)
htmleNBFailureMsg += htmlMsg
for ue in retx_status:
msg = f"retransmissions for UE {ue}: DL {retx_status[ue]['dl']} UL {retx_status[ue]['ul']}"
if False in retx_status[ue]['dl'] or False in retx_status[ue]['ul']:
msg = 'Failure: ' + msg
logging.error(f'\u001B[1;37;41m {msg}\u001B[0m')
htmleNBFailureMsg += f'{msg}\n'
global_status = CONST.ENB_RETX_ISSUE
else:
logging.debug(msg)
if RealTimeProcessingIssue:
logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with real time processing issue! \u001B[0m')
htmleNBFailureMsg += 'Fail due to real time processing issue\n'
global_status = CONST.ENB_REAL_TIME_PROCESSING_ISSUE
if uciStatMsgCount > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if pdcpFailure > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if ulschFailure > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if ulschAllocateCCEerror > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(ulschAllocateCCEerror) + ' "eNB_dlsch_ulsch_scheduler(); ERROR ALLOCATING CCEs" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if uplinkSegmentsAborted > 0:
statMsg = nodeB_prefix + 'NB showed ' + str(uplinkSegmentsAborted) + ' "uplink segment error 0/2, aborted * segments" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if dropNotEnoughRBs > 0:
statMsg = 'eNB showed ' + str(dropNotEnoughRBs) + ' "dropping, not enough RBs" message(s)'
logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
htmleNBFailureMsg += statMsg + '\n'
if rrcSetupComplete > 0:
rrcMsg = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if rrcReleaseRequest > 0:
rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if rrcReconfigRequest > 0 or rrcReconfigComplete > 0:
rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0:
rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if self.eNBmbmsEnables[0]:
if mbmsRequestMsg > 0:
rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if X2HO_inNbProcedures > 0:
rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if X2HO_outNbProcedures > 0:
rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if self.eNBOptions[0] != '':
res1 = re.search('drx_Config_present prSetup', self.eNBOptions[0])
if res1 is not None:
if cdrxActivationMessageCount > 0:
rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)'
logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
else:
rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration'
logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m')
htmleNBFailureMsg += rrcMsg + '\n'
if rachCanceledProcedure > 0:
rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)'
logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m')
htmleNBFailureMsg += rachMsg + '\n'
if isRRU:
if isSlave:
if slaveReceivesFrameResyncCmd:
rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU'
logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m')
htmleNBFailureMsg += rruMsg + '\n'
else:
rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU'
logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m')
htmleNBFailureMsg += rruMsg + '\n'
global_status = CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED
if foundSegFault:
logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m')
global_status = CONST.ENB_PROCESS_SEG_FAULT
if foundAssertion:
logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m')
htmleNBFailureMsg += msgAssertion
global_status = CONST.ENB_PROCESS_ASSERTION
if foundRealTimeIssue:
logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m')
htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues! COUNT = '+ str(foundRealTimeIssue_cnt) +' lines\n'
if rlcDiscardBuffer > 0:
rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)'
logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m')
htmleNBFailureMsg += rlcMsg + '\n'
global_status = CONST.ENB_PROCESS_REALTIME_ISSUE
HTML.htmleNBFailureMsg=htmleNBFailureMsg
# Runtime statistics for console output and HTML
if runTime != '':
logging.debug(runTime)
logging.debug(userTime)
logging.debug(systemTime)
logging.debug(maxPhyMemUsage)
logging.debug(nbContextSwitches)
self.runtime_stats='<pre>'+runTime + '\n'+ userTime + '\n' + systemTime + '\n' + maxPhyMemUsage + '\n' + nbContextSwitches+'</pre>'
return global_status
logging.info(f"check against thresholds from {thresholds}")
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, l1_file, mac_file)
HTML.CreateHtmlDataLogTable(datalog_rt_stats)
return success

View File

@@ -1,6 +1,5 @@
#!/bin/bash
set -e
SHORT_COMMIT_SHA=$(git rev-parse --short=8 HEAD)
COMMIT_SHA=$(git rev-parse HEAD)
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
@@ -13,6 +12,8 @@ if [ $# -eq 0 ]
exit 1
fi
set -x
# The script assumes you've build the following images:
#
# docker build . -f docker/Dockerfile.gNB.ubuntu -t oai-gnb
@@ -31,15 +32,15 @@ docker tag oai-nr-cuup oai-ci/oai-nr-cuup:develop-${SHORT_COMMIT_SHA}
python3 main.py --mode=InitiateHtml --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
--ranTargetBranch=NONE \
--XMLTestFile=xml_files/${TESTCASE} --local
--XMLTestFile=xml_files/${TESTCASE} --local --datefmt="%H:%M:%S"
python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
--ranTargetBranch=NONE \
--eNBSourceCodePath=${REPO_PATH} \
--XMLTestFile=${TESTCASE} --local
--XMLTestFile=${TESTCASE} --local --datefmt="%H:%M:%S"
RET=$?
python3 main.py --mode=FinalizeHtml --local
python3 main.py --mode=FinalizeHtml --local --datefmt="%H:%M:%S"
exit ${RET}

View File

@@ -0,0 +1,46 @@
#!/bin/bash
function die() { echo $@; exit 1; }
[ $# -ge 1 ] || die "usage: $0 <directory> [ctest-options]"
IMAGE=ran-physimtests:ci-temp
CONTAINER=ran-physimtests
function cleanup-docker() {
docker stop ${CONTAINER}
docker rm ${CONTAINER}
docker rmi ${IMAGE}
docker volume prune --force
}
trap cleanup-docker EXIT
set -x
DIR=$1
RESULT_DIR=${DIR}/
shift
CTEST_OPT=$@
# build physims
docker build --progress=plain --tag ${IMAGE} --file ${DIR}/ci-scripts/docker/Dockerfile.physim.cuda.ubuntu ${DIR} &>> ${RESULT_DIR}/physim_log.txt
if [ $? -ne 0 ]; then
echo "build of physims failed"
exit 1
fi
# get a JSON description of all tests to run
docker run -a STDOUT --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --rm --name ${CONTAINER} ${IMAGE} ctest ${CTEST_OPT} --show-only=json-v1 &> ${RESULT_DIR}/desc-tests.json
JSON_RES=$?
# run the actual tests: we don't suppy --rm as we have to copy the files
# similar to unit tests, we can't mount the file where we write physims-5g-run.xml to
# as it would write a file as root, but this script is run as a normal user
docker run -a STDOUT --gpus all --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --name ${CONTAINER} ${IMAGE} ctest ${CTEST_OPT} --output-junit results-run.xml --test-output-size-passed 100000 --test-output-size-failed 100000 &>> ${RESULT_DIR}/physim_log.txt
RUN_RES=$?
docker cp ${CONTAINER}:/oai-ran/build/results-run.xml ${RESULT_DIR}/
docker cp ${CONTAINER}:/oai-ran/build/Testing/Temporary/LastTestsFailed.log ${RESULT_DIR}/
docker cp ${CONTAINER}:/oai-ran/build/Testing/Temporary/LastTest.log ${RESULT_DIR}/
# if both were successful, return 0
# TODO not sure
#[[ $JSON_RES -eq 0 && $RUN_RES -eq 0 ]] && exit 0
exit 0

View File

@@ -10,12 +10,15 @@ directory, i.e., `ci-scripts/`, and run
To run individual unit tests, start them like so:
python tests/analysis.py -v
python tests/build.py -v
python tests/cmd.py -v
python tests/corenetwork.py -v
python tests/deployment.py -v
python tests/iperf-analysis.py -v
python tests/log-analysis.py -v
python tests/ping-iperf.py -v
python tests/pull-clean-int-registry.py -v
The logs will indicate if all tests passed. `tests/deployment.py` requires
these images to be present:

View File

@@ -0,0 +1,71 @@
import sys
import logging
logging.basicConfig(
level=logging.DEBUG,
stream=sys.stdout,
format="[%(asctime)s] %(levelname)8s: %(message)s"
)
import os
import unittest
import yaml
sys.path.append('./') # to find OAI imports below
import cls_analysis
import cls_oai_html
import constants
class TestAnalysis(unittest.TestCase):
def setUp(self):
self.html = cls_oai_html.HTMLManagement()
self.html.testCaseId = "000000"
self.maxDiff = 10000 # to compare long files below
def test_gnb_phytest(self):
rtsf = "datalog_rt_stats.100.2x2.yaml"
l1f = "tests/analysis/gnb_phytest.success.nrL1.log"
macf = "tests/analysis/gnb_phytest.success.nrMAC.log"
status, s = cls_analysis.Analysis.analyze_rt_stats(rtsf, l1f, macf)
self.assertTrue(status)
self.assertEqual(s['Title'], "Processing Time (us) from datalog_rt_stats.100.2x2.yaml")
self.assertEqual(s['ColNames'], ["Metric", "Average; Max; Count", "Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)"])
with open(rtsf, 'r') as f:
rt_stats = yaml.load(f, Loader=yaml.FullLoader)
# check that analyze_rt_stats() picked up all Ref/DeviationThreshold values from yaml file, e.g.
# s['Ref']['L1 Tx processing'] == corresponding value in yaml
# s['DeviationThreshold']['L1 Tx processing'] == corresponding value in yaml
for k, v in rt_stats['Ref'].items():
self.assertEqual(s['Ref'][k], v)
for k, v in rt_stats['DeviationThreshold'].items():
self.assertEqual(s['DeviationThreshold'][k], v)
for k, v in s['Ref'].items():
self.assertEqual(v, rt_stats['Ref'][k])
for k, v in s['DeviationThreshold'].items():
self.assertEqual(v, rt_stats['DeviationThreshold'][k])
self.assertEqual(s['Data']['L1 Tx processing'], ['476', '872', '102933', '1.00'])
self.assertEqual(s['Data']['DLSCH encoding'], ['216', '544', '77201', '1.08'])
self.assertEqual(s['Data']['L1 Rx processing'], ['488', '868', '38598', '0.92'])
self.assertEqual(s['Data']['UL Indication'], ['1', '10', '38598', '0.76'])
self.assertEqual(s['Data']['Slot Indication'], ['18', '94', '128667', '1.38'])
self.assertEqual(s['Data']['PUSCH inner-receiver'], ['307', '530', '25730', '0.85'])
self.assertEqual(s['Data']['feprx'], ['169', '310', '38600', '1.12'])
self.assertEqual(s['Data']['feptx_ofdm (per port, half_slot)'], ['56', '88', '102933', '0.98'])
self.assertEqual(s['Data']['feptx_total'], ['148', '299', '102933', '1.00'])
# TODO this one is not found, the CI does not recover this??
#self.assertEqual(s['Data']['DL & UL scheduling timing'], ['17', '97', '159371', '1.14'])
def test_analze_services_no_service(self):
service_desc = {} # nothing to analyze
to_analyze = ["testserv"] # some service requested to be analyze that does not exist
status = cls_analysis.AnalyzeServices(self.html, service_desc, to_analyze)
self.assertFalse(status)
# TODO this does not work: we don't evaluate return codes yet
#def test_analze_service_exit_nonnull(self):
# service_desc = {}
# service_desc["testserv"] = {'returncode': 129, 'logfile': 'tests/log-analysis/empty.log'}
# to_analyze = ["testserv"] # some service requested to be analyze that does not exist
# status = cls_analysis.AnalyzeServices(self.html, service_desc, to_analyze)
# self.assertFalse(status)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,37 @@
Blacklisted PRBs 0/273
-5.-6.-4.-4.-4.-6.-6.-6.-8.-6.-6.-4.-4.-4.-3.-6.-6.-11.-8.-8.-5.-4.-5.-4.-5.
-6.-11.-11.-8.-8.-5.-5.-4.-4.-6.-8.-11.-11.-8.-8.-6.-5.-6.-6.-8.-11.-11.-11.-8.-6.
-6.-6.-6.-11.-11.-11.-11.-11.-11.-6.-6.-6.-8.-3.-11.-11.-11.-8.-8.-6.-6.-6.-11.-11.-11.
-11.-8.-6.-5.-6.-6.-8.-11.-11.-11.-6.-6.-5.-4.-4.-5.-8.-8.-8.-6.-5.-4.-3.-3.-4.
-4.-6.-6.-5.-3.-3.-2.-2.-2.-3.-3.-4.-5.-5.-3.-2.-1.-1.-2.-5.-4.-4.-4.-3.-2.
0.-1.-1.-1.-2.-2.-3.-2.-1. 0. 2.-11.13. 8. 7. 6. 5. 0. 0.-1. 0. 0. 0.-1.-3.
-3.-3.-3.-1.-1.-1.-1.-1.-1.-2.-3.-1.-1.-1.-1.-2.-1.-3.-4.-5.-8.-6.-3.-3.-3.
-3.-3.-5.-8.-8.-8.-6.-4.-4.-3.-4.-6.-6.-8.-8.-8.-6.-5.-6.-5.-6.-8.-11.-11.-11.
-8.-5.-5.-8.-6.-6.-8.-11.-11.-11.-8.-6.-6.-6.-8.-11.-11.-11.-8.-8.-6.-6.-5.-5.-8.
-11.-11.-8.-11.-6.-5.-5.-5.-5.-6.-11.-11.-8.-6.-3.-4.-5.-5.-6.-8.-6.-6.-5.-4.-4.
-4.-5.-6.-6.-11.-8.-6.-4.-3.-4.-3.-4.-5.-6.-8.-6.-5.-4.-3.-4.-3.-6.-5.
max_IO = 24 (137), min_I0 = 0 (17), avg_I0 = 11 dB(8.8.)
PRACH I0 = 0.0 dB
DLSCH RNTI 1234: current_Qm 6, current_RI 2, total_bytes TX -1130807110
ULSCH RNTI 1234, 389: ulsch_power[0] 41,5 ulsch_noise_power[0] 7.8, sync_pos 0
ulsch_power[1] 26.7, ulsch_noise_power[1] 7.8
round_trials 6434(1.0e+00):6432(1.0e+00):6432(1.0e+00):6432, DTX 0, current_Qm 6, current_RI 1, total_bytes RX/SCHED 0/385630560
L1 Tx job: 401.013 us; 128667; 895.809 us;
L1 Rx job: 183.883 us; 128667; 980.814 us;
L1 Tx processing: 476.247 us; 102933; 872.099 us;
DLSCH encoding: 216.371 us; 77201; 544.272 us;
DLSCH scrambling: 5.524 us; 77201; 19.192 us;
DLSCH modulation: 21.137 us; 77201; 36.428 us;
DLSCH resource mapping: 1.127 us; 1003613; 12.027 us;
DLSCH precoding: 3.667 us; 1003613; 17.411 us;
L1 Rx processing: 488.478 us; 38598; 867.672 us;
UL segment deinterleaving: 5.063 us; 488870; 27.005 us;
UL segment rate recovery: 11.554 us; 488870; 517.998 us;
UL segments decoding: 134.035 us; 488870; 759.164 us;
UL Indication: 0.763 us; 38598; 9.588 us;
Slot Indication: 17.891 us; 128667; 94.446 us;
PUSCH inner-receiver: 307.193 us; 25730; 529.580 us;
feprx: 169.305 us; 38600; 310.489 us;
feptx_ofdm (per port, half_slot): 56.093 us; 102933; 88.125 us;
feptx_total: 147.889 us; 102933; 299.307 us;

View File

@@ -16,7 +16,6 @@ import cls_oai_html
import cls_oaicitest
import cls_containerize
from cls_ci_helper import TestCaseCtx
import ran
import cls_cmd
class TestDeploymentMethods(unittest.TestCase):
@@ -39,7 +38,6 @@ class TestDeploymentMethods(unittest.TestCase):
self.html.testCaseId = "000000"
self.ci = cls_oaicitest.OaiCiTest()
self.cont = cls_containerize.Containerize()
self.ran = ran.RANManagement()
self.cont.yamlPath = ''
self.cont.ranAllowMerge = True
self.cont.ranBranch = ''
@@ -56,7 +54,7 @@ class TestDeploymentMethods(unittest.TestCase):
self.cont.yamlPath = 'tests/simple-dep/'
self.cont.deploymentTag = "noble"
deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, [])
self.assertTrue(deploy)
self.assertTrue(undeploy)
@@ -79,7 +77,7 @@ class TestDeploymentMethods(unittest.TestCase):
stopB = self.cont.StopObject(self.ctx, self.node, self.html)
# should not undeploy anything (everything already stopped)
self.cont.services = None
undeployAll = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
undeployAll = self.cont.UndeployObject(self.ctx, self.node, self.html, [])
self.assertTrue(deploy)
self.assertFalse(stopC)
self.assertTrue(stopA)
@@ -92,7 +90,7 @@ class TestDeploymentMethods(unittest.TestCase):
old = self.cont.yamlPath
self.cont.yamlPath = 'tests/simple-fail/'
deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
self.cont.UndeployObject(self.ctx, self.node, self.html, [])
self.assertFalse(deploy)
self.cont.yamlPath = old
@@ -101,7 +99,7 @@ class TestDeploymentMethods(unittest.TestCase):
old = self.cont.yamlPath
self.cont.yamlPath = 'tests/simple-fail-2svc/'
deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
self.cont.UndeployObject(self.ctx, self.node, self.html, [])
self.assertFalse(deploy)
self.cont.yamlPath = old
@@ -110,7 +108,7 @@ class TestDeploymentMethods(unittest.TestCase):
self.cont.services = "oai-gnb"
self.cont.deploymentTag = 'develop-12345678'
deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, [])
self.assertTrue(deploy)
self.assertTrue(undeploy)
@@ -119,7 +117,7 @@ class TestDeploymentMethods(unittest.TestCase):
self.cont.services = "oai-gnb oai-nr-ue"
self.cont.deploymentTag = 'develop-12345678'
deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, [])
self.assertTrue(deploy)
self.assertTrue(undeploy)
@@ -130,7 +128,7 @@ class TestDeploymentMethods(unittest.TestCase):
deploy1 = self.cont.DeployObject(self.ctx, self.node, self.html)
self.cont.services = "oai-nr-ue"
deploy2 = self.cont.DeployObject(self.ctx, self.node, self.html)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, [])
self.assertTrue(deploy1)
self.assertTrue(deploy2)
self.assertTrue(undeploy)
@@ -145,5 +143,37 @@ class TestDeploymentMethods(unittest.TestCase):
cmd.run(f"rm -rf {self.cont.eNBSourceCodePath}")
self.assertTrue(ws)
def test_undeploy_loganalysis(self):
self.cont.yamlPath = 'yaml_files/5g_rfsimulator_tdd_dora'
self.cont.services = "oai-gnb"
self.cont.deploymentTag = 'develop-12345678'
deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
analyze = ["oai-gnb"]
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, analyze)
self.assertTrue(deploy)
self.assertTrue(undeploy)
def test_undeploy_multi_loganalysis(self):
self.cont.yamlPath = 'yaml_files/5g_rfsimulator_tdd_dora'
self.cont.services = "oai-gnb"
self.cont.deploymentTag = 'develop-12345678'
deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
analyze = ["oai-gnb", "oai-gnb=ContainsString=NOTFOUND"]
undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, analyze)
self.assertTrue(deploy)
self.assertFalse(undeploy)
# TODO this does not work: we don't evaluate return codes yet
#def test_undeploy_rc_nonnull(self):
# # fails reliably
# old = self.cont.yamlPath
# self.cont.yamlPath = 'tests/simple-fail/'
# deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
# # should be false because wrong exit code
# undeploy = self.cont.UndeployObject(self.ctx, self.node, self.html, ["test"])
# self.assertFalse(deploy)
# self.assertFalse(undeploy)
# self.cont.yamlPath = old
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,131 @@
import sys
import logging
logging.basicConfig(
level=logging.DEBUG,
stream=sys.stdout,
format="[%(asctime)s] %(levelname)8s: %(message)s"
)
import os
import unittest
sys.path.append('./') # to find OAI imports below
import cls_loganalysis
class TestLogAnalysis(unittest.TestCase):
def setUp(self):
self.maxDiff = None
#def test_no_file(self):
# f = "/total/fantasy/path/file.log"
# result, _ = cls_loganalysis.Default.run(f, None)
# self.assertFalse(result)
def test_no_error(self):
f = "tests/log-analysis/empty.log"
result, _ = cls_loganalysis.Default.run(f, None)
self.assertTrue(result)
def test_retx_check_good(self):
f = "tests/log-analysis/retx-check-good.log"
opt = "dl=1,0,0,0;ul=1,0,0,0"
result, log = cls_loganalysis.RetxCheck.run(f, opt)
expected = """UE f40a: dlsch_rounds 86/0/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.00052 MCS (0) 0 CCE fail 3
UE f40a: ulsch_rounds 518/0/0/0, ulsch_errors 0, ulsch_DTX 0, BLER 0.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 51.0 dB CCE fail 0"""
self.assertTrue(result)
self.assertEqual(log, expected)
def test_retx_check_good_single_val(self):
f = "tests/log-analysis/retx-check-good.log"
opt = "1,0,0,0"
result, log = cls_loganalysis.RetxCheck.run(f, opt)
expected = """UE f40a: dlsch_rounds 86/0/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.00052 MCS (0) 0 CCE fail 3
UE f40a: ulsch_rounds 518/0/0/0, ulsch_errors 0, ulsch_DTX 0, BLER 0.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 51.0 dB CCE fail 0"""
self.assertTrue(result)
self.assertEqual(log, expected)
def test_retx_check_good_ul_only(self):
f = "tests/log-analysis/retx-check-good.log"
opt = "ul=1,0,0,0"
result, log = cls_loganalysis.RetxCheck.run(f, opt)
expected = """UE f40a: dlsch_rounds 86/0/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.00052 MCS (0) 0 CCE fail 3
UE f40a: ulsch_rounds 518/0/0/0, ulsch_errors 0, ulsch_DTX 0, BLER 0.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 51.0 dB CCE fail 0"""
self.assertTrue(result)
self.assertEqual(log, expected)
def test_retx_check_bad(self):
f = "tests/log-analysis/retx-check-bad.log"
opt = "dl=10,100,100,100;ul=10,100,100,100"
result, log = cls_loganalysis.RetxCheck.run(f, opt)
expected = """UE a491: dlsch_rounds 13/1/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.11000 MCS (0) 0 CCE fail 0
UE a491: ulsch_rounds 23/1/0/0, ulsch_errors 0, ulsch_DTX 1, BLER 0.08447 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 34.0 dB CCE fail 0
UE bf9b: dlsch_rounds 370/368/368/368, dlsch_errors 368, pucch0_DTX 1377, BLER 1.00000 MCS (0) 0 CCE fail 64
UE bf9b: ulsch_rounds 150/148/147/147, ulsch_errors 147, ulsch_DTX 589, BLER 1.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 104 SNR 38.0 dB CCE fail 0
!!! Failure: UE bf9b: retx rounds DL [1] UL [1] exceeded threshold
UE 257a: dlsch_rounds 68071/142/14/0, dlsch_errors 0, pucch0_DTX 10, BLER 0.00427 MCS (1) 25 CCE fail 0
UE 257a: ulsch_rounds 41777/2863/10/0, ulsch_errors 0, ulsch_DTX 17, BLER 0.11456 MCS (1) 10 (Qm 4 deltaMCS 0 dB) NPRB 5 SNR 29.0 dB CCE fail 0"""
self.assertFalse(result)
self.assertEqual(log, expected)
def test_retx_check_dl_only_bad(self):
f = "tests/log-analysis/retx-check-bad.log"
opt = "dl=10,80,100,100"
result, log = cls_loganalysis.RetxCheck.run(f, opt)
expected = """UE a491: dlsch_rounds 13/1/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.11000 MCS (0) 0 CCE fail 0
UE a491: ulsch_rounds 23/1/0/0, ulsch_errors 0, ulsch_DTX 1, BLER 0.08447 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 34.0 dB CCE fail 0
UE bf9b: dlsch_rounds 370/368/368/368, dlsch_errors 368, pucch0_DTX 1377, BLER 1.00000 MCS (0) 0 CCE fail 64
UE bf9b: ulsch_rounds 150/148/147/147, ulsch_errors 147, ulsch_DTX 589, BLER 1.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 104 SNR 38.0 dB CCE fail 0
!!! Failure: UE bf9b: retx rounds DL [1, 2] exceeded threshold
UE 257a: dlsch_rounds 68071/142/14/0, dlsch_errors 0, pucch0_DTX 10, BLER 0.00427 MCS (1) 25 CCE fail 0
UE 257a: ulsch_rounds 41777/2863/10/0, ulsch_errors 0, ulsch_DTX 17, BLER 0.11456 MCS (1) 10 (Qm 4 deltaMCS 0 dB) NPRB 5 SNR 29.0 dB CCE fail 0"""
self.assertFalse(result)
self.assertEqual(log, expected)
def test_retx_check_ul_bad(self):
f = "tests/log-analysis/retx-check-bad.log"
opt = "dl=100,100,100,100;ul=10,100,100,100"
result, log = cls_loganalysis.RetxCheck.run(f, opt)
expected = """UE a491: dlsch_rounds 13/1/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.11000 MCS (0) 0 CCE fail 0
UE a491: ulsch_rounds 23/1/0/0, ulsch_errors 0, ulsch_DTX 1, BLER 0.08447 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 34.0 dB CCE fail 0
UE bf9b: dlsch_rounds 370/368/368/368, dlsch_errors 368, pucch0_DTX 1377, BLER 1.00000 MCS (0) 0 CCE fail 64
UE bf9b: ulsch_rounds 150/148/147/147, ulsch_errors 147, ulsch_DTX 589, BLER 1.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 104 SNR 38.0 dB CCE fail 0
!!! Failure: UE bf9b: retx rounds UL [1] exceeded threshold
UE 257a: dlsch_rounds 68071/142/14/0, dlsch_errors 0, pucch0_DTX 10, BLER 0.00427 MCS (1) 25 CCE fail 0
UE 257a: ulsch_rounds 41777/2863/10/0, ulsch_errors 0, ulsch_DTX 17, BLER 0.11456 MCS (1) 10 (Qm 4 deltaMCS 0 dB) NPRB 5 SNR 29.0 dB CCE fail 0"""
self.assertFalse(result)
self.assertEqual(log, expected)
def test_last_line_contains_false(self):
f = "tests/log-analysis/arbitrary.log"
opt = "Bye."
result, log = cls_loganalysis.LastLineContains.run(f, opt)
expected = f"could not find '{opt}' in last line"
self.assertFalse(result)
self.assertEqual(log, expected)
def test_last_line_contains_false(self):
f = "tests/log-analysis/arbitrary.log"
opt = "got sync"
result, log = cls_loganalysis.LastLineContains.run(f, opt)
expected = ""
self.assertTrue(result)
self.assertEqual(log, expected)
def test_ends_no_bye(self):
f = "tests/log-analysis/arbitrary.log"
opt = None
result, log = cls_loganalysis.EndsWithBye.run(f, opt)
expected = "No Bye. message found, did not stop properly"
self.assertFalse(result)
self.assertEqual(log, expected)
def test_ends_with_bye(self):
f = "tests/log-analysis/with-bye.log"
opt = None
result, log = cls_loganalysis.EndsWithBye.run(f, opt)
expected = ""
self.assertTrue(result)
self.assertEqual(log, expected)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,9 @@
[UTIL] threadCreate() for L1_rx_thread: creating thread (no affinity, default priority)
[UTIL] threadCreate() for L1_tx_thread: creating thread (no affinity, default priority)
[UTIL] threadCreate() for L1_stats: creating thread (no affinity, default priority)
TYPE <CTRL-C> TO TERMINATE
[PHY] got sync (ru_thread)
[PHY] RU 0 rf device ready
[PHY] RU 0 RF started cpu_meas_enabled 0
[HW] No connected device, generating void samples...
[PHY] got sync (L1_stats_thread)

View File

View File

@@ -0,0 +1,54 @@
9185541.336575 [NR_RRC] I UE 1 Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes 3)
9185541.356794 [NR_RRC] A [UL] (cellID bc614e, UE ID 1 RNTI a491) Received Security Mode Complete
9185541.357264 [NR_RRC] I UE 1: Logical Channel DL-DCCH, Generate NR UECapabilityEnquiry (bytes 8, xid 2)
9185541.373199 [NR_RRC] A [UL] (cellID bc614e, UE ID 1 RNTI a491) Received UE capabilities
9185541.373330 [NR_RRC] I Send message to ngap: NGAP_UE_CAPABILITIES_IND
9185541.373356 [NR_RRC] A [DL] (cellID bc614e, UE ID 1 RNTI a491) Send DL Information Transfer [53 bytes]
9185541.373368 [NR_RRC] I Send message to sctp: NGAP_InitialContextSetupResponse
9185541.390034 [NR_MAC] I Frame.Slot 384.0
UE RNTI a491 CU-UE-ID 1 in-sync PH 59 dB PCMAX 21 dBm, average RSRP -101 (4 meas)
UE a491: CQI 2, RI 2, PMI (0,0)
UE a491: dlsch_rounds 13/1/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.11000 MCS (0) 0 CCE fail 0
UE a491: ulsch_rounds 23/1/0/0, ulsch_errors 0, ulsch_DTX 1, BLER 0.08447 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 34.0 dB CCE fail 0
UE a491: MAC: TX 367 RX 3664 bytes
UE a491: LCID 1: TX 213 RX 1649 bytes
9185559.310044 [NR_MAC] I Frame.Slot 128.0
UE RNTI bf9b CU-UE-ID 1 in-sync PH 48 dB PCMAX 21 dBm
UE bf9b: dlsch_rounds 370/368/368/368, dlsch_errors 368, pucch0_DTX 1377, BLER 1.00000 MCS (0) 0 CCE fail 64
UE bf9b: ulsch_rounds 150/148/147/147, ulsch_errors 147, ulsch_DTX 589, BLER 1.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 104 SNR 38.0 dB CCE fail 0
UE bf9b: MAC: TX 10145 RX 82 bytes
UE bf9b: LCID 1: TX 5283 RX 53 bytes
9185582.350069 [NR_MAC] I Frame.Slot 384.0
UE RNTI 257a CU-UE-ID 2 in-sync PH 48 dB PCMAX 21 dBm, average RSRP -83 (16 meas)
UE 257a: CQI 15, RI 2, PMI (0,1)
UE 257a: UL-RI 2, TPMI 0
UE 257a: dlsch_rounds 153/1/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.00000 MCS (1) 0 CCE fail 0
UE 257a: ulsch_rounds 562/2/1/0, ulsch_errors 0, ulsch_DTX 3, BLER 0.00000 MCS (1) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 29.5 dB CCE fail 0
UE 257a: MAC: TX 13416 RX 26519 bytes
UE 257a: LCID 1: TX 523 RX 2046 bytes
UE 257a: LCID 2: TX 0 RX 0 bytes
UE 257a: LCID 4: TX 9800 RX 9945 bytes
9185687.310202 [NR_MAC] I Frame.Slot 640.0
UE RNTI 257a CU-UE-ID 2 in-sync PH 61 dB PCMAX 21 dBm, average RSRP -83 (16 meas)
UE 257a: CQI 15, RI 2, PMI (0,1)
UE 257a: UL-RI 2, TPMI 0
UE 257a: dlsch_rounds 64992/129/13/0, dlsch_errors 0, pucch0_DTX 10, BLER 0.00242 MCS (1) 27 CCE fail 0
UE 257a: ulsch_rounds 39328/2610/8/0, ulsch_errors 0, ulsch_DTX 14, BLER 0.11139 MCS (1) 9 (Qm 4 deltaMCS 0 dB) NPRB 273 SNR 25.5 dB CCE fail 0
UE 257a: MAC: TX 3344707955 RX 818603547 bytes
UE 257a: LCID 1: TX 832 RX 4312 bytes
UE 257a: LCID 2: TX 0 RX 0 bytes
UE 257a: LCID 4: TX 3322610250 RX 815642955 bytes
9185692.430254 [NR_MAC] I Frame.Slot 128.0
UE RNTI 257a CU-UE-ID 2 in-sync PH 48 dB PCMAX 21 dBm, average RSRP -84 (16 meas)
UE 257a: CQI 15, RI 2, PMI (0,1)
UE 257a: UL-RI 2, TPMI 0
UE 257a: dlsch_rounds 68071/142/14/0, dlsch_errors 0, pucch0_DTX 10, BLER 0.00427 MCS (1) 25 CCE fail 0
UE 257a: ulsch_rounds 41777/2863/10/0, ulsch_errors 0, ulsch_DTX 17, BLER 0.11456 MCS (1) 10 (Qm 4 deltaMCS 0 dB) NPRB 5 SNR 29.0 dB CCE fail 0
UE 257a: MAC: TX 3424886787 RX 879242724 bytes
UE 257a: LCID 1: TX 847 RX 4422 bytes
UE 257a: LCID 2: TX 0 RX 0 bytes
UE 257a: LCID 4: TX 3401067134 RX 875911216 bytes

View File

@@ -0,0 +1,8 @@
7799905.793901 [NR_MAC] I Frame.Slot 256.0
UE RNTI f40a CU-UE-ID 2 in-sync PH 48 dB PCMAX 20 dBm, average RSRP -44 (16 meas)
UE f40a: dlsch_rounds 86/0/0/0, dlsch_errors 0, pucch0_DTX 0, BLER 0.00052 MCS (0) 0 CCE fail 3
UE f40a: ulsch_rounds 518/0/0/0, ulsch_errors 0, ulsch_DTX 0, BLER 0.00000 MCS (0) 0 (Qm 2 deltaMCS 0 dB) NPRB 5 SNR 51.0 dB CCE fail 0
UE f40a: MAC: TX 3836 RX 13684 bytes
UE f40a: LCID 1: TX 530 RX 281 bytes
UE f40a: LCID 2: TX 3 RX 35 bytes
UE f40a: LCID 4: TX 1886 RX 2100 bytes

View File

@@ -0,0 +1,3 @@
Some other logs
Bye.
process exited.

View File

@@ -32,3 +32,5 @@
- Custom_Command
- Custom_Script
- Create_Workspace
- AnalyzeRTStats
- AnalyzeRTStats_Object

View File

@@ -129,6 +129,9 @@
<node>localhost</node>
<desc>Undeploy all OAI 4G stack</desc>
<yaml_path>ci-scripts/yaml_files/4g_l2sim_fdd</yaml_path>
<analysis>
<services>oai_enb=EndsWithBye oai_ue1</services>
</analysis>
</testCase>
<testCase>

View File

@@ -147,6 +147,9 @@
<desc>Undeploy all OAI 4G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz</yaml_path>
<analysis>
<services>oai_enb0=EndsWithBye oai_ue0</services>
</analysis>
</testCase>
<testCase>

View File

@@ -118,6 +118,9 @@
<desc>Undeploy all OAI 4G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1</yaml_path>
<analysis>
<services>oai_enb0=EndsWithBye oai_ue0</services>
</analysis>
</testCase>
<testCase>

View File

@@ -147,6 +147,9 @@
<desc>Undeploy all OAI 4G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz</yaml_path>
<analysis>
<services>oai_enb0=EndsWithBye oai_ue0</services>
</analysis>
</testCase>
<testCase>

View File

@@ -147,6 +147,9 @@
<desc>Undeploy all OAI 4G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz</yaml_path>
<analysis>
<services>oai_enb0=EndsWithBye oai_ue0</services>
</analysis>
</testCase>
<testCase>

View File

@@ -84,6 +84,9 @@
<desc>Undeploy all OAI 4G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/4g_rfsimulator_fembms</yaml_path>
<analysis>
<services>oai_enb0=EndsWithBye oai_ue0</services>
</analysis>
</testCase>
<testCase>

View File

@@ -84,6 +84,9 @@
<desc>Undeploy all OAI 4G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/4g_rfsimulator_mbms</yaml_path>
<analysis>
<services>oai_enb0=EndsWithBye oai_ue0</services>
</analysis>
</testCase>
<testCase>

View File

@@ -146,6 +146,9 @@
<desc>Undeploy all OAI 4G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz</yaml_path>
<analysis>
<services>oai_enb0=EndsWithBye oai_ue0</services>
</analysis>
</testCase>
<testCase>

View File

@@ -86,8 +86,9 @@
<node>localhost</node>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_e1</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-cucp=EndsWithBye oai-cuup=EndsWithBye oai-cuup2=EndsWithBye oai-cuup3=EndsWithBye oai-du=RetxCheck=1,0,0,0 oai-du=EndsWithBye oai-du2=RetxCheck=1,0,0,0 oai-du2=EndsWithBye oai-du3=RetxCheck=1,0,0,0 oai-du3=EndsWithBye oai-nr-ue oai-nr-ue2 oai-nr-ue3</services>
</analysis>
</testCase>
<testCase>

View File

@@ -311,8 +311,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_f1_rfsimulator</yaml_path>
<d_retx_th>30,100,100,100</d_retx_th>
<u_retx_th>30,100,100,100</u_retx_th>
<analysis>
<services>oai-cu=EndsWithBye oai-du-pci0=RetxCheck=30,100,100,100 oai-du-pci0=EndsWithBye oai-du-pci1=RetxCheck=30,100,100,100 oai-du-pci1=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -113,8 +113,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_fdd_rfsimulator</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -197,6 +197,14 @@
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_flexric</yaml_path>
<always_exec>true</always_exec>
<analysis>
<service>nearRT-RIC=LastLineContains=Removing E2 Node</service>
<service>xapp-rc-moni=LastLineContains=Test xApp run SUCCESSFULLY</service>
<service>xapp-kpm-moni=LastLineContains=Test xApp run SUCCESSFULLY</service>
<service>xapp-kpm-rc=LastLineContains=Test xApp run SUCCESSFULLY</service>
<service>xapp-gtp-mac-rlc-pdcp-moni=LastLineContains=Test xApp run SUCCESSFULLY</service>
<services>oai-gnb=EndsWithBye oai-nr-ue oai-nr-ue2</services>
</analysis>
</testCase>
<testCase>

View File

@@ -243,8 +243,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=1,0,0,0 oai-gnb=EndsWithBye oai-nr-ue oai-nr-ue2 oai-nr-ue3 oai-nr-ue4 oai-nr-ue5 oai-nr-ue6 oai-nr-ue7 oai-nr-ue8 oai-nr-ue9 oai-nr-ue10</services>
</analysis>
</testCase>
<testCase>

View File

@@ -257,6 +257,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_24prb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -113,8 +113,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_2x2</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=1,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -113,8 +113,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=10,100,100,100 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -89,8 +89,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb</yaml_path>
<d_retx_th>10,0,0,0</d_retx_th>
<u_retx_th>10,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=10,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -159,10 +159,11 @@
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_multiue</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_multiue</yaml_path>
<analysis>
<services>oai-gnb=RetxCheck=1,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -227,8 +227,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_n2_ho</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>oai-cucp-0=EndsWithBye oai-cuup-0=EndsWithBye oai-du-0=RetxCheck=10,100,100,100 oai-du-0=EndsWithBye oai-nr-ue oai-cucp-1=EndsWithBye oai-cuup-1=EndsWithBye oai-du-1=RetxCheck=10,100,100,100 oai-du-1=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -138,6 +138,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_ntn_geo</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -138,6 +138,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_ntn_leo</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -74,8 +74,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_prs</yaml_path>
<d_retx_th>30,100,100,100</d_retx_th>
<u_retx_th>30,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=30,100,100,100 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -60,21 +60,16 @@
<idle_sleep_time_in_sec>20</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>Custom_Command</class>
<desc>Check that UE synched</desc>
<node>localhost</node>
<command>docker logs rfsim5g-oai-nr-ue-2 | grep -m 1 "PSBCH RX:OK"</command>
</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/5g_rfsimulator_sidelink</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-nr-ue-1</services>
<service>oai-nr-ue-2=ContainsString=PSBCH RX:OK</service>
</analysis>
</testCase>
<testCase>

View File

@@ -80,8 +80,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=1,0,0,0 oai-gnb=EndsWithBye oai-nr-ue oai-nr-ue2 oai-nr-ue3 oai-nr-ue4 oai-nr-ue5 oai-nr-ue6 oai-nr-ue7 oai-nr-ue8 oai-nr-ue9 oai-nr-ue10</services>
</analysis>
</testCase>
</testCaseList>

View File

@@ -95,8 +95,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_tdd_dora</yaml_path>
<d_retx_th>0,0,0,0</d_retx_th>
<u_retx_th>0,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=0,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -174,8 +174,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_u0_25prb</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-vnf=RetxCheck=0,0,0,0 oai-vnf=EndsWithBye oai-pnf=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -113,8 +113,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_vrtsim_chanmod</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=1,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -114,8 +114,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_vrtsim_chanmod</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=1,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -114,8 +114,9 @@
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/5g_vrtsim_cirdb</yaml_path>
<d_retx_th>10,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=dl=10,0,0,0;ul=1,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>

View File

@@ -183,6 +183,9 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml
<desc>Undeploy eNB</desc>
<node>hutch</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1</yaml_path>
<analysis>
<services>enb_mono_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -165,6 +165,9 @@
<desc>Undeploy RCC/RRU</desc>
<node>hutch</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5</yaml_path>
<analysis>
<services>rru_fdd=EndsWithBye rcc_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -156,6 +156,9 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm
<desc>Undeploy eNB</desc>
<node>hutch</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1_no_rrc_activity</yaml_path>
<analysis>
<services>enb_mono_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -168,6 +168,9 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
<desc>Undeploy eNB</desc>
<node>hutch</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1</yaml_path>
<analysis>
<services>enb_mono_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -116,6 +116,9 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
<desc>Undeploy eNB</desc>
<node>hutch</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_cdrx</yaml_path>
<analysis>
<services>enb_mono_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -133,6 +133,9 @@
<desc>Undeploy LTE-UE</desc>
<node>carabe</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma</yaml_path>
<analysis>
<services>lte_ue0</services>
</analysis>
</testCase>
<testCase>
@@ -147,6 +150,9 @@
<desc>Undeploy eNB</desc>
<node>hutch</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma</yaml_path>
<analysis>
<services>enb_mono_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -140,6 +140,9 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
<desc>Undeploy eNB</desc>
<node>hutch</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_fdd_20Mhz_tm1</yaml_path>
<analysis>
<services>enb_mono_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -194,6 +194,9 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml
<desc>Undeploy eNB</desc>
<node>starsky</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm1</yaml_path>
<analysis>
<services>enb_mono_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -174,6 +174,9 @@
<desc>Undeploy RRU/RCC</desc>
<node>starsky</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5</yaml_path>
<analysis>
<services>rru_tdd=EndsWithBye rcc_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -187,6 +187,9 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml
<desc>Undeploy eNB</desc>
<node>starsky</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_tdd_10Mhz_tm1</yaml_path>
<analysis>
<services>enb_mono_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -133,6 +133,9 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml
<desc>Undeploy eNB</desc>
<node>starsky</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1</yaml_path>
<analysis>
<services>enb_mono_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -189,6 +189,9 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml
<desc>Undeploy eNB</desc>
<node>starsky</node>
<yaml_path>ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1_default_scheduler</yaml_path>
<analysis>
<services>enb_mono_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -125,6 +125,9 @@
<desc>Undeploy gNB</desc>
<node>obelix</node>
<yaml_path>ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1</yaml_path>
<analysis>
<services>oai-enb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -125,6 +125,9 @@
<desc>Undeploy gNB</desc>
<node>obelix</node>
<yaml_path>ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2</yaml_path>
<analysis>
<services>oai-enb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -192,8 +192,9 @@
<desc>Undeploy gNB</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/nsa_b200_gnb</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>gnb_mono_tdd=RetxCheck=10,100,100,100 gnb_mono_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
@@ -202,6 +203,9 @@
<desc>Undeploy eNB</desc>
<node>nepes</node>
<yaml_path>ci-scripts/yaml_files/nsa_b200_enb</yaml_path>
<analysis>
<services>enb_mono_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -132,8 +132,9 @@
<desc>Undeploy gNB</desc>
<node>gracehopper1-oai</node>
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial</yaml_path>
<d_retx_th>20,100,100,100</d_retx_th>
<u_retx_th>20,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb-aerial=RetxCheck=20,100,100,100 oai-gnb-aerial=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -121,8 +121,9 @@
<desc>Undeploy gNB</desc>
<node>gracehopper1-oai</node>
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial_ul</yaml_path>
<d_retx_th>20,100,100,100</d_retx_th>
<u_retx_th>20,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb-aerial=RetxCheck=20,100,100,100 oai-gnb-aerial=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -177,6 +177,9 @@
<desc>Undeploy gNB</desc>
<node>avra</node>
<yaml_path>ci-scripts/yaml_files/sa_aw2s_gnb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -235,6 +235,9 @@
<desc>Undeploy gNB</desc>
<node>avra</node>
<yaml_path>ci-scripts/yaml_files/sa_aw2s_2x2_gnb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -229,8 +229,9 @@
<desc>Undeploy gNB</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/sa_b200_gnb</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>gnb_mono_tdd=RetxCheck=10,100,100,100 gnb_mono_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -255,8 +255,9 @@
<desc>Undeploy CUCP/CU-UP/DU</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/sa_e1_b200_gnb</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>gnb_cucp=EndsWithBye gnb_cuup=EndsWithBye gnb_du_tdd=RetxCheck=10,100,100,100 gnb_du_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -263,8 +263,9 @@
<desc>Undeploy CU-DU</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/sa_f1_b200_gnb</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>gnb_cu=EndsWithBye gnb_du_fdd=RetxCheck=10,100,100,100 gnb_du_fdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -191,6 +191,9 @@
<desc>Undeploy CU-DU0</desc>
<node>groot</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_f1_b210_ho</yaml_path>
<analysis>
<services>oai-cu=EndsWithBye oai-du0=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
@@ -199,6 +202,9 @@
<desc>Undeploy DU1</desc>
<node>rocket</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_f1_b210_ho</yaml_path>
<analysis>
<services>oai-du1=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -127,6 +127,9 @@
<desc>Undeploy gNB</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -138,6 +138,9 @@
<desc>Undeploy gNB</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -160,6 +160,9 @@
<desc>Undeploy Monolithic gNB-PCI0</desc>
<node>groot</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n2_ho_b210</yaml_path>
<analysis>
<services>oai-gnb-pci0=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
@@ -168,6 +171,9 @@
<desc>Undeploy Monolithic gNB-PCI1</desc>
<node>rocket</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n2_ho_b210</yaml_path>
<analysis>
<services>oai-gnb-pci1=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -123,8 +123,9 @@
<desc>Undeploy gNB</desc>
<node>matix</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=10,100,100,100 oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -123,8 +123,9 @@
<desc>Undeploy gNB</desc>
<node>matix</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz</yaml_path>
<d_retx_th>15,100,100,100</d_retx_th>
<u_retx_th>20,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=dl=15,100,100,100;ul=20,100,100,100 oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -123,8 +123,9 @@
<desc>Undeploy VNF-PNF</desc>
<node>matix</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>oai-vnf=RetxCheck=10,100,100,100 oai-vnf=EndsWithBye oai-pnf=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -125,6 +125,9 @@
<desc>Undeploy nr UE</desc>
<node>caracal</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_nrue</yaml_path>
<analysis>
<services>oai-nr-ue</services>
</analysis>
</testCase>
<testCase>
@@ -133,8 +136,9 @@
<desc>Undeploy gNB</desc>
<node>avra</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_gnb</yaml_path>
<d_retx_th>20,100,100,100</d_retx_th>
<u_retx_th>20,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=20,100,100,100 oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -205,6 +205,9 @@
<desc>Undeploy nr UE</desc>
<node>caracal</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_nrue</yaml_path>
<analysis>
<services>oai-nr-ue</services>
</analysis>
</testCase>
<testCase>
@@ -213,8 +216,9 @@
<desc>Undeploy gNB</desc>
<node>avra</node>
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_gnb</yaml_path>
<d_retx_th>20,100,100,100</d_retx_th>
<u_retx_th>20,100,100,100</u_retx_th>
<analysis>
<services>oai-gnb=RetxCheck=20,100,100,100 oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -183,8 +183,9 @@
<desc>Undeploy gNB</desc>
<node>ofqot</node>
<yaml_path>ci-scripts/yaml_files/sa_sc_b200_gnb</yaml_path>
<d_retx_th>10,100,100,100</d_retx_th>
<u_retx_th>10,100,100,100</u_retx_th>
<analysis>
<services>gnb_mono_tdd=RetxCheck=10,100,100,100 gnb_mono_tdd=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -0,0 +1,88 @@
<!--
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The OpenAirInterface Software Alliance licenses this file to You under
the OAI Public License, Version 1.1 (the "License"); you may not use this file
except in compliance with the License.
You may obtain a copy of the License at
http://www.openairinterface.org/?page_id=698
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
For more information about the OpenAirInterface (OAI) Software Alliance:
contact@openairinterface.org
-->
<testCaseList>
<htmlTabRef>gNB-PHY-Test-100-4x4-FHI72</htmlTabRef>
<htmlTabName>Timing phytest 100 MHz 4x4 FHI7.2</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<testCase>
<class>Custom_Script</class>
<desc>Setup sriov and network interfaces for dummy (no RU)</desc>
<node>bulbul</node>
<script>yaml_files/phytest_fhi72/setup_sriov_dummy.sh</script>
</testCase>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>bulbul</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<node>bulbul</node>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Initialize gNB FHI7.2</desc>
<node>bulbul</node>
<yaml_path>ci-scripts/yaml_files/phytest_fhi72</yaml_path>
<services>oai-gnb</services>
</testCase>
<testCase>
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>AnalyzeRTStats_Object</class>
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.100.4x4.fhi72.yaml</stats_cfg>
<node>bulbul</node>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<node>bulbul</node>
<always_exec>true</always_exec>
<desc>Terminate gNB</desc>
<yaml_path>ci-scripts/yaml_files/phytest_fhi72</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>bulbul</node>
<images>oai-gnb-fhi72</images>
</testCase>
</testCaseList>

View File

@@ -37,7 +37,6 @@
<desc>Initialize gNB USRP</desc>
<node>caracal</node>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 273 -t 23 -D 127 -m 23 -M 273 -l 2 --device.name rf_emulator --rf_emulator.noise_level_dBFS -36 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<rt_stats_cfg>datalog_rt_stats.100.2x2.yaml</rt_stats_cfg>
<air_interface>NR</air_interface>
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0</cmd_prefix>
</testCase>
@@ -48,12 +47,21 @@
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>AnalyzeRTStats</class>
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.100.2x2.yaml</stats_cfg>
<node>caracal</node>
</testCase>
<testCase>
<class>Terminate_eNB</class>
<node>caracal</node>
<always_exec>true</always_exec>
<desc>Terminate gNB</desc>
<air_interface>NR</air_interface>
<analysis>
<services>nr-softmodem=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -37,9 +37,6 @@
<desc>Initialize gNB USRP</desc>
<node>caracal</node>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band79.106prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 106 -t 23 -D 127 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<rt_stats_cfg>datalog_rt_stats.default.yaml</rt_stats_cfg>
<air_interface>NR</air_interface>
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0</cmd_prefix>
</testCase>
@@ -49,12 +46,21 @@
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>AnalyzeRTStats</class>
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.default.yaml</stats_cfg>
<node>caracal</node>
</testCase>
<testCase>
<class>Terminate_eNB</class>
<always_exec>true</always_exec>
<desc>Terminate gNB</desc>
<node>caracal</node>
<air_interface>NR</air_interface>
<analysis>
<services>nr-softmodem=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -37,9 +37,6 @@
<desc>Initialize gNB USRP</desc>
<node>caracal</node>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band79.273prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 273 -t 23 -D 127 -m 23 -M 273 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<rt_stats_cfg>datalog_rt_stats.100.2x2.yaml</rt_stats_cfg>
<air_interface>NR</air_interface>
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0</cmd_prefix>
</testCase>
@@ -49,12 +46,21 @@
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>AnalyzeRTStats</class>
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.100.2x2.yaml</stats_cfg>
<node>caracal</node>
</testCase>
<testCase>
<class>Terminate_eNB</class>
<always_exec>true</always_exec>
<desc>Terminate gNB</desc>
<node>caracal</node>
<air_interface>NR</air_interface>
<analysis>
<services>nr-softmodem=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -37,9 +37,6 @@
<desc>Initialize gNB USRP</desc>
<node>caracal</node>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf --phy-test -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<rt_stats_cfg>datalog_rt_stats.1x1.60.yaml</rt_stats_cfg>
<air_interface>NR</air_interface>
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0</cmd_prefix>
</testCase>
@@ -49,12 +46,21 @@
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>AnalyzeRTStats</class>
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.1x1.60.yaml</stats_cfg>
<node>caracal</node>
</testCase>
<testCase>
<class>Terminate_eNB</class>
<always_exec>true</always_exec>
<desc>Terminate gNB</desc>
<node>caracal</node>
<air_interface>NR</air_interface>
<analysis>
<services>nr-softmodem=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

View File

@@ -37,9 +37,6 @@
<desc>Initialize gNB USRP</desc>
<node>caracal</node>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band79.162prb.usrpn300.phytest-dora.conf --phy-test --gNBs.[0].pdsch_AntennaPorts_XP 2 --RUs.[0].nb_tx 2 --RUs.[0].nb_rx 2 -q -U 768 -T 162 -t 23 -D 127 -m 23 -M 162 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<rt_stats_cfg>datalog_rt_stats.60.2x2.yaml</rt_stats_cfg>
<air_interface>NR</air_interface>
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0</cmd_prefix>
</testCase>
@@ -49,12 +46,21 @@
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>AnalyzeRTStats</class>
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.60.2x2.yaml</stats_cfg>
<node>caracal</node>
</testCase>
<testCase>
<class>Terminate_eNB</class>
<always_exec>true</always_exec>
<desc>Terminate gNB</desc>
<node>caracal</node>
<air_interface>NR</air_interface>
<analysis>
<services>nr-softmodem=EndsWithBye</services>
</analysis>
</testCase>
<testCase>

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