Compare commits

..

91 Commits

Author SHA1 Message Date
Bartosz Podrygajlo
0671ed89a5 Add Dockerfile for cuda tests 2025-08-27 17:53:41 +02:00
Nika Ghaderi
99ef2957d2 documentation updated 2025-08-27 09:31:04 +00:00
Nika Ghaderi
04e5f73d27 further bug fixes for the batch mode 2025-08-26 16:19:12 +00:00
Nika Ghaderi
1c3ad6681d addressed some logic issues in the scalability test 2025-08-26 14:54:52 +00:00
Nika Ghaderi
e80f52a657 changed channel generation method in test-channel-simulation from new_channel_desc_scm to create_manual_channel_desc becasue the former appears to have a buffer overflow problem. 2025-08-26 09:31:20 +00:00
Nika Ghaderi
2b2313f078 Updated the integration section 2025-08-25 14:29:49 +00:00
Nika Ghaderi
db7cdd0338 Updated implementation section in the markdown report 2025-08-25 14:22:12 +00:00
Nika Ghaderi
b3c12fd64c Updated test_SSE with the latest updates 2025-08-25 13:15:23 +00:00
Nika Ghaderi
941e615fb4 further optimizations 2025-08-25 12:06:28 +00:00
Nika Ghaderi
1e8085334f Made optimizations to the scalability test 2025-08-25 12:06:28 +00:00
Nika Ghaderi
74372f5f50 Updated test_channel_scalability with the latest changes 2025-08-25 12:06:28 +00:00
Nika Ghaderi
3195964aae Updated test_channel_simulation with the latest changes 2025-08-25 12:06:28 +00:00
Nika Ghaderi
1998d62e70 Replaced the memory allocation logic in simulation test 2025-08-25 12:06:28 +00:00
Nika Ghaderi
f7058faaf1 Updated test-multipath with the latest changes 2025-08-25 12:06:28 +00:00
Nika Ghaderi
888a471599 Added zero-pad logic to all multipath functions and kernels.
Removed the interleaved input entirely and replaced it by the void pointer for simplicity.
2025-08-25 12:06:28 +00:00
Nika Ghaderi
f510eb05bd cleanup in dlsim 2025-08-25 12:06:28 +00:00
Nika Ghaderi
4f1c7a00b5 Zero-pad the input buffer for dlsim/ulsim and pipeline 2025-08-25 12:06:28 +00:00
Nika Ghaderi
28f9d07bee cleanup 2025-08-25 12:06:28 +00:00
Nika Ghaderi
f23dc335b5 Fixes for the benchmarks 2025-08-25 12:06:28 +00:00
Nika Ghaderi
636caf7b39 Debugging the scalability test zeroing out issue 2025-08-25 12:06:28 +00:00
Nika Ghaderi
93d83b9a6f removed path_loss from benchmarks and pipeline 2025-08-25 12:06:28 +00:00
Nika Ghaderi
ceb0af2a11 removed path_loss from dlsim/ulsim logic 2025-08-25 12:06:28 +00:00
Nika Ghaderi
13c8a8f124 removed path_loss from multipath-channel.cu logic 2025-08-25 12:06:28 +00:00
Nika Ghaderi
898d643a1c removed path_loss from multipath-channel.c float functions 2025-08-25 12:06:28 +00:00
Nika Ghaderi
f34ecdb2a8 Remove temporary interleaver test file after validation 2025-08-25 12:06:28 +00:00
Nika Ghaderi
37d350286a Changed interleave_channel_output_cuda output type from float2** to void** to avoid float2 type conflicts and allow compilation with a C compiler 2025-08-25 12:06:28 +00:00
Nika Ghaderi
847ffc1ac8 Add CPU/GPU interleaver test for channel output conversion
- Implement interleave_channel_output() for CPU reference
- Add interleave_channel_output_cuda() for GPU acceleration
- Test validates conversion from separate I/Q arrays to interleaved format
- Includes sample display and error verification functions
- Ready for integration into other parts of the project
2025-08-25 12:06:28 +00:00
Nika Ghaderi
b15eb72751 Modified multipath_channel.c to support the new interleaved input format and corrected its calling from dlsim/ulsim and other benchmarks. 2025-08-25 12:06:28 +00:00
Nika Ghaderi
528bb77f0a updated benchmarks to use the new input format 2025-08-25 12:06:28 +00:00
Nika Ghaderi
1af4c2f323 Migration from de-interleaved IQ input signals to interleaved pairs 2025-08-25 12:06:28 +00:00
Nika Ghaderi
1ed256b5ae Minor modification to the markdown 2025-08-25 12:06:28 +00:00
Nika Ghaderi
ccb0f6f767 markdown completed 2025-08-25 12:06:28 +00:00
Nika Ghaderi
3ce4f0b695 added an initial markdown for the mr 2025-08-25 12:06:28 +00:00
Nika Ghaderi
4863e54c7f removed a duplicate declaration in um code 2025-08-25 12:06:28 +00:00
Nika Ghaderi
e5993fbf9c fixed memory allcoation for the batch mode 2025-08-25 12:06:28 +00:00
Nika Ghaderi
ba6a0ad8a4 enabled cpu run 2025-08-25 12:06:28 +00:00
Nika Ghaderi
6f2068dbd7 added the batch kernels 2025-08-25 12:06:28 +00:00
Nika Ghaderi
9767adbad2 code cleanup and review 2025-08-25 12:06:28 +00:00
Nika Ghaderi
ad37c5b291 Refined memory allocation for the current function with the risk of race conditions 2025-08-25 12:06:28 +00:00
Nika Ghaderi
2633aba5dd combined gpu execution modes: batch, stream and serial 2025-08-25 12:06:28 +00:00
Nika Ghaderi
96e7dc7356 feat: Use the single batched kernel instead of CUDA streams. 2025-08-25 12:06:28 +00:00
Nika Ghaderi
517e40a5b2 final code for the scalability test 2025-08-25 12:06:28 +00:00
Nika Ghaderi
726dc2487f added cuda streams 2025-08-25 12:06:28 +00:00
Nika Ghaderi
18e0442687 corrected output report's format in the analysis script 2025-08-25 12:06:28 +00:00
Nika Ghaderi
40acdbf9f0 refined run_scalability_analysis 2025-08-25 12:06:28 +00:00
Nika Ghaderi
f97be1fdc2 the final report of the scalability test is now more detailed 2025-08-25 12:06:28 +00:00
Nika Ghaderi
e4f1bd597c feat: added multi-ue uplink scenario to the scalability test 2025-08-25 12:06:28 +00:00
Nika Ghaderi
48ca5a60c0 rewritten test_scalability file 2025-08-25 12:06:28 +00:00
Nika Ghaderi
54a7cea232 rewriting the new banchmark from scratch: added input parameters 2025-08-25 12:06:28 +00:00
Nika Ghaderi
252a108294 new implementation for the scalability benchmark 2025-08-25 12:06:28 +00:00
Nika Ghaderi
c4b50ad628 channels can now run sequentially in the scalability test 2025-08-25 12:06:28 +00:00
Nika Ghaderi
bfcb01f6b9 added a script to analyse the gpu utilization 2025-08-25 12:06:28 +00:00
Nika Ghaderi
d1cecc0adc Switched from constant memory to global memory for channel coefficients.
Added a benchmark to test the scalability of the channel emulation functions.
2025-08-25 12:06:28 +00:00
Nika Ghaderi
7f5b4364f7 initial logci for scalability test, although it uses limited memory 2025-08-25 12:06:28 +00:00
Nika Ghaderi
8477aea6a6 cleanup 2025-08-25 12:06:28 +00:00
Nika Ghaderi
ecb1023c45 unified input types for all multipath functions 2025-08-25 12:06:28 +00:00
Nika Ghaderi
1a0bd4fa1e sse comparison test updated 2025-08-25 12:06:28 +00:00
Nika Ghaderi
d6f7ee72d2 added doppler effect to the float, SIMD code in channel multipath 2025-08-25 12:06:28 +00:00
Nika Ghaderi
cca709e17d set default memory logic to the hybrid mode (ats + explicit copy back to the cpu) 2025-08-25 12:06:28 +00:00
Nika Ghaderi
73261051d6 the sse, float version of multipath_channel now runs without any problems 2025-08-25 12:06:27 +00:00
Nika Ghaderi
e561e9bce7 updated ulsim to allign with dlsim's modifications 2025-08-25 12:06:27 +00:00
Nika Ghaderi
4c69990e0d further bug fixes in dlsim (for the normal cpu execution) 2025-08-25 12:06:27 +00:00
Nika Ghaderi
549055a6ff fixed a typo in ulsim 2025-08-25 12:06:27 +00:00
ghaderi
6795083390 modified ulsim to support new memory flags + added a cuda_enable flag 2025-08-25 12:06:27 +00:00
Nika Ghaderi
bfbb5962a3 fixed the 'cuda_found' problem 2025-08-25 12:06:27 +00:00
Nika Ghaderi
56a5da6ceb problems with the cuda-found flag 2025-08-25 12:06:27 +00:00
Nika Ghaderi
5210dd168d removed build commands from the sse-comparison script 2025-08-25 12:06:27 +00:00
ghaderi
e7fd573160 fixed a segmentation fault in test_SSE 2025-08-25 12:06:27 +00:00
ghaderi
a883e94af2 added a unified test for comparing SSE vs non-SSE code 2025-08-25 12:06:27 +00:00
Nika Ghaderi
bb0647010f Added a hybrid model to manage the memory. (uses ATS for gpu reads and explicit copy for writes) 2025-08-25 12:06:27 +00:00
Nika Ghaderi
e26c11ac8d added memory hints for the um 2025-08-25 12:06:27 +00:00
Nika Ghaderi
75a35dda8a some debugging + added prefetch logic 2025-08-25 12:06:27 +00:00
Nika Ghaderi
e6c0f41031 initial logic for USE_UNIFIED_MEMORY 2025-08-25 12:06:27 +00:00
Nika Ghaderi
3a7529c983 sse test added 2025-08-25 12:06:27 +00:00
Nika Ghaderi
ba17b42476 cleanup and some bug fixes 2025-08-25 12:06:27 +00:00
Nika Ghaderi
dd8e9de9df added the pipeline logic to nr_ulsim 2025-08-25 12:06:27 +00:00
Nika Ghaderi
d1e6c9f3f6 feat(sim): Activate and debug the CUDA channel simulation pipeline
This commit enables the optimized CUDA pipeline for channel simulation (multipath + noise) in the nr-dlsim simulator. This significantly accelerates simulations running with the --cuda flag.

The integration involved several key bug fixes to ensure logical correctness and stability:

- Corrected Path Loss Application: The original pipeline implementation was missing the path loss scaling step. This was fixed by integrating the scaling directly into the CUDA noise kernel.

- Fixed `cudaMemcpyToSymbol` Scope Issue: A silent failure was occurring when copying channel coefficients to `__constant__` memory from a different compilation unit. This was the primary cause of the simulation failure (zero-energy output). The issue was resolved by creating an `update_channel_coeffs_symbol()` helper function to encapsulate the memory copy within the correct file (`multipath_channel.cu`).

- Aligned Channel Generation Logic: The channel generation timing in the CUDA path was aligned with the working CPU path. A new channel is now correctly generated for each HARQ round inside the main simulation loop, resolving DCI decoding failures.
2025-08-25 12:06:27 +00:00
Nika Ghaderi
8062a742e7 initial pipeline logic added 2025-08-25 12:06:27 +00:00
Nika Ghaderi
46a06c7748 merged benchmarks 2025-08-25 12:06:27 +00:00
Nika Ghaderi
36e8880dfd trying some optimization strategies 2025-08-25 12:06:27 +00:00
Nika Ghaderi
5fa37d87cc optimized noise-cuda and added a benchmark 2025-08-25 12:06:27 +00:00
Nika Ghaderi
00345e8421 initial implementation of the noise functions in cuda 2025-08-25 12:06:27 +00:00
Nika Ghaderi
cf2be69c4d testing cuda graphs for multipath_channel.cu 2025-08-25 12:06:27 +00:00
Nika Ghaderi
47c15b1c4e added refined stride logic, not sure about its efficiency though 2025-08-25 12:06:27 +00:00
Nika Ghaderi
d24d3b34ba reverted to the 512 block logic 2025-08-25 12:06:27 +00:00
Nika Ghaderi
d957c52ae4 grid-stride loop optimization 2025-08-25 12:06:27 +00:00
Nika Ghaderi
15926127ef block size testing 2025-08-25 12:06:27 +00:00
Nika Ghaderi
8edd34cd38 ome issues with the cuda code are fixed. A tmp benchma
rk script was added next to the test_multipath.
2025-08-25 12:06:27 +00:00
Nika Ghaderi
5043985129 initial benchmark for multipath_chennel 2025-08-25 12:06:27 +00:00
Nika Ghaderi
f9ce6dc366 Add initial CUDA implementation for multipath_channel 2025-08-25 12:06:27 +00:00
Nika Ghaderi
a874cd8e28 feat: Add test harness for multipath_channel 2025-08-25 12:06:27 +00:00
3487 changed files with 112761 additions and 128335 deletions

View File

@@ -62,7 +62,6 @@ ForEachMacros:
- BOOST_FOREACH
- RB_FOREACH
- UE_iterator
- FOR_EACH_SEQ_ARR
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'

8
.gitignore vendored
View File

@@ -20,14 +20,6 @@ GRTAGS
GTAGS
tags
# Package conffiles
tools/packages/oai-lte/conffiles
tools/packages/oai-nr/conffiles
tools/packages/liboai-common/conffiles
tools/packages/liboai-usrp/conffiles
# others
nfapi_nr_interface_scf
*.log

View File

@@ -1,119 +1,5 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
# RELEASE NOTES: #
## [v2.4.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.4.0) -> December 2025. ##
General new features and improvements (both RAN and UE):
- Rework LDPC BBdev/AAL interface and support both AMD T2/Intel vRAN Boost
(VRB) 1 accelerators
- Add a taps client for vrtsim real-time simulator (check: vrtsim release?)
- Add new RFemulator virtual radio driver to emulate radio (including noise
generation) for gNB/UE standalone operation
- RLC AM reception improvements for high-throughput scenarios (!3512)
- Small NTN fixes (!3659, !3666, !3581, !3652)
- Improvements to imScope
Stability and bug fixes:
- RFsimulator: fix concurrency problems during multi-client connection
- USRP driver: support synchronization of USRP B200
- MAC scheduler improvements
- General L1 improvements for efficiency and stability
- Correct PRS bug and test in CI
- Upgrade Ubuntu container images to Ubuntu 24.04
- All build system targets compile (`make/ninja all`)
- Minor cleanup, harmonization, and performance improvements all over the stack
- Simplify CI code
RAN changes (gNB/CU/CU-CP/CU-UP/DU/DU-high/DU-low):
- Support of N2 handover
- Support of "UL-heavy" TDD patterns, e.g., DSUUU
- Open Fronthaul M-plane: CM improvements, PM implementation, and additional
v16.01 support
- Improve interoperability with Nvidia Aerial L1 to support 2 layer UL
- Add O-RAN OSC WLS library as FAPI transport and enable L1/L2 shared memory
split
- Implement FAPI Stop exchange
- Improve interoperability with srsRAN_Project DU
- Add new synchronized real-time data recording application (!3462)
- Support for measurement gaps and general handover fixes
- Support of RRC PDU session release procedure
- Add CU-UP load tester
- Correct BWP scheduling and support multiple BWPs per UE
nrUE changes:
- Support one additional PDU session (see !3486)
- L3 measurements for A2 measurement reports
- Support for type0 PDSCH frequency allocation
- UE symbol based PDCCH receiver
Regression or removals:
- No known regressions
- Unused L2 simulator code has been removed
- Unused Benetel radio driver code (not FHI 7.2!) has been removed
Configuration file changes:
- `gNBs.[0].servingCellConfigCommon.[0].ra_ResponseWindow` is automatically
computed and can be removed
- `gNBs.[0].bwp_list` has been added (moved from entries in
`gNBs.[0].servingCellConfigDedicated`)
- `gNBs.[0].phaseTrackingRS` has been added (moved from entries in
`gNBs.[0].servingCellConfigDedicated`)
- `gNBs.[0].local_s_portc` and `gNBs.[0].remote_s_portc` have no effect and
should be removed
- `gNBs.[0].CSI_report_type` has been added
- `MACRLCs.[0].ulsch_max_frame_inactivity` is automatically computed and can be
removed
- `MACRLCs.[0].local_n_portc` and `MACRLCs.[0].remote_n_portc` have no effect and
should be removed
- `MACRLCs.[0].stats_max_ue` has been added
## [v2.3.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.3.0) -> July 2025. ##
General new features and improvements (both RAN and UE):
- Preliminary support for RedCap UEs
- Support for NTN LEO scenarios including SIB19 and channel emulation (see
doc/RUNMODEM.md)
- VRTSIM: new shared memory realtime radio (see develop/radio/vrtsim/README.md)
- Support for TDD pattern 2
- Support for long PRACH
- Support for SIB2
- Add unit tests using ctest (see doc/UnitTests.md)
Stability and bug fixes:
- Improve various procedures (e.g., RRC reestablishment, RRC Reject, ...)
- Add improvements for ImScope
- Bugfixes in the entire stack (e.g., #803, #805, #810, #812, #818, #852, #878,
#884, #890, #895, #901, #907, #932, #939 ...)
- Documentation updates
- And many other small fixes, like memory leaks, crashes, ...
RAN changes (gNB/CU/CU-CP/CU-UP/DU/DU-high/DU-low):
- Stability and performance improvements when running with 4-layer DL MIMO
- Stability and performance improvements when running with 2-layer UL MIMO
- Interoperability testing with Metanoia Jura and Foxconn RUs
- Support of O-RAN 7.2 M-plane (Start-up procedure including configuration
management, see also doc/ORAN_FHI7.2_Tutorial.md)
- Upgrade OSC FHI (xran) from E to F release
- Refactoring of LDPC interface and performance improvements
- Support for nFAPI in all scenarios for FR1 (see doc/nfapi.md)
- Support at least 32 UEs concurrently
- Improve robustness when running in split modes (F1, E1)
- Add basic support for beam management in FR2
- Add support for O1 on DU (see also https://gitlab.eurecom.fr/oai/o1-adapter)
- E2 agent: Support for multiple E2SM-RC report service styles
nrUE changes:
- Refactoring of threading towards better code and performance
- Add or rework various procedures (e.g., RA with C-RNTI, Going to Idle, RA, ...)
- Refactor and extend NAS implementation (e.g., Service Request, Registration
Request, Service Acept, Service Reject, ...)
- Support for continuous frequency offset compensation
- Reduce minimum RX-to-TX time to 3
Regression:
- Multiple BWPs do not work reliably on gNB; use tag 2025.w17
## [v2.2.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.2.0) -> November 2024. ##
General 5G improvements (both gNB and UE):

View File

@@ -1,16 +1,37 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
cmake_minimum_required (VERSION 3.19)
# Author: laurent THOMAS, Lionel GAUTHIER
cmake_minimum_required (VERSION 3.16)
project (OpenAirInterface LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(OAI_VERSION 2.4.0)
option(CUDA_ENABLE "Enable CUDA accelerated channel simulation" OFF)
find_package(CUDA)
if(CUDA_ENABLE)
find_package(CUDA REQUIRED)
find_package(CUDAToolkit REQUIRED)
message(STATUS "CUDA explicitly enabled, building with GPU acceleration support.")
enable_language(CUDA)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
@@ -35,8 +56,20 @@ if(CUDA_ENABLE)
endif()
add_compile_definitions(ENABLE_CUDA)
add_library(oai_cuda_lib STATIC
${CMAKE_SOURCE_DIR}/openair1/SIMULATION/TOOLS/multipath_channel.cu
${CMAKE_SOURCE_DIR}/openair1/SIMULATION/TOOLS/phase_noise.cu
${CMAKE_SOURCE_DIR}/openair1/SIMULATION/TOOLS/channel_pipeline.cu
)
target_include_directories(oai_cuda_lib PUBLIC
${CMAKE_SOURCE_DIR}/openair1/SIMULATION/TOOLS
)
endif()
set(CMAKE_CXX_STANDARD 17)
#########################################################
# Base directories, compatible with legacy OAI building #
#########################################################
@@ -75,15 +108,6 @@ endif()
###################################
include(FindPkgConfig)
option(PACKAGING_RPM "By default will create debian packages, with this option willl create rpm packages" OFF)
option(PACKAGING_NR "Will produce a package containing nr target, configuration files and docs" OFF)
option(PACKAGING_LTE "Will produce a package containing lte target, configuration files and docs" OFF)
option(PACKAGING_COMMON "Will produce a package containing common target, configuration files and docs" OFF)
option(PACKAGING_USRP "Will produce a package containing usrp target, configuration files and docs" OFF)
option(PACKAGING_PHYSIM "Will produce a package containing physim target, configuration files and docs" OFF)
# Check if asn1c is installed, and check if it supports all options we need
# a user can provide ASN1C_EXEC to override an asn1c to use (e.g., parallel
# installation)
@@ -110,8 +134,10 @@ set (NFAPI_USER_DIR ${OPENAIR_DIR}/nfapi/oai_integration)
set (OPENAIR1_DIR ${OPENAIR_DIR}/openair1)
set (OPENAIR2_DIR ${OPENAIR_DIR}/openair2)
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
set (OPENAIR_CMAKE ${OPENAIR_DIR}/cmake_targets)
project (OpenAirInterface)
# project (OpenAirInterface)
####################################################
# compilation flags
@@ -179,8 +205,6 @@ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=neoverse-n1 -lgcc -lrt")
elseif (CPUPART MATCHES "0xd49") # Neoverse-N2
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=neoverse-n2 -ftree-vectorize -lgcc -lrt")
elseif (CPUPART MATCHES "0xd03") # Cortex-A53
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=cortex-a53 -lgcc -lrt")
else ()
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=native -lgcc -lrt")
endif()
@@ -189,16 +213,14 @@ else()
endif()
if (NOT CROSS_COMPILE)
if (CPUPART MATCHES "0xd03")
# Cortex-A53 does not support ARMv8.2-A extensions
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8-a+simd")
else()
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=native")
endif()
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=native")
else ()
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8.2-a")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8-a")
endif()
# add autotools definitions that were maybe used!
add_definitions(-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP)
# we need -rdynamic to incorporate all symbols in shared objects, see man page
set(commonOpts "-pipe -fPIC -Wall -fno-strict-aliasing -rdynamic")
# GNU C/C++ Compiler might throw many warnings without packed-bitfield-compat, see man page
@@ -250,16 +272,9 @@ endif()
add_definitions("-DASN_DISABLE_OER_SUPPORT -DHAVE_CONFIG_H -DHAVE_CONFIG_H_")
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_RPATH ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
if(PACKAGING_LTE OR PACKAGING_NR OR PACKAGING_COMMON OR PACKAGING_USRP OR PACKAGING_PHYSIM)
set(CMAKE_SKIP_INSTALL_RPATH TRUE)
endif()
#########################
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb2 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}")
#########################
# set a flag for changes in the source code
# these changes are related to hardcoded path to include .h files
set(debugOpt "-ggdb2 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks")
@@ -333,7 +348,7 @@ add_boolean_option(TRACY_ENABLE OFF "Enable tracy instrumentation" ON)
if (TRACY_ENABLE)
# the tracy version here should match the tracy server version
# below is latest release as of this commit
CPMAddPackage("gh:wolfpld/tracy#v0.13.1")
CPMAddPackage("gh:wolfpld/tracy#0.12.2")
endif()
set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti)
@@ -378,7 +393,7 @@ target_link_libraries(lte_rrc PRIVATE nr_rrc)
#NR RRC
#######
add_library(nr_rrc ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c)
target_link_libraries(nr_rrc PUBLIC asn1_nr_rrc asn1_lte_rrc rrc_cell_management)
target_link_libraries(nr_rrc PUBLIC asn1_nr_rrc asn1_lte_rrc)
# S1AP
##############
@@ -409,26 +424,19 @@ add_library(ngap
${NGAP_DIR}/ngap_gNB.c
${NGAP_DIR}/ngap_common.c
${NGAP_DIR}/ngap_gNB_context_management_procedures.c
${NGAP_DIR}/ngap_gNB_mobility_management.c
${NGAP_DIR}/ngap_gNB_decoder.c
${NGAP_DIR}/ngap_gNB_encoder.c
${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
${NGAP_DIR}/ngap_gNB_ue_context.c
${NGAP_DIR}/ngap_gNB_NRPPa_transport_procedures.c
)
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
##############
@@ -519,7 +527,7 @@ add_library(f1ap
${F1AP_DIR}/f1ap_itti_messaging.c)
target_include_directories(f1ap PUBLIC F1AP_DIR)
target_link_libraries(f1ap PUBLIC asn1_f1ap GTPV1U)
target_link_libraries(f1ap PRIVATE ngap nr_rrc ds f1ap_lib)
target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib)
target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib)
if(E2_AGENT)
target_compile_definitions(f1ap PRIVATE E2_AGENT)
@@ -531,10 +539,8 @@ endif()
# Hardware dependant options
###################################
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")
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 (CONFIG_ROOTDIR ${OPENAIR_DIR}/common/config)
add_library(config_internals OBJECT
@@ -559,6 +565,8 @@ target_link_libraries(params_libconfig PRIVATE config_internals ${libconfig_LIBR
add_library(shlib_loader OBJECT common/utils/load_module_shlib.c)
target_link_libraries(shlib_loader PRIVATE CONFIG_LIB)
include_directories ("${OPENAIR_DIR}/radio/COMMON")
##############################################################
# ???!!! TO BE DOCUMENTED OPTIONS !!!???
##############################################################
@@ -601,6 +609,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories("${OPENAIR_DIR}/executables")
include_directories("${OPENAIR2_DIR}/COMMON")
include_directories("${OPENAIR2_DIR}/UTIL")
include_directories("${OPENAIR2_DIR}/UTIL/LOG")
include_directories("${OPENAIR3_DIR}/COMMON")
include_directories("${OPENAIR3_DIR}/UTILS")
include_directories("${NFAPI_DIR}/nfapi/public_inc")
@@ -637,10 +646,16 @@ 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")
include_directories("${OPENAIR2_DIR}/UTIL/OSA")
include_directories("${OPENAIR2_DIR}/UTIL/MEM")
include_directories("${OPENAIR2_DIR}/UTIL/LISTS")
include_directories("${OPENAIR2_DIR}/UTIL/FIFO")
include_directories("${OPENAIR2_DIR}/UTIL/MATH")
include_directories("${OPENAIR2_DIR}/UTIL/TIMER")
include_directories("${OPENAIR2_DIR}/UTIL/OTG")
include_directories("${OPENAIR2_DIR}/UTIL/OPT")
include_directories("${OPENAIR_DIR}")
@@ -658,10 +673,21 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common/utils/T
# set the T_LIB name to T if the target exists, otherwise leave empty
set(T_LIB $<TARGET_NAME_IF_EXISTS:T>)
add_library(HASHTABLE
${OPENAIR_DIR}/common/utils/hashtable/hashtable.c
${OPENAIR_DIR}/common/utils/hashtable/obj_hashtable.c
)
include_directories(${OPENAIR_DIR}/common/utils/hashtable)
add_library(UTIL
${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.c
${OPENAIR2_DIR}/UTIL/OPT/probe.c
)
if (ENABLE_LTTNG)
find_package(LTTngUST 2.3.8 EXACT REQUIRED)
else()
message(STATUS "LTTNG support disabled")
endif()
pkg_check_modules(cap libcap)
if (cap_FOUND)
@@ -705,6 +731,7 @@ add_library(SCHED_LIB ${SCHED_SRC})
target_link_libraries(SCHED_LIB PRIVATE asn1_lte_rrc_hdrs)
set(SCHED_NR_SRC
${OPENAIR1_DIR}/SCHED_NR/fapi_nr_l1.c
${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_gNB.c
${OPENAIR1_DIR}/SCHED_NR/nr_prach_procedures.c
${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c
@@ -815,6 +842,24 @@ include_directories(${NFAPI_USER_DIR})
# Layer 1
#############################
set(PHY_POLARSRC
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_init.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_bitwise_operations.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_crc_byte.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_encoder.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_interleaving_pattern.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_kernal_operation.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_kronecker_power_matrices.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_matrix_and_array.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_procedures.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_sequence_pattern.c
)
set(PHY_SMALLBLOCKSRC
${OPENAIR1_DIR}/PHY/CODING/nrSmallBlock/encodeSmallBlock.c
${OPENAIR1_DIR}/PHY/CODING/nrSmallBlock/decodeSmallBlock.c
)
set(PHY_TURBOIF
${OPENAIR1_DIR}/PHY/CODING/coding_load.c
)
@@ -825,6 +870,8 @@ set(PHY_NRLDPC_CODINGIF
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
add_library(crc_byte OBJECT ${OPENAIR1_DIR}/PHY/CODING/crc_byte.c)
set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c
@@ -914,6 +961,7 @@ 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
@@ -954,9 +1002,9 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_csirs.c
${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_srs.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/refsig.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
)
set(PHY_NR_SRC
@@ -970,6 +1018,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
@@ -992,6 +1041,8 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/TOOLS/dB_routines.c
${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c
${OPENAIR1_DIR}/PHY/TOOLS/oai_arith_operations.c
${PHY_POLARSRC}
${PHY_SMALLBLOCKSRC}
${PHY_NRLDPC_CODINGIF}
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/srs_rx.c
@@ -1006,7 +1057,6 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ntn_l1.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
@@ -1041,6 +1091,8 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c
${OPENAIR1_DIR}/PHY/TOOLS/oai_arith_operations.c
${OPENAIR1_DIR}/PHY/INIT/nr_init_ue.c
${PHY_POLARSRC}
${PHY_SMALLBLOCKSRC}
${PHY_NRLDPC_CODINGIF}
)
@@ -1059,21 +1111,29 @@ 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` 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} ${lapacke_INCLUDE_DIRS})
add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
add_library(PHY_NR ${PHY_NR_SRC})
target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock)
target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5)
add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC})
target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common)
target_compile_definitions(PHY_NR_NO_AVX_256 PUBLIC USE_128BIT)
add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL polar smallblock)
target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL)
add_library(PHY_RU ${PHY_SRC_RU})
target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs UTIL)
@@ -1137,7 +1197,7 @@ set(L2_SRC
${RRC_DIR}/rrc_eNB_S1AP.c
${RRC_DIR}/rrc_eNB_M2AP.c
${RRC_DIR}/rrc_eNB_UE_context.c
${RRC_DIR}/rrc_eNB_GTPV1U.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${RRC_DIR}/rrc_common.c
${RRC_DIR}/L2_interface.c
${RRC_DIR}/L2_interface_common.c
@@ -1167,7 +1227,6 @@ set(L2_NR_SRC
${NR_RRC_DIR}/rrc_gNB.c
${NR_RRC_DIR}/mac_rrc_dl_direct.c
${NR_RRC_DIR}/mac_rrc_dl_f1ap.c
${NR_RRC_DIR}/rrc_gNB_asn1.c
${NR_RRC_DIR}/rrc_gNB_nsa.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${NR_RRC_DIR}/rrc_gNB_NGAP.c
@@ -1203,7 +1262,7 @@ set(NR_L2_SRC_UE
${NR_UE_RRC_DIR}/L2_interface_ue.c
${NR_UE_RRC_DIR}/main_ue.c
${NR_UE_RRC_DIR}/rrc_UE.c
${NR_UE_RRC_DIR}/verify_RRC.c
${NR_UE_RRC_DIR}/rrc_nsa.c
${NR_UE_RRC_DIR}/rrc_timers_and_constants.c
${NR_UE_RRC_DIR}/rrc_sl_preconfig.c
)
@@ -1235,6 +1294,7 @@ set (MAC_SRC
set (MAC_NR_SRC
${NR_PHY_INTERFACE_DIR}/NR_IF_Module.c
${NR_PHY_INTERFACE_DIR}/nr_sched_response.c
${NR_GNB_MAC_DIR}/main.c
${NR_GNB_MAC_DIR}/config.c
${NR_GNB_MAC_DIR}/gNB_scheduler.c
@@ -1290,8 +1350,6 @@ set (GNB_APP_SRC
${OPENAIR2_DIR}/GNB_APP/gnb_app.c
${OPENAIR2_DIR}/E1AP/e1ap_setup.c
${OPENAIR2_DIR}/GNB_APP/gnb_config.c
${OPENAIR2_DIR}/GNB_APP/gnb_config_common.c
${OPENAIR2_DIR}/GNB_APP/gnb_config_ng.c
)
set (MCE_APP_SRC
@@ -1304,6 +1362,12 @@ set (MISC_NFAPI_LTE
add_library(MISC_NFAPI_LTE_LIB ${MISC_NFAPI_LTE})
set (MISC_NFAPI_NR
${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c
)
add_library(MISC_NFAPI_NR_LIB ${MISC_NFAPI_NR})
add_library(L2
${L2_SRC}
${MAC_SRC}
@@ -1312,10 +1376,13 @@ add_library(L2
)
target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap)
target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(E2_AGENT)
target_link_libraries(L2 PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup)
target_compile_definitions(L2 PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
add_library(MAC_UE_NR ${MAC_NR_SRC_UE})
target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs PUBLIC nr_ue_power_procedures nr_ue_ra_procedures)
@@ -1330,12 +1397,6 @@ add_library(L2_NR
target_link_libraries(L2_NR PRIVATE ds alg)
target_link_libraries(L2_NR PRIVATE f1ap_lib)
target_include_directories(L2_NR PRIVATE ${F1AP_DIR}/lib)
if(E2_AGENT)
target_compile_definitions(L2_NR PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
if (OAI_AERIAL_CUMAC)
target_compile_definitions(L2_NR PUBLIC ENABLE_CUMAC)
endif()
add_library(e1_if
${NR_RRC_DIR}/cucp_cuup_direct.c
@@ -1348,6 +1409,10 @@ target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc nr_co
if(OAI_AERIAL)
target_compile_definitions(L2_NR PRIVATE ENABLE_AERIAL)
endif()
if(E2_AGENT)
target_link_libraries(L2_NR PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup)
target_compile_definitions(L2_NR PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
add_library(L2_LTE_NR
# temporary solution until 4G/5G code completely untangled (as evidenced by deletion of the following file)
@@ -1389,6 +1454,15 @@ 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
@@ -1668,6 +1742,13 @@ include_directories(${NAS_SRC}UE/EMM/SAP)
include_directories(${NAS_SRC}UE/ESM)
include_directories(${NAS_SRC}UE/ESM/SAP)
# nbiot
add_definitions("-DNUMBER_OF_UE_MAX_NB_IoT=16")
set (NBIOT_SOURCES
${OPENAIR2_DIR}/ENB_APP/NB_IoT_config.c
)
add_library(NB_IoT MODULE ${NBIOT_SOURCES} )
# Simulation library
##########################
set (SIMUSRC
@@ -1683,6 +1764,7 @@ set (SIMUSRC
${OPENAIR1_DIR}/SIMULATION/RF/dac.c
${OPENAIR1_DIR}/SIMULATION/RF/adc.c
)
add_library(SIMU STATIC ${SIMUSRC} )
target_include_directories(SIMU PUBLIC ${OPENAIR1_DIR}/SIMULATION/TOOLS ${OPENAIR1_DIR}/SIMULATION/RF)
@@ -1704,8 +1786,9 @@ include_directories("${NFAPI_DIR}/nfapi/inc")
include_directories("${NFAPI_DIR}/sim_common/inc")
include_directories("${NFAPI_DIR}/pnf_sim/inc")
add_library(oai_iqplayer MODULE ${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c)
target_link_libraries(oai_iqplayer PRIVATE log_headers)
add_library(oai_iqplayer MODULE
${OPENAIR_DIR}/radio/iqplayer/iqplayer_lib.c
)
#################################
# add executables for operation
@@ -1715,6 +1798,10 @@ add_library(minimal_lib
)
target_link_libraries(minimal_lib PUBLIC pthread dl ${T_LIB} LOG)
add_executable(nfapi_test
${OPENAIR_DIR}/openair2/NR_PHY_INTERFACE/nfapi_5g_test.c
)
add_executable(measurement_display
${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c)
target_link_libraries (measurement_display minimal_lib)
@@ -1727,9 +1814,12 @@ add_executable(lte-softmodem
${OPENAIR_DIR}/executables/lte-ru.c
${OPENAIR_DIR}/executables/ru_control.c
${OPENAIR_DIR}/executables/lte-softmodem.c
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c
${OPENAIR_DIR}/executables/create_tasks.c
${OPENAIR_DIR}/executables/create_tasks_mbms.c
${OPENAIR_DIR}/radio/COMMON/common_lib.c
${OPENAIR_DIR}/radio/COMMON/record_player.c
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${PHY_INTERFACE_DIR}/queue_t.c
${OPENAIR_DIR}/common/utils/lte/ue_power.c
@@ -1740,30 +1830,33 @@ add_dependencies(lte-softmodem oai_iqplayer)
target_link_libraries(lte-softmodem PRIVATE
-Wl,--start-group
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI SIMU radio_common softmodem_common
${NAS_UE_LIB} ITTI SIMU shlib_loader
-Wl,--end-group z dl)
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)
target_compile_definitions(lte-softmodem PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
add_executable(oairu
${OPENAIR_DIR}/executables/lte-ru.c
${OPENAIR_DIR}/executables/ru_control.c
${OPENAIR_DIR}/radio/COMMON/common_lib.c
${OPENAIR_DIR}/radio/COMMON/record_player.c
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
${OPENAIR_DIR}/executables/main_ru.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
)
target_link_libraries(oairu PRIVATE
-Wl,--start-group
SCHED_RU_LIB PHY_COMMON PHY_RU UTIL radio_common softmodem_common
SCHED_RU_LIB PHY_COMMON PHY_RU UTIL shlib_loader
-Wl,--end-group z dl)
target_link_libraries(oairu PRIVATE pthread m CONFIG_LIB rt ${T_LIB})
@@ -1780,7 +1873,10 @@ target_link_libraries(lte-softmodem PRIVATE
add_executable(lte-uesoftmodem
${OPENAIR_DIR}/executables/lte-ue.c
${OPENAIR_DIR}/executables/lte-uesoftmodem.c
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR_DIR}/executables/create_tasks_ue.c
${OPENAIR_DIR}/radio/COMMON/common_lib.c
${OPENAIR_DIR}/radio/COMMON/record_player.c
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/lte/ue_power.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
@@ -1790,35 +1886,20 @@ add_executable(lte-uesoftmodem
target_link_libraries(lte-uesoftmodem PRIVATE
-Wl,--start-group
lte_rrc nr_rrc s1ap x2ap m2ap m3ap
SECURITY UTIL SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
PHY_UE PHY_RU L2_UE L2_LTE SIMU NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI radio_common softmodem_common
${NAS_UE_LIB} ITTI shlib_loader
-Wl,--end-group z dl)
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
asn1_lte_rrc asn1_s1ap asn1_m2ap asn1_m3ap asn1_x2ap)
# nr RRU
add_executable(nr-oru
${OPENAIR_DIR}/executables/nr-ru.c
${OPENAIR_DIR}/openair1/PHY/INIT/nr_parms.c
${OPENAIR_DIR}/openair1/SCHED_NR/phy_frame_config_nr.c
${OPENAIR_DIR}/openair1/SCHED_NR/nr_prach_procedures.c
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
${OPENAIR_DIR}/executables/main_nr_ru.c
)
target_link_libraries(nr-oru PRIVATE
UTIL SCHED_RU_LIB PHY_COMMON PHY_RU PHY_NR shlib_loader z dl
radio_common softmodem_common)
target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
barrier actor)
target_link_libraries(nr-oru PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_phy_common time_management)
# nr-softmodem
###################################################
@@ -1829,6 +1910,9 @@ add_executable(nr-softmodem
${OPENAIR_DIR}/executables/nr-gnb.c
${OPENAIR_DIR}/executables/nr-ru.c
${OPENAIR_DIR}/executables/nr-softmodem.c
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR_DIR}/radio/COMMON/common_lib.c
${OPENAIR_DIR}/radio/COMMON/record_player.c
${OPENAIR_DIR}/common/utils/lte/ue_power.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
${PHY_INTERFACE_DIR}/queue_t.c
@@ -1837,11 +1921,11 @@ add_executable(nr-softmodem
target_link_libraries(nr-softmodem PRIVATE
-Wl,--start-group
UTIL SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU
x2ap f1ap m2ap m3ap e1ap radio_common
time_management softmodem_common
x2ap f1ap m2ap m3ap e1ap shlib_loader
time_management
-Wl,--end-group z dl)
target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt)
@@ -1859,13 +1943,7 @@ if (OAI_AERIAL)
target_compile_definitions(nr-softmodem PUBLIC ENABLE_AERIAL)
target_link_libraries(nr-softmodem PUBLIC aerial_lib)
endif()
add_boolean_option(OAI_AERIAL_CUMAC OFF "Activate OAI's AERIAL_CUMAC driver" OFF)
if (OAI_AERIAL_CUMAC)
target_link_libraries(nr-softmodem PUBLIC aerial_cumac_lib)
target_compile_definitions(nr-softmodem PUBLIC ENABLE_CUMAC)
endif()
if(E2_AGENT)
target_link_libraries(nr-softmodem PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup)
target_compile_definitions(nr-softmodem PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
@@ -1876,6 +1954,7 @@ target_link_libraries(nr-softmodem PRIVATE
add_executable(nr-cuup
executables/nr-cuup.c
executables/softmodem-common.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${OPENAIR2_DIR}/E1AP/e1ap_setup.c
${NR_PDCP_SRC}
@@ -1885,9 +1964,8 @@ add_executable(nr-cuup
target_link_libraries(nr-cuup PRIVATE
CONFIG_LIB ITTI SCTP_CLIENT
GTPV1U e1ap f1ap
time_management softmodem_common
alg
z dl pthread ${T_LIB})
time_management
z dl pthread shlib_loader ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(E2_AGENT)
target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup)
@@ -1903,7 +1981,11 @@ add_executable(nr-uesoftmodem
${OPENAIR_DIR}/executables/nr-uesoftmodem.c
${OPENAIR_DIR}/executables/position_interface.c
${OPENAIR_DIR}/executables/nr-ue.c
${OPENAIR_DIR}/executables/nr-ue-ru.c
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR_DIR}/radio/COMMON/common_lib.c
${OPENAIR_DIR}/radio/COMMON/record_player.c
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
${NFAPI_USER_DIR}/nfapi.c
${PHY_INTERFACE_DIR}/queue_t.c
@@ -1911,10 +1993,10 @@ add_executable(nr-uesoftmodem
target_link_libraries(nr-uesoftmodem PRIVATE
-Wl,--start-group
nr_rrc SECURITY UTIL SCHED_RU_LIB SCHED_NR_UE_LIB
nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB
ITTI SIMU radio_common
time_management softmodem_common
ITTI SIMU shlib_loader
time_management
-Wl,--end-group z dl)
target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_meas)
@@ -1935,22 +2017,22 @@ target_link_libraries(nr-uesoftmodem PRIVATE
#####################################
#special case for dlim TM4, which uses its own version of phy_scope code
#add_executable(dlsim_tm4
# ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/dlsim_tm4.c
# ${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope_tm4.c
# )
#target_link_libraries (dlsim_tm4
# -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group
# pthread m rt CONFIG_LIB ${T_LIB}
# )
add_executable(dlsim_tm4
${OPENAIR1_DIR}/SIMULATION/LTE_PHY/dlsim_tm4.c
${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope_tm4.c
)
target_link_libraries (dlsim_tm4
-Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group
pthread m rt CONFIG_LIB ${T_LIB}
)
add_executable(rftest
${OPENAIR_DIR}/openair1/PHY/TOOLS/calibration_test.c
${OPENAIR_DIR}/openair1/PHY/TOOLS/calibration_scope.c
${OPENAIR_DIR}/radio/COMMON/common_lib.c
${OPENAIR_DIR}/executables/softmodem-common.c
)
target_link_libraries(rftest PRIVATE
minimal_lib PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB}
radio_common softmodem_common)
target_link_libraries(rftest PRIVATE minimal_lib PHY_NR_COMMON UTIL forms pthread dl m ${T_LIB} shlib_loader)
target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
add_executable(polartest
@@ -1967,7 +2049,7 @@ add_executable(smallblocktest
target_link_libraries(smallblocktest PRIVATE
-Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group
m pthread dl ${T_LIB}
m pthread dl shlib_loader ${T_LIB}
)
@@ -1977,7 +2059,7 @@ add_executable(ldpctest
)
target_link_libraries(ldpctest PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON -Wl,--end-group
m pthread dl ${T_LIB}
m pthread dl shlib_loader ${T_LIB}
# link 'check_crc' to make it resolved in the LDPC coding libraries
# 'check_crc' is not used in ldpctest so it is not linked in the executable by default
# --whole-archive links 'check_crc' in the executable even though it is note used, see 'man ld'
@@ -1990,98 +2072,93 @@ target_link_libraries(physim_common PRIVATE UTIL)
add_executable(nr_dlschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c)
target_link_libraries(nr_dlschsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
m pthread ${T_LIB} ITTI dl shlib_loader physim_common
)
target_link_libraries(nr_dlschsim PRIVATE asn1_nr_rrc_hdrs)
add_executable(nr_pbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c)
target_link_libraries(nr_pbchsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
m pthread ${T_LIB} ITTI dl shlib_loader physim_common
)
target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_psbchsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/psbchsim.c
${OPENAIR_DIR}/executables/softmodem-common.c
${NR_UE_RRC_DIR}/rrc_nsa.c
${NFAPI_USER_DIR}/nfapi.c
${NFAPI_USER_DIR}/gnb_ind_vars.c
${PHY_INTERFACE_DIR}/queue_t.c
)
target_link_libraries(nr_psbchsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common softmodem_common
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB L2_NR -lz -Wl,--end-group
m pthread ${T_LIB} ITTI dl shlib_loader physim_common
)
target_link_libraries(nr_psbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_pucchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c)
target_link_libraries(nr_pucchsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
m pthread ${T_LIB} ITTI dl shlib_loader physim_common
)
target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_dlsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c
${OPENAIR_DIR}/executables/softmodem-common.c
${NR_UE_RRC_DIR}/rrc_nsa.c
${NFAPI_USER_DIR}/nfapi.c
${NFAPI_USER_DIR}/gnb_ind_vars.c
${PHY_INTERFACE_DIR}/queue_t.c
)
target_link_libraries(nr_dlsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB L2_NR -Wl,--end-group
m pthread ${T_LIB} ITTI dl nr_ue_phy_meas physim_common
softmodem_common
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${T_LIB} ITTI dl shlib_loader nr_ue_phy_meas physim_common
)
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_prachsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c)
target_link_libraries(nr_prachsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common)
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group
m pthread ${T_LIB} ITTI dl shlib_loader physim_common)
target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_ulschsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c
${PHY_INTERFACE_DIR}/queue_t.c
)
target_link_libraries(nr_ulschsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
m pthread ${T_LIB} ITTI dl shlib_loader physim_common
)
target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_ulsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c
${OPENAIR_DIR}/executables/softmodem-common.c
${NR_UE_RRC_DIR}/rrc_nsa.c
${NFAPI_USER_DIR}/nfapi.c
${NFAPI_USER_DIR}/gnb_ind_vars.c
${PHY_INTERFACE_DIR}/queue_t.c
)
target_link_libraries(nr_ulsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB L2_NR -Wl,--end-group
m pthread ${T_LIB} ITTI dl nr_ue_phy_meas physim_common softmodem_common
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${T_LIB} ITTI dl shlib_loader nr_ue_phy_meas physim_common
)
target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_srssim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/srssim.c
${NFAPI_USER_DIR}/nfapi.c
)
if (TARGET oai_cuda_lib)
target_link_libraries(nr_dlsim PRIVATE oai_cuda_lib ${CUDAToolkit_LIBRARIES})
target_link_libraries(nr_ulsim PRIVATE oai_cuda_lib ${CUDAToolkit_LIBRARIES})
target_link_libraries(nr_srssim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON -Wl,--end-group
m pthread ITTI dl nr_ue_phy_meas physim_common softmodem_common
)
if(CUDA_ENABLE)
if (TARGET oai_cuda_lib)
target_link_libraries(nr_dlsim PRIVATE oai_cuda_lib)
target_link_libraries(nr_ulsim PRIVATE oai_cuda_lib)
target_compile_definitions(nr_dlsim PRIVATE ENABLE_CUDA)
target_compile_definitions(nr_ulsim PRIVATE ENABLE_CUDA)
endif()
target_compile_definitions(nr_dlsim PRIVATE ENABLE_CUDA)
target_compile_definitions(nr_ulsim PRIVATE ENABLE_CUDA)
endif()
# these simulators do not compile:
# dlsim_tm7 pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim
foreach(myExe dlsim ulsim)
foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim)
add_executable(${myExe}
${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c
${OPENAIR_DIR}/common/utils/lte/ue_power.c
@@ -2091,7 +2168,7 @@ foreach(myExe dlsim ulsim)
)
target_link_libraries (${myExe} PRIVATE
-Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU ITTI -Wl,--end-group
pthread m rt CONFIG_LIB ${T_LIB} dl
pthread m rt CONFIG_LIB ${T_LIB} dl shlib_loader
)
target_link_libraries(${myExe} PRIVATE asn1_lte_rrc_hdrs)
add_dependencies(${myExe} coding)
@@ -2100,23 +2177,22 @@ endforeach(myExe)
#unitary tests for Core NEtwork pieces
#################################
#foreach(myExe
# s1ap
# secu_knas_encrypt_eia1
# secu_kenb
# aes128_ctr
# secu_knas_encrypt_eea2
# secu_knas secu_knas_encrypt_eea1
# kdf
# aes128_cmac_encrypt
# secu_knas_encrypt_eia2)
# add_executable(test_${myExe}
# ${OPENAIR3_DIR}/TEST/test_${myExe}.c
# )
# target_link_libraries (test_${myExe}
# -Wl,--start-group SECURITY UTIL -Wl,--end-group m rt CONFIG_LIB
# )
#endforeach(myExe)
foreach(myExe s1ap
secu_knas_encrypt_eia1
secu_kenb
aes128_ctr
secu_knas_encrypt_eea2
secu_knas secu_knas_encrypt_eea1
kdf
aes128_cmac_encrypt
secu_knas_encrypt_eia2)
add_executable(test_${myExe}
${OPENAIR3_DIR}/TEST/test_${myExe}.c
)
target_link_libraries (test_${myExe}
-Wl,--start-group SECURITY UTIL -Wl,--end-group m rt CONFIG_LIB
)
endforeach(myExe)
#ensure that the T header files are generated before targets depending on them
if (${T_TRACER})
@@ -2126,17 +2202,17 @@ if (${T_TRACER})
nr-uesoftmodem dlsim dlsim_tm4 dlsim_tm7
ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim
syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_pucchsim
nr_ulschsim ldpctest polartest smallblocktest nr_srssim
nr_ulschsim ldpctest polartest smallblocktest cu_test du_test
#all "add_library" definitions
ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap
params_libconfig
oai_eth_transpro UTIL
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB
params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer
oai_eth_transpro oai_mobipass HASHTABLE UTIL OMG_SUMO
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
MISC_NFAPI_LTE_LIB
MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_UE_NR ngap
GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE SIMU
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU OPENAIR0_LIB
dfts config_internals nr_common crc_byte)
if (TARGET ${i})
add_dependencies(${i} generate_T)
@@ -2144,6 +2220,8 @@ if (${T_TRACER})
endforeach(i)
endif (${T_TRACER})
include(${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt)
set(ENABLE_TESTS OFF CACHE STRING "Activate build of tests")
set_property(CACHE ENABLE_TESTS PROPERTY TYPE BOOL)
set(ENABLE_PHYSIM_TESTS OFF CACHE STRING "Activate build of physim tests")
@@ -2183,7 +2261,6 @@ if(ENABLE_TESTS)
endif()
add_subdirectory(common)
add_subdirectory(executables)
add_subdirectory(doc)
add_subdirectory(nfapi)
add_subdirectory(openair1)
@@ -2194,10 +2271,11 @@ add_subdirectory(tests)
if(TARGET oai_cuda_lib)
message(STATUS "CUDA library 'oai_cuda_lib' found, linking to targets...")
target_link_libraries(nr_dlsim PRIVATE oai_cuda_lib)
target_link_libraries(nr_ulsim PRIVATE oai_cuda_lib)
endif()
target_link_libraries(nr_dlsim PRIVATE oai_cuda_lib ${CUDAToolkit_LIBRARIES})
target_link_libraries(nr_ulsim PRIVATE oai_cuda_lib ${CUDAToolkit_LIBRARIES})
if(PACKAGING_LTE OR PACKAGING_NR OR PACKAGING_COMMON OR PACKAGING_USRP OR PACKAGING_PHYSIM)
include("tools/packages/packages.cmake")
# target_link_libraries(test_multipath PRIVATE oai_cuda_lib ${CUDAToolkit_LIBRARIES})
# target_link_libraries(test_noise PRIVATE oai_cuda_lib ${CUDAToolkit_LIBRARIES})
# target_link_libraries(test_channel_simulation PRIVATE oai_cuda_lib ${CUDAToolkit_LIBRARIES})
endif()

View File

@@ -1,5 +1,3 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
# Contributing to OpenAirInterface #
We want to make contributing to this project as easy and transparent as possible.
@@ -28,13 +26,5 @@ Please refer to the steps described on our website: [How to contribute to OAI](h
# License #
By contributing to OpenAirInterface, you agree that your contributions will be
licensed under
1. [CSSL v1.0 license](LICENSES/preferred/CSSL-v1.0.txt): for RAN and UE
related source code and test scripts
2. [CC-BY-4.0](LICENSES/preferred/CC-BY-4.0.txt): All the documentation
3. [MIT](LICENSES/preferred/MIT.txt): Orchestration (helm-charts, docker
compose)
Certain files are using different licenses; you can read about them in
[NOTICE](NOTICE).
licensed under the license described in the file [`LICENSE`](./LICENSE) in the
root directory of this source tree.

335
LICENSE Normal file → Executable file
View File

@@ -1,223 +1,200 @@
Collaborative Standards Software License v1.0 (CSSL)
The OpenAirInterface Software Alliance (OSA)
OAI Public License (Version 1.1)
LICENSE TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION OF
OPENAIRINTERFACE. The pdf version of this document can be downloaded from
https://openairinterface.org/oai-cssl/.
LICENSE TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION OF OPENAIR 5G SOFTWARE.
1. Definitions.
1. Definitions.
“License” shall mean the terms and conditions for use, reproduction, and
distribution set forth in this document.
“License” shall mean the terms and conditions for use, reproduction, and distribution set forth
in this document.
“Licensor” shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
“Licensor” shall mean the OpenAirInterface Software Alliance.
“Legal Entity” shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, “control” means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
“Legal Entity” shall mean the union, at the time an acting entity joins the Alliance, of the
acting entity and all other entities that control, are controlled by, or are under common control
with that entity. For the purposes of this definition, “control” means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii)
beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity exercising
permissions granted by this License.
“You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by
this License.
“Source” form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
“Source” form shall mean the preferred form for making modifications, including but not
limited to software source code, documentation source, and configuration files.
“Object” form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
“Object” form shall mean any form resulting from mechanical transformation or translation of
a Source form, including but not limited to compiled object code, generated documentation,
and conversions to other media types.
Work” shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
OpenAirInterface Software Alliance” shall mean the endowment fund established at the
initiative of Eurecom, an educational and research establishment located at Campus Sophia
Tech, 450 Route des Chappes, 06410 Biot, France, which statutes were signed on 18
November 2014.
Derivative Works” shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
“Work” shall mean the work of authorship, whether in Source or Object form, made available
under the License, as indicated by a copyright notice that is included in or attached to the
work (an example is provided in the Appendix below).
Contribution” shall mean any work of authorship that is intentionally submitted
to Licensor for inclusion in the Work by the copyright owner or by an individual
or Legal Entity authorized to submit on behalf of the copyright owner. For the
purposes of this definition, “submitted” means any form of electronic, or
written communication sent to the Licensor or its representatives, including but
not limited to communication on electronic mailing lists, source code control
systems, and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work but excluding
communication that is conspicuously marked or otherwise designated in writing by
the copyright owner or entity authorized by the copyright owner as "Not a
Contribution."
Derivative Works” shall mean any work, whether in Source or Object form, that is based on
(or derived from) the Work and for which the editorial revisions, annotations, elaborations, or
other modifications represent, as a whole, an original work of authorship. For the purposes of
this License, Derivative Works shall not include works that remain separable from, or merely
link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
“Contributor License Agreement” shall mean the agreement signed by any
Contributor setting forth the terms and conditions applicable to its
Contribution.
“Contribution” shall mean any work of authorship that is intentionally submitted to Licensor
for inclusion in the Work by the copyright owner or by an individual or Legal Entity
authorized to submit on behalf of the copyright owner. For the purposes of this definition,
“submitted” means any form of electronic, , or written communication sent to the Licensor or
its representatives, including but not limited to communication on electronic mailing lists,
source code control systems, and issue tracking systems that are managed by, or on behalf of,
the Licensor for the purpose of discussing and improving the Work
“Contributor” shall mean any individual or Legal Entity on behalf of whom a
Contribution has been received by Licensor and subsequently incorporated within
the Work.
“Contributor License Agreement” shall mean the agreement signed by any Contributor setting
forth the terms and conditions applicable to its Contribution.
2. Grant of Copyright License.
“Contributor” shall mean any individual or Legal Entity on behalf of whom a Contribution
has been received by Licensor and subsequently incorporated within the Work.
Subject to the terms and conditions of this License, Licensor and each
Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, and distribute the Work
and such Derivative Works in Source or Object form.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, Licensor and each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of, publicly display, publicly
perform, and distribute the Work and such Derivative Works in Source or Object form
3. Grant of Patent License.
3. Grant of Patent License.
3.1 Grant of Patent License for study, testing and research purposes:
Subject to the terms and conditions of this License, Licensor and each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made, use, and otherwise
transfer (excluding selling) the Work, solely for study, testing and research purposes, where
such license applies only to those patent claims licensable by Licensor or such Contributor
that are necessarily infringed respectively by the Work and/or the said Contributor
Contribution(s) alone or by combination of their Contribution(s) with the Work to which
such Contribution(s) was submitted (“Essential Patents”).
Subject to the terms and conditions of this License, Licensor and each
Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section) patent
license to make, have made, use, and otherwise transfer (excluding selling) the
Work, solely for study, testing and research purposes, where such license
applies only to those patent claims licensable by Licensor or such Contributor
that are necessarily infringed respectively by the Work and/or the said
Contributor Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted (“Essential Patents”).
3.2 Grant of Patent License for purposes other than study, testing and research:
For purposes other than study, testing and research, and subject to the terms
and conditions of this License, You commit to be prepared to negotiate, in good
faith, a non-exclusive, nontransferable, non-assignable license of Essential
Patents with each Contributor and/or the Licensor on Fair, Reasonable and
Non-Discriminatory (“FRAND”) terms and conditions for the use of the Work or
Contribution(s) incorporated within the Work.
3.2 Grant of Patent License for purposes other than study and research:
For purposes other than study, testing and research, and subject to the terms and conditions of
this License, You commit to be prepared to negotiate a non-exclusive, non-transferable, non-
assignable license of Essential Patents with each Contributor and/or the Licensor on Fair,
Reasonable and Non-Discriminatory (“FRAND”) terms and conditions for the use of the
Work or Contribution(s) incorporated within the Work.
Licensor and/or each Contributor, by submitting a Contribution, will identify any of its known
Essential Patent it owns related to the Work and/or its Contribution.
3.3 Patent Litigation
If You institute patent litigation against any entity making use of the Work
solely for study, testing and research purposes (including a cross-claim or
counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated
within the Work constitutes direct or contributory patent infringement, then the
patent licenses granted to You under section 3.1 of this License for that Work
shall terminate as of the date such litigation is filed.
If You institute patent litigation against any entity making use of the Work solely for study,
testing and research purposes (including a cross-claim or counterclaim in a lawsuit) alleging
that the Work or a Contribution incorporated within the Work constitutes direct or
contributory patent infringement, then the patent licenses granted to You under section 3.1 of
this License for that Work shall terminate as of the date such litigation is filed.
4. Sublicensing
You may grant sublicenses under the licenses granted under sections 2 and 3.1
provided that the sublicense is subject to and inclusive of all the terms of and
rights under this License to which the Work is or was distributed.
You may grant sublicenses under the licenses granted under sections 2 and 3.1 provided that
the sublicense is subject to and inclusive of all the terms of and rights under this License to
which the Work is or was distributed by the OpenAirInterface Software Alliance.
5. Redistribution
Subject to terms and conditions set forth in sections 2 and 3, You may reproduce and
distribute copies of the Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You meet the following
conditions:
Subject to terms and conditions set forth in sections 2 and 3, You may reproduce
and distribute copies of the Work or Derivative Works thereof in any medium,
with or without modifications, and in Source or Object form, provided that You
meet the following conditions:
1. You must give any other recipients of the Work or Derivative Works a copy of this
License; and
1. You must give any other recipients of the Work or Derivative Works a copy of
this License; and
2. You must cause any modified files by You to carry prominent notices stating that You
changed the files; and
2. You must cause any modified files by You to carry prominent notices stating
that You changed the files; and
3. You must retain, in the Source form of any Derivative Works that You distribute, all
copyright, patent, trademark, and attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of the Derivative Works; and
3. You must retain, in the Source form of any Derivative Works that You
distribute, all copyright, patent, trademark, and attribution notices from the
Source form of the Work, excluding those notices that do not pertain to any part
of the Derivative Works; and
4. If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative
Works that You distribute must include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not pertain to any part of the
Derivative Works, in at least one of the following places: within a NOTICE text file
distributed as part of the Derivative Works; within the Source form or documentation, if
provided along with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of the
NOTICE file are for informational purposes only and do not modify the License. You may
add Your own attribution notices within Derivative Works that You distribute, alongside or as
an addendum to the NOTICE text from the Work, provided that such additional attribution
notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or distribution of
Your modifications, or for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with the conditions stated in
this License.
4. If the Work includes a “NOTICE” text file as part of its distribution, then
any Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
6. Submission of Contributions.
Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be
under the terms and conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of any
separate license agreement such as the Contributor License Agreement You may have
executed with Licensor regarding such Contributions.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
7. Trademarks.
This License does not grant permission to use the trade names, trademarks, service marks, or
product names of the Licensor, except as required for reasonable and customary use in
describing the origin of the Work and reproducing the content of the NOTICE file.
6. Submission of Contributions.
8. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and
each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including,
without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely
responsible for determining the appropriateness of using or redistributing the Work and
assume any risks associated with your exercise of permissions under this License.
Any contribution intentionally submitted for inclusion in the Work by You to the
Licensor shall be under the terms and conditions of this License, without any
additional terms or conditions. Notwithstanding the above, nothing herein shall
supersede or modify the terms of any separate license agreement such as the
Contributor License Agreement You may have executed with Licensor regarding such
Contributions.
9. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence), contract, or
otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or
agreed to in writing, shall Licensor and any Contributor, as such, be liable to You for
damages, including any direct, indirect, special, incidental, or consequential damages of any
character arising as a result of this License or out of Your use or inability to use the Work
(including but not limited to damages for loss of goodwill, work stoppage, computer failure or
malfunction, or any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
7. Trademarks.
10. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to offer, and
charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations
and/or rights consistent with this License. However, in accepting such obligations, You may
act only on Your own behalf and on Your sole responsibility, not on behalf of any other
Contributor and/or the Licensor, and only if You agree to indemnify, defend, and hold each
Contributor and/or the Licensor harmless for any liability incurred by, or claims asserted
against, such Contributor and/or Licensor by reason of Your accepting any such warranty or
additional liability.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
8. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with your exercise of
permissions under this License.
9. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall Licensor and any
Contributor, as such, be liable to You for damages, including any direct,
indirect, special, incidental, or consequential damages of any character arising
as a result of this License or out of Your use or inability to use the Work
(including but not limited to damages for loss of goodwill, work stoppage,
computer failure or malfunction, or any and all other commercial damages or
losses), even if such Contributor has been advised of the possibility of such
damages.
10. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor and/or the Licensor,
and only if You agree to indemnify, defend, and hold each Contributor and/or the
Licensor harmless for any liability incurred by, or claims asserted against,
such Contributor and/or Licensor by reason of Your accepting any such warranty
or additional liability obligations.
11. Applicable law.
The present license shall be governed by the laws of France.
END OF TERMS AND CONDITIONS
1. APPENDIX: How to apply the PRESENT License to your work
To apply the present License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets “[]” replaced with your own
identifying information. (Dont include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same “printed page” as the copyright notice for easier identification within
1. APPENDIX: How to apply the PRESENT OPENAIR 5G License to your work
To apply the present License to your work, attach the following boilerplate notice, with the
fields enclosed by brackets “[]” replaced with your own identifying information. (Dont
include the brackets!) The text should be enclosed in the appropriate comment syntax for the
file format. We also recommend that a file or class name and description of purpose be
included on the same “printed page” as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Standards Software License, version 1.0, terms and conditions
(the “License”); you may not use this file except in compliance with the
License. You may obtain a copy of the License at [URL link]
Licensed under the License terms and conditions for use, reproduction, and distribution of
OPENAIR 5G software (the “License”);
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.
you may not use this file except in compliance with the License. You may obtain a copy of
the License at
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.
See the License for the specific language governing permissions and limitations
under the License.

View File

@@ -1,201 +0,0 @@
Valid-License-Identifier: OAI-PL-v1.1
URL: https://openairinterface.org/oai-public-license-v1-1/
Usage-Guide:
To use the OAI-PL-v1.1 License put the following text in the header
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
License-Text:
OAI Public License (Version 1.1)
LICENSE TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION OF OPENAIR 5G SOFTWARE.
1. Definitions.
“License” shall mean the terms and conditions for use, reproduction, and distribution set forth
in this document.
“Licensor” shall mean the OpenAirInterface Software Alliance.
“Legal Entity” shall mean the union, at the time an acting entity joins the Alliance, of the
acting entity and all other entities that control, are controlled by, or are under common control
with that entity. For the purposes of this definition, “control” means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii)
beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by
this License.
“Source” form shall mean the preferred form for making modifications, including but not
limited to software source code, documentation source, and configuration files.
“Object” form shall mean any form resulting from mechanical transformation or translation of
a Source form, including but not limited to compiled object code, generated documentation,
and conversions to other media types.
“OpenAirInterface Software Alliance” shall mean the endowment fund established at the
initiative of Eurecom, an educational and research establishment located at Campus Sophia
Tech, 450 Route des Chappes, 06410 Biot, France, which statutes were signed on 18
November 2014.
“Work” shall mean the work of authorship, whether in Source or Object form, made available
under the License, as indicated by a copyright notice that is included in or attached to the
work (an example is provided in the Appendix below).
“Derivative Works” shall mean any work, whether in Source or Object form, that is based on
(or derived from) the Work and for which the editorial revisions, annotations, elaborations, or
other modifications represent, as a whole, an original work of authorship. For the purposes of
this License, Derivative Works shall not include works that remain separable from, or merely
link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
“Contribution” shall mean any work of authorship that is intentionally submitted to Licensor
for inclusion in the Work by the copyright owner or by an individual or Legal Entity
authorized to submit on behalf of the copyright owner. For the purposes of this definition,
“submitted” means any form of electronic, , or written communication sent to the Licensor or
its representatives, including but not limited to communication on electronic mailing lists,
source code control systems, and issue tracking systems that are managed by, or on behalf of,
the Licensor for the purpose of discussing and improving the Work
“Contributor License Agreement” shall mean the agreement signed by any Contributor setting
forth the terms and conditions applicable to its Contribution.
“Contributor” shall mean any individual or Legal Entity on behalf of whom a Contribution
has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, Licensor and each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of, publicly display, publicly
perform, and distribute the Work and such Derivative Works in Source or Object form
3. Grant of Patent License.
3.1 Grant of Patent License for study, testing and research purposes:
Subject to the terms and conditions of this License, Licensor and each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made, use, and otherwise
transfer (excluding selling) the Work, solely for study, testing and research purposes, where
such license applies only to those patent claims licensable by Licensor or such Contributor
that are necessarily infringed respectively by the Work and/or the said Contributor
Contribution(s) alone or by combination of their Contribution(s) with the Work to which
such Contribution(s) was submitted (“Essential Patents”).
3.2 Grant of Patent License for purposes other than study and research:
For purposes other than study, testing and research, and subject to the terms and conditions of
this License, You commit to be prepared to negotiate a non-exclusive, non-transferable, non-
assignable license of Essential Patents with each Contributor and/or the Licensor on Fair,
Reasonable and Non-Discriminatory (“FRAND”) terms and conditions for the use of the
Work or Contribution(s) incorporated within the Work.
Licensor and/or each Contributor, by submitting a Contribution, will identify any of its known
Essential Patent it owns related to the Work and/or its Contribution.
3.3 Patent Litigation
If You institute patent litigation against any entity making use of the Work solely for study,
testing and research purposes (including a cross-claim or counterclaim in a lawsuit) alleging
that the Work or a Contribution incorporated within the Work constitutes direct or
contributory patent infringement, then the patent licenses granted to You under section 3.1 of
this License for that Work shall terminate as of the date such litigation is filed.
4. Sublicensing
You may grant sublicenses under the licenses granted under sections 2 and 3.1 provided that
the sublicense is subject to and inclusive of all the terms of and rights under this License to
which the Work is or was distributed by the OpenAirInterface Software Alliance.
5. Redistribution
Subject to terms and conditions set forth in sections 2 and 3, You may reproduce and
distribute copies of the Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You meet the following
conditions:
1. You must give any other recipients of the Work or Derivative Works a copy of this
License; and
2. You must cause any modified files by You to carry prominent notices stating that You
changed the files; and
3. You must retain, in the Source form of any Derivative Works that You distribute, all
copyright, patent, trademark, and attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of the Derivative Works; and
4. If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative
Works that You distribute must include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not pertain to any part of the
Derivative Works, in at least one of the following places: within a NOTICE text file
distributed as part of the Derivative Works; within the Source form or documentation, if
provided along with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of the
NOTICE file are for informational purposes only and do not modify the License. You may
add Your own attribution notices within Derivative Works that You distribute, alongside or as
an addendum to the NOTICE text from the Work, provided that such additional attribution
notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or distribution of
Your modifications, or for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with the conditions stated in
this License.
6. Submission of Contributions.
Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be
under the terms and conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of any
separate license agreement such as the Contributor License Agreement You may have
executed with Licensor regarding such Contributions.
7. Trademarks.
This License does not grant permission to use the trade names, trademarks, service marks, or
product names of the Licensor, except as required for reasonable and customary use in
describing the origin of the Work and reproducing the content of the NOTICE file.
8. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and
each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including,
without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely
responsible for determining the appropriateness of using or redistributing the Work and
assume any risks associated with your exercise of permissions under this License.
9. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence), contract, or
otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or
agreed to in writing, shall Licensor and any Contributor, as such, be liable to You for
damages, including any direct, indirect, special, incidental, or consequential damages of any
character arising as a result of this License or out of Your use or inability to use the Work
(including but not limited to damages for loss of goodwill, work stoppage, computer failure or
malfunction, or any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
10. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to offer, and
charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations
and/or rights consistent with this License. However, in accepting such obligations, You may
act only on Your own behalf and on Your sole responsibility, not on behalf of any other
Contributor and/or the Licensor, and only if You agree to indemnify, defend, and hold each
Contributor and/or the Licensor harmless for any liability incurred by, or claims asserted
against, such Contributor and/or Licensor by reason of Your accepting any such warranty or
additional liability.
11. Applicable law.
The present license shall be governed by the laws of France.
END OF TERMS AND CONDITIONS

View File

@@ -1,183 +0,0 @@
Valid-License-Identifier: Apache-2.0
SPDX-URL: https://spdx.org/licenses/Apache-2.0.html
Usage-Guide:
To use the Apache License version 2.0 put the following SPDX tag/value
pair into a comment according to the placement guidelines in the
licensing rules documentation:
SPDX-License-Identifier: Apache-2.0
License-Text:
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the
copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other
entities that control, are controlled by, or are under common control with
that entity. For the purposes of this definition, "control" means (i) the
power, direct or indirect, to cause the direction or management of such
entity, whether by contract or otherwise, or (ii) ownership of fifty
percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source,
and configuration files.
"Object" form shall mean any form resulting from mechanical transformation
or translation of a Source form, including but not limited to compiled
object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form,
made available under the License, as indicated by a copyright notice that
is included in or attached to the work (an example is provided in the
Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form,
that is based on (or derived from) the Work and for which the editorial
revisions, annotations, elaborations, or other modifications represent, as
a whole, an original work of authorship. For the purposes of this License,
Derivative Works shall not include works that remain separable from, or
merely link (or bind by name) to the interfaces of, the Work and Derivative
Works thereof.
"Contribution" shall mean any work of authorship, including the original
version of the Work and any modifications or additions to that Work or
Derivative Works thereof, that is intentionally submitted to Licensor for
inclusion in the Work by the copyright owner or by an individual or Legal
Entity authorized to submit on behalf of the copyright owner. For the
purposes of this definition, "submitted" means any form of electronic,
verbal, or written communication sent to the Licensor or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems that
are managed by, or on behalf of, the Licensor for the purpose of discussing
and improving the Work, but excluding communication that is conspicuously
marked or otherwise designated in writing by the copyright owner as "Not a
Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on
behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this
License, each Contributor hereby grants to You a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable copyright license to
reproduce, prepare Derivative Works of, publicly display, publicly
perform, sublicense, and distribute the Work and such Derivative Works
in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this
License, each Contributor hereby grants to You a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable (except as stated in
this section) patent license to make, have made, use, offer to sell,
sell, import, and otherwise transfer the Work, where such license
applies only to those patent claims licensable by such Contributor that
are necessarily infringed by their Contribution(s) alone or by
combination of their Contribution(s) with the Work to which such
Contribution(s) was submitted. If You institute patent litigation
against any entity (including a cross-claim or counterclaim in a
lawsuit) alleging that the Work or a Contribution incorporated within
the Work constitutes direct or contributory patent infringement, then
any patent licenses granted to You under this License for that Work
shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or
Derivative Works thereof in any medium, with or without modifications,
and in Source or Object form, provided that You meet the following
conditions:
a. You must give any other recipients of the Work or Derivative Works a
copy of this License; and
b. You must cause any modified files to carry prominent notices stating
that You changed the files; and
c. You must retain, in the Source form of any Derivative Works that You
distribute, all copyright, patent, trademark, and attribution notices
from the Source form of the Work, excluding those notices that do not
pertain to any part of the Derivative Works; and
d. If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained within
such NOTICE file, excluding those notices that do not pertain to any
part of the Derivative Works, in at least one of the following
places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if
provided along with the Derivative Works; or, within a display
generated by the Derivative Works, if and wherever such third-party
notices normally appear. The contents of the NOTICE file are for
informational purposes only and do not modify the License. You may
add Your own attribution notices within Derivative Works that You
distribute, alongside or as an addendum to the NOTICE text from the
Work, provided that such additional attribution notices cannot be
construed as modifying the License.
You may add Your own copyright statement to Your modifications and may
provide additional or different license terms and conditions for use,
reproduction, or distribution of Your modifications, or for any such
Derivative Works as a whole, provided Your use, reproduction, and
distribution of the Work otherwise complies with the conditions stated
in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any
Contribution intentionally submitted for inclusion in the Work by You to
the Licensor shall be under the terms and conditions of this License,
without any additional terms or conditions. Notwithstanding the above,
nothing herein shall supersede or modify the terms of any separate
license agreement you may have executed with Licensor regarding such
Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
in writing, Licensor provides the Work (and each Contributor provides
its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied, including, without limitation,
any warranties or conditions of TITLE, NON-INFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely
responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your
exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether
in tort (including negligence), contract, or otherwise, unless required
by applicable law (such as deliberate and grossly negligent acts) or
agreed to in writing, shall any Contributor be liable to You for
damages, including any direct, indirect, special, incidental, or
consequential damages of any character arising as a result of this
License or out of the use or inability to use the Work (including but
not limited to damages for loss of goodwill, work stoppage, computer
failure or malfunction, or any and all other commercial damages or
losses), even if such Contributor has been advised of the possibility of
such damages.
9. Accepting Warranty or Additional Liability. While redistributing the
Work or Derivative Works thereof, You may choose to offer, and charge a
fee for, acceptance of support, warranty, indemnity, or other liability
obligations and/or rights consistent with this License. However, in
accepting such obligations, You may act only on Your own behalf and on
Your sole responsibility, not on behalf of any other Contributor, and
only if You agree to indemnify, defend, and hold each Contributor
harmless for any liability incurred by, or claims asserted against, such
Contributor by reason of your accepting any such warranty or additional
liability.
END OF TERMS AND CONDITIONS

View File

@@ -1,30 +0,0 @@
Valid-License-Identifier: BSD-2-Clause
SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html
Usage-Guide:
To use the BSD 2-clause "Simplified" License put the following SPDX
tag/value pair into a comment according to the placement guidelines in
the licensing rules documentation:
SPDX-License-Identifier: BSD-2-Clause
License-Text:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,33 +0,0 @@
Valid-License-Identifier: BSD-3-Clause
SPDX-URL: https://spdx.org/licenses/BSD-3-Clause.html
Usage-Guide:
To use the BSD 3-clause "New" or "Revised" License put the following SPDX
tag/value pair into a comment according to the placement guidelines in
the licensing rules documentation:
SPDX-License-Identifier: BSD-3-Clause
License-Text:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,404 +0,0 @@
Valid-License-Identifier: CC-BY-4.0
SPDX-URL: https://spdx.org/licenses/CC-BY-4.0.html
Usage-Guide:
To use the CC-BY-4.0 License put the following SPDX tag/value pair into a
comment according to the placement guidelines in the licensing rules
documentation:
SPDX-License-Identifier: CC-BY-4.0
License-Text:
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

View File

@@ -1,223 +0,0 @@
Collaborative Standards Software License v1.0 (CSSL)
LICENSE TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION OF
OPENAIRINTERFACE. The pdf version of this document can be downloaded from
https://openairinterface.org/oai-cssl/.
1. Definitions.
“License” shall mean the terms and conditions for use, reproduction, and
distribution set forth in this document.
“Licensor” shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
“Legal Entity” shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, “control” means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity exercising
permissions granted by this License.
“Source” form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
“Object” form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
“Work” shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
“Derivative Works” shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
“Contribution” shall mean any work of authorship that is intentionally submitted
to Licensor for inclusion in the Work by the copyright owner or by an individual
or Legal Entity authorized to submit on behalf of the copyright owner. For the
purposes of this definition, “submitted” means any form of electronic, or
written communication sent to the Licensor or its representatives, including but
not limited to communication on electronic mailing lists, source code control
systems, and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work but excluding
communication that is conspicuously marked or otherwise designated in writing by
the copyright owner or entity authorized by the copyright owner as "Not a
Contribution."
“Contributor License Agreement” shall mean the agreement signed by any
Contributor setting forth the terms and conditions applicable to its
Contribution.
“Contributor” shall mean any individual or Legal Entity on behalf of whom a
Contribution has been received by Licensor and subsequently incorporated within
the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, Licensor and each
Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
Derivative Works of, publicly display, publicly perform, and distribute the Work
and such Derivative Works in Source or Object form.
3. Grant of Patent License.
3.1 Grant of Patent License for study, testing and research purposes:
Subject to the terms and conditions of this License, Licensor and each
Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section) patent
license to make, have made, use, and otherwise transfer (excluding selling) the
Work, solely for study, testing and research purposes, where such license
applies only to those patent claims licensable by Licensor or such Contributor
that are necessarily infringed respectively by the Work and/or the said
Contributor Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted (“Essential Patents”).
3.2 Grant of Patent License for purposes other than study, testing and research:
For purposes other than study, testing and research, and subject to the terms
and conditions of this License, You commit to be prepared to negotiate, in good
faith, a non-exclusive, nontransferable, non-assignable license of Essential
Patents with each Contributor and/or the Licensor on Fair, Reasonable and
Non-Discriminatory (“FRAND”) terms and conditions for the use of the Work or
Contribution(s) incorporated within the Work.
3.3 Patent Litigation
If You institute patent litigation against any entity making use of the Work
solely for study, testing and research purposes (including a cross-claim or
counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated
within the Work constitutes direct or contributory patent infringement, then the
patent licenses granted to You under section 3.1 of this License for that Work
shall terminate as of the date such litigation is filed.
4. Sublicensing
You may grant sublicenses under the licenses granted under sections 2 and 3.1
provided that the sublicense is subject to and inclusive of all the terms of and
rights under this License to which the Work is or was distributed.
5. Redistribution
Subject to terms and conditions set forth in sections 2 and 3, You may reproduce
and distribute copies of the Work or Derivative Works thereof in any medium,
with or without modifications, and in Source or Object form, provided that You
meet the following conditions:
1. You must give any other recipients of the Work or Derivative Works a copy of
this License; and
2. You must cause any modified files by You to carry prominent notices stating
that You changed the files; and
3. You must retain, in the Source form of any Derivative Works that You
distribute, all copyright, patent, trademark, and attribution notices from the
Source form of the Work, excluding those notices that do not pertain to any part
of the Derivative Works; and
4. If the Work includes a “NOTICE” text file as part of its distribution, then
any Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
6. Submission of Contributions.
Any contribution intentionally submitted for inclusion in the Work by You to the
Licensor shall be under the terms and conditions of this License, without any
additional terms or conditions. Notwithstanding the above, nothing herein shall
supersede or modify the terms of any separate license agreement such as the
Contributor License Agreement You may have executed with Licensor regarding such
Contributions.
7. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
8. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with your exercise of
permissions under this License.
9. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall Licensor and any
Contributor, as such, be liable to You for damages, including any direct,
indirect, special, incidental, or consequential damages of any character arising
as a result of this License or out of Your use or inability to use the Work
(including but not limited to damages for loss of goodwill, work stoppage,
computer failure or malfunction, or any and all other commercial damages or
losses), even if such Contributor has been advised of the possibility of such
damages.
10. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor and/or the Licensor,
and only if You agree to indemnify, defend, and hold each Contributor and/or the
Licensor harmless for any liability incurred by, or claims asserted against,
such Contributor and/or Licensor by reason of Your accepting any such warranty
or additional liability obligations.
END OF TERMS AND CONDITIONS
1. APPENDIX: How to apply the PRESENT License to your work
To apply the present License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets “[]” replaced with your own
identifying information. (Dont include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same “printed page” as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Standards Software License, version 1.0, terms and conditions
(the “License”); you may not use this file except in compliance with the
License. You may obtain a copy of the License at [URL link]
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.

View File

@@ -1,28 +0,0 @@
Valid-License-Identifier: MIT
SPDX-URL: https://spdx.org/licenses/MIT.html
Usage-Guide:
To use the MIT License put the following SPDX tag/value pair into a
comment according to the placement guidelines in the licensing rules
documentation:
SPDX-License-Identifier: MIT
License-Text:
MIT License
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

86
NOTICE
View File

@@ -1,86 +0,0 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
The source code is distributed under [**Collaborative Standards Software
License (CSSL) v1.0**](LICENSE). Some files, such as for orchestration,
are distributed under [MIT license](preferred)(MIT.txt). Documentation is
distributed under [Creative Commons Attribution 4.0 International
license](LICENSES/preferred/CC-BY-4.0.txt).
For more details of the license, refer to the `LICENSES` directory for a list
of preferred and exceptionally-applied licenses.
However, the source code also contains third party software that is
acknowledged here for reference.
Credits for source code https://github.com/mouse07410/asn1c:
Github ID mouse07410: BSD-2-Clause License
Credits for https://github.com/simd-everywhere/simde-no-tests.git:
Github ID simd-everywhere: MIT License
Credits for source code common/utils/collection/queue.h:
The Regents of the University of California: BSD 3-Clause Licence
Credits for source code common/utils/collection/tree.h:
Niels Provos provos@citi.umich.edu: BSD 2-Clause Licence
Credits for openair2/UTIL/OPT/packet-rohc.h:
Anders Broman <anders.broman@ericsson.com>: GPL-2.0-or-later
Credits for openair3/NAS/COMMON/milenage.h
Jouni Malinen <j@w1.fi>: BSD 2-Clause License
Credits for source code at:
- openair1/PHY/CODING/crc.h
- openair1/PHY/CODING/crcext.h
- openair1/PHY/CODING/types.h
- openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.c
- openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_aal/nrLDPC_coding_aal.h
Intel Corporation SPDX-License-Identifier: BSD-3-Clause Licence
Credits for source code nFAPI/open-nFAPI:
- Most of the files are from CISCO: Apache 2.0 License
- FAPI/*: CSSL v1.0
- utils/nfapi_hex_parser.c: CSSL v1.0
- nfapi/public_inc/nfapi_common_interface.h: CSSL v1.0
- nfapi/public_inc/nr_nfapi_p7.h: CSSL v1.0
- nfapi/public_inc/fapi_nr_ue_interface.h: CSSL v1.0
Optional software downloaded on demand/if requested by user:
Credits for Yang model radio/fhi_72/mplane/yang/models:
O-RAN Alliance: BSD 3-Clause License
IETF Trust and the persons identified as authors of the code: BSD 2-Clause Licence
Credits for https://github.com/CESNET/libyang:
Czech Educational and Research Network: BSD-3-Clause License
Credits for https://github.com/CESNET/libnetconf2:
Czech Educational and Research Network: BSD-3-Clause License
Credits for https://github.com/google/googletest used for unit test:
Google: BSD 3-Clause License
Credits for https://github.com/google/benchmark used for unit test:
Google: Apache 2.0 License
Credits for https://github.com/google/sanitizers used for the address sanitizer:
Google: Apache 2.0 License
Credits for https://github.com/krallin/tini used for init in containers:
Github ID krallin: MIT License
Credits for https://github.com/EttusResearch/uhd.git:
EttusResearch: GPLv3 License
Credits for https://github.com/mikefarah/yq used for parsing YAML in Docker images:
Github ID mikefarah: MIT License
Credits for https://github.com/intel/pf-bb-config:
Intel: Apache 2.0 License
Credits for https://github.com/Nuand/bladeRF:
Nuand: https://github.com/Nuand/bladeRF/tree/master?tab=License-1-ov-file
Credits for https://github.com/pothosware/SoapySDR
Pothosware: BSL 1.0 License

17
NOTICE.md Normal file
View File

@@ -0,0 +1,17 @@
The source code of openairinterface5g is distributed under **OAI Public License V1.1**.
For more details of the license, refer to [LICENSE](LICENSE) file in the same directory.
However, the source code also contains third party software that is acknowledged here for reference.
## Credits for source code common/utils/collection/queue.h: ##
The Regents of the University of California: BSD 3-Clause Licence.
## Credits for source code common/utils/collection/tree.h: ##
Niels Provos <provos@citi.umich.edu>: BSD 2-Clause Licence.
## Credits for source code openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c and nrLDPC_offload.h: ##
Intel Corporation SPDX-License-Identifier: BSD-3-Clause Licence

View File

@@ -1,15 +1,13 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<h1 align="center">
<a href="https://openairinterface.org/"><img src="https://openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png" alt="OAI" width="550"></a>
</h1>
<p align="center">
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-CSSL--v1.0-blue" alt="License"></a>
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-OAI--Public--V1.1-blue" alt="License"></a>
<a href="https://releases.ubuntu.com/22.04/"><img src="https://img.shields.io/badge/OS-Ubuntu22-Green" alt="Supported OS Ubuntu 22"></a>
<a href="https://releases.ubuntu.com/24.04/"><img src="https://img.shields.io/badge/OS-Ubuntu24-Green" alt="Supported OS Ubuntu 24"></a>
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL9-Green" alt="Supported OS RHEL9"></a>
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore41-Green" alt="Supported OS Fedora 43"></a>
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore41-Green" alt="Supported OS Fedora 41"></a>
</p>
<p align="center">
@@ -33,14 +31,13 @@
# OpenAirInterface License #
* [OAI License Model](http://www.openairinterface.org/?page_id=101)
* [CSSL v1.0](http://www.openairinterface.org/?page_id=698)
* [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698)
The source code is distributed under [**CSSL v1.0**](LICENSE).
Some files, such as for orchestration, are distributed under
[MIT license](preferred)(MIT.txt). Documentation is distributed under
[Creative Commons Attribution 4.0 International license](LICENSES/preferred/CC-BY-4.0.txt).
It is distributed under **OAI Public License V1.1**.
Please see [NOTICE](NOTICE.md) for other licenses which are used in the software.
The license information is distributed under [LICENSE](LICENSE) file in the same directory.
Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources.
# Where to Start #

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: v1
name: oai-physim
description: A Helm chart for physical simulators network function

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: v1
name: oai-physims-4g
description: A Helm subchart for 4G physims network function

View File

@@ -1,5 +1,4 @@
{{/* vim: set filetype=mustache: */}}
{{/* SPDX-License-Identifier: MIT */}}
{{/*
Expand the name of the chart.
*/}}

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: batch/v1
kind: Job
metadata:

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
# Default values for oai-physims-4g
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: v1
kind: ServiceAccount
metadata:

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
# Default values for oai-physim.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: v1
name: oai-physim
description: A Helm chart for physical simulators network function

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: v1
name: oai-physims-5g
description: A Helm subchart for 5G physims network function

View File

@@ -1,5 +1,4 @@
{{/* vim: set filetype=mustache: */}}
{{/* SPDX-License-Identifier: MIT */}}
{{/*
Expand the name of the chart.
*/}}

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: batch/v1
kind: Job
metadata:

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
# Default values for oai-physims-5g
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
apiVersion: v1
kind: ServiceAccount
metadata:

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: MIT
# Default values for oai-physim.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

216
ci-scripts/Jenkinsfile vendored
View File

@@ -1,216 +0,0 @@
#!/bin/groovy
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
def pythonExecutor = params.pythonExecutor
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
def JOB_TIMESTAMP
// Choose test stage name or fallback default
def testStageName = params.pipelineTestStageName != null ? params.pipelineTestStageName : 'Template Test Stage'
// Name of the resource
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def sourceRepository = params.eNB_Repository ?: env.GIT_URL
def sourceBranch = params.eNB_Branch ?: env.GIT_BRANCH
def targetRepository = params.Target_Repository ?: sourceRepository
def targetBranch = params.eNB_TargetBranch ?: 'develop'
def commitID = params.eNB_CommitID ?: env.GIT_COMMIT
def is_MR = params.eNB_mergeRequest ?: false
def flexricOption = ""
def runWithOC = false
//-------------------------------------------------------------------------------
// Pipeline start
pipeline {
agent {
label pythonExecutor
}
options {
timestamps()
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
script {
echo '\u2705 \u001B[94mBuild Init\u001B[0m'
JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim()
}
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${sourceBranch}"
}
}
stage ('Verify Parameters') {
steps {
script {
echo '\u2705 \u001B[94mVerify Parameters\u001B[0m'
def allParametersPresent = true
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
echo "no eNB_SourceCodePath given"
allParametersPresent = false
}
if (params.OC_Credentials != null) {
echo "This pipeline is configured to run with Opensift Cluster."
runWithOC = true
if (params.OC_ProjectName == null) {
echo "no OC_ProjectName given"
allParametersPresent = false
}
}
if (params.Flexric_Tag != null) {
echo "This pipeline is configured to run with a FlexRIC deployment."
echo "Appending FlexRicTag option to the list of options"
flexricOption = "--FlexRicTag=${params.Flexric_Tag}"
echo "Using new Flexric option: ${flexricOption}"
}
echo "CI executor node : ${pythonExecutor}"
echo "Source Repository : ${sourceRepository}"
echo "Source Branch : ${sourceBranch}"
echo "Target Repository : ${targetRepository}"
echo "Target Branch : ${targetBranch}"
echo "Commit ID : ${commitID}"
if (allParametersPresent) {
echo '\u2705 \u001B[94m All parameters are present\u001B[0m'
if (is_MR) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${sourceBranch} --src-commit ${commitID} --target-branch ${targetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${commitID}"
}
} else {
echo "\u274C Some parameters are missing"
sh "./ci-scripts/fail.sh"
}
}
}
}
stage ("Deploy and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[94m Deploy and Test: ${testStageName}\u001B[0m"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
sh """
python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
${flexricOption} ${mainPythonAllXmlFiles}
"""
if (runWithOC) {
withCredentials([usernamePassword(credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password')]) {
sh """
python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
${flexricOption} ${mainPythonAllXmlFiles}
"""
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh """
python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
--eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \
--OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} \
${flexricOption}
"""
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
}
} else {
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh """
python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
--eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \
${flexricOption}
"""
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
stage ("Log Collection") {
steps {
script {
echo '\u2705 \u001B[94mLog Collection\u001B[0m'
dir ('ci-scripts') {
// Zipping all archived log files
sh "mkdir test_logs"
sh "mv *.log* test_logs || true"
// Zip all log files matching cmake_targets/{*.log*,log/*} into test_logs_XXXX.zip
if (fileExists('../cmake_targets/log')) {
sh "mv ../cmake_targets/log/* test_logs || true"
}
sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/"
sh "rm -rf *test_log*/"
if (fileExists("test_logs_${env.BUILD_ID}.zip")) {
archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip"
}
if (fileExists("test_results.html")) {
def reportName = "test_results-${env.JOB_NAME}.html"
sh "mv test_results.html ${reportName}"
sh """
sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' \
-e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' \
-e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' \
-e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' \
-e 's#TEMPLATE_STAGE_NAME#${testStageName}#' ${reportName}
"""
archiveArtifacts artifacts: "${reportName}"
}
}
}
}
}
}
}

View File

@@ -1,6 +1,23 @@
#!/bin/groovy
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
* 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
*/
// Location of the executor node
@@ -18,8 +35,6 @@ def gitCommitAuthorEmailAddr
// list of failing stages
def failingStages = ""
OAI_Registry = "gracehopper3-oai.sboai.cs.eurecom.fr"
pipeline {
agent {
label nodeExecutor
@@ -160,28 +175,6 @@ pipeline {
}
}
}
stage ("Ubuntu-Jetson-Image-Builder") {
steps {
script {
triggerSlaveJob ('RAN-Ubuntu-Jetson-Image-Builder', 'Ubuntu-Jetson-Image-Builder')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
ubuntuJetsonBuildStatus = finalizeSlaveJob('RAN-Ubuntu-Jetson-Image-Builder')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += ubuntuJetsonBuildStatus
}
}
}
}
stage ("RHEL-Cluster-Image-Builder") {
steps {
script {
@@ -250,24 +243,6 @@ pipeline {
}
}
}
stage ("DockerHub-Push") {
when { expression {doBuild && "PUSH".equals(env.gitlabActionType)} }
steps {
script {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
triggerSlaveJob ('RAN-DockerHub-Push', 'DockerHub-Push')
}
}
}
post {
failure {
script {
echo "Push to Docker-Hub KO"
failingStages += '\n * RAN-DockerHub-Push'
}
}
}
}
stage ("Image Test Processes") {
when { expression {doBuild} }
parallel {
@@ -294,52 +269,6 @@ pipeline {
}
}
}
stage ("PhySim-GraceHopper-5G") {
when { expression {do5Gtest || do5GUeTest} }
steps {
script {
triggerSlaveJob ('RAN-PhySim-GraceHopper-5G', 'PhySim-GraceHopper-5G')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
physimGH5GStatus = finalizeSlaveJob('RAN-PhySim-GraceHopper-5G')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += physimGH5GStatus
}
}
}
}
stage ("Channel-Simulation") {
when { expression {do5Gtest || do5GUeTest} }
steps {
script {
triggerSlaveJob ('RAN-Channel-Simulation', 'Channel-Simulation')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
channelSimStatus = finalizeSlaveJob('RAN-Channel-Simulation')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += channelSimStatus
}
}
}
}
stage ("PhySim-Cluster-4G") {
when { expression {do4Gtest} }
steps {
@@ -386,29 +315,6 @@ pipeline {
}
}
}
stage ("VRT-Sim-Test-5G") {
when { expression {do5Gtest || do5GUeTest} }
steps {
script {
triggerSlaveJob ('RAN-VRT-Sim-Test-5G', 'VRT-Sim-Test-5G')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
vrtSim5GStatus = finalizeSlaveJob('RAN-VRT-Sim-Test-5G')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += vrtSim5GStatus
}
}
}
}
stage ("RF-Sim-Test-5G") {
when { expression {do5Gtest || do5GUeTest} }
steps {
@@ -709,11 +615,11 @@ pipeline {
}
}
}
stage ("SA-Multi-Antenna-CN5G") {
stage ("SA-2x2-Module-CN5G") {
when { expression {do5Gtest} }
steps {
script {
triggerSlaveJob ('RAN-SA-Multi-Antenna-CN5G', 'SA-Multi-Antenna-CN5G')
triggerSlaveJob ('RAN-SA-2x2-Module-CN5G', 'SA-2x2-Module-CN5G')
}
}
post {
@@ -721,13 +627,13 @@ pipeline {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
saMultiAntennaStatus = finalizeSlaveJob('RAN-SA-Multi-Antenna-CN5G')
saTDD2x2Status = finalizeSlaveJob('RAN-SA-2x2-Module-CN5G')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += saMultiAntennaStatus
failingStages += saTDD2x2Status
}
}
}
@@ -755,52 +661,6 @@ pipeline {
}
}
}
stage ("SA-Handover-CN5G") {
when { expression {do5Gtest} }
steps {
script {
triggerSlaveJob ('RAN-SA-Handover-CN5G', 'SA-Handover-CN5G')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
saHandoverStatus = finalizeSlaveJob('RAN-SA-Handover-CN5G')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += saHandoverStatus
}
}
}
}
stage ("SA-AERIAL-OAIUE-CN5G") {
when { expression {do5Gtest || do5GUeTest} }
steps {
script {
triggerSlaveJob ('RAN-SA-AERIAL-OAIUE-CN5G', 'SA-AERIAL-OAIUE-CN5G')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
saAERIALOAIUEStatus = finalizeSlaveJob('RAN-SA-AERIAL-OAIUE-CN5G')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += saAERIALOAIUEStatus
}
}
}
}
stage ("SA-OAIUE-CN5G") {
when { expression {do5Gtest || do5GUeTest} }
steps {
@@ -826,6 +686,23 @@ pipeline {
}
}
}
stage ("DockerHub-Push") {
when { expression {doBuild && "PUSH".equals(env.gitlabActionType)} }
steps {
script {
triggerSlaveJob ('RAN-DockerHub-Push', 'DockerHub-Push')
}
}
post {
failure {
script {
echo "Push to Docker-Hub KO"
currentBuild.result = 'FAILURE'
failingStages += '\n * RAN-DockerHub-Push'
}
}
}
}
}
post {
success {
@@ -889,11 +766,11 @@ def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.gitlabMergeRequestLastCommit
shortenShaOne = shortenShaOne.trim()
branchName = env.gitlabSourceBranch.replaceAll("/", "-").trim()
fullRanTag = OAI_Registry + '/oai-gnb:' + env.gitlabSourceBranch + '-' + shortenShaOne
fullRanTag = 'porcepix.sboai.cs.eurecom.fr/oai-gnb:' + env.gitlabSourceBranch + '-' + shortenShaOne
} else {
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.GIT_COMMIT
shortenShaOne = shortenShaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + shortenShaOne
fullRanTag = 'porcepix.sboai.cs.eurecom.fr/oai-gnb:develop-' + shortenShaOne
}
// Workaround for the "cancelled" GitLab pipeline notification
// The slave job is triggered with the propagate false so the following commands are executed

View File

@@ -0,0 +1,228 @@
#!/bin/groovy
/*
* 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
*/
// Location of the executor node
def pythonExecutor = params.pythonExecutor
// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
// Name of the test stage
def testStageName = params.pipelineTestStageName
// Name of the resource
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess = false
def eNB_TargetBranch
def directoryExistsGlob(fileNameWithGlob) {
/* if multiple directories match, will join their names and call fileExists() on that */
def dir = sh returnStdout: true, script: 'find . -name \'' + fileNameWithGlob + '\' -type d'
dir = dir.replaceAll("\n", "").trim()
echo "matching '" + fileNameWithGlob + "' found: '" + dir + "'"
if (dir == "")
return false
return fileExists(dir)
}
//-------------------------------------------------------------------------------
// Pipeline start
pipeline {
agent {
label pythonExecutor
}
options {
timestamps()
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${params.eNB_Branch}"
}
}
stage ('Verify Parameters') {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
def allParametersPresent = true
// It is already to late to check it
if (params.pythonExecutor != null) {
echo "eNB CI executor node : ${pythonExecutor}"
}
// If not present picking a default Stage Name
if (params.pipelineTestStageName == null) {
// picking default
testStageName = 'Template Test Stage'
}
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
echo "no eNB_SourceCodePath given"
allParametersPresent = false
}
// the following 4 parameters should be pushed by the master trigger
// if not present, take the job GIT variables (used for developing)
if (params.eNB_Repository == null) {
eNB_Repository = env.GIT_URL
} else {
eNB_Repository = params.eNB_Repository
}
echo "eNB_Repository : ${eNB_Repository}"
if (params.eNB_Branch == null) {
eNB_Branch = env.GIT_BRANCH
} else {
eNB_Branch = params.eNB_Branch
}
echo "eNB_Branch : ${eNB_Branch}"
if (params.eNB_CommitID == null) {
eNB_CommitID = env.GIT_COMMIT
} else {
eNB_CommitID = params.eNB_CommitID
}
echo "eNB_CommitID : ${eNB_CommitID}"
if (params.eNB_mergeRequest != null) {
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
if (eNB_AllowMergeRequestProcess) {
if (params.eNB_TargetBranch != null) {
eNB_TargetBranch = params.eNB_TargetBranch
} else {
eNB_TargetBranch = 'develop'
}
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
}
} else {
echo "no eNB_mergeRequest given - not merging develop"
}
if (params.OC_Credentials == null) {
echo "no OC_Credentials given"
allParametersPresent = false
}
if (params.OC_ProjectName == null) {
echo "no OC_ProjectName given"
allParametersPresent = false
}
if (params.pythonTestXmlFile == null) {
echo "no pythonTestXmlFile given"
allParametersPresent = false
}
if (allParametersPresent) {
echo "All parameters are present"
if (eNB_AllowMergeRequestProcess) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${eNB_CommitID}"
}
} else {
echo "Some parameters are missing"
sh "./ci-scripts/fail.sh"
}
}
}
}
stage ("Deploy and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
withCredentials([
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password']
]) {
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
}
stage ("Log Collection") {
steps {
script {
dir ('ci-scripts') {
if (directoryExistsGlob("build_log_*")) {
sh "zip -r -qq build_log_${env.BUILD_ID}.zip build_log_*/*"
sh "rm -rf build_log_*/"
archiveArtifacts artifacts: "build_log_${env.BUILD_ID}.zip"
}
if (directoryExistsGlob("test_log_*")) {
sh "zip -r -qq test_log_${env.BUILD_ID}.zip test_log_*/*"
sh "rm -rf test_log_*/"
archiveArtifacts artifacts: "test_log_${env.BUILD_ID}.zip"
}
if (fileExists("test_results.html")) {
sh "mv test_results.html test_results-${env.JOB_NAME}.html"
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html"
}
}
}
}
}
}
}

View File

@@ -1,6 +1,23 @@
#!/bin/groovy
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
* 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
*/
def node = "${params.JenkinsNode}"

223
ci-scripts/Jenkinsfile-nrue Normal file
View File

@@ -0,0 +1,223 @@
#!/bin/groovy
/*
* 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
*/
// Location of the executor node
def pythonExecutor = params.pythonExecutor
// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
// Name of the test stage
def testStageName = params.pipelineTestStageName
// Name of the resource
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess = false
def eNB_TargetBranch
// Flags
def scmEvent = false
def upstreamEvent = false
//-------------------------------------------------------------------------------
// Pipeline start
pipeline {
agent {
label pythonExecutor
}
options {
timestamps()
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${params.eNB_Branch}"
}
}
stage ('Verify Parameters') {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
def allParametersPresent = true
// It is already to late to check it
if (params.pythonExecutor != null) {
echo "eNB CI executor node : ${pythonExecutor}"
}
// If not present picking a default Stage Name
if (params.pipelineTestStageName == null) {
// picking default
testStageName = 'Template Test Stage'
}
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
allParametersPresent = false
}
// the following 4 parameters should be pushed by the master trigger
// if not present, take the job GIT variables (used for developing)
if (params.eNB_Repository == null) {
eNB_Repository = env.GIT_URL
} else {
eNB_Repository = params.eNB_Repository
}
echo "eNB_Repository : ${eNB_Repository}"
if (params.eNB_Branch == null) {
eNB_Branch = env.GIT_BRANCH
} else {
eNB_Branch = params.eNB_Branch
}
echo "eNB_Branch : ${eNB_Branch}"
if (params.eNB_CommitID == null) {
eNB_CommitID = env.GIT_COMMIT
} else {
eNB_CommitID = params.eNB_CommitID
}
echo "eNB_CommitID : ${eNB_CommitID}"
if (params.eNB_mergeRequest != null) {
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
if (eNB_AllowMergeRequestProcess) {
if (params.eNB_TargetBranch != null) {
eNB_TargetBranch = params.eNB_TargetBranch
} else {
eNB_TargetBranch = 'develop'
}
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
}
}
if (params.OC_Credentials == null) {
allParametersPresent = false
}
if (params.OC_ProjectName == null) {
allParametersPresent = false
}
if (allParametersPresent) {
echo "All parameters are present"
if (eNB_AllowMergeRequestProcess) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${eNB_CommitID}"
}
} else {
echo "Some parameters are missing"
sh "./ci-scripts/fail.sh"
}
}
}
}
stage ("Deploy and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
// If not present picking a default XML file
if (params.pythonTestXmlFile == null) {
// picking default
testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
echo "Test XML file(default): ${testXMLFile}"
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
} else {
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
}
withCredentials([
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password']
]) {
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
}
stage ("Log Collection") {
steps {
script {
dir ('ci-scripts') {
// Zipping all archived log files
sh "mkdir test_logs"
sh "mv *.log* test_logs || true"
// Zip all log files matching cmake_targets/{*.log*,log/*} into test_logs_XXXX.zip
if (fileExists('../cmake_targets/log')) {
sh "mv ../cmake_targets/log/* test_logs || true"
}
sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/"
sh "rm -rf *test_log*/"
if (fileExists("test_logs_${env.BUILD_ID}.zip")) {
archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip"
}
if (fileExists("test_results.html")) {
sh "mv test_results.html test_results-${env.JOB_NAME}.html"
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,224 @@
#!/bin/groovy
/*
* 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
*/
// Location of the executor node
def pythonExecutor = params.pythonExecutor
// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
// Name of the test stage
def testStageName = params.pipelineTestStageName
// Name of the resource
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess = false
def eNB_TargetBranch
// Flags
def scmEvent = false
def upstreamEvent = false
//-------------------------------------------------------------------------------
// Pipeline start
pipeline {
agent {
label pythonExecutor
}
options {
timestamps()
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${params.eNB_Branch}"
}
}
stage ('Verify Parameters') {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
def allParametersPresent = true
// It is already to late to check it
if (params.pythonExecutor != null) {
echo "eNB CI executor node : ${pythonExecutor}"
}
// If not present picking a default Stage Name
if (params.pipelineTestStageName == null) {
// picking default
testStageName = 'Template Test Stage'
}
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
allParametersPresent = false
}
// the following 4 parameters should be pushed by the master trigger
// if not present, take the job GIT variables (used for developing)
if (params.eNB_Repository == null) {
eNB_Repository = env.GIT_URL
} else {
eNB_Repository = params.eNB_Repository
}
echo "eNB_Repository : ${eNB_Repository}"
if (params.eNB_Branch == null) {
eNB_Branch = env.GIT_BRANCH
} else {
eNB_Branch = params.eNB_Branch
}
echo "eNB_Branch : ${eNB_Branch}"
if (params.eNB_CommitID == null) {
eNB_CommitID = env.GIT_COMMIT
} else {
eNB_CommitID = params.eNB_CommitID
}
echo "eNB_CommitID : ${eNB_CommitID}"
if (params.eNB_mergeRequest != null) {
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
if (eNB_AllowMergeRequestProcess) {
if (params.eNB_TargetBranch != null) {
eNB_TargetBranch = params.eNB_TargetBranch
} else {
eNB_TargetBranch = 'develop'
}
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
}
}
if (params.OC_Credentials == null) {
allParametersPresent = false
}
if (params.OC_ProjectName == null) {
allParametersPresent = false
}
if (allParametersPresent) {
echo "All parameters are present"
if (eNB_AllowMergeRequestProcess) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${eNB_CommitID}"
}
} else {
echo "Some parameters are missing"
sh "./ci-scripts/fail.sh"
}
}
}
}
stage ("Deploy and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
// If not present picking a default XML file
if (params.pythonTestXmlFile == null) {
// picking default
testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
echo "Test XML file(default): ${testXMLFile}"
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
} else {
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
}
withCredentials([
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password']
]) {
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
}
stage ("Log Collection") {
steps {
script {
dir ('ci-scripts') {
// Zipping all archived log files
sh "mkdir test_logs"
sh "mv *.log* test_logs || true"
// Zip all log files matching cmake_targets/{*.log*,log/*} into test_logs_XXXX.zip
if (fileExists('../cmake_targets/log')) {
sh "mv ../cmake_targets/log/* test_logs || true"
}
sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/"
sh "rm -rf *test_log*/"
if (fileExists("test_logs_${env.BUILD_ID}.zip")) {
archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip"
}
if (fileExists("test_results.html")) {
sh "mv test_results.html test_results-${env.JOB_NAME}.html"
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html"
}
}
}
}
}
}
}

View File

@@ -1,6 +1,23 @@
#!/bin/groovy
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
* 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
*/
// Location of the python executor node shall be in the same subnet as the others servers
@@ -14,9 +31,6 @@ if (params.LockResources != null && params.LockResources.trim().length() > 0)
// Docker Hub account to push to
def DH_Account = "oaisoftwarealliance"
// internal registry to use
def OAI_Registry = "gracehopper3-oai.sboai.cs.eurecom.fr"
pipeline {
agent {
label nodeExecutor
@@ -65,22 +79,14 @@ pipeline {
def listOfImages = ["oai-enb", "oai-gnb", "oai-lte-ue", "oai-nr-ue", "oai-nr-cuup", "oai-gnb-fhi72"]
// Logging in on both registries
sh "docker login -u ${DH_Username} -p ${DH_Password} > /dev/null 2>&1"
sh "docker login -u oaicicd -p oaicicd ${OAI_Registry} > /dev/null 2>&1"
sh "docker login -u oaicicd -p oaicicd porcepix.sboai.cs.eurecom.fr > /dev/null 2>&1"
listOfImages.eachWithIndex { item, iindex ->
if (["oai-gnb", "oai-nr-ue", "oai-nr-cuup"].contains(item)) {
// For images built on AMD64 and ARMv8 Jetson
echo "Pushing image '${item}' for both AMD64 and ARM64 architectures with tags: ${WEEK_TAG} and develop"
sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop || true"
sh "docker buildx imagetools create --tag ${DH_Account}/${item}:${WEEK_TAG} ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}"
sh "docker buildx imagetools create --tag ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}"
} else {
sh "docker pull --quiet ${OAI_Registry}/${item}:develop-${WEEK_SHA}"
sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:develop"
sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:${WEEK_TAG}"
sh "docker push --quiet ${DH_Account}/${item}:develop"
sh "docker push --quiet ${DH_Account}/${item}:${WEEK_TAG}"
}
sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:develop-${WEEK_SHA} || true"
sh "docker pull --quiet porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA}"
sh "docker image tag porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:develop"
sh "docker image tag porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:${WEEK_TAG}"
sh "docker push --quiet ${DH_Account}/${item}:${WEEK_TAG}"
sh "docker push --quiet ${DH_Account}/${item}:develop"
sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop porcepix.sboai.cs.eurecom.fr/${item}:develop-${WEEK_SHA}"
}
// Proxy is not following the same pattern.
sh "docker image tag proxy:develop ${DH_Account}/proxy:develop"
@@ -89,7 +95,7 @@ pipeline {
sh "docker push --quiet ${DH_Account}/proxy:${WEEK_TAG}"
sh "docker rmi ${DH_Account}/proxy:develop ${DH_Account}/proxy:${WEEK_TAG}"
// Logging out on both registries
sh "docker logout ${OAI_Registry} > /dev/null 2>&1"
sh "docker logout porcepix.sboai.cs.eurecom.fr > /dev/null 2>&1"
sh "docker logout > /dev/null 2>&1"
}
}
@@ -99,7 +105,7 @@ pipeline {
post {
always {
script {
sh "docker logout ${OAI_Registry} > /dev/null 2>&1"
sh "docker logout porcepix.sboai.cs.eurecom.fr > /dev/null 2>&1"
sh "docker logout > /dev/null 2>&1"
echo "End of Registry Push"
}

View File

@@ -0,0 +1,250 @@
#!/bin/groovy
/*
* 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
*/
// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
// Location of the python executor node shall be in the same subnet as the others servers
def pythonExecutor = params.pythonExecutor
// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
// Name of the test stage
def testStageName = params.pipelineTestStageName
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Terminate Status
def termENB = 0
def termStatusArray = new Boolean[termENB + 1]
termStatusArray[termENB] = false
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess = false
def eNB_TargetBranch
def doEpcLogCollection = true
pipeline {
agent {
label pythonExecutor
}
options {
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${params.eNB_Branch}"
}
}
stage ("Verify Parameters") {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
def allParametersPresent = true
// It is already to late to check it
if (params.pythonExecutor != null) {
echo "eNB CI executor node : ${pythonExecutor}"
}
// If not present picking a default Stage Name
if (params.pipelineTestStageName == null) {
// picking default
testStageName = 'Template Test Stage'
}
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
allParametersPresent = false
}
// the following 4 parameters should be pushed by the master trigger
// if not present, take the job GIT variables (used for developing)
if (params.eNB_Repository == null) {
eNB_Repository = env.GIT_URL
} else {
eNB_Repository = params.eNB_Repository
}
echo "eNB_Repository : ${eNB_Repository}"
if (params.eNB_Branch == null) {
eNB_Branch = env.GIT_BRANCH
} else {
eNB_Branch = params.eNB_Branch
}
echo "eNB_Branch : ${eNB_Branch}"
if (params.eNB_CommitID == null) {
eNB_CommitID = env.GIT_COMMIT
} else {
eNB_CommitID = params.eNB_CommitID
}
echo "eNB_CommitID : ${eNB_CommitID}"
if (params.eNB_mergeRequest != null) {
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
if (eNB_AllowMergeRequestProcess) {
if (params.eNB_TargetBranch != null) {
eNB_TargetBranch = params.eNB_TargetBranch
} else {
eNB_TargetBranch = 'develop'
}
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
}
}
if (allParametersPresent) {
echo "All parameters are present"
if (eNB_AllowMergeRequestProcess) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${eNB_CommitID}"
}
} else {
currentBuild.result = 'ABORTED'
error('Stopping early because some parameters are missing')
}
}
}
}
stage ("Build and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
// If not present picking a default XML file
if (params.pythonTestXmlFile == null) {
// picking default
testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
echo "Test XML file(default): ${testXMLFile}"
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
} else {
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
}
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
stage ("Terminate") {
parallel {
stage('Terminate eNB') {
steps {
echo '\u2705 \u001B[32mTerminate eNB\u001B[0m'
sh "python3 ci-scripts/main.py --mode=TerminateeNB"
}
post {
success {
script {
termStatusArray[termENB] = true
}
}
}
}
}
}
stage('Log Collection') {
parallel {
stage('Log Collection (eNB - Run)') {
steps {
echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
script {
if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
}
if(fileExists("ci-scripts/test_results.html")) {
sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
archiveArtifacts "test_results-${JOB_NAME}.html"
}
}
}
}
}
}
}
post {
always {
script {
if (params.pipelineZipsConsoleLog != null) {
if (params.pipelineZipsConsoleLog) {
echo "Archiving Jenkins console log"
sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
}
}
}
}
}
// Making sure that we really shutdown every thing before leaving
failure {
script {
if (!termStatusArray[termENB]) {
sh "python3 ci-scripts/main.py --mode=TerminateeNB"
}
}
}
}
}

View File

@@ -0,0 +1,225 @@
#!/bin/groovy
/*
* 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
*/
// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
// Location of the python executor node shall be in the same subnet as the others servers
def pythonExecutor = params.pythonExecutor
// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
// Name of the test stage
def testStageName = params.pipelineTestStageName
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess = false
def eNB_TargetBranch
pipeline {
agent {
label pythonExecutor
}
options {
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${params.eNB_Branch}"
}
}
stage ("Verify Parameters") {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
def allParametersPresent = true
// It is already to late to check it
if (params.pythonExecutor != null) {
echo "eNB CI executor node : ${pythonExecutor}"
}
// If not present picking a default Stage Name
if (params.pipelineTestStageName == null) {
// picking default
testStageName = 'Template Test Stage'
}
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
allParametersPresent = false
}
// the following 4 parameters should be pushed by the master trigger
// if not present, take the job GIT variables (used for developing)
if (params.eNB_Repository == null) {
eNB_Repository = env.GIT_URL
} else {
eNB_Repository = params.eNB_Repository
}
echo "eNB_Repository : ${eNB_Repository}"
if (params.eNB_Branch == null) {
eNB_Branch = env.GIT_BRANCH
} else {
eNB_Branch = params.eNB_Branch
}
echo "eNB_Branch : ${eNB_Branch}"
if (params.eNB_CommitID == null) {
eNB_CommitID = env.GIT_COMMIT
} else {
eNB_CommitID = params.eNB_CommitID
}
echo "eNB_CommitID : ${eNB_CommitID}"
if (params.eNB_mergeRequest != null) {
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
if (eNB_AllowMergeRequestProcess) {
if (params.eNB_TargetBranch != null) {
eNB_TargetBranch = params.eNB_TargetBranch
} else {
eNB_TargetBranch = 'develop'
}
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
}
}
if (allParametersPresent) {
echo "All parameters are present"
if (eNB_AllowMergeRequestProcess) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${eNB_CommitID}"
}
} else {
echo "Some parameters are missing"
sh "./ci-scripts/fail.sh"
}
}
}
}
stage ("Build and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
// If not present picking a default XML file
if (params.pythonTestXmlFile == null) {
// picking default
testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
echo "Test XML file(default): ${testXMLFile}"
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
} else {
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
}
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
stage ("Terminate") {
parallel {
stage('Terminate eNB') {
steps {
echo '\u2705 \u001B[32mTerminate eNB\u001B[0m'
sh "python3 ci-scripts/main.py --mode=TerminateeNB"
}
}
}
}
stage('Log Collection') {
parallel {
stage('Log Collection (eNB - Run)') {
steps {
echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
script {
if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
}
if(fileExists("ci-scripts/test_results.html")) {
sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
archiveArtifacts "test_results-${JOB_NAME}.html"
}
}
}
}
}
}
}
post {
always {
script {
if (params.pipelineZipsConsoleLog != null) {
if (params.pipelineZipsConsoleLog) {
echo "Archiving Jenkins console log"
sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,216 @@
#!/bin/groovy
/*
* 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
*/
// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
// Location of the python executor node shall be in the same subnet as the others servers
def pythonExecutor = params.pythonExecutor
// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
// Name of the test stage
def testStageName = params.pipelineTestStageName
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess
def eNB_TargetBranch
//Status fed to the database
def StatusForDb = ""
pipeline {
agent {label pythonExecutor}
options {
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${params.eNB_Branch}"
}
}
stage ("Verify Parameters") {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
def allParametersPresent = true
// It is already to late to check it
if (params.pythonExecutor != null) {
echo "eNB CI executor node : ${pythonExecutor}"
}
// If not present picking a default Stage Name
if (params.pipelineTestStageName == null) {
// picking default
testStageName = 'Template Test Stage'
}
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
allParametersPresent = false
}
// the following 4 parameters should be pushed by the master trigger
// if not present, take the job GIT variables (used for developing)
if (params.eNB_Repository == null) {
eNB_Repository = env.GIT_URL
} else {
eNB_Repository = params.eNB_Repository
}
echo "eNB_Repository : ${eNB_Repository}"
if (params.eNB_Branch == null) {
eNB_Branch = env.GIT_BRANCH
} else {
eNB_Branch = params.eNB_Branch
}
echo "eNB_Branch : ${eNB_Branch}"
if (params.eNB_CommitID == null) {
eNB_CommitID = env.GIT_COMMIT
} else {
eNB_CommitID = params.eNB_CommitID
}
echo "eNB_CommitID : ${eNB_CommitID}"
if (params.eNB_mergeRequest!= null) {
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
if (eNB_AllowMergeRequestProcess) {
if (params.eNB_TargetBranch != null) {
eNB_TargetBranch = params.eNB_TargetBranch
} else {
eNB_TargetBranch = 'develop'
}
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
}
}
if (allParametersPresent) {
echo "All parameters are present"
if (eNB_AllowMergeRequestProcess) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${eNB_CommitID}"
}
} else {
echo "Some parameters are missing"
sh "./ci-scripts/fail.sh"
}
}
}
}
stage ("Build and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
// If not present picking a default XML file
if (params.pythonTestXmlFile == null) {
// picking default
testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
echo "Test XML file(default): ${testXMLFile}"
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
} else {
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
}
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
stage('Log Collection') {
parallel {
stage('Log Collection (eNB - Run)') {
steps {
echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
script {
if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
}
}
}
}
}
}
}
post {
always {
script {
if(fileExists("ci-scripts/test_results.html")) {
sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
archiveArtifacts "test_results-${JOB_NAME}.html"
}
if (params.pipelineZipsConsoleLog != null) {
if (params.pipelineZipsConsoleLog) {
echo "Archiving Jenkins console log"
sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
}
}
}
}
}
}
}

View File

@@ -0,0 +1,260 @@
#!/bin/groovy
/*
* 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
*/
// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
// Location of the python executor node shall be in the same subnet as the others servers
def pythonExecutor = params.pythonExecutor
// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true
// Name of the test stage
def testStageName = params.pipelineTestStageName
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
// Terminate Status
def termUE = 0
def termENB = 1
def termSPGW = 2
def termMME = 3
def termHSS = 4
def termStatusArray = new Boolean[termHSS + 1]
termStatusArray[termUE] = false
termStatusArray[termENB] = false
termStatusArray[termSPGW] = false
termStatusArray[termMME] = false
termStatusArray[termHSS] = false
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess = false
def eNB_TargetBranch
def flexricOption = ""
pipeline {
agent {
label pythonExecutor
}
options {
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage("Build Init") {
steps {
// update the build name and description
buildName "${params.eNB_MR}"
buildDescription "Branch : ${params.eNB_Branch}"
}
}
stage ("Verify Parameters") {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
def allParametersPresent = true
// It is already to late to check it
if (params.pythonExecutor != null) {
echo "eNB CI executor node : ${pythonExecutor}"
}
// If not present picking a default Stage Name
if (params.pipelineTestStageName == null) {
// picking default
testStageName = 'Template Test Stage'
}
if (params.LockResources == null) {
echo "no LockResources given"
allParametersPresent = false
}
if (params.eNB_SourceCodePath == null) {
allParametersPresent = false
}
// the following 4 parameters should be pushed by the master trigger
// if not present, take the job GIT variables (used for developing)
if (params.eNB_Repository == null) {
eNB_Repository = env.GIT_URL
} else {
eNB_Repository = params.eNB_Repository
}
echo "eNB_Repository : ${eNB_Repository}"
if (params.eNB_Branch == null) {
eNB_Branch = env.GIT_BRANCH
} else {
eNB_Branch = params.eNB_Branch
}
echo "eNB_Branch : ${eNB_Branch}"
if (params.eNB_CommitID == null) {
eNB_CommitID = env.GIT_COMMIT
} else {
eNB_CommitID = params.eNB_CommitID
}
echo "eNB_CommitID : ${eNB_CommitID}"
if (params.eNB_mergeRequest != null) {
eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
if (eNB_AllowMergeRequestProcess) {
if (params.eNB_TargetBranch != null) {
eNB_TargetBranch = params.eNB_TargetBranch
} else {
eNB_TargetBranch = 'develop'
}
echo "eNB_TargetBranch : ${eNB_TargetBranch}"
}
}
if (params.Flexric_Tag != null) {
echo "This pipeline is configured to run with a FlexRIC deployment."
echo "Appending FlexRicTag option to the list of options"
flexricOption = "--FlexRicTag=${params.Flexric_Tag}"
echo "Using new Flexric option: ${flexricOption}"
}
if (allParametersPresent) {
echo "All parameters are present"
if (eNB_AllowMergeRequestProcess) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
} else if (eNB_CommitID != 'develop') {
sh "git fetch"
sh "git checkout -f ${eNB_CommitID}"
}
} else {
error "Some parameters are missing"
}
}
}
}
stage ("Build and Test") {
steps {
script {
dir ('ci-scripts') {
echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
// If not present picking a default XML file
if (params.pythonTestXmlFile == null) {
// picking default
testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
echo "Test XML file(default): ${testXMLFile}"
mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
} else {
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
echo "Test XML file : ${xmlFile}"
} else {
echo "Test XML file ${xmlFile}: no such file"
}
}
}
sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} ${mainPythonAllXmlFiles}"
String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
buildStageStatus = false
}
}
}
sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
}
}
}
}
stage ("Terminate") {
parallel {
stage('Terminate eNB') {
steps {
echo '\u2705 \u001B[32mTerminate eNB\u001B[0m'
sh "python3 ci-scripts/main.py --mode=TerminateeNB"
}
post {
success {
script {
termStatusArray[termENB] = true
}
}
}
}
}
}
stage('Log Collection') {
parallel {
stage('Log Collection (eNB - Run)') {
steps {
echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
script {
if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
}
if(fileExists("ci-scripts/test_results.html")) {
sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
archiveArtifacts "test_results-${JOB_NAME}.html"
}
}
}
}
}
}
}
post {
always {
script {
if (params.pipelineZipsConsoleLog != null) {
if (params.pipelineZipsConsoleLog) {
echo "Archiving Jenkins console log"
sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
}
}
}
}
}
// Making sure that we really shutdown every thing before leaving
failure {
script {
if (!termStatusArray[termENB]) {
sh "python3 ci-scripts/main.py --mode=TerminateeNB"
}
}
}
}
}

View File

@@ -1,5 +1,3 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
This document outlines how to use the OAI CI framework and gives a quickstart.
[[_TOC_]]

View File

@@ -1,5 +1,23 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
# * 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
# */
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
@@ -15,6 +33,7 @@
#-----------------------------------------------------------
import sys # arg
import re # reg
import yaml
import constants as CONST
#-----------------------------------------------------------
@@ -24,8 +43,11 @@ import constants as CONST
def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
py_param_file_present = False
py_params={}
force_local = False
date_fmt = None
while len(argvs) > 1:
myArgv = argvs.pop(1) # 0th is this file's name
@@ -38,9 +60,6 @@ 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)
@@ -143,6 +162,9 @@ 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)
@@ -150,4 +172,4 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
HELP.GenericHelp(CONST.Version)
sys.exit('Invalid Parameter: ' + myArgv)
return mode, force_local, date_fmt
return py_param_file_present, py_params, mode, force_local

View File

@@ -44,4 +44,4 @@ rf_driver: {
#endif
tx_gain: 75.0, /* TX gain (in dB) */
rx_gain: 52.0, /* RX gain (in dB) */
rx_gain: 55.0, /* RX gain (in dB) */

18
ci-scripts/as_ue/oai_ext_app.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
ue_id="$1" # UE id
duration="$2" # Sim duration
shift
shift
function end
{
exit 0
}
trap end INT TERM
echo "ip netns exec $ue_id $@ > /tmp/test_${ue_id}.log"
ip netns exec $ue_id $@ > /tmp/test_$ue_id.log

View File

@@ -1,177 +0,0 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#!/usr/bin/env python3
import argparse
import logging
import itertools
import usb.core
import usb.util
import sys
import time
logging.basicConfig(
level=logging.DEBUG,
stream=sys.stdout,
format="%(message)s"
)
# helper class parsing command line options for channels and attenuators
class ValidateChAtt(argparse.Action):
def _parse_channels(s):
if len(s.split("-")) == 2:
s, e = [int(x) for x in s.split("-")]
chs = [x for x in range(s, e+1)]
if len(chs) == 0:
raise Exception(f"empty range")
elif len(s.split(",")) > 1:
chs = [int(x) for x in s.split(",")]
elif s.isdigit():
chs = [int(s)]
else:
raise Exception(f"could not parse channel expression")
for c in chs:
if not 1 <= c <= 4:
raise Exception(f"channel number must be within [1,4], but have {c}")
return chs
def __call__(self, parse, args, values, option_string=None):
ch, att = values
try:
chs = ValidateChAtt._parse_channels(ch)
except Exception as e:
parse.exit(1, f"while parsing channel expression {ch}: {e}\n")
if not att.isdigit():
parse.exit(1, f'expected number for attenuation, but got {att}\n')
if not 0 <= int(att) <= 63:
parse.exit(1, f'attenuation must be within [0,63], but is {att}\n')
opts = getattr(args, self.dest) or {}
for c in chs:
opts[c] = int(att)
setattr(args, self.dest, opts)
def _parse_args() -> argparse.Namespace:
epilog = '''
[CHs] can have the following forms:
(1) single channel number w (within [1-4])
(2) a range of channels in the form x-y (x <= y)
(3) a list of channels in the form a,b,c
[ATT] must be within [0,63] (dB)
--set and --reach are mutually exclusive
Examples:
- reset all channels to 0: -s 1-4 0
- set channels 3 and 4 to attenuation 60: -s 3,4 60
- perform attenuation sweep during 10s, reaching ch. 1+2 to 60: -r 1,2 60 -d 10
'''
parser = argparse.ArgumentParser(description='Mini-Circuit RC*DAT attenuator controller',
epilog=epilog,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('--info', '-i', action='store_true', default=False,
help='Get Infos for all connected Mini-Circuits RC*DAT',)
parser.add_argument('--set', '-s', nargs=2, metavar=("[CHs]","[ATT]"),
action=ValidateChAtt, help="Set a fixed attenuation ATT on channels CHs")
parser.add_argument('--reach', '-r', nargs=2, metavar=("[CHs]","[ATT]"),
action=ValidateChAtt, help="Perform an \"attenuation sweep\": reach attenuation ATT on channels CHs")
parser.add_argument('--duration', '-d', action='store', type=float, default=5.0,
help='DURATION for attenuation sweep to --reach given attenuation (Default: 5)',)
parser.add_argument('--progress', '-p', action='store_true', default=False,
help='If provided, will show progress during attenuation sweep',)
return parser.parse_args()
def _exec(dev, cmd):
dev.write(1, cmd)
ans = dev.read(0x81,64)
# take from ans(wer) while valid bytes
sn = itertools.takewhile(lambda x: x < 255 and x > 0, ans)
# turn bytes into characters and accumulate into string
return "".join(map(chr, sn))
def devId(dev):
return f"{dev.idVendor:04x}:{dev.idProduct:04x}"
def _info(dev):
ident = devId(dev)
SerialN = _exec(dev, "*:SN?")
ModelN = _exec(dev, "*:MN?")
Fw = _exec(dev, "*:FIRMWARE?")
logging.info(f'{ident}: model is {ModelN}')
logging.info(f'{ident}: serial number is {SerialN}')
logging.info(f'{ident}: FW version is {Fw}')
def _get_attenuation(dev):
ident = devId(dev)
att = _exec(dev, "*:ATT?")
# remove leading "*" and split by channels
return [float(n) for n in att[1:].split(" ")]
def _set_attenuation(dev, ch_att):
ident = devId(dev)
for ch, att in ch_att:
#logging.debug(f"{ident}: Set attenuation channel {ch}: {att} dB")
att = round(4 * att) / 4 # round to closest 0.25dB
resp = _exec(dev, f"*:CHAN:{ch}:SETATT:{att};" )
def _continuous_set_attenuation(dev, ch_att_end, duration, show_progress=False, step_duration=0.25):
ident = devId(dev)
current = _get_attenuation(dev)
steps = duration / step_duration
ch_att_step = [(ch, (att_end - current[ch - 1]) / steps) for ch, att_end in ch_att_end]
logging.info(f"{ident}: sweep attenuation during {duration} s in {steps} steps: increments {ch_att_step}")
for i in range(1, int(steps)+1):
next_att = [(ch, current[ch - 1] + i * att_step) for ch, att_step in ch_att_step]
_set_attenuation(dev, next_att)
if show_progress:
logging.debug(f"{ident}: attenuation for channel(s): {next_att}")
time.sleep(step_duration)
_set_attenuation(dev, ch_att_end)
def _get_usb_devs(idVendor, idProduct):
devs = []
for dev in usb.core.find(idVendor=idVendor, idProduct=idProduct, find_all=True):
for configuration in dev:
for interface in configuration:
ifnum = interface.bInterfaceNumber
if not dev.is_kernel_driver_active(ifnum):
continue
try:
dev.detach_kernel_driver(ifnum)
except e:
pass
devs.append(dev)
return devs
if __name__ == '__main__':
# Parse the arguments
args = _parse_args()
if args.set and args.reach:
logging.error("--set and --reach are mutually exclusive")
sys.exit(1)
# 20ce:0023 is Mini-Circuit RC*DAT device
devs = _get_usb_devs(idVendor=0x20ce, idProduct=0x0023)
if len(devs) == 0:
logging.error('no Mini-Circuits RC*DAT device detected')
sys.exit(-1)
if len(devs) > 1:
logging.error('more than one Mini-Circuits RC*DAT device detected')
sys.exit(-1)
dev = devs[0]
if args.info:
_info(dev)
if args.set:
_set_attenuation(dev, [(k,v) for k,v in args.set.items()])
if args.reach:
_continuous_set_attenuation(dev, [(k,v) for k,v in args.reach.items()], args.duration, args.progress)
ident = devId(dev)
for i, a in enumerate(_get_attenuation(dev)):
logging.info(f"{ident}: Attenuation channel {i+1}: {a} dB")
sys.exit(0)

View File

@@ -1,8 +1,28 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
function usage {
echo "OAI Warning Check script"
echo " Original Author: Raphael Defosseux"
echo ""
echo "Usage:"
echo "------"

View File

@@ -1,8 +1,28 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
function usage {
echo "OAI Coding / Formatting Guideline Check script"
echo " Original Author: Raphael Defosseux"
echo ""
echo " By default (no options) the complete repository will be checked"
echo " In case of merge request, provided source and target branch,"
@@ -52,9 +72,9 @@ then
for FILE in $LIST_OF_FILES_W_BANNER
do
IS_NFAPI=`echo $FILE | grep -E -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
IS_OAI_LICENCE_PRESENT=`grep -E -c "SPDX-License-Identifier: LicenseRef-CSSL-1.0" $FILE || true`
IS_OAI_LICENCE_PRESENT=`grep -E -c "OAI Public License" $FILE || true`
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause|License-Identifier: BSD-3-Clause" $FILE || true`
IS_MIT_LICENCE_PRESENT=`grep -E -c "SPDX-License-Identifier: MIT" $FILE || true`
IS_MIT_LICENCE_PRESENT=`grep -E -c "MIT License" $FILE || true`
IS_EXCEPTION=`echo $FILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h" || true`
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
then
@@ -163,9 +183,9 @@ do
if [ $IS_BANNER -ne 0 ]
then
IS_NFAPI=`echo $FULLFILE | grep -E -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
IS_OAI_LICENCE_PRESENT=`grep -E -c "SPDX-License-Identifier: LicenseRef-CSSL-1.0" $FULLFILE || true`
IS_OAI_LICENCE_PRESENT=`grep -E -c "OAI Public License" $FULLFILE || true`
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause|License-Identifier: BSD-3-Clause" $FULLFILE || true`
IS_MIT_LICENCE_PRESENT=`grep -E -c "SPDX-License-Identifier: MIT" $FULLFILE || true`
IS_MIT_LICENCE_PRESENT=`grep -E -c "MIT License" $FULLFILE || true`
IS_EXCEPTION=`echo $FULLFILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h" || true`
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
then

View File

@@ -1,8 +1,28 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
function usage {
echo "OAI GitLab merge request applying script"
echo " Original Author: Raphael Defosseux"
echo ""
echo "Usage:"
echo "------"

View File

@@ -1,5 +1,4 @@
#!/bin/bash
# SPDX-License-Identifier: MIT
usage() {
echo "usage: $0 <command> <id>"

View File

@@ -1,5 +1,22 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
# * 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
# */
#---------------------------------------------------------------------
#
# Required Python Version

View File

@@ -12,14 +12,6 @@ idefix:
IF: wwan0
MTU: 1500
raspix:
Host: raspix
AttachScript: sudo /opt/mbim_scripts/start_quectel_mbim.sh
DetachScript: sudo /opt/mbim_scripts/stop_quectel_mbim.sh
NetworkScript: ip a show dev wwan0
IF: wwan0
MTU: 1500
up2:
Host: up2
AttachScript: sudo /opt/mbim/start_quectel_mbim.sh
@@ -85,14 +77,6 @@ oc-cn5g-20897:
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72"
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72 %%log_dir%%"
oc-cn5g-00103-ho:
Host: groot
NetworkScript: echo "inet 172.21.6.111"
RunIperf3Server: False
Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ho"
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ho"
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ho %%log_dir%%"
oc-cn5g-20897-aerial:
Host: gracehopper1-oai
NetworkScript: echo "inet 172.21.6.105"
@@ -101,14 +85,6 @@ oc-cn5g-20897-aerial:
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-nvidia-aerial"
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-nvidia-aerial %%log_dir%%"
oc-cn5g-00104:
Host: gracehopper1-oai
NetworkScript: echo "inet 172.21.6.105"
RunIperf3Server: False
Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-00104 oaicicd-core-for-nvidia-aerial"
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-00104 oaicicd-core-for-nvidia-aerial"
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-00104 oaicicd-core-for-nvidia-aerial %%log_dir%%"
matix-cn5g:
Host: matix
NetworkScript: docker exec prod-trf-gen ip a show dev eth0
@@ -183,6 +159,10 @@ amarisoft_ue_2x2:
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_2x2/aw2s-multi-00102-2x2-v2.cfg &
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
NetworkScript: ip netns exec ue1 ip a show dev pdn0
amarisoft_ue_fhi72:
Host: amariue
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_fhi72_asue_2x2_benetel550/fhi72-multi-20897-2x2.cfg &
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
amarisoft_ue_1:
Host: amariue
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}'
@@ -304,14 +284,6 @@ oai_ue_caracal:
IF: oaitun_ue1
MTU: 1500
oai_ue_jetson2:
Host: jetson2-oai
AttachScript: 'docker start oai-nr-ue'
DetachScript: 'docker stop oai-nr-ue'
NetworkScript: ip a show dev oaitun_ue1
IF: oaitun_ue1
MTU: 1500
lte_oai_ue_carabe:
Host: carabe
NetworkScript: docker exec lte-b200-ue-fdd-10Mhz-tm1 ip a show dev oaitun_ue1
@@ -483,93 +455,3 @@ l2sim4g_ext_dn:
Host: "%%current_host%%"
NetworkScript: docker exec l2sim4g-trf-gen ip a show dev eth0
CmdPrefix: docker exec l2sim4g-trf-gen
rfsim5g_multiue1:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue1
AttachScript: docker start rfsim5g-oai-nr-ue
DetachScript: docker stop rfsim5g-oai-nr-ue
MTU: 1500
rfsim5g_multiue2:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue2
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue2
AttachScript: true
DetachScript: true
MTU: 1500
rfsim5g_multiue3:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue3
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue3
AttachScript: "true"
DetachScript: "true"
MTU: 1500
rfsim5g_multiue4:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue4
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue4
AttachScript: "true"
DetachScript: "true"
MTU: 1500
rfsim5g_multiue5:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue5
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue5
AttachScript: "true"
DetachScript: "true"
MTU: 1500
rfsim5g_multiue6:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue6
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue6
AttachScript: "true"
DetachScript: "true"
MTU: 1500
rfsim5g_multiue7:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue7
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue7
AttachScript: "true"
DetachScript: "true"
MTU: 1500
rfsim5g_multiue8:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue8
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue8
AttachScript: "true"
DetachScript: "true"
MTU: 1500
rfsim5g_multiue9:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue9
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue9
AttachScript: "true"
DetachScript: "true"
MTU: 1500
rfsim5g_multiue10:
Host: "%%current_host%%"
NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue10
CmdPrefix: docker exec rfsim5g-oai-nr-ue
IF: oaitun_ue10
AttachScript: "true"
DetachScript: "true"
MTU: 1500

View File

@@ -1,36 +1,90 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
import yaml
import signal
import xml.etree.ElementTree as ET
import json
import importlib, inspect
# Define the mapping of physim_test values to search patterns
PHYSIM_PATTERN_MAPPING = {
'nr_ulsim': [
r'(Total PHY proc rx)\s+(\d+\.\d+)\s+us', # Pattern for RX PHY processing time
r'(ULSCH total decoding time)\s+(\d+\.\d+)\s+us', # Pattern for ULSCH decoding time
],
'nr_dlsim': [
r'(PHY proc tx)\s+(\d+\.\d+)\s+us', # Pattern for TX PHY processing time
r'(DLSCH encoding time)\s+(\d+\.\d+)\s+us', # Pattern for DLSCH encoding time
],
'ldpctest': [
r'(Encoding time mean):\s+(\d+\.\d+)\s+us', # Pattern for encoding time mean
r'(Decoding time mean):\s+(\d+\.\d+)\s+us', # Pattern for decoding time mean
],
}
# Define test conditions based on the simulation type
PHYSIM_TEST_CONDITION = {
'nr_ulsim': 'test OK', # For nr_ulsim, check if 'test OK' is present
'nr_dlsim': 'test OK', # For nr_dlsim, check if 'test OK' is present
'ldpctest': None, # No condition for ldpctest, just process the patterns
}
class Analysis():
def _get_test_description(properties):
env_vars = None
for p in properties:
if p["name"] == "ENVIRONMENT":
env_vars = p["value"] # save for later if no custom property
if p["name"] == "TEST_DESCRIPTION":
return p["value"]
# if we came till here, it means there is no custom test property
# saved in JSON. See if we have a description in environment variables
if not env_vars:
return "<none>"
for ev in env_vars:
name, value = ev.split("=", 1)
if name == "TEST_DESCRIPTION":
return value
return "<none>"
def analyze_physim(log, physim_test, options, threshold):
search_patterns = PHYSIM_PATTERN_MAPPING.get(physim_test)
test_condition = PHYSIM_TEST_CONDITION.get(physim_test)
success = False
msg = ''
def analyze_physim(result_junit, details_json, logPath):
try:
with open(log, 'r') as f:
log_content = f.read()
except FileNotFoundError as e:
msg = f'{log} file not found, exception: {e}'
return False, msg
except Exception as e:
msg = f'Error while parsing log file {log}: exception: {e}'
return False, msg
if test_condition and test_condition not in log_content:
msg = f"Test did not succeed, '{test_condition}' not found in log file {log}."
return False, msg
time1_match = re.search(search_patterns[0], log_content)
time2_match = re.search(search_patterns[1], log_content)
if not(time1_match and time2_match):
msg = f"Processing time not found in log file {log}."
return False, msg
success = float(time2_match.group(2)) < float(threshold)
if success:
msg = f'{time1_match.group(1)}: {time1_match.group(2)} us\n{time2_match.group(1)}: {time2_match.group(2)} us'
else:
msg = f'{time1_match.group(1)}: {time1_match.group(2)} us\n{time2_match.group(1)}: {time2_match.group(2)} us exceeds a limit of {threshold} us'
return success,msg
def analyze_oc_physim(result_junit, details_json, logPath):
try:
tree = ET.parse(result_junit)
root = tree.getroot()
@@ -62,7 +116,7 @@ class Analysis():
for test in root: # for each test
test_name = test.attrib["name"]
test_exec = json_test_desc[test_name]["properties"][1]["value"][0]
desc = Analysis._get_test_description(json_test_desc[test_name]["properties"])
desc = json_test_desc[test_name]["properties"][1]["value"][1]
# get runtime and checks
test_check = test.attrib["status"] == "run"
time = round(float(test.attrib["time"]), 1)
@@ -75,16 +129,13 @@ class Analysis():
with open(f'{log_dir}/{test_name}.log', 'w') as f:
f.write(output)
# prepare result and info
info = f"Runtime: {f'{time:.3f}'[:5]} s"
resultstr = 'PASS' if (test_check and time_check and output_check) else 'FAIL'
info = f"{test_name}.log: test {resultstr}"
for l in output.splitlines():
if l.startswith("CHECK "):
info += f"\n{l}"
if test_check:
if not output_check:
info += "\nTest log exceeds maximal allowed length 100 kB"
info += " Test log exceeds maximal allowed length 100 kB"
if not time_check:
info += "\nTest exceeds 150s"
info += " Test exceeds 150s"
if not (time_check and output_check):
nb_failed += 1 # time threshold/output length error, not counted for by ctest as of now
test_result[test_name] = [desc, info, resultstr]
@@ -94,134 +145,3 @@ 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

@@ -1,18 +1,38 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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 os
from typing import NamedTuple
import logging
class TestCaseCtx(NamedTuple):
test_idx: int
count: int
test_id: int
logPath: str
def Default(logPath):
return TestCaseCtx(112233, logPath)
return TestCaseCtx(123, 112233, logPath)
def baseFilename(self):
# typically, the test ID is of form 001234 (6 digits)
return f"{self.logPath}/{self.test_idx:06d}"
return f"{self.logPath}/{self.count}-{self.test_id:06d}"
def archiveArtifact(cmd, ctx, remote_path):
base = os.path.basename(remote_path)

View File

@@ -1,5 +1,23 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
#---------------------------------------------------------------------
#
# Required Python Version
@@ -16,6 +34,7 @@ import time
import os
import cls_oai_html
import cls_analysis
import constants as CONST
import helpreadme as HELP
import cls_containerize
@@ -146,6 +165,7 @@ class Cluster:
def PullClusterImage(self, HTML, node, images, tag_prefix):
logging.debug(f'Pull OC image {images} to server {node}')
self.testCase_id = HTML.testCase_id
with cls_cmd.getConnection(node) as cmd:
succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, CI_OC_RAN_NAMESPACE)
if not succeeded:
@@ -192,6 +212,8 @@ class Cluster:
logging.debug(f'Building on cluster triggered from server: {node}')
self.cmd = cls_cmd.RemoteCmd(node)
self.testCase_id = HTML.testCase_id
# Workaround for some servers, we need to erase completely the workspace
self.cmd.cd(lSourcePath)
# to reduce the amount of data send to OpenShift, we
@@ -376,9 +398,9 @@ class Cluster:
# Analyze the logs
collectInfo = {}
for image, lf in log_files:
imgStatus, errors = cls_containerize.AnalyzeBuildLogs(image, lf)
info = f"Analysis of {os.path.basename(lf)}: {imgStatus=}, size {imageSize[image]}, {len(errors)} errors"
msg = "\n".join([info] + errors)
ret = cls_containerize.AnalyzeBuildLogs(image, lf)
imgStatus = ret['status']
msg = f"size {imageSize[image]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings"
HTML.CreateHtmlTestRowQueue(image, 'OK' if imgStatus else 'KO', [msg])
status = status and imgStatus
@@ -391,7 +413,38 @@ class Cluster:
# the groovy scripts expects all logs in
# <jenkins-workspace>/<pipeline>/ci-scripts, so copy it there
with cls_cmd.LocalCmd() as c:
c.run(f'mkdir -p {os.getcwd()}/test_log_{ctx.test_idx}/')
c.run(f'cp -r {ctx.logPath} {os.getcwd()}/test_log_{ctx.test_idx}/')
c.run(f'mkdir -p {os.getcwd()}/test_log_{ctx.test_id}/')
c.run(f'cp -r {ctx.logPath} {os.getcwd()}/test_log_{ctx.test_id}/')
return status
def deploy_oc_physim(self, ctx, HTML, oc_release, node):
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
HELP.GenericHelp(CONST.Version)
raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {self.ranBranch} ranCommitID {self.ranCommitID}')
image_tag = cls_containerize.CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
logging.debug(f'Running physims from server: {node}')
script = "scripts/oc-deploy-physims.sh"
options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {self.eNBSourceCodePath}"
ret = cls_cmd.runScript(node, script, 600, options)
logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}')
with cls_cmd.getConnection(node) as ssh:
details_json = archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/{oc_release}-tests.json')
result_junit = archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/{oc_release}-run.xml')
archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_log.txt')
archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/physim_pods_summary.txt')
archiveArtifact(ssh, ctx, f'{self.eNBSourceCodePath}/ci-scripts/LastTestsFailed.log')
test_status, test_summary, test_result = cls_analysis.Analysis.analyze_oc_physim(result_junit, details_json, ctx.logPath)
if test_summary:
if test_status:
HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result)
logging.info('\u001B[1m Physical Simulator Pass\u001B[0m')
else:
HTML.CreateHtmlTestRowQueue('At least one physical simulator test failed!', 'KO', ["See below for details"])
HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result)
logging.error('\u001B[1m Physical Simulator Fail\u001B[0m')
else:
HTML.CreateHtmlTestRowQueue('Physical simulator failed', 'KO', [test_result])
logging.error('\u001B[1m Physical Simulator Fail\u001B[0m')
return test_status

View File

@@ -1,5 +1,23 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
#---------------------------------------------------------------------
#
# Required Python Version
@@ -27,6 +45,12 @@ def getConnection(host, d=None):
else:
return RemoteCmd(host, d=d)
def runScript(host, path, timeout, parameters=None, redirect=None, silent=False):
if is_local(host):
return LocalCmd.exec_script(path, timeout, parameters, redirect, silent)
else:
return RemoteCmd.exec_script(host, path, timeout, parameters, redirect, silent)
# provides a partial interface for the legacy SSHconnection class (getBefore(), command())
class Cmd(metaclass=abc.ABCMeta):
def cd(self, d, silent=False):
@@ -87,12 +111,12 @@ class LocalCmd(Cmd):
logging.debug(f'Working dir is {self.cwd}')
self.cp = sp.CompletedProcess(args='', returncode=0, stdout='')
def exec_script(self, path, timeout, parameters=None, redirect=None, silent=False):
def exec_script(path, timeout, parameters=None, redirect=None, silent=False):
if redirect and not redirect.startswith("/"):
raise ValueError(f"redirect must be absolute, but is {redirect}")
c = f"{path} {parameters}" if parameters else path
if not redirect:
ret = sp.run(c, shell=True, cwd=self.cwd, timeout=timeout, stdout=sp.PIPE, stderr=sp.STDOUT)
ret = sp.run(c, shell=True, timeout=timeout, stdout=sp.PIPE, stderr=sp.STDOUT)
ret.stdout = ret.stdout.decode('utf-8').strip()
else:
with open(redirect, "w") as f:
@@ -214,15 +238,18 @@ class RemoteCmd(Cmd):
cfg['sock'] = paramiko.ProxyCommand(ucfg['proxycommand'])
return cfg
def exec_script(self, path, timeout, parameters=None, redirect=None, silent=False):
def exec_script(host, path, timeout, parameters=None, redirect=None, silent=False):
if redirect and not redirect.startswith("/"):
raise ValueError(f"redirect must be absolute, but is {redirect}")
p = parameters if parameters else ""
r = f"> {redirect}" if redirect else ""
if not silent:
logging.debug(f"local> ssh {self.hostname} bash -s {p} < {path} {r}")
logging.debug(f"local> ssh {host} bash -s {p} < {path} {r} # {path} from localhost")
client = RemoteCmd._ssh_init()
cfg = RemoteCmd._lookup_ssh_config(host)
client.connect(**cfg)
bash_opt = 'BASH_XTRACEFD=1' # write bash set -x output to stdout, see bash(1)
stdin, stdout, stderr = self.client.exec_command(f"{bash_opt} bash -s {p} {r}", timeout=timeout)
stdin, stdout, stderr = client.exec_command(f"{bash_opt} bash -s {p} {r}", timeout=timeout)
# open() the file f at path, read() it and write() it into the stdin of the bash -s cmd
with open(path) as f:
stdin.write(f.read())
@@ -232,6 +259,7 @@ class RemoteCmd(Cmd):
if redirect: cmd += f" &> {redirect}"
ret = sp.CompletedProcess(args=cmd, returncode=stdout.channel.recv_exit_status(), stdout=stdout.read(size=None) + stderr.read(size=None))
ret.stdout = ret.stdout.decode('utf-8').strip()
client.close()
return ret
def run(self, line, timeout=300, silent=False, reportNonZero=True):

View File

@@ -1,5 +1,23 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
@@ -13,16 +31,21 @@
#-----------------------------------------------------------
# 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_analysis
import cls_oaicitest
from cls_ci_helper import archiveArtifact
#-----------------------------------------------------------
@@ -30,7 +53,6 @@ from cls_ci_helper import archiveArtifact
# (e.g., cls_cluster.py)
#-----------------------------------------------------------
IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-enb-asan', 'oai-gnb-asan', 'oai-lte-ue-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan', 'oai-gnb-aerial', 'oai-gnb-fhi72']
DEFAULT_REGISTRY = "gracehopper3-oai.sboai.cs.eurecom.fr"
def CreateWorkspace(host, sourcePath, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge):
if ranCommitID == '':
@@ -44,8 +66,7 @@ def CreateWorkspace(host, sourcePath, ranRepository, ranCommitID, ranTargetBranc
ranTargetBranch = 'develop'
options += f" {ranTargetBranch}"
logging.info(f'execute "{script}" with options "{options}" on node {host}')
with cls_cmd.getConnection(host) as c:
ret = c.exec_script(script, 90, options)
ret = cls_cmd.runScript(host, script, 90, options)
logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}')
return ret.returncode == 0
@@ -62,9 +83,9 @@ def CreateTag(ranCommitID, ranBranch, ranAllowMerge):
return tagToUse
def AnalyzeBuildLogs(image, lf):
errorandwarnings = {}
committed = False
tagged = False
errors = []
with open(lf, mode='r') as inputfile:
for line in inputfile:
lineHasTag = re.search(f'Successfully tagged {image}:', str(line)) is not None
@@ -73,13 +94,11 @@ def AnalyzeBuildLogs(image, lf):
# the OpenShift Cluster builder prepends image registry URL
lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None
committed = committed or lineHasCommit
if re.search(r'error:|Errors|ERROR', line):
errors.append(f"=> {line.strip()}")
status = (committed or tagged) and len(errors) == 0
logging.info(f"Analyzing {image}, file {lf}: {status=}, {len(errors)} errors")
for e in errors:
logging.info(e)
return status, errors
errorandwarnings['errors'] = 0 if committed or tagged else 1
errorandwarnings['warnings'] = 0
errorandwarnings['status'] = committed or tagged
logging.info(f"Analyzing {image}, file {lf}: {errorandwarnings}")
return errorandwarnings
def GetImageName(ssh, svcName, file):
ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".image'", silent=True)
@@ -98,7 +117,7 @@ def ExistEnvFilePrint(ssh, wd, prompt='env vars in existing'):
def WriteEnvFile(ssh, services, wd, tag, flexric_tag):
ret = ssh.run(f'cat {wd}/.env', silent=True, reportNonZero=False)
registry = "oai-ci/" # pull_images() gives us this registry path
registry = "oai-ci" # pull_images() gives us this registry path
envs = {"REGISTRY":registry, "TAG": tag, "FLEXRIC_TAG": flexric_tag}
if ret.returncode == 0: # it exists, we have to update
# transforms env file to dictionary
@@ -113,8 +132,7 @@ def WriteEnvFile(ssh, services, wd, tag, flexric_tag):
# or -asan images. We need to detect which kind we did pull.
fullImageName = GetImageName(ssh, svc, f"{wd}/docker-compose.y*ml")
image = fullImageName.split("/")[-1].split(":")[0]
# registry now includes the trailing slash ("oai-ci/")
checkimg = f"{registry}{image}-asan:{tag}"
checkimg = f"{registry}/{image}-asan:{tag}"
ret = ssh.run(f'docker image inspect {checkimg}', reportNonZero=False)
if ret.returncode == 0:
logging.info(f"detected pulled image {checkimg}")
@@ -144,26 +162,60 @@ def CopyinServiceLog(ssh, lSourcePath, svcName, wd_yaml, ctx):
ssh.run(f'docker compose -f {wd_yaml} logs {svcName} --no-log-prefix &> {remote_filename}')
return archiveArtifact(ssh, ctx, remote_filename)
def GetDeployedServices(ssh, file):
def GetRunningServices(ssh, file):
ret = ssh.run(f'docker compose -f {file} config --services')
if ret.returncode != 0:
logging.error("could not get services")
return None
allServices = ret.stdout.splitlines()
deployed_services = []
running_services = []
for s in allServices:
# outputs the hash if the container has been deployed (but might be stopped)
ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}', silent=True)
# outputs the hash if the container is running
ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}')
if ret.returncode != 0:
# error: should not happen as we iterate over docker-provided service list
logging.error(f"service {s}: {ret.stdout}")
logging.info(f"service {s}: {ret.stdout}")
elif ret.stdout == "":
logging.info(f"service {s} not deployed")
logging.warning(f"could not retrieve information for service {s}")
else:
c = ret.stdout
logging.info(f'service {s} with container id {c}')
deployed_services.append((s, c))
return deployed_services
logging.debug(f'running service {s} with container id {c}')
running_services.append((s, c))
logging.info(f'stopping services: {running_services}')
return running_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'])):
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 = ""
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
@@ -189,6 +241,8 @@ class Containerize():
self.dockerfileprefix = ''
self.host = ''
#checkers from xml
self.ran_checkers={}
self.num_attempts = 1
self.flexricTag = ''
@@ -225,7 +279,7 @@ class Containerize():
result = re.search('gNB', self.imageKind)
if result is not None:
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
result = re.search('x86', self.imageKind)
result = re.search('all', self.imageKind)
if result is not None:
imageNames.append(('oai-enb', 'eNB', 'oai-enb', ''))
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
@@ -236,6 +290,7 @@ class Containerize():
imageNames.append(('oai-physim', 'phySim', 'oai-physim', ''))
if self.host == 'Ubuntu':
imageNames.append(('oai-lte-ru', 'lteRU', 'oai-lte-ru', ''))
imageNames.append(('oai-gnb-aerial', 'gNB.aerial', 'oai-gnb-aerial', ''))
# Building again the 5G images with Address Sanitizer
imageNames.append(('ran-build', 'build', 'ran-build-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
imageNames.append(('oai-enb', 'eNB', 'oai-enb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
@@ -245,22 +300,16 @@ class Containerize():
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', ''))
imageNames.append(('oai-nr-oru', 'nrORU.fhi72', 'oai-nr-oru', ''))
result = re.search('build_cross_arm64', self.imageKind)
if result is not None:
self.dockerfileprefix = '.ubuntu.cross-arm64'
result = re.search('native_armv9', self.imageKind)
result = re.search('native_arm', self.imageKind)
if result is not None:
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
imageNames.append(('ran-build-fhi72', 'build.fhi72.native_arm', 'ran-build-fhi72', ''))
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', ''))
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
imageNames.append(('oai-gnb-aerial', 'gNB.aerial', 'oai-gnb-aerial', ''))
result = re.search('native_armv8', self.imageKind)
if result is not None:
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', ''))
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
cmd.cd(lSourcePath)
# if asterix, copy the entitlement and subscription manager configurations
@@ -293,16 +342,12 @@ 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'
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)
cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} . &> {logfile}", timeout=1600)
t = ("ran-base", archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
@@ -317,6 +362,7 @@ class Containerize():
cmd.close()
logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
HTML.CreateHtmlTabFooter(False)
return False
else:
result = re.search(r'Size *= *(?P<size>[0-9\-]+) *bytes', cmd.getBefore())
@@ -338,20 +384,18 @@ class Containerize():
# target images should use the proper ran-build image
if image != 'ran-build' and "-asan" in name:
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
elif "fhi72" in name or name == "oai-nr-oru":
elif "fhi72" in name:
cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
elif image != 'ran-build':
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
if image == 'oai-gnb-aerial':
cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2026.01.07.tar.gz .')
cmd.run('cp -f /opt/nvidia-ipc/nvipc.src.2025.05.20.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)
if image == 'oai-gnb-aerial':
cmd.run('rm -f nvipc_src.2026.01.07.tar.gz')
cmd.run('rm -f nvipc.src.2025.05.20.tar.gz')
# check the status of the build
ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}")
if ret.returncode != 0:
@@ -373,7 +417,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")
@@ -389,9 +433,9 @@ class Containerize():
# Analyze the logs
for name, lf in log_files:
imgStatus, errors = AnalyzeBuildLogs(name, lf)
info = f"Analysis of {os.path.basename(lf)}: {imgStatus=}, size {allImagesSize[name]}, {len(errors)} errors"
msg = "\n".join([info] + errors)
ret = AnalyzeBuildLogs(name, lf)
imgStatus = ret['status']
msg = f"size {allImagesSize[name]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings"
HTML.CreateHtmlTestRowQueue(name, 'OK' if imgStatus else 'KO', [msg])
status = status and imgStatus
@@ -442,6 +486,7 @@ class Containerize():
logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m')
ssh.close()
HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK)
HTML.CreateHtmlTabFooter(False)
return False
else:
logging.debug('L2sim proxy image for tag ' + tag + ' already exists, skipping build')
@@ -509,7 +554,8 @@ class Containerize():
ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
if ret.returncode != 0:
logging.error(f'No {baseImage} image present, cannot build tests')
HTML.CreateHtmlTestRow("Unit test build failed", 'KO', CONST.ALL_PROCESSES_OK)
HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
HTML.CreateHtmlTabFooter(False)
return False
# build ran-unittests image
@@ -520,6 +566,7 @@ class Containerize():
if ret.returncode != 0:
logging.error(f'Cannot build unit tests')
HTML.CreateHtmlTestRow("Unit test build failed", 'KO', [dockerfile])
HTML.CreateHtmlTabFooter(False)
return False
HTML.CreateHtmlTestRowQueue("Build unit tests", 'OK', [dockerfile])
@@ -538,16 +585,18 @@ class Containerize():
if ret.returncode == 0:
HTML.CreateHtmlTestRowQueue('Unit tests succeeded', 'OK', [ret.stdout])
HTML.CreateHtmlTabFooter(True)
return True
else:
HTML.CreateHtmlTestRowQueue('Unit tests failed (see also doc/UnitTests.md)', 'KO', [ret.stdout])
HTML.CreateHtmlTabFooter(False)
return False
def Push_Image_to_Local_Registry(self, node, HTML, tag_prefix=""):
lSourcePath = self.eNBSourceCodePath
logging.debug('Pushing images to server: ' + node)
ssh = cls_cmd.getConnection(node)
imagePrefix = DEFAULT_REGISTRY
imagePrefix = 'porcepix.sboai.cs.eurecom.fr'
ret = ssh.run(f'docker login -u oaicicd -p oaicicd {imagePrefix}')
if ret.returncode != 0:
msg = 'Could not log into local registry'
@@ -618,7 +667,7 @@ class Containerize():
msg = "Pulled Images:\n" + '\n'.join(pulled_images)
return True, msg
def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry=DEFAULT_REGISTRY, username="oaicicd", password="oaicicd"):
def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry="porcepix.sboai.cs.eurecom.fr", username="oaicicd", password="oaicicd"):
logging.debug(f'\u001B[1m Pulling image(s) on server: {node}\u001B[0m')
if not tag:
tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
@@ -664,6 +713,7 @@ class Containerize():
def DeployObject(self, ctx, node, HTML):
num_attempts = self.num_attempts
lSourcePath = self.eNBSourceCodePath
logging.debug(f'Deploying OAI Object on server: {node}')
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
@@ -674,7 +724,6 @@ class Containerize():
logging.error(msg)
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg])
return False
logging.info(f'\u001B[1mDeploying object(s) "{services}" on server {node}\u001B[0m')
ExistEnvFilePrint(ssh, wd)
WriteEnvFile(ssh, services, wd, self.deploymentTag, self.flexricTag)
if num_attempts <= 0:
@@ -699,100 +748,36 @@ class Containerize():
imagesInfo = info.stdout.splitlines()[1:]
logging.debug(f'{info.stdout.splitlines()[1:]}')
if deployed:
HTML.CreateHtmlTestRowQueue(self.services, 'OK', ['\n'.join(imagesInfo)])
logging.info('\u001B[1m Deploying objects Pass\u001B[0m')
HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)])
else:
HTML.CreateHtmlTestRowQueue(self.services, 'KO', ['\n'.join(imagesInfo)])
logging.error('\u001B[1m Deploying objects Failed\u001B[0m')
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)])
return deployed
def StopObject(self, ctx, node, HTML):
def UndeployObject(self, ctx, node, HTML, RAN):
lSourcePath = self.eNBSourceCodePath
if not self.services:
raise ValueError(f'no services provided')
logging.info(f'\u001B[1m Stopping objects "{self.services}" from server: {node}\u001B[0m')
reqServices = self.services.split()
logging.debug(f'\u001B[1m Undeploying OAI Object from server: {node}\u001B[0m')
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as ssh:
ExistEnvFilePrint(ssh, wd)
services = [s for s, _ in GetDeployedServices(ssh, wd_yaml)]
success = []
fail = []
for s in reqServices:
if s in services:
ssh.run(f'docker compose -f {wd_yaml} stop -- {s}')
success.append(s)
else:
logging.error(f"no such service {s}")
fail.append(s)
if success == reqServices:
logging.info('\u001B[1m Stopping object Pass\u001B[0m')
HTML.CreateHtmlTestRowQueue(self.services, 'OK', [f'Stopped {self.services}'])
else:
logging.error('\u001B[1m Stopping object Failed\u001B[0m')
HTML.CreateHtmlTestRowQueue(self.services, 'KO', [f'Failed stopping {" ".join(fail)}, succeeded {" ".join(success)}'])
return success
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('/')
wd = f'{lSourcePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as ssh:
ExistEnvFilePrint(ssh, wd)
services = GetDeployedServices(ssh, wd_yaml)
all_logs = True
ssh.run(f'docker compose -f {wd_yaml} stop')
services = GetRunningServices(ssh, f"{wd}/docker-compose.y*ml")
copyin_res = None
if services is not None:
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}
all_serv = " ".join([s for s, _ in services])
ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}')
copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, f"{wd}/docker-compose.y*ml", ctx) for s, _ in services]
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'docker compose -f {wd}/docker-compose.y*ml down -v')
ssh.run(f'rm {wd}/.env')
if not all_logs:
if not copyin_res:
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['Could not copy logfile(s)'])
logging.error(f"could not copy all files: {all_logs=} {services=}")
success = False
return False
else:
success = cls_analysis.AnalyzeServices(HTML, service_desc, to_analyze)
log_results = [CheckLogs(self, f, HTML, RAN) for f in copyin_res]
success = all(log_results)
if success:
logging.info('\u001B[1m Undeploying objects Pass\u001B[0m')
logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m')
else:
logging.error('\u001B[1m Undeploying objects Failed\u001B[0m')
return success
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None):
logging.info(f'Analyzing realtime stats from server: {node}')
yaml = self.yamlPath.strip('/')
wd = f'{self.eNBSourceCodePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as cmd:
services = GetDeployedServices(cmd, wd_yaml)
if not services:
raise RuntimeError("No deployed docker compose services found")
deployed_services = [s for s, _ in services]
s = service or deployed_services[0] # choose first service if not provided
if s not in deployed_services:
raise RuntimeError(f"Requested service {s} not found among services: {deployed_services}")
logging.info(f"Analyzing deployed service '{s}'")
# 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)
logging.error('\u001B[1m Undeploying OAI Object Failed\u001B[0m')
return success

View File

@@ -1,5 +1,22 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
# * 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
# */
#---------------------------------------------------------------------
#
# Required Python Version
@@ -60,8 +77,7 @@ class CoreNetwork:
words = line[1:].strip().split(" ")
script_name = words[0]
options = " ".join(words[1:])
with cls_cmd.getConnection(host) as c:
ret = c.exec_script(script_name, 300, parameters=options, silent=silent)
ret = cls_cmd.runScript(host, script_name, 300, parameters=options, silent=silent)
return ret
def _command(self, cmd_list, must_succeed=False, silent=False):

View File

@@ -1,141 +0,0 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
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

@@ -1,5 +1,22 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
# * 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
# */
#---------------------------------------------------------------------
#
# Required Python Version
@@ -94,7 +111,7 @@ class Module_UE:
return self._collectTrace(ctx)
return None
def attach(self, attach_tries = 3, attach_timeout = 40):
def attach(self, attach_tries = 4, attach_timeout = 60):
ip = None
while attach_tries > 0:
self._command(self.cmd_dict["attach"])
@@ -108,7 +125,6 @@ class Module_UE:
if ip:
break
logging.warning(f"UE did not receive IP address after {attach_timeout} s, detaching")
attach_timeout += 20
attach_tries -= 1
self._command(self.cmd_dict["detach"])
time.sleep(5)

View File

@@ -1,4 +1,24 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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 logging
import re
@@ -14,8 +34,9 @@ DPDK_PATH = '/opt/dpdk-t2-22.11.0'
class Native():
def Build(ctx, node, HTML, directory, options):
def Build(ctx, node, test_case, HTML, directory, options):
logging.debug(f'Building on server: {node}')
HTML.testCase_id = test_case
with cls_cmd.getConnection(node) as ssh:
base = f"{directory}/cmake_targets"
@@ -43,3 +64,18 @@ class Native():
logging.error('\u001B[1m Building OAI Failed\u001B[0m')
HTML.CreateHtmlTestRow(options, 'KO', CONST.ALL_PROCESSES_OK)
return success
def Run_Physim(ctx, HTML, host, directory, options, physim_test, threshold):
logging.debug(f'Runnin {physim_test} on server: {host}')
workSpacePath = f'{directory}/cmake_targets'
runLogFile=f'{workSpacePath}/physim.log'
with cls_cmd.getConnection(host) as cmd:
cmd.run(f'sudo LD_LIBRARY_PATH=.:{DPDK_PATH}/lib64/ {workSpacePath}/ran_build/build/{physim_test} {options} > {runLogFile} 2>&1')
physim_file = archiveArtifact(cmd, ctx, runLogFile)
success, msg = cls_analysis.Analysis.analyze_physim(physim_file, physim_test, options, threshold)
if success:
HTML.CreateHtmlTestRowQueue(options, 'OK', [msg])
else:
logging.error(msg)
HTML.CreateHtmlTestRowQueue(options, 'KO', [msg])
return success

View File

@@ -1,5 +1,23 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
@@ -49,7 +67,7 @@ class HTMLManagement():
self.htmlUEFailureMsg = ''
self.startTime = int(round(time.time() * 1000))
self.testCaseIdx = ''
self.testCase_id = ''
self.desc = ''
#-----------------------------------------------------------
@@ -173,7 +191,7 @@ class HTMLManagement():
self.htmlFile.write(' <table class="table" border = "1">\n')
self.htmlFile.write(' <tr bgcolor = "#33CCFF" >\n')
self.htmlFile.write(' <th style="width:5%">Relative Time (s)</th>\n')
self.htmlFile.write(' <th style="width:5%">Test Index</th>\n')
self.htmlFile.write(' <th style="width:5%">Test Id</th>\n')
self.htmlFile.write(' <th>Test Desc</th>\n')
self.htmlFile.write(' <th>Test Options</th>\n')
self.htmlFile.write(' <th style="width:5%">Test Status</th>\n')
@@ -200,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] + r"__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
subprocess.run(cmd, shell=True)
self.htmlFooterCreated = False
@@ -229,7 +247,7 @@ class HTMLManagement():
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' </table>\n')
self.htmlFile.write(' <p></p>\n')
self.htmlFile.write(' <div class="well well-lg">End of Test Report -- Copyright <span class="glyphicon glyphicon-copyright-mark"></span> 2026 <a href="http://www.openairinterface.org/">OpenAirInterface</a>. All Rights Reserved.</div>\n')
self.htmlFile.write(' <div class="well well-lg">End of Test Report -- Copyright <span class="glyphicon glyphicon-copyright-mark"></span> 2018 <a href="http://www.openairinterface.org/">OpenAirInterface</a>. All Rights Reserved.</div>\n')
self.htmlFile.write('</div></body>\n')
self.htmlFile.write('</html>\n')
self.htmlFile.close()
@@ -241,7 +259,7 @@ class HTMLManagement():
currentTime = int(round(time.time() * 1000)) - self.startTime
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + self.testCaseIdx + '</td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + self.testCase_id + '</td>\n')
self.htmlFile.write(' <td>' + self.desc + '</td>\n')
self.htmlFile.write(' <td>' + str(options) + '</td>\n')
if (str(status) == 'OK'):
@@ -356,7 +374,7 @@ class HTMLManagement():
addOrangeBK = False
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + self.testCaseIdx + '</td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + self.testCase_id + '</td>\n')
self.htmlFile.write(' <td>' + self.desc + '</td>\n')
self.htmlFile.write(' <td>' + str(options) + '</td>\n')
if (str(status) == 'OK'):
@@ -515,6 +533,6 @@ class HTMLManagement():
self.htmlFile.write(' <td bgcolor = "green" ><font color="white"><b>' + value[2] + '</b></font></td>\n')
else:
self.htmlFile.write(' <td bgcolor = "red" ><font color="white"><b>' + value[2] + '</b></font></td>\n')
self.htmlFile.write(f' <td colspan="2" bgcolor = "lightcyan"><pre style="display: inline flow-root list-item; margin: 0 3px 0 3px; min-width: 24em;">{value[1]}</pre></td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan">' + value[1] + '</td>\n')
self.htmlFile.close()

View File

@@ -1,5 +1,23 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
#---------------------------------------------------------------------
#
#
@@ -14,6 +32,7 @@
#-----------------------------------------------------------
# Import Libs
#-----------------------------------------------------------
import sys # arg
import re # reg
import time # sleep
import os
@@ -22,11 +41,11 @@ import concurrent.futures
import json
#import our libs
import helpreadme as HELP
import constants as CONST
import cls_module
import cls_corenetwork
import cls_analysis
import cls_cmd
from cls_ci_helper import archiveArtifact
@@ -213,10 +232,9 @@ def Custom_Command(HTML, node, command):
HTML.CreateHtmlTestRowQueue(command, status, message)
return status == 'OK' or status == 'Warning'
def Custom_Script(HTML, node, script, args):
def Custom_Script(HTML, node, script):
logging.info(f"Executing custom script on {node}")
with cls_cmd.getConnection(node) as c:
ret = c.exec_script(script, 90, args)
ret = cls_cmd.runScript(node, script, 90)
logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}")
status = 'OK'
message = [ret.stdout]
@@ -231,34 +249,6 @@ def IdleSleep(HTML, idle_sleep_time):
HTML.CreateHtmlTestRow(f"{idle_sleep_time} sec", 'OK', CONST.ALL_PROCESSES_OK)
return True
def Deploy_Physim(ctx, HTML, node, workdir, script, options):
logging.debug(f'Running physims on server {node} workdir {workdir}')
with cls_cmd.getConnection(node) as c:
sys_info = c.exec_script("scripts/sys-info.sh", 5)
ret = c.exec_script(script, 1500, options)
logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}')
HTML.CreateHtmlTestRowQueue('Query system info', 'OK', [sys_info.stdout])
with cls_cmd.getConnection(node) as ssh:
details_json = archiveArtifact(ssh, ctx, f'{workdir}/desc-tests.json')
result_junit = archiveArtifact(ssh, ctx, f'{workdir}/results-run.xml')
archiveArtifact(ssh, ctx, f'{workdir}/physim_log.txt')
archiveArtifact(ssh, ctx, f'{workdir}/LastTestsFailed.log')
archiveArtifact(ssh, ctx, f'{workdir}/LastTest.log')
test_status, test_summary, test_result = cls_analysis.Analysis.analyze_physim(result_junit, details_json, ctx.logPath)
if test_summary:
if test_status:
HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result)
logging.info('\u001B[1m Physical Simulator Pass\u001B[0m')
else:
HTML.CreateHtmlTestRowQueue('At least one physical simulator test failed!', 'KO', ["See below for details"])
HTML.CreateHtmlTestRowPhySimTestResult(test_summary, test_result)
logging.error('\u001B[1m Physical Simulator Fail\u001B[0m')
else:
HTML.CreateHtmlTestRowQueue('Physical simulator failed', 'KO', [test_result])
logging.error('\u001B[1m Physical Simulator Fail\u001B[0m')
return test_status
#-----------------------------------------------------------
# OaiCiTest Class Definition
#-----------------------------------------------------------
@@ -279,15 +269,18 @@ class OaiCiTest():
self.iperf_packetloss_threshold = ''
self.iperf_bitrate_threshold = ''
self.iperf_profile = ''
self.iperf_options = ''
self.iperf_tcp_rate_target = ''
self.finalStatus = False
self.air_interface=''
self.ue_ids = []
self.nodes = []
self.svr_node = None
self.svr_id = None
self.cmd_prefix = '' # prefix before {lte,nr}-uesoftmodem
def InitializeUE(self, node, HTML):
ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids]
def InitializeUE(self, HTML):
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
messages = []
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(ue.initialize) for ue in ues]
@@ -298,8 +291,8 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue('N/A', 'OK', messages)
return True
def AttachUE(self, node, HTML):
ues = [cls_module.Module_UE(ue_id, node) for ue_id in self.ue_ids]
def AttachUE(self, HTML):
ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(ue.attach) for ue in ues]
attached = [f.result() for f in futures]
@@ -314,8 +307,8 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not retrieve UE IP address(es) or MTU(s) wrong!"])
return success
def DetachUE(self, node, HTML):
ues = [cls_module.Module_UE(ue_id, node) for ue_id in self.ue_ids]
def DetachUE(self, HTML):
ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(ue.detach) for ue in ues]
[f.result() for f in futures]
@@ -323,8 +316,8 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue('NA', 'OK', messages)
return True
def DataDisableUE(self, node, HTML):
ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids]
def DataDisableUE(self, HTML):
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(ue.dataDisable) for ue in ues]
status = [f.result() for f in futures]
@@ -337,8 +330,8 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not disable UE data!"])
return success
def DataEnableUE(self, node, HTML):
ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids]
def DataEnableUE(self, HTML):
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
logging.debug(f'disabling data for UEs {ues}')
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(ue.dataEnable) for ue in ues]
@@ -352,8 +345,8 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not enable UE data!"])
return success
def CheckStatusUE(self, node, HTML):
ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids]
def CheckStatusUE(self,HTML):
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
logging.debug(f'checking status of UEs {ues}')
messages = []
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
@@ -423,10 +416,10 @@ class OaiCiTest():
return (True, message)
def Ping(self, ctx, node, HTML, infra_file="ci_infra.yaml"):
def Ping(self, ctx, HTML, infra_file="ci_infra.yaml"):
if self.ue_ids == [] or self.svr_id == None:
raise Exception("no module names in self.ue_ids or/and self.svr_id provided")
ues = [cls_module.Module_UE(ue_id, node, infra_file) for ue_id in self.ue_ids]
ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file)
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(self.Ping_common, ctx, cn, ue) for ue in ues]
@@ -480,11 +473,6 @@ class OaiCiTest():
t = iperf_time * 2.5
cmd_ue.run(f'rm {client_filename}', reportNonZero=False, silent=True)
if cn.runIperf3Server():
# Clean up any existing iperf3 server processes on this port.
ret = cmd_svr.run(f"{cn.getCmdPrefix()} pkill -f '.*iperf3.*{port}'", reportNonZero=False)
# If pkill succeeds, it means there was a leftover iperf3 server.
if ret.returncode == 0:
logging.warning(f'Iperf3 server on port {port} detected and terminated')
cmd_svr.run(f'{cn.getCmdPrefix()} timeout -vk3 {t} iperf3 -s -B {svrIP} -p {port} -1 {jsonReport} >> /dev/null &', timeout=t)
cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -B {ueIP} -c {svrIP} -p {port} {iperf_opt} {jsonReport} {serverReport} -O 5 >> {client_filename}', timeout=t)
dest_filename = archiveArtifact(cmd_ue, ctx, client_filename)
@@ -497,12 +485,12 @@ class OaiCiTest():
return (status, f'{ue_header}\n{msg}')
def Iperf(self, ctx, node, HTML, infra_file="ci_infra.yaml"):
logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}"')
def Iperf(self, ctx, HTML, infra_file="ci_infra.yaml"):
logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}" iperf_options "{self.iperf_options}"')
if self.ue_ids == [] or self.svr_id == None:
raise Exception("no module names in self.ue_ids or/and self.svr_id provided")
ues = [cls_module.Module_UE(ue_id, node, infra_file) for ue_id in self.ue_ids]
ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)]
cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file)
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(self.Iperf_Module, ctx, cn, ue, i, len(ues)) for i, ue in enumerate(ues)]
@@ -526,10 +514,10 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages)
return success
def Iperf2_Unidir(self, ctx, node, HTML, infra_file="ci_infra.yaml"):
def Iperf2_Unidir(self, ctx, HTML, infra_file="ci_infra.yaml"):
if self.ue_ids == [] or self.svr_id == None or len(self.ue_ids) != 1:
raise Exception("no module names in self.ue_ids or/and self.svr_id provided, multi UE scenario not supported")
ue = cls_module.Module_UE(self.ue_ids[0].strip(), node, infra_file)
ue = cls_module.Module_UE(self.ue_ids[0].strip(),self.nodes[0].strip(), infra_file)
cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file)
ueIP = ue.getIP()
if not ueIP:
@@ -558,8 +546,279 @@ class OaiCiTest():
HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', [f'{ue_header}\n{msg}'])
return success
def TerminateUE(self, ctx, node, HTML):
ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids]
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, HTML):
ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids]
with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor:
futures = [executor.submit(ue.terminate, ctx) for ue in ues]
archives = [f.result() for f in futures]

View File

@@ -1,5 +1,23 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
@@ -70,8 +88,9 @@ class StaticCodeAnalysis():
raise ValueError(f"{lSourcePath=} {node=}")
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
self.testCase_id = HTML.testCase_id
# on RedHat/CentOS .git extension is mandatory
result = re.search(r'([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
if result is not None:
full_ran_repo_name = self.ranRepository.replace('git/', 'git')
else:
@@ -103,7 +122,7 @@ class StaticCodeAnalysis():
xmlStart = False
with open(filename, 'r') as logfile:
for line in logfile:
ret = re.search(r'cppcheck version="(?P<version>[0-9\.]+)"', str(line))
ret = re.search('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:
@@ -168,6 +187,8 @@ class StaticCodeAnalysis():
raise ValueError(f"{lSourcePath=} {node=}")
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
self.testCase_id = HTML.testCase_id
check_options = ''
if self.ranAllowMerge:
check_options = f'--build-arg MERGE_REQUEST=true --build-arg SRC_BRANCH={self.ranBranch}'

View File

@@ -1,5 +1,3 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
# Colosseum Automated Testing
These scripts are used by a Jenkins [job](../Jenkinsfile-colosseum) to trigger automated testing of OpenAirInterface (OAI) gNB and softUE on the [Colosseum](https://www.northeastern.edu/colosseum/) Open RAN digital twin.

View File

@@ -1,5 +1,24 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
set -x

View File

@@ -1,5 +1,24 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
set -eu

View File

@@ -1,5 +1,24 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
set -eu

View File

@@ -1,5 +1,24 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
set -eu

View File

@@ -1,5 +1,24 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/*
# * 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
# */
set -xeu

View File

@@ -1,5 +1,3 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
# Configuration files: naming style guide
The configuration files should have the following name format:

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#/* configuration for channel modelisation */
#/* To be included in main config file when */
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "rcc-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "rcc-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
RUs =
(
{

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
RUs =
(
{

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB_Eurecom_LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -202,11 +200,9 @@ RUs = (
}
);
rfsimulator = (
{
rfsimulator: {
serveraddr = "server";
}
);
};
THREAD_STRUCT = (
{

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-B38");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-B38");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-B38");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom_LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -235,11 +233,9 @@ RUs =
}
);
rfsimulator = (
{
rfsimulator: {
serveraddr = "server";
}
);
};
THREAD_STRUCT =
(

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "enb-l2sim-vnf");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -235,11 +233,9 @@ RUs =
}
);
rfsimulator = (
{
rfsimulator: {
serveraddr = "server";
}
);
};
THREAD_STRUCT =
(

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -235,11 +233,9 @@ RUs =
}
);
rfsimulator = (
{
rfsimulator: {
serveraddr = "server";
}
);
};
THREAD_STRUCT =
(

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -235,11 +233,9 @@ RUs =
}
);
rfsimulator = (
{
rfsimulator: {
serveraddr = "server";
}
);
};
THREAD_STRUCT =
(

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -364,11 +362,9 @@ RUs = (
}
);
rfsimulator = (
{
rfsimulator: {
serveraddr = "server";
}
);
};
THREAD_STRUCT = (
{

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-Eurecom-LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_eNBs = ( "eNB-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_gNBs = ( "cu-rfsim");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -17,7 +15,7 @@ gNBs =
// 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, sd = 0xffffff }) });
@include "neighbour-config.conf"
nr_cellid = 12345678L;

View File

@@ -1,5 +1,3 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_gNBs = ( "gNB-Eurecom-CU");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";

View File

@@ -1,78 +0,0 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_gNBs = ( "CU-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe88;
# cell_type = "CELL_MACRO_GNB";
gNB_name = "CU-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 03; mnc_length = 2; snssaiList = ({ sst = 1 }) });
@include "neighbour-config-ho.conf"
nr_cellid = 12345678L;
tr_s_preference = "f1";
local_s_address = "172.21.19.98";
remote_s_address = "0.0.0.0";
local_s_portd = 2153;
remote_s_portd = 2154;
# ------- 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.109"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.19.98/22";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.19.98/22";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
security = {
# preferred ciphering algorithms
# the first one of the list that an UE supports in chosen
# valid values: nea0, nea1, nea2, nea3
ciphering_algorithms = ( "nea2", "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 = "yes";
};
log_config :
{
global_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
f1ap_log_level ="info";
ngap_log_level ="info";
};

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