Compare commits

..

59 Commits
rs ... dapp

Author SHA1 Message Date
Filippo Olimpieri
7d3ef0140b Modified nr_radio_config.c to always include SLIV(0,12) UL TDA when E3_AGENT is enabled 2026-05-01 20:13:18 +00:00
Filippo Olimpieri
ecc6c9ec3e modified CMakeLists of E3 to compile asn files the same way as in the other parts of the repository 2026-04-30 18:22:56 -04:00
Filippo Olimpieri
ce211dc2ef removed duplicated definition and modified skipping of TDS symbol to match the new code structure 2026-04-30 17:19:13 -04:00
Filippo Olimpieri
c3971d524f E2SM DAPP revision
* updated ran functiond for dapp to remove action def and renamed formats

* updated e3_agent code and ran_func_dapp to expose dapp ids and e3 ran func to which each dapp is subscribed

* implemented triggering of RIC service update at every status change of dApp

* modified ran function dapp to handle action definition to specify the kind of report to send in return

* removed report style 1 that was used to geth both types of indications

* updated ran func dapp to populate the new ran func struct following the new structure definition

* fixed missing branchets in if, restored some comments and exception messages, and added macros for report styles

* clang-formatted files in ran func def
2026-04-14 13:31:44 -04:00
Andrea Lacava
5f3ea814e5 Implementation of LIBE3 inside OAI
* implemented spectrum SM

* fix t tracer connection

* Enhance E3 Agent integration and logging in Spectrum Service Model

* Refactor E3 service model: update data types and improve memory handling

* Update documentation
2026-03-05 15:02:21 -05:00
Andrea Lacava
c2fdea2f01 Add documentation
* Add documentation for Spectrum Service Model architecture and functionalities

* Add xApp-dApp bridge

* updated documentation

* Update documentation for xApp-dApp interaction and files

---------

Co-authored-by: Andrea Lacava <a.lacava@northeastern.edu>

---------

Co-authored-by: Filippo Olimpieri <126257005+Ninjabippo1205@users.noreply.github.com>
2026-02-19 12:44:18 -05:00
Filippo Olimpieri
df5ddd2ea4 solve ASN E3AP PDU duplication 2026-01-26 16:11:01 -05:00
Filippo Olimpieri
e5c922feba E2SM-DAPP for xApp-dApp synchronization
* updated flexric submodule

* added support in E3AP for report messages and xAppControlMessages

* improved consistecy

* added conditional compilation guard to ensure generate_e2_indication_from_e3_dapp_report is called only when E2_AGENT is defined

* updated ran func dapp to handle the new version of the e3 agent, and modified also e3 agent to support xAppControlAction

* addressed comments of PR by removing code in CMakeLists and renamed shared queue, marked as untested the code not tested

* removed unused code and  implemented read_dapp_setup_sm

* updated flexric

* removed unused code

* removed unused parameters and updated code to work with new implementation of flexric dapp sm

* updated dapp_e3_obj with e3sm_obj

* updated flexric

* build ran functions of e2sm_dapp ony if E3_AGENT is defined

* fixed decoding of dapp control to enable read of all 273 prbs, currently it supports max 137

* update asn and encoding/decoding to consider prbblacklist and whitelist as sequence of integers instead of octet string

* fix issue that cap the number of xapps to which the indication message could be sent

* added include guard for void* e3_agent_dapp_task(void* args_p);

* modified PRB_Index in e3sm_spectrum.asn

* updated flexric

* resolved confict with develop-dapp branch

* resolved confict with develop-dapp branch

* updated flexric to new branch

* restored initial .gitmodule and flexric submodule

* updated .gitmodules to add missing newline

* added compilation guards to avoid to use of  e2sm-dapp when e3 agent is not defined during copilation

* update DAPP service model description for clarity in synchronization context

---------

Co-authored-by: Andrea Lacava <a.lacava@northeastern.edu>
2026-01-23 16:49:04 -05:00
Andrea Lacava
65df4e2afd enable restart of the main thread for SM 2025-12-17 15:18:44 -05:00
Andrea Lacava
af8d1daf36 Increase indication for the foxconn
* Enhance spectrum encoding with improved error logging and validation checks

* Increase encode buffer size to 32KB for improved IQ data handling
2025-12-09 10:00:07 -05:00
Andrea Lacava
e4ea2170b0 increase buffer size for foxconn 2025-12-05 18:26:29 -05:00
Andrea Lacava
4bb6c48a2f Enhance subscription management by tracking affected RAN functions during dApp unregistration and managing SM lifecycle accordingly 2025-12-05 14:38:59 -05:00
Andrea Lacava
4e6caca5a7 Include dApp report and xApp control action to ensure compatibility and fix ordering 2025-12-04 14:56:38 -05:00
Andrea Lacava
aa01359088 Management of subscribe request to allow clean disconnection
* Refactor subscription management: streamline add/remove logic and enhance error handling

* Enhance dApp unregistration: collect affected RAN function IDs and stop SMs if necessary

* Allow connection from different hosts

* Add management of already existing subscription in E3 Agent

* Change log level for existing subscription warning

* Refactor subscription management: now the RAN functions in the SMs are initialized and run from the beginning. the dApp subscriptions are not going to affect their behaviors, only the E3AP delivery

---------

Co-authored-by: absentio <20925479+absentio@users.noreply.github.com>
2025-12-01 15:48:59 -05:00
Andrea Lacava
d92a51d468 Introducing structured E3SM for different use cases support (#39)
Ex cathedra: squash-merge of E3AP integration and Spectrum SM refactor

This PR consolidates multiple commits that implement, refactor, and stabilize the E3AP integration into the OAI Layer 2 stack with support for Spectrum Service Models and full subscription management.
Thanks to this, now the codebase features a fully working E3AP/E3SM-based control loop in OAI, with subscription and indication message flow, Spectrum SM integration, dynamic sensing thresholds, and compile-time encoding format selection — establishing a solid foundation for scalable multi-RU support.
	•	E3AP Integration & Infrastructure
• Moved E3AP handling into the OAI Layer 2 to support multiple RUs.
• Defined generic data types and introduced compile-time encoding format selection for E3AP messages.
• Refactored socket handling with permission settings for IPC endpoints; added e3_response_queue and new thread support for SMs.
• Reorganized configuration handling, removing deprecated structs, obsolete control logic, and T-tracer functions.
	•	Subscription Management
• Added E3 Subscription Manager (e3_subscription_manager.h/.c) to manage dApp registrations and RAN function subscriptions.
• Implemented add/remove/check subscription functions, integrated with e3_agent.c for handling subscription requests and indications.
• Enhanced agent lifecycle (init/destroy) to incorporate subscription manager cleanup.
• Added subscription request/response handling, with logging improvements for traceability.
	•	Control Loop & Spectrum SM Enhancements
• Implemented setup response with RAN function ID list.
• Subscription and indication messages working end-to-end; completed full control loop.
• Enabled dynamic sampling threshold changes; renamed e3_agent_control to e3_sm_spectrum_control.
• Refined spectrum encoding functions to use uint32_t timestamps and updated ASN.1 definitions accordingly.
• Added ranFunctionIdentifier to control actions for consistency.
	•	Cleanup & Utilities
• Reduced verbosity and removed unused code, buffers, and logs.
• Commented unused timestamp functions to remove warnings.
• Updated CMakeLists and generator scripts.
2025-10-09 15:35:03 -04:00
Noemi Giustini
876696494f Add support for 100MHz over the E3AP and add additional configurations for RUs (#30)
* increase protocolData size to support 100MHz

---------

Co-authored-by: Andrea Lacava <lacava.a@northeastern.edu>
2025-07-02 16:53:25 -04:00
Andrea Lacava
7c6dd3b563 remove all helpers 2025-04-04 18:56:58 +00:00
Andrea Lacava
3ef37bfb37 formatting and cleanup of unnecessary code 2025-04-04 14:05:52 -04:00
Andrea Lacava
a0a0f1dbcd add RIC capabilities and E2AP on the dApp (#18)
* Optimize PHY actions, remove redundant code.
Ensure correct access to the gNB MAC parameters using locking.

* remove magic numbers

* improve memory management of the control action list

* fix direct memory leaks

* change scripts

* add size check

* Successful near-rt, xApp and dApps coexistence

* improve feedback logic of the PRB blocked

* fix index in NR PRB update policy
2025-03-14 17:30:51 -04:00
Andrea Lacava
7bdf1edf8a add include guards and reduce changes only to the necessary ones 2025-02-21 00:03:12 +00:00
Andrea Lacava
3c45d35972 fix data extraction thanks @RajeevGa 2025-02-11 23:12:53 +00:00
Andrea Lacava
4b14d6609b code formatting 2025-02-03 20:39:34 +00:00
Andrea Lacava
b3c9ef630a add back a space 2025-02-03 20:31:28 +00:00
Andrea Lacava
29d2586b8d remove references to GNB_PHY_INPUT_SIGNAL 2025-02-03 20:29:17 +00:00
Andrea Lacava
51ca8ed10d add UTIL back 2025-01-31 23:40:15 +00:00
Andrea Lacava
c48e3e21e4 Update mirror.yml 2025-01-31 16:50:07 -05:00
Andrea Lacava
a9d8f6edb4 Update mirror.yml 2025-01-31 16:43:40 -05:00
Andrea Lacava
ea95f93427 Update mirror.yml to remove conditional push 2025-01-31 16:40:39 -05:00
Andrea Lacava
7ccc29aed3 fix branch 2025-01-27 15:28:26 -05:00
Andrea Lacava
ac90a535f7 Implementation of ZeroMQ, IPC, SCTP, TCP to serve ASN1 PDU for the E3AP (#12)
* work with x310

* E3AP ASN inside

* fix the logs and remove dead code

* add unix domain socket

* add zmq handlers

* Add parameters for E3

* add e3connector to include all the logic related to the message exchange

* add mutex to the contol actions

* list of integers 84% of overhead

* loop apparently works

* indication working

* Action control working

* zmq tcp working

* start work ipc

* simplyfy uds as ipc and remove sctp zmq from valid configurations

* zmq and ipc almost working

* control working better

* LOG_I on the endpoints

* sampling done before the use of the t-tracer

* apply @gabri94 patch to extract modulation order

* remove topic for the inbound connection

* improve the ASN to reduce the PDU size

* improve sampling logic to support no sampling

* code to support data taking commented

* comment on the save of MAC stats

* create stats files

* fix taskset on dapp

* remove OP reference : (

* the best open source projects have references in their code

* add mirror workflow
2025-01-27 15:23:56 -05:00
Andrea Lacava
c5f3bae132 add local core and fix cmakelists for L2_NR 2024-10-19 21:41:03 +00:00
Andrea Lacava
b6d928d7a1 fix cmakelists.txt files for enabling and disabling the e3ap over builds and give the possibility to select whether to use raw tcp sockets or unix domain sockets 2024-10-18 20:35:47 +00:00
Andrea Lacava
21de22e0a3 sampling 5 symbols 2024-10-17 20:02:35 +00:00
Andrea Lacava
ec5f6e7e57 enabling TCP sockets along with UDS 2024-10-17 19:21:01 +00:00
Andrea Lacava
7999a88ea0 revert path of unix domain socket 2024-10-17 18:20:03 +00:00
Andrea Lacava
3ea1ad3a54 test speed colosseum 2024-10-17 17:52:49 +00:00
Andrea Lacava
2213ea1b31 Change of the configurations after the call (#11)
* add sampling counter and sampling_threshold for IQs, reduced RX gain for 410 conf

* removed sampling add configurations

* enable x410
2024-10-17 13:50:01 -04:00
Andrea Lacava
54e0287330 add x410 conf 2024-10-16 20:26:26 +00:00
Andrea Lacava
aa4481ac08 change TCP sockets to UDS (#10)
* change TCP sockets to UDS

* Save IQ samples to file and work OTA (#9)

* IQ logging into a file

* Logs aligned with timestamp

* remove python code

* change relative path

* OTA working (no control)

* change address to .62

---------

Co-authored-by: RajeevGa <gangula@eurecom.fr>
Co-authored-by: RajeevGa <r.gangula@northeastern.edu>

* add unix domain sockets

---------

Co-authored-by: RajeevGa <gangula@eurecom.fr>
Co-authored-by: RajeevGa <r.gangula@northeastern.edu>
2024-10-09 17:46:08 -04:00
Andrea Lacava
74374975ca Save IQ samples to file and work OTA (#9)
* IQ logging into a file

* Logs aligned with timestamp

* remove python code

* change relative path

* OTA working (no control)

* change address to .62

---------

Co-authored-by: RajeevGa <gangula@eurecom.fr>
Co-authored-by: RajeevGa <r.gangula@northeastern.edu>
2024-10-07 15:20:16 -04:00
Andrea Lacava
69efebb153 Add PRB masking and save data through dApp (#7)
* IQ logging into a file

* Logs aligned with timestamp

* remove python code

* change relative path

* OTA working (no control)

---------

Co-authored-by: RajeevGa <gangula@eurecom.fr>
Co-authored-by: RajeevGa <r.gangula@northeastern.edu>
2024-09-27 16:57:15 -04:00
Andrea Lacava
0f1bd004d3 change configuration for OTA 2024-09-27 18:34:05 +00:00
Andrea Lacava
efdf65d763 indentation 2024-09-27 16:00:47 +00:00
Andrea Lacava
707b031007 fix relative paths 2024-06-13 12:49:10 +00:00
Andrea Lacava
8b59a83ab6 move python code in the dApp repo 2024-06-13 12:21:28 +00:00
RajeevGa
b33261e10c Adding readme file 2024-06-09 15:47:41 -04:00
RajeevGa
2048ba532f adding gNB config file 2024-05-28 15:28:11 -04:00
RajeevGa
ac5212053f qtr working demo 2024-05-28 15:26:26 -04:00
Andrea Lacava
82a60c6d7b t tracer working internally 2024-04-25 20:14:53 +00:00
Andrea Lacava
1043bf4a6c moved initialization of E3 agent before the T tracer 2024-04-22 15:13:47 -04:00
Andrea Lacava
ad3158887c Add --nrUE option to build script 2024-03-25 19:39:40 -04:00
Andrea Lacava
70a7d63888 add stub e3 agent 2024-03-22 15:38:25 -04:00
Andrea Lacava
a455ae1436 Update build_oai.sh and e3_agent.c***
***Add run_oai.sh and gnb.band78.sa.fr1.106PRB.usrpx300.conf***

***Fix T_MESSAGES_PATH in e3_agent.h
2024-03-18 14:31:48 -04:00
Andrea Lacava
f71a0fd372 fix typo 2024-03-14 18:34:18 -04:00
RajeevGa
8aeb08d5e2 Added tracer for getting time domain UL iq samples 2024-03-14 15:38:17 -04:00
Andrea Lacava
3ae1b6fc7c Update E3AP CMakeLists.txt and e3_agent.c 2024-03-07 23:36:48 -05:00
Andrea Lacava
7d95e58ad8 Add E3AP capabilities and enable E3_AGENT in build 2024-03-07 22:33:10 -05:00
Andrea Lacava
79645dd554 fix error on including directories 2024-03-07 16:20:05 -05:00
Andrea Lacava
02a95300cd reproduced error on the develop version 2024-03-05 16:32:39 -05:00
392 changed files with 11936 additions and 40779 deletions

2
.gitignore vendored
View File

@@ -34,3 +34,5 @@ nfapi_nr_interface_scf
*.log
*.out
CMakeUserPresets.json
build/*

View File

@@ -5,8 +5,8 @@ project (OpenAirInterface LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(OAI_VERSION 2.4.0)
option(ENABLE_CHANNEL_SIM_CUDA "Enable CUDA accelerated channel simulation" OFF)
if(ENABLE_CHANNEL_SIM_CUDA)
option(CUDA_ENABLE "Enable CUDA accelerated channel simulation" OFF)
if(CUDA_ENABLE)
find_package(CUDA REQUIRED)
find_package(CUDAToolkit REQUIRED)
message(STATUS "CUDA explicitly enabled, building with GPU acceleration support.")
@@ -34,7 +34,7 @@ if(ENABLE_CHANNEL_SIM_CUDA)
message(STATUS "CUDA Explicit Copy path enabled (default ATS was overridden).")
endif()
add_compile_definitions(CHANNEL_SIM_CUDA)
add_compile_definitions(ENABLE_CUDA)
endif()
#########################################################
@@ -155,17 +155,14 @@ add_boolean_option(AVX512 ${AUTODETECT_AVX512} "Whether AVX512 intrinsics is ava
eval_boolean(AUTODETECT_AVX2 DEFINED CPUFLAGS AND CPUFLAGS MATCHES "avx2")
add_boolean_option(AVX2 ${AUTODETECT_AVX2} "Whether AVX2 intrinsics is available on the host processor" ON)
eval_boolean(AUTODETECT_GFNI DEFINED CPUFLAGS AND CPUFLAGS MATCHES "gfni")
add_boolean_option(GFNI ${AUTODETECT_GFNI} "Whether GFNI intrinsics is available on the host processor" ON)
message(STATUS "CPU architecture is ${CMAKE_SYSTEM_PROCESSOR}")
if (CROSS_COMPILE)
message(STATUS "setting as aarch64")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -lgcc -lrt")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
# The following intrinsics are assumed to be available on any x86 system
# (avx, f16c, fma, mmx, pclmul, sse, sse2, sse3, xop)
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_F16C_NATIVE -DSIMDE_X86_FMA_NATIVE -DSIMDE_X86_MMX_NATIVE -DSIMDE_X86_PCLMUL_NATIVE -DSIMDE_X86_SSE2_NATIVE -DSIMDE_X86_SSE3_NATIVE -DSIMDE_X86_SSE_NATIVE -DSIMDE_X86_XOP_HAVE_COM_ -DSIMDE_X86_XOP_NATIVE")
# (avx, f16c, fma, gnfi, mmx, pclmul, sse, sse2, sse3, xop)
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_F16C_NATIVE -DSIMDE_X86_FMA_NATIVE -DSIMDE_X86_GFNI_NATIVE -DSIMDE_X86_MMX_NATIVE -DSIMDE_X86_PCLMUL_NATIVE -DSIMDE_X86_SSE2_NATIVE -DSIMDE_X86_SSE3_NATIVE -DSIMDE_X86_SSE_NATIVE -DSIMDE_X86_XOP_HAVE_COM_ -DSIMDE_X86_XOP_NATIVE")
message(STATUS "AVX512 intrinsics are ${AVX512}")
if(${AVX512})
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX512BW_NATIVE -DSIMDE_X86_AVX512F_NATIVE -DSIMDE_X86_AVX512VL_NATIVE -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512")
@@ -176,17 +173,13 @@ elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
if(${AVX2})
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX2_NATIVE -DSIMDE_X86_VPCLMULQDQ_NATIVE")
endif()
message(STATUS "GFNI intrinsics are ${GFNI}")
if(${GFNI})
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_GFNI_NATIVE -mgfni")
endif()
if (CPUFLAGS MATCHES "sse4_1")
if (CPUINFO MATCHES "sse4_1")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSE4_1_NATIVE")
endif()
if(CPUFLAGS MATCHES "sse4_2")
if(CPUINFO MATCHES "sse4_2")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSE4_2_NATIVE")
endif()
if(CPUFLAGS MATCHES "ssse3")
if(CPUINFO MATCHES "ssse3")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSSE3_NATIVE")
endif()
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l")
@@ -228,14 +221,9 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(commonOpts "${commonOpts} -Wno-packed-bitfield-compat")
endif()
# clang: suppress complaints about unused command line argument (-rdynamic only
# used during linking) and "const member leaves the object uninitialized"
# used during linking)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(commonOpts "${commonOpts} -Wno-unused-command-line-argument -Wno-default-const-init-field-unsafe")
endif()
if (ENABLE_LDPC_CUDA)
# TODO only on specific targets!!
set(commonOpts "${commonOpts} -DLDPC_CUDA")
set(commonOpts "${commonOpts} -Wno-unused-command-line-argument")
endif()
set(CMAKE_C_FLAGS
@@ -389,6 +377,12 @@ endif()
add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" OFF)
add_boolean_option(ENABLE_IMSCOPE_RECORD OFF "Enable recording IQ data for imscope" OFF)
#########################
##### E3 AGENT
#########################
set(E3_AGENT "OFF" CACHE STRING "O-RAN nGRG E3 Agent for dApps")
set_property(CACHE E3_AGENT PROPERTY STRINGS "ON" "OFF")
##################################################
# ASN.1 grammar C code generation & dependencies #
##################################################
@@ -741,6 +735,9 @@ set(SCHED_NR_SRC
add_library(SCHED_NR_LIB ${SCHED_NR_SRC})
target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs UTIL)
target_link_libraries(SCHED_NR_LIB PRIVATE NFAPI_LIB) # some FAPI messages pack "subPDUs"
if(E3_AGENT)
target_compile_definitions(SCHED_NR_LIB PRIVATE E3_AGENT)
endif()
set(SCHED_SRC_RU
${OPENAIR1_DIR}/SCHED/ru_procedures.c
@@ -854,7 +851,6 @@ set(PHY_NRLDPC_CODINGIF
)
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
target_compile_options(dfts PRIVATE -fno-semantic-interposition)
set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
@@ -1099,30 +1095,15 @@ target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
if (ENABLE_LDPC_CUDA)
find_package(CUDA REQUIRED)
if (NOT CUDA_FOUND)
message(FATAL_ERROR "no CUDA found")
endif()
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_80 -g -ggdb") # A100
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_90") # GH200
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_87") # Jetson
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_89") # L40S
SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_121") # GB10
set(CUDA_VERBOS_BUILD_ON)
cuda_add_library(PHY_NR ${PHY_NR_SRC} ${PHY_NR_SRC_CU})
cuda_add_library(PHY_NR_UE ${PHY_NR_UE_SRC} ${PHY_NR_UE_SRC_CU})
else()
add_library(PHY_NR ${PHY_NR_SRC})
add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
endif()
add_library(PHY_NR ${PHY_NR_SRC})
target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock ds)
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)
target_link_libraries(PHY_NR_UE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL polar smallblock)
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)
add_library(PHY_RU ${PHY_SRC_RU})
target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs UTIL)
@@ -1164,20 +1145,12 @@ set(NR_PDCP_SRC
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
)
# gNB: PDCP + CU-CP/CU-UP interface
set(NR_PDCP_SRC_GNB
${NR_PDCP_SRC}
openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c
openair2/LAYER2/nr_pdcp/cuup_cucp_if.c
openair2/LAYER2/nr_pdcp/cuup_cucp_direct.c
openair2/LAYER2/nr_pdcp/cuup_cucp_e1ap.c
)
# UE build: PDCP only; CU-CP/CU-UP interface is gNB-only.
set(NR_PDCP_SRC_UE ${NR_PDCP_SRC})
set(NR_SDAP_SRC
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap.c
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_entity.c
@@ -1221,7 +1194,7 @@ set(L2_LTE_SRC
)
set(L2_NR_SRC
${NR_PDCP_SRC_GNB}
${NR_PDCP_SRC}
${NR_SDAP_SRC}
${NR_RRC_DIR}/rrc_gNB.c
${NR_RRC_DIR}/mac_rrc_dl_direct.c
@@ -1257,7 +1230,7 @@ set(L2_RRC_SRC_UE
)
set(NR_L2_SRC_UE
${NR_PDCP_SRC_UE}
${NR_PDCP_SRC}
${NR_SDAP_SRC}
${NR_UE_RRC_DIR}/L2_interface_ue.c
${NR_UE_RRC_DIR}/main_ue.c
@@ -1299,9 +1272,7 @@ set (MAC_NR_SRC
${NR_GNB_MAC_DIR}/gNB_scheduler.c
${NR_GNB_MAC_DIR}/gNB_scheduler_bch.c
${NR_GNB_MAC_DIR}/gNB_scheduler_dlsch.c
${NR_GNB_MAC_DIR}/gNB_scheduler_dlsch_default_policies.c
${NR_GNB_MAC_DIR}/gNB_scheduler_ulsch.c
${NR_GNB_MAC_DIR}/gNB_scheduler_ulsch_default_policies.c
${NR_GNB_MAC_DIR}/gNB_scheduler_primitives.c
${NR_GNB_MAC_DIR}/gNB_scheduler_phytest.c
${NR_GNB_MAC_DIR}/gNB_scheduler_uci.c
@@ -1377,6 +1348,7 @@ if(E2_AGENT)
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)
@@ -1403,14 +1375,18 @@ add_library(e1_if
target_link_libraries(e1_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap SECURITY ${OPENSSL_LIBRARIES} e1ap GTPV1U)
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc nr_common)
target_compile_definitions(L2_NR PRIVATE PDCP_CUCP_CUUP)
if(OAI_AERIAL)
target_compile_definitions(L2_NR PRIVATE ENABLE_AERIAL)
endif()
if(E3_AGENT)
target_compile_definitions(L2_NR PRIVATE E3_AGENT)
endif()
add_library(L2_LTE_NR
# temporary solution until 4G/5G code completely untangled (as evidenced by deletion of the following file)
${MAC_DIR}/dummy_functions.c
${ENB_APP_SRC}
)
target_link_libraries(L2_LTE_NR PRIVATE f1ap s1ap nr_rrc)
@@ -1927,6 +1903,11 @@ if(E2_AGENT)
target_compile_definitions(nr-softmodem PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
if (E3_AGENT)
target_link_libraries(nr-softmodem PRIVATE e3ap)
target_compile_definitions(nr-softmodem PRIVATE E3_AGENT)
endif()
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries(nr-softmodem PRIVATE
@@ -1936,7 +1917,7 @@ add_executable(nr-cuup
executables/nr-cuup.c
${NR_RRC_DIR}/rrc_gNB_UE_context.c
${OPENAIR2_DIR}/E1AP/e1ap_setup.c
${NR_PDCP_SRC_GNB}
${NR_PDCP_SRC}
${NR_SDAP_SRC}
)
@@ -1947,9 +1928,12 @@ target_link_libraries(nr-cuup PRIVATE
alg
dl pthread ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
target_compile_definitions(nr-cuup PRIVATE PDCP_CUCP_CUUP)
if(E2_AGENT)
target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup)
if(E3_AGENT)
target_link_libraries(nr-cuup PRIVATE e3ap)
target_compile_definitions(nr-cuup PRIVATE E3_AGENT)
endif()
target_compile_definitions(nr-cuup PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
@@ -2036,19 +2020,12 @@ 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} ${CUDA_LIBRARIES}
m pthread dl ${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'
-Wl,--whole-archive crc_byte -Wl,--no-whole-archive
)
if (ENABLE_LDPC_CUDA)
# ldpctest.c uses cudaHostAlloc(), so include dir/link libr to make available
# TODO don't write it directly into ldpctest, but separate compilation unit?
find_package(CUDA REQUIRED)
target_link_libraries(ldpctest PRIVATE ${CUDA_LIBRARIES})
target_include_directories(ldpctest PRIVATE ${CUDA_INCLUDE_DIRS})
endif()
add_library(physim_common OBJECT ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_unitary_common.c)
target_link_libraries(physim_common PRIVATE UTIL)
@@ -2135,13 +2112,13 @@ target_link_libraries(nr_srssim PRIVATE
m pthread ITTI dl nr_ue_phy_meas physim_common softmodem_common
)
if(ENABLE_CHANNEL_SIM_CUDA)
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 CHANNEL_SIM_CUDA)
target_compile_definitions(nr_ulsim PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(nr_dlsim PRIVATE ENABLE_CUDA)
target_compile_definitions(nr_ulsim PRIVATE ENABLE_CUDA)
endif()
endif()

View File

@@ -1,6 +1,6 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
# Contributing to OpenAirInterface
# Contributing to OpenAirInterface #
We want to make contributing to this project as easy and transparent as possible.
@@ -11,10 +11,10 @@ Please refer to the steps described on our website: [How to contribute to OAI](h
if you do not have any.
- We recommend that you register with a professional or student email address.
- If your email domain (`@domain.com`) is not whitelisted, please contact us
(mailto:oaicicdteam@openairinterface.org).
(mailto:contact@openairinterface.org).
- Eurecom GitLab does NOT accept public email domains.
3. Provide the OAI team with the **username** of this account to
(mailto:oaicicdteam@openairinterface.org) ; we will give you the developer
(mailto:contact@openairinterface.org) ; we will give you the developer
rights on this repository.
4. The contributing policies are described in the [corresponding documentation
page](doc/code-style-contrib.md).
@@ -24,43 +24,8 @@ Please refer to the steps described on our website: [How to contribute to OAI](h
request from a forked repository.
* This decision was made for the license reasons.
* The Continuous Integration will reject your merge request.
5. Mandatory signing of all the commits using the email address used for CLA.
## Commit Guidelines
### Signing Commits
To sign commits:
You can also get the verified label
on your commits via using [SSH KEYS or GPG KEYS](https://docs.gitlab.com/user/project/repository/signed_commits/)
```
# Edit .git/config in the git repository you are working on
# Add the user section
[user]
name = YOUR NAME
email = YOUR EMAIL ADDRESS
# If you use a signing key, use the below configuration instead
[user]
name = YOUR NAME
email = YOUR EMAIL ADDRESS
signingkey = LOCATION OF SSH KEYS or GPG KEY
[gpg]
format = ssh
[commit]
gpgsign = true
```
> **NOTE:** If your commits are not signed the CI framework will not accept the MR.
For more information regarding contribution guidelines
please check [this document](doc/code-style-contrib.md)
## License
# License #
By contributing to OpenAirInterface, you agree that your contributions will be
licensed under

View File

@@ -8,9 +8,8 @@
<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://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://releases.ubuntu.com/26.04/"><img src="https://img.shields.io/badge/OS-Ubuntu26-Green" alt="Supported OS Ubuntu 26"></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-Fedore44-Green" alt="Supported OS Fedora 44"></a>
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore41-Green" alt="Supported OS Fedora 43"></a>
</p>
<p align="center">

View File

@@ -20,13 +20,12 @@ if (params.LockResources != null && params.LockResources.trim().length() > 0)
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def INTERNAL_REPO = "asterix:/home/git/openairinterface5g.git"
def sourceBranch = params.sourceBranch ?: env.GIT_BRANCH
def targetBranch = params.targetBranch ?: 'develop'
def commitID = params.sourceCommit ?: env.GIT_COMMIT
def testRepository = params.customRepository ?: INTERNAL_REPO
def testBranch = params.customBranch ?: "${sourceBranch}-${commitID}"
def mergeWithTarget = params.mergeWithTarget ?: false
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
@@ -51,7 +50,7 @@ pipeline {
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.requestNumber}"
buildName "${params.eNB_MR}"
buildDescription "Branch : ${sourceBranch}"
}
}
@@ -65,12 +64,12 @@ pipeline {
echo "no LockResources given"
allParametersPresent = false
}
if (params.workspace == null) {
echo "no workspace given"
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 Openshift Cluster."
echo "This pipeline is configured to run with Opensift Cluster."
runWithOC = true
if (params.OC_ProjectName == null) {
echo "no OC_ProjectName given"
@@ -85,11 +84,21 @@ pipeline {
}
echo "CI executor node : ${pythonExecutor}"
echo "Testing Repository : ${testRepository}"
echo "Testing Branch : ${testBranch}"
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"
@@ -112,21 +121,28 @@ pipeline {
}
}
sh """
python3 main.py --mode=InitiateHtml --repository=${testRepository} \
--branch=${testBranch} --commitID=${commitID} \
${mainPythonAllXmlFiles}
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 --repository=${testRepository} \
--branch=${testBranch} \
--ranAllowMerge=${mergeWithTarget} --targetBranch=${targetBranch} \
--workspace=${params.workspace} --XMLTestFile=${xmlFile} \
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}
"""
@@ -144,10 +160,10 @@ pipeline {
try {
timeout (time: 60, unit: 'MINUTES') {
sh """
python3 main.py --mode=TesteNB --repository=${testRepository} \
--branch=${testBranch} \
--ranAllowMerge=${mergeWithTarget} --targetBranch=${targetBranch} \
--workspace=${params.workspace} --XMLTestFile=${xmlFile} \
python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
--eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \
${flexricOption}
"""
}

View File

@@ -87,20 +87,9 @@ pipeline {
// since a bit, in push events, gitlabUserEmail is not populated
gitCommitAuthorEmailAddr = env.gitlabUserEmail
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
// Validate MR commits: checks for missing Signed-off-by and merge commits
def mrValidationLog = "signedCommit_${env.BUILD_NUMBER}.log"
def mrValidationExitCode = sh(
script: "bash ./ci-scripts/pre-ci-check.sh -s origin/${env.gitlabSourceBranch} -t origin/${env.gitlabTargetBranch} > ${mrValidationLog} 2>&1",
returnStatus: true
)
def mrValidationMessage = readFile(mrValidationLog).trim()
sh "rm -f ${mrValidationLog}"
if (mrValidationExitCode >= 1) {
addGitLabMRComment comment: "${mrValidationMessage}"
}
if (mrValidationExitCode >= 2) {
error("${mrValidationMessage}")
}
// GitLab-Jenkins plugin integration is lacking to perform the merge by itself
// Doing it manually --> it may have merge conflicts
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
} else {
echo "Git Branch is ${GIT_BRANCH}"
echo "Git Commit is ${GIT_COMMIT}"
@@ -111,19 +100,29 @@ pipeline {
}
}
}
post {
failure {
script {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI"
addGitLabMRComment comment: message
currentBuild.result = 'FAILURE'
}
}
}
}
stage ("Local-Repo-Push") {
steps {
script {
triggerSlaveJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
triggerSlaveJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
}
}
}
post {
failure {
script {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Cannot perform CI - merge validation failed (merge conflict, git operation failure, or internal CI error)."
addGitLabMRComment comment: message
currentBuild.result = 'FAILURE'
echo "Push to local repository KO"
failingStages += '\n * RAN-Local-Repo-Push'
}
}
}
@@ -749,29 +748,6 @@ pipeline {
}
}
}
stage ("SA-FHI72-MPLANE-CN5G") {
when { expression {do5Gtest} }
steps {
script {
triggerSlaveJob ('RAN-SA-FHI72-MPLANE-CN5G', 'SA-FHI72-MPLANE-CN5G')
}
}
post {
always {
script {
// Using a unique variable name for each test stage to avoid overwriting on a global variable
// due to parallel-time concurrency
saFHI72MplaneStatus = finalizeSlaveJob('RAN-SA-FHI72-MPLANE-CN5G')
}
}
failure {
script {
currentBuild.result = 'FAILURE'
failingStages += saFHI72MplaneStatus
}
}
}
}
stage ("SA-Handover-CN5G") {
when { expression {do5Gtest} }
steps {
@@ -880,19 +856,12 @@ def triggerSlaveJob (jobName, gitlabStatusName) {
def localStatus = build job: jobName,
parameters: [
string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)),
string(name: 'targetRepo', value: String.valueOf(GIT_URL)),
string(name: 'SourceRepo', value: String.valueOf(env.gitlabSourceRepoHttpUrl)),
string(name: 'sourceRepo', value: String.valueOf(env.gitlabSourceRepoHttpUrl)),
string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)),
string(name: 'sourceBranch', value: String.valueOf(env.gitlabSourceBranch)),
string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
string(name: 'sourceCommit', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
string(name: 'eNB_MR', value: String.valueOf(MR_NUMBER)),
string(name: 'requestNumber', value: String.valueOf(MR_NUMBER)),
booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)),
booleanParam(name: 'mergeWithTarget', value: "MERGE".equals(env.gitlabActionType)),
string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)),
string(name: 'targetBranch', value: String.valueOf(env.gitlabTargetBranch))
string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch))
], propagate: false
def localResult = localStatus.getResult()
echo "${jobName} Slave Job status is ${localResult}"
@@ -907,13 +876,14 @@ def triggerSlaveJob (jobName, gitlabStatusName) {
def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
if ("MERGE".equals(env.gitlabActionType)) {
shaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%H" ' + env.gitlabMergeRequestLastCommit
shaOne = shaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:' + env.gitlabSourceBranch + '-' + shaOne
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
} else {
shaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%H" ' + env.GIT_COMMIT
shaOne = shaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + shaOne
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
}
// Workaround for the "cancelled" GitLab pipeline notification
// The slave job is triggered with the propagate false so the following commands are executed

View File

@@ -27,26 +27,21 @@ pipeline {
steps {
script {
def missingParams = []
if (!params.sourceRepo?.trim()) { missingParams << 'sourceRepo' }
if (!params.sourceBranch?.trim()) { missingParams << 'sourceBranch' }
if (!params.sourceCommit?.trim()) { missingParams << 'sourceCommit' }
if (params.mergeWithTarget) {
if (!params.targetRepo?.trim()) { missingParams << 'targetRepo' }
if (!params.targetBranch?.trim()) { missingParams << 'targetBranch' }
}
if (!params.SourceRepo?.trim()) { missingParams << 'SourceRepo' }
if (!params.eNB_Branch?.trim()) { missingParams << 'eNB_Branch' }
if (!params.eNB_CommitID?.trim()) { missingParams << 'eNB_CommitID' }
if (!params.eNB_TargetBranch?.trim()) { missingParams << 'eNB_TargetBranch' }
if (!params.eNB_Repository?.trim()) { missingParams << 'eNB_Repository' }
if (missingParams) {
error "Missing required parameters: ${missingParams.join(', ')}"
}
echo "Source Repo : ${params.sourceRepo}"
echo "Source Branch : ${params.sourceBranch}"
echo "Source Commit : ${params.sourceCommit}"
echo "Merge : ${params.mergeWithTarget}"
if (params.mergeWithTarget) {
echo "Target Branch : ${params.targetBranch}"
echo "Target Repo : ${params.targetRepo}"
}
echo "Source Repo : ${params.SourceRepo}"
echo "Source Branch : ${params.eNB_Branch}"
echo "Source Commit : ${params.eNB_CommitID}"
echo "Target Branch : ${params.eNB_TargetBranch}"
echo "Target Repo : ${params.eNB_Repository}"
}
}
}
@@ -56,7 +51,6 @@ pipeline {
git config user.email "jenkins@openairinterface.org"
git config user.name "OAI Jenkins"
git remote remove source || true
git remote remove target || true
git remote remove internal-repo || true
"""
}
@@ -64,38 +58,31 @@ pipeline {
stage('Add source repo & fetch branches') {
steps {
sh """
git remote add source ${params.sourceRepo} || true
git fetch source ${params.sourceBranch}
git remote add source ${params.SourceRepo} || true
git fetch source ${params.eNB_Branch}
git fetch origin ${params.eNB_TargetBranch}
"""
script {
if (params.mergeWithTarget) {
sh """
git remote add target ${params.targetRepo} || true
git fetch target ${params.targetBranch}
"""
}
}
}
}
stage('Create temporary branch for CI') {
steps {
script {
env.NEW_BRANCH = "${params.sourceBranch}-${params.sourceCommit}"
def shortCommit = params.eNB_CommitID.take(8)
env.NEW_BRANCH = "${params.eNB_Branch}-${shortCommit}"
echo "New branch: ${env.NEW_BRANCH}"
}
sh """
# Checkout source commit
git checkout -B ${env.NEW_BRANCH} ${params.sourceCommit}
git checkout -B ${env.NEW_BRANCH} ${params.eNB_CommitID}
"""
}
}
stage('Merge target into source') {
when { expression { return params.mergeWithTarget } }
steps {
sh """
echo "Merging target branch ${params.targetBranch} into source branch ${env.NEW_BRANCH}"
if ! git merge --ff target/${params.targetBranch} \
-m "Merge ${params.targetBranch} into ${params.sourceBranch} for CI"; then
echo "Merging target branch ${params.eNB_TargetBranch} into source branch ${env.NEW_BRANCH}"
if ! git merge --ff origin/${params.eNB_TargetBranch} \
-m "Merge ${params.eNB_TargetBranch} into ${params.eNB_Branch} for CI"; then
echo "Merge conflicts detected. Aborting."
git merge --abort || true
exit 1

View File

@@ -56,7 +56,7 @@ pipeline {
echo "Forced Tag is ${WEEK_TAG}"
}
}
WEEK_SHA = sh returnStdout: true, script: 'git log -n1 --pretty=format:"%H" origin/develop'
WEEK_SHA = sh returnStdout: true, script: 'git log -n1 --pretty=format:"%h" origin/develop | cut -c 1-8'
WEEK_SHA = WEEK_SHA.trim()
withCredentials([

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -32,15 +32,35 @@ from cls_ci_helper import archiveArtifact
IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-enb-asan', 'oai-gnb-asan', 'oai-lte-ue-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan', 'oai-gnb-aerial', 'oai-gnb-fhi72']
DEFAULT_REGISTRY = "gracehopper3-oai.sboai.cs.eurecom.fr"
def CreateWorkspace(host, sourcePath, repository, branch):
def CreateWorkspace(host, sourcePath, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge):
if ranCommitID == '':
logging.error('need ranCommitID in CreateWorkspace()')
raise ValueError('Insufficient Parameter in CreateWorkspace(): need ranCommitID')
script = "scripts/create_workspace.sh"
options = f"{sourcePath} {repository} {branch}"
options = f"{sourcePath} {ranRepository} {ranCommitID}"
if ranAllowMerge:
if ranTargetBranch == '':
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)
logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}')
return ret.returncode == 0
def CreateTag(ranCommitID, ranBranch, ranAllowMerge):
if ranCommitID == 'develop':
return 'develop'
shortCommit = ranCommitID[0:8]
if ranAllowMerge:
# Allowing contributor to have a name/branchName format
branchName = ranBranch.replace('/','-')
tagToUse = f'{branchName}-{shortCommit}'
else:
tagToUse = f'develop-{shortCommit}'
return tagToUse
def AnalyzeBuildLogs(image, lf):
committed = False
tagged = False
@@ -55,7 +75,7 @@ def AnalyzeBuildLogs(image, lf):
committed = committed or lineHasCommit
if re.search(r'error:|Errors|ERROR', line):
errors.append(f"=> {line.strip()}")
status = (committed or tagged)
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)
@@ -152,12 +172,14 @@ class Containerize():
def __init__(self):
self.repository = ''
self.branch = ''
self.merge = False
self.targetBranch = ''
self.workspace = ''
self.ranRepository = ''
self.ranBranch = ''
self.ranAllowMerge = False
self.ranCommitID = ''
self.ranTargetBranch = ''
self.eNBSourceCodePath = ''
self.imageKind = ''
self.proxyCommit = None
self.yamlPath = ''
self.services = ''
self.deploymentTag = ''
@@ -171,27 +193,16 @@ class Containerize():
#-----------------------------------------------------------
def BuildImage(self, ctx, node, HTML):
lSourcePath = self.workspace
lSourcePath = self.eNBSourceCodePath
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
log_files = []
dockerfileprefix = '.ubuntu'
baseImage = 'ran-base'
baseTag = 'develop'
buildImage = 'ran-build'
forceBaseImageBuild = False
imageTag = 'develop'
result = re.search('native_cuda_armv8', self.imageKind)
if result is not None:
baseImage = 'ran-base-cuda'
buildImage = 'ran-build-cuda'
dockerfileprefix = '.cuda.ubuntu'
# we always build the ran-build image with all targets
# Creating a tupple with the imageName, the DockerFile prefix pattern, targetName and sanitized option
imageNames = [(buildImage, 'build', f'{buildImage}', '')]
imageNames = [('ran-build', 'build', 'ran-build', '')]
result = re.search('eNB', self.imageKind)
if result is not None:
imageNames.append(('oai-enb', 'eNB', 'oai-enb', ''))
@@ -231,23 +242,23 @@ class Containerize():
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', ''))
result = re.search('native_cuda_armv8', self.imageKind)
if result is not None:
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
cmd.cd(lSourcePath)
if (self.merge):
baseImage = 'ran-base'
baseTag = 'develop'
forceBaseImageBuild = False
imageTag = 'develop'
if (self.ranAllowMerge):
imageTag = 'ci-temp'
if self.targetBranch == 'develop':
if self.ranTargetBranch == 'develop':
cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{dockerfileprefix} | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
# if the branch name contains integration_20xx_wyy, let rebuild ran-base
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.branch)
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.ranBranch)
if not forceBaseImageBuild and result is not None:
forceBaseImageBuild = True
baseTag = 'ci-temp'
@@ -265,17 +276,17 @@ class Containerize():
# On when the base image docker file is being modified.
if forceBaseImageBuild:
cmd.run(f"docker image rm {baseImage}:{baseTag}")
logfile = f'{lSourcePath}/cmake_targets/log/{baseImage}.docker.log'
logfile = f'{lSourcePath}/cmake_targets/log/ran-base.docker.log'
option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
cmd.run(f"docker build --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{dockerfileprefix} {option} . &> {logfile}", timeout=1600)
t = (baseImage, archiveArtifact(cmd, ctx, logfile))
t = ("ran-base", archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
# First verify if the base image was properly created.
ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
allImagesSize = {}
if ret.returncode != 0:
logging.error(f'\u001B[1m Could not build properly {baseImage}\u001B[0m')
logging.error('\u001B[1m Could not build properly ran-base\u001B[0m')
# Recover the name of the failed container?
cmd.run(f"docker ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty docker rm -f")
cmd.run(f"docker image prune --force")
@@ -288,10 +299,10 @@ class Containerize():
if result is not None:
size = float(result.group("size")) / 1000000
imageSizeStr = f'{size:.1f}'
logging.debug(f'\u001B[1m {baseImage} size is {imageSizeStr} Mbytes\u001B[0m')
allImagesSize[baseImage] = f'{imageSizeStr} Mbytes'
logging.debug(f'\u001B[1m ran-base size is {imageSizeStr} Mbytes\u001B[0m')
allImagesSize['ran-base'] = f'{imageSizeStr} Mbytes'
else:
logging.debug(f'{baseImage} size is unknown')
logging.debug('ran-base size is unknown')
# Build the target image(s)
status = True
@@ -302,11 +313,11 @@ class Containerize():
cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
# target images should use the proper ran-build image
if image != 'ran-build' and "-asan" in name:
cmd.run(f'sed -i -e "s#{buildImage}:latest#{buildImage}-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif "fhi72" in name or name == "oai-nr-oru":
cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif image != 'ran-build':
cmd.run(f'sed -i -e "s#{buildImage}:latest#{buildImage}:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
if image == 'oai-gnb-aerial':
cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2026.01.07.tar.gz .')
logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log'
@@ -365,8 +376,90 @@ class Containerize():
logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
return status
def BuildProxy(self, ctx, node, HTML):
lSourcePath = self.eNBSourceCodePath
logging.debug('Building on server: ' + node)
ssh = cls_cmd.getConnection(node)
oldRanCommidID = self.ranCommitID
oldRanRepository = self.ranRepository
oldRanAllowMerge = self.ranAllowMerge
oldRanTargetBranch = self.ranTargetBranch
self.ranCommitID = self.proxyCommit
self.ranRepository = 'https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy.git'
self.ranAllowMerge = False
self.ranTargetBranch = 'master'
# Let's remove any previous run artifacts if still there
ssh.run('docker image prune --force')
# Remove any previous proxy image
ssh.run('docker image rm oai-lte-multi-ue-proxy:latest')
tag = self.proxyCommit
logging.debug('building L2sim proxy image for tag ' + tag)
# check if the corresponding proxy image with tag exists. If not, build it
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
buildProxy = ret.returncode != 0 # if no image, build new proxy
if buildProxy:
ssh.run(f'rm -Rf {lSourcePath}')
success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
if not success:
raise Exception("could not clone proxy repository")
fullpath = f'{lSourcePath}/proxy_build.log'
ssh.run(f'docker build --target oai-lte-multi-ue-proxy --tag proxy:{tag} --file {lSourcePath}/docker/Dockerfile.ubuntu18.04 {lSourcePath} > {fullpath} 2>&1')
archiveArtifact(ssh, ctx, fullpath)
ssh.run('docker image prune --force')
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
if ret.returncode != 0:
logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m')
ssh.close()
HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK)
return False
else:
logging.debug('L2sim proxy image for tag ' + tag + ' already exists, skipping build')
# retag the build images to that we pick it up later
ssh.run(f'docker image tag proxy:{tag} oai-lte-multi-ue-proxy:latest')
# we assume that the host on which this is built will also run the proxy. The proxy
# currently requires the following command, and the docker-compose up mechanism of
# the CI does not allow to run arbitrary commands. Note that the following actually
# belongs to the deployment, not the build of the proxy...
logging.warning('the following command belongs to deployment, but no mechanism exists to exec it there!')
ssh.run('sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up')
# to prevent accidentally overwriting data that might be used later
self.ranCommitID = oldRanCommidID
self.ranRepository = oldRanRepository
self.ranAllowMerge = oldRanAllowMerge
self.ranTargetBranch = oldRanTargetBranch
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
result = re.search(r'Size *= *(?P<size>[0-9\-]+) *bytes', ret.stdout)
# Cleaning any created tmp volume
ssh.run('docker volume prune --force')
ssh.close()
allImagesSize = {}
if result is not None:
imageSize = float(result.group('size')) / 1000000
logging.debug('\u001B[1m proxy size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m')
allImagesSize['proxy'] = str(round(imageSize,1)) + ' Mbytes'
logging.info('\u001B[1m Building L2sim Proxy Image Pass\u001B[0m')
HTML.CreateHtmlTestRow('commit ' + tag, 'OK', CONST.ALL_PROCESSES_OK)
return True
else:
logging.error('proxy size is unknown')
allImagesSize['proxy'] = 'unknown'
logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m')
HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK)
return False
def BuildRunTests(self, ctx, node, dockerfile, runtime_opt, ctest_opt, HTML):
lSourcePath = self.workspace
lSourcePath = self.eNBSourceCodePath
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
cmd.cd(lSourcePath)
@@ -374,8 +467,8 @@ class Containerize():
# check that ran-base image exists as we expect it
baseImage = 'ran-base'
baseTag = 'develop'
if self.merge:
if self.targetBranch == 'develop':
if self.ranAllowMerge:
if self.ranTargetBranch == 'develop':
cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.ubuntu | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
@@ -418,7 +511,7 @@ class Containerize():
return False
def Push_Image_to_Local_Registry(self, node, HTML, tag_prefix=""):
lSourcePath = self.workspace
lSourcePath = self.eNBSourceCodePath
logging.debug('Pushing images to server: ' + node)
ssh = cls_cmd.getConnection(node)
imagePrefix = DEFAULT_REGISTRY
@@ -431,10 +524,10 @@ class Containerize():
return False
orgTag = 'develop'
if self.merge:
if self.ranAllowMerge:
orgTag = 'ci-temp'
for image in IMAGES:
tagToUse = tag_prefix + self.branch
tagToUse = tag_prefix + CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
imageTag = f"{image}:{tagToUse}"
ret = ssh.run(f'docker image tag {image}:{orgTag} {imagePrefix}/{imageTag}')
if ret.returncode != 0:
@@ -447,7 +540,7 @@ class Containerize():
HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK)
return False
# Creating a develop tag on the local private registry
if not self.merge:
if not self.ranAllowMerge:
devTag = f"{tag_prefix}develop"
ssh.run(f'docker image tag {image}:{orgTag} {imagePrefix}/{image}:{devTag}')
ssh.run(f'docker push {imagePrefix}/{image}:{devTag}')
@@ -495,7 +588,7 @@ class Containerize():
def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry=DEFAULT_REGISTRY, username="oaicicd", password="oaicicd"):
logging.debug(f'\u001B[1m Pulling image(s) on server: {node}\u001B[0m')
if not tag:
tag = self.branch
tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
with cls_cmd.getConnection(node) as cmd:
success, msg = Containerize.Pull_Image(cmd, images, tag, tag_prefix, registry, username, password)
param = f"on node {node}"
@@ -508,7 +601,7 @@ class Containerize():
def Clean_Test_Server_Images(self, HTML, node, images, tag=None):
logging.debug(f'\u001B[1m Cleaning image(s) from server: {node}\u001B[0m')
if not tag:
tag = self.branch
tag = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
status = True
with cls_cmd.getConnection(node) as myCmd:
@@ -527,17 +620,17 @@ class Containerize():
return status
def Create_Workspace(self, node, HTML):
sourcePath = self.workspace
success = CreateWorkspace(node, sourcePath, self.repository, self.branch)
lSourcePath = self.eNBSourceCodePath
success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
if success:
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {sourcePath} on node {node}"])
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {lSourcePath}"])
else:
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["cannot create workspace"])
return success
def DeployObject(self, ctx, node, HTML):
num_attempts = self.num_attempts
lSourcePath = self.workspace
lSourcePath = self.eNBSourceCodePath
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
@@ -555,7 +648,7 @@ class Containerize():
raise ValueError(f'Invalid value for num_attempts: {num_attempts}, must be greater than 0')
for attempt in range(num_attempts):
logging.info(f'will start services {services}')
status = ssh.run(f'docker compose -f {wd_yaml} up -d --wait --wait-timeout 120 -- {services}')
status = ssh.run(f'docker compose -f {wd_yaml} up -d --wait --wait-timeout 60 -- {services}')
info = ssh.run(f"docker compose -f {wd_yaml} ps --all --format=\'table {{{{.Service}}}} [{{{{.Image}}}}] {{{{.Status}}}}\' -- {services} | column -t")
deployed = status.returncode == 0
if not deployed:
@@ -581,7 +674,7 @@ class Containerize():
return deployed
def StopObject(self, ctx, node, HTML):
lSourcePath = self.workspace
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')
@@ -610,7 +703,7 @@ class Containerize():
return success
def UndeployObject(self, ctx, node, HTML, to_analyze):
lSourcePath = self.workspace
lSourcePath = self.eNBSourceCodePath
logging.info(f'\u001B[1m Undeploying all objects from server {node}\u001B[0m')
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
@@ -648,7 +741,7 @@ class Containerize():
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None):
logging.info(f'Analyzing realtime stats from server: {node}')
yaml = self.yamlPath.strip('/')
wd = f'{self.workspace}/{yaml}'
wd = f'{self.eNBSourceCodePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as cmd:

View File

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

View File

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

View File

@@ -207,40 +207,3 @@ channelmod:
forgetfact: 0
offset: 0
ds_tdl: 0
vrtsim:
role: server
# Channel mode: exactly one of the three modes below should be active.
#
# No channel - plain passthrough, no impairments:
# cirdb: 0
# chanmod: 0
#
# Built-in channel model defined in the channelmod: section above:
# chanmod: 1
# cirdb: 0
#
# External taps emitter publishing over a nanomsg socket.
# Requires a running emit_from_db.py and build with -DOAI_VRTSIM_TAPS_CLIENT=ON:
# cirdb: 0
# chanmod: 0
# taps-socket: "tcp://127.0.0.1:5555"
#
# In-process CIR database: reads precomputed 3GPP TDL taps directly from
# cir_db.bin. No external emitter required. Generate the database offline
# with cir_generator.py. Use cirdb-path to point to the directory containing
# cir_db.bin and cir_db.yaml.
cirdb_file: /cirdb/cir_db.bin
cirdb_yaml: /cirdb/cir_db.yaml
#
# Per-UE channel configuration for multi-UE operation
ue_config:
- antennas: "2x2" # NxM where N=UE-TX, M=gNB-TX; M must equal RU nb_tx
model_id: 0 # 0=TDL-A 1=TDL-B 2=TDL-C 3=TDL-D 4=TDL-E
ds_ns: 1.0 # RMS delay spread in ns
speed_mps: 1.5 # UE speed in m/s
# aoa_deg: 0.0 # angle of arrival in degrees; TDL-D/E only
- antennas: "1x2"
model_id: 0
ds_ns: 1.0
speed_mps: 1.5
# aoa_deg: 0.0

View File

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

View File

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

126
ci-scripts/doGitLabMerge.sh Executable file
View File

@@ -0,0 +1,126 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
function usage {
echo "OAI GitLab merge request applying script"
echo ""
echo "Usage:"
echo "------"
echo ""
echo " doGitLabMerge.sh [OPTIONS] [MANDATORY_OPTIONS]"
echo ""
echo "Mandatory Options:"
echo "------------------"
echo ""
echo " --src-branch #### OR -sb ####"
echo " Specify the source branch of the merge request."
echo ""
echo " --src-commit #### OR -sc ####"
echo " Specify the source commit ID (SHA-1) of the merge request."
echo ""
echo " --target-branch #### OR -tb ####"
echo " Specify the target branch of the merge request (usually develop)."
echo ""
echo " --target-commit #### OR -tc ####"
echo " Specify the target commit ID (SHA-1) of the merge request."
echo ""
echo "Options:"
echo "--------"
echo " --help OR -h"
echo " Print this help message."
echo ""
}
if [ $# -ne 8 ] && [ $# -ne 1 ]
then
echo "Syntax Error: not the correct number of arguments"
echo ""
usage
exit 1
fi
checker=0
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-h|--help)
shift
usage
exit 0
;;
-sb|--src-branch)
SOURCE_BRANCH="$2"
let "checker|=0x1"
shift
shift
;;
-sc|--src-commit)
SOURCE_COMMIT_ID="$2"
let "checker|=0x2"
shift
shift
;;
-tb|--target-branch)
TARGET_BRANCH="$2"
let "checker|=0x4"
shift
shift
;;
-tc|--target-commit)
TARGET_COMMIT_ID="$2"
let "checker|=0x8"
shift
shift
;;
*)
echo "Syntax Error: unknown option: $key"
echo ""
usage
exit 1
esac
done
if [[ $TARGET_COMMIT_ID == "latest" ]]
then
TARGET_COMMIT_ID=`git log -n1 --pretty=format:%H origin/$TARGET_BRANCH`
fi
echo "Source Branch is : $SOURCE_BRANCH"
echo "Source Commit ID is : $SOURCE_COMMIT_ID"
echo "Target Branch is : $TARGET_BRANCH"
echo "Target Commit ID is : $TARGET_COMMIT_ID"
if [ $checker -ne 15 ]
then
echo ""
echo "Syntax Error: missing option"
echo ""
usage
exit 1
fi
git config user.email "jenkins@openairinterface.org"
git config user.name "OAI Jenkins"
git checkout -f $SOURCE_COMMIT_ID > checkout.txt 2>&1
STATUS=`grep -E -c "fatal: reference is not a tree" checkout.txt`
rm -f checkout.txt
if [ $STATUS -ne 0 ]
then
echo "fatal: reference is not a tree --> $SOURCE_COMMIT_ID"
STATUS=-1
exit $STATUS
fi
git merge --ff $TARGET_COMMIT_ID -m "Temporary merge for CI"
STATUS=`git status | grep -E -c "You have unmerged paths.|fix conflicts"`
if [ $STATUS -ne 0 ]
then
echo "There are merge conflicts.. Cannot perform further build tasks"
STATUS=-1
fi
exit $STATUS

View File

@@ -26,7 +26,7 @@ RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON -DENABLE_TESTS=ON \
-DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \
-DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \
-DPHYSIM_CHECK_FILES="ThresholdsCuda.cmake" \
-DENABLE_CHANNEL_SIM_CUDA=ON \
-DCUDA_ENABLE=ON \
-DUSE_UNIFIED_MEMORY=ON \
-DUSE_ATS_MEMORY=OFF \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \

View File

@@ -26,7 +26,7 @@ RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON -DENABLE_TESTS=ON \
-DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \
-DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \
-DPHYSIM_CHECK_FILES="ThresholdsCuda.cmake" \
-DENABLE_CHANNEL_SIM_CUDA=ON \
-DCUDA_ENABLE=ON \
-DUSE_UNIFIED_MEMORY=ON \
-DUSE_ATS_MEMORY=OFF \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \

View File

@@ -22,4 +22,4 @@ WORKDIR /oai-ran
COPY . .
WORKDIR /oai-ran/build
RUN cmake -GNinja -DENABLE_TESTS=ON -DENABLE_CHANNEL_SIM_CUDA=ON .. && ninja tests
RUN cmake -GNinja -DENABLE_TESTS=ON -DCUDA_ENABLE=ON .. && ninja tests

View File

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

View File

@@ -28,15 +28,16 @@ def GenericHelp(vers):
print(' images are available locally, will not remove any images and will run inside the current repo directory')
def GitSrvHelp(repository,branch,commit,mergeallow,targetbranch):
print(' --repository=[OAI RAN Repository URL] -- ' + repository)
print(' --branch=[OAI RAN Repository Branch] -- ' + branch)
print(' --commitID=[OAI RAN Repository Commit SHA-1] -- ' + commit)
print(' --ranRepository=[OAI RAN Repository URL] -- ' + repository)
print(' --ranBranch=[OAI RAN Repository Branch] -- ' + branch)
print(' --ranCommitID=[OAI RAN Repository Commit SHA-1] -- ' + commit)
print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)] -- ' + mergeallow)
print(' --targetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch)
print(' --ranTargetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch)
def SrvHelp(sourcepath):
print(' --workspace=[directory for workspaces on remote hosts] -- ' + sourcepath)
def eNBSrvHelp(sourcepath):
print(' --eNBSourceCodePath=[eNB\'s Source Code Path] -- ' + sourcepath)
def XmlHelp(filename):
print(' --XMLTestFile=[XML Test File to be run] -- ' + filename)
print(' Note: multiple xml files can be specified (--XMLFile=File1 ... --XMLTestFile=FileN) when HTML headers are created ("InitiateHtml" mode)')

View File

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

View File

@@ -1,96 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
function usage {
echo "OAI GitLab MR validation script (Signed-off-by and merge commits)"
echo ""
echo "Usage:"
echo "------"
echo " $0 -s <source-branch> -t <target-branch>"
echo ""
echo "Options:"
echo "--------"
echo " -s"
echo " The source branch of the merge request. Default value is current Git Branch (HEAD)"
echo ""
echo " -t"
echo " The target branch of the merge request. Default value is develop"
echo ""
echo " -h"
echo " Print this help message."
echo ""
}
# Parse arguments properly
SOURCE_BRANCH=$(git rev-parse --abbrev-ref HEAD)
TARGET_BRANCH="origin/develop"
git fetch --quiet
while getopts ":s:t:h" opt; do
case "$opt" in
s)
SOURCE_BRANCH="$OPTARG"
;;
t)
TARGET_BRANCH="$OPTARG"
;;
h)
usage
exit 0
;;
:)
echo "Error: Option -$OPTARG requires a value."
echo ""
usage
exit 2
;;
\?)
echo "Error: Invalid option -$OPTARG"
echo ""
usage
exit 2
;;
esac
done
# ----------------------------
# Merged commits
# ----------------------------
mergeCommits=$(git rev-list --merges --abbrev-commit "$TARGET_BRANCH".."$SOURCE_BRANCH")
if [[ ! "$SOURCE_BRANCH" =~ ^(origin/)?integration_[0-9]{4}_w[0-9]{2}$ ]]; then
if [[ -n "$mergeCommits" ]]; then
message="> ERROR: Following merge commits are found in the source branch history. Please rebase your branch.\n>\n"
message+="> $(echo "$mergeCommits" | paste -sd ',' -)\n"
echo -e "$message"
exit 3
fi
fi
# ----------------------------
# Check unsigned commits
# ----------------------------
unsignedCommits=$(
for c in $(git rev-list "$TARGET_BRANCH".."$SOURCE_BRANCH" --no-merges); do
if ! git log -1 --format=%B "$c" | grep -q "Signed-off-by:"; then
git log -1 --format='%h' "$c"
fi
done | paste -sd ","
)
# ----------------------------
# Report unsigned commits
# ----------------------------
message=""
if [ -n "$unsignedCommits" ]; then
message="> WARNING: The following commit(s) are missing a Signed-off-by:\n>\n> $unsignedCommits\n>\n"
message+="> Please use 'git commit -s' to sign your commits.\n>\n"
message+="> For detailed instructions, refer to the CONTRIBUTING file at the root of this repository."
echo -e "$message"
exit 1
else
message="> All commits are signed off using 'git commit -s'."
echo -e "$message"
exit 0
fi

View File

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

View File

@@ -30,13 +30,15 @@ docker tag oai-nr-ue oai-ci/oai-nr-ue:develop-${SHORT_COMMIT_SHA}
docker tag oai-gnb oai-ci/oai-gnb:develop-${SHORT_COMMIT_SHA}
docker tag oai-nr-cuup oai-ci/oai-nr-cuup:develop-${SHORT_COMMIT_SHA}
python3 main.py --mode=InitiateHtml --repository=NONE --branch=${CURRENT_BRANCH} \
python3 main.py --mode=InitiateHtml --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
--ranTargetBranch=NONE \
--XMLTestFile=xml_files/${TESTCASE} --local --datefmt="%H:%M:%S"
python3 main.py --mode=TesteNB --repository=NONE --branch=${CURRENT_BRANCH} \
--ranAllowMerge=false \
--targetBranch=NONE \
--workspace=${REPO_PATH} \
python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
--ranTargetBranch=NONE \
--eNBSourceCodePath=${REPO_PATH} \
--XMLTestFile=${TESTCASE} --local --datefmt="%H:%M:%S"
RET=$?

View File

@@ -6,16 +6,22 @@ function die() {
exit 1
}
[ $# -eq 3 ] || die "usage: $0 <directory> <repository> <branch>"
[ $# -ge 3 -a $# -le 4 ] || die "usage: $0 <directory> <repository> <ref> [<merge-ref>]"
set -ex
dir=$1
repo=$2
branch=$3
ref=$3
merge=$4
rm -rf ${dir}
git clone --depth=1 --branch "${branch}" "${repo}" "${dir}"
git clone --filter=blob:none -n ${repo} ${dir}
cd ${dir}
git config user.email "jenkins@openairinterface.org"
git config user.name "OAI Jenkins"
git config advice.detachedHead false
mkdir -p cmake_targets/log
git checkout -f ${ref}
[ -n "${merge}" ] && git fetch origin ${merge} && git merge --ff FETCH_HEAD -m "Temporary merge for CI"
exit 0

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,17 +9,21 @@ rm -f ${file}
cd ../../
python3 main.py \
--mode=InitiateHtml \
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--branch=${branch} \
--ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--ranBranch=${branch} \
--ranCommitID=${commit} \
--ranAllowMerge=true \
--ranTargetBranch=develop \
--XMLTestFile=tests/test-runner/test.xml
python3 main.py \
--mode=TesteNB \
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--branch=${branch} \
--ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--ranBranch=${branch} \
--ranCommitID=${commit} \
--ranAllowMerge=true \
--targetBranch=develop \
--workspace=NONE \
--ranTargetBranch=develop \
--eNBSourceCodePath=NONE \
--XMLTestFile=tests/test-runner/test.xml
python3 main.py \

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>obelix</node>
</testCase>

View File

@@ -7,7 +7,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>gracehopper3-oai</node>
</testCase>

View File

@@ -1,28 +0,0 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>build-cuda-tab</htmlTabRef>
<htmlTabName>Build Container Images for ARM with CUDA</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace for server 0</desc>
<node>jetson3-oai</node>
</testCase>
<testCase>
<class>Build_Image</class>
<desc>Build all Images</desc>
<node>jetson3-oai</node>
<kind>native_cuda_armv8</kind>
</testCase>
<testCase>
<class>Push_Local_Registry</class>
<desc>Push Images to Local Registry</desc>
<node>jetson3-oai</node>
<tag_prefix>armv8_cuda_</tag_prefix>
</testCase>
</testCaseList>

View File

@@ -7,7 +7,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>jetson3-oai</node>
</testCase>

View File

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

View File

@@ -34,7 +34,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -34,7 +34,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -35,7 +35,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>
@@ -54,7 +54,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 1</desc>
<node>carabe</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -34,7 +34,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -28,7 +28,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -31,7 +31,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>gracehopper1-oai</node>
</testCase>

View File

@@ -31,7 +31,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>gracehopper1-oai</node>
</testCase>

View File

@@ -1,192 +0,0 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>JETSON-5G-NRUE-CUDA</htmlTabRef>
<htmlTabName>30 MHz TDD SA JETSON with CUDA</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<testCase>
<class>DeployCoreNetwork</class>
<desc>Initialize 5G Core</desc>
<cn_id>oc-cn5g-00104</cn_id>
</testCase>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>jetson2-oai</node>
<images>oai-nr-ue</images>
<tag_prefix>armv8_cuda_</tag_prefix>
</testCase>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>gracehopper1-oai</node>
<images>oai-gnb-aerial</images>
<tag_prefix>arm_</tag_prefix>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<node>jetson2-oai</node>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<node>gracehopper1-oai</node>
</testCase>
<testCase>
<class>Custom_Script</class>
<desc>Configure 30 MHz bandwidth on WNC RU</desc>
<node>gracehopper1-oai</node>
<script>scripts/set-wnc-bandwidth.sh</script>
<args>30</args>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy PNF/Nvidia CUBB in a container</desc>
<node>gracehopper1-oai</node>
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial_30MHz</yaml_path>
<services>nv-cubb</services>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy VNF in a container</desc>
<node>gracehopper1-oai</node>
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial_30MHz</yaml_path>
<services>oai-gnb-aerial</services>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy nrUE (TDD/Band78/40MHz/N310) in a container</desc>
<yaml_path>ci-scripts/yaml_files/sa_b200_jetson_cuda_nrue</yaml_path>
<node>jetson2-oai</node>
<num_attempts>3</num_attempts>
</testCase>
<testCase>
<class>Attach_UE</class>
<desc>Attach OAIUE</desc>
<id>oai_ue_jetson2</id>
</testCase>
<testCase>
<class>Custom_Command</class>
<desc>Configure IP route</desc>
<node>jetson2-oai</node>
<command>sudo ip route add 172.21.6.105 via 13.1.1.100 dev oaitun_ue1</command>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping: 20pings in 20sec</desc>
<id>oai_ue_jetson2</id>
<svr_id>oc-cn5g-00104</svr_id>
<ping_args>-c 20</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_rttavg_threshold>25</ping_rttavg_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/10Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 10M -t 30 -i 1</iperf_args>
<id>oai_ue_jetson2</id>
<svr_id>oc-cn5g-00104</svr_id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/10Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 10M -t 30 -i 1 -R</iperf_args>
<id>oai_ue_jetson2</id>
<svr_id>oc-cn5g-00104</svr_id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/30Mbps/UDP)(30 sec)</desc>
<may_fail>true</may_fail>
<iperf_args>-u -b 30M -t 30 -i 1</iperf_args>
<id>oai_ue_jetson2</id>
<svr_id>oc-cn5g-00104</svr_id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/30Mbps/UDP)(30 sec)</desc>
<may_fail>true</may_fail>
<iperf_args>-u -b 30M -t 30 -i 1 -R</iperf_args>
<id>oai_ue_jetson2</id>
<svr_id>oc-cn5g-00104</svr_id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy nr UE</desc>
<node>jetson2-oai</node>
<yaml_path>ci-scripts/yaml_files/sa_b200_jetson_cuda_nrue</yaml_path>
<analysis>
<services>oai-nr-ue</services>
</analysis>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy gNB</desc>
<node>gracehopper1-oai</node>
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial_30MHz</yaml_path>
<analysis>
<services>oai-gnb-aerial=RetxCheck=20,100,100,100 oai-gnb-aerial=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
<class>Custom_Script</class>
<always_exec>true</always_exec>
<desc>Configure 100 MHz bandwidth on WNC RU</desc>
<node>gracehopper1-oai</node>
<script>scripts/set-wnc-bandwidth.sh</script>
<args>100</args>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>gracehopper1-oai</node>
<images>oai-gnb-aerial</images>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>jetson2-oai</node>
<images>oai-nr-ue</images>
</testCase>
<testCase>
<class>UndeployCoreNetwork</class>
<always_exec>true</always_exec>
<desc>Terminate 5G Core</desc>
<cn_id>oc-cn5g-00104</cn_id>
</testCase>
</testCaseList>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>ofqot</node>
</testCase>

View File

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

View File

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

View File

@@ -28,7 +28,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>cacofonix</node>
</testCase>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -97,7 +97,7 @@ services:
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.chanmod 1 --vrtsim.num_ues 1
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.chanmod 1
depends_on:
- oai-ext-dn
networks:
@@ -123,7 +123,7 @@ services:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --ue-nb-ant-rx 2 --ue-nb-ant-tx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim
depends_on:
- oai-gnb
networks:

View File

@@ -111,7 +111,7 @@ services:
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.cirdb 1 --vrtsim.num_ues 1
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.cirdb 1 --vrtsim.cirdb_file /cirdb/cir_db.bin --vrtsim.cirdb_yaml /cirdb/cir_db.yaml --vrtsim.cirdb_model_id 0 --vrtsim.cirdb_ds_ns 1 --vrtsim.cirdb_speed_mps 1.5
depends_on:
cir-generator:
condition: service_completed_successfully
@@ -142,7 +142,7 @@ services:
- NET_ADMIN
- NET_RAW
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --ue-nb-ant-rx 2 --ue-nb-ant-tx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client
depends_on:
- oai-gnb
networks:

View File

@@ -111,7 +111,7 @@ services:
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.cirdb 1 --vrtsim.num_ues 2 --gNBs.[0].min_rxtxtime 8
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.num_ues 2 --vrtsim.cirdb 1 --vrtsim.cirdb_file /cirdb/cir_db.bin --vrtsim.cirdb_yaml /cirdb/cir_db.yaml --vrtsim.ue_config.[0].antennas 1x2 --vrtsim.ue_config.[0].model_id 0 --vrtsim.ue_config.[0].ds_ns 10.0 --vrtsim.ue_config.[0].speed_mps 1.5 --vrtsim.ue_config.[1].antennas 2x2 --vrtsim.ue_config.[1].model_id 1 --vrtsim.ue_config.[1].ds_ns 10.0 --vrtsim.ue_config.[1].speed_mps 1.5 --gNBs.[0].min_rxtxtime 8
depends_on:
cir-generator:
condition: service_completed_successfully
@@ -142,7 +142,7 @@ services:
- NET_ADMIN
- NET_RAW
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 0 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 0 --ue-nb-ant-tx 1 --ue-nb-ant-rx 2
depends_on:
- oai-gnb
networks:
@@ -171,7 +171,7 @@ services:
- NET_ADMIN
- NET_RAW
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001101 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 1 --ue-nb-ant-tx 1 --ue-nb-ant-rx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001101 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 1 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2
depends_on:
- oai-gnb
networks:

View File

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

View File

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

View File

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

View File

@@ -1,40 +0,0 @@
# SPDX-License-Identifier: MIT
services:
oai-nr-ue:
image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
network_mode: host
runtime: nvidia
container_name: oai-nr-ue
cap_drop:
- ALL
cap_add:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
- SYS_NICE # for performance
- IPC_LOCK # for memory locking
devices:
- /dev/net/tun:/dev/net/tun
- /dev/bus/usb/:/dev/bus/usb/
ulimits:
core: -1 # for core dumps
environment:
TZ: Europe/Paris
USE_B2XX: 'yes'
USE_ADDITIONAL_OPTIONS: --usrp-args type=b200 -C 3350010000 -r 78 --numerology 1 --band 78 --ssb 345 --ue-fo-compensation --uicc0.imsi 001040000000001 --uicc0.pdu_sessions.[0].dnn oai.ipv4 --thread-pool 5,6,7,8,9 --ue-txgain 15 --ue-rxgain 90 --loader.ldpc.shlibversion _cuda -A 60
cpuset: "3-11"
volumes:
- ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,7 +18,7 @@ HWs=""
BUILD_DIR=ran_build
CMAKE_BUILD_TYPE="RelWithDebInfo"
CMAKE_CMD="$CMAKE"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_aal ldpc_cuda websrv oai_iqplayer imscope imscope_record"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_aal ldpc_xdma websrv oai_iqplayer imscope imscope_record"
TARGET_LIST=""
BUILD_TOOL_OPT="-j$(nproc)"
@@ -43,6 +43,8 @@ Options:
Sets build directory (will be <oai-root>/cmake_targets/<build-dir>/build)
--build-e2
Enable the the E2 Agent
--build-e3
Enable the the E3 Agent
-I | --install-external-packages
Installs required packages such as LibXML, asn1.1 compiler, ...
This option will require root password
@@ -143,6 +145,10 @@ function main() {
CMAKE_CMD="$CMAKE_CMD -DE2_AGENT=ON"
shift
;;
--build-e3 )
CMAKE_CMD="$CMAKE_CMD -DE3_AGENT=ON"
shift
;;
-I | --install-external-packages)
INSTALL_EXTERNAL=1
echo_info "Will install external packages"

View File

@@ -88,85 +88,3 @@ function(run_asn1c ASN1C_GRAMMAR ASN1C_PREFIX)
COMMENT "Generating ${ASN1C_COMMENT} from ${GRAMMAR_FILE}"
)
endfunction()
define_property(TEST PROPERTY TEST_DESCRIPTION
BRIEF_DOCS "A human-readable description of this test"
FULL_DOCS "A human-readable description of this test")
define_property(TEST PROPERTY CHECK_COUNT
BRIEF_DOCS "helper property to enumerate checks in environment"
FULL_DOCS "the property counts the number of threshold checks, used to enumerate environment variables given to analyze-timing.sh")
function(add_physim_test test_name test_description test_exec)
# catch all the arguments past the last expected arqument and store them in the options_list
if (NOT TARGET ${test_exec})
message(FATAL_ERROR "test executable ${test_exec} is not an executable")
endif()
set(test_invocation $<TARGET_FILE:${test_exec}> ${ARGN})
add_test(
NAME ${test_name}
COMMAND ${CMAKE_COMMAND}
"-DTEST_CMD=${test_invocation}"
"-DCHECK_SCRIPT=${CMAKE_SOURCE_DIR}/openair1/SIMULATION/tests/analyze-timing.sh"
-P ${CMAKE_SOURCE_DIR}/openair1/SIMULATION/tests/RunTimedTest.cmake
)
set_tests_properties(${test_name} PROPERTIES
LABELS "${test_exec}"
TEST_DESCRIPTION "${test_description}"
# pass test description also through environment variable: for cmake < 3.30,
# in JSON export, we cannot recover the description otherwise
# see also https://gitlab.kitware.com/cmake/cmake/-/issues/21490
ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR};TEST_DESCRIPTION=${test_description}"
)
set_tests_properties(${test_name} PROPERTIES CHECK_COUNT 0)
add_dependencies(tests ${test_exec})
endfunction()
function(check_threshold testname threshold condition)
# check that threshold and condition don't have a colon (;), because that
# would interfere with cmake's list management
string(FIND "${threshold}" ";" pos)
if (pos GREATER -1)
message(FATAL_ERROR "colon not allowed in threshold, but have \"${threshold}\"")
endif()
string(FIND "${condition}" ";" pos)
if (pos GREATER -1)
message(FATAL_ERROR "colon not allowed in condition, but have \"${condition}\"")
endif()
set(THRCOND "${threshold}\;${condition}")
get_test_property(${testname} CHECK_COUNT count)
#message(STATUS "add check ${count} ${THRCOND}")
if (${count} GREATER 10)
message(FATAL_ERROR "only maximum of 10 checks per test allowed")
endif()
# add a new environment variable CHECK_X with this threshold+condition, then
# increase test property regarding check count
set_property(TEST ${testname} APPEND PROPERTY ENVIRONMENT "CHECK_${count}=${THRCOND}")
MATH(EXPR count "${count}+1")
set_tests_properties(${testname} PROPERTIES CHECK_COUNT ${count})
endfunction()
function(check_threshold_range testname threshold)
cmake_parse_arguments(RANGE "" "LOWER;UPPER" "" ${ARGN})
if (NOT RANGE_LOWER AND NOT RANGE_UPPER)
message(FATAL_ERROR "need at least one LOWER or one UPPER threshold")
endif()
if (RANGE_LOWER)
check_threshold(${testname} ${threshold} "> ${RANGE_LOWER}")
endif()
if (RANGE_UPPER)
check_threshold(${testname} ${threshold} "< ${RANGE_UPPER}")
endif()
endfunction()
function(check_threshold_variance testname threshold)
cmake_parse_arguments(VARIANCE "" "AVG;ABS_VAR" "" ${ARGN})
if (NOT VARIANCE_AVG AND NOT VARIANCE_ABS_VAR)
message(FATAL_ERROR "need both AVG and ABS_VAR")
endif()
MATH(EXPR upper "${VARIANCE_AVG}+${VARIANCE_ABS_VAR}")
MATH(EXPR lower "${VARIANCE_AVG}-${VARIANCE_ABS_VAR}")
check_threshold_range(${testname} ${threshold} LOWER ${lower} UPPER ${upper})
endfunction()

View File

@@ -83,13 +83,11 @@ get_distribution_release() {
check_supported_distribution() {
local distribution=$(get_distribution_release)
case "$distribution" in
"ubuntu26.04") return 0 ;;
"ubuntu24.04") return 0 ;;
"ubuntu22.04") return 0 ;;
"debian11") return 0 ;;
"debian12") return 0 ;;
"fedora43") return 0 ;;
"fedora44") return 0 ;;
"rhel9.0") return 0 ;;
"rhel9.1") return 0 ;;
"rhel9.2") return 0 ;;
@@ -98,7 +96,6 @@ check_supported_distribution() {
"rhel9.5") return 0 ;;
"rhel9.6") return 0 ;;
"rhel9.7") return 0 ;;
"rhel9.8") return 0 ;;
"centos9") return 0 ;; # CentOS stream
"rocky9.1") return 0 ;;
"rocky9.2") return 0 ;;
@@ -107,7 +104,6 @@ check_supported_distribution() {
"rocky9.5") return 0 ;;
"rocky9.6") return 0 ;;
"rocky9.7") return 0 ;;
"rocky9.8") return 0 ;;
esac
return 1
}
@@ -145,8 +141,12 @@ install_usrp_uhd_driver_from_source(){
# - 3.15.0.0
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-3.15-tdd-patch.diff
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
elif [[ "$UHD_VERSION" == "4.10.0.0" || "$UHD_VERSION" == "4.9.0.0" || "$UHD_VERSION" == "4.8.0.0" || "$UHD_VERSION" == "4.7.0.0" || "$UHD_VERSION" == "4.6.0.0" || "$UHD_VERSION" == "4.5.0.0" ]]; then
# Tested patch for versions listed in elif clause
elif [[ "$UHD_VERSION" == "4.8.0.0" || "$UHD_VERSION" == "4.7.0.0" || "$UHD_VERSION" == "4.6.0.0" || "$UHD_VERSION" == "4.5.0.0" ]]; then
# Tested that patch for the following versions:
# - 4.7.0.0
cp $OPENAIR_DIR/cmake_targets/tools/uhd-4.x-tdd-patch.diff $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
sed -i '9,13 s/STATE_OFF/STATE_RX1_OFF/' $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
sed -i '24,28 s/STATE_OFF/STATE_RX2_OFF/' $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
else
@@ -162,8 +162,8 @@ install_usrp_uhd_driver_from_source(){
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
fi
else
git checkout tags/v4.8.0.0
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
git checkout tags/v4.0.0.0
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-4.x-tdd-patch.diff
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
fi
# Printing out the results of the patch to make sure it was properly applied
@@ -199,14 +199,29 @@ check_install_usrp_uhd_driver(){
install_usrp_uhd_driver_from_source
return
fi
# The new USRP repository
# Raphael Defosseux: Adding a loop on adding PPA because in CI the gpg key retrieve may
# timeout due to proxy / network latencies in Eurecom on VM
echo_info "\nAdding PPA repository ettusresearch/uhd\n"
$SUDO add-apt-repository ppa:ettusresearch/uhd -y
x=0
while [ $x -le 5 ]
do
if $SUDO add-apt-repository ppa:ettusresearch/uhd -y
then
echo_info "add-apt-repository successful\n"
break
else
echo_info "add-apt-repository failed, retrying...\n"
sleep 30
fi
x=$((x + 1))
done
$SUDO apt-get update
$SUDO apt-get -y install python3-tk $boost_libs_ubuntu libusb-1.0-0-dev
case "$(get_distribution_release)" in
"ubuntu22.04") $SUDO apt-get -y install libuhd-dev libuhd4.5.0 uhd-host ;;
"ubuntu24.04") $SUDO apt-get -y install libuhd-dev libuhd4.8.0 uhd-host ;;
"ubuntu26.04") $SUDO apt-get -y install libuhd-dev libuhd4.9.0 uhd-host ;;
"ubuntu22.04")
$SUDO apt-get -y install libuhd-dev libuhd4.5.0 uhd-host
;;
esac
elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
boost_libs_fedora="boost-chrono boost-date-time boost-filesystem boost-program-options boost-thread boost-test boost-regex boost-devel"

View File

@@ -1,34 +0,0 @@
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 6de161e87..432af5784 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -1410,10 +1410,10 @@ void b200_impl::update_atrs(void)
if (not enb_rx and enb_tx)
fd = txonly;
gpio_atr_3000::sptr atr = perif.atr;
- atr->set_atr_reg(ATR_REG_IDLE, STATE_RX1_OFF);
- atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly);
- atr->set_atr_reg(ATR_REG_TX_ONLY, txonly);
- atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd);
+ atr->set_atr_reg(ATR_REG_IDLE, STATE_RX1_OFF | (1<<7));
+ atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_TX_ONLY, txonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd | (1<<7));
}
if (_radio_perifs.size() > _fe2 and _radio_perifs[_fe2].atr) {
radio_perifs_t& perif = _radio_perifs[_fe2];
@@ -1431,10 +1431,10 @@ void b200_impl::update_atrs(void)
if (not enb_rx and enb_tx)
fd = txonly;
gpio_atr_3000::sptr atr = perif.atr;
- atr->set_atr_reg(ATR_REG_IDLE, STATE_RX2_OFF);
- atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly);
- atr->set_atr_reg(ATR_REG_TX_ONLY, txonly);
- atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd);
+ atr->set_atr_reg(ATR_REG_IDLE, STATE_RX2_OFF | (1<<7));
+ atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_TX_ONLY, txonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd | (1<<7));
}
}

View File

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

View File

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

View File

@@ -17,6 +17,7 @@
# define NUMBER_OF_SCH_STATS_MAX 16
# ifndef PHYSIM
# ifndef UE_EXPANSION
# define NUMBER_OF_UE_MAX 40
# define NUMBER_OF_CONNECTED_eNB_MAX 1
@@ -26,5 +27,10 @@
# define NUMBER_OF_CONNECTED_eNB_MAX 1
# define NUMBER_OF_CONNECTED_gNB_MAX 1
# endif
# else
# define NUMBER_OF_UE_MAX 4
# define NUMBER_OF_CONNECTED_eNB_MAX 1
# define NUMBER_OF_CONNECTED_gNB_MAX 1
# endif
#endif /* OPENAIRINTERFACE5G_LIMITS_H_ */

View File

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

View File

@@ -11,7 +11,7 @@ LOG_D(<component>,<format>,<argument>,...)
LOG_T(<component>,<format>,<argument>,...)
)
```
these macros are used in place of the printf C function. The additionnal ***component*** parameter identifies the functionnal module which generates the message. At run time, the message will only be printed if the configured log level for the component is greater or equal than the macro level used in the code.
these macros are used in place of the printf C function. The additionnal ***component*** parameter identifies the functional module which generates the message. At run time, the message will only be printed if the configured log level for the component is greater or equal than the macro level used in the code.
| macro | level letter | level value | level name |
|:---------|:---------------|:---------------|----------------:|

View File

@@ -155,6 +155,7 @@ static const char *const flag_name[] = {FOREACH_FLAG(FLAG_TEXT) ""};
COMP_DEF(NFAPI_PNF, log) \
COMP_DEF(ITTI, log) \
COMP_DEF(UTIL, log) \
COMP_DEF(E3AP, log) \
COMP_DEF(MAX_LOG_PREDEF_COMPONENTS, )
#define COMP_ENUM(comp, file_extension) comp,

View File

@@ -159,6 +159,10 @@ ID = GNB_PHY_UL_SRS_TOA_NS
DESC = gNB ToA estimate from SRS (in ns)
GROUP = ALL:PHY:GNB
FORMAT = int,gNB_ID : int,rnti : int,frame : int,subframe : buffer,toa_ns
ID = GNB_PHY_UL_FREQ_SENSING_SYMBOL
DESC = gNodeB output data in the freq domain for sensing symbols
GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
FORMAT = int,gNB_ID : int,frame : int,slot : int,antenna : buffer,rxdata
#MAC logs
ID = ENB_MAC_UE_DL_SDU
@@ -426,6 +430,27 @@ ID = LEGACY_MAC_TRACE
GROUP = ALL:LEGACY_MAC:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_E3AP_INFO
DESC = E3AP legacy logs - info level
GROUP = ALL:LEGACY_E3AP:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_E3AP_ERROR
DESC = E3AP legacy logs - error level
GROUP = ALL:LEGACY_E3AP:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
ID = LEGACY_E3AP_WARNING
DESC = E3AP legacy logs - warning level
GROUP = ALL:LEGACY_E3AP:LEGACY_GROUP_WARNING:LEGACY
FORMAT = string,log
ID = LEGACY_E3AP_DEBUG
DESC = E3AP legacy logs - debug level
GROUP = ALL:LEGACY_E3AP:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_E3AP_TRACE
DESC = E3AP legacy logs - trace level
GROUP = ALL:LEGACY_E3AP:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_NR_MAC_INFO
DESC = NR_MAC legacy logs - info level
GROUP = ALL:LEGACY_NR_MAC:LEGACY_GROUP_INFO:LEGACY
@@ -1454,7 +1479,7 @@ ID = UE_PHY_PDCCH_ENERGY
ID = UE_PHY_PDSCH_IQ
DESC = UE PDSCH received IQ data
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_DL : int,symbols_per_tti : buffer,pdsch_comp
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pdsch_comp
ID = UE_PHY_PDSCH_ENERGY
DESC = UE PDSCH 1 energy and threshold
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE

View File

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

View File

@@ -12,6 +12,8 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <math.h>
#include <sys/un.h>
#include <sys/stat.h>
void new_thread(void *(*f)(void *), void *data) {
pthread_t t;
@@ -233,6 +235,117 @@ again:
return s;
}
/****************************************************************************/
/* unix domain socket */
/****************************************************************************/
int try_connect_to_uds(char *path)
{
int s;
struct sockaddr_un a;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1) {
perror("socket");
exit(1);
}
memset(&a, 0, sizeof(struct sockaddr_un));
a.sun_family = AF_UNIX;
strncpy(a.sun_path, path, sizeof(a.sun_path) - 1);
if (connect(s, (struct sockaddr *)&a, sizeof(a)) == -1) {
perror("connect");
close(s);
return -1;
}
return s;
}
int connect_to_uds(char *path)
{
int s;
printf("connecting to %s\n", path);
again:
s = try_connect_to_uds(path);
if (s == -1) {
perror("trying again in 1s\n");
sleep(1);
goto again;
}
return s;
}
int create_listen_uds_socket(char *path)
{
struct sockaddr_un a;
int s;
int v;
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s == -1) {
perror("socket");
exit(1);
}
v = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(int))) {
perror("setsockopt");
exit(1);
}
// Bind the socket to a file path
memset(&a, 0, sizeof(struct sockaddr_un));
a.sun_family = AF_UNIX;
strncpy(a.sun_path, path, sizeof(a.sun_path) - 1);
// Remove any existing socket file
unlink(path);
if (bind(s, (struct sockaddr *)&a, sizeof(a)) == -1) {
perror("Bind failed");
close(s);
exit(1);
}
// Set permissions to 770 (rwxrwx---) to make sure groups can access
if (chmod(path, 0770) == -1) {
perror("Failed to change permissions");
close(s);
exit(1);
}
// Listen for incoming connections
if (listen(s, 5) == -1) {
perror("Listen failed");
close(s);
exit(1);
}
return s;
}
int get_uds_connection(char *path)
{
int s, t;
printf("waiting for connection on %s\n", path);
s = create_listen_uds_socket(path);
t = socket_accept(s);
if (t == -1) {
perror("accept");
exit(1);
}
close(s);
printf("connected\n");
return t;
}
/****************************************************************************/
/* buffer */
/****************************************************************************/

View File

@@ -8,7 +8,7 @@
#include "spsc_q.h"
bool spsc_q_alloc(spsc_q_t *rbn, size_t cnt, size_t elsiz)
spsc_q_t spsc_q_alloc(size_t cnt, size_t elsiz)
{
/* internally, use one element more: the ringbuffer is full if
* (write_idx + 1) % cnt == read_idx, so it's full if one element is still
@@ -17,8 +17,7 @@ bool spsc_q_alloc(spsc_q_t *rbn, size_t cnt, size_t elsiz)
cnt += 1;
spsc_q_t rb = {.cnt = cnt, .elsiz = elsiz};
rb.buf = calloc(cnt, elsiz);
*rbn = rb;
return rb.buf != NULL;
return rb;
}
void spsc_q_free(spsc_q_t *rb)

View File

@@ -25,7 +25,7 @@ typedef struct spsc_q {
atomic_size_t read_idx;
} spsc_q_t;
bool spsc_q_alloc(spsc_q_t *rbn, size_t cnt, size_t elsiz);
spsc_q_t spsc_q_alloc(size_t cnt, size_t elsiz);
void spsc_q_free(spsc_q_t *rb);
bool spsc_q_put(spsc_q_t *rb, const void *src, size_t elsiz);

View File

@@ -8,8 +8,7 @@ extern "C" {
}
TEST(spsc_q, basic_test) {
spsc_q_t rb;
EXPECT_TRUE(spsc_q_alloc(&rb, 2, sizeof(int)));
spsc_q_t rb = spsc_q_alloc(2, sizeof(int));
int a = 1;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
@@ -27,8 +26,7 @@ TEST(spsc_q, basic_test) {
}
TEST(spsc_q, cont_write) {
spsc_q_t rb;
EXPECT_TRUE(spsc_q_alloc(&rb, 10, sizeof(int)));
spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
int a = 1;
for (int i = 0; i < 1111; ++i) {
@@ -59,8 +57,7 @@ bool count(const void *data, void *user)
return true; /* count all */
}
TEST(spsc_q, iterator) {
spsc_q_t rb;
EXPECT_TRUE(spsc_q_alloc(&rb, 10, sizeof(int)));
spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
int n = 8;
for (int i = 0; i < n; ++i)
EXPECT_TRUE(spsc_q_put(&rb, &i, sizeof(i)));
@@ -88,8 +85,7 @@ bool drop(const void *data, void *user)
return true; /* drop all */
}
TEST(spsc_q, drop) {
spsc_q_t rb;
EXPECT_TRUE(spsc_q_alloc(&rb, 10, sizeof(int)));
spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
int n = 8;
for (int i = 0; i < n; ++i)
EXPECT_TRUE(spsc_q_put(&rb, &i, sizeof(i)));
@@ -108,8 +104,7 @@ TEST(spsc_q, drop) {
TEST(spsc_q, full) {
int n = 3;
spsc_q_t rb;
EXPECT_TRUE(spsc_q_alloc(&rb, n, sizeof(int)));
spsc_q_t rb = spsc_q_alloc(n, sizeof(int));
int a = 1;
EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
a++;

View File

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

View File

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

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