mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Compare commits
180 Commits
nr_gnb_uci
...
4aeee8fbc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4aeee8fbc1 | ||
|
|
c4125d1c74 | ||
|
|
09c9bb998f | ||
|
|
6d4573905a | ||
|
|
dc01a3540a | ||
|
|
c3f6af1008 | ||
|
|
633b6de92a | ||
|
|
ad5e941bc9 | ||
|
|
75d7fa275d | ||
|
|
829d6fe7cf | ||
|
|
db7dbda8e2 | ||
|
|
f448088c8d | ||
|
|
a3268a9c2f | ||
|
|
716c29fe1f | ||
|
|
3cbf777835 | ||
|
|
813a90bd21 | ||
|
|
0548191fac | ||
|
|
145ab730c0 | ||
|
|
5f2108edb0 | ||
|
|
b7ab31854e | ||
|
|
f7d0ec0960 | ||
|
|
7032477784 | ||
|
|
7e0c0fe18b | ||
|
|
5a478deac4 | ||
|
|
40024d4caa | ||
|
|
3fb74dc66e | ||
|
|
82c3c04018 | ||
|
|
df5a9facbe | ||
|
|
71c692d727 | ||
|
|
159c219bdd | ||
|
|
ecfe769205 | ||
|
|
21329e1b70 | ||
|
|
0aa3f89c52 | ||
|
|
cd79eec3ec | ||
|
|
a1049e8dd1 | ||
|
|
28786af8bf | ||
|
|
eb1ae91051 | ||
|
|
31eb466a7d | ||
|
|
bbd8b295cf | ||
|
|
2d57ec1987 | ||
|
|
26553423ac | ||
|
|
0f50702483 | ||
|
|
7a0489842b | ||
|
|
a211c0ef5a | ||
|
|
9fd43efaf2 | ||
|
|
037c5dae31 | ||
|
|
47e9ad9cbd | ||
|
|
d776779509 | ||
|
|
3516ed3b5e | ||
|
|
4e92eabc18 | ||
|
|
c0f6e70259 | ||
|
|
3205c9a367 | ||
|
|
90c85e8b9c | ||
|
|
a3b077a30f | ||
|
|
b04fa5f7ae | ||
|
|
8542b813e1 | ||
|
|
89d578e7bb | ||
|
|
78b92485ee | ||
|
|
84bbe66c07 | ||
|
|
d8744c52f2 | ||
|
|
5d309b93d1 | ||
|
|
294599d327 | ||
|
|
ddccd57e5c | ||
|
|
6cb51988b1 | ||
|
|
8d2895463b | ||
|
|
f51e47b1c2 | ||
|
|
7b93b83fd4 | ||
|
|
0d118c9821 | ||
|
|
b31846c62f | ||
|
|
e7f12fdd61 | ||
|
|
7cf0e252b3 | ||
|
|
10ff25e530 | ||
|
|
a52883c051 | ||
|
|
4b767c3ab1 | ||
|
|
8cd7dc4f04 | ||
|
|
2241af180f | ||
|
|
37cef0e2cb | ||
|
|
ff2e6f8425 | ||
|
|
d8c1f68da4 | ||
|
|
9651a571d9 | ||
|
|
4ed41739c0 | ||
|
|
659d184265 | ||
|
|
d3688ce345 | ||
|
|
74f661f3d6 | ||
|
|
5e37598e02 | ||
|
|
e5c95a2d7e | ||
|
|
c9e82d6a12 | ||
|
|
bae10b8831 | ||
|
|
21b901aefc | ||
|
|
6cba089c34 | ||
|
|
dc32077fe9 | ||
|
|
ec24751adb | ||
|
|
fff0ced519 | ||
|
|
8aa2f1b965 | ||
|
|
6dac6fed13 | ||
|
|
f3589d97c2 | ||
|
|
05a2fdf095 | ||
|
|
945fe9a756 | ||
|
|
443f580153 | ||
|
|
43fc8c084c | ||
|
|
4b32f4d161 | ||
|
|
f19b44639d | ||
|
|
48806d032a | ||
|
|
d75e99af63 | ||
|
|
b9fc7cc5d2 | ||
|
|
f1e5d1fb4f | ||
|
|
885e5e8895 | ||
|
|
11b8ba54ea | ||
|
|
8eeb1b125f | ||
|
|
ad44ee75f6 | ||
|
|
1360217cae | ||
|
|
b7cba9d266 | ||
|
|
ad12c4f9a8 | ||
|
|
31084d6698 | ||
|
|
0bcc3b3229 | ||
|
|
8b04c038f1 | ||
|
|
9163c8b2bd | ||
|
|
5fae4b3c29 | ||
|
|
29d31cde8e | ||
|
|
dfb0c61c62 | ||
|
|
854090632f | ||
|
|
a1162f9fd3 | ||
|
|
096a107704 | ||
|
|
63af7fcfb8 | ||
|
|
911f069709 | ||
|
|
2c7530e0bf | ||
|
|
4b79c55ce6 | ||
|
|
2ff86cfb27 | ||
|
|
0a0de88ff8 | ||
|
|
fa237ffab4 | ||
|
|
8c255558f0 | ||
|
|
460cbf954d | ||
|
|
80451a917f | ||
|
|
d2bbf09121 | ||
|
|
039b008676 | ||
|
|
1b77adcb10 | ||
|
|
7db4dfec73 | ||
|
|
e2676b5159 | ||
|
|
ce4a9da3ca | ||
|
|
79171c19af | ||
|
|
0a9d817d9c | ||
|
|
33e09d7e3e | ||
|
|
d6e9492b6f | ||
|
|
29be39948c | ||
|
|
d4d494d0d3 | ||
|
|
62846a9311 | ||
|
|
db5c84e864 | ||
|
|
acab173950 | ||
|
|
19a8a0d1d4 | ||
|
|
8e30ec8031 | ||
|
|
ba9b9b217a | ||
|
|
416248f951 | ||
|
|
1c850b622d | ||
|
|
de00110649 | ||
|
|
4ed6de5dd5 | ||
|
|
867cb7f7d0 | ||
|
|
f8ecc3befa | ||
|
|
01fb12cfbd | ||
|
|
55e0693beb | ||
|
|
b4c9f67b30 | ||
|
|
ef35085329 | ||
|
|
165ceb983b | ||
|
|
438de535fa | ||
|
|
00e7cd49fa | ||
|
|
568898e80a | ||
|
|
f8ebed5cad | ||
|
|
1bf3fd674e | ||
|
|
ce6a54ab94 | ||
|
|
18efff1ca4 | ||
|
|
053365ad77 | ||
|
|
98d829e535 | ||
|
|
26956bf8e1 | ||
|
|
3a8e3b9408 | ||
|
|
c9461ac4d4 | ||
|
|
d95d911e96 | ||
|
|
97ac8a5cd1 | ||
|
|
778fb90f44 | ||
|
|
80735e2b39 | ||
|
|
ed53bd8f95 | ||
|
|
ea35109ba2 |
112
.github/workflows/jenkins-dispatch.yml
vendored
Normal file
112
.github/workflows/jenkins-dispatch.yml
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
name: Duranta Jenkins Dispatch
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
branches: [develop]
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name }}-${{ github.event.action }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
if: |
|
||||
github.event.action != 'labeled' ||
|
||||
github.event.label.name == vars.RETRIGGER_CI_LABEL
|
||||
|
||||
outputs:
|
||||
protected_files_changed: ${{ steps.filter.outputs.protected }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check changed files
|
||||
uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
protected:
|
||||
- 'ci-scripts/**'
|
||||
- '.github/workflows/**'
|
||||
- '.github/actions/**'
|
||||
- 'docker/**'
|
||||
- 'charts/**'
|
||||
- 'openshift/**'
|
||||
- 'cmake_targets/build_oai'
|
||||
- 'cmake_targets/tools/build_helper'
|
||||
|
||||
require-maintainer-approval:
|
||||
needs: detect-changes
|
||||
|
||||
if: needs.detect-changes.outputs.protected_files_changed == 'true'
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
environment:
|
||||
name: ci-approval
|
||||
|
||||
steps:
|
||||
- run: echo "Maintainer has approved the changes"
|
||||
|
||||
trigger-jenkins:
|
||||
needs:
|
||||
- detect-changes
|
||||
- require-maintainer-approval
|
||||
|
||||
if: |
|
||||
always() &&
|
||||
(
|
||||
needs.detect-changes.outputs.protected_files_changed == 'false' ||
|
||||
needs.require-maintainer-approval.result == 'success'
|
||||
)
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.ref }}
|
||||
|
||||
- name: Trigger Jenkins
|
||||
run: |
|
||||
# Write payload to a temp file to avoid shell escaping issues
|
||||
cat << 'EOF' > /tmp/payload.json
|
||||
${{ toJson(github.event) }}
|
||||
EOF
|
||||
|
||||
# Filter and send
|
||||
jq -c 'del(.pull_request.body)' /tmp/payload.json > /tmp/filtered_payload.json
|
||||
|
||||
# Remap pull_request_target -> pull_request for Jenkins compatibility
|
||||
EVENT_NAME="${{ github.event_name }}"
|
||||
if [ "$EVENT_NAME" = "pull_request_target" ]; then
|
||||
EVENT_NAME="pull_request"
|
||||
fi
|
||||
|
||||
curl -X POST "https://${{ secrets.J_USER }}:${{ secrets.J_PASS }}@${{ secrets.J_URL }}" \
|
||||
-H "Accept: */*" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "User-Agent: GitHub-Hookshot/${{ secrets.H_AGENT }}" \
|
||||
-H "X-Github-Delivery: ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "X-Github-Event: $EVENT_NAME" \
|
||||
-H "X-Github-Hook-Id: ${{ secrets.H_ID }}" \
|
||||
-H "X-Github-Hook-Installation-Target-Id: ${{ secrets.H_TARGET }}" \
|
||||
-H "X-Github-Hook-Installation-Target-Type: repository" \
|
||||
--data @/tmp/filtered_payload.json
|
||||
|
||||
- name: Remove retrigger-ci label
|
||||
if: always() && github.event.action == 'labeled' && github.event.label.name == vars.RETRIGGER_CI_LABEL
|
||||
run: gh pr edit ${{ github.event.pull_request.number }} --remove-label "${{ vars.RETRIGGER_CI_LABEL }}"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -2,7 +2,7 @@
|
||||
|
||||
# RELEASE NOTES: #
|
||||
|
||||
## [v2.4.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.4.0) -> December 2025. ##
|
||||
## [v2.4.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v2.4.0) -> December 2025. ##
|
||||
|
||||
General new features and improvements (both RAN and UE):
|
||||
- Rework LDPC BBdev/AAL interface and support both AMD T2/Intel vRAN Boost
|
||||
@@ -68,7 +68,7 @@ Configuration file changes:
|
||||
should be removed
|
||||
- `MACRLCs.[0].stats_max_ue` has been added
|
||||
|
||||
## [v2.3.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.3.0) -> July 2025. ##
|
||||
## [v2.3.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v2.3.0) -> July 2025. ##
|
||||
|
||||
General new features and improvements (both RAN and UE):
|
||||
- Preliminary support for RedCap UEs
|
||||
@@ -114,7 +114,7 @@ nrUE changes:
|
||||
Regression:
|
||||
- Multiple BWPs do not work reliably on gNB; use tag 2025.w17
|
||||
|
||||
## [v2.2.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.2.0) -> November 2024. ##
|
||||
## [v2.2.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v2.2.0) -> November 2024. ##
|
||||
|
||||
General 5G improvements (both gNB and UE):
|
||||
- Make standalone mode (SA) the default (see [`RUNMODEM.md`](doc/RUNMODEM.md))
|
||||
@@ -170,7 +170,7 @@ General 5G improvements (both gNB and UE):
|
||||
This release also includes many fixes and documentation updates. See
|
||||
`doc/README.md` in the repository for an overview of documentation.
|
||||
|
||||
## [v2.1.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.1.0) -> February 2024. ##
|
||||
## [v2.1.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v2.1.0) -> February 2024. ##
|
||||
|
||||
This release improves existing 5G support and adds various new features.
|
||||
|
||||
@@ -197,7 +197,7 @@ interoperability is under testing.
|
||||
|
||||
This release also includes many fixes and documentation updates.
|
||||
|
||||
## [v2.0.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.0.0) -> August 2023. ##
|
||||
## [v2.0.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v2.0.0) -> August 2023. ##
|
||||
|
||||
This release adds support for 5G and maintains previous features:
|
||||
* 5G SA in gNB
|
||||
@@ -226,11 +226,11 @@ This release adds support for 5G and maintains previous features:
|
||||
|
||||
For more information on supported features, please refer to the [feature set](doc/FEATURE_SET.md).
|
||||
|
||||
## [v1.2.1](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.2.1) -> February 2020. ##
|
||||
## [v1.2.1](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.2.1) -> February 2020. ##
|
||||
|
||||
* Bug fix for mutex lock for wake-up signal
|
||||
|
||||
## [v1.2.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.2.0) -> January 2020. ##
|
||||
## [v1.2.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.2.0) -> January 2020. ##
|
||||
|
||||
This version adds the following implemented features:
|
||||
|
||||
@@ -246,11 +246,11 @@ This version also has an improved code quality:
|
||||
* Better Test Coverage in Continuous Integration:
|
||||
- Initial framework to do long-run testing at R2LAB
|
||||
|
||||
## [v1.1.1](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.1.1) -> November 2019. ##
|
||||
## [v1.1.1](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.1.1) -> November 2019. ##
|
||||
|
||||
- Bug fix in the TDD Fair Round-Robin scheduler
|
||||
|
||||
## [v1.1.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.1.0) -> July 2019. ##
|
||||
## [v1.1.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.1.0) -> July 2019. ##
|
||||
|
||||
This version adds the following implemented features:
|
||||
|
||||
@@ -282,19 +282,19 @@ This version has an improved code quality:
|
||||
- Multi-RRU TDD mode
|
||||
- X2 Handover in FDD mode
|
||||
|
||||
## [v1.0.3](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.0.3) -> June 2019. ##
|
||||
## [v1.0.3](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.0.3) -> June 2019. ##
|
||||
|
||||
- Bug fix for LimeSuite v19.04.0 API
|
||||
|
||||
## [v1.0.2](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.0.2) -> February 2019. ##
|
||||
## [v1.0.2](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.0.2) -> February 2019. ##
|
||||
|
||||
- Full OAI support for 3.13.1 UHD
|
||||
|
||||
## [v1.0.1](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.0.1) -> February 2019. ##
|
||||
## [v1.0.1](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.0.1) -> February 2019. ##
|
||||
|
||||
- Bug fix for the UE L1 simulator.
|
||||
|
||||
## [v1.0.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.0.0) -> January 2019. ##
|
||||
## [v1.0.0](https://github.com/duranta-project/openairinterface5g/releases/tag/v1.0.0) -> January 2019. ##
|
||||
|
||||
This version first implements the architectural split described in the following picture.
|
||||
|
||||
|
||||
@@ -855,7 +855,6 @@ set(NR_PHY_SRC_RU
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/nr_beamforming.c
|
||||
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c
|
||||
${OPENAIR1_DIR}/PHY/INIT/nr_init_ru.c
|
||||
${OPENAIR1_DIR}/PHY/if4_tools.c
|
||||
)
|
||||
|
||||
set(PHY_SRC_UE
|
||||
@@ -924,7 +923,6 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
|
||||
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c
|
||||
@@ -1207,6 +1205,7 @@ set (MAC_NR_SRC
|
||||
${NR_GNB_MAC_DIR}/gNB_scheduler_uci.c
|
||||
${NR_GNB_MAC_DIR}/gNB_scheduler_srs.c
|
||||
${NR_GNB_MAC_DIR}/gNB_scheduler_RA.c
|
||||
${NR_GNB_MAC_DIR}/gNB_scheduler_pcch.c
|
||||
${NR_GNB_MAC_DIR}/mac_rrc_dl_handler.c
|
||||
${NR_GNB_MAC_DIR}/mac_rrc_ul_direct.c
|
||||
${NR_GNB_MAC_DIR}/mac_rrc_ul_f1ap.c
|
||||
@@ -1769,23 +1768,25 @@ target_link_libraries(lte-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs
|
||||
# force the generation of ASN.1 so that we don't need to wait during the build
|
||||
target_link_libraries(lte-uesoftmodem PRIVATE
|
||||
asn1_lte_rrc asn1_s1ap asn1_m2ap asn1_m3ap asn1_x2ap)
|
||||
# nr RRU
|
||||
add_executable(nr-oru
|
||||
${OPENAIR_DIR}/executables/nr-ru.c
|
||||
${OPENAIR_DIR}/openair1/PHY/INIT/nr_parms.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/phy_frame_config_nr.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/nr_prach_procedures.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/nr_ru_procedures.c
|
||||
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
|
||||
${OPENAIR_DIR}/executables/main_nr_ru.c
|
||||
)
|
||||
target_link_libraries(nr-oru PRIVATE
|
||||
UTIL NR_PHY_RU PHY_NR shlib_loader dl
|
||||
radio_common softmodem_common nfapi_pnf_lib)
|
||||
target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
|
||||
barrier actor nfapi_user_lib)
|
||||
target_link_libraries(nr-oru PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_phy_common time_management)
|
||||
|
||||
if (OAI_RU_FRONTHAUL)
|
||||
add_executable(nr-oru
|
||||
${OPENAIR_DIR}/executables/nr-ru.c
|
||||
${OPENAIR_DIR}/openair1/PHY/INIT/nr_parms.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/phy_frame_config_nr.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/nr_prach_procedures.c
|
||||
${OPENAIR_DIR}/openair1/SCHED_NR/nr_ru_procedures.c
|
||||
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
|
||||
${OPENAIR_DIR}/executables/main_nr_ru.c
|
||||
${OPENAIR_DIR}/executables/nr-oru.c
|
||||
)
|
||||
target_link_libraries(nr-oru PRIVATE
|
||||
UTIL NR_PHY_RU PHY_NR shlib_loader dl oru_fh MAC_NR_COMMON
|
||||
radio_common softmodem_common nfapi_pnf_lib)
|
||||
target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
|
||||
barrier actor nfapi_user_lib)
|
||||
target_link_libraries(nr-oru PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_phy_common time_management)
|
||||
endif()
|
||||
# nr-softmodem
|
||||
###################################################
|
||||
|
||||
|
||||
@@ -4,26 +4,16 @@
|
||||
|
||||
We want to make contributing to this project as easy and transparent as possible.
|
||||
|
||||
Please refer to the steps described on our website: [How to contribute to OAI](https://www.openairinterface.org/?page_id=112).
|
||||
|
||||
1. Sign and return a Contributor License Agreement to OAI team.
|
||||
2. Register on [Eurecom GitLab Server](https://gitlab.eurecom.fr/users/sign_up)
|
||||
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).
|
||||
- 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
|
||||
rights on this repository.
|
||||
4. The contributing policies are described in the [corresponding documentation
|
||||
1. Create an account on [GitHub](https://github.com/). Only contributions
|
||||
against [`duranta-project/openairinterface5g/`](https://github.com/duranta-project/openairinterface5g/)
|
||||
are accepted.
|
||||
2. Fork the repository, and open pull requests for your contributions from your
|
||||
fork.
|
||||
3. The contributing policies are described in the [corresponding documentation
|
||||
page](doc/code-style-contrib.md).
|
||||
- PLEASE DO NOT FORK the OAI repository on your own Eurecom GitLab account.
|
||||
It just eats up space on our servers.
|
||||
- You can fork onto another hosting system. But we will NOT accept a merge
|
||||
request from a forked repository.
|
||||
* This decision was made for the license reasons.
|
||||
* The Continuous Integration will reject your merge request.
|
||||
4. [Sign the CLA](https://github.com/duranta-project/governance/blob/main/docs/easy_cla_process.md)
|
||||
either before doing making your first pull request or after submitting the
|
||||
pull request.
|
||||
5. Mandatory signing of all the commits using the email address used for CLA.
|
||||
|
||||
## Commit Guidelines
|
||||
@@ -32,8 +22,8 @@ Please refer to the steps described on our website: [How to contribute to OAI](h
|
||||
|
||||
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/)
|
||||
You can also get the verified label on your commits via using [SSH keys or GPG
|
||||
keys](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)
|
||||
|
||||
```
|
||||
# Edit .git/config in the git repository you are working on
|
||||
@@ -55,7 +45,7 @@ on your commits via using [SSH KEYS or GPG KEYS](https://docs.gitlab.com/user/pr
|
||||
gpgsign = true
|
||||
```
|
||||
|
||||
> **NOTE:** If your commits are not signed the CI framework will not accept the MR.
|
||||
> **NOTE:** If your commits are not signed the CI framework will not accept the PR.
|
||||
|
||||
For more information regarding contribution guidelines
|
||||
please check [this document](doc/code-style-contrib.md)
|
||||
|
||||
37
README.md
37
README.md
@@ -1,25 +1,21 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
<h1 align="center">
|
||||
<a href="https://openairinterface.org/"><img src="https://openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png" alt="OAI" width="550"></a>
|
||||
<a href="https://lfnetworking.org/projects/duranta/"><img src="https://raw.githubusercontent.com/duranta-project/governance/main/logos/Duranta-Logo-Color.png" alt="Duranta OAI" width="550"></a>
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-CSSL--v1.0-blue" alt="License"></a>
|
||||
<a href="https://github.com/duranta-project/openairinterface5g/blob/develop/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-Fedora44-Green" alt="Supported OS Fedora 44"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/releases"><img alt="GitLab Release (custom instance)" src="https://img.shields.io/gitlab/v/release/oai/openairinterface5g?gitlab_url=https%3A%2F%2Fgitlab.eurecom.fr&include_prereleases&sort=semver"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-Ubuntu18-Image-Builder%2F&label=build-Ubuntu-x86%20Images"></a>
|
||||
<a href="https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Cluster-Image-Builder/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-RHEL8-Cluster-Image-Builder%2F&label=build-UBI-x86%20Images"></a>
|
||||
<a href="https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-Image-Builder/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-Ubuntu-Image-Builder%2F&label=build-Ubuntu-x86%20Images"></a>
|
||||
<a href="https://jenkins-oai.eurecom.fr/job/RAN-RHEL-Cluster-Image-Builder/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-RHEL-Cluster-Image-Builder%2F&label=build-RHEL-Cluster%20Images"></a>
|
||||
<a href="https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-ARM-Image-Builder/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-Ubuntu-ARM-Image-Builder%2F&label=build-Ubuntu-ARM%20Images"></a>
|
||||
</p>
|
||||
|
||||
@@ -31,14 +27,23 @@
|
||||
<a href="https://hub.docker.com/r/oaisoftwarealliance/oai-nr-cuup"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-nr-cuup?label=NR-CUUP%20docker%20pulls"></a>
|
||||
</p>
|
||||
|
||||
# OpenAirInterface License #
|
||||
# Duranta - OpenAirInterface
|
||||
|
||||
Duranta OpenAirInterface RAN delivers and maintains an open-source cellular
|
||||
wireless software stack for 4G, 5G and future networking technologies. It
|
||||
supports simulation, prototyping, and end-to-end deployments on
|
||||
Commercial-Off-The-Shelf (COTS) hardware. Built for research and
|
||||
experimentation, it provides standard-compliant interfaces and is released
|
||||
under the Collaborative Standards Software License (CSSL).
|
||||
|
||||
## License
|
||||
|
||||
* [OAI License Model](http://www.openairinterface.org/?page_id=101)
|
||||
* [CSSL v1.0](http://www.openairinterface.org/?page_id=698)
|
||||
|
||||
The source code is distributed under [**CSSL v1.0**](LICENSE).
|
||||
Some files, such as for orchestration, are distributed under
|
||||
[MIT license](preferred)(MIT.txt). Documentation is distributed under
|
||||
[MIT license](./LICENSES/preferred/MIT.txt). Documentation is distributed under
|
||||
[Creative Commons Attribution 4.0 International license](LICENSES/preferred/CC-BY-4.0.txt).
|
||||
|
||||
All the files without an explicit copyright header have an implicit "Copyright
|
||||
@@ -54,7 +59,7 @@ history:
|
||||
3. OAI Public License v1.0: starting tag v.04 till v1.0
|
||||
4. GPL 3: starting tag v.0 till v.04 (only initial implementation of 4G)
|
||||
|
||||
# Where to Start #
|
||||
## Where to Start
|
||||
|
||||
* [General overview of documentation](./doc/README.md)
|
||||
* [The implemented features](./doc/FEATURE_SET.md)
|
||||
@@ -70,7 +75,7 @@ To find all READMEs, this command might be handy:
|
||||
find . -iname "readme*"
|
||||
```
|
||||
|
||||
# RAN repository structure #
|
||||
## RAN repository structure
|
||||
|
||||
The OpenAirInterface (OAI) software is composed of the following parts:
|
||||
|
||||
@@ -95,9 +100,9 @@ openairinterface5g
|
||||
└── tools : Tools for use by the developers/ci machines: code analysis and formatting
|
||||
```
|
||||
|
||||
# How to get support from the OAI Community #
|
||||
## How to get support from the Community
|
||||
|
||||
You can ask your question on the [mailing lists](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/MailingList).
|
||||
You can ask your question on the [mailing lists](https://github.com/duranta-project/openairinterface5g/wiki/MailingList).
|
||||
|
||||
Your email should contain below information:
|
||||
|
||||
@@ -108,6 +113,6 @@ Your email should contain below information:
|
||||
- OAI gNB/DU/CU/CU-CP/CU-UP configuration file in `.conf` format only.
|
||||
- Logs of OAI gNB/DU/CU/CU-CP/CU-UP in `.log` or `.txt` format only.
|
||||
- In case your question is related to performance, include a small description of the machine (Operating System, Kernel version, CPU, RAM and networking card) and diagram of your testing environment.
|
||||
- Known/open issues are present on [GitLab](https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues), so keep checking.
|
||||
- Known/open issues are present on [Github](https://github.com/duranta-project/openairinterface5g/issues), so keep checking.
|
||||
|
||||
Always remember a structured email will help us understand your issues quickly.
|
||||
|
||||
61
ROADMAP.md
Normal file
61
ROADMAP.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Duranta-OpenAirInterface Roadmap
|
||||
|
||||
## RAN Roadmap
|
||||
|
||||
### Q2 2026
|
||||
|
||||
- GPU LDPC Accelerator
|
||||
- NR-DC Support
|
||||
- CN Paging procedures
|
||||
- Support for 64 UEs with E2E throughput validation
|
||||
- Basic Cat-A OAI O-RU (simulated radio)
|
||||
|
||||
### Q3 2026
|
||||
|
||||
- QoS-enforcing scheduler
|
||||
- Xn Handover Support
|
||||
- UL MU-MIMO
|
||||
- Aperiodic UL channels (SRS/CSI reporting)
|
||||
- NR user plane protocol
|
||||
- Multi-cell support in L2
|
||||
- Support for 128 UEs with E2E throughput validation
|
||||
|
||||
### Q4 2026
|
||||
|
||||
- Cat-B Support for FHI 7.2 at RU/DU
|
||||
- RAN Paging
|
||||
- Support of 5G RAN Slicing
|
||||
- Multi-cell performance evaluation (with at-least 3 cells)
|
||||
|
||||
### Q1 2027
|
||||
|
||||
- Digital Beamforming Support
|
||||
- DL MU-MIMO at L1
|
||||
|
||||
---
|
||||
|
||||
## UE Roadmap
|
||||
|
||||
### Q2 2026
|
||||
|
||||
- Support for Handover Procedures
|
||||
- Basic Sidelink Procedures (PSSCH, PSCCH)
|
||||
- PUCCH formats 1&3
|
||||
|
||||
### Q3 2026
|
||||
|
||||
- Support for 2 UL layers
|
||||
- Support for 2 DL layers
|
||||
- RU sharing
|
||||
|
||||
### Q4 2026
|
||||
|
||||
- Reduce feedback time
|
||||
- AT command interface
|
||||
- DL KPI Improvements
|
||||
- UL KPI Improvements
|
||||
|
||||
### Q1 2027
|
||||
|
||||
- Scan carrier
|
||||
- Power control procedures for outdoor operation
|
||||
@@ -14,7 +14,7 @@ description: A Helm chart for physical simulators network function
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png
|
||||
icon: https://raw.githubusercontent.com/duranta-project/governance/main/logos/Duranta-Logo-Color.png
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
@@ -31,8 +31,8 @@ keywords:
|
||||
- 5G
|
||||
|
||||
sources:
|
||||
- https://gitlab.eurecom.fr/oai/openairinterface5g
|
||||
- https://github.com/duranta-project/openairinterface5g
|
||||
|
||||
maintainers:
|
||||
- name: OPENAIRINTERFACE
|
||||
email: contact@openairinterface.org
|
||||
email: oaicicdteam@openairinterface.org
|
||||
|
||||
@@ -14,7 +14,7 @@ description: A Helm subchart for 4G physims network function
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png
|
||||
icon: https://raw.githubusercontent.com/duranta-project/governance/main/logos/Duranta-Logo-Color.png
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
@@ -30,8 +30,8 @@ keywords:
|
||||
- 4G
|
||||
|
||||
sources:
|
||||
- https://gitlab.eurecom.fr/oai/openairinterface5g
|
||||
- https://github.com/duranta-project/openairinterface5g
|
||||
|
||||
maintainers:
|
||||
- name: OPENAIRINTERFACE
|
||||
email: contact@openairinterface.org
|
||||
email: oaicicdteam@openairinterface.org
|
||||
|
||||
@@ -14,7 +14,7 @@ description: A Helm chart for physical simulators network function
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png
|
||||
icon: https://raw.githubusercontent.com/duranta-project/governance/main/logos/Duranta-Logo-Color.png
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
@@ -31,8 +31,8 @@ keywords:
|
||||
- 5G
|
||||
|
||||
sources:
|
||||
- https://gitlab.eurecom.fr/oai/openairinterface5g
|
||||
- https://github.com/duranta-project/openairinterface5g
|
||||
|
||||
maintainers:
|
||||
- name: OPENAIRINTERFACE
|
||||
email: contact@openairinterface.org
|
||||
email: oaicicdteam@openairinterface.org
|
||||
|
||||
@@ -14,7 +14,7 @@ description: A Helm subchart for 5G physims network function
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png
|
||||
icon: https://raw.githubusercontent.com/duranta-project/governance/main/logos/Duranta-Logo-Color.png
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
@@ -30,8 +30,8 @@ keywords:
|
||||
- 5G
|
||||
|
||||
sources:
|
||||
- https://gitlab.eurecom.fr/oai/openairinterface5g
|
||||
- https://github.com/duranta-project/openairinterface5g
|
||||
|
||||
maintainers:
|
||||
- name: OPENAIRINTERFACE
|
||||
email: contact@openairinterface.org
|
||||
email: oaicicdteam@openairinterface.org
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field def branch = ''
|
||||
@Field def gitLocalBranch = ''
|
||||
@Field def downstreamResults = [:]
|
||||
|
||||
// Location of the executor node
|
||||
def nodeExecutor = params.nodeExecutor
|
||||
|
||||
@@ -12,13 +18,44 @@ def do4Gtest = false
|
||||
def do5Gtest = false
|
||||
def do5GUeTest = false
|
||||
|
||||
//
|
||||
def gitCommitAuthorEmailAddr
|
||||
|
||||
// list of failing stages
|
||||
def failingStages = ""
|
||||
def mrValidationWarning = ""
|
||||
|
||||
OAI_Registry = "gracehopper3-oai.sboai.cs.eurecom.fr"
|
||||
// Globally scoped status result variables for downstream jobs.
|
||||
def ubuntuBuildStatus = ''
|
||||
def ubuntuArmBuildStatus = ''
|
||||
def ubuntuJetsonBuildStatus = ''
|
||||
def rhelBuildStatus = ''
|
||||
def armBuildStatus = ''
|
||||
|
||||
def physim5GStatus = ''
|
||||
def physimGH5GStatus = ''
|
||||
def channelSimStatus = ''
|
||||
def vrtSim5GStatus = ''
|
||||
def rfSim5GStatus = ''
|
||||
def flexricRAN5GStatus = ''
|
||||
|
||||
def physim4GStatus = ''
|
||||
def rfSim4GStatus = ''
|
||||
def l2Sim4GStatus = ''
|
||||
def lteTDDB200Status = ''
|
||||
def lteFDDB200OAIUEStatus = ''
|
||||
def lteFDDB200Status = ''
|
||||
def lteTDD2x2N3xxStatus = ''
|
||||
|
||||
def nsaTDDB200Status = ''
|
||||
def saTDDB200Status = ''
|
||||
def phytestLDPCoffloadStatus = ''
|
||||
def saAW2SStatus = ''
|
||||
def cn5gCOTSUESanityCheck = ''
|
||||
def saAERIALStatus = ''
|
||||
def saMultiAntennaStatus = ''
|
||||
def saFHI72Status = ''
|
||||
def saFHI72MplaneStatus = ''
|
||||
def saHandoverStatus = ''
|
||||
def saAERIALOAIUEStatus = ''
|
||||
def saOAIUEStatus = ''
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
@@ -26,77 +63,100 @@ pipeline {
|
||||
}
|
||||
options {
|
||||
timestamps()
|
||||
gitLabConnection('OAI GitLab')
|
||||
ansiColor('xterm')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage ("Verify Parameters") {
|
||||
stage ("Get Parameters") {
|
||||
steps {
|
||||
script {
|
||||
echo '\u2705 \u001B[32mGet Parameters\u001B[0m'
|
||||
// GIT_BRANCH is prefixed with "origin/" by Jenkins - stripped version for use in tags and params in case of PUSH event
|
||||
gitLocalBranch = env.GIT_BRANCH.replace('origin/', '')
|
||||
if (env.GITHUB_PR_NUMBER) {
|
||||
echo "PR number : ${env.GITHUB_PR_NUMBER}"
|
||||
echo "Source Repository : ${env.GITHUB_PR_URL}"
|
||||
echo "Source Branch : ${env.GITHUB_PR_SOURCE_BRANCH}"
|
||||
echo "Commit ID : ${env.GITHUB_PR_HEAD_SHA}"
|
||||
echo "Target Repo : ${env.GIT_URL}"
|
||||
echo "Target Branch : ${env.GITHUB_PR_TARGET_BRANCH}"
|
||||
echo "Label : ${env.GITHUB_PR_LABELS}"
|
||||
branch = "${env.GITHUB_PR_SOURCE_BRANCH.replace('/', '-').replace('+', '-')}-${env.GITHUB_PR_HEAD_SHA}"
|
||||
} else {
|
||||
echo "Branch : ${gitLocalBranch}"
|
||||
echo "Commit ID : ${env.GIT_COMMIT}"
|
||||
branch = "${gitLocalBranch}-${env.GIT_COMMIT}"
|
||||
}
|
||||
env.JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim()
|
||||
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
|
||||
def allParametersPresent = true
|
||||
|
||||
echo '\u2705 \u001B[32mVerify Labels\u001B[0m'
|
||||
if ("MERGE".equals(env.gitlabActionType)) {
|
||||
LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid
|
||||
LABEL_CHECK = LABEL_CHECK.trim()
|
||||
if (LABEL_CHECK == 'NONE') {
|
||||
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request should have one of the mandatory labels:\n\n"
|
||||
message += " - ~documentation (don't perform any stages)\n"
|
||||
message += " - ~BUILD-ONLY (execute only build stages)\n"
|
||||
message += " - ~4G-LTE (perform 4G tests)\n"
|
||||
message += " - ~5G-NR (perform 5G tests)\n"
|
||||
message += " - ~CI (perform both 4G and 5G tests)\n"
|
||||
message += " - ~nrUE (perform only 5G-UE related tests including physims excluding LDPC tests)\n\n"
|
||||
message += "Not performing CI due to lack of labels"
|
||||
addGitLabMRComment comment: message
|
||||
error('Not performing CI due to lack of labels')
|
||||
} else if (LABEL_CHECK == 'FULL') {
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Verify Labels") {
|
||||
steps {
|
||||
echo '\u2705 \u001B[32mVerify Labels\u001B[0m'
|
||||
script {
|
||||
if (env.GITHUB_PR_NUMBER) {
|
||||
if (!(env.GITHUB_PR_LABELS)) {
|
||||
def gitBaseUrl = env.GIT_URL.trim().replace('.git', '')
|
||||
def message = "**CI Build:** [#${env.BUILD_NUMBER}](${BUILD_URL}) | Not performing CI due to the absence of one of the following mandatory labels:\n"
|
||||
message += "- ${gitBaseUrl}/labels/documentation (don't perform any stages)\n"
|
||||
message += "- ${gitBaseUrl}/labels/BUILD-ONLY (execute only build stages)\n"
|
||||
message += "- ${gitBaseUrl}/labels/4G-LTE (perform 4G tests)\n"
|
||||
message += "- ${gitBaseUrl}/labels/5G-NR (perform 5G tests)\n"
|
||||
message += "- ${gitBaseUrl}/labels/nrUE (perform only 5G-UE related tests including physims excluding LDPC tests)\n"
|
||||
message += "- ${gitBaseUrl}/labels/CI (perform both 4G and 5G tests)\n"
|
||||
githubPRComment comment: githubPRMessage(message)
|
||||
error('Not performing CI due to lack of mandatory labels')
|
||||
}
|
||||
if (env.GITHUB_PR_LABELS.contains('CI')) {
|
||||
do4Gtest = true
|
||||
do5Gtest = true
|
||||
do5GUeTest = true
|
||||
} else if (LABEL_CHECK == "SHORTEN-4G") {
|
||||
}
|
||||
if (env.GITHUB_PR_LABELS.contains('4G-LTE')) {
|
||||
do4Gtest = true
|
||||
} else if (LABEL_CHECK == 'SHORTEN-5G') {
|
||||
}
|
||||
if (env.GITHUB_PR_LABELS.contains('5G-NR')) {
|
||||
do5Gtest = true
|
||||
} else if (LABEL_CHECK == 'SHORTEN-5G-UE') {
|
||||
}
|
||||
if (env.GITHUB_PR_LABELS.contains('nrUE')) {
|
||||
do5GUeTest = true
|
||||
} else if (LABEL_CHECK == 'SHORTEN-4G-5G-UE') {
|
||||
do4Gtest = true
|
||||
do5GUeTest = true
|
||||
} else if (LABEL_CHECK == 'documentation') {
|
||||
}
|
||||
if (env.GITHUB_PR_LABELS.contains('documentation')) {
|
||||
doBuild = false
|
||||
} else {
|
||||
// is "BUILD-ONLY", will only build
|
||||
}
|
||||
} else {
|
||||
// PUSH event
|
||||
do4Gtest = true
|
||||
do5Gtest = true
|
||||
}
|
||||
echo """
|
||||
CI decision summary:
|
||||
doBuild = ${doBuild}
|
||||
do4Gtest = ${do4Gtest}
|
||||
do5Gtest = ${do5Gtest}
|
||||
do5GUeTest = ${do5GUeTest}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Verify Guidelines") {
|
||||
steps {
|
||||
echo "Git URL is ${GIT_URL}"
|
||||
echo "GitLab Act is ${env.gitlabActionType}"
|
||||
echo "Git URL is ${GIT_URL}"
|
||||
echo "Job Name is ${JOB_NAME}"
|
||||
echo "Build Id is ${BUILD_ID}"
|
||||
script {
|
||||
if ("MERGE".equals(env.gitlabActionType)) {
|
||||
// since a bit, in push events, gitlabUserEmail is not populated
|
||||
gitCommitAuthorEmailAddr = env.gitlabUserEmail
|
||||
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
|
||||
if (env.GITHUB_PR_NUMBER) {
|
||||
// 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",
|
||||
script: "bash ./ci-scripts/pre-ci-check.sh -s ${env.GITHUB_PR_HEAD_SHA} -t origin/${env.GITHUB_PR_TARGET_BRANCH} > ${mrValidationLog} 2>&1",
|
||||
returnStatus: true
|
||||
)
|
||||
def mrValidationMessage = readFile(mrValidationLog).trim()
|
||||
sh "rm -f ${mrValidationLog}"
|
||||
if (mrValidationExitCode >= 1) {
|
||||
addGitLabMRComment comment: "${mrValidationMessage}"
|
||||
mrValidationWarning = mrValidationMessage
|
||||
}
|
||||
if (mrValidationExitCode >= 2) {
|
||||
error("${mrValidationMessage}")
|
||||
@@ -104,26 +164,21 @@ pipeline {
|
||||
} else {
|
||||
echo "Git Branch is ${GIT_BRANCH}"
|
||||
echo "Git Commit is ${GIT_COMMIT}"
|
||||
// since a bit, in push events, gitlabUserEmail is not populated
|
||||
gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}'
|
||||
gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim()
|
||||
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Local-Repo-Push") {
|
||||
stage ("Internal-Repo-Push") {
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
|
||||
triggerDownstreamJob ('RAN-Internal-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'
|
||||
failingStages += '\n * Internal-Repo-Push - merge validation failed (merge conflict, git operation failure, or internal CI error)'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +190,7 @@ pipeline {
|
||||
stage ("Ubuntu-Image-Builder") {
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-Ubuntu18-Image-Builder', 'Ubuntu-Image-Builder')
|
||||
triggerDownstreamJob ('RAN-Ubuntu-Image-Builder')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -143,7 +198,7 @@ pipeline {
|
||||
script {
|
||||
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
||||
// due to parallel-time concurrency
|
||||
ubuntuBuildStatus = finalizeDownstreamJob('RAN-Ubuntu18-Image-Builder')
|
||||
ubuntuBuildStatus = finalizeDownstreamJob('RAN-Ubuntu-Image-Builder')
|
||||
}
|
||||
}
|
||||
failure {
|
||||
@@ -157,7 +212,7 @@ pipeline {
|
||||
stage ("Ubuntu-ARM-Image-Builder") {
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-Ubuntu-ARM-Image-Builder', 'Ubuntu-ARM-Image-Builder')
|
||||
triggerDownstreamJob ('RAN-Ubuntu-ARM-Image-Builder')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -179,7 +234,7 @@ pipeline {
|
||||
stage ("Ubuntu-Jetson-Image-Builder") {
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-Ubuntu-Jetson-Image-Builder', 'Ubuntu-Jetson-Image-Builder')
|
||||
triggerDownstreamJob ('RAN-Ubuntu-Jetson-Image-Builder')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -201,7 +256,7 @@ pipeline {
|
||||
stage ("RHEL-Cluster-Image-Builder") {
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-RHEL8-Cluster-Image-Builder', 'RHEL-Cluster-Image-Builder')
|
||||
triggerDownstreamJob ('RAN-RHEL-Cluster-Image-Builder')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -209,7 +264,7 @@ pipeline {
|
||||
script {
|
||||
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
||||
// due to parallel-time concurrency
|
||||
rhelBuildStatus = finalizeDownstreamJob('RAN-RHEL8-Cluster-Image-Builder')
|
||||
rhelBuildStatus = finalizeDownstreamJob('RAN-RHEL-Cluster-Image-Builder')
|
||||
}
|
||||
}
|
||||
failure {
|
||||
@@ -223,7 +278,7 @@ pipeline {
|
||||
stage ("ARM-Cross-Compile") {
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-ARM-Cross-Compile-Builder', 'ARM-Cross-Compilation')
|
||||
triggerDownstreamJob ('RAN-ARM-Cross-Compile-Builder')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -245,11 +300,11 @@ pipeline {
|
||||
}
|
||||
}
|
||||
stage ("DockerHub-Push") {
|
||||
when { expression {doBuild && "PUSH".equals(env.gitlabActionType)} }
|
||||
when { expression {doBuild && !(env.GITHUB_PR_NUMBER)} }
|
||||
steps {
|
||||
script {
|
||||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||
triggerDownstreamJob ('RAN-DockerHub-Push', 'DockerHub-Push')
|
||||
triggerDownstreamJob ('RAN-DockerHub-Push')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,7 +324,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-PhySim-Cluster-5G', 'PhySim-Cluster-5G')
|
||||
triggerDownstreamJob ('RAN-PhySim-Cluster-5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -292,7 +347,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-PhySim-GraceHopper-5G', 'PhySim-GraceHopper-5G')
|
||||
triggerDownstreamJob ('RAN-PhySim-GraceHopper-5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -315,7 +370,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-Channel-Simulation', 'Channel-Simulation')
|
||||
triggerDownstreamJob ('RAN-Channel-Simulation')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -338,7 +393,7 @@ pipeline {
|
||||
when { expression {do4Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-PhySim-Cluster-4G', 'PhySim-Cluster-4G')
|
||||
triggerDownstreamJob ('RAN-PhySim-Cluster-4G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -361,7 +416,7 @@ pipeline {
|
||||
when { expression {do4Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-RF-Sim-Test-4G', 'RF-Sim-Test-4G')
|
||||
triggerDownstreamJob ('RAN-RF-Sim-Test-4G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -384,7 +439,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-VRT-Sim-Test-5G', 'VRT-Sim-Test-5G')
|
||||
triggerDownstreamJob ('RAN-VRT-Sim-Test-5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -407,7 +462,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-RF-Sim-Test-5G', 'RF-Sim-Test-5G')
|
||||
triggerDownstreamJob ('RAN-RF-Sim-Test-5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -430,7 +485,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('OAI-FLEXRIC-RAN-Integration-Test', 'OAI-FLEXRIC-RAN-Integration-Test')
|
||||
triggerDownstreamJob ('OAI-FLEXRIC-RAN-Integration-Test')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -453,7 +508,7 @@ pipeline {
|
||||
when { expression {do4Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-L2-Sim-Test-4G', 'L2-Sim-Test-4G')
|
||||
triggerDownstreamJob ('RAN-L2-Sim-Test-4G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -476,7 +531,7 @@ pipeline {
|
||||
when { expression {do4Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-LTE-FDD-LTEBOX-Container', 'LTE-FDD-LTEBOX-Container')
|
||||
triggerDownstreamJob ('RAN-LTE-FDD-LTEBOX-Container')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -484,13 +539,13 @@ pipeline {
|
||||
script {
|
||||
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
||||
// due to parallel-time concurrency
|
||||
lteTDDB200Status = finalizeDownstreamJob('RAN-LTE-FDD-LTEBOX-Container')
|
||||
lteFDDB200Status = finalizeDownstreamJob('RAN-LTE-FDD-LTEBOX-Container')
|
||||
}
|
||||
}
|
||||
failure {
|
||||
script {
|
||||
currentBuild.result = 'FAILURE'
|
||||
failingStages += lteTDDB200Status
|
||||
failingStages += lteFDDB200Status
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -500,7 +555,7 @@ pipeline {
|
||||
when { expression {do4Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-LTE-FDD-OAIUE-OAICN4G-Container', 'LTE-FDD-OAIUE-OAICN4G-Container')
|
||||
triggerDownstreamJob ('RAN-LTE-FDD-OAIUE-OAICN4G-Container')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -523,7 +578,7 @@ pipeline {
|
||||
when { expression {do4Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-LTE-TDD-LTEBOX-Container', 'LTE-TDD-LTEBOX-Container')
|
||||
triggerDownstreamJob ('RAN-LTE-TDD-LTEBOX-Container')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -531,13 +586,13 @@ pipeline {
|
||||
script {
|
||||
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
||||
// due to parallel-time concurrency
|
||||
lteFDDB200Status = finalizeDownstreamJob('RAN-LTE-TDD-LTEBOX-Container')
|
||||
lteTDDB200Status = finalizeDownstreamJob('RAN-LTE-TDD-LTEBOX-Container')
|
||||
}
|
||||
}
|
||||
failure {
|
||||
script {
|
||||
currentBuild.result = 'FAILURE'
|
||||
failingStages += lteFDDB200Status
|
||||
failingStages += lteTDDB200Status
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,7 +601,7 @@ pipeline {
|
||||
when { expression {do4Gtest || do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-NSA-B200-Module-LTEBOX-Container', 'NSA-B200-Module-LTEBOX-Container')
|
||||
triggerDownstreamJob ('RAN-NSA-B200-Module-LTEBOX-Container')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -569,7 +624,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-B200-Module-SABOX-Container', 'SA-B200-Module-SABOX-Container')
|
||||
triggerDownstreamJob ('RAN-SA-B200-Module-SABOX-Container')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -592,7 +647,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-gNB-N300-Timing-Phytest-LDPC', 'gNB-N300-Timing-Phytest-LDPC')
|
||||
triggerDownstreamJob ('RAN-gNB-N300-Timing-Phytest-LDPC')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -615,7 +670,7 @@ pipeline {
|
||||
when { expression {do4Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-LTE-TDD-2x2-Container', 'LTE-TDD-2x2-Container')
|
||||
triggerDownstreamJob ('RAN-LTE-TDD-2x2-Container')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -638,7 +693,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-AW2S-CN5G', 'SA-AW2S-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-AW2S-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -661,7 +716,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerCN5GDownstreamJob ('OAI-CN5G-COTS-UE-Test', 'OAI-CN5G-COTS-UE-Test')
|
||||
triggerCN5GDownstreamJob ('OAI-CN5G-COTS-UE-Test')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -684,7 +739,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-AERIAL-CN5G', 'SA-AERIAL-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-AERIAL-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -707,7 +762,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-Multi-Antenna-CN5G', 'SA-Multi-Antenna-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-Multi-Antenna-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -730,7 +785,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-FHI72-CN5G', 'SA-FHI72-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-FHI72-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -753,7 +808,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-FHI72-MPLANE-CN5G', 'SA-FHI72-MPLANE-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-FHI72-MPLANE-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -776,7 +831,7 @@ pipeline {
|
||||
when { expression {do5Gtest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-Handover-CN5G', 'SA-Handover-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-Handover-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -799,7 +854,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-AERIAL-OAIUE-CN5G', 'SA-AERIAL-OAIUE-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-AERIAL-OAIUE-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -822,7 +877,7 @@ pipeline {
|
||||
when { expression {do5Gtest || do5GUeTest} }
|
||||
steps {
|
||||
script {
|
||||
triggerDownstreamJob ('RAN-SA-OAIUE-CN5G', 'SA-OAIUE-CN5G')
|
||||
triggerDownstreamJob ('RAN-SA-OAIUE-CN5G')
|
||||
}
|
||||
}
|
||||
post {
|
||||
@@ -847,21 +902,47 @@ pipeline {
|
||||
post {
|
||||
success {
|
||||
script {
|
||||
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")"
|
||||
if ("MERGE".equals(env.gitlabActionType)) {
|
||||
addGitLabMRComment comment: message
|
||||
def message2 = message + " -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")"
|
||||
if (env.GITHUB_PR_NUMBER) {
|
||||
if (mrValidationWarning) {
|
||||
def message = "**CI Build:** [#${env.BUILD_NUMBER}](${BUILD_URL}) | **Passed**"
|
||||
message += "\n\n**Validation:** " + mrValidationWarning
|
||||
githubPRComment comment: githubPRMessage(message)
|
||||
}
|
||||
githubNotify account: params.gitAccount,
|
||||
repo: params.gitRepo,
|
||||
credentialsId: 'github-jenkins-duranta',
|
||||
sha: env.GITHUB_PR_HEAD_SHA,
|
||||
status: 'SUCCESS',
|
||||
description: 'Build success',
|
||||
targetUrl: BUILD_URL,
|
||||
context: 'Jenkins Duranta CI'
|
||||
}
|
||||
echo "Pipeline is SUCCESSFUL"
|
||||
}
|
||||
}
|
||||
failure {
|
||||
script {
|
||||
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")"
|
||||
if ("MERGE".equals(env.gitlabActionType)) {
|
||||
def fullMessage = message + '\n\nList of failing test stages:' + failingStages
|
||||
addGitLabMRComment comment: fullMessage
|
||||
def message2 = message + " -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")"
|
||||
if (env.GITHUB_PR_NUMBER) {
|
||||
def message = "**CI Build:** [#${env.BUILD_NUMBER}](${BUILD_URL}) | **Failed** on the following stages:"
|
||||
if (failingStages) {
|
||||
message += failingStages
|
||||
} else {
|
||||
message += "\nThe pipeline may have failed due to CI, validation, or scripting error. See the build for more details."
|
||||
}
|
||||
if (mrValidationWarning) {
|
||||
message += '\n\n**Validation:** ' + mrValidationWarning
|
||||
}
|
||||
if (env.GITHUB_PR_LABELS) {
|
||||
githubPRComment comment: githubPRMessage(message)
|
||||
}
|
||||
githubNotify account: params.gitAccount,
|
||||
repo: params.gitRepo,
|
||||
credentialsId: 'github-jenkins-duranta',
|
||||
sha: env.GITHUB_PR_HEAD_SHA,
|
||||
status: 'FAILURE',
|
||||
description: 'Build failed',
|
||||
targetUrl: BUILD_URL,
|
||||
context: 'Jenkins Duranta CI'
|
||||
}
|
||||
echo "Pipeline FAILED"
|
||||
}
|
||||
@@ -871,41 +952,35 @@ pipeline {
|
||||
|
||||
// ---- Slave Job functions
|
||||
|
||||
def triggerDownstreamJob (jobName, gitlabStatusName) {
|
||||
def MR_NUMBER = "MERGE".equals(env.gitlabActionType) ? env.gitlabMergeRequestIid : 'develop'
|
||||
// Workaround for the "cancelled" GitLab pipeline notification
|
||||
def triggerDownstreamJob (jobName) {
|
||||
// Workaround for the "cancelled" pipeline notification
|
||||
// The downstream job is triggered with the propagate false so the following commands are executed
|
||||
// Its status is now PASS/SUCCESS from a stage pipeline point of view
|
||||
// localStatus variable MUST be analyzed to properly assess the status
|
||||
def localStatus = build job: jobName,
|
||||
parameters: [
|
||||
string(name: 'targetRepo', value: String.valueOf(env.gitlabTargetRepoHttpUrl)),
|
||||
string(name: 'sourceRepo', value: String.valueOf(env.gitlabSourceRepoHttpUrl)),
|
||||
string(name: 'sourceBranch', value: String.valueOf(env.gitlabSourceBranch)),
|
||||
string(name: 'sourceCommit', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
|
||||
string(name: 'requestNumber', value: String.valueOf(MR_NUMBER)),
|
||||
booleanParam(name: 'mergeWithTarget', value: "MERGE".equals(env.gitlabActionType)),
|
||||
string(name: 'targetBranch', value: String.valueOf(env.gitlabTargetBranch)),
|
||||
string(name: 'targetRepo', value: String.valueOf(env.GIT_URL)),
|
||||
string(name: 'sourceRepo', value: String.valueOf(env.GITHUB_PR_URL ?: env.GIT_URL)),
|
||||
string(name: 'sourceBranch', value: String.valueOf(env.GITHUB_PR_SOURCE_BRANCH ?: gitLocalBranch)),
|
||||
string(name: 'sourceCommit', value: String.valueOf(env.GITHUB_PR_HEAD_SHA ?: env.GIT_COMMIT)),
|
||||
string(name: 'requestNumber', value: String.valueOf(env.GITHUB_PR_NUMBER ?: gitLocalBranch)),
|
||||
booleanParam(name: 'mergeWithTarget', value: env.GITHUB_PR_NUMBER != null),
|
||||
string(name: 'targetBranch', value: (env.GITHUB_PR_TARGET_BRANCH ?: gitLocalBranch)),
|
||||
string(name: 'repository', value: String.valueOf(params.ciRepositoryURL)),
|
||||
string(name: 'branch', value: "${env.gitlabSourceBranch.replace('/', '-')}-${env.gitlabMergeRequestLastCommit}")
|
||||
string(name: 'branch', value: String.valueOf(branch))
|
||||
], propagate: false
|
||||
def localResult = localStatus.getResult()
|
||||
echo "${jobName} Slave Job status is ${localResult}"
|
||||
gitlabCommitStatus(name: gitlabStatusName) {
|
||||
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
|
||||
echo "${jobName} Slave Job is OK"
|
||||
} else {
|
||||
error "${jobName} Slave Job is KO"
|
||||
}
|
||||
downstreamResults[jobName] = localStatus.resultIsBetterOrEqualTo('SUCCESS') ? 'SUCCESS' : 'FAILURE'
|
||||
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
|
||||
echo "${jobName} Slave Job is OK"
|
||||
} else {
|
||||
error "${jobName} Slave Job is KO"
|
||||
}
|
||||
}
|
||||
|
||||
def triggerCN5GDownstreamJob (jobName, gitlabStatusName) {
|
||||
if ("MERGE".equals(env.gitlabActionType)) {
|
||||
fullRanTag = OAI_Registry + '/oai-gnb:' + "${env.gitlabSourceBranch.replace('/', '-')}-${env.gitlabMergeRequestLastCommit}"
|
||||
} else {
|
||||
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + env.GIT_COMMIT
|
||||
}
|
||||
def triggerCN5GDownstreamJob (jobName) {
|
||||
def fullRanTag = params.internalRegistry + '/oai-gnb:' + "${branch}"
|
||||
// Workaround for the "cancelled" GitLab pipeline notification
|
||||
// The downstream job is triggered with the propagate false so the following commands are executed
|
||||
// Its status is now PASS/SUCCESS from a stage pipeline point of view
|
||||
@@ -916,12 +991,11 @@ def triggerCN5GDownstreamJob (jobName, gitlabStatusName) {
|
||||
], propagate: false
|
||||
def localResult = localStatus.getResult()
|
||||
echo "${jobName} Slave Job status is ${localResult}"
|
||||
gitlabCommitStatus(name: gitlabStatusName) {
|
||||
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
|
||||
echo "${jobName} Slave Job is OK"
|
||||
} else {
|
||||
error "${jobName} Slave Job is KO"
|
||||
}
|
||||
downstreamResults[jobName] = localStatus.resultIsBetterOrEqualTo('SUCCESS') ? 'SUCCESS' : 'FAILURE'
|
||||
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
|
||||
echo "${jobName} Slave Job is OK"
|
||||
} else {
|
||||
error "${jobName} Slave Job is KO"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -929,12 +1003,13 @@ def finalizeDownstreamJob(jobName) {
|
||||
lock ('Parent-Lock') {
|
||||
// In case of any non-success, we are retrieving the HTML report of the last completed
|
||||
// downstream job. The only drop-back is that we may retrieve the HTML report of a previous build
|
||||
def fileName
|
||||
if (jobName == 'OAI-CN5G-COTS-UE-Test') {
|
||||
fileName = "test_results_oai_cn5g_cots_ue.html"
|
||||
} else {
|
||||
fileName = "test_results-${jobName}.html"
|
||||
}
|
||||
artifactUrl = BUILD_URL
|
||||
def artifactUrl = BUILD_URL
|
||||
if (!fileExists(fileName)) {
|
||||
copyArtifacts(projectName: jobName,
|
||||
filter: 'test_results*.html',
|
||||
@@ -950,6 +1025,15 @@ def finalizeDownstreamJob(jobName) {
|
||||
// no need to add a prefixed '/'
|
||||
artifactUrl += 'artifact/' + fileName
|
||||
}
|
||||
if (env.GITHUB_PR_NUMBER) {
|
||||
githubNotify account: params.gitAccount,
|
||||
repo: params.gitRepo,
|
||||
credentialsId: "github-jenkins-duranta",
|
||||
sha: env.GITHUB_PR_HEAD_SHA,
|
||||
status: downstreamResults.getOrDefault(jobName, 'FAILURE'),
|
||||
targetUrl: "${artifactUrl}",
|
||||
context: jobName
|
||||
}
|
||||
artifactUrl = "\n * [${jobName}](${artifactUrl})"
|
||||
return artifactUrl
|
||||
}
|
||||
@@ -23,11 +23,54 @@ pipeline {
|
||||
lock(extra: lockResources)
|
||||
}
|
||||
stages {
|
||||
stage("Job init") {
|
||||
steps {
|
||||
buildName "${params.requestNumber ?: params.targetBranch}"
|
||||
buildDescription "Branch: ${params.sourceBranch}"
|
||||
}
|
||||
}
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
script {
|
||||
if (params.mergeWithTarget) {
|
||||
echo "PR triggered - checking out merge ref for PR #${params.requestNumber}"
|
||||
try {
|
||||
checkout([
|
||||
$class: 'GitSCM',
|
||||
branches: [[name: "refs/remotes/origin/pr/${params.requestNumber}/merge"]],
|
||||
userRemoteConfigs: [[
|
||||
url: params.targetRepo,
|
||||
refspec: "+refs/pull/${params.requestNumber}/merge:refs/remotes/origin/pr/${params.requestNumber}/merge",
|
||||
credentialsId: 'github-jenkins-duranta'
|
||||
]]
|
||||
])
|
||||
} catch (e) {
|
||||
error("Checkout failed for PR #${params.requestNumber} - " +
|
||||
"merge ref not found. The PR likely has a conflict with ${params.targetBranch} " +
|
||||
"that must be resolved before CI can run. (${e.message})")
|
||||
}
|
||||
} else {
|
||||
echo "Push triggered - checking out branch ${params.targetBranch}"
|
||||
try {
|
||||
checkout([
|
||||
$class: 'GitSCM',
|
||||
branches: [[name: params.targetBranch]],
|
||||
userRemoteConfigs: [[
|
||||
url: params.targetRepo,
|
||||
credentialsId: 'github-jenkins-duranta'
|
||||
]]
|
||||
])
|
||||
} catch (e) {
|
||||
error("Checkout failed for branch ${params.targetBranch} from ${params.targetRepo}. (${e.message})")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Verify parameters') {
|
||||
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) {
|
||||
@@ -39,7 +82,6 @@ pipeline {
|
||||
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}"
|
||||
@@ -53,49 +95,17 @@ pipeline {
|
||||
stage('Prepare workspace') {
|
||||
steps {
|
||||
sh """
|
||||
git config user.email "jenkins@openairinterface.org"
|
||||
git config user.name "OAI Jenkins"
|
||||
git remote remove source || true
|
||||
git remote remove target || true
|
||||
git config user.email "oaicicdteam@openairinterface.org"
|
||||
git config user.name "Duranta Jenkins"
|
||||
git remote remove internal-repo || true
|
||||
"""
|
||||
}
|
||||
}
|
||||
stage('Add source repo & fetch branches') {
|
||||
steps {
|
||||
sh """
|
||||
git remote add source ${params.sourceRepo} || true
|
||||
git fetch source ${params.sourceBranch}
|
||||
"""
|
||||
script {
|
||||
if (params.mergeWithTarget) {
|
||||
sh """
|
||||
git remote add target ${params.targetRepo} || true
|
||||
git fetch target ${params.targetBranch}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Create testing branch for CI') {
|
||||
steps {
|
||||
sh """
|
||||
# Checkout source commit
|
||||
git checkout -B ${params.branch} ${params.sourceCommit}
|
||||
"""
|
||||
}
|
||||
}
|
||||
stage('Merge target into source') {
|
||||
when { expression { return params.mergeWithTarget } }
|
||||
steps {
|
||||
sh """
|
||||
echo "Merging target branch ${params.targetBranch} into source branch ${params.branch}"
|
||||
if ! git merge --ff target/${params.targetBranch} \
|
||||
-m "Merge ${params.targetBranch} into ${params.sourceBranch} for CI"; then
|
||||
echo "Merge conflicts detected. Aborting."
|
||||
git merge --abort || true
|
||||
exit 1
|
||||
fi
|
||||
git checkout -B ${params.branch}
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ pipeline {
|
||||
stage ("Push to DockerHub") {
|
||||
steps {
|
||||
script {
|
||||
WEEK_REF = sh returnStdout: true, script: 'date +"%Y.w%V"'
|
||||
def WEEK_REF = sh returnStdout: true, script: 'date +"%Y.w%V"'
|
||||
WEEK_REF = WEEK_REF.trim()
|
||||
WEEK_TAG = sh returnStdout: true, script: 'python3 ./ci-scripts/provideUniqueImageTag.py --start_tag ' + WEEK_REF
|
||||
def WEEK_TAG = sh returnStdout: true, script: 'python3 ./ci-scripts/provideUniqueImageTag.py --start_tag ' + WEEK_REF
|
||||
WEEK_TAG = WEEK_TAG.trim()
|
||||
if ((params.forceTag != null) && (params.tagToUse != null)) {
|
||||
if (params.forceTag) {
|
||||
@@ -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'
|
||||
def WEEK_SHA = sh returnStdout: true, script: 'git log -n1 --pretty=format:"%H" origin/develop'
|
||||
WEEK_SHA = WEEK_SHA.trim()
|
||||
|
||||
withCredentials([
|
||||
|
||||
@@ -92,7 +92,7 @@ pipeline {
|
||||
sourceBranch = selected_ref.replaceFirst("^origin/", "")
|
||||
commitID = sh(script: "git rev-parse ${selected_ref}", returnStdout: true).trim()
|
||||
echo "Found branch ${sourceBranch}, commit ${commitID}"
|
||||
testBranch = "${sourceBranch}"
|
||||
testBranch = "${sourceBranch}-${commitID}"
|
||||
}
|
||||
|
||||
echo "CI executor node : ${pythonExecutor}"
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
function usage {
|
||||
echo "OAI GitLab merge request applying script"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo "------"
|
||||
echo ""
|
||||
echo " checkGitLabMergeRequestLabels.sh [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo "------------------"
|
||||
echo ""
|
||||
echo " --mr-id ####"
|
||||
echo " Specify the ID of the merge request."
|
||||
echo ""
|
||||
echo " --help OR -h"
|
||||
echo " Print this help message."
|
||||
echo ""
|
||||
}
|
||||
|
||||
if [ $# -ne 2 ] && [ $# -ne 1 ]
|
||||
then
|
||||
echo "Syntax Error: not the correct number of arguments"
|
||||
echo ""
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
-h|--help)
|
||||
shift
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--mr-id)
|
||||
MERGE_REQUEST_ID="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Syntax Error: unknown option: $key"
|
||||
echo ""
|
||||
usage
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
|
||||
LABELS=`curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/$MERGE_REQUEST_ID" | jq '.labels' || true`
|
||||
|
||||
IS_MR_DOCUMENTATION=`echo $LABELS | grep -ic documentation`
|
||||
IS_MR_BUILD_ONLY=`echo $LABELS | grep -c BUILD-ONLY`
|
||||
IS_MR_CI=`echo $LABELS | grep -c CI`
|
||||
IS_MR_4G=`echo $LABELS | grep -c 4G-LTE`
|
||||
IS_MR_5G=`echo $LABELS | grep -c 5G-NR`
|
||||
IS_MR_5G_UE=`echo $LABELS | grep -c nrUE`
|
||||
|
||||
# none is present! No CI
|
||||
if [ $IS_MR_BUILD_ONLY -eq 0 ] && [ $IS_MR_CI -eq 0 ] && [ $IS_MR_4G -eq 0 ] && [ $IS_MR_5G -eq 0 ] && [ $IS_MR_DOCUMENTATION -eq 0 ] && [ $IS_MR_5G_UE -eq 0 ]
|
||||
then
|
||||
echo "NONE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 4G and 5G or CI labels: run everything (4G, 5G)
|
||||
if [ $IS_MR_4G -eq 1 ] && [ $IS_MR_5G -eq 1 ] || [ $IS_MR_CI -eq 1 ]
|
||||
then
|
||||
echo "FULL"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $IS_MR_5G_UE -eq 1 ] && [ $IS_MR_4G -eq 1 ]
|
||||
then
|
||||
echo "SHORTEN-4G-5G-UE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 4G is present: run only 4G
|
||||
if [ $IS_MR_4G -eq 1 ]
|
||||
then
|
||||
echo "SHORTEN-4G"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 5G is present: run only 5G
|
||||
if [ $IS_MR_5G -eq 1 ]
|
||||
then
|
||||
echo "SHORTEN-5G"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $IS_MR_5G_UE -eq 1 ]
|
||||
then
|
||||
echo "SHORTEN-5G-UE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# BUILD-ONLY is present: only build stages
|
||||
if [ $IS_MR_BUILD_ONLY -eq 1 ]
|
||||
then
|
||||
echo "BUILD-ONLY"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Documentation is present: don't do anything
|
||||
if [ $IS_MR_DOCUMENTATION -eq 1 ]
|
||||
then
|
||||
echo "documentation"
|
||||
exit 0
|
||||
fi
|
||||
@@ -95,13 +95,13 @@ class Analysis():
|
||||
test_summary['Nbfail'] = nb_failed
|
||||
return nb_failed == 0, test_summary, test_result
|
||||
|
||||
def analyze_rt_stats(thresholds, L1_stats, MAC_stats):
|
||||
def analyze_rt_stats(thresholds, stat_files):
|
||||
with open(thresholds, 'r') as f:
|
||||
datalog_rt_stats = yaml.load(f, Loader=yaml.FullLoader)
|
||||
|
||||
rt_keys = datalog_rt_stats['Ref']
|
||||
real_time_stats = {}
|
||||
for sf in [L1_stats, MAC_stats]:
|
||||
for sf in stat_files:
|
||||
with open(sf, 'r') as f:
|
||||
for line in f.readlines():
|
||||
for k in rt_keys:
|
||||
|
||||
@@ -401,7 +401,7 @@ class Containerize():
|
||||
# I would like to run it with --rm and mount the ctest result directory to avoid 'docker cp'
|
||||
# below, but then permissions are messed up and we can't remove the directory without sudo
|
||||
# making the next pipeline fail
|
||||
ret = cmd.run(f'docker run -a STDOUT {runtime_opt} --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --name ran-unittests ran-unittests:{baseTag} ctest --no-label-summary -j$(nproc) {ctest_opt}')
|
||||
ret = cmd.run(f'docker run -a STDOUT {runtime_opt} --shm-size=2g --workdir /oai-ran/build/ --env LD_LIBRARY_PATH=/oai-ran/build/ --name ran-unittests ran-unittests:{baseTag} ctest --no-label-summary -j$(nproc) {ctest_opt}')
|
||||
cmd.run('docker cp ran-unittests:/oai-ran/build/Testing/Temporary/LastTest.log .')
|
||||
archiveArtifact(cmd, ctx, f'{lSourcePath}/LastTest.log')
|
||||
cmd.run('docker cp ran-unittests:/oai-ran/build/Testing/Temporary/LastTestsFailed.log .')
|
||||
@@ -644,7 +644,7 @@ class Containerize():
|
||||
logging.error('\u001B[1m Undeploying objects Failed\u001B[0m')
|
||||
return success
|
||||
|
||||
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None):
|
||||
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None, stats_files=None):
|
||||
logging.info(f'Analyzing realtime stats from server: {node}')
|
||||
yaml = self.yamlPath.strip('/')
|
||||
wd = f'{self.workspace}/{yaml}'
|
||||
@@ -660,12 +660,20 @@ class Containerize():
|
||||
raise RuntimeError(f"Requested service {s} not found among services: {deployed_services}")
|
||||
logging.info(f"Analyzing deployed service '{s}'")
|
||||
# similar to BuildRunTests(), use docker cp to avoid problems with permissions
|
||||
cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrL1_stats.log {wd}/')
|
||||
l1_file = archiveArtifact(cmd, ctx, f"{wd}/nrL1_stats.log")
|
||||
cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrMAC_stats.log {wd}/')
|
||||
mac_file = archiveArtifact(cmd, ctx, f"{wd}/nrMAC_stats.log")
|
||||
local_files = []
|
||||
for sf in stats_files:
|
||||
basename = os.path.basename(sf)
|
||||
ret = cmd.run(f'docker compose -f {wd_yaml} cp {s}:{sf} {wd}/')
|
||||
if ret.returncode != 0:
|
||||
logging.error(f"Cannot retrieve {s}:{sf}")
|
||||
return False
|
||||
file = archiveArtifact(cmd, ctx, f"{wd}/{basename}")
|
||||
if not file:
|
||||
logging.error(f"Cannot retrieve file {basename}")
|
||||
return False
|
||||
local_files.append(file)
|
||||
|
||||
logging.info(f"check against thresholds from {thresholds}")
|
||||
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, l1_file, mac_file)
|
||||
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, local_files)
|
||||
HTML.CreateHtmlDataLogTable(datalog_rt_stats)
|
||||
return success
|
||||
|
||||
@@ -75,12 +75,12 @@ class HTMLManagement():
|
||||
self.htmlFile.write(' <tr style="border-collapse: collapse; border: none;">\n')
|
||||
self.htmlFile.write(' <td style="border-collapse: collapse; border: none;">\n')
|
||||
self.htmlFile.write(' <a href="http://www.openairinterface.org/">\n')
|
||||
self.htmlFile.write(' <img src="http://www.openairinterface.org/wp-content/uploads/2016/03/cropped-oai_final_logo2.png" alt="" border="none" height=50 width=150>\n')
|
||||
self.htmlFile.write(' <img src="https://raw.githubusercontent.com/duranta-project/governance/main/logos/Duranta-Logo-Color.png" alt="" border="none" style="margin-right: 2rem;" width=150>\n')
|
||||
self.htmlFile.write(' </img>\n')
|
||||
self.htmlFile.write(' </a>\n')
|
||||
self.htmlFile.write(' </td>\n')
|
||||
self.htmlFile.write(' <td style="border-collapse: collapse; border: none; vertical-align: center;">\n')
|
||||
self.htmlFile.write(' <b><font size = "6">Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID</font></b>\n')
|
||||
self.htmlFile.write(' <b><font size = "6">TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID</font></b>\n')
|
||||
self.htmlFile.write(' </td>\n')
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
self.htmlFile.write(' </table>\n')
|
||||
|
||||
222
ci-scripts/conf_files/gnb.band79.106prb.vrtsim.phytest-dora.conf
Normal file
222
ci-scripts/conf_files/gnb.band79.106prb.vrtsim.phytest-dora.conf
Normal file
@@ -0,0 +1,222 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({mcc = 208; mnc = 99; mnc_length = 2;});
|
||||
|
||||
tr_s_preference = "local_mac"
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 4412.64 MHz
|
||||
absoluteFrequencySSB = 694176;
|
||||
dl_frequencyBand = 79;
|
||||
# this is 4400.94 MHz
|
||||
dl_absoluteFrequencyPointA = 693396;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=41,L=24 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 6368;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 79;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 6368;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -118;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#one (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// MME parameters:
|
||||
mme_ip_address = ({ ipv4 = "192.168.12.26"; port = 36412; });
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
|
||||
GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24";
|
||||
GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
});
|
||||
|
||||
L1s = (
|
||||
{
|
||||
tr_n_preference = "local_mac";
|
||||
});
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
});
|
||||
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
};
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 641280;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3600 MHz
|
||||
dl_absoluteFrequencyPointA = 640008;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 148;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 10;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#one (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# 0=sl1, 1=sl2, 2=sl4, 3=sl8, 4=sl10, 5=sl20, 6=sl40, 7=sl80, 8=sl160, 9=sl320
|
||||
msgB_ResponseWindow_r16 = 5;
|
||||
msgA_RSRP_Threshold_r16 = 19;
|
||||
|
||||
msgA_CB_PreamblesPerSSB_PerSharedRO_r16 = 1;
|
||||
|
||||
msgA_MCS_r16 = 2;
|
||||
nrofSlotsMsgA_PUSCH_r16 = 1;
|
||||
# 0=one, 1=two, 2=three, 3=six
|
||||
nrofMsgA_PO_PerSlot_r16 = 0;
|
||||
msgA_PUSCH_TimeDomainOffset_r16 = 8;
|
||||
startSymbolAndLengthMsgA_PO_r16 = 38;
|
||||
mappingTypeMsgA_PUSCH_r16 = 0;
|
||||
guardBandMsgA_PUSCH_r16 = 0;
|
||||
frequencyStartMsgA_PUSCH_r16 = 0;
|
||||
nrofPRBs_PerMsgA_PO_r16 = 8;
|
||||
# 0=one, 1=two, 2=four, 3=eight
|
||||
nrofMsgA_PO_FDM_r16 = 0;
|
||||
msgA_PUSCH_NrofPorts_r16 = 1;
|
||||
nrofDMRS_Sequences_r16 = 1;
|
||||
# 0=enabled, 1=disabled
|
||||
msgA_TransformPrecoder_r16 = 1;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ({ ipv4 = "192.168.71.132"; });
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/24";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 150;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 12;
|
||||
att_rx = 12;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = 4043;
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="debug";
|
||||
};
|
||||
|
||||
e2_agent = {
|
||||
near_ric_ip_addr = "127.0.0.1";
|
||||
#sm_dir = "/path/where/the/SMs/are/located/"
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
};
|
||||
32
ci-scripts/datalog_rt_stats.gnb.40.vrtsim.yaml
Normal file
32
ci-scripts/datalog_rt_stats.gnb.40.vrtsim.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
#this is a configuration file
|
||||
#used to build real time processing statistics
|
||||
#for 5G NR phy test (gNB terminate)
|
||||
Title : gNB Processing Time (us) from datalog_rt_stats.default.yaml
|
||||
ColNames :
|
||||
- Metric
|
||||
- Average; Max; Count
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
|
||||
Ref :
|
||||
L1 Tx processing : 190.0
|
||||
DLSCH encoding : 120.0
|
||||
L1 Rx processing : 235.0
|
||||
UL segments decoding : 120.0
|
||||
PUSCH inner-receiver : 150.0
|
||||
UL Indication : 2.0
|
||||
Slot Indication : 10.0
|
||||
feprx : 40.0
|
||||
feptx_ofdm (per port, half_slot) : 30
|
||||
feptx_total : 52
|
||||
DeviationThreshold :
|
||||
L1 Tx processing : 0.25
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
UL segments decoding : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.50
|
||||
feprx : 0.25
|
||||
feptx_ofdm (per port, half_slot) : 0.25
|
||||
feptx_total : 0.25
|
||||
40
ci-scripts/datalog_rt_stats.ue.40.vrtsim.yaml
Normal file
40
ci-scripts/datalog_rt_stats.ue.40.vrtsim.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
#this is a configuration file
|
||||
#used to build real time processing statistics
|
||||
#for 5G NR phy test (gNB terminate)
|
||||
Title : UE Processing Time (us) from datalog_rt_stats.ue.40.vrtsim.yaml
|
||||
ColNames :
|
||||
- Metric
|
||||
- Average; Max; Count
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
|
||||
Ref :
|
||||
RX_PDSCH_STATS : 62.0
|
||||
DLSCH_RX_PDCCH_STATS : 30.5
|
||||
RX_DFT_STATS : 5.5
|
||||
DLSCH_CHANNEL_ESTIMATION_STATS : 39.0
|
||||
DLSCH_DECODING_STATS : 178.0
|
||||
DLSCH_LDPC_DECODING_STATS : 78.0
|
||||
DLSCH_LLR_STATS : 25.0
|
||||
DLSCH_LAYER_DEMAPPING : 8.5
|
||||
DLSCH_PROCEDURES_STATS : 188.0
|
||||
PHY_PROC_TX : 158.0
|
||||
PUSCH_PROC_STATS : 167.0
|
||||
ULSCH_LDPC_ENCODING_STATS : 43.0
|
||||
ULSCH_ENCODING_STATS : 121.0
|
||||
OFDM_MOD_STATS : 44.5
|
||||
DeviationThreshold :
|
||||
RX_PDSCH_STATS : 0.25
|
||||
DLSCH_RX_PDCCH_STATS : 0.25
|
||||
RX_DFT_STATS : 0.25
|
||||
DLSCH_CHANNEL_ESTIMATION_STATS : 0.25
|
||||
DLSCH_DECODING_STATS : 0.25
|
||||
DLSCH_LDPC_DECODING_STATS : 0.25
|
||||
DLSCH_LLR_STATS : 0.25
|
||||
DLSCH_LAYER_DEMAPPING : 0.5
|
||||
DLSCH_PROCEDURES_STATS : 0.25
|
||||
PHY_PROC_TX : 0.25
|
||||
PUSCH_PROC_STATS : 0.25
|
||||
ULSCH_LDPC_ENCODING_STATS : 0.25
|
||||
ULSCH_ENCODING_STATS : 0.25
|
||||
OFDM_MOD_STATS : 0.25
|
||||
@@ -245,7 +245,8 @@ def ExecuteActionWithParam(action, ctx, node):
|
||||
elif action == 'AnalyzeRTStats_Object':
|
||||
yaml = test.findtext('stats_cfg')
|
||||
service = test.findtext('service')
|
||||
success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml, service)
|
||||
stats_files = (test.findtext('stats_file') or '').split()
|
||||
success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml, service, stats_files)
|
||||
|
||||
else:
|
||||
logging.warning(f"unknown action {action}, skip step")
|
||||
|
||||
@@ -25,8 +25,6 @@ function usage {
|
||||
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)
|
||||
@@ -57,11 +55,20 @@ 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 [[ "$SOURCE_BRANCH" =~ ^[0-9a-f]{40}$ ]]; then
|
||||
# note: if no branch could be found, it will result in "" and git rev-list
|
||||
# will use the commit ID. Exclude "HEAD detached at", then use first branch
|
||||
# name.
|
||||
BRANCH_NAME=$(git branch -a --points-at $SOURCE_BRANCH --format='%(refname:short)' | grep -v detached | head -n1)
|
||||
echo "SHA recognized in $SOURCE_BRANCH, using \"$BRANCH_NAME\" as branch name"
|
||||
else
|
||||
BRANCH_NAME="$SOURCE_BRANCH"
|
||||
fi
|
||||
if [[ ! "$BRANCH_NAME" =~ ^(origin/)?integration_[0-9]{4}_w[0-9]{2}$ ]]; then
|
||||
mergeCommits=$(git rev-list --merges --abbrev-commit "$TARGET_BRANCH".."$SOURCE_BRANCH")
|
||||
if [[ -n "$mergeCommits" ]]; then
|
||||
message="> ERROR: Following merge commits are found in the source branch history. Please rebase your branch.\n>\n"
|
||||
message+="> $(echo "$mergeCommits" | paste -sd ',' -)\n"
|
||||
message="Error: Following merge commits are found in the source branch history. Please rebase your branch.\n\n"
|
||||
message+="$(echo "$mergeCommits" | paste -sd ',' | sed 's/,/, /g')\n"
|
||||
echo -e "$message"
|
||||
exit 3
|
||||
fi
|
||||
@@ -75,7 +82,7 @@ unsignedCommits=$(
|
||||
if ! git log -1 --format=%B "$c" | grep -q "Signed-off-by:"; then
|
||||
git log -1 --format='%h' "$c"
|
||||
fi
|
||||
done | paste -sd ","
|
||||
done | paste -sd ',' | sed 's/,/, /g'
|
||||
)
|
||||
|
||||
# ----------------------------
|
||||
@@ -84,13 +91,13 @@ unsignedCommits=$(
|
||||
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."
|
||||
message="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"
|
||||
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'."
|
||||
message="All commits are signed off using 'git commit -s'."
|
||||
echo -e "$message"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -145,6 +145,6 @@ class RANManagement():
|
||||
mac_file = archiveArtifact(cmd, ctx, f"{logdir}/nrMAC_stats.log")
|
||||
|
||||
logging.info(f"check against thresholds from {thresholds}")
|
||||
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, l1_file, mac_file)
|
||||
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, [l1_file, mac_file])
|
||||
HTML.CreateHtmlDataLogTable(datalog_rt_stats)
|
||||
return success
|
||||
|
||||
@@ -26,7 +26,7 @@ class TestAnalysis(unittest.TestCase):
|
||||
rtsf = "datalog_rt_stats.100.2x2.yaml"
|
||||
l1f = "tests/analysis/gnb_phytest.success.nrL1.log"
|
||||
macf = "tests/analysis/gnb_phytest.success.nrMAC.log"
|
||||
status, s = cls_analysis.Analysis.analyze_rt_stats(rtsf, l1f, macf)
|
||||
status, s = cls_analysis.Analysis.analyze_rt_stats(rtsf, [l1f, macf])
|
||||
self.assertTrue(status)
|
||||
self.assertEqual(s['Title'], "Processing Time (us) from datalog_rt_stats.100.2x2.yaml")
|
||||
self.assertEqual(s['ColNames'], ["Metric", "Average; Max; Count", "Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)"])
|
||||
|
||||
@@ -136,7 +136,7 @@ class TestDeploymentMethods(unittest.TestCase):
|
||||
|
||||
def test_create_workspace(self):
|
||||
self.cont.workspace = tempfile.mkdtemp()
|
||||
self.cont.repository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git"
|
||||
self.cont.repository = "https://github.com/duranta-project/openairinterface5g.git"
|
||||
self.cont.branch = "develop"
|
||||
ws = self.cont.Create_Workspace(self.node, self.html)
|
||||
with cls_cmd.LocalCmd() as cmd:
|
||||
|
||||
@@ -8,13 +8,13 @@ rm -f ${file}
|
||||
cd ../../
|
||||
python3 main.py \
|
||||
--mode=InitiateHtml \
|
||||
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
|
||||
--repository=https://github.com/duranta-project/openairinterface5g.git \
|
||||
--branch=${branch} \
|
||||
--XMLTestFile=tests/test-runner/test.xml
|
||||
|
||||
python3 main.py \
|
||||
--mode=TesteNB \
|
||||
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
|
||||
--repository=https://github.com/duranta-project/openairinterface5g.git \
|
||||
--branch=${branch} \
|
||||
--ranAllowMerge=true \
|
||||
--targetBranch=develop \
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<desc>Analyze Real-Time Stats</desc>
|
||||
<stats_cfg>datalog_rt_stats.100.4x4.fhi72.yaml</stats_cfg>
|
||||
<service>oai-gnb</service>
|
||||
<stats_file>/opt/oai-gnb/nrL1_stats.log /opt/oai-gnb/nrMAC_stats.log</stats_file>
|
||||
<node>bulbul</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<desc>Analyze Real-Time Stats</desc>
|
||||
<stats_cfg>datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml</stats_cfg>
|
||||
<service>oai-gnb</service>
|
||||
<stats_file>/opt/oai-gnb/nrL1_stats.log /opt/oai-gnb/nrMAC_stats.log</stats_file>
|
||||
<node>cacofonix</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
85
ci-scripts/xml_files/monolithic_2step_ra_gnb_rfsim.xml
Normal file
85
ci-scripts/xml_files/monolithic_2step_ra_gnb_rfsim.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
|
||||
|
||||
<testCaseList>
|
||||
<htmlTabRef>monolithic_2step_ra_gnb_rfsim</htmlTabRef>
|
||||
<htmlTabName>Monolithic 2-Step RA gNB rfsim</htmlTabName>
|
||||
<htmlTabIcon>wrench</htmlTabIcon>
|
||||
|
||||
<testCase>
|
||||
<class>Pull_Local_Registry</class>
|
||||
<desc>Pull Images from Local Registry</desc>
|
||||
<node>localhost</node>
|
||||
<images>oai-gnb-asan oai-nr-ue-asan</images>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>localhost</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy OAI gNB</desc>
|
||||
<node>localhost</node>
|
||||
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
|
||||
<services>mysql oai-amf oai-smf oai-upf oai-ext-dn</services>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy OAI NR-UE</desc>
|
||||
<node>localhost</node>
|
||||
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
|
||||
<services>oai-gnb oai-nr-ue</services>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach OAI UE (Wait for IP)</desc>
|
||||
<id>rfsim5g_ue</id>
|
||||
<node>localhost</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Ping</class>
|
||||
<desc>Ping ext-dn from NR-UE</desc>
|
||||
<id>rfsim5g_ue</id>
|
||||
<node>localhost</node>
|
||||
<svr_id>rfsim5g_ext_dn</svr_id>
|
||||
<svr_node>localhost</svr_node>
|
||||
<ping_args>-c 20 -i0.2</ping_args>
|
||||
<ping_packetloss_threshold>0</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Ping</class>
|
||||
<desc>Ping NR-UE from ext-dn</desc>
|
||||
<id>rfsim5g_ext_dn</id>
|
||||
<node>localhost</node>
|
||||
<svr_id>rfsim5g_ue</svr_id>
|
||||
<svr_node>localhost</svr_node>
|
||||
<ping_args>-c 20 -i0.2</ping_args>
|
||||
<ping_packetloss_threshold>0</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Undeploy_Object</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Undeploy all OAI 5G stack</desc>
|
||||
<node>localhost</node>
|
||||
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
|
||||
<analysis>
|
||||
<services>oai-gnb=RetxCheck=10,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
|
||||
</analysis>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Clean_Test_Server_Images</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Clean Test Images on Test Server</desc>
|
||||
<node>localhost</node>
|
||||
<images>oai-gnb-asan oai-nr-ue-asan</images>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
82
ci-scripts/xml_files/phytest_vrtsim_40MHz.xml
Normal file
82
ci-scripts/xml_files/phytest_vrtsim_40MHz.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
|
||||
|
||||
<testCaseList>
|
||||
<htmlTabRef>PHY-Test-40-vrtsim</htmlTabRef>
|
||||
<htmlTabName>Timing phytest 40 MHz with vrtsim</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
|
||||
<testCase>
|
||||
<class>Pull_Cluster_Image</class>
|
||||
<desc>Pull Images from Cluster</desc>
|
||||
<images>oai-gnb oai-nr-ue</images>
|
||||
<node>caracal</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>caracal</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Initialize gNB</desc>
|
||||
<node>caracal</node>
|
||||
<yaml_path>ci-scripts/yaml_files/phytest_vrtsim_40MHz</yaml_path>
|
||||
<services>oai-gnb</services>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Initialize UE</desc>
|
||||
<node>caracal</node>
|
||||
<yaml_path>ci-scripts/yaml_files/phytest_vrtsim_40MHz</yaml_path>
|
||||
<services>oai-nr-ue</services>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>AnalyzeRTStats_Object</class>
|
||||
<desc>Analyze Real-Time Stats on gNB</desc>
|
||||
<always_exec>true</always_exec>
|
||||
<stats_cfg>datalog_rt_stats.gnb.40.vrtsim.yaml</stats_cfg>
|
||||
<service>oai-gnb</service>
|
||||
<stats_file>/opt/oai-gnb/nrL1_stats.log /opt/oai-gnb/nrMAC_stats.log</stats_file>
|
||||
<node>caracal</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>AnalyzeRTStats_Object</class>
|
||||
<desc>Analyze Real-Time Stats on UE</desc>
|
||||
<always_exec>true</always_exec>
|
||||
<stats_cfg>datalog_rt_stats.ue.40.vrtsim.yaml</stats_cfg>
|
||||
<service>oai-nr-ue</service>
|
||||
<stats_file>/opt/oai-nr-ue/nrL1_UE_stats-0.log</stats_file>
|
||||
<node>caracal</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Undeploy_Object</class>
|
||||
<node>caracal</node>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Terminate gNB</desc>
|
||||
<yaml_path>ci-scripts/yaml_files/phytest_vrtsim_40MHz</yaml_path>
|
||||
<analysis>
|
||||
<services>oai-gnb=EndsWithBye oai-nr-ue=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>caracal</node>
|
||||
<images>oai-nr-ue oai-gnb</images>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -1,20 +1,6 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr style="border-collapse: collapse; border: none;">
|
||||
<td style="border-collapse: collapse; border: none;">
|
||||
<a href="http://www.openairinterface.org/">
|
||||
<img src="../../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
|
||||
</img>
|
||||
</a>
|
||||
</td>
|
||||
<td style="border-collapse: collapse; border: none; vertical-align: center;">
|
||||
<b><font size = "5">OAI Full Stack 4G-LTE RF simulation with containers</font></b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
This page is only valid for an `Ubuntu 22` host.
|
||||
OAI Full Stack 4G-LTE RF simulation with containers
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
|
||||
@@ -1,22 +1,6 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr style="border-collapse: collapse; border: none;">
|
||||
<td style="border-collapse: collapse; border: none;">
|
||||
<a href="http://www.openairinterface.org/">
|
||||
<img src="../../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
|
||||
</img>
|
||||
</a>
|
||||
</td>
|
||||
<td style="border-collapse: collapse; border: none; vertical-align: center;">
|
||||
<b><font size = "5">OAI Full Stack 5G-NR RF simulation with containers</font></b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
This page is only valid for an `Ubuntu 22` host.
|
||||
|
||||
**NOTE: this version (2023-01-27) has been updated for the `v1.5.0` version of the `OAI 5G CN`.**
|
||||
OAI Full Stack 5G-NR RF simulation with containers
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ ru_sdr:
|
||||
srate: 23.04
|
||||
tx_gain: 25
|
||||
rx_gain: 25
|
||||
amplitude_control:
|
||||
tx_gain_backoff: 22
|
||||
|
||||
cell_cfg:
|
||||
dl_arfcn: 632628
|
||||
@@ -42,8 +44,8 @@ cell_cfg:
|
||||
nof_cell_csi_res: 0
|
||||
|
||||
log:
|
||||
filename: gnb.log
|
||||
all_level: debug
|
||||
filename: stdout
|
||||
all_level: info
|
||||
|
||||
pcap:
|
||||
mac_enable: false
|
||||
|
||||
@@ -20,6 +20,8 @@ ru_sdr:
|
||||
srate: 61.44
|
||||
tx_gain: 25
|
||||
rx_gain: 25
|
||||
amplitude_control:
|
||||
tx_gain_backoff: 22
|
||||
|
||||
cell_cfg:
|
||||
dl_arfcn: 632628
|
||||
@@ -44,8 +46,8 @@ cell_cfg:
|
||||
nof_cell_csi_res: 0
|
||||
|
||||
log:
|
||||
filename: gnb.log
|
||||
all_level: debug
|
||||
filename: stdout
|
||||
all_level: info
|
||||
|
||||
pcap:
|
||||
mac_enable: false
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
services:
|
||||
mysql:
|
||||
container_name: "rfsim5g-mysql"
|
||||
image: mysql:9.6
|
||||
init: true
|
||||
volumes:
|
||||
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
|
||||
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- MYSQL_DATABASE=oai_db
|
||||
- MYSQL_USER=test
|
||||
- MYSQL_PASSWORD=test
|
||||
- MYSQL_ROOT_PASSWORD=linux
|
||||
healthcheck:
|
||||
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
|
||||
start_period: 10s
|
||||
start_interval: 500ms
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.131
|
||||
oai-amf:
|
||||
container_name: "rfsim5g-oai-amf"
|
||||
image: oaisoftwarealliance/oai-amf:v2.2.1
|
||||
environment:
|
||||
- TZ=Europe/paris
|
||||
volumes:
|
||||
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml
|
||||
depends_on:
|
||||
- mysql
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.132
|
||||
oai-smf:
|
||||
container_name: "rfsim5g-oai-smf"
|
||||
image: oaisoftwarealliance/oai-smf:v2.2.1
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
|
||||
depends_on:
|
||||
- oai-amf
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.133
|
||||
oai-upf:
|
||||
container_name: "rfsim5g-oai-upf"
|
||||
image: oaisoftwarealliance/oai-upf:v2.2.1
|
||||
init: true
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml
|
||||
depends_on:
|
||||
- oai-smf
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
cap_drop:
|
||||
- ALL
|
||||
privileged: true
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.134
|
||||
interface_name: eth0
|
||||
traffic_net:
|
||||
ipv4_address: 192.168.72.134
|
||||
interface_name: eth1
|
||||
oai-ext-dn:
|
||||
privileged: true
|
||||
container_name: rfsim5g-oai-ext-dn
|
||||
image: oaisoftwarealliance/trf-gen-cn5g:latest
|
||||
init: true
|
||||
entrypoint: /bin/bash -c \
|
||||
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
|
||||
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
|
||||
depends_on:
|
||||
- oai-upf
|
||||
networks:
|
||||
traffic_net:
|
||||
ipv4_address: 192.168.72.135
|
||||
healthcheck:
|
||||
test: /bin/bash -c "ping -c 2 192.168.72.134"
|
||||
start_period: 10s
|
||||
start_interval: 500ms
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
oai-gnb:
|
||||
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop}
|
||||
container_name: rfsim5g-oai-gnb
|
||||
cap_drop:
|
||||
- ALL
|
||||
environment:
|
||||
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
|
||||
ASAN_OPTIONS: detect_leaks=0
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.140
|
||||
volumes:
|
||||
- ../../conf_files/gnb.sa.band78.106prb.usrpb210.RA_2-Step.conf:/opt/oai-gnb/etc/gnb.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-softmodem"
|
||||
start_period: 10s
|
||||
start_interval: 500ms
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
oai-nr-ue:
|
||||
image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
|
||||
container_name: rfsim5g-oai-nr-ue
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- NET_ADMIN # for interface bringup
|
||||
- NET_RAW # for ping
|
||||
environment:
|
||||
USE_ADDITIONAL_OPTIONS: --rfsim
|
||||
--rfsimulator.[0].serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
|
||||
-C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78
|
||||
ASAN_OPTIONS: detect_leaks=0
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
volumes:
|
||||
- ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf
|
||||
depends_on:
|
||||
- oai-gnb
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.150
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-uesoftmodem"
|
||||
start_period: 10s
|
||||
start_interval: 500ms
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
networks:
|
||||
public_net:
|
||||
driver: bridge
|
||||
name: rfsim5g-oai-public-net
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 192.168.71.128/26
|
||||
driver_opts:
|
||||
com.docker.network.bridge.name: "rfsim5g-public"
|
||||
traffic_net:
|
||||
driver: bridge
|
||||
name: rfsim5g-oai-traffic-net
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 192.168.72.128/26
|
||||
driver_opts:
|
||||
com.docker.network.bridge.name: "rfsim5g-traffic"
|
||||
@@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
services:
|
||||
oai-gnb:
|
||||
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop}
|
||||
container_name: rfsim5g-oai-gnb
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- SYS_NICE
|
||||
environment:
|
||||
USE_ADDITIONAL_OPTIONS: --phy-test --device.name vrtsim --vrtsim.role server -q -U 768 -T 106 -t 23 -D 127 -m 28 -M 106 --log_config.global_log_options level,nocolor,time
|
||||
ASAN_OPTIONS: detect_leaks=0
|
||||
ipc: host
|
||||
volumes:
|
||||
- ../../conf_files/gnb.band79.106prb.vrtsim.phytest-dora.conf:/opt/oai-gnb/etc/gnb.conf
|
||||
- rrc.config:/opt/oai-gnb/
|
||||
- tmp_data:/tmp/
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-softmodem"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
oai-nr-ue:
|
||||
image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
|
||||
container_name: rfsim5g-oai-nr-ue
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- SYS_NICE
|
||||
environment:
|
||||
USE_ADDITIONAL_OPTIONS: --phy-test --reconfig-file etc/rrc/reconfig.raw --rbconfig-file etc/rrc/rbconfig.raw --device.name vrtsim --vrtsim.role client -q --log_config.global_log_options level,nocolor,time
|
||||
ASAN_OPTIONS: detect_leaks=0
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
ipc: host
|
||||
volumes:
|
||||
- ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf
|
||||
- rrc.config:/opt/oai-nr-ue/etc/rrc/
|
||||
- tmp_data:/tmp/
|
||||
depends_on:
|
||||
- oai-gnb
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-uesoftmodem"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
rrc.config:
|
||||
tmp_data:
|
||||
@@ -1,18 +1,6 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr style="border-collapse: collapse; border: none;">
|
||||
<td style="border-collapse: collapse; border: none;">
|
||||
<a href="http://www.openairinterface.org/">
|
||||
<img src="../../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
|
||||
</img>
|
||||
</a>
|
||||
</td>
|
||||
<td style="border-collapse: collapse; border: none; vertical-align: center;">
|
||||
<b><font size = "5">OAI O-RAN 7.2 Front-haul Docker Compose</font></b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
OAI O-RAN 7.2 Front-haul Docker Compose
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -201,6 +201,7 @@ function main() {
|
||||
shift;;
|
||||
--nrRU)
|
||||
NRRU=1
|
||||
CMAKE_CMD="$CMAKE_CMD -DOAI_RU_FRONTHAUL=ON"
|
||||
TARGET_LIST="$TARGET_LIST nr-oru"
|
||||
echo_info "Will compile NR O-RU"
|
||||
shift;;
|
||||
|
||||
@@ -465,7 +465,6 @@ install_asn1c_from_source(){
|
||||
echo_info "\nInstalling ASN1."
|
||||
$SUDO $INSTALLER -y install bison flex
|
||||
$SUDO rm -rf /tmp/asn1c
|
||||
# GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/asn1c.git /tmp/asn1c
|
||||
git clone https://github.com/mouse07410/asn1c /tmp/asn1c
|
||||
cd /tmp/asn1c
|
||||
#git checkout vlm_master
|
||||
|
||||
@@ -39,8 +39,9 @@ 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 */
|
||||
* - Pre-configured 5QI values: pre-configured in the AN (not in Table 5.7.4-1)
|
||||
* - Dynamically assigned 5QI values: require signaling of QoS characteristics as part of QoS profile
|
||||
* OAI implements standardized non-dynamic 5QI only. */
|
||||
#define MIN_FIVEQI 0
|
||||
#define MAX_STANDARDIZED_FIVEQI 90
|
||||
#define MAX_FIVEQI 255
|
||||
|
||||
@@ -9,5 +9,3 @@ The configuration module provides an api that other oai components can use to ge
|
||||
* [runtime usage](config/rtusage.md)
|
||||
* [developer usage](config/devusage.md)
|
||||
* [module architecture](config/arch.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -14,9 +14,9 @@ As a developer you may need to look at these sections:
|
||||
|
||||
Whatever your need is, configuration module usage examples can be found in oai sources:
|
||||
* complex example, using all the configuration module functionalities, including parameter checking:
|
||||
[NB-IoT configuration code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/ENB_APP/NB_IoT_config.c) and [NB-IoT configuration include file](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/ENB_APP/NB_IoT_paramdef.h)
|
||||
* very simple example, just reading a parameter set corresponding to a dedicated section: the telnetsrv_autoinit function in [common/utils/telnetsrv/telnetsrv.c, around line 726](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/telnetsrv/telnetsrv.c#L726)
|
||||
* an example with run-time definition of parameters, in the logging sub-system: the log_getconfig function at the top of [openair2/UTIL/LOG/log.c](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/UTIL/LOG/log.c)
|
||||
[NB-IoT configuration code](../../../../openair2/ENB_APP/NB_IoT_config.c) and [NB-IoT configuration include file](../../../../openair2/ENB_APP/NB_IoT_paramdef.h)
|
||||
* very simple example, just reading a parameter set corresponding to a dedicated section: the telnetsrv_autoinit function in [common/utils/telnetsrv/telnetsrv.c, around line 726](../../../../common/utils/telnetsrv/telnetsrv.c)
|
||||
* an example with run-time definition of parameters, in the logging sub-system: the log_getconfig function at the top of [openair2/UTIL/LOG/log.c](../../../../common/utils/LOG/log.c)
|
||||
|
||||
|
||||
[Configuration module home](../config.md)
|
||||
|
||||
@@ -82,7 +82,7 @@ for(int i=0 ; i < sizeof(someoptions)/sizeof(paramdesc_t) ; i ++) {
|
||||
}
|
||||
....
|
||||
```
|
||||
When you need a specific verification algorithm, you can provide your own verification function and use it in place of the available ones, in the `checkedparam_t` union. If no existing structure definition match your need, you can enhance the configuration module. You then have to add a new verification function in https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_userapi.c and add a new structure definition in the `checkedparam_t` type defined in https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h
|
||||
When you need a specific verification algorithm, you can provide your own verification function and use it in place of the available ones, in the `checkedparam_t` union. If no existing structure definition match your need, you can enhance the configuration module. You then have to add a new verification function in ../../../../../common/config/config_userapi.c and add a new structure definition in the `checkedparam_t` type defined in ../../../../../common/config/config_paramdesc.h
|
||||
|
||||
[Configuration module developer main page](../../config/devusage.md)
|
||||
[Configuration module home](../../config.md)
|
||||
|
||||
@@ -45,7 +45,7 @@ int config_libconfig_getlist(paramlist_def_t *ParamList, paramdef_t *params, int
|
||||
|
||||
## utility functions and macros
|
||||
|
||||
The configuration module also defines APIs to access the `paramdef_t` and `configmodule_interface_t` fields. They are listed in the configuration module [include file `common/config/config_userapi.h`](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_userapi.h)
|
||||
The configuration module also defines APIs to access the `paramdef_t` and `configmodule_interface_t` fields. They are listed in the configuration module [include file `common/config/config_userapi.h`](../../../../common/config/config_userapi.h)
|
||||
|
||||
[Configuration module developer main page](../../config/devusage.md)
|
||||
[Configuration module home](../../config.md)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
# `paramdef_t`structure
|
||||
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L103). This structure is used by developers to describe parameters and by the configuration module to return parameters value. A pointer to a `paramdef_t` array is passed to `config_get` and `config_getlist` calls to instruct the configuration module what parameters it should read.
|
||||
It is defined in include file [ common/config/config_paramdesc.h ](../../../../../common/config/config_paramdesc.h#L103). This structure is used by developers to describe parameters and by the configuration module to return parameters value. A pointer to a `paramdef_t` array is passed to `config_get` and `config_getlist` calls to instruct the configuration module what parameters it should read.
|
||||
|
||||
| Fields | Description | I/O |
|
||||
|:-----------|:------------------------------------------------------------------|----:|
|
||||
@@ -32,7 +32,7 @@ It is defined in include file [ common/config/config_paramdesc.h ](https://gitla
|
||||
|
||||
|
||||
# `paramlist_def_t`structure
|
||||
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L160).
|
||||
It is defined in include file [ common/config/config_paramdesc.h ](../../../../../common/config/config_paramdesc.h#L160).
|
||||
It is used as an argument to `config_getlist` calls, to get values of multiple occurrences of group of parameters.
|
||||
|
||||
| Fields | Description | I/O |
|
||||
@@ -42,7 +42,7 @@ It is used as an argument to `config_getlist` calls, to get values of multiple o
|
||||
| `numelt` | Number of items in the `paramarray` field | O |
|
||||
|
||||
# `checkedparam_t` union
|
||||
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L62).
|
||||
It is defined in include file [ common/config/config_paramdesc.h ](../../../../../common/config/config_paramdesc.h#L62).
|
||||
This union of structures is used to provide a parameter checking mechanism. Each `paramdef_t` instance may include a pointer to a `checkedparam_t`structure which is then used by the configuration module to check the value it got from the config source.
|
||||
Each structure in the union provides one parameter verification method, which returns `-1` when the verification fails. Currently the following structures are defined in the `checkedparam_t` union:
|
||||
|
||||
|
||||
@@ -45,10 +45,18 @@
|
||||
|
||||
#define NR_MAX_NB_PDU_SESSIONS (256)
|
||||
|
||||
#define NR_MAX_NB_ALLOWED_SNSSAI (8) /* Maximum number of allowed S-NSSAI in TS 38.413 */
|
||||
|
||||
#define MAX_DRBS_PER_UE (32) /* Maximum number of Data Radio Bearers per UE
|
||||
* defined for NGAP in TS 38.413 - maxnoofDRBs */
|
||||
#define MAX_PDUS_PER_UE (8) /* Maximum number of PDU Sessions per UE */
|
||||
|
||||
/** Maximum value of nrofPDCCH-MonitoringOccasionPerSSB-InPO-r16 (TS 38.331 PCCH-Config) */
|
||||
#define NR_PCCH_MAX_MO_PER_SSB_IN_PO 4
|
||||
|
||||
/** Maximum number of Paging Occasions per Paging Frame (TS 38.331 PCCH-Config) */
|
||||
#define NR_PCCH_MAX_PO 4
|
||||
|
||||
#define NB_RB_MBMS_MAX (29 * 16) /* 29 = LTE_maxSessionPerPMCH + 16 = LTE_maxServiceCount from LTE_asn_constant.h */
|
||||
|
||||
#define NB_RAB_MAX 11 /* from LTE_maxDRB in LTE_asn_constant.h */
|
||||
@@ -71,6 +79,9 @@
|
||||
// SDAP
|
||||
#define MAX_QOS_FLOWS 64
|
||||
|
||||
/** Maximum number of PagingRecords in one PCCH Paging message (TS 38.331) */
|
||||
#define NR_PCCH_MAX_PAGING_RECORDS 32
|
||||
|
||||
// SDAP/5G NAS NOS1
|
||||
#define DEFAULT_NOS1_PDU_ID 10
|
||||
|
||||
|
||||
@@ -15,5 +15,3 @@ The main drawback is a performance cost at init time, when loading libraries.
|
||||
* [runtime usage](loader/rtusage.md)
|
||||
* [developer usage](loader/devusage.md)
|
||||
* [module architecture](loader/arch.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
# loader source files
|
||||
|
||||
The oai shared library loader is implemented in two source files, located in [common/utils](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils)
|
||||
1. [load_module_shlib.c](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/load_module_shlib.c) contains the loader implementation
|
||||
1. [load_module_shlib.h](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/load_module_shlib.h) is the loader include file containing both private and public data type definitions. It also contain API prototypes.
|
||||
The oai shared library loader is implemented in two source files, located in `common/utils/`:
|
||||
1. [load_module_shlib.c](../../load_module_shlib.c) contains the loader implementation
|
||||
1. [load_module_shlib.h](../../load_module_shlib.h) is the loader include file containing both private and public data type definitions. It also contain API prototypes.
|
||||
|
||||
[loader home page](../loader.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
Loader API is defined in the [common/utils/load_module_shlib.h](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/load_module_shlib.h) include file.
|
||||
Loader API is defined in the [common/utils/load_module_shlib.h](../../load_module_shlib.h) include file.
|
||||
```c
|
||||
int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf)
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
# `loader_shlibfunc_t`structure
|
||||
It is defined in include file [ common/util/load_module_shlib.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/load_module_shlib.h#L38). This structure is used to list the symbols that should be searched by the loader when calling the `load_module_shlib` function.
|
||||
It is defined in include file [ common/util/load_module_shlib.h ](../../load_module_shlib.h#L38). This structure is used to list the symbols that should be searched by the loader when calling the `load_module_shlib` function.
|
||||
|
||||
| Fields | Description | I/O |
|
||||
|:-----------|:------------------------------------------------------------------|----:|
|
||||
|
||||
@@ -22,7 +22,7 @@ these macros are used in place of the printf C function. The additionnal ***comp
|
||||
| LOG_D | D | 4 | debug |
|
||||
| LOG_T | T | 5 | trace |
|
||||
|
||||
component list is defined as an `enum` in [log.h](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.h). A new component can be defined by adding an item in this type, it must also be defined in the T tracer [T_messages.txt ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/T/T_messages.txt).
|
||||
component list is defined as an `enum` in [log.h](../log.h). A new component can be defined by adding an item in this type, it must also be defined in the T tracer [T_messages.txt ](../../T/T_messages.txt).
|
||||
|
||||
Most oai sources are including LOG macros.
|
||||
|
||||
@@ -42,7 +42,6 @@ if ( LOG_DEBUGFLAG(<flag>) {
|
||||
......................
|
||||
}
|
||||
```
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c#L396)
|
||||
|
||||
#### memory dump macros
|
||||
```C
|
||||
@@ -60,7 +59,6 @@ LOG_M(.............
|
||||
log_dump(...
|
||||
}
|
||||
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/LTE_TRANSPORT/prach.c#L205)
|
||||
#### matlab format dump
|
||||
```C
|
||||
LOG_M(file, vector, data, len, dec, format)
|
||||
@@ -74,8 +72,7 @@ LOG_M(file, vector, data, len, dec, format)
|
||||
| dec| int | length of each data item.Interpretation depends on format|
|
||||
|format| int | defines the type of data to be dumped|
|
||||
|
||||
This macro can be used to dump a buffer in a format that can be used for analyze via tools like matlab or octave. **It must be surrounded by LOG_DEBUGFLAG or LOG_DUMPFLAG macros, to prevent the dump to be built unconditionally.** The LOG_M macro points to the `write_file_matlab` function implemented in [log.c](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.c). **This function should be revisited for more understandable implementation and ease of use (format parameter ???)**
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/LTE_TRANSPORT/prach.c#L205)
|
||||
This macro can be used to dump a buffer in a format that can be used for analyze via tools like matlab or octave. **It must be surrounded by LOG_DEBUGFLAG or LOG_DUMPFLAG macros, to prevent the dump to be built unconditionally.** The LOG_M macro points to the `write_file_matlab` function implemented in [log.c](../log.c). **This function should be revisited for more understandable implementation and ease of use (format parameter ???)**
|
||||
|
||||
#### hexadecimal format dump
|
||||
```C
|
||||
@@ -86,15 +83,14 @@ dumps a memory region if the corresponding debug flag `f` is set as explained he
|
||||
|argument| type| description |
|
||||
|:-----------|:-------|-----------------:|
|
||||
| c | int, component id (in `comp_name_t` enum)| used to print the message, as specified by the s and x arguments |
|
||||
|f |int |flag used to filter the dump depending on the logs configuration. flag list is defined by the LOG_MASKMAP_INIT macro in [log.h](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.h) |
|
||||
|f |int |flag used to filter the dump depending on the logs configuration. flag list is defined by the LOG_MASKMAP_INIT macro in [log.h](../log.h) |
|
||||
|b| void *| pointer to the memory to be dumpped |
|
||||
|s | int | length of the data to be dumpped in char|
|
||||
| x...| printf format and arguments| text string to be printed at the top of the dump|
|
||||
|
||||
This macro can be used to conditionaly dump a buffer, bytes by bytes, giving the integer value of each byte in hexadecimal form.
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/RRC/LTE/rrc_eNB.c#L1181)
|
||||
|
||||
This macro points to the `log_dump` function, implemented in [log.c](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.c). This function can also dump buffers containing `double` data via the LOG_UDUMPMSG macro
|
||||
This macro points to the `log_dump` function, implemented in [log.c](../log.c). This function can also dump buffers containing `double` data via the LOG_UDUMPMSG macro
|
||||
|
||||
```C
|
||||
LOG_UDUMPMSG(c, b, s, f, x...)
|
||||
@@ -107,8 +103,5 @@ LOG_UDUMPMSG(c, b, s, f, x...)
|
||||
|f| int | format of dumped data LOG_DUMP_CHAR or LOG_DUMP_DOUBLE|
|
||||
| x...| printf format and arguments| text string to be printed at the top of the dump|
|
||||
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/SIMULATION/LTE_PHY/dlsim.c#L1974)
|
||||
|
||||
[logging facility developer main page](devusage.md)
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -11,4 +11,3 @@ The logging facility doesn't create any thread, all api's are executed in the co
|
||||
Data used by the logging utility are defined by the `log_t` structure which is allocated at init time, when calling the `logInit` function.
|
||||
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -39,7 +39,7 @@ CLEAR_LOG_DUMP(flag)
|
||||
```
|
||||
These macros are used to set or clear the corresponding bit flag, trigerring the activation or un-activation of conditional code or memory dumps generation.
|
||||
|
||||
Example of using the logging utility APIs can be found, for initialization and cleanup, in [lte-softmodem.c](../../../../targets/RT/USER/lte-softmodem.c) and in the [telnet server log command implementation](../../telnetsrv/telnetsrv_proccmd.c) for a complete access to the logging facility features.
|
||||
Example of using the logging utility APIs can be found, for initialization and cleanup, in [lte-softmodem.c](../../../../executables/lte-softmodem.c) and in the [telnet server log command implementation](../../telnetsrv/telnetsrv_proccmd.c) for a complete access to the logging facility features.
|
||||
|
||||
#### components and debug flags definitions
|
||||
|
||||
@@ -48,4 +48,3 @@ To add a flag than can then be used for adding conditional code or memory dumps
|
||||
|
||||
[logging facility developer main page](devusage.md)
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -18,5 +18,3 @@ By default, this facility is included at build-time and activated at run-time. T
|
||||
* [developer usage](devusage.md)
|
||||
* [module architecture](arch.md)
|
||||
* [lttng usage](lttng_logs.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -276,4 +276,3 @@ The telnet server includes a `log` command which can be used to dymically modify
|
||||
[telnet server ***softmodem log*** commands](../../telnetsrv/DOC/telnetlog.md)
|
||||
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -70,7 +70,8 @@ static __attribute__((always_inline)) inline int count_bits64(uint64_t v)
|
||||
|
||||
static __attribute__((always_inline)) inline int count_bits64_with_mask(uint64_t v, int start, int num)
|
||||
{
|
||||
uint64_t mask = ((1LL << num) - 1) << start;
|
||||
AssertFatal(start >= 0 && num > 0 && start + num <= 64, "Invalid range: start=%d num=%d for 64 bits mask\n", start, num);
|
||||
uint64_t mask = (num == 64 ? ~0ULL : (1ULL << num) - 1) << start;
|
||||
return count_bits64(v & mask);
|
||||
}
|
||||
|
||||
|
||||
@@ -257,11 +257,9 @@ uint32_t nr_timer_remaining_time(const NR_timer_t *timer);
|
||||
|
||||
int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_subframe);
|
||||
|
||||
static inline int get_num_dmrs(uint16_t dmrs_mask )
|
||||
static inline int get_num_dmrs(uint16_t dmrs_mask)
|
||||
{
|
||||
int num_dmrs=0;
|
||||
for (int i=0;i<16;i++) num_dmrs+=((dmrs_mask>>i)&1);
|
||||
return(num_dmrs);
|
||||
return __builtin_popcount(dmrs_mask);
|
||||
}
|
||||
|
||||
void warn_higher_threequarter_fs(const int n_rb, const int mu);
|
||||
|
||||
@@ -40,6 +40,9 @@ typedef struct ShmTDIQChannel_s {
|
||||
|
||||
ShmTDIQChannel *shm_td_iq_channel_create(const char *name, int num_tx_ant, int num_rx_ant)
|
||||
{
|
||||
// Unlink any stale shared memory segment first to ensure we start fresh and reclaim space
|
||||
shm_unlink(name);
|
||||
|
||||
// Create shared memory segment
|
||||
int fd = shm_open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
AssertFatal(fd != -1, "shm_open failed: %s\n", strerror(errno));
|
||||
@@ -96,29 +99,48 @@ ShmTDIQChannel *shm_td_iq_channel_connect(const char *name, int timeout_in_secon
|
||||
{
|
||||
// Create shared memory segment
|
||||
int fd = -1;
|
||||
while (timeout_in_seconds > 0 && fd == -1) {
|
||||
double timeout_in_uS = timeout_in_seconds * 1000000.0;
|
||||
while (timeout_in_uS > 0 && fd == -1) {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
fd = shm_open(name, O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (fd != -1) {
|
||||
break;
|
||||
}
|
||||
usleep(1000);
|
||||
timeout_in_uS -= 1000;
|
||||
}
|
||||
timeout_in_seconds--;
|
||||
if (fd == -1) {
|
||||
printf("Waiting for server to create shared memory segment\n");
|
||||
}
|
||||
}
|
||||
AssertFatal(fd != -1, "shm_open() failed: errno %d, %s", errno, strerror(errno));
|
||||
|
||||
// Map just the header first to wait for initialization
|
||||
ShmTDIQChannelData *shm_ptr = mmap(NULL, sizeof(ShmTDIQChannelData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (shm_ptr == MAP_FAILED) {
|
||||
perror("mmap header");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Wait until server initializes the segment
|
||||
while (timeout_in_uS > 0 && shm_ptr->magic != SHM_MAGIC_NUMBER) {
|
||||
usleep(1000);
|
||||
timeout_in_uS -= 1000;
|
||||
}
|
||||
AssertFatal(shm_ptr->magic == SHM_MAGIC_NUMBER, "Timeout waiting for server to initialize shared memory segment\n");
|
||||
|
||||
// Now that it's initialized, ftruncate has finished, so we can get the actual size
|
||||
struct stat buf;
|
||||
fstat(fd, &buf);
|
||||
size_t total_size = buf.st_size;
|
||||
|
||||
// Map shared memory segment to address space
|
||||
ShmTDIQChannelData *shm_ptr = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
// Unmap the temporary header mapping
|
||||
munmap(shm_ptr, sizeof(ShmTDIQChannelData));
|
||||
|
||||
// Map the entire shared memory segment
|
||||
shm_ptr = mmap(NULL, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (shm_ptr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
perror("mmap full");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -134,10 +156,6 @@ ShmTDIQChannel *shm_td_iq_channel_connect(const char *name, int timeout_in_secon
|
||||
channel->nb_rx_ant = channel->data->num_antennas_tx;
|
||||
printf("\033[38;5;208mnb_tx_ant, nb_rx_ant: %d, %d\n\033[0m", channel->nb_tx_ant, channel->nb_rx_ant);
|
||||
channel->type = IQ_CHANNEL_TYPE_CLIENT;
|
||||
while (shm_ptr->magic != SHM_MAGIC_NUMBER) {
|
||||
printf("Waiting for server to initialize shared memory\n");
|
||||
sleep(1);
|
||||
}
|
||||
close(fd);
|
||||
return channel;
|
||||
}
|
||||
@@ -238,7 +256,7 @@ int shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t
|
||||
fprintf(stderr, "Error: clock_gettime failed: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
ts.tv_sec += timeout_uS / 1000000; // Convert microseconds to seconds
|
||||
ts.tv_nsec += (timeout_uS % 1000000) * 1000; // Convert remaining microseconds to nanoseconds
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# code example of adding a command to the telnet server
|
||||
|
||||
The following example is extracted from [the oai `openair1/PHY/CODING/coding_load.c` file](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/CODING/coding_load.c).
|
||||
The following example is extracted from [the oai `openair1/PHY/CODING/coding_load.c` file](../../../../openair1/PHY/CODING/coding_load.c).
|
||||
|
||||
```c
|
||||
/*
|
||||
|
||||
@@ -21,7 +21,7 @@ The telnet server provides an API which can be used by any oai component to add
|
||||
|
||||
# telnet server source files
|
||||
|
||||
telnet server source files are located in [common/utils/telnetsrv](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/telnetsrv)
|
||||
telnet server source files are located in `common/utils/telnetsrv/`
|
||||
|
||||
1. [telnetsrv.c](../telnetsrv.c) contains the telnet server implementation, including the implementation of the `telnet` CLI command. This implementation is compatible with all softmodem executables and is in charge of loading any additional `libtelnetsrv_<app> .so` containing code specific to the running executables.
|
||||
1. [telnetsrv.h](../telnetsrv.h) is the telnet server include file containing both private and public data type definitions. It also contains API prototypes for functions that are used to register a new command in the server.
|
||||
|
||||
@@ -92,4 +92,3 @@ Connection closed by foreign host.
|
||||
|
||||
[oai telnetserver home](telnetsrv.md)
|
||||
[oai telnetserver usage home](telnetusage.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -6,5 +6,3 @@ The oai embedded telnet server is an optional monitoring and debugging tool. It
|
||||
* [Adding commands to the oai telnet server](telnetaddcmd.md)
|
||||
* [telnet server architecture ](telnetarch.md)
|
||||
* [on the telnet O1 module](telneto1.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_NGAP.h"
|
||||
#include "openair3/NGAP/ngap_gNB_ue_context.h"
|
||||
|
||||
#define TELNETSERVERCODE
|
||||
#include "telnetsrv.h"
|
||||
@@ -106,9 +108,50 @@ int rrc_gNB_trigger_release_all(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rrc_gNB_trigger_ue_context_release_req(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
UNUSED(debug);
|
||||
int ue_id = -1;
|
||||
|
||||
if (!buf) {
|
||||
ue_id = get_single_ue_id();
|
||||
if (ue_id < 1) {
|
||||
prnt("No UE found!\n");
|
||||
ERROR_MSG_RET("No UE found!\n");
|
||||
}
|
||||
} else {
|
||||
char *end = NULL;
|
||||
errno = 0;
|
||||
long parsed_id = strtol(buf, &end, 10);
|
||||
if (end == buf || *end != '\0' || errno != 0 || parsed_id < 1 || parsed_id >= 0xfffffe) {
|
||||
ERROR_MSG_RET("UE ID needs to be [1,0xfffffe]\n");
|
||||
}
|
||||
ue_id = parsed_id;
|
||||
}
|
||||
|
||||
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, ue_id);
|
||||
if (!ue_context_p) {
|
||||
ERROR_MSG_RET("No RRC UE context for ue_id %d\n", ue_id);
|
||||
}
|
||||
if (!ngap_get_ue_context(ue_id)) {
|
||||
ERROR_MSG_RET("No NGAP UE context for ue_id %d\n", ue_id);
|
||||
}
|
||||
|
||||
ngap_cause_t cause = {
|
||||
.type = NGAP_CAUSE_RADIO_NETWORK,
|
||||
.value = NGAP_CAUSE_RADIO_NETWORK_USER_INACTIVITY,
|
||||
};
|
||||
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(0, ue_context_p, cause);
|
||||
|
||||
prnt("Sent NGAP UE Context Release Request (user-inactivity) for ue_id %d\n", ue_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static telnetshell_cmddef_t rrc_cmds[] = {
|
||||
{"release_rrc", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_release},
|
||||
{"release_rrc_all", "", rrc_gNB_trigger_release_all},
|
||||
{"ctx_rel_req", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_ue_context_release_req},
|
||||
{"", "", NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -9,3 +9,7 @@ add_executable(test_fsn test_fsn.cpp)
|
||||
add_dependencies(tests test_fsn)
|
||||
target_link_libraries(test_fsn PRIVATE utils GTest::gtest)
|
||||
add_test(NAME test_fsn COMMAND ./test_fsn)
|
||||
|
||||
add_executable(test_bits test_bits.c)
|
||||
add_dependencies(tests test_bits)
|
||||
add_test(NAME test_bits COMMAND ./test_bits)
|
||||
|
||||
224
common/utils/tests/test_bits.c
Normal file
224
common/utils/tests/test_bits.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
#include <bits.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ── test harness ── */
|
||||
static int g_failures = 0;
|
||||
#define ARRSIZE 9
|
||||
#define BITS_PER_WORD 32
|
||||
#define TOTAL_BITS (ARRSIZE * BITS_PER_WORD)
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline void set_bit_in_array(uint32_t *arr, int bit_pos)
|
||||
{
|
||||
arr[bit_pos / BITS_PER_WORD] |= 1u << (bit_pos % BITS_PER_WORD);
|
||||
}
|
||||
|
||||
static void run_test(const char *name, int result, int expected)
|
||||
{
|
||||
if (result != expected) {
|
||||
fprintf(stderr, "FAIL [%s]: got %d, want %d\n", name, result, expected);
|
||||
g_failures++;
|
||||
} else {
|
||||
printf("PASS [%s]\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_get_first_bit_index_mask(void)
|
||||
{
|
||||
/* --- no bits set --- */
|
||||
uint32_t zeros[ARRSIZE] = {0};
|
||||
run_test("firstbit_all_zeros", get_first_bit_index_mask(zeros, ARRSIZE, 0, TOTAL_BITS), -1);
|
||||
|
||||
uint32_t arr[ARRSIZE];
|
||||
/* --- random single hit at a random position --- */
|
||||
int num_trials = 5;
|
||||
for (int t = 0; t < num_trials; t++) {
|
||||
int bit_pos = rand() % (TOTAL_BITS); /* random bit in [0, 128) */
|
||||
char test_name[64];
|
||||
snprintf(test_name, sizeof(test_name), "firstbit_single_hit_bit%d", bit_pos);
|
||||
memset(arr, 0, sizeof(arr));
|
||||
set_bit_in_array(arr, bit_pos);
|
||||
run_test(test_name, get_first_bit_index_mask(arr, ARRSIZE, 0, TOTAL_BITS), bit_pos);
|
||||
}
|
||||
|
||||
/* --- random multi-hit with random window --- */
|
||||
int multi_trials = 5;
|
||||
for (int t = 0; t < multi_trials; t++) {
|
||||
memset(arr, 0, sizeof(arr));
|
||||
int from_bit = rand() % (TOTAL_BITS);
|
||||
int num_bits = 1 + rand() % (TOTAL_BITS - from_bit); /* at least 1 bit wide */
|
||||
int window_end = from_bit + num_bits;
|
||||
int min_pos = -1;
|
||||
int num_bits_set = 5 + rand() % 20;
|
||||
for (int b = 0; b < num_bits_set; b++) {
|
||||
int bit_pos = from_bit + rand() % num_bits; /* confined to the window */
|
||||
set_bit_in_array(arr, bit_pos);
|
||||
if (min_pos == -1 || bit_pos < min_pos)
|
||||
min_pos = bit_pos;
|
||||
}
|
||||
/* put some bits outside the window to test they are ignored in some trial */
|
||||
if (from_bit > 0 && t % 2) {
|
||||
int bit_pos = rand() % from_bit; /* before the window */
|
||||
set_bit_in_array(arr, bit_pos);
|
||||
}
|
||||
if (window_end < TOTAL_BITS && t % 2) {
|
||||
int bit_pos = window_end + rand() % (TOTAL_BITS - window_end); /* after */
|
||||
set_bit_in_array(arr, bit_pos);
|
||||
}
|
||||
|
||||
char test_name[64];
|
||||
snprintf(test_name, sizeof(test_name), "firstbit_multi_hit_trial%d_from%d_num%d_min%d", t, from_bit, num_bits, min_pos);
|
||||
run_test(test_name, get_first_bit_index_mask(arr, ARRSIZE, from_bit, num_bits), min_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_get_last_bit_index(void)
|
||||
{
|
||||
/* --- no bits set --- */
|
||||
uint32_t zeros[ARRSIZE] = {0};
|
||||
run_test("lastbit_all_zeros", get_last_bit_index(zeros, ARRSIZE), -1);
|
||||
|
||||
uint32_t arr[ARRSIZE];
|
||||
|
||||
/* --- random single hit at a random position --- */
|
||||
int num_trials = 5;
|
||||
for (int t = 0; t < num_trials; t++) {
|
||||
int bit_pos = rand() % (TOTAL_BITS);
|
||||
char test_name[64];
|
||||
snprintf(test_name, sizeof(test_name), "lastbit_single_hit_bit%d", bit_pos);
|
||||
memset(arr, 0, sizeof(arr));
|
||||
set_bit_in_array(arr, bit_pos);
|
||||
run_test(test_name, get_last_bit_index(arr, ARRSIZE), bit_pos);
|
||||
}
|
||||
|
||||
/* --- random multi-hit: scattered bits, must return the maximum --- */
|
||||
int multi_trials = 5;
|
||||
for (int t = 0; t < multi_trials; t++) {
|
||||
memset(arr, 0, sizeof(arr));
|
||||
int max_pos = -1;
|
||||
int num_bits_set = 5 + rand() % 20;
|
||||
for (int b = 0; b < num_bits_set; b++) {
|
||||
int bit_pos = rand() % (TOTAL_BITS);
|
||||
set_bit_in_array(arr, bit_pos);
|
||||
if (bit_pos > max_pos)
|
||||
max_pos = bit_pos;
|
||||
}
|
||||
char test_name[64];
|
||||
snprintf(test_name, sizeof(test_name), "lastbit_multi_hit_trial%d_max%d", t, max_pos);
|
||||
run_test(test_name, get_last_bit_index(arr, ARRSIZE), max_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void fisher_yates_shuffle(int *positions, int total, int n)
|
||||
{
|
||||
/* partial shuffle: pick n distinct random positions from [0, total) */
|
||||
/* see https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm */
|
||||
for (int i = 0; i < n; i++) {
|
||||
int j = i + rand() % (total - i);
|
||||
int tmp = positions[i];
|
||||
positions[i] = positions[j];
|
||||
positions[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_count_bits(void)
|
||||
{
|
||||
uint32_t arr[ARRSIZE];
|
||||
|
||||
/* --- no bits set --- */
|
||||
uint32_t zeros[ARRSIZE] = {0};
|
||||
run_test("countbits_all_zeros", count_bits(zeros, ARRSIZE), 0);
|
||||
|
||||
/* --- all bits set --- */
|
||||
uint32_t all_set[ARRSIZE];
|
||||
memset(all_set, 0xFF, sizeof(all_set));
|
||||
run_test("countbits_all_set", count_bits(all_set, ARRSIZE), TOTAL_BITS);
|
||||
|
||||
/* --- random trials: set exactly N random bits, expect count N --- */
|
||||
int positions[TOTAL_BITS];
|
||||
for (int i = 0; i < TOTAL_BITS; i++)
|
||||
positions[i] = i;
|
||||
|
||||
int num_trials = 5;
|
||||
for (int t = 0; t < num_trials; t++) {
|
||||
memset(arr, 0, sizeof(arr));
|
||||
int n = 1 + rand() % TOTAL_BITS;
|
||||
fisher_yates_shuffle(positions, TOTAL_BITS, n);
|
||||
for (int i = 0; i < n; i++)
|
||||
set_bit_in_array(arr, positions[i]);
|
||||
char test_name[64];
|
||||
snprintf(test_name, sizeof(test_name), "countbits_trial%d_n%d", t, n);
|
||||
run_test(test_name, count_bits(arr, ARRSIZE), n);
|
||||
}
|
||||
}
|
||||
|
||||
void test_count_bits64_with_mask(void)
|
||||
{
|
||||
/* --- zero value --- */
|
||||
run_test("countbits64_zero_value", count_bits64_with_mask(0ULL, 0, 64), 0);
|
||||
|
||||
/* --- all bits set, full window --- */
|
||||
run_test("countbits64_all_set_full_window", count_bits64_with_mask(0xFFFFFFFFFFFFFFFFULL, 0, 64), 64);
|
||||
|
||||
/* --- all bits set, window filters correctly --- */
|
||||
run_test("countbits64_all_set_window_16_from_8", count_bits64_with_mask(0xFFFFFFFFFFFFFFFFULL, 8, 16), 16);
|
||||
|
||||
/* --- random trials: set exactly N bits within window, expect count N --- */
|
||||
int num_trials = 5;
|
||||
for (int t = 0; t < num_trials; t++) {
|
||||
int start = rand() % 64;
|
||||
int num = 1 + rand() % (64 - start);
|
||||
int window_end = start + num;
|
||||
|
||||
/* initialise positions to the window [start, start+num) */
|
||||
int positions[64];
|
||||
for (int i = 0; i < num; i++)
|
||||
positions[i] = start + i;
|
||||
|
||||
int n = 1 + rand() % num;
|
||||
fisher_yates_shuffle(positions, num, n);
|
||||
|
||||
uint64_t v = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
v |= 1ULL << positions[i];
|
||||
|
||||
/* put bits outside the window on odd trials */
|
||||
if (t % 2) {
|
||||
if (start > 0)
|
||||
v |= 1ULL << (rand() % start);
|
||||
if (window_end < 64)
|
||||
v |= 1ULL << (window_end + rand() % (64 - window_end));
|
||||
}
|
||||
|
||||
char test_name[64];
|
||||
snprintf(test_name, sizeof(test_name), "countbits64_trial%d_start%d_num%d_n%d", t, start, num, n);
|
||||
run_test(test_name, count_bits64_with_mask(v, start, num), n);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
srand((unsigned)time(NULL));
|
||||
test_get_first_bit_index_mask();
|
||||
test_get_last_bit_index();
|
||||
test_count_bits();
|
||||
test_count_bits64_with_mask();
|
||||
|
||||
if (g_failures > 0) {
|
||||
fprintf(stderr, "\n%d test(s) FAILED.\n", g_failures);
|
||||
return 1;
|
||||
}
|
||||
printf("\nAll tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -184,6 +184,18 @@ static bool set_if_flags(int sock_fd, const char *ifn, short flags)
|
||||
return true;
|
||||
}
|
||||
|
||||
short tuntap_set_up(const char *ifname, int sock_fd)
|
||||
{
|
||||
short flags = 0;
|
||||
if (!get_if_flags(sock_fd, ifname, &flags))
|
||||
return -1;
|
||||
|
||||
flags |= IFF_UP;
|
||||
if (!set_if_flags(sock_fd, ifname, flags))
|
||||
return -1;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool tun_config(const char* ifname, const char *ipv4, const char *ipv6)
|
||||
{
|
||||
@@ -215,10 +227,10 @@ bool tun_config(const char* ifname, const char *ipv4, const char *ipv6)
|
||||
close(sock_fd);
|
||||
}
|
||||
|
||||
// if successfully set IP addresses: set iterface up, disable ARP, no
|
||||
// multicast, point-to-point
|
||||
if (success)
|
||||
success = set_if_flags(sock_fd, ifname, (IFF_UP | IFF_NOARP | IFF_POINTOPOINT) & ~IFF_MULTICAST);
|
||||
if (success) {
|
||||
const short flags = tuntap_set_up(ifname, sock_fd);
|
||||
success = flags >= 0 && set_if_flags(sock_fd, ifname, (flags | IFF_NOARP | IFF_POINTOPOINT) & ~IFF_MULTICAST);
|
||||
}
|
||||
|
||||
if (success)
|
||||
LOG_A(OIP, "TUN Interface %s successfully configured, IPv4 %s, IPv6 %s\n", ifname, ipv4, ipv6);
|
||||
@@ -233,11 +245,11 @@ bool tap_config(const char* ifname)
|
||||
{
|
||||
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock_fd < 0) {
|
||||
LOG_E(UTIL, "Failed creating socket for interface management: %d, %s\n", errno, strerror(errno));
|
||||
LOG_E(UTIL, "tap_config: failed creating socket %d, %s\n", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = set_if_flags(sock_fd, ifname, IFF_UP);
|
||||
const bool success = tuntap_set_up(ifname, sock_fd) >= 0;
|
||||
|
||||
if (success)
|
||||
LOG_A(OIP, "TAP interface %s successfully configured\n", ifname);
|
||||
@@ -282,6 +294,7 @@ int tuntap_generate_ue_ifname(char *ifname, int flag, int instance_id, int pdu_s
|
||||
char pdu_session_string[10];
|
||||
snprintf(pdu_session_string, sizeof(pdu_session_string), "p%d", pdu_session_id);
|
||||
const char *basename = flag == IFF_TUN ? "oaitun_ue" : "oaitap_ue";
|
||||
// ifname: oaitun_ue<ue_id+1>[p<pdu_session_id>] when not default
|
||||
return snprintf(ifname, IFNAMSIZ, "%s%d%s", basename, instance_id + 1, pdu_session_id == -1 ? "" : pdu_session_string);
|
||||
}
|
||||
|
||||
@@ -295,7 +308,7 @@ void tuntap_destroy(const char *dev)
|
||||
}
|
||||
|
||||
// interface not up => down
|
||||
short flags;
|
||||
short flags = 0;
|
||||
bool success = get_if_flags(fd, dev, &flags);
|
||||
success = success && set_if_flags(fd, dev, flags & ~IFF_UP);
|
||||
if (success) {
|
||||
|
||||
@@ -90,4 +90,12 @@ int tuntap_alloc(int flag, const char *dev);
|
||||
*/
|
||||
void tuntap_destroy(const char *dev);
|
||||
|
||||
/*!
|
||||
* \brief Bring a TUN/TAP interface administratively up (IOCTL SIOCSIFFLAGS, set IFF_UP).
|
||||
* \param[in] ifname name of the interface
|
||||
* \param[in] sock_fd IPv4 SOCK_DGRAM fd for ioctl (opened by the caller)
|
||||
* \return interface flags with IFF_UP set, or -1 on failure
|
||||
*/
|
||||
short tuntap_set_up(const char *ifname, int sock_fd);
|
||||
|
||||
#endif /*TUN_IF_H_*/
|
||||
|
||||
@@ -5,5 +5,3 @@ The oai web server is an optional monitoring and debugging tool. Purpose is to g
|
||||
* [Using the web server](websrvuse.md)
|
||||
* [enhancing the webserver](websrvdev.md)
|
||||
* [web server architecture ](websrvarch.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
13
doc/5Gnas.md
13
doc/5Gnas.md
@@ -17,7 +17,7 @@ Key 5GS NAS messages:
|
||||
|
||||
## OAI Implementation Status
|
||||
|
||||
The following tables lists implemented NAS messages and whether there is an encoder or decoder function, and if a corresponding unit test exists.
|
||||
The following table lists implemented NAS messages and whether there is an encoder or decoder function, and if a corresponding unit test exists.
|
||||
|
||||
| Type | Message | Encoding | Decoding | Unit test |
|
||||
|-------|-------------------------------------------|----------|----------|------------|
|
||||
@@ -28,6 +28,9 @@ The following tables lists implemented NAS messages and whether there is an enco
|
||||
| 5GMM | Identity Response | yes | no | no |
|
||||
| 5GMM | Security Mode Complete | yes | no | no |
|
||||
| 5GMM | Uplink NAS Transport | yes | no | no |
|
||||
| 5GMM | Authentication Failure | yes | yes | yes |
|
||||
| 5GMM | Authentication Reject | yes | yes | yes |
|
||||
| 5GMM | Security Mode Reject | yes | yes | yes |
|
||||
| 5GMM | Registration Request | yes | yes | no |
|
||||
| 5GMM | Registration Accept | yes | yes | yes |
|
||||
| 5GMM | Registration Complete | yes | yes | no |
|
||||
@@ -45,10 +48,14 @@ The following tables lists implemented NAS messages and whether there is an enco
|
||||
|
||||
[openair3/NAS/NR_UE/5GS/fgs_nas_lib.c](../openair3/NAS/NR_UE/5GS/fgs_nas_lib.c):
|
||||
|
||||
* top-level encode/decode dispatch for NAS 5GMM/5GSM payloads
|
||||
* delegates message-specific encoding/decoding to `5GMM/MSG` and `5GSM/MSG`
|
||||
|
||||
[openair3/NAS/NR_UE/5GS/NR_NAS_defs.h](../openair3/NAS/NR_UE/5GS/NR_NAS_defs.h):
|
||||
|
||||
* encoding and decoding functions for 5G NAS message headers and payloads
|
||||
* relies on 5GMM/5GSM messages libs for payload encoding
|
||||
* 5GS NAS message types and security header definitions
|
||||
* shared NAS structures used by UE NAS handlers and encoders
|
||||
* prototypes for 5GMM header and security-header encode/decode, implementations in `fgs_nas_lib.c`
|
||||
|
||||
[openair3/NAS/NR_UE/5GS/fgs_nas_utils.h](../openair3/NAS/NR_UE/5GS/fgs_nas_utils.h):
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ The hardware on which we have tried this tutorial:
|
||||
- These are not minimum hardware requirements. This is the configuration of our
|
||||
servers. The NIC card should support hardware PTP time stamping.
|
||||
- Starting from tag
|
||||
[2025.w13](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/2025.w13?ref_type=tags)
|
||||
[2025.w13](https://github.com/duranta-project/openairinterface5g/releases/tag/2025.w13)
|
||||
of OAI, we are only testing with the Grace Hopper server.
|
||||
|
||||
PTP enabled switches and grandmaster clock we have tested with:
|
||||
@@ -60,7 +60,7 @@ To set up the L1 and install the components manually refer to this [instructions
|
||||
|
||||
**Note**:
|
||||
- To configure the Gigabyte server please refer to these
|
||||
[instructions](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/2025.w13/doc/Aerial_FAPI_Split_Tutorial.md)
|
||||
[instructions](https://github.com/duranta-project/openairinterface5g/blob/2025.w13/doc/Aerial_FAPI_Split_Tutorial.md)
|
||||
- The last release to support the Gigabyte server is **Aerial CUDA-Accelerated
|
||||
RAN 24-1**.
|
||||
|
||||
@@ -183,7 +183,7 @@ WantedBy=multi-user.target
|
||||
If it's not already cloned, the first step is to clone OAI repository
|
||||
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g/
|
||||
```
|
||||
|
||||
@@ -224,8 +224,7 @@ With the nvIPC sources in the project directory, the L2 docker image can be buil
|
||||
|
||||
In order to build the target image (`oai-gnb-aerial`), first you should build a
|
||||
common shared image (`ran-base`). For more information about `docker build`
|
||||
files please refer to this
|
||||
[tutorial](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/ARC1.7_integration/docker/README.md?ref_type=heads)
|
||||
files please refer to this [tutorial](../docker/README.md)
|
||||
|
||||
```bash
|
||||
~$ cd ~/openairinterface5g/
|
||||
@@ -238,26 +237,24 @@ files please refer to this
|
||||
|
||||
### Adapt the OAI-gNB configuration file to your system/workspace
|
||||
|
||||
Edit the [OAI gNB configuration file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf?ref_type=heads)
|
||||
Edit the [OAI gNB configuration file](../ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf)
|
||||
and check the following parameters:
|
||||
|
||||
* `gNBs` section
|
||||
* The PLMN section shall match the one defined in the AMF
|
||||
* To calculate the `absoluteFrequencySSB` and `dl_absoluteFrequencyPointA`,
|
||||
please follow these
|
||||
[instructions](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/gNB_frequency_setup.md)
|
||||
please follow these [instructions](./gNB_frequency_setup.md)
|
||||
* `amf_ip_address` shall be the correct AMF IP address in your system
|
||||
* `GNB_IPV4_ADDRESS_FOR_NG_AMF` shall match your DU N2 interface IP address
|
||||
* `GNB_IPV4_ADDRESS_FOR_NGU` shall match your DU N3 interface IP address
|
||||
|
||||
The default amf_ip_address:ipv4 value is 192.168.70.132, when installing the
|
||||
CN5G following [this
|
||||
tutorial](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_OAI_CN5G.md)
|
||||
CN5G following [this tutorial](./NR_SA_Tutorial_OAI_CN5G.md)
|
||||
Both `GNB_IPV4_ADDRESS_FOR_NG_AMF` and `GNB_IPV4_ADDRESS_FOR_NGU` need to be
|
||||
set to the IP address of the NIC referenced previously.
|
||||
|
||||
**Note**: If the Core Network is running on the same server, 3 cores should be
|
||||
allocated to it. 2 for the UPF and 1 for the all the remaining services as shown
|
||||
allocated to it. 2 for the UPF and 1 core shared between the remaining services as shown
|
||||
below.
|
||||
|
||||
```patch
|
||||
|
||||
@@ -51,7 +51,7 @@ PROJECT_BRIEF = "Full experimental OpenSource LTE and NR implementation
|
||||
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
|
||||
# the logo to the output directory.
|
||||
|
||||
PROJECT_LOGO = @CMAKE_SOURCE_DIR@/doc/images/oai_logo.png
|
||||
PROJECT_LOGO =
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
|
||||
@@ -145,6 +145,11 @@ These modes of operation are supported:
|
||||
- evalution of RSRP report
|
||||
- evaluation of CQI report
|
||||
- MAC scheduling of SR reception
|
||||
- Paging (PCCH/P-RNTI)
|
||||
- CN paging records queued
|
||||
- PF/PO dequeue from SIB1 PCCH-Config
|
||||
- PCCH encoded at the UE's PO
|
||||
- Type2 common search-space based P-RNTI PDCCH + PDSCH scheduling for PCCH
|
||||
- Intra-frequency handover
|
||||
- Inter-frequency handover
|
||||
- Measurement gaps are automatically computed at the DU if the CU has neighbor information and the configured
|
||||
@@ -230,9 +235,12 @@ These modes of operation are supported:
|
||||
- NGAP Initial UE message
|
||||
- NGAP Initial context setup request/response
|
||||
- NGAP Downlink/Uplink NAS transfer
|
||||
- NGAP UE context release request/complete
|
||||
- NGAP Paging
|
||||
- NGAP UE context release request/command/complete
|
||||
- NGAP UE radio capability info indication
|
||||
- NGAP PDU session resource setup request/response
|
||||
- NGAP PDU session resource modify request/response
|
||||
- NGAP PDU session resource release command/response
|
||||
- NGAP Mobility Management Procedures:
|
||||
* NGAP Handover Required
|
||||
* NGAP Handover Request
|
||||
@@ -259,6 +267,7 @@ These modes of operation are supported:
|
||||
* F1 UE Context modification request/response
|
||||
* F1 UE Context modification required
|
||||
* F1 UE Context release req/cmd/complete
|
||||
- F1 Paging
|
||||
- F1 gNB CU configuration update
|
||||
- F1 gNB DU configuration update
|
||||
- F1 Reset (handled at DU only, full reset only)
|
||||
@@ -279,10 +288,14 @@ These modes of operation are supported:
|
||||
- E1 Bearer Context Setup (gNB-CU-CP initiated)
|
||||
- E1 Bearer Context Setup Request
|
||||
- E1 Bearer Context Setup Response
|
||||
- E1 Bearer Context Setup Failure
|
||||
- Bearer Context Modification (gNB-CU-CP initiated)
|
||||
- E1 Bearer Context Modification Request
|
||||
- E1 Bearer Context Modification Response
|
||||
- E1 Reset
|
||||
- E1 Bearer Context Modification Failure
|
||||
- Bearer Context Release (gNB-CU-CP initiated)
|
||||
- E1 Bearer Context Release Command
|
||||
- E1 Bearer Context Release Complete
|
||||
- Interface with RRC and PDCP/SDAP
|
||||
- One CU-CP can handle multiple CU-UPs
|
||||
|
||||
@@ -356,9 +369,9 @@ These modes of operation are supported:
|
||||
* NR-PRACH
|
||||
- Formats 0,1,2,3, A1-A3, B1-B3
|
||||
* NTN
|
||||
- TA adjustemt based on ntn-Config-r17 information
|
||||
- Different TA adjustemt algorithms between SIB19 receptions:
|
||||
- Autonomous TA adjustemt based on DL time tracking
|
||||
- TA adjustment based on ntn-Config-r17 information
|
||||
- Different TA adjustment algorithms between SIB19 receptions:
|
||||
- Autonomous TA adjustment based on DL time tracking
|
||||
- Standard compliant epoch time based TA adjustment including orbital propagation
|
||||
- DL Doppler compensation based on ntn-Config-r17 information
|
||||
- UL Doppler pre-compensation based on ntn-Config-r17 information and residual DL FO estimation
|
||||
@@ -395,9 +408,12 @@ These modes of operation are supported:
|
||||
- Fallback not supported
|
||||
* DCI processing
|
||||
- format 10 (RA-RNTI, C-RNTI, SI-RNTI, TC-RNTI)
|
||||
- format 10 with P-RNTI
|
||||
- format 00 (C-RNTI, TC-RNTI)
|
||||
- format 11 (C-RNTI)
|
||||
- format 01 (C-RNTI)
|
||||
* Paging monitoring and reception
|
||||
- PF/PO-based paging PDCCH monitoring in IDLE/non-connected states
|
||||
* UCI processing
|
||||
- ACK/NACK processing
|
||||
- Scheduling request procedures
|
||||
@@ -462,6 +478,7 @@ These modes of operation are supported:
|
||||
- Support for master cell group configuration
|
||||
- Reception of UECapabilityEnquiry, encoding and transmission of UECapability
|
||||
- Support for measurement report of Event A2/A3
|
||||
- Paging: PCCH reception
|
||||
* NTN according to 38.331 Rel.17
|
||||
- Reception of ntn-Config-r17 from SIB19 or reconfigurationWithSync
|
||||
- Handling of ntn-UlSyncValidityDuration-r17 in SIB19
|
||||
@@ -472,7 +489,8 @@ These modes of operation are supported:
|
||||
|
||||
* Transfer of NAS messages between the AMF and the UE supporting the UE registration with the core network and the PDU session establishment according to 24.501 Rel.16
|
||||
* 5GMM (5G Mobility Management) messages:
|
||||
- Service Request/Accept/Reject (enc/dec library only)
|
||||
- Service Request/Accept/Reject (Network-triggered Service Request TS 23.502 §4.2.3.3,
|
||||
UE-Triggered Service Request after paging, TS 23.502 §4.2.3.2)
|
||||
- Identity Request/Response
|
||||
- Authentication Request/Response
|
||||
- Security Mode Command/Complete
|
||||
@@ -694,9 +712,6 @@ The NAS layer is based on **3GPP 24.301** and implements the following functions
|
||||
- EMM attach/detach, authentication, tracking area update, and more
|
||||
- ESM default/dedicated bearer, PDN connectivity, and more
|
||||
|
||||
|
||||
[OAI wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
[OAI softmodem build procedure](BUILD.md)
|
||||
|
||||
[Running the OAI softmodem ](RUNMODEM.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
The OpenAirInterface software can be obtained from our gitLab server. You will
|
||||
The Duranta OpenAirInterface software can be obtained Github. You will
|
||||
need a git client to get the sources. The repository is used for main
|
||||
developments.
|
||||
|
||||
@@ -13,9 +13,9 @@ sudo apt-get update
|
||||
sudo apt-get install git
|
||||
```
|
||||
|
||||
## Clone the Git repository (for OAI Users without login to gitlab server)
|
||||
## Clone the Git repository (for OAI Users without login to github server)
|
||||
|
||||
The [openairinterface5g repository](https://gitlab.eurecom.fr/oai/openairinterface5g.git)
|
||||
The [openairinterface5g repository](https://github.com/duranta-project/openairinterface5g.git)
|
||||
holds the source code for the RAN (4G and 5G).
|
||||
|
||||
### All users, anonymous access
|
||||
@@ -23,37 +23,24 @@ holds the source code for the RAN (4G and 5G).
|
||||
Clone the RAN repository:
|
||||
|
||||
```shell
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git
|
||||
```
|
||||
|
||||
### For contributors
|
||||
|
||||
Configure git with your name/email address, important if you are developer and
|
||||
want to contribute by pushing code. Please put your full name and the e-mail
|
||||
address you use in Gitlab.
|
||||
|
||||
```shell
|
||||
git config --global user.name "Your Name"
|
||||
git config --global user.email "Your email address"
|
||||
```
|
||||
|
||||
More information can be found in [the contributing page](../CONTRIBUTING.md).
|
||||
|
||||
## Which branch to checkout?
|
||||
|
||||
- `develop`: contains recent commits that are tested on our CI test bench. The
|
||||
update frequency is about once a week. 5G is only in this branch. **It is the
|
||||
update frequency is about once a week. **This is the
|
||||
recommended and default branch.**
|
||||
- `master`: contains a known stable version.
|
||||
|
||||
You can find the latest stable tag release [here](https://gitlab.eurecom.fr/oai/openairinterface5g/tags).
|
||||
You can find the latest stable tag release [here](https://github.com/duranta-project/openairinterface5g/releases).
|
||||
|
||||
The tag naming conventions are:
|
||||
|
||||
- On `master` branch: **v`x`.`y`.`z`**
|
||||
- On `develop` branch **`yyyy`.w`xx`**
|
||||
* `yyyy` is the calendar year
|
||||
* `xx` the week number within the year
|
||||
- On `develop` branch **`YYYY.wXX`**
|
||||
* `YYYY` is the calendar year
|
||||
* `XX` the week number within the year
|
||||
- On `develop` branch **`vX.Y`**
|
||||
* a semantic version number
|
||||
|
||||
More information on work flow and policies can be found in [this
|
||||
document](./code-style-contrib.md).
|
||||
|
||||
@@ -35,14 +35,14 @@ Please try to use the same commit ID on both eNB/UE hosts.
|
||||
|
||||
```bash
|
||||
$ ssh sudousername@machineB
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git enb_folder
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git enb_folder
|
||||
cd enb_folder
|
||||
git checkout develop
|
||||
```
|
||||
|
||||
```bash
|
||||
$ ssh sudousername@machineC
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ue_folder
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ue_folder
|
||||
cd ue_folder
|
||||
git checkout develop
|
||||
```
|
||||
@@ -315,8 +315,6 @@ iperf -c 10.0.1.1 -u -t 30 -b 2M -i 1 -fm -B 10.0.1.2 -p 5002
|
||||
|
||||
----
|
||||
|
||||
[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
[oai softmodem features](FEATURE_SET.md)
|
||||
|
||||
[oai softmodem build procedure](BUILD.md)
|
||||
|
||||
@@ -40,14 +40,14 @@ Please try to use the same commit ID on both eNB/UE hosts.
|
||||
|
||||
```bash
|
||||
$ ssh sudousername@machineB
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git enb_folder
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git enb_folder
|
||||
cd enb_folder
|
||||
git checkout develop
|
||||
```
|
||||
|
||||
```bash
|
||||
$ ssh sudousername@machineC
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ue_folder
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ue_folder
|
||||
cd ue_folder
|
||||
git checkout develop
|
||||
```
|
||||
@@ -295,8 +295,6 @@ iperf operations can also be performed.
|
||||
|
||||
----
|
||||
|
||||
[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
[oai softmodem features](FEATURE_SET.md)
|
||||
|
||||
[oai softmodem build procedure](BUILD.md)
|
||||
|
||||
@@ -182,12 +182,12 @@ Baseband devices using DPDK-compatible driver
|
||||
|
||||
## Building OAI with ORAN-AAL
|
||||
OTA deployment is precisely described in the following tutorial:
|
||||
- [NR_SA_Tutorial_COTS_UE](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_COTS_UE.md)
|
||||
- [NR_SA_Tutorial_COTS_UE](./NR_SA_Tutorial_COTS_UE.md)
|
||||
Instead of section *3.2 Build OAI gNB* from the tutorial, run the following commands:
|
||||
|
||||
```bash
|
||||
# Get openairinterface5g source code
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g
|
||||
git checkout develop
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ sudo uhd_images_downloader
|
||||
|
||||
```bash
|
||||
# Get openairinterface5g source code
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g
|
||||
git checkout develop
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ sudo uhd_images_downloader
|
||||
|
||||
```bash
|
||||
# Get openairinterface5g source code
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g
|
||||
git checkout develop
|
||||
|
||||
|
||||
@@ -44,7 +44,8 @@ PTP enabled switches and Grandmaster clock we have tested with:
|
||||
|Fibrolan Falcon-RX/812/G|
|
||||
|Qulsar Qg2 (Grandmaster)|
|
||||
|
||||
**S-Plane synchronization is mandatory.** S-plane support is done via `ptp4l` and `phc2sys`. Make sure your version matches.
|
||||
**S-Plane synchronization is mandatory.** S-plane support is done via
|
||||
`ptp4l` and `phc2sys`. Make sure your version matches.
|
||||
|
||||
| Software | Software Version|
|
||||
|-----------|-----------------|
|
||||
@@ -228,19 +229,19 @@ Once installed you can use this configuration file for ptp4l (`/etc/ptp4l.conf`)
|
||||
```
|
||||
[global]
|
||||
domainNumber 24
|
||||
slaveOnly 1
|
||||
clientOnly 1
|
||||
time_stamping hardware
|
||||
tx_timestamp_timeout 1
|
||||
tx_timestamp_timeout 50
|
||||
logging_level 6
|
||||
summary_interval 0
|
||||
#priority1 127
|
||||
|
||||
[your_PTP_ENABLED_NIC]
|
||||
[PTP_ENABLED_NIC_INTERFACE]
|
||||
network_transport L2
|
||||
hybrid_e2e 0
|
||||
```
|
||||
|
||||
You need to increase `tx_timestamp_timeout` to 50 or 100 for Intel E-810. You will see that in the logs of ptp.
|
||||
You need to increase `tx_timestamp_timeout` to 100 if needed. You will see that in the logs of ptp.
|
||||
|
||||
Create the configuration file for ptp4l (`/etc/sysconfig/ptp4l`)
|
||||
|
||||
@@ -251,7 +252,7 @@ OPTIONS="-f /etc/ptp4l.conf"
|
||||
Create the configuration file for phc2sys (`/etc/sysconfig/phc2sys`)
|
||||
|
||||
```
|
||||
OPTIONS="-a -r -r -n 24"
|
||||
OPTIONS="-s PTP_ENABLED_NIC_INTERFACE -w -n 24 -r -r -m -R 8"
|
||||
```
|
||||
|
||||
The service of ptp4l (`/usr/lib/systemd/system/ptp4l.service`) should be configured as below:
|
||||
@@ -295,8 +296,7 @@ Beware that PTP issues may show up only when running OAI and XRAN. If you are us
|
||||
1. Make sure that you have `skew_tick=1` in `/proc/cmdline`
|
||||
2. For Intel E-810 cards set `tx_timestamp_timeout` to 50 or 100 if there are errors in ptp4l logs
|
||||
3. Other time sources than PTP, such as NTP or chrony timesources, should be disabled. Make sure they are enabled as further below.
|
||||
4. Make sure you set `kthread_cpus=<cpu_list>` in `/proc/cmdline`.
|
||||
5. If `rms` or `delay` in `ptp4l` or `offset` in `phc2sys` logs remain high then you can try pinning the `ptp4l` and `phc2sys` processes to an isolated CPU.
|
||||
4. If `rms` or `delay` in `ptp4l` or `offset` in `phc2sys` logs remain high then you can try pinning the `ptp4l` and `phc2sys` processes to an isolated CPU.
|
||||
|
||||
```bash
|
||||
#to check there is NTP enabled or not
|
||||
@@ -400,7 +400,7 @@ sudo ninja deinstall -C build
|
||||
Clone OAI code base in a suitable repository, here we are cloning in `~/openairinterface5g` directory,
|
||||
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g/
|
||||
```
|
||||
|
||||
@@ -421,8 +421,9 @@ git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/
|
||||
```bash
|
||||
git clone https://github.com/openairinterface/o-du-phy.git ~/phy
|
||||
cd ~/phy
|
||||
git checkout <desired-tag> # shall match a variable `K_VERSION`
|
||||
git checkout 11.1.1 # the tag points to the `main` branch which has all patches applied that are relevant for OAI integration; the tag matches the value of cmake variable `K_VERSION`
|
||||
```
|
||||
or use `xran_DOWNLOAD` option when compiling OAI gNB.
|
||||
|
||||
Compile the fronthaul interface library by calling `make` and the option
|
||||
`XRAN_LIB_SO=1` to have it build a shared object. Note that we provide two
|
||||
@@ -2084,7 +2085,7 @@ Compiled libraries:
|
||||
|
||||
#### Using build_oai script
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g/cmake_targets/
|
||||
./build_oai -I # if you never installed OAI, use this command once before the next line
|
||||
./build_oai --install-optional-packages # for pcre/libpcre3, libssh, and libxml2 library installation
|
||||
@@ -2095,7 +2096,7 @@ PKG_CONFIG_PATH=/opt/mplane-v2/lib/pkgconfig ./build_oai --gNB --ninja -t oran_f
|
||||
|
||||
#### Using cmake directly
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g/
|
||||
mkdir build && cd build
|
||||
cmake .. -GNinja -DOAI_FHI72=ON -DOAI_FHI72_MPLANE=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
|
||||
@@ -3705,7 +3706,7 @@ sudo ./nr-softmodem -O <without-mplane-configuration file> --thread-pool <list o
|
||||
|
||||
## Contact in case of questions
|
||||
|
||||
You can ask your question on the [mailing lists](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/MailingList).
|
||||
You can ask your question on the [mailing lists](https://github.com/duranta-project/openairinterface5g/wiki/MailingList).
|
||||
|
||||
Your email should contain below information:
|
||||
|
||||
@@ -3718,4 +3719,4 @@ Your email should contain below information:
|
||||
- RU Vendor and Version.
|
||||
- In case your question is related to performance, include a small description of the machine (CPU, RAM and networking card) and diagram of your testing environment.
|
||||
- If you have any issues related to PTP or synchronization, then first check the section "Debugging PTP issues". Then share your problem with PTP version you are using, switch details and master clock.
|
||||
- Known/open issues are present on [GitLab](https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues), so keep checking.
|
||||
- Known/open issues are present on [Github](https://github.com/duranta-project/openairinterface5g/issues), so keep checking.
|
||||
|
||||
@@ -626,6 +626,116 @@ sequenceDiagram
|
||||
Note over ue,tdu: UE active on target DU
|
||||
```
|
||||
|
||||
### Paging and Network Triggered Service Request (CM-IDLE to CM-CONNECTED)
|
||||
|
||||
The following flow documents the current OAI stack path for paging-triggered
|
||||
service resumption in SA: context release to idle, NGAP/F1AP/PCCH paging, then
|
||||
RRC setup with NAS Service Request.
|
||||
|
||||
End-to-end flow is split across these 3GPP procedures:
|
||||
|
||||
| Spec clause | Procedure name | Actor | Spec role in this flow |
|
||||
|-------------|----------------|-------|------------------------|
|
||||
| TS 23.502 §4.2.3.3 | Network Triggered Service Request | AMF / 5GC | Network must deliver MT signalling/data to a CM-IDLE UE. "The Paging Request triggers the UE Triggered Service Request procedure in the UE". Step 4b = Paging Request to RAN, step 6 = UE initiates §4.2.3.2 |
|
||||
| TS 23.502 §4.2.3.2 | UE Triggered Service Request | UE | CM-IDLE UE may initiate SR "as a response to a network paging request" |
|
||||
| TS 24.501 §5.6.2.2 | Paging for 5GS services | UE NAS | On paging indication from lower layers: initiate service request (§5.6.1.2) when in `5GMM-REGISTERED` and `5GMM-IDLE` |
|
||||
| TS 24.501 §8.2.16 | SERVICE REQUEST | UE NAS | NAS PDU sent by UE |
|
||||
|
||||
#### OAI implementation
|
||||
|
||||
In summary:
|
||||
- UE transitions to `RRC_IDLE` and AMF transitions UE to `CM-IDLE`
|
||||
- CN-triggered paging is performed with `5G-S-TMSI` (NGAP Paging -> RRC Paging)
|
||||
- One radio page per cell per NGAP PAGING at UE PO
|
||||
- UE resumes via NAS Service Request and `RRCSetup`/`RRCSetupComplete`
|
||||
- AMF continues §4.2.3.3 after Initial UE Message / context setup
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant dn as DN
|
||||
participant cn as 5GC
|
||||
participant cu as gNB-CU
|
||||
participant du as gNB-DU
|
||||
participant ue as UE
|
||||
|
||||
cu->>cn: NGAP UE Context Release Request
|
||||
Note over cu: example trigger: telnet `rrc ctx_rel_req`
|
||||
cu->>cu: rrc_gNB_trigger_ue_context_release_req()
|
||||
cu->>cu: rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ()
|
||||
cn->>cu: NGAP UE Context Release Command
|
||||
cu->>cu: rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND()
|
||||
cu->>cu: rrc_gNB_generate_RRCRelease()
|
||||
cu->>du: F1AP DL RRC Message Transfer (RRCRelease)
|
||||
du->>ue: RRCRelease
|
||||
ue->>ue: handle_RRCRelease()
|
||||
ue->>ue: nr_rrc_going_to_IDLE()
|
||||
Note over ue: RRC_IDLE, NAS remains REGISTERED and can request service
|
||||
du->>cu: F1AP UE Context Release Complete
|
||||
cu->>cn: NGAP UE Context Release Complete
|
||||
|
||||
Note over dn,ue: Trigger Paging
|
||||
dn->>cn: DL user data
|
||||
Note over cn: AMF paging decision [23.502 §4.2.3.3]
|
||||
cn->>cu: NGAP Paging (5G-S-TMSI)
|
||||
cu->>cu: ngap_gNB_handle_paging()
|
||||
cu->>cu: decode_ng_paging()
|
||||
cu->>cu: rrc_gNB_process_PAGING_IND()
|
||||
cu->>cu: rrc_send_paging_to_dus()
|
||||
cu->>du: F1AP Paging
|
||||
du->>du: DU_handle_Paging()
|
||||
du->>du: f1_paging()
|
||||
du->>du: nr_mac_pcch_enqueue()
|
||||
Note over du: at UE PO: schedule_nr_pcch()
|
||||
du->>du: do_NR_Paging()
|
||||
du->>ue: RRC Paging (ng-5G-S-TMSI, P-RNTI)
|
||||
|
||||
ue->>ue: nr_rrc_ue_decode_pcch()
|
||||
ue->>ue: NAS_PAGING_IND
|
||||
ue->>ue: generateServiceRequest()
|
||||
ue->>ue: send_nas_initial_ul_transfer_req()
|
||||
Note over ue: paging match triggers Service Request [24.501 §5.6.2]
|
||||
Note over ue,cn: Resume service
|
||||
|
||||
ue->>ue: NAS_INITIAL_UL_TRANSFER_REQ
|
||||
ue->>ue: nr_rrc_ue_prepare_RRCSetupRequest()
|
||||
ue->>ue: nr_rrc_trigger_mac_ra(NR_MAC_RA_START_SETUP)
|
||||
ue->>du: RRCSetupRequest
|
||||
du->>cu: F1AP Initial UL RRC Message Transfer (RRCSetupRequest)
|
||||
cu->>cu: rrc_handle_RRCSetupRequest()
|
||||
cu->>du: F1AP DL RRC Message Transfer (RRCSetup)
|
||||
du->>ue: RRCSetup
|
||||
ue->>ue: do_RRCSetupComplete()
|
||||
Note over ue: uses dedicatedNAS when no SRB exists
|
||||
ue->>du: RRCSetupComplete + NAS SERVICE REQUEST
|
||||
du->>cu: F1AP UL RRC Message Transfer (RRCSetupComplete + NAS)
|
||||
cu->>cu: rrc_handle_RRCSetupComplete()
|
||||
cu->>cn: NGAP Initial UE Message
|
||||
cn->>cu: NGAP Initial Context Setup Request
|
||||
cu->>cu: rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ()
|
||||
cu->>du: F1AP DL RRC Message Transfer (RRCReconfiguration)
|
||||
du->>ue: RRCReconfiguration
|
||||
ue->>du: RRCReconfigurationComplete
|
||||
du->>cu: F1AP UL RRC Message Transfer (RRCReconfigurationComplete)
|
||||
cu->>cu: handle_rrcReconfigurationComplete()
|
||||
cu->>cn: NGAP Initial Context Setup Response
|
||||
cn->>ue: DL user data
|
||||
```
|
||||
|
||||
In OAI RFsim lab runs, a practical trigger sequence is:
|
||||
1. `rrc ctx_rel_req <ue-id>` at gNB telnet
|
||||
2. wait until AMF reports UE in IDLE state
|
||||
3. send host-side traffic to UE IP
|
||||
|
||||
Relevant specs:
|
||||
- TS 23.502: §4.2.3.3 Network Triggered Service Request (AMF pages, step 4b),
|
||||
UE Triggered Service Request §4.2.3.2 (by network paging)
|
||||
- TS 24.501 §5.6.2.2: Paging for 5G services
|
||||
- TS 24.501 §5.6.1: Service Request procedure
|
||||
- TS 38.331 §5.3.2: Paging
|
||||
- TS 38.331 §5.3.11: UE actions upon going to RRC_IDLE
|
||||
- TS 38.413 §8.5: Paging procedures (NGAP Paging)
|
||||
- TS 38.473 §8.7: Paging procedures (F1AP CU-to-DU paging)
|
||||
|
||||
## Structures
|
||||
|
||||
### DUs and Cells
|
||||
|
||||
@@ -263,7 +263,7 @@ Finally the number of TX physical antenna in the RU part of the configuration fi
|
||||
|
||||
It is possible to limit the number supported DL MIMO layers via RRC configuration, e.g. to a value lower than the number of logical antenna ports configured, by using the configuration file parameter `maxMIMO_layers`.
|
||||
|
||||
[Example of configuration file with parameters for 2-layer MIMO](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf)
|
||||
[Example of configuration file with parameters for 2-layer MIMO](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf)
|
||||
|
||||
## IF (Intermediate Frequency) equipment
|
||||
|
||||
|
||||
@@ -80,10 +80,14 @@
|
||||
|
||||
## Pipelines
|
||||
|
||||
### [RAN-Container-Parent](https://jenkins-oai.eurecom.fr/job/RAN-Container-Parent/)
|
||||
### [RAN-GitHub-Container-Parent](https://jenkins-oai.eurecom.fr/job/RAN-GitHub-Container-Parent/)
|
||||
|
||||
**Purpose**: automatically triggered tests on MR creation or push, from Gitlab
|
||||
Webhook ~documentation ~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
|
||||
**Purpose**: automatically triggered tests on pull request creation or push
|
||||
https://github.com/duranta-project/openairinterface5g/labels/documentation
|
||||
https://github.com/duranta-project/openairinterface5g/labels/BUILD-ONLY
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
|
||||
This pipeline has basically two main stages, as follows. For the image build,
|
||||
please also refer to the [dedicated documentation](../docker/README.md) for
|
||||
@@ -92,12 +96,18 @@ information on how the images are built.
|
||||
#### Image Build pipelines
|
||||
|
||||
- [RAN-ARM-Cross-Compile-Builder](https://jenkins-oai.eurecom.fr/job/RAN-ARM-Cross-Compile-Builder/)
|
||||
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/BUILD-ONLY
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- orion: Cross-compilation from Intel to ARM
|
||||
- base image from `Dockerfile.base.ubuntu.cross-arm64`
|
||||
- build image from `Dockerfile.build.ubuntu.cross-arm64` (no target images)
|
||||
- [RAN-RHEL8-Cluster-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Cluster-Image-Builder/)
|
||||
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
|
||||
- [RAN-RHEL-Cluster-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL-Cluster-Image-Builder/)
|
||||
https://github.com/duranta-project/openairinterface5g/labels/BUILD-ONLY
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- cluster (`Asterix-OC-oaicicd-session` resource): RHEL image build using the OpenShift Cluster (using gcc/clang)
|
||||
- base image from `Dockerfile.build.rhel9`
|
||||
- build image from `Dockerfile.build.rhel9`, followed by
|
||||
@@ -112,10 +122,13 @@ information on how the images are built.
|
||||
- build image from `Dockerfile.phySim.rhel9` (creates as direct target physical simulator
|
||||
image)
|
||||
- build image from `Dockerfile.clang.rhel9` (compilation only, artifacts not used currently)
|
||||
- [RAN-Ubuntu18-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/)
|
||||
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
|
||||
- [RAN-Ubuntu-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-Image-Builder/)
|
||||
https://github.com/duranta-project/openairinterface5g/labels/BUILD-ONLY
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- run formatting check from `ci-scripts/docker/Dockerfile.formatting.ubuntu`
|
||||
- obelix: Ubuntu image build using docker (Note: builds Ubuntu images of newer version while pipeline is named U18!)
|
||||
- obelix: Ubuntu image build using docker
|
||||
- base image from `Dockerfile.base.ubuntu`
|
||||
- build image from `Dockerfile.build.ubuntu`, followed by
|
||||
- target image from `Dockerfile.eNB.ubuntu`
|
||||
@@ -129,7 +142,10 @@ information on how the images are built.
|
||||
- target image from `Dockerfile.gNB.fhi72.ubuntu`
|
||||
- build unit tests from `ci-scripts/docker/Dockerfile.unittest.ubuntu`, and run them
|
||||
- [RAN-Ubuntu-ARM-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-ARM-Image-Builder/)
|
||||
~BUILD-ONLY ~4G-LTE ~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/BUILD-ONLY
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- gracehopper3-oai: ARM Ubuntu image build using docker
|
||||
- base image from `Dockerfile.base.ubuntu`
|
||||
- build image from `Dockerfile.build.ubuntu`, followed by
|
||||
@@ -138,7 +154,10 @@ information on how the images are built.
|
||||
- target image from `Dockerfile.nrUE.ubuntu`
|
||||
- target image from `Dockerfile.gNB.aerial.ubuntu`
|
||||
- [RAN-Ubuntu-Jetson-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-Jetson-Image-Builder/)
|
||||
~BUILD-ONLY ~4G-LTE ~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/BUILD-ONLY
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- jetson3-oai: ARMv8 Ubuntu image build using docker
|
||||
- base image from `Dockerfile.base.ubuntu`
|
||||
- build image from `Dockerfile.build.ubuntu`, followed by
|
||||
@@ -149,113 +168,113 @@ information on how the images are built.
|
||||
#### Image Test pipelines
|
||||
|
||||
- [OAI-CN5G-COTS-UE-Test](https://jenkins-oai.eurecom.fr/job/OAI-CN5G-COTS-UE-Test/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- using 5GC bench (resources `Cetautomatix`, `Dogmatix`): Attach/Detach of UE with multiple PDU sessions
|
||||
- [OAI-FLEXRIC-RAN-Integration-Test](https://jenkins-oai.eurecom.fr/job/OAI-FLEXRIC-RAN-Integration-Test/) ~5G-NR ~nrUE
|
||||
- [OAI-FLEXRIC-RAN-Integration-Test](https://jenkins-oai.eurecom.fr/job/OAI-FLEXRIC-RAN-Integration-Test/)
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- selfix (gNB, nrUE, OAI 5GC, FlexRIC)
|
||||
- uses RFsimulator, tests FlexRIC/E2 interface and xApps
|
||||
- [RAN-gNB-N300-Timing-Phytest-LDPC](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-gNB-N300-Timing-Phytest-LDPC/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- caracal + N310
|
||||
- pure performance test through phy-test scheduler, see command line for more details
|
||||
- [RAN-L2-Sim-Test-4G](https://jenkins-oai.eurecom.fr/job/RAN-L2-Sim-Test-4G/)
|
||||
~4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
- obelix (eNB, 1x UE, OAI EPC)
|
||||
- L2simulator: skips physical layer and uses proxy between eNB and UE
|
||||
- [RAN-LTE-FDD-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-FDD-LTEBOX-Container/)
|
||||
~4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
- hutch + B210, nano w/ ltebox + 2x UE
|
||||
- tests RRC inactivity timers, different bandwidths, IF4p5 fronthaul
|
||||
- [RAN-LTE-FDD-OAIUE-OAICN4G-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-FDD-OAIUE-OAICN4G-Container/)
|
||||
~4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
- hutch + B210 (eNB), carabe + B210 (4G UE), nano w/ OAI 4GC
|
||||
- tests OAI 4G for 10 MHz/TM1; known to be unstable
|
||||
- [RAN-LTE-TDD-2x2-Container](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-LTE-TDD-2x2-Container/)
|
||||
~4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
- obelix + N310, porcepix, up2 + Quectel
|
||||
- TM1 and TM2 test, IF4p5 fronthaul
|
||||
- [RAN-LTE-TDD-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-TDD-LTEBOX-Container/)
|
||||
~4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
- starsky + B210, nano w/ ltebox + 2x UE
|
||||
- TM1 over bandwidths 5, 10, 20 MHz in Band 40, default scheduler for 20 MHz
|
||||
- [RAN-NSA-B200-Module-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX-Container/)
|
||||
~4G-LTE ~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- nepes + B200 (eNB), ofqot + B200 (gNB), idefix + Quectel, nepes w/ ltebox
|
||||
- basic NSA test
|
||||
- [RAN-PhySim-Cluster-4G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-4G/)
|
||||
~4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
- tests 4G physical simulators (`nr_dlsim`, etc.) in OpenShift Cluster (x86)
|
||||
- see [`./physical-simulators.md`](./physical-simulators.md) for an overview
|
||||
- [RAN-PhySim-Cluster-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster-5G/)
|
||||
~5G-NR ~nrUE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- tests 5G physical simulators (`nr_dlsim`, etc.) in OpenShift Cluster (x86)
|
||||
- see [`./physical-simulators.md`](./physical-simulators.md) for an overview
|
||||
- [RAN-PhySim-GraceHopper-5G](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-GraceHopper-5G/)
|
||||
~5G-NR ~nrUE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- tests 5G physical simulators (`nr_dlsim`, etc.) on Nvidia GraceHopper (ARMv9)
|
||||
- see [`./physical-simulators.md`](./physical-simulators.md) for an overview
|
||||
- [RAN-RF-Sim-Test-4G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-4G/)
|
||||
~4G-LTE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/4G-LTE
|
||||
- acamas (eNB, lteUE, OAI EPC)
|
||||
- uses RFsimulator, for FDD 5, 10, 20MHz with core, 5MHz noS1
|
||||
- [RAN-RF-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-5G/)
|
||||
~5G-NR ~nrUE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- acamas (gNB, nrUE, OAI 5GC)
|
||||
- uses RFsimulator, TDD 40MHz, FDD 40MHz, F1 split
|
||||
- [RAN-SA-AW2S-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AW2S-CN5G/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- 5G-NR SA test setup: avra + AW2S, amariue, OAI CN5G
|
||||
- uses OpenShift cluster for CN deployment and container images for gNB deployment
|
||||
- multi UE testing using Amarisoft UE simulator
|
||||
- [RAN-SA-B200-Module-SABOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-SA-B200-Module-SABOX-Container/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- ofqot + B200, idefix + Quectel, nepes w/ sabox
|
||||
- basic SA test (20 MHz TDD), F1, reestablishment, ...
|
||||
- [RAN-SA-OAIUE-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-OAIUE-CN5G/)
|
||||
~5G-NR ~nrUE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- 5G-NR SA test setup: gNB on avra + N310, OAIUE on caracal + N310, OAI CN5G
|
||||
- OpenShift cluster for CN deployment and container images for gNB and UE deployment
|
||||
- [RAN-SA-AERIAL-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AERIAL-CN5G/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on gracehopper1-oai + Foxconn RU, up2 + COTS UE (Quectel RM520N), OAI CN5G
|
||||
- container images for gNB deployment
|
||||
- [RAN-SA-Multi-Antenna-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-Multi-Antenna-CN5G/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- matix + N310 (gNB), up2 + COTS UE (Quectel RM520N), OAI 5GC deployed in docker on matix
|
||||
- NR performance tests: 2x2 configuration, 60 MHz and 100 MHz bandwidth
|
||||
- [RAN-SA-FHI72-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-FHI72-CN5G/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- cacofonix + FHI72 + Metanoia (gNB), up2 (Quectel RM520N UE), OAI CN5G
|
||||
- OpenShift cluster for CN deployment
|
||||
- FHI 7.2 testing with 100 MHz bandwidth, 2 layers in DL
|
||||
- [RAN-SA-Handover-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-Handover-CN5G/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- groot (CU+DU0) + B210, rocket (DU1) + B210, raspix (Quectel RM520N UE), OAI CN5G
|
||||
- OpenShift cluster for CN deployment
|
||||
- Attenuator (mini circuits RC4DAT-6G-60) - controlled from rocket
|
||||
- [RAN-Channel-Simulation](https://jenkins-oai.eurecom.fr/job/RAN-Channel-Simulation/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- gracehopper1-oai
|
||||
- run channel simulation on CPU and GPU using test_channel_scalability
|
||||
- [RAN-SA-AERIAL-OAIUE-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AERIAL-OAIUE-CN5G/)
|
||||
~5G-NR ~nrUE
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/nrUE
|
||||
- 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on gracehopper1-oai + WNC RU, OAIUE on jetson1-oai + B210, OAI CN5G
|
||||
- OpenShift cluster for CN deployment and container images for gNB and UE deployment
|
||||
- [RAN-SA-FHI72-MPLANE-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-FHI72-MPLANE-CN5G/)
|
||||
~5G-NR
|
||||
https://github.com/duranta-project/openairinterface5g/labels/5G-NR
|
||||
- cacofonix + FHI72 + Benetel550 (gNB), AmarisoftUE, OAI CN5G
|
||||
- OpenShift cluster for CN deployment
|
||||
- FHI 7.2 testing with 40 MHz, 4x4 MIMO configuration and 100 MHz, 2x2 MIMO configuration
|
||||
- FHI 7.2 Configuration and Performance Management via NETCONF session of an O-RU
|
||||
|
||||
### RAN-CI-NSA-Trigger
|
||||
|
||||
***DEFUNCT***: longer-running over-the-air LTE, NSA, and SA tests. To be integrated into RAN-Container-Parent.
|
||||
|
||||
- [RAN-NSA-2x2-Module-OAIEPC](https://jenkins-oai.eurecom.fr/job/RAN-NSA-2x2-Module-OAIEPC/)
|
||||
- obelix + N310 (eNB), asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ Magma EPC
|
||||
- LTE 2x2 and NR 2x2 (non-standalone)
|
||||
|
||||
## How to reproduce CI results
|
||||
|
||||
The CI builds docker images at the beginning of every test run. To see the
|
||||
|
||||
@@ -42,7 +42,7 @@ Our code might not work with all 5G phones yet, but we are constantly improving
|
||||
|
||||
## Repository
|
||||
|
||||
[OAI](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop)
|
||||
[OAI](https://github.com/duranta-project/openairinterface5g)
|
||||
|
||||
## Architecture Setup
|
||||
|
||||
@@ -58,7 +58,7 @@ The photo depicts the FR1 setup part of the scheme above:
|
||||
## Build and Install
|
||||
|
||||
General guidelines to build eNB and gNB :
|
||||
See [Building UE, eNB and gNb executables](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/doc/BUILD.md#building-ues-enodeb-and-gnodeb-executables)
|
||||
See [Building UE, eNB and gNb executables](./BUILD.md)
|
||||
|
||||
|
||||
- **eNB**
|
||||
|
||||
@@ -10,23 +10,24 @@ review is performed.
|
||||
|
||||
## General
|
||||
|
||||
OpenAirInterface employs both human review and automated CI tests to judge
|
||||
whether a code contribution is ready to be merged.
|
||||
Duranta OpenAirInterface employs both human review and automated CI tests to
|
||||
judge whether a code contribution is ready to be merged.
|
||||
|
||||
The contributor has to sign a contributor license agreement (CLA) as described
|
||||
in [`CONTRIBUTING.md`](../CONTRIBUTING.md). After creating an account on the
|
||||
Eurecom Gitlab, the contributor can open a merge request: he becomes the
|
||||
"author" of such code contribution. A senior OAI member will review this work,
|
||||
and make suggestions for possible improvements. Each week, we discuss the
|
||||
progress of the merge requests in a [weekly external developer
|
||||
call](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/OpenAirDevMeetings),
|
||||
and discuss which merge requests can be merged.
|
||||
in [`CONTRIBUTING.md`](../CONTRIBUTING.md). After creating an account on
|
||||
Github, the contributor can open a pull request from a fork: he becomes the
|
||||
"author" of such code contribution. A senior Duranta OAI member will review
|
||||
this work, and make suggestions for possible improvements. Each week, we
|
||||
discuss the progress of the pull requests in a [weekly developer
|
||||
call](https://github.com/duranta-project/openairinterface5g/wiki/Developer-Meetings),
|
||||
and discuss which pull requests can be merged.
|
||||
|
||||
The CI consists in various Jenkins pipelines that run on each merge request.
|
||||
The CI consists in various Jenkins pipelines that run on each pull request.
|
||||
See [`TESTBenches.md`](./TESTBenches.md) for more details about the CI setup.
|
||||
|
||||
There is the official [Gitlab Help](https://docs.gitlab.com/) that can help you
|
||||
with any questions regarding Gitlab. We recommend reading the [Git
|
||||
There is the official [Github Help](https://docs.github.com/) that can help you
|
||||
with any questions regarding Github. Note that unlike Gitlab, password-based
|
||||
code pushes are not allowed. Also, we recommend reading the [Git
|
||||
Book](https://git-scm.com/book/en/v2) to use Git properly.
|
||||
|
||||
## Basic coding rules
|
||||
@@ -57,8 +58,11 @@ A number of high-level comments:
|
||||
put output variables (via a pointer) last
|
||||
- Do not do premature optimization; measure the code before writing SIMD
|
||||
instructions by hand, and measure again to show it is faster.
|
||||
- Avoid variables marked with `extern`. Function prototypes must be in one
|
||||
unique header file that should be included by all source files that define
|
||||
this function or use it.
|
||||
|
||||
If in doubt, check out code that has been recently written (e.g., use the merge
|
||||
If in doubt, check out code that has been recently written (e.g., use the pull
|
||||
requests page to check for code that has recently been added) and follow that
|
||||
style. Checking surrounding code is usually not the best idea, as OAI has a
|
||||
long history in which coding rules were not really enforced.
|
||||
@@ -74,15 +78,8 @@ that might be useful; if this document and `.clang-format` contradict,
|
||||
|
||||
You should be familiar with git branching, merging, and rebasing.
|
||||
|
||||
The target branch for every contribution, and the general development branch,
|
||||
is `develop`. Typically every week, we collect multiple merge requests in an
|
||||
"integration branch" that gets tested by the CI individually. If everything is
|
||||
fine, we merge to develop and tag it `YYYY.wXX` with `YYYY` the current year,
|
||||
and `XX` the week number.
|
||||
|
||||
Note that the above includes a lot of merging, making the Git history difficult
|
||||
to understand. To not needlessly increase the complexity, please keep your
|
||||
branch history linear (i.e., no merges). Each commit should be able to
|
||||
To make branches simple to read for a reviewer, developer, or anyone interested
|
||||
in the code, please keep your branch history linear (i.e., no merges). Each commit should be able to
|
||||
compile, and ideally be able to run an End-to-End test of gNB/UE using RFsim.
|
||||
This can be achieved by making each commit a **logical change** to be applied to
|
||||
the code base, which also facilitates the review of your changes. The Linux
|
||||
@@ -108,14 +105,16 @@ A commit message can (and often should) take several lines. One-line commit
|
||||
messages should be reserved for very simple changes. If in doubt, prefer to
|
||||
explain your work more than less.
|
||||
|
||||
The workflow of the integration branch has its weaknesses; we might revise this
|
||||
in the future towards a workflow using rebase to integrate work of different
|
||||
people, in order to simplify the history, and allow the usage of tools such as
|
||||
`git bisect` to search for bugs.
|
||||
### Release Strategy
|
||||
|
||||
After some time, we make a stable release. For this, we simply merge develop
|
||||
into master, and give a semantic versioning number, e.g., `v1.1`. We target to
|
||||
make releases bi-yearly.
|
||||
The target branch for every contribution, and the general development branch,
|
||||
is `develop`. Typically every week, we collect multiple pull requests in an
|
||||
"integration branch" that gets tested by the CI individually. If everything is
|
||||
fine, we merge to develop and tag it `YYYY.wXX` with `YYYY` the current year,
|
||||
and `XX` the week number.
|
||||
|
||||
After some time, we make a stable release using a semantic version number,
|
||||
e.g., `v3.0`. We target to make releases bi-yearly.
|
||||
|
||||
### How to manage your own branch
|
||||
|
||||
@@ -157,21 +156,98 @@ Once you rebased, push the changes to the remote
|
||||
$ git push origin my-new-feature --force-with-lease # force with lease let's you only overwrite what you also have locally in origin/my-new-feature
|
||||
```
|
||||
|
||||
## Merge Requests
|
||||
### Use of git commit trailers
|
||||
|
||||
A merge request (MR) can be submitted as soon as the code is considered stable
|
||||
As noted in the [contribution guidelines](../CONTRIBUTING.md), you have to sign
|
||||
all your commits. Thus, every commit must have a git commit trailer that reads
|
||||
|
||||
```
|
||||
Signed-off-by: Full Name <email-for-cla>
|
||||
```
|
||||
|
||||
There are additional commit trailers that you can or should use:
|
||||
|
||||
- `Assisted-by: <Name>:<model>`: if you have been assisted by an AI/LLM, you
|
||||
must disclose this by indicating both the LLM name and model. Note that LLMs
|
||||
do not author, as _the submission is under your name_ (i.e., NEVER add an LLM
|
||||
through `Co-authored:by:`). The [Linux kernel documentation on AI
|
||||
assistents](https://docs.kernel.org/process/coding-assistants.html)
|
||||
might be helpful.
|
||||
- `Reviewed-by: Full Name <email>` for a person that reviewed a code. We attach
|
||||
this trailer to the merge commit for people that reviewed a pull request.
|
||||
- `Co-authored-by: Full Name <email>` for a person that significantly
|
||||
contributed to a commit and has co-authorship.
|
||||
- `Fixes: <commit> ("<title>")` if a given commit fixes bug in an earlier,
|
||||
referenced commit. For ease-of-use, please include the commit title, and only
|
||||
the commit SHA, not a link.
|
||||
- `Closes: #Issue` if a specific commit closes a bug. If the pull request
|
||||
description includes this, we add this to the merge commit.
|
||||
- `Reported-by: Full Name <email>` if a person reported a bug or other useful
|
||||
information that led to this commit.
|
||||
- `Tested-By: Full Name <email>` if a person tested a given patch.
|
||||
|
||||
This list is non-exhaustive, and you might attach more trailers. Please also
|
||||
check the documentation via `man git-interpret-trailers`, and note that the
|
||||
general free-form format is (from the documentation):
|
||||
|
||||
```
|
||||
key: value
|
||||
|
||||
This means that the trimmed <key> and <value> will be separated by ": " (one colon followed by one space).
|
||||
```
|
||||
|
||||
### AI Assistants
|
||||
|
||||
These guidelines are mostly based on [linux kernel
|
||||
guidelines](https://docs.kernel.org/process/coding-assistants.html)
|
||||
|
||||
This document provides guidance for AI tools and developers using AI assistance
|
||||
when contributing to the respository.
|
||||
|
||||
AI tools helping with openairinterface development should follow the standard
|
||||
openairinterface developement procedure. They should comply with Duranta OAI’s
|
||||
licensing requirements:
|
||||
|
||||
- All code must be compatible with CSSL v1.0
|
||||
- Use appropriate SPDX license identifiers
|
||||
|
||||
AI agents MUST NOT add `Signed-off-by` nor `Co-authored-by` tags. Only humans
|
||||
can legally certify the Developer Certificate of Origin (DCO). The human
|
||||
submitter is responsible for:
|
||||
|
||||
- Reviewing all AI-generated code
|
||||
- Ensuring compliance with licensing requirements
|
||||
- Adding their own Signed-off-by tag to certify the DCO
|
||||
- Taking full responsibility for the contribution
|
||||
|
||||
When AI tools contribute to openairinterface,
|
||||
proper commit message helps track the evolving role of AI in the development process.
|
||||
Contributions should include an `Assisted-by` tag in the following format:
|
||||
|
||||
Assisted-by: AGENT_NAME:MODEL_VERSION
|
||||
|
||||
- `AGENT_NAME` is the name of the AI tool or framework
|
||||
- `MODEL_VERSION` is the specific model version used
|
||||
|
||||
Example:
|
||||
|
||||
Assisted-by: Claude:claude-3-opus
|
||||
|
||||
## Pull Requests
|
||||
|
||||
A pull request (PR) can be submitted as soon as the code is considered stable
|
||||
and reviewable. The idea is to start the review early enough so that the code
|
||||
author (the MR owner) can incorporate fixes while the reviewer is giving
|
||||
feedback. Note that while it should not be common, a refusal of a merge request
|
||||
is a valid outcome of a merge request review (subject to proper justification).
|
||||
author (the PR owner) can incorporate fixes while the reviewer is giving
|
||||
feedback. Note that while it should not be common, a refusal of a pull request
|
||||
is a valid outcome of a pull request review (subject to proper justification).
|
||||
|
||||
When preparing a contribution that is large, the developer is responsible for
|
||||
warning the OAI team, so that the review work can start as early as possible
|
||||
warning the maintainers team, so that the review work can start as early as possible
|
||||
and run in parallel to the contribution finalization. Failing to do so, there
|
||||
is a risk that the work will take a long time to be merged or might even not be
|
||||
merged at all if judged too complex by the OAI team. Also, note that big
|
||||
merged at all if judged too complex by the maintainers team. Also, note that big
|
||||
contributions should be cut into small commits each containing a logical
|
||||
change, as described above. Finally, as a rule of thumb, the smaller the merge
|
||||
change, as described above. Finally, as a rule of thumb, the smaller the pull
|
||||
request, the easier it will be to review and merge.
|
||||
|
||||
The reviewer comments on code changes ("open comments") that should be
|
||||
@@ -180,50 +256,55 @@ resolved by themselves to double check the modifications and close such
|
||||
comments. As an author, please don't resolve open comments (don't click the
|
||||
"Resolve thread" button) unless explicitly instructed by the reviewer.
|
||||
|
||||
Note that the _merge request author_ asks for inclusion of code, so _they
|
||||
Note that the _pull request author_ asks for inclusion of code, so _they
|
||||
should make the review easy_; in particular, if facilitating review incurs
|
||||
extra work to make a simpler code review (e.g., rewriting entire commits or
|
||||
their order), this extra work is justified. This particularly(!) applies for
|
||||
big merge requests.
|
||||
big pull requests.
|
||||
|
||||
When opening a merge requests, the author should select `develop` as the target
|
||||
branch, and add at least one of these labels when opening the merge request:
|
||||
When opening a pull requests, the author should select `develop` as the target
|
||||
branch, and add at least one of these labels when opening the pull request:
|
||||
|
||||
- ~documentation: don't perform any testing stages, for documentation
|
||||
- ~BUILD-ONLY: execute only build stages, for code improvements without impact
|
||||
on 4G or 5G code
|
||||
- ~4G-LTE: perform 4G tests
|
||||
- ~5G-NR: perform 5G tests
|
||||
- https://github.com/duranta-project/openairinterface5g/labels/documentation:
|
||||
don't perform any testing stages, for documentation
|
||||
- https://github.com/duranta-project/openairinterface5g/labels/BUILD-ONLY:
|
||||
execute only build stages, for code improvements without impact on 4G or 5G
|
||||
code
|
||||
- https://github.com/duranta-project/openairinterface5g/labels/4G-LTE: perform
|
||||
4G tests
|
||||
- https://github.com/duranta-project/openairinterface5g/labels/5G-NR: perform
|
||||
5G tests
|
||||
- https://github.com/duranta-project/openairinterface5g/labels/nrUE: perform
|
||||
only 5G-UE related tests including physims
|
||||
|
||||
Failure to add a label will prevent the CI from running. You can add both
|
||||
~4G-LTE and ~5G-NR together; if in doubt about the right label, add both. The
|
||||
CI posts the results in the comments section of the merge request. Both merge
|
||||
request authors and reviewers are responsible for manual inspection and
|
||||
pre-filtering of the CI results. An overview of the CI tests is in
|
||||
[`TESTBenches.md`](./TESTBenches.md).
|
||||
Failure to add a label will prevent the CI from running. If in doubt about the
|
||||
right label, add both 4G and 5G labels. The CI posts the results in the
|
||||
comments section of the pull request. Both pull request authors and reviewers
|
||||
are responsible for manual inspection and pre-filtering of the CI results. An
|
||||
overview of the CI tests is in [`TESTBenches.md`](./TESTBenches.md).
|
||||
|
||||
To communicate the review progress both between author and reviewer, as well as
|
||||
to the outside world, we (ab-)use the milestones feature of Gitlab to track the
|
||||
current progress. The milestone can be set when opening the merge request, and
|
||||
to the outside world, we (ab-)use the milestones feature of Github to track the
|
||||
current progress. The milestone can be set when opening the pull request, and
|
||||
during its lifetime in the sidebar on the right. Following options:
|
||||
|
||||
- _no milestone_: not ready for review yet and is generally used to wait for a
|
||||
first CI run that the author will inspect and fix problems detected by the CI
|
||||
(please limit the time in which your code is in that phase)
|
||||
- %REVIEW_CAN_START: the reviewer can start the review
|
||||
- %REVIEW_IN_PROGRESS: the reviewer is currently doing review, and might
|
||||
- [REVIEW_CAN_START](https://github.com/duranta-project/openairinterface5g/milestone/2): the reviewer can start the review
|
||||
- [REVIEW_IN_PROGRESS](https://github.com/duranta-project/openairinterface5g/milestone/4): the reviewer is currently doing review, and might
|
||||
request changes to the code that the author should include (or refute with
|
||||
justification)
|
||||
- %REVIEW_COMPLETED_AND_APPROVED: the reviewer is happy with code changes
|
||||
- [REVIEW_COMPLETED_AND_APPROVED](https://github.com/duranta-project/openairinterface5g/milestone/3): the reviewer is happy with code changes
|
||||
(*open comments still have to be addressed!*)
|
||||
- %OK_TO_BE_MERGED: the OAI team plans to merge this; *do not push any changes
|
||||
- [OK_TO_BE_MERGED](https://github.com/duranta-project/openairinterface5g/milestone/1): the maintainers team plans to merge this; *do not push any changes
|
||||
anymore at this point*.
|
||||
|
||||
## Review Form
|
||||
|
||||
The following is a check list that might be used by a reviewer to check that
|
||||
code contribution fulfils minimum standard w.r.t. formatting, data types,
|
||||
assertions, etc. The reviewer might copy/paste this form into a merge request,
|
||||
assertions, etc. The reviewer might copy/paste this form into a pull request,
|
||||
or simply check that all have been filled.
|
||||
|
||||
All points should be marked to complete a review.
|
||||
@@ -252,9 +333,9 @@ Additional optional questions in case they apply:
|
||||
|
||||
Please report only true bugs in the [issue tracker](../../issues). Do not
|
||||
report general user problems; use the [mailing
|
||||
lists](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/MailingList)
|
||||
lists](https://github.com/duranta-project/openairinterface5g/wiki/MailingList)
|
||||
instead. If in doubt, prefer the mailing lists and if needed and requested by
|
||||
the OAI team, an issue will be opened.
|
||||
the maintainers team, an issue will be opened.
|
||||
|
||||
When reporting a bug, please clearly
|
||||
- explain the problem,
|
||||
@@ -265,4 +346,4 @@ When reporting a bug, please clearly
|
||||
|
||||
You are encouraged to use these bullet points to structure your issue for easy
|
||||
understanding. Use code tags (the "insert code" button with symbol </> in
|
||||
the gitlab editor) for logs and small code snippets.
|
||||
the github editor) for logs and small code snippets.
|
||||
|
||||
@@ -61,7 +61,7 @@ Correct (Markdown):
|
||||
**Bold text**
|
||||
*Italic text*
|
||||
|
||||
 instead of <img src="./images/oai_final_logo.png" alt="OAI Logo">
|
||||

|
||||
|
||||
| Feature | Description |
|
||||
|---------------|---------------------------------|
|
||||
@@ -75,7 +75,7 @@ Incorrect (HTML):
|
||||
<b>Bold text</b>
|
||||
<i>Italic text</i>
|
||||
|
||||
<img src="./images/oai_final_logo.png" alt="OAI Logo">
|
||||
<img src="./path/to/image.png" alt="some image">
|
||||
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr>
|
||||
@@ -114,7 +114,7 @@ Incorrect (HTML):
|
||||
is](https://www.kernel.org/doc/html/latest/process/submitting-patches.html#separate-your-changes).
|
||||
- See [OAI CN5G configuration files](#22-oai-cn5g-configuration-files) for
|
||||
details.
|
||||
- 
|
||||
- 
|
||||
```
|
||||
|
||||
## Inline code for technical elements
|
||||
|
||||
@@ -8,9 +8,9 @@ This tutorial explains how to perform handovers. It covers both F1 handovers
|
||||
This document assumes familiarity with the F1 split architecture and basic
|
||||
OAI knowledge. Please refer to the prerequisite documentation listed below:
|
||||
|
||||
- To run the [Core Network](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_OAI_CN5G.md)
|
||||
- To run [OAI full stack with COTS UE](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_COTS_UE.md)
|
||||
- [F1 split design document](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/F1AP/F1-design.md?ref_type=heads)
|
||||
- To run the [Core Network](./NR_SA_Tutorial_OAI_CN5G.md)
|
||||
- To run [OAI full stack with COTS UE](./NR_SA_Tutorial_COTS_UE.md)
|
||||
- [F1 split design document](./F1AP/F1-design.md)
|
||||
for details on the F1 architecture and the networking relationships between
|
||||
the CU and the associated DUs.
|
||||
|
||||
@@ -198,9 +198,9 @@ triggered:
|
||||
- By connecting them to a GPS or an Octoclock to provide a common time and clock
|
||||
reference.
|
||||
- By synchronizing the RU hosts.
|
||||
- By using Openairinterface starting tag [2025.w42](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/2025.w42?ref_type=tags)
|
||||
- By using Openairinterface starting tag [2025.w42](https://github.com/duranta-project/openairinterface5g/releases/tag/2025.w42)
|
||||
(A fix was added to force the USRP to "use" the time/clock provided by the
|
||||
external source instead to its own master clock. for more info see [MR](https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/3693)).
|
||||
external source instead to its own master clock.).
|
||||
- Make sure that the UE sees both cells. For instance, you can switch to flight
|
||||
mode, go closer to the other DU, and switch off flight mode -- the UE should
|
||||
connect to that second DU.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 161 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 209 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB |
@@ -70,5 +70,3 @@ options for replay mode are:
|
||||
..................................
|
||||
..................................
|
||||
```
|
||||
|
||||
[OAI Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
FROM registry.redhat.io/ubi9/ubi:latest AS ran-base
|
||||
LABEL MAINTAINER OpenAirInterface <contact@openairinterface.org>
|
||||
LABEL MAINTAINER OpenAirInterface <oaicicdteam@openairinterface.org>
|
||||
ARG NEEDED_GIT_PROXY
|
||||
ARG TARGETARCH
|
||||
ENV TZ=Europe/Paris
|
||||
|
||||
@@ -1,20 +1,6 @@
|
||||
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
|
||||
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr style="border-collapse: collapse; border: none;">
|
||||
<td style="border-collapse: collapse; border: none;">
|
||||
<a href="http://www.openairinterface.org/">
|
||||
<img src="../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
|
||||
</img>
|
||||
</a>
|
||||
</td>
|
||||
<td style="border-collapse: collapse; border: none; vertical-align: center;">
|
||||
<b><font size = "5">OAI Docker/Podman Build and Usage Procedures</font></b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
---
|
||||
OAI Docker/Podman Build and Usage Procedures
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
@@ -116,7 +102,7 @@ possibilities:
|
||||
There are two shared images: one that has all dependencies, and a second that compiles all targets (eNB, gNB, [nr]UE).
|
||||
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
|
||||
git clone https://github.com/duranta-project/openairinterface5g.git
|
||||
cd openairinterface5g
|
||||
# default branch is develop, to change use git checkout <BRANCH>
|
||||
docker build --target ran-base --tag ran-base:latest --file docker/Dockerfile.base.ubuntu .
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include <executables/softmodem-common.h>
|
||||
#include <executables/thread-common.h>
|
||||
#include "executables/nr-softmodem.h"
|
||||
#include "nr-oru.h"
|
||||
#include "openair1/PHY/INIT/nr_phy_init.h"
|
||||
#include "openair1/SCHED_NR/sched_nr.h"
|
||||
|
||||
pthread_cond_t sync_cond;
|
||||
pthread_mutex_t sync_mutex;
|
||||
@@ -33,6 +36,14 @@ int sf_ahead = 4;
|
||||
int emulate_rf = 0;
|
||||
|
||||
RAN_CONTEXT_t RC;
|
||||
|
||||
extern void kill_NR_RU_proc(int inst);
|
||||
extern void set_function_spec_param(RU_t *ru);
|
||||
extern void start_NR_RU();
|
||||
extern void init_NR_RU(configmodule_interface_t *cfg, char *);
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file);
|
||||
void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_request_scf_t *config, const NR_DL_FRAME_PARMS *fp);
|
||||
|
||||
int64_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
void nfapi_setmode(nfapi_mode_t nfapi_mode)
|
||||
@@ -106,23 +117,15 @@ struct timespec timespec_sub(struct timespec, struct timespec)
|
||||
struct timespec t = {0};
|
||||
return t;
|
||||
};
|
||||
|
||||
void perform_symbol_rotation(NR_DL_FRAME_PARMS *fp, double f0, c16_t *symbol_rotation)
|
||||
void beam_index_allocation(uint16_t fapi_beam_index,
|
||||
int ant,
|
||||
int num_ports,
|
||||
int symbols_per_slot,
|
||||
int slot,
|
||||
uint16_t bitmap_symbols,
|
||||
int num_ant_max,
|
||||
uint16_t **ant_beam_id_list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
return;
|
||||
};
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
int bitmap_symbols)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint16_t get_first_ant_idx(bool das, uint16_t num_ports_beams, uint16_t beam_id, uint16_t fapi_start_port)
|
||||
{
|
||||
@@ -132,6 +135,12 @@ void nr_fill_du(uint16_t N_ZC, const uint16_t *prach_root_sequence_map, uint16_t
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
static void sig_handler(int sig_num)
|
||||
{
|
||||
oai_exit = 1;
|
||||
}
|
||||
|
||||
uint16_t nr_du[838];
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
@@ -168,6 +177,7 @@ int main(int argc, char **argv)
|
||||
printf("About to Init RU threads\n");
|
||||
|
||||
lock_memory_to_ram();
|
||||
load_dftslib();
|
||||
|
||||
RC.nb_RU = 1;
|
||||
RC.ru = malloc(sizeof(RC.ru));
|
||||
@@ -175,24 +185,77 @@ int main(int argc, char **argv)
|
||||
init_NR_RU(config_get_if(), NULL);
|
||||
|
||||
RU_t *ru = RC.ru[0];
|
||||
ORU_t oru = {0};
|
||||
oru.ru = ru;
|
||||
int ret = get_oru_options(&oru);
|
||||
AssertFatal(ret == 0, "Cannot configure oru, check your config file/cmdline");
|
||||
ru->numerology = oru.numerology;
|
||||
oru_init_frame_parms(&oru);
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nr_dump_frame_parms(fp);
|
||||
init_symbol_rotation(fp);
|
||||
init_timeshift_rotation(fp->ofdm_symbol_size, fp->nb_prefix_samples, fp->ofdm_offset_divisor, fp->timeshift_symbol_rotation);
|
||||
ru->if_south = LOCAL_RF;
|
||||
nr_phy_init_RU(oru.ru);
|
||||
fill_rf_config(ru, ru->rf_config_file);
|
||||
ru->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe);
|
||||
|
||||
while (oai_exit == 0)
|
||||
/* set PRACH configuration */
|
||||
nfapi_nr_prach_config_t *prach_config = &ru->config.prach_config;
|
||||
prach_config->prach_ConfigurationIndex.value = oru.prach_config_index;
|
||||
prach_config->num_prach_fd_occasions_list[0].k1.value = oru.prach_msg1_freq;
|
||||
prach_config->prach_sequence_length.value = 1;
|
||||
prach_config->prach_sub_c_spacing.value = 1;
|
||||
prach_config->num_prach_fd_occasions.value = 1;
|
||||
|
||||
reset_meas(&oru.rx_prach);
|
||||
oru.prach_info = get_nr_prach_occasion_info_from_index(oru.prach_config_index, FR1, fp->frame_type);
|
||||
LOG_A(PHY, "PRACH configuration index %d\n", oru.prach_config_index);
|
||||
LOG_A(PHY,
|
||||
"PRACH format %d start_symbol %d duration %d\n",
|
||||
oru.prach_info.format,
|
||||
oru.prach_info.start_symbol,
|
||||
oru.prach_info.N_dur);
|
||||
prepare_prach_item(&oru);
|
||||
|
||||
oru.fronthaul = oru_fh_init(&oru.fh_config);
|
||||
AssertFatal(oru.fronthaul != NULL, "Cannot configure oru fronthaul, check your config file/cmdline");
|
||||
|
||||
LOG_I(PHY, "starting vrtsim\n");
|
||||
ret = openair0_load(&ru->rfdevice, "vrtsim", &ru->openair0_cfg, NULL);
|
||||
AssertFatal(ret == 0, "RU %u: openair0_load() ret %d: cannot initialize vrtsim\n", ru->idx, ret);
|
||||
ret = ru->rfdevice.trx_start_func(&ru->rfdevice);
|
||||
AssertFatal(ret == 0, "RU %u: trx_start_func() ret %d: cannot start vrtsim\n", ru->idx, ret);
|
||||
|
||||
threadCreate(&oru.north_read_thread, oru_north_read_thread, (void *)&oru, "north_read_thread", -1, OAI_PRIORITY_RT_MAX);
|
||||
threadCreate(&oru.south_read_thread, oru_south_read_thread, (void *)&oru, "south_read_thread", -1, OAI_PRIORITY_RT_MAX);
|
||||
usleep(1000);
|
||||
oru_fh_start(oru.fronthaul);
|
||||
|
||||
// Signal handler
|
||||
signal(SIGINT, sig_handler);
|
||||
|
||||
while (oai_exit == 0) {
|
||||
oru_fh_print_stats(oru.fronthaul);
|
||||
sleep(1);
|
||||
// stop threads
|
||||
}
|
||||
|
||||
kill_NR_RU_proc(0);
|
||||
pthread_join(oru.north_read_thread, NULL);
|
||||
pthread_join(oru.south_read_thread, NULL);
|
||||
|
||||
end_configmodule(uniqCfg);
|
||||
oru_fh_stop(oru.fronthaul);
|
||||
|
||||
if (ru->rfdevice.trx_stop_func) {
|
||||
ru->rfdevice.trx_stop_func(&ru->rfdevice);
|
||||
ru->rfdevice.trx_stop_func = NULL;
|
||||
}
|
||||
|
||||
if (ru->rfdevice.trx_end_func) {
|
||||
ru->rfdevice.trx_end_func(&ru->rfdevice);
|
||||
ru->rfdevice.trx_end_func = NULL;
|
||||
}
|
||||
|
||||
if (ru->ifdevice.trx_end_func) {
|
||||
ru->ifdevice.trx_end_func(&ru->ifdevice);
|
||||
ru->ifdevice.trx_end_func = NULL;
|
||||
}
|
||||
end_configmodule(uniqCfg);
|
||||
|
||||
logClean();
|
||||
printf("Bye.\n");
|
||||
|
||||
@@ -172,13 +172,17 @@ static void rx_func(processingData_L1_t *info)
|
||||
if (gNB->phase_comp) {
|
||||
//apply the rx signal rotation here
|
||||
int soffset = (slot_rx % RU_RX_SLOT_DEPTH) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size;
|
||||
for (int aa = 0; aa < gNB->frame_parms.nb_antennas_tx; aa++) {
|
||||
const uint max_symb = (gNB->frame_parms.Ncp == NR_EXTENDED) ? 12 : 14;
|
||||
const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
for (int aa = 0; aa < fp->nb_antennas_rx; aa++) {
|
||||
const uint max_symb = fp->Ncp == NR_EXTENDED ? 12 : 14;
|
||||
for (int sym = 0; sym < max_symb; sym++)
|
||||
apply_nr_rotation_symbol_RX(&gNB->frame_parms,
|
||||
gNB->common_vars.rxdataF[aa] + soffset + sym * gNB->frame_parms.ofdm_symbol_size,
|
||||
gNB->frame_parms.symbol_rotation[1],
|
||||
gNB->frame_parms.N_RB_UL,
|
||||
apply_nr_rotation_symbol_RX(fp->symbols_per_slot,
|
||||
fp->slots_per_subframe,
|
||||
fp->timeshift_symbol_rotation,
|
||||
fp->first_carrier_offset,
|
||||
gNB->common_vars.rxdataF[aa] + soffset + sym * fp->ofdm_symbol_size,
|
||||
fp->symbol_rotation[1],
|
||||
fp->N_RB_UL,
|
||||
slot_rx,
|
||||
sym);
|
||||
}
|
||||
|
||||
766
executables/nr-oru.c
Normal file
766
executables/nr-oru.c
Normal file
@@ -0,0 +1,766 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/system.h"
|
||||
#include "nr-oru.h"
|
||||
#include "openair1/PHY/defs_nr_common.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "oru_packet_processor.h"
|
||||
#include <time.h>
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
#include "openair1/SCHED_NR/sched_nr.h"
|
||||
#include "openair1/PHY/MODULATION/modulation_common.h"
|
||||
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
|
||||
#define CONFIG_SECTION_ORU "ORUs.[0]"
|
||||
|
||||
#define CONFIG_STRING_ORU_TX_BW_LIST "tx_bw"
|
||||
#define CONFIG_STRING_ORU_RX_BW_LIST "rx_bw"
|
||||
#define CONFIG_STRING_ORU_CARRIER_TX_LIST "carrier_tx"
|
||||
#define CONFIG_STRING_ORU_CARRIER_RX_LIST "carrier_rx"
|
||||
#define CONFIG_STRING_ORU_FRAME_TYPE "frame_type"
|
||||
#define CONFIG_STRING_ORU_PRACH_CONFIGID "prach_config_index"
|
||||
#define CONFIG_STRING_ORU_PRACH_MSG1FREQ "prach_msg1_start"
|
||||
#define CONFIG_STRING_ORU_NUMEROLOGY "mu"
|
||||
#define CONFIG_STRING_ORU_TDD_PERIOD "tdd_period"
|
||||
#define CONFIG_STRING_ORU_NUM_DL_SLOTS "num_dl_slots"
|
||||
#define CONFIG_STRING_ORU_NUM_UL_SLOTS "num_ul_slots"
|
||||
#define CONFIG_STRING_ORU_NUM_DL_SYMBOLS "num_dl_symbols"
|
||||
#define CONFIG_STRING_ORU_NUM_UL_SYMBOLS "num_ul_symbols"
|
||||
|
||||
#define HLP_ORU_TX_BW "set the TX bandwidth list per component carrier"
|
||||
#define HLP_ORU_RX_BW "set the RX bandwidth list per component carrier"
|
||||
#define HLP_ORU_CARRIER_TX "set the TX carrier frequencies per component carrier"
|
||||
#define HLP_ORU_CARRIER_RX "set the RX carrier frequencies per component carrier"
|
||||
#define HLP_ORU_FRAMETYPE "set the Frame type TDD/FDD of all component carriers"
|
||||
#define HLP_ORU_PRACH_CONFIGID "set the PRACH configuration id of all component carriers"
|
||||
#define HLP_ORU_PRACH_MSG1FREQ "set the PRACH MSG1 frequency of all component carriers"
|
||||
#define HLP_ORU_NUMEROLOGY "set the numerology of the RU"
|
||||
#define HLP_ORU_TDD_PERIOD "set the 3GPP TDD periodificty 0-9"
|
||||
#define HLP_ORU_NUM_DL_SLOTS "set the number of DL Slots in TDD"
|
||||
#define HLP_ORU_NUM_UL_SLOTS "set the number of UL Slots in TDD"
|
||||
#define HLP_ORU_NUM_DL_SYMBOLS "set the number of DL symbols in the mixed slot"
|
||||
#define HLP_ORU_NUM_UL_SYMBOLS "set the number of UL symbols in the mixed slot"
|
||||
|
||||
// clang-format off
|
||||
#define CMDLINE_PARAMS_DESC_ORU \
|
||||
{ \
|
||||
{CONFIG_STRING_ORU_TX_BW_LIST, HLP_ORU_TX_BW, 0, .iptr=NULL, .defintarrayval=DEFBW, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_ORU_RX_BW_LIST, HLP_ORU_RX_BW, 0, .iptr=NULL, .defintarrayval=DEFBW, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_ORU_CARRIER_TX_LIST, HLP_ORU_CARRIER_TX, 0, .iptr=NULL, .defintarrayval=DEFCARRIER, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_ORU_CARRIER_RX_LIST, HLP_ORU_CARRIER_RX, 0, .iptr=NULL, .defintarrayval=DEFCARRIER, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_ORU_FRAME_TYPE, HLP_ORU_FRAMETYPE, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_PRACH_CONFIGID, HLP_ORU_PRACH_CONFIGID, 0, .uptr=NULL, .defintval=152, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_PRACH_MSG1FREQ, HLP_ORU_PRACH_MSG1FREQ, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_NUMEROLOGY, HLP_ORU_NUMEROLOGY, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_TDD_PERIOD, HLP_ORU_TDD_PERIOD, 0, .uptr=NULL, .defintval=5, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_NUM_DL_SLOTS, HLP_ORU_NUM_DL_SLOTS, 0, .uptr=NULL, .defintval=3, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_NUM_UL_SLOTS, HLP_ORU_NUM_UL_SLOTS, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_NUM_DL_SYMBOLS, HLP_ORU_NUM_DL_SYMBOLS, 0, .uptr=NULL, .defintval=7, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ORU_NUM_UL_SYMBOLS, HLP_ORU_NUM_UL_SYMBOLS, 0, .uptr=NULL, .defintval=3, TYPE_UINT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
#define CONFIG_SECTION_ORU_FH "ORUs.[0].fronthaul"
|
||||
|
||||
#define CONFIG_STRING_ORU_DPDK_DEVICES "dpdk_devices"
|
||||
#define CONFIG_STRING_RX_CORE "rx_core"
|
||||
#define CONFIG_STRING_EXTRA_EAL_ARGS "extra_eal_args"
|
||||
#define CONFIG_STRING_DU_MAC_ADDRESSES "du_mac_addr"
|
||||
#define CONFIG_STRING_MTU "mtu"
|
||||
#define CONFIG_STRING_T2A_UP "T2a_up"
|
||||
#define CONFIG_STRING_T2A_CP "T2a_cp"
|
||||
#define CONFIG_STRING_PRACH_EAXC_OFFSET "prach_eaxc_offset"
|
||||
|
||||
#define HLP_DPDK_DEVICES "DPDK devices to use for the O-RU."
|
||||
#define HLP_RX_CORE "The CPU core to be used to deploy dpdk RX worker for O-RU."
|
||||
#define HLP_EXTRA_EAL_ARGS "Extra arguments passed to RTE_EAL_INIT."
|
||||
#define HLP_DU_MAC_ADDRESSES "DU MAC addreses, used to prepare Ethernet headers."
|
||||
#define HLP_MTU "MTU for RX and TX."
|
||||
#define HLP_PRACH_EAXC_OFFSET "PRACH eAxC offset."
|
||||
|
||||
// clang-format off
|
||||
#define CMDLINE_PARAMS_DESC_ORU_FH \
|
||||
{ \
|
||||
{CONFIG_STRING_ORU_DPDK_DEVICES, HLP_DPDK_DEVICES, PARAMFLAG_MANDATORY, .strptr=NULL, .defstrval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{CONFIG_STRING_RX_CORE, HLP_RX_CORE, PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_EXTRA_EAL_ARGS, HLP_EXTRA_EAL_ARGS, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{CONFIG_STRING_DU_MAC_ADDRESSES, HLP_DU_MAC_ADDRESSES, PARAMFLAG_MANDATORY, .strptr=NULL, .defstrval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{CONFIG_STRING_MTU, HLP_MTU, 0, .iptr=NULL, .defintval=9600, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_T2A_UP, "", 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_T2A_CP, "", 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \
|
||||
{CONFIG_STRING_PRACH_EAXC_OFFSET, HLP_PRACH_EAXC_OFFSET, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0} \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
extern void set_scs_parameters(NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL, int ssb_case);
|
||||
void tx_rf_symbols(RU_t *ru, int frame, int slot, uint64_t timestamp, int start_symbol, int num_symbols);
|
||||
|
||||
void prepare_prach_item(ORU_t *oru)
|
||||
{
|
||||
AssertFatal(oru->ru != NULL, "ORU not configured\n");
|
||||
AssertFatal(oru->ru->nr_frame_parms != NULL, "ORU not configured\n");
|
||||
NR_DL_FRAME_PARMS *fp = oru->ru->nr_frame_parms;
|
||||
RU_t *ru = oru->ru;
|
||||
prach_item_t *prach_item = &oru->prach_item;
|
||||
prach_item->num_slots = oru->prach_info.format < 4 ? get_long_prach_dur(oru->prach_info.format, fp->numerology_index) : 1;
|
||||
prach_item->msg1_frequencystart = oru->prach_msg1_freq;
|
||||
prach_item->mu = fp->numerology_index;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
prach_item->prach_sequence_length = cfg->prach_config.prach_sequence_length.value;
|
||||
prach_item->restricted_set = 0;
|
||||
prach_item->numerology_index = fp->numerology_index;
|
||||
prach_item->nb_rx = ru->nb_rx;
|
||||
prach_item->rx_prach = &oru->rx_prach;
|
||||
|
||||
// Fill PRACH PDU
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &prach_item->pdu;
|
||||
prach_pdu->prach_start_symbol = oru->prach_info.start_symbol;
|
||||
prach_pdu->num_prach_ocas = 1; // TODO: Hardcoded.
|
||||
|
||||
uint16_t format0 = oru->prach_info.format & 0xff;
|
||||
uint16_t format1 = (oru->prach_info.format >> 8) & 0xff;
|
||||
if (format1 != 0xff) {
|
||||
switch (format0) {
|
||||
case 0xa1:
|
||||
prach_pdu->prach_format = 11;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_pdu->prach_format = 12;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_pdu->prach_format = 13;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
|
||||
}
|
||||
} else {
|
||||
switch (format0) {
|
||||
case 0:
|
||||
prach_pdu->prach_format = 0;
|
||||
break;
|
||||
case 1:
|
||||
prach_pdu->prach_format = 1;
|
||||
break;
|
||||
case 2:
|
||||
prach_pdu->prach_format = 2;
|
||||
break;
|
||||
case 3:
|
||||
prach_pdu->prach_format = 3;
|
||||
break;
|
||||
case 0xa1:
|
||||
prach_pdu->prach_format = 4;
|
||||
break;
|
||||
case 0xa2:
|
||||
prach_pdu->prach_format = 5;
|
||||
break;
|
||||
case 0xa3:
|
||||
prach_pdu->prach_format = 6;
|
||||
break;
|
||||
case 0xb1:
|
||||
prach_pdu->prach_format = 7;
|
||||
break;
|
||||
case 0xb4:
|
||||
prach_pdu->prach_format = 8;
|
||||
break;
|
||||
case 0xc0:
|
||||
prach_pdu->prach_format = 9;
|
||||
break;
|
||||
case 0xc2:
|
||||
prach_pdu->prach_format = 10;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid PRACH format");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_oru_options(ORU_t *oru)
|
||||
{
|
||||
int DEFBW[] = {273};
|
||||
int DEFCARRIER[] = {3430560};
|
||||
paramdef_t param[] = CMDLINE_PARAMS_DESC_ORU;
|
||||
int nump = sizeofArray(param);
|
||||
|
||||
int ret = config_get(config_get_if(), param, nump, CONFIG_SECTION_ORU);
|
||||
if (ret <= 0) {
|
||||
LOG_E(NR_PHY, "problem reading section \"%s\"\n", CONFIG_SECTION_ORU);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < oru->ru->num_bands; i++) {
|
||||
oru->bw_tx[i] = gpd(param, nump, CONFIG_STRING_ORU_TX_BW_LIST)->iptr[i];
|
||||
oru->bw_rx[i] = gpd(param, nump, CONFIG_STRING_ORU_RX_BW_LIST)->iptr[i];
|
||||
oru->carrier_freq_tx[i] = gpd(param, nump, CONFIG_STRING_ORU_CARRIER_TX_LIST)->iptr[i];
|
||||
oru->carrier_freq_rx[i] = gpd(param, nump, CONFIG_STRING_ORU_CARRIER_RX_LIST)->iptr[i];
|
||||
}
|
||||
oru->frame_type = *gpd(param, nump, CONFIG_STRING_ORU_FRAME_TYPE)->iptr;
|
||||
oru->prach_config_index = *gpd(param, nump, CONFIG_STRING_ORU_PRACH_CONFIGID)->iptr;
|
||||
oru->prach_msg1_freq = *gpd(param, nump, CONFIG_STRING_ORU_PRACH_MSG1FREQ)->iptr;
|
||||
oru->numerology = *gpd(param, nump, CONFIG_STRING_ORU_NUMEROLOGY)->iptr;
|
||||
oru->tdd_period = *gpd(param, nump, CONFIG_STRING_ORU_TDD_PERIOD)->iptr;
|
||||
oru->num_DL_slots = *gpd(param, nump, CONFIG_STRING_ORU_NUM_DL_SLOTS)->iptr;
|
||||
oru->num_UL_slots = *gpd(param, nump, CONFIG_STRING_ORU_NUM_UL_SLOTS)->iptr;
|
||||
oru->num_DL_symbols = *gpd(param, nump, CONFIG_STRING_ORU_NUM_DL_SYMBOLS)->iptr;
|
||||
oru->num_UL_symbols = *gpd(param, nump, CONFIG_STRING_ORU_NUM_UL_SYMBOLS)->iptr;
|
||||
|
||||
paramdef_t fh_param[] = CMDLINE_PARAMS_DESC_ORU_FH;
|
||||
nump = sizeofArray(fh_param);
|
||||
oru_fh_config_t *fh_cfg = &oru->fh_config;
|
||||
ret = config_get(config_get_if(), fh_param, nump, CONFIG_SECTION_ORU_FH);
|
||||
if (ret <= 0) {
|
||||
printf("problem reading section \"%s\"\n", CONFIG_SECTION_ORU_FH);
|
||||
return -1;
|
||||
}
|
||||
|
||||
oru_fh_dpdk_config_t *dpdk_conf = &fh_cfg->dpdk_conf;
|
||||
int num_dpdk_devices = gpd(fh_param, nump, CONFIG_STRING_ORU_DPDK_DEVICES)->numelt;
|
||||
dpdk_conf->num_dpdk_devices = num_dpdk_devices;
|
||||
AssertFatal(num_dpdk_devices > 0 && num_dpdk_devices <= 2,
|
||||
"Invalid number of DPDK devices (%d). Configure 1 or 2 devices\n",
|
||||
num_dpdk_devices);
|
||||
for (int i = 0; i < num_dpdk_devices; i++) {
|
||||
dpdk_conf->dpdk_devices[i] = gpd(fh_param, nump, CONFIG_STRING_ORU_DPDK_DEVICES)->strlistptr[i];
|
||||
}
|
||||
dpdk_conf->extra_eal_args = gpd(fh_param, nump, CONFIG_STRING_EXTRA_EAL_ARGS)->strlistptr;
|
||||
dpdk_conf->num_extra_eal_args = gpd(fh_param, nump, CONFIG_STRING_EXTRA_EAL_ARGS)->numelt;
|
||||
|
||||
fh_cfg->num_du_mac_addrs = gpd(fh_param, nump, CONFIG_STRING_DU_MAC_ADDRESSES)->numelt;
|
||||
for (int i = 0; i < fh_cfg->num_du_mac_addrs; i++) {
|
||||
fh_cfg->du_mac_addrs[i] = gpd(fh_param, nump, CONFIG_STRING_DU_MAC_ADDRESSES)->strlistptr[i];
|
||||
AssertFatal(strlen(fh_cfg->du_mac_addrs[i]) == 17, "Invalid MAC address\n");
|
||||
}
|
||||
fh_cfg->enable_compression = false;
|
||||
fh_cfg->rx_core = *gpd(fh_param, nump, CONFIG_STRING_RX_CORE)->iptr;
|
||||
fh_cfg->mtu = *gpd(fh_param, nump, CONFIG_STRING_MTU)->iptr;
|
||||
fh_cfg->num_prbs = oru->bw_tx[0];
|
||||
fh_cfg->numerology = oru->numerology;
|
||||
fh_cfg->prach_eaxc_offset = *gpd(fh_param, nump, CONFIG_STRING_PRACH_EAXC_OFFSET)->iptr;
|
||||
|
||||
AssertFatal(gpd(fh_param, nump, CONFIG_STRING_T2A_UP)->numelt == 2, "Two parameters required for %s\n", CONFIG_STRING_T2A_UP);
|
||||
fh_cfg->T2a_up_min_uS = gpd(fh_param, nump, CONFIG_STRING_T2A_UP)->iptr[0];
|
||||
fh_cfg->T2a_up_max_uS = gpd(fh_param, nump, CONFIG_STRING_T2A_UP)->iptr[1];
|
||||
AssertFatal(fh_cfg->T2a_up_min_uS <= fh_cfg->T2a_up_max_uS,
|
||||
"T2a max (%d) has to be greater than T2a min (%d)\n",
|
||||
fh_cfg->T2a_up_max_uS,
|
||||
fh_cfg->T2a_up_min_uS);
|
||||
|
||||
AssertFatal(gpd(fh_param, nump, CONFIG_STRING_T2A_CP)->numelt == 2, "Two parameters required for %s\n", CONFIG_STRING_T2A_CP);
|
||||
fh_cfg->T2a_cp_min_uS = gpd(fh_param, nump, CONFIG_STRING_T2A_CP)->iptr[0];
|
||||
fh_cfg->T2a_cp_max_uS = gpd(fh_param, nump, CONFIG_STRING_T2A_CP)->iptr[1];
|
||||
AssertFatal(fh_cfg->T2a_cp_min_uS <= fh_cfg->T2a_cp_max_uS,
|
||||
"T2a max (%d) has to be greater than T2a min (%d)\n",
|
||||
fh_cfg->T2a_cp_max_uS,
|
||||
fh_cfg->T2a_cp_min_uS);
|
||||
|
||||
oru_fh_tdd_pattern_t *tdd_pattern = &fh_cfg->tdd_pattern;
|
||||
tdd_pattern->num_dl_slots = oru->num_DL_slots;
|
||||
tdd_pattern->num_ul_slots = oru->num_UL_slots;
|
||||
tdd_pattern->num_dl_symbols = oru->num_DL_symbols;
|
||||
tdd_pattern->num_ul_symbols = oru->num_UL_symbols;
|
||||
int num_slots_frame = (1 << oru->numerology) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
int num_period_frame = get_nb_periods_per_frame(oru->tdd_period);
|
||||
int num_slots_period = num_slots_frame / num_period_frame;
|
||||
tdd_pattern->tdd_pattern_length_slots = num_slots_period;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void oru_init_frame_parms(ORU_t *oru)
|
||||
{
|
||||
RU_t *ru = oru->ru;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
fp->frame_type = oru->frame_type;
|
||||
ru->config.cell_config.frame_duplex_type.value = oru->frame_type;
|
||||
ru->config.cell_config.frame_duplex_type.tl.tag = 0x100D;
|
||||
fp->N_RB_DL = oru->bw_tx[0];
|
||||
ru->config.ssb_config.scs_common.value = ru->numerology;
|
||||
ru->config.carrier_config.dl_grid_size[ru->config.ssb_config.scs_common.value].value = oru->bw_tx[0];
|
||||
fp->N_RB_UL = oru->bw_rx[0];
|
||||
ru->config.carrier_config.ul_grid_size[ru->config.ssb_config.scs_common.value].value = oru->bw_rx[0];
|
||||
fp->numerology_index = ru->numerology;
|
||||
LOG_I(NR_PHY,
|
||||
"Set RU frame type to %s, N_RB_DL %d, N_RB_UL %d, mu %d\n",
|
||||
oru->frame_type == TDD ? "TDD" : "FDD",
|
||||
oru->bw_tx[0],
|
||||
oru->bw_rx[0],
|
||||
ru->numerology);
|
||||
set_scs_parameters(fp, fp->numerology_index, oru->bw_tx[0], 0);
|
||||
fp->slots_per_frame = 10 * fp->slots_per_subframe;
|
||||
fp->nb_antennas_rx = ru->nb_rx;
|
||||
fp->nb_antennas_tx = ru->nb_tx;
|
||||
fp->symbols_per_slot = 14;
|
||||
fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe;
|
||||
fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP;
|
||||
fp->samples_per_slot_wCP = fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
fp->samples_per_slotN0 = (fp->nb_prefix_samples + fp->ofdm_symbol_size) * fp->symbols_per_slot;
|
||||
fp->samples_per_slot0 =
|
||||
fp->nb_prefix_samples0 + ((fp->symbols_per_slot - 1) * fp->nb_prefix_samples) + (fp->symbols_per_slot * fp->ofdm_symbol_size);
|
||||
fp->samples_per_subframe = (fp->nb_prefix_samples0 + fp->ofdm_symbol_size) * 2
|
||||
+ (fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2);
|
||||
fp->samples_per_frame = 10 * fp->samples_per_subframe;
|
||||
fp->freq_range = (oru->carrier_freq_tx[0] < 6e6) ? FR1 : FR2;
|
||||
|
||||
fp->dl_CarrierFreq = (double)oru->carrier_freq_tx[0] * 1000;
|
||||
fp->ul_CarrierFreq = (double)oru->carrier_freq_rx[0] * 1000;
|
||||
fp->Ncp = NORMAL;
|
||||
fp->ofdm_offset_divisor = 8;
|
||||
|
||||
// Split 7.2 parameters
|
||||
ru->config.prach_config.num_prach_fd_occasions.value = 1;
|
||||
ru->config.prach_config.prach_ConfigurationIndex.value = oru->prach_config_index;
|
||||
ru->config.prach_config.prach_ConfigurationIndex.tl.tag = 0x1029;
|
||||
ru->config.prach_config.num_prach_fd_occasions_list = malloc(sizeof(*ru->config.prach_config.num_prach_fd_occasions_list));
|
||||
ru->config.prach_config.num_prach_fd_occasions_list[0].k1.value = oru->prach_msg1_freq;
|
||||
if (ru->config.cell_config.frame_duplex_type.value == 1 /* TDD */) {
|
||||
ru->config.tdd_table.tdd_period.value = oru->tdd_period;
|
||||
ru->config.tdd_table.tdd_period.tl.tag = 0x1026;
|
||||
int numb_slots_frame = (1 << ru->numerology) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
int numb_period_frame = get_nb_periods_per_frame(oru->tdd_period);
|
||||
int numb_slots_period = numb_slots_frame / numb_period_frame;
|
||||
ru->config.tdd_table.max_tdd_periodicity_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list) * (numb_slots_frame));
|
||||
for (int n = 0; n < numb_slots_frame; n++) {
|
||||
int s = 0;
|
||||
int p = n % numb_slots_period;
|
||||
if (p < oru->num_DL_slots) {
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list) * NR_SYMBOLS_PER_SLOT);
|
||||
for (s = 0; s < 14; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 0;
|
||||
} else if (p == oru->num_DL_slots) {
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list) * NR_SYMBOLS_PER_SLOT);
|
||||
for (s = 0; s < oru->num_DL_symbols; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 0;
|
||||
for (; s < NR_SYMBOLS_PER_SLOT - oru->num_UL_symbols; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 2;
|
||||
for (; s < NR_SYMBOLS_PER_SLOT; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 1;
|
||||
} else {
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list =
|
||||
malloc(sizeof(*ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list) * NR_SYMBOLS_PER_SLOT);
|
||||
for (s = 0; s < NR_SYMBOLS_PER_SLOT; s++)
|
||||
ru->config.tdd_table.max_tdd_periodicity_list[n].max_num_of_symbol_per_slot_list[s].slot_config.value = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fft_and_cp_insertion(NR_DL_FRAME_PARMS *fp, c16_t *txdataF, c16_t *txdata, int slot, int symbol)
|
||||
{
|
||||
if (fp->Ncp == 1) {
|
||||
PHY_ofdm_mod((int *)txdataF, (int *)txdata, fp->ofdm_symbol_size, 1, fp->nb_prefix_samples, CYCLIC_PREFIX);
|
||||
} else {
|
||||
if (fp->numerology_index != 0) {
|
||||
if (!(slot % (fp->slots_per_subframe / 2)) && (symbol == 0)) {
|
||||
PHY_ofdm_mod((int *)txdataF, (int *)txdata, fp->ofdm_symbol_size, 1, fp->nb_prefix_samples0, CYCLIC_PREFIX);
|
||||
} else {
|
||||
PHY_ofdm_mod((int *)txdataF, (int *)txdata, fp->ofdm_symbol_size, 1, fp->nb_prefix_samples, CYCLIC_PREFIX);
|
||||
}
|
||||
} else {
|
||||
if (symbol % 0x7) {
|
||||
PHY_ofdm_mod((int *)txdataF, (int *)txdata, fp->ofdm_symbol_size, 1, fp->nb_prefix_samples, CYCLIC_PREFIX);
|
||||
} else {
|
||||
PHY_ofdm_mod((int *)txdataF, (int *)txdata, fp->ofdm_symbol_size, 1, fp->nb_prefix_samples0, CYCLIC_PREFIX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dl_symbol_process(RU_t *ru, int frame, int slot, int symbol, c16_t **txDataF, int64_t timestamp)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
uint32_t slot_offset = get_samples_slot_timestamp(fp, slot);
|
||||
uint32_t symbol_offset = get_samples_symbol_timestamp(fp, slot, symbol);
|
||||
|
||||
__attribute__((aligned(64))) c16_t txdataF_shifted[fp->ofdm_symbol_size];
|
||||
memset(txdataF_shifted, 0, sizeof(txdataF_shifted));
|
||||
c16_t *rotation = fp->symbol_rotation[0] + (slot % fp->slots_per_subframe) * fp->symbols_per_slot + symbol;
|
||||
for (int aatx = 0; aatx < ru->nb_tx; aatx++) {
|
||||
// Phase compensation
|
||||
rotate_cpx_vector(txDataF[aatx], *rotation, txDataF[aatx], fp->N_RB_DL * NR_NB_SC_PER_RB, 15);
|
||||
// FFT Shift
|
||||
const int num_samp_half = fp->N_RB_DL * NR_NB_SC_PER_RB / 2;
|
||||
const int first_carrier_offset = fp->ofdm_symbol_size - num_samp_half;
|
||||
memcpy(txdataF_shifted + first_carrier_offset, txDataF[aatx], num_samp_half * sizeof(c16_t));
|
||||
memcpy(txdataF_shifted, txDataF[aatx] + num_samp_half, num_samp_half * sizeof(c16_t));
|
||||
fft_and_cp_insertion(ru->nr_frame_parms,
|
||||
txdataF_shifted,
|
||||
(c16_t *)&ru->common.txdata[aatx][slot_offset + symbol_offset],
|
||||
slot,
|
||||
symbol);
|
||||
}
|
||||
tx_rf_symbols(ru, frame, slot, timestamp, symbol, 1);
|
||||
}
|
||||
|
||||
void *oru_north_read_thread(void *arg)
|
||||
{
|
||||
ORU_t *oru = (ORU_t *)arg;
|
||||
|
||||
RU_t *ru = (RU_t *)oru->ru;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
__attribute__((aligned(64))) c16_t txDataF[ru->nb_tx][fp->N_RB_DL * NR_NB_SC_PER_RB];
|
||||
memset(txDataF, 0, sizeof(txDataF));
|
||||
c16_t *txDataF_ptr[ru->nb_tx];
|
||||
for (int aatx = 0; aatx < ru->nb_tx; aatx++) {
|
||||
txDataF_ptr[aatx] = txDataF[aatx];
|
||||
}
|
||||
uint32_t start_frame, start_slot;
|
||||
uint64_t start_hyper_frame;
|
||||
struct timespec utc_anchor_point;
|
||||
oru_fh_get_utc_anchor_point(oru->fronthaul, &start_hyper_frame, &start_frame, &start_slot, &utc_anchor_point);
|
||||
AssertFatal(ru->rfdevice.get_timestamp != NULL, "rfdevice has no capability to translate UTC timestamp to sample index\n");
|
||||
int64_t start_timestamp = ru->rfdevice.get_timestamp(&ru->rfdevice, &utc_anchor_point);
|
||||
// subtract the start_frame and start_slot from the timestamp simplify calculation below.
|
||||
start_timestamp -= (start_frame * fp->samples_per_frame + get_samples_slot_timestamp(fp, start_slot));
|
||||
// Now start_timestamp points to the start sample of the frame 0 slot 0 symbol 0 of hyperframe 0
|
||||
LOG_A(PHY, "DL thread started: start_timestamp %ld, start_frame %d, start_slot %d\n", start_timestamp, start_frame, start_slot);
|
||||
|
||||
while (!oai_exit) {
|
||||
int frame = -1, slot = -1, symbol = -1;
|
||||
uint64_t hyper_frame;
|
||||
int ret = oru_fh_tx_read_symbol(oru->fronthaul, (uint32_t **)txDataF_ptr, ru->nb_tx, &hyper_frame, &frame, &slot, &symbol);
|
||||
if (ret != 0) {
|
||||
LOG_E(PHY, "[RU_thread] read data error: frame %d, slot %d, symbol %d\n", frame, slot, symbol);
|
||||
continue;
|
||||
}
|
||||
if (start_hyper_frame > hyper_frame) {
|
||||
continue;
|
||||
}
|
||||
uint64_t num_frames = (hyper_frame - start_hyper_frame) * 1024 + frame;
|
||||
int64_t timestamp = start_timestamp + num_frames * fp->samples_per_frame + get_samples_slot_timestamp(fp, slot)
|
||||
+ get_samples_symbol_timestamp(fp, slot, symbol);
|
||||
if (timestamp < 0) {
|
||||
continue;
|
||||
}
|
||||
dl_symbol_process(ru, frame, slot, symbol, txDataF_ptr, timestamp);
|
||||
if (frame % 256 == 0 && slot == 0 && symbol == 0) {
|
||||
LOG_I(PHY, "[RU_thread] read data: frame %d, slot %d, symbol %d\n", frame, slot, symbol);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns PRACH symbol that was received in current frame, slot and symbol.
|
||||
// If no PRACH symbol was received, returns -1
|
||||
int get_prach_symbol(ORU_t *oru, int frame, int slot, int symbol, int numerology)
|
||||
{
|
||||
uint16_t RA_sfn_index;
|
||||
AssertFatal(oru->ru->nr_frame_parms->frame_type == TDD, "Only supports TDD\n");
|
||||
if (get_nr_prach_sched_from_info(oru->prach_info, oru->prach_config_index, frame, slot, numerology, FR1, &RA_sfn_index, true)) {
|
||||
int format = oru->prach_item.pdu.prach_format;
|
||||
int start_symbol = oru->prach_item.pdu.prach_start_symbol;
|
||||
symbol -= start_symbol;
|
||||
// TODO: Support more PRACH formats
|
||||
AssertFatal(format == 8, "only support format B4\n");
|
||||
// TODO: This is not exactly the case but it is correct
|
||||
if (symbol >= 0 && symbol < 12) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void receive_prach(ORU_t *oru, int frame, int slot, int symbol, int prach_symbol)
|
||||
{
|
||||
RU_t *ru = oru->ru;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
oru->prach_item.frame = frame;
|
||||
oru->prach_item.slot = slot;
|
||||
|
||||
c16_t rxdataF[ru->nb_rx][NR_PRACH_SEQ_LEN_L];
|
||||
memset(rxdataF, 0, sizeof(rxdataF));
|
||||
|
||||
rx_nr_prach_ru_rep(&oru->prach_item,
|
||||
ru->common.rxdata,
|
||||
fp,
|
||||
ru->N_TA_offset,
|
||||
prach_symbol,
|
||||
0, // prachOccasion
|
||||
rxdataF);
|
||||
|
||||
c16_t *rxdataF_ptr[ru->nb_rx];
|
||||
for (int aarx = 0; aarx < ru->nb_rx; aarx++) {
|
||||
rxdataF_ptr[aarx] = rxdataF[aarx];
|
||||
}
|
||||
oru_fh_rx_send_prach(oru->fronthaul, (uint32_t **)rxdataF_ptr, ru->nb_rx, frame, slot, symbol);
|
||||
}
|
||||
|
||||
#define MAX_PENDING_UL_JOBS 64
|
||||
|
||||
typedef struct {
|
||||
ul_job_t job;
|
||||
bool active;
|
||||
int symbols_sent;
|
||||
} ul_pending_t;
|
||||
|
||||
static void receive_pusch(ORU_t *oru, int frame, int slot, int symbol, ul_job_t *job)
|
||||
{
|
||||
RU_t *ru = oru->ru;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int aarx = job->antenna_id;
|
||||
|
||||
if (aarx < 0 || aarx >= fp->nb_antennas_rx) {
|
||||
LOG_W(PHY, "[ORU south] receive_pusch: invalid antenna_id %d\n", aarx);
|
||||
return;
|
||||
}
|
||||
|
||||
// CP removal + FFT → full ofdm_symbol_size frequency-domain output
|
||||
c16_t rxdataF_fft[fp->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
nr_symbol_fep_ul(fp, (c16_t *)ru->common.rxdata[aarx], rxdataF_fft, symbol, slot, ru->N_TA_offset);
|
||||
|
||||
// Phase decompensation (conjugate rotation for UL)
|
||||
apply_nr_rotation_symbol_RX(fp->symbols_per_slot,
|
||||
fp->slots_per_subframe,
|
||||
fp->timeshift_symbol_rotation,
|
||||
fp->first_carrier_offset,
|
||||
rxdataF_fft,
|
||||
fp->symbol_rotation[link_type_ul],
|
||||
fp->N_RB_UL,
|
||||
slot,
|
||||
symbol);
|
||||
|
||||
// Inverse FFT shift: split format → contiguous PRB format sent to DU.
|
||||
// DL TX shift: contiguous[0..N/2-1] → FFT_input[first_carrier_offset..] (negative freqs)
|
||||
// contiguous[N/2..N-1] → FFT_input[0..N/2-1] (positive freqs)
|
||||
// UL RX inverse: FFT_out[first_carrier_offset..] → contiguous[0..N/2-1]
|
||||
// FFT_out[0..N/2-1] → contiguous[N/2..N-1]
|
||||
const int num_samp_half = fp->N_RB_UL * NR_NB_SC_PER_RB / 2;
|
||||
const int first_carrier_offset = fp->ofdm_symbol_size - num_samp_half;
|
||||
c16_t rxdataF[fp->N_RB_UL * NR_NB_SC_PER_RB];
|
||||
memcpy(rxdataF, rxdataF_fft + first_carrier_offset, num_samp_half * sizeof(c16_t));
|
||||
memcpy(rxdataF + num_samp_half, rxdataF_fft, num_samp_half * sizeof(c16_t));
|
||||
|
||||
oru_fh_rx_send_pusch(oru->fronthaul, (uint32_t *)rxdataF, symbol, job);
|
||||
}
|
||||
|
||||
#define UL_WORK_QUEUE_DEPTH 128
|
||||
|
||||
typedef struct {
|
||||
ORU_t *oru;
|
||||
int frame;
|
||||
int slot;
|
||||
int symbol;
|
||||
ul_job_t job;
|
||||
} ul_work_item_t;
|
||||
|
||||
typedef struct {
|
||||
ul_work_item_t ring[UL_WORK_QUEUE_DEPTH];
|
||||
int head;
|
||||
int tail;
|
||||
int count;
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t work_available;
|
||||
pthread_cond_t space_available;
|
||||
bool running;
|
||||
} ul_work_queue_t;
|
||||
|
||||
static void *ul_worker_thread(void *arg)
|
||||
{
|
||||
ul_work_queue_t *q = arg;
|
||||
while (1) {
|
||||
pthread_mutex_lock(&q->lock);
|
||||
while (q->count == 0 && q->running)
|
||||
pthread_cond_wait(&q->work_available, &q->lock);
|
||||
if (!q->running && q->count == 0) {
|
||||
pthread_mutex_unlock(&q->lock);
|
||||
break;
|
||||
}
|
||||
ul_work_item_t item = q->ring[q->head];
|
||||
q->head = (q->head + 1) % UL_WORK_QUEUE_DEPTH;
|
||||
q->count--;
|
||||
pthread_cond_signal(&q->space_available);
|
||||
pthread_mutex_unlock(&q->lock);
|
||||
|
||||
receive_pusch(item.oru, item.frame, item.slot, item.symbol, &item.job);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dispatch_ul_work(ul_work_queue_t *q, ORU_t *oru, int frame, int slot, int symbol, const ul_job_t *job)
|
||||
{
|
||||
pthread_mutex_lock(&q->lock);
|
||||
while (q->count == UL_WORK_QUEUE_DEPTH)
|
||||
pthread_cond_wait(&q->space_available, &q->lock);
|
||||
q->ring[q->tail] = (ul_work_item_t){.oru = oru, .frame = frame, .slot = slot, .symbol = symbol, .job = *job};
|
||||
q->tail = (q->tail + 1) % UL_WORK_QUEUE_DEPTH;
|
||||
q->count++;
|
||||
pthread_cond_signal(&q->work_available);
|
||||
pthread_mutex_unlock(&q->lock);
|
||||
}
|
||||
|
||||
void *oru_south_read_thread(void *arg)
|
||||
{
|
||||
ORU_t *oru = arg;
|
||||
RU_t *ru = oru->ru;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
struct timespec utc_anchor_point;
|
||||
AssertFatal(ru->rfdevice.get_timestamp != NULL, "rfdevice has no capability to translate UTC timestamp to sample index\n");
|
||||
uint32_t start_frame, start_slot;
|
||||
uint64_t hyper_frame;
|
||||
oru_fh_get_utc_anchor_point(oru->fronthaul, &hyper_frame, &start_frame, &start_slot, &utc_anchor_point);
|
||||
int64_t start_timestamp = ru->rfdevice.get_timestamp(&ru->rfdevice, &utc_anchor_point);
|
||||
|
||||
const int num_samples = 3000;
|
||||
c16_t throwaway_samples[ru->nb_rx][num_samples];
|
||||
void *rxp[ru->nb_rx];
|
||||
for (int i = 0; i < ru->nb_rx; i++)
|
||||
rxp[i] = throwaway_samples[i];
|
||||
|
||||
openair0_timestamp_t timestamp;
|
||||
int num_samples_read = ru->rfdevice.trx_read_func(&ru->rfdevice, ×tamp, rxp, num_samples, ru->nb_rx);
|
||||
AssertFatal(num_samples_read == num_samples, "Unexpected number of samples received\n");
|
||||
openair0_timestamp_t next_timestamp = timestamp + num_samples_read;
|
||||
while (next_timestamp > start_timestamp) {
|
||||
start_timestamp += get_samples_slot_duration(fp, start_slot, 1);
|
||||
start_slot++;
|
||||
if (start_slot == fp->slots_per_frame) {
|
||||
start_slot = 0;
|
||||
start_frame++;
|
||||
if (start_frame == 1024) {
|
||||
start_frame = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (next_timestamp < start_timestamp) {
|
||||
int num_samples_to_read = min(num_samples, (int)(start_timestamp - next_timestamp));
|
||||
int num_samples_read = ru->rfdevice.trx_read_func(&ru->rfdevice, ×tamp, rxp, num_samples_to_read, ru->nb_rx);
|
||||
AssertFatal(num_samples_read == num_samples_to_read, "Unexpected number of samples received\n");
|
||||
next_timestamp += num_samples_read;
|
||||
}
|
||||
|
||||
AssertFatal(next_timestamp == start_timestamp, "O-RU South thread could not sync to UTC anchor point\n");
|
||||
|
||||
int slot = start_slot;
|
||||
int frame = start_frame;
|
||||
|
||||
// Worker pool: one thread per RX antenna so all antennas in a symbol process in parallel.
|
||||
const int num_workers = ru->nb_rx;
|
||||
pthread_t workers[num_workers];
|
||||
ul_work_queue_t work_queue = {
|
||||
.lock = PTHREAD_MUTEX_INITIALIZER,
|
||||
.work_available = PTHREAD_COND_INITIALIZER,
|
||||
.space_available = PTHREAD_COND_INITIALIZER,
|
||||
.running = true,
|
||||
};
|
||||
for (int i = 0; i < num_workers; i++) {
|
||||
char name[32];
|
||||
snprintf(name, sizeof(name), "ul_worker_%d", i);
|
||||
threadCreate(&workers[i], ul_worker_thread, &work_queue, name, -1, OAI_PRIORITY_RT_MAX);
|
||||
}
|
||||
|
||||
ul_pending_t pending_ul[MAX_PENDING_UL_JOBS] = {0};
|
||||
|
||||
while (!oai_exit) {
|
||||
int rx_slot_type = nr_slot_select(&ru->config, frame, slot);
|
||||
for (int symbol = 0; symbol < 14; symbol++) {
|
||||
int samples_to_read = get_samples_symbol_duration(fp, slot, symbol, 1);
|
||||
size_t offset = get_samples_slot_timestamp(fp, slot) + get_samples_symbol_timestamp(fp, slot, symbol);
|
||||
c16_t *rxp[fp->nb_antennas_rx];
|
||||
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
|
||||
rxp[aarx] = (c16_t *)&ru->common.rxdata[aarx][offset];
|
||||
}
|
||||
|
||||
openair0_timestamp_t timestamp;
|
||||
int num_samples_read = ru->rfdevice.trx_read_func(&ru->rfdevice, ×tamp, (void **)rxp, samples_to_read, ru->nb_rx);
|
||||
AssertFatal(num_samples_read == samples_to_read, "Unexpected number of samples received\n");
|
||||
LOG_D(PHY,
|
||||
"[ORU south] read data: frame %d, slot %d, symbol %d, timestamp %ld num_symbols %d, samples %d\n",
|
||||
frame,
|
||||
slot,
|
||||
symbol,
|
||||
timestamp,
|
||||
1,
|
||||
num_samples_read);
|
||||
|
||||
// Drain the UL job ring
|
||||
ul_job_t new_job;
|
||||
while (oru_fh_poll_ul_job(oru->fronthaul, &new_job) == 0) {
|
||||
bool added = false;
|
||||
for (int i = 0; i < MAX_PENDING_UL_JOBS; i++) {
|
||||
if (!pending_ul[i].active) {
|
||||
pending_ul[i] = (ul_pending_t){.job = new_job, .active = true, .symbols_sent = 0};
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added)
|
||||
LOG_W(PHY, "[ORU south] UL pending queue full, dropping job frame=%d slot=%d sym=%d\n",
|
||||
new_job.frame, new_job.slot_in_frame, new_job.symbol);
|
||||
}
|
||||
|
||||
if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
|
||||
|
||||
// Process pending jobs whose next symbol matches the current one
|
||||
for (int i = 0; i < MAX_PENDING_UL_JOBS; i++) {
|
||||
if (!pending_ul[i].active)
|
||||
continue;
|
||||
ul_job_t *j = &pending_ul[i].job;
|
||||
|
||||
// Skip jobs scheduled for a future slot or frame, and drop jobs in the past
|
||||
int slots_per_frame = fp->slots_per_frame;
|
||||
int total_slots = 1024 * slots_per_frame;
|
||||
int diff_slots = (j->frame * slots_per_frame + j->slot_in_frame) - (frame * slots_per_frame + slot);
|
||||
if (diff_slots < -total_slots / 2) {
|
||||
diff_slots += total_slots;
|
||||
} else if (diff_slots > total_slots / 2) {
|
||||
diff_slots -= total_slots;
|
||||
}
|
||||
|
||||
if (diff_slots > 0) {
|
||||
// Future slot: skip
|
||||
continue;
|
||||
}
|
||||
if (diff_slots < 0) {
|
||||
// Past slot: drop
|
||||
LOG_W(PHY, "[ORU south] missed UL slot %d.%d (now %d.%d), dropping job ant=%d\n",
|
||||
j->frame, j->slot_in_frame, frame, slot, j->antenna_id);
|
||||
pending_ul[i].active = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Same slot: check symbol
|
||||
int expected_symbol = j->symbol + pending_ul[i].symbols_sent;
|
||||
if (expected_symbol < symbol) {
|
||||
LOG_W(PHY, "[ORU south] missed UL symbol %d (now %d), dropping job ant=%d\n",
|
||||
expected_symbol, symbol, j->antenna_id);
|
||||
pending_ul[i].active = false;
|
||||
} else if (expected_symbol == symbol) {
|
||||
dispatch_ul_work(&work_queue, oru, frame, slot, symbol, j);
|
||||
if (++pending_ul[i].symbols_sent == j->num_symbols)
|
||||
pending_ul[i].active = false;
|
||||
}
|
||||
// expected_symbol > symbol: job spans multiple symbols, revisit next iteration
|
||||
}
|
||||
}
|
||||
int prach_symbol = get_prach_symbol(oru, frame, slot, symbol, ru->numerology);
|
||||
if (prach_symbol != -1)
|
||||
receive_prach(oru, frame, slot, symbol, prach_symbol);
|
||||
}
|
||||
slot++;
|
||||
if (slot == fp->slots_per_frame) {
|
||||
slot = 0;
|
||||
frame++;
|
||||
if (frame == 1024) {
|
||||
frame = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&work_queue.lock);
|
||||
work_queue.running = false;
|
||||
pthread_cond_broadcast(&work_queue.work_available);
|
||||
pthread_mutex_unlock(&work_queue.lock);
|
||||
for (int i = 0; i < num_workers; i++)
|
||||
pthread_join(workers[i], NULL);
|
||||
pthread_cond_destroy(&work_queue.work_available);
|
||||
pthread_cond_destroy(&work_queue.space_available);
|
||||
pthread_mutex_destroy(&work_queue.lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
59
executables/nr-oru.h
Normal file
59
executables/nr-oru.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
#ifndef __NR_ORU_H__
|
||||
#define __NR_ORU_H__
|
||||
#include "openair1/PHY/defs_RU.h"
|
||||
#include <pthread.h>
|
||||
#include "oru_fh.h"
|
||||
#include "openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h"
|
||||
#include "openair1/PHY/defs_gNB.h"
|
||||
|
||||
typedef struct {
|
||||
RU_t *ru;
|
||||
/// tx carrier
|
||||
uint64_t carrier_freq_tx[MAX_BANDS_PER_RRU];
|
||||
/// rx carrier
|
||||
uint64_t carrier_freq_rx[MAX_BANDS_PER_RRU];
|
||||
/// tx BW in PRBs
|
||||
int bw_tx[MAX_BANDS_PER_RRU];
|
||||
/// rx BW in PRBs
|
||||
int bw_rx[MAX_BANDS_PER_RRU];
|
||||
/// 3GPP FRAME Type FDD/TDD
|
||||
int frame_type;
|
||||
/// 3GPP PRACH configuration index
|
||||
int prach_config_index;
|
||||
/// 3GPP MSG1 Start frequency
|
||||
int prach_msg1_freq;
|
||||
/// 3GPP TDD periodicity (0.5 ms, 1 0.625ms, 2 1ms, 3 1.25ms, 4 2ms,5 2.5ms, 6 5ms, 7 10ms, 8 3ms, 9 4ms
|
||||
int tdd_period;
|
||||
/// number of DL slots
|
||||
int num_DL_slots;
|
||||
/// number of UL slots
|
||||
int num_UL_slots;
|
||||
/// number of DL symbols
|
||||
int num_DL_symbols;
|
||||
/// number of UL symbols
|
||||
int num_UL_symbols;
|
||||
int numerology;
|
||||
|
||||
pthread_t north_read_thread;
|
||||
pthread_t south_read_thread;
|
||||
oru_fh_config_t fh_config;
|
||||
void *fronthaul;
|
||||
|
||||
// PRACH related
|
||||
nr_prach_info_t prach_info;
|
||||
time_stats_t rx_prach;
|
||||
time_stats_t rx;
|
||||
prach_item_t prach_item;
|
||||
} ORU_t;
|
||||
|
||||
int get_oru_options(ORU_t *oru);
|
||||
void oru_init_frame_parms(ORU_t *oru);
|
||||
void *oru_north_read_thread(void *arg);
|
||||
void *oru_south_read_thread(void *arg);
|
||||
void prepare_prach_item(ORU_t *oru);
|
||||
|
||||
#endif
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "radio/COMMON/common_lib.h"
|
||||
#include "radio/ETHERNET/ethernet_lib.h"
|
||||
|
||||
#include "PHY/if4_tools.h"
|
||||
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
@@ -76,15 +74,6 @@ void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice, timestamp, buffs, 0, get_samples_per_slot(slot, ru->nr_frame_parms), 0, ru->nb_tx);
|
||||
}
|
||||
|
||||
// southbound IF4p5 fronthaul
|
||||
void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx);
|
||||
|
||||
if ((nr_slot_select(&ru->config, ru->proc.frame_tx, ru->proc.tti_tx) & NR_DOWNLINK_SLOT) > 0)
|
||||
send_IF4p5(ru,frame, slot, IF4p5_PDLFFT);
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/* Input Fronthaul from south RCC/RAU */
|
||||
|
||||
@@ -148,196 +137,6 @@ void fh_if5_south_in(RU_t *ru, int *frame, int *tti)
|
||||
rxmeas.tv_nsec);
|
||||
}
|
||||
|
||||
// Synchronous if4p5 from south
|
||||
void fh_if4p5_south_in(RU_t *ru,
|
||||
int *frame,
|
||||
int *slot) {
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
int f,sl;
|
||||
uint16_t packet_type;
|
||||
uint32_t symbol_number=0;
|
||||
uint32_t symbol_mask_full=0;
|
||||
|
||||
do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
|
||||
recv_IF4p5(ru, &f, &sl, &packet_type, &symbol_number);
|
||||
|
||||
if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sl] = proc->symbol_mask[sl] | (1<<symbol_number);
|
||||
else if (packet_type == IF4p5_PULTICK) {
|
||||
if ((proc->first_rx == 0) && (f != *frame))
|
||||
LOG_E(PHY, "rx_fh_if4p5: PULTICK received frame %d != expected %d\n", f, *frame);
|
||||
|
||||
if ((proc->first_rx == 0) && (sl != *slot))
|
||||
LOG_E(PHY, "rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n", sl, *slot, proc->first_rx);
|
||||
|
||||
break;
|
||||
} else if (packet_type == IF4p5_PRACH) {
|
||||
// nothing in RU for RAU
|
||||
}
|
||||
|
||||
LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*slot,proc->symbol_mask[sl]);
|
||||
} while(proc->symbol_mask[sl] != symbol_mask_full);
|
||||
|
||||
//caculate timestamp_rx, timestamp_tx based on frame and subframe
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + get_samples_slot_timestamp(fp, proc->tti_rx);
|
||||
// proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe);
|
||||
proc->tti_tx = (sl+ru->sl_ahead)%fp->slots_per_frame;
|
||||
proc->frame_tx = (sl > (fp->slots_per_frame - 1 - (ru->sl_ahead))) ? (f + 1) & 1023 : f;
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *slot) {
|
||||
LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*slot);
|
||||
exit_fun("Exiting");
|
||||
}
|
||||
|
||||
if (proc->frame_rx != *frame) {
|
||||
LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
|
||||
exit_fun("Exiting");
|
||||
}
|
||||
} else {
|
||||
proc->first_rx = 0;
|
||||
*frame = proc->frame_rx;
|
||||
*slot = proc->tti_rx;
|
||||
}
|
||||
|
||||
proc->symbol_mask[proc->tti_rx] = 0;
|
||||
LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx);
|
||||
}
|
||||
|
||||
// asynchronous inbound if4p5 fronthaul from south
|
||||
void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
uint16_t packet_type;
|
||||
uint32_t symbol_number = 0;
|
||||
uint32_t symbol_mask = (1 << fp->symbols_per_slot) - 1;
|
||||
uint32_t prach_rx = 0;
|
||||
|
||||
do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
|
||||
recv_IF4p5(ru, &proc->frame_rx, &proc->tti_rx, &packet_type, &symbol_number);
|
||||
if (proc->first_rx != 0) {
|
||||
*frame = proc->frame_rx;
|
||||
*slot = proc->tti_rx;
|
||||
proc->first_rx = 0;
|
||||
} else {
|
||||
if (proc->frame_rx != *frame) {
|
||||
LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame);
|
||||
exit_fun("Exiting");
|
||||
}
|
||||
if (proc->tti_rx != *slot) {
|
||||
LOG_E(PHY,"tti_rx %d is not what we expect %d\n",proc->tti_rx,*slot);
|
||||
exit_fun("Exiting");
|
||||
}
|
||||
}
|
||||
|
||||
if (packet_type == IF4p5_PULFFT)
|
||||
symbol_mask &= ~(1 << symbol_number);
|
||||
else if (packet_type == IF4p5_PRACH)
|
||||
prach_rx &= ~0x1;
|
||||
} while (symbol_mask > 0 || prach_rx > 0); // haven't received all PUSCH symbols and PRACH information
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/* Input Fronthaul from North RRU */
|
||||
|
||||
// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output
|
||||
// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates
|
||||
void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot)
|
||||
{
|
||||
uint32_t symbol_number=0;
|
||||
uint32_t symbol_mask, symbol_mask_full;
|
||||
uint16_t packet_type;
|
||||
/// **** incoming IF4p5 from remote RCC/RAU **** ///
|
||||
symbol_number = 0;
|
||||
symbol_mask = 0;
|
||||
symbol_mask_full = (1<<(ru->nr_frame_parms->symbols_per_slot))-1;
|
||||
|
||||
do {
|
||||
recv_IF4p5(ru, frame, slot, &packet_type, &symbol_number);
|
||||
symbol_mask = symbol_mask | (1<<symbol_number);
|
||||
} while (symbol_mask != symbol_mask_full);
|
||||
}
|
||||
|
||||
void fh_if5_north_asynch_in(RU_t *ru, int *frame, int *slot)
|
||||
{
|
||||
AssertFatal(1 == 0, "Shouldn't get here\n");
|
||||
}
|
||||
|
||||
void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
uint16_t packet_type;
|
||||
uint32_t symbol_mask_full = 0;
|
||||
int slot_tx,frame_tx;
|
||||
LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
|
||||
uint32_t symbol_number = 0;
|
||||
uint32_t symbol_mask = 0;
|
||||
|
||||
// symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_slot))-1;
|
||||
do {
|
||||
recv_IF4p5(ru, &frame_tx, &slot_tx, &packet_type, &symbol_number);
|
||||
|
||||
if (((nr_slot_select(cfg, frame_tx, slot_tx) & NR_DOWNLINK_SLOT) > 0) && (symbol_number == 0))
|
||||
start_meas(&ru->rx_fhaul);
|
||||
|
||||
LOG_D(PHY,"slot %d (%d): frame %d, slot %d, symbol %d\n",
|
||||
*slot,nr_slot_select(cfg,frame_tx,*slot),frame_tx,slot_tx,symbol_number);
|
||||
|
||||
if (proc->first_tx != 0) {
|
||||
*frame = frame_tx;
|
||||
*slot = slot_tx;
|
||||
proc->first_tx = 0;
|
||||
} else {
|
||||
AssertFatal(frame_tx == *frame,
|
||||
"frame_tx %d is not what we expect %d\n",frame_tx,*frame);
|
||||
AssertFatal(slot_tx == *slot,
|
||||
"slot_tx %d is not what we expect %d\n",slot_tx,*slot);
|
||||
}
|
||||
|
||||
if (packet_type == IF4p5_PDLFFT) {
|
||||
symbol_mask = symbol_mask | (1<<symbol_number);
|
||||
} else
|
||||
AssertFatal(false, "Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n", packet_type);
|
||||
} while (symbol_mask != symbol_mask_full);
|
||||
|
||||
if ((nr_slot_select(cfg, frame_tx, slot_tx) & NR_DOWNLINK_SLOT) > 0)
|
||||
stop_meas(&ru->rx_fhaul);
|
||||
|
||||
proc->tti_tx = slot_tx;
|
||||
proc->frame_tx = frame_tx;
|
||||
|
||||
if (frame_tx == 0 && slot_tx == 0)
|
||||
proc->frame_tx_unwrap += 1024;
|
||||
|
||||
proc->timestamp_tx =
|
||||
((uint64_t)frame_tx + proc->frame_tx_unwrap) * fp->samples_per_subframe * 10 + get_samples_slot_timestamp(fp, slot_tx);
|
||||
LOG_D(PHY, "RU %d/%d TST %lu, frame %d, subframe %d\n", ru->idx, 0, proc->timestamp_tx, frame_tx, slot_tx);
|
||||
|
||||
if (ru->feptx_ofdm)
|
||||
ru->feptx_ofdm(ru, frame_tx, slot_tx);
|
||||
|
||||
if (ru->fh_south_out)
|
||||
ru->fh_south_out(ru, frame_tx, slot_tx, proc->timestamp_tx);
|
||||
}
|
||||
|
||||
void fh_if5_north_out(RU_t *ru)
|
||||
{
|
||||
/// **** send_IF5 of rxdata to BBU **** ///
|
||||
AssertFatal(1 == 0, "Shouldn't get here\n");
|
||||
}
|
||||
|
||||
// RRU IF4p5 northbound interface (RX)
|
||||
void fh_if4p5_north_out(RU_t *ru)
|
||||
{
|
||||
RU_proc_t *proc=&ru->proc;
|
||||
start_meas(&ru->tx_fhaul);
|
||||
send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULFFT);
|
||||
stop_meas(&ru->tx_fhaul);
|
||||
}
|
||||
|
||||
static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
{
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
@@ -494,7 +293,7 @@ static radio_tx_gpio_flag_t get_gpio_flags(RU_t *ru, int slot)
|
||||
return flags_gpio;
|
||||
}
|
||||
|
||||
void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
void tx_rf_symbols(RU_t *ru, int frame, int slot, uint64_t timestamp, int start_symbol, int num_symbols)
|
||||
{
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
@@ -521,22 +320,23 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
txsymb++;
|
||||
}
|
||||
|
||||
AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb);
|
||||
AssertFatal(txsymb > 0, "illegal txsymb %d\n", txsymb);
|
||||
|
||||
if (fp->slots_per_subframe == 1) {
|
||||
if (txsymb <= 7)
|
||||
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
else
|
||||
siglen = 2 * (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 2) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
} else {
|
||||
if(slot%(fp->slots_per_subframe/2))
|
||||
siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
else
|
||||
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
if (txsymb < start_symbol) {
|
||||
// No DL symbols in this transmission
|
||||
return;
|
||||
}
|
||||
|
||||
//+ ru->end_of_burst_delay;
|
||||
flags_burst = TX_BURST_END;
|
||||
int end_symbol = start_symbol + num_symbols - 1;
|
||||
if (end_symbol >= txsymb) {
|
||||
flags_burst = TX_BURST_END;
|
||||
} else {
|
||||
flags_burst = TX_BURST_MIDDLE;
|
||||
}
|
||||
|
||||
int num_symbols_this_transmission = min(txsymb, end_symbol) - start_symbol + 1;
|
||||
|
||||
siglen = get_samples_symbol_duration(fp, slot, start_symbol, num_symbols_this_transmission);
|
||||
} else if (slot_type == NR_DOWNLINK_SLOT) {
|
||||
int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame);
|
||||
int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame);
|
||||
@@ -548,9 +348,11 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
} else {
|
||||
flags_burst = proc->first_tx == 1 ? TX_BURST_START : TX_BURST_MIDDLE;
|
||||
}
|
||||
siglen = get_samples_symbol_duration(fp, slot, start_symbol, num_symbols);
|
||||
}
|
||||
} else { // FDD
|
||||
flags_burst = proc->first_tx == 1 ? TX_BURST_START : TX_BURST_MIDDLE;
|
||||
siglen = get_samples_symbol_duration(fp, slot, start_symbol, num_symbols);
|
||||
}
|
||||
|
||||
if (ru->openair0_cfg.gpio_controller != RU_GPIO_CONTROL_NONE)
|
||||
@@ -561,8 +363,9 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
|
||||
int nt = ru->nb_tx;
|
||||
void *txp[nt];
|
||||
uint32_t time_offset = get_samples_slot_timestamp(fp, slot) + get_samples_symbol_timestamp(fp, slot, start_symbol);
|
||||
for (int i = 0; i < nt; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][get_samples_slot_timestamp(fp, slot)] - sf_extension * sizeof(int32_t);
|
||||
txp[i] = (void *)&ru->common.txdata[i][time_offset] - sf_extension * sizeof(int32_t);
|
||||
|
||||
// prepare tx buffer pointers
|
||||
uint32_t txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
|
||||
@@ -586,7 +389,12 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
10 * log10((double)signal_energy(txp[0], siglen + sf_extension)));
|
||||
}
|
||||
|
||||
static void fill_rf_config(RU_t *ru, char *rf_config_file)
|
||||
void tx_rf(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
tx_rf_symbols(ru, frame, slot, timestamp, 0, 14);
|
||||
}
|
||||
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_scf_t *config = &ru->config; //tmp index
|
||||
@@ -649,7 +457,7 @@ static void fill_rf_config(RU_t *ru, char *rf_config_file)
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_request_scf_t *config, const NR_DL_FRAME_PARMS *fp)
|
||||
void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_request_scf_t *config, const NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
const nfapi_nr_prach_config_t *prach_config = &config->prach_config;
|
||||
const nfapi_nr_tdd_table_t *tdd_table = &config->tdd_table;
|
||||
@@ -833,7 +641,7 @@ void *ru_thread(void *param)
|
||||
ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params);
|
||||
AssertFatal(ret == 0, "RU %u: openair0_transport_init() ret %d: cannot initialize transport protocol\n", ru->idx, ret);
|
||||
|
||||
if (ru->ifdevice.get_internal_parameter != NULL) {
|
||||
if (ru->ifdevice.get_internal_parameter) {
|
||||
/* it seems the device can "overwrite" (request?) to set the callbacks
|
||||
* for fh_south_in()/fh_south_out() differently */
|
||||
void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in");
|
||||
@@ -842,8 +650,6 @@ void *ru_thread(void *param)
|
||||
t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out");
|
||||
if (t != NULL)
|
||||
ru->fh_south_out = t;
|
||||
} else {
|
||||
malloc_IF4p5_buffer(ru);
|
||||
}
|
||||
|
||||
int cpu = sched_getcpu();
|
||||
@@ -1088,94 +894,59 @@ void set_function_spec_param(RU_t *ru)
|
||||
switch (ru->if_south) {
|
||||
case LOCAL_RF: // this is an RU with integrated RF (RRU, gNB)
|
||||
reset_meas(&ru->rx_fhaul);
|
||||
if (ru->function == NGFI_RRU_IF5) { // IF5 RRU
|
||||
ru->do_prach = 0; // no prach processing in RU
|
||||
ru->fh_north_in = NULL; // no shynchronous incoming fronthaul from north
|
||||
ru->fh_north_out = fh_if5_north_out; // need only to do send_IF5 reception
|
||||
ru->fh_south_out = tx_rf; // send output to RF
|
||||
ru->fh_north_asynch_in = fh_if5_north_asynch_in; // TX packets come asynchronously
|
||||
ru->feprx = NULL; // nothing (this is a time-domain signal)
|
||||
ru->feptx_ofdm = NULL; // nothing (this is a time-domain signal)
|
||||
ru->feptx_prec = NULL; // nothing (this is a time-domain signal)
|
||||
ru->nr_start_if = nr_start_if; // need to start the if interface for if5
|
||||
ru->ifdevice.host_type = RRU_HOST;
|
||||
ru->rfdevice.host_type = RRU_HOST;
|
||||
ru->ifdevice.eth_params = &ru->eth_params;
|
||||
reset_meas(&ru->rx_fhaul);
|
||||
reset_meas(&ru->tx_fhaul);
|
||||
reset_meas(&ru->compression);
|
||||
reset_meas(&ru->transport);
|
||||
} else if (ru->function == NGFI_RRU_IF4p5) {
|
||||
ru->do_prach = 1; // do part of prach processing in RU
|
||||
ru->fh_north_in = NULL; // no synchronous incoming fronthaul from north
|
||||
ru->fh_north_out = fh_if4p5_north_out; // send_IF4p5 on reception
|
||||
ru->fh_south_out = tx_rf; // send output to RF
|
||||
ru->fh_north_asynch_in = fh_if4p5_north_asynch_in; // TX packets come asynchronously
|
||||
ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs
|
||||
ru->feptx_ofdm = nr_feptx_tp; // this is fep with idft only (no precoding in RRU)
|
||||
ru->feptx_prec = NULL;
|
||||
ru->nr_start_if = nr_start_if; // need to start the if interface for if4p5
|
||||
ru->ifdevice.host_type = RRU_HOST;
|
||||
ru->rfdevice.host_type = RRU_HOST;
|
||||
ru->ifdevice.eth_params = &ru->eth_params;
|
||||
reset_meas(&ru->tx_fhaul);
|
||||
reset_meas(&ru->compression);
|
||||
reset_meas(&ru->transport);
|
||||
} else if (ru->function == gNodeB_3GPP) {
|
||||
ru->do_prach = 0; // no prach processing in RU
|
||||
ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs
|
||||
ru->feptx_ofdm = nr_feptx_tp; // this is fep with idft and precoding
|
||||
ru->feptx_prec = NULL;
|
||||
ru->fh_north_in = NULL; // no incoming fronthaul from north
|
||||
ru->fh_north_out = NULL; // no outgoing fronthaul to north
|
||||
ru->nr_start_if = NULL; // no if interface
|
||||
ru->rfdevice.host_type = RAU_HOST;
|
||||
ru->fh_south_in = rx_rf; // local synchronous RF RX
|
||||
ru->fh_south_out = tx_rf; // local synchronous RF TX
|
||||
ru->start_rf = start_rf; // need to start the local RF interface
|
||||
ru->stop_rf = stop_rf;
|
||||
ru->start_write_thread = start_write_thread; // starting RF TX in different thread
|
||||
}
|
||||
AssertFatal(ru->function == gNodeB_3GPP, "ru->function %d not supported for LOCAL_RF\n", ru->function);
|
||||
ru->do_prach = 0; // no prach processing in RU
|
||||
ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs
|
||||
ru->feptx_ofdm = nr_feptx_tp; // this is fep with idft and precoding
|
||||
ru->feptx_prec = NULL;
|
||||
ru->fh_north_in = NULL; // no incoming fronthaul from north
|
||||
ru->fh_north_out = NULL; // no outgoing fronthaul to north
|
||||
ru->nr_start_if = NULL; // no if interface
|
||||
ru->rfdevice.host_type = RAU_HOST;
|
||||
ru->fh_south_in = rx_rf; // local synchronous RF RX
|
||||
ru->fh_south_out = tx_rf; // local synchronous RF TX
|
||||
ru->start_rf = start_rf; // need to start the local RF interface
|
||||
ru->stop_rf = stop_rf;
|
||||
ru->start_write_thread = start_write_thread; // starting RF TX in different thread
|
||||
break;
|
||||
|
||||
case REMOTE_IF5: // the remote unit is IF5 RRU
|
||||
ru->do_prach = 0;
|
||||
ru->txfh_in_fep = 0;
|
||||
ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs
|
||||
ru->feptx_prec = NULL; // need to do transmit Precoding + IDFTs
|
||||
ru->feptx_ofdm = nr_feptx_tp; // need to do transmit Precoding + IDFTs
|
||||
ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception
|
||||
ru->fh_south_out = (ru->txfh_in_fep>0) ? NULL : fh_if5_south_out; // synchronous IF5 transmission
|
||||
ru->fh_south_asynch_in = NULL; // no asynchronous UL
|
||||
ru->start_rf = ru->eth_params.transp_preference == ETH_UDP_IF5_ECPRI_MODE ? start_streaming : NULL;
|
||||
ru->stop_rf = NULL;
|
||||
ru->start_write_thread = NULL;
|
||||
ru->nr_start_if = nr_start_if; // need to start if interface for IF5
|
||||
ru->ifdevice.host_type = RAU_HOST;
|
||||
ru->ifdevice.eth_params = &ru->eth_params;
|
||||
|
||||
ru->do_prach = 0;
|
||||
ru->txfh_in_fep = 0;
|
||||
ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs
|
||||
ru->feptx_prec = NULL; // need to do transmit Precoding + IDFTs
|
||||
ru->feptx_ofdm = nr_feptx_tp; // need to do transmit Precoding + IDFTs
|
||||
ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception
|
||||
ru->fh_south_out = (ru->txfh_in_fep > 0) ? NULL : fh_if5_south_out; // synchronous IF5 transmission
|
||||
ru->fh_south_asynch_in = NULL; // no asynchronous UL
|
||||
ru->start_rf = ru->eth_params.transp_preference == ETH_UDP_IF5_ECPRI_MODE ? start_streaming : NULL;
|
||||
ru->stop_rf = NULL;
|
||||
ru->start_write_thread = NULL;
|
||||
ru->nr_start_if = nr_start_if; // need to start if interface for IF5
|
||||
ru->ifdevice.host_type = RAU_HOST;
|
||||
ru->ifdevice.eth_params = &ru->eth_params;
|
||||
break;
|
||||
|
||||
case REMOTE_IF4p5:
|
||||
ru->do_prach = 0;
|
||||
ru->feprx = NULL; // DFTs
|
||||
ru->feptx_prec = nr_feptx_prec; // Precoding operation
|
||||
ru->feptx_ofdm = NULL; // no OFDM mod
|
||||
ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception
|
||||
ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission
|
||||
ru->fh_south_asynch_in = (ru->if_timing == synch_to_other) ? fh_if4p5_south_in : NULL; // asynchronous UL if synch_to_other
|
||||
ru->fh_north_out = NULL;
|
||||
ru->fh_north_asynch_in = NULL;
|
||||
ru->start_rf = NULL; // no local RF
|
||||
ru->stop_rf = NULL;
|
||||
ru->start_write_thread = NULL;
|
||||
ru->nr_start_if = nr_start_if; // need to start if interface for IF4p5
|
||||
ru->ifdevice.host_type = RAU_HOST;
|
||||
ru->ifdevice.eth_params = &ru->eth_params;
|
||||
ru->do_prach = 0;
|
||||
ru->feprx = NULL; // DFTs
|
||||
ru->feptx_prec = nr_feptx_prec; // Precoding operation
|
||||
ru->feptx_ofdm = NULL; // no OFDM mod
|
||||
ru->fh_south_in = NULL;
|
||||
ru->fh_south_out = NULL;
|
||||
ru->fh_south_asynch_in = NULL;
|
||||
ru->fh_north_out = NULL;
|
||||
ru->fh_north_asynch_in = NULL;
|
||||
ru->start_rf = NULL; // no local RF
|
||||
ru->stop_rf = NULL;
|
||||
ru->start_write_thread = NULL;
|
||||
ru->nr_start_if = nr_start_if; // need to start if interface for IF4p5
|
||||
ru->ifdevice.host_type = RAU_HOST;
|
||||
ru->ifdevice.eth_params = &ru->eth_params;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south);
|
||||
LOG_E(PHY, "RU with invalid or unknown southbound interface type %d\n", ru->if_south);
|
||||
break;
|
||||
} // switch on interface type
|
||||
}
|
||||
@@ -1369,47 +1140,14 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
ru->openair0_cfg.tune_offset = get_softmodem_params()->tune_offset;
|
||||
|
||||
if (strcmp(*param[RU_LOCAL_RF_IDX].strptr, "yes") == 0) {
|
||||
if (!config_isparamset(param, RU_LOCAL_IF_NAME_IDX)) {
|
||||
ru->if_south = LOCAL_RF;
|
||||
ru->function = gNodeB_3GPP;
|
||||
LOG_D(PHY, "Setting function for RU %d to gNodeB_3GPP\n", j);
|
||||
} else {
|
||||
ru->eth_params.local_if_name = strdup(*param[RU_LOCAL_IF_NAME_IDX].strptr);
|
||||
ru->eth_params.my_addr = strdup(*param[RU_LOCAL_ADDRESS_IDX].strptr);
|
||||
ru->eth_params.remote_addr = strdup(*param[RU_REMOTE_ADDRESS_IDX].strptr);
|
||||
ru->eth_params.my_portc = *param[RU_LOCAL_PORTC_IDX].uptr;
|
||||
ru->eth_params.remote_portc = *param[RU_REMOTE_PORTC_IDX].uptr;
|
||||
ru->eth_params.my_portd = *param[RU_LOCAL_PORTD_IDX].uptr;
|
||||
ru->eth_params.remote_portd = *param[RU_REMOTE_PORTD_IDX].uptr;
|
||||
char *str = *param[RU_TRANSPORT_PREFERENCE_IDX].strptr;
|
||||
if (strcmp(str, "udp") == 0) {
|
||||
ru->if_south = LOCAL_RF;
|
||||
ru->function = NGFI_RRU_IF5;
|
||||
ru->eth_params.transp_preference = ETH_UDP_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (udp)\n", j);
|
||||
} else if (strcmp(str, "raw") == 0) {
|
||||
ru->if_south = LOCAL_RF;
|
||||
ru->function = NGFI_RRU_IF5;
|
||||
ru->eth_params.transp_preference = ETH_RAW_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF5 (raw)\n", j);
|
||||
} else if (strcmp(str, "udp_if4p5") == 0) {
|
||||
ru->if_south = LOCAL_RF;
|
||||
ru->function = NGFI_RRU_IF4p5;
|
||||
ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n", j);
|
||||
} else if (strcmp(str, "raw_if4p5") == 0) {
|
||||
ru->if_south = LOCAL_RF;
|
||||
ru->function = NGFI_RRU_IF4p5;
|
||||
ru->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
|
||||
LOG_D(PHY, "Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n", j);
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(!config_isparamset(param, RU_LOCAL_IF_NAME_IDX), "RU_TRANSPORT_PREFERENCE not supported for local RF\n");
|
||||
ru->if_south = LOCAL_RF;
|
||||
ru->function = gNodeB_3GPP;
|
||||
LOG_D(PHY, "Setting function for RU %d to gNodeB_3GPP\n", j);
|
||||
ru->max_pdschReferenceSignalPower = *param[RU_MAX_RS_EPRE_IDX].uptr;
|
||||
ru->max_rxgain = *param[RU_MAX_RXGAIN_IDX].uptr;
|
||||
ru->sf_extension = *param[RU_SF_EXTENSION_IDX].uptr;
|
||||
} // strcmp(local_rf, "yes") == 0
|
||||
else {
|
||||
} else { // strcmp(local_rf, "yes") == 0
|
||||
char *str = *param[RU_TRANSPORT_PREFERENCE_IDX].strptr;
|
||||
LOG_D(PHY, "RU %d: Transport %s\n", j, str);
|
||||
ru->eth_params.local_if_name = strdup(*param[RU_LOCAL_IF_NAME_IDX].strptr);
|
||||
@@ -1432,10 +1170,6 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
ru->if_south = REMOTE_IF5;
|
||||
ru->function = NGFI_RAU_IF5;
|
||||
ru->eth_params.transp_preference = ETH_RAW_MODE;
|
||||
} else if (strcmp(str, "udp_if4p5") == 0) {
|
||||
ru->if_south = REMOTE_IF4p5;
|
||||
ru->function = NGFI_RAU_IF4p5;
|
||||
ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
|
||||
} else if (strcmp(str, "raw_if4p5") == 0) {
|
||||
ru->if_south = REMOTE_IF4p5;
|
||||
ru->function = NGFI_RAU_IF4p5;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user