From 389ca60d5e15db5b18edf7a0e951692d4e163f4b Mon Sep 17 00:00:00 2001 From: Sagar Arora Date: Thu, 13 Nov 2025 14:15:46 +0100 Subject: [PATCH 01/30] add yq in 5G NF Dockerfiles Signed-off-by: Sagar Arora --- docker/Dockerfile.base.rhel9 | 4 ++++ docker/Dockerfile.base.rocky | 4 ++++ docker/Dockerfile.base.ubuntu | 4 ++++ docker/Dockerfile.gNB.aerial.ubuntu | 2 ++ docker/Dockerfile.gNB.aw2s.rhel9 | 1 + docker/Dockerfile.gNB.aw2s.rocky | 1 + docker/Dockerfile.gNB.aw2s.ubuntu | 1 + docker/Dockerfile.gNB.fhi72.rhel9 | 2 ++ docker/Dockerfile.gNB.fhi72.rocky | 2 ++ docker/Dockerfile.gNB.fhi72.ubuntu | 2 ++ docker/Dockerfile.gNB.rhel9 | 1 + docker/Dockerfile.gNB.rocky | 1 + docker/Dockerfile.gNB.ubuntu | 1 + docker/Dockerfile.nr-cuup.rhel9 | 1 + docker/Dockerfile.nr-cuup.rocky | 1 + docker/Dockerfile.nr-cuup.ubuntu | 2 ++ docker/Dockerfile.nrUE.rhel9 | 2 ++ docker/Dockerfile.nrUE.rocky | 2 ++ docker/Dockerfile.nrUE.ubuntu | 2 ++ 19 files changed, 36 insertions(+) diff --git a/docker/Dockerfile.base.rhel9 b/docker/Dockerfile.base.rhel9 index dde540556b..e57c705471 100644 --- a/docker/Dockerfile.base.rhel9 +++ b/docker/Dockerfile.base.rhel9 @@ -73,6 +73,10 @@ ENV TINI_VERSION=v0.19.0 ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini RUN chmod +x /tini +ENV YQ_VERSION=v4.2.0 +RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\ + chmod +x /usr/local/bin/yq + # In some network environments, GIT proxy is required RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" diff --git a/docker/Dockerfile.base.rocky b/docker/Dockerfile.base.rocky index 98a9ef703a..d34dcdafc6 100644 --- a/docker/Dockerfile.base.rocky +++ b/docker/Dockerfile.base.rocky @@ -66,6 +66,10 @@ ENV TINI_VERSION=v0.19.0 ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini RUN chmod +x /tini +ENV YQ_VERSION=v4.2.0 +RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\ + chmod +x /usr/local/bin/yq + # Copying only the needed files to create ran-base WORKDIR /oai-ran/cmake_targets/tools COPY cmake_targets/tools/build_helper \ diff --git a/docker/Dockerfile.base.ubuntu b/docker/Dockerfile.base.ubuntu index 34dadd1757..ee42085a40 100644 --- a/docker/Dockerfile.base.ubuntu +++ b/docker/Dockerfile.base.ubuntu @@ -60,6 +60,10 @@ RUN apt-get update && \ ENV TINI_VERSION=v0.19.0 RUN wget https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} -O /tini && chmod +x /tini +ENV YQ_VERSION=v4.2.0 +RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\ + chmod +x /usr/local/bin/yq + # In some network environments, GIT proxy is required RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" diff --git a/docker/Dockerfile.gNB.aerial.ubuntu b/docker/Dockerfile.gNB.aerial.ubuntu index 04bed658fe..b79ab78fa8 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu +++ b/docker/Dockerfile.gNB.aerial.ubuntu @@ -110,6 +110,8 @@ RUN ldconfig && \ /usr/local/lib/libnvipc.so WORKDIR /opt/oai-gnb + +COPY --from=ran-build /usr/local/bin/yq /usr/local/bin/yq COPY --from=ran-build /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.aw2s.rhel9 b/docker/Dockerfile.gNB.aw2s.rhel9 index 65eafac37b..e35b0a7690 100644 --- a/docker/Dockerfile.gNB.aw2s.rhel9 +++ b/docker/Dockerfile.gNB.aw2s.rhel9 @@ -101,6 +101,7 @@ RUN ln -s /usr/local/lib/libaw2sori_transpro.so /usr/local/lib/libthirdparty_tra WORKDIR /opt/oai-gnb-aw2s +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"] CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.aw2s.rocky b/docker/Dockerfile.gNB.aw2s.rocky index 1c0adfccd8..8fbd6cc91d 100644 --- a/docker/Dockerfile.gNB.aw2s.rocky +++ b/docker/Dockerfile.gNB.aw2s.rocky @@ -95,6 +95,7 @@ RUN ln -s /usr/local/lib/libaw2sori_transpro.so /usr/local/lib/libthirdparty_tra WORKDIR /opt/oai-gnb-aw2s +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"] CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu b/docker/Dockerfile.gNB.aw2s.ubuntu index b55977dfab..840b4a8a28 100644 --- a/docker/Dockerfile.gNB.aw2s.ubuntu +++ b/docker/Dockerfile.gNB.aw2s.ubuntu @@ -95,6 +95,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/libaw2sori_transpro.so /usr/local/lib/lib WORKDIR /opt/oai-gnb-aw2s +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"] CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.fhi72.rhel9 b/docker/Dockerfile.gNB.fhi72.rhel9 index 122b3b668d..bda79eba28 100644 --- a/docker/Dockerfile.gNB.fhi72.rhel9 +++ b/docker/Dockerfile.gNB.fhi72.rhel9 @@ -126,6 +126,8 @@ RUN ldconfig && \ /opt/phy/fhi_lib/lib/build/libxran.so WORKDIR /opt/oai-gnb + +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.fhi72.rocky b/docker/Dockerfile.gNB.fhi72.rocky index f95310059d..2dd7848d38 100644 --- a/docker/Dockerfile.gNB.fhi72.rocky +++ b/docker/Dockerfile.gNB.fhi72.rocky @@ -114,6 +114,8 @@ RUN ldconfig && \ /opt/phy/fhi_lib/lib/build/libxran.so WORKDIR /opt/oai-gnb + +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.fhi72.ubuntu b/docker/Dockerfile.gNB.fhi72.ubuntu index fb9d1d43f7..09af53eed5 100644 --- a/docker/Dockerfile.gNB.fhi72.ubuntu +++ b/docker/Dockerfile.gNB.fhi72.ubuntu @@ -111,6 +111,8 @@ RUN ldconfig && \ /opt/phy/fhi_lib/lib/build/libxran.so WORKDIR /opt/oai-gnb + +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9 index 1c201eeeab..4e766bd011 100644 --- a/docker/Dockerfile.gNB.rhel9 +++ b/docker/Dockerfile.gNB.rhel9 @@ -130,6 +130,7 @@ WORKDIR /opt/oai-gnb #EXPOSE 50000/udp # IF5 / ORI (control) #EXPOSE 50001/udp # IF5 / ECPRI (data) +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.rocky b/docker/Dockerfile.gNB.rocky index d005c36c9f..2f646cf1b3 100644 --- a/docker/Dockerfile.gNB.rocky +++ b/docker/Dockerfile.gNB.rocky @@ -124,6 +124,7 @@ WORKDIR /opt/oai-gnb #EXPOSE 50000/udp # IF5 / ORI (control) #EXPOSE 50001/udp # IF5 / ECPRI (data) +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.ubuntu b/docker/Dockerfile.gNB.ubuntu index 2259aa39c9..c88857f2d6 100644 --- a/docker/Dockerfile.gNB.ubuntu +++ b/docker/Dockerfile.gNB.ubuntu @@ -128,6 +128,7 @@ WORKDIR /opt/oai-gnb #EXPOSE 50000/udp # IF5 / ORI (control) #EXPOSE 50001/udp # IF5 / ECPRI (data) +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.nr-cuup.rhel9 b/docker/Dockerfile.nr-cuup.rhel9 index b1b083e57c..a9c5f0d65a 100644 --- a/docker/Dockerfile.nr-cuup.rhel9 +++ b/docker/Dockerfile.nr-cuup.rhel9 @@ -73,6 +73,7 @@ WORKDIR /opt/oai-gnb/etc WORKDIR /opt/oai-gnb +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.nr-cuup.rocky b/docker/Dockerfile.nr-cuup.rocky index 7f0e8fc2f1..8bbd206381 100644 --- a/docker/Dockerfile.nr-cuup.rocky +++ b/docker/Dockerfile.nr-cuup.rocky @@ -71,6 +71,7 @@ WORKDIR /opt/oai-gnb/etc WORKDIR /opt/oai-gnb +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.nr-cuup.ubuntu b/docker/Dockerfile.nr-cuup.ubuntu index 2c3c58e7e3..1455dc1397 100644 --- a/docker/Dockerfile.nr-cuup.ubuntu +++ b/docker/Dockerfile.nr-cuup.ubuntu @@ -69,6 +69,8 @@ RUN ldconfig && ldd /opt/oai-gnb/bin/nr-cuup WORKDIR /opt/oai-gnb/etc WORKDIR /opt/oai-gnb + +COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9 index 0929ab3df0..79f44dfafb 100644 --- a/docker/Dockerfile.nrUE.rhel9 +++ b/docker/Dockerfile.nrUE.rhel9 @@ -122,6 +122,8 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-nr-ue + +COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=nr-ue-base /tini /tini CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"] ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"] diff --git a/docker/Dockerfile.nrUE.rocky b/docker/Dockerfile.nrUE.rocky index bfe84dc011..8d9057a0ed 100644 --- a/docker/Dockerfile.nrUE.rocky +++ b/docker/Dockerfile.nrUE.rocky @@ -119,6 +119,8 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib64/libuhd.so.4.8.0 WORKDIR /opt/oai-nr-ue + +COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=nr-ue-base /tini /tini CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"] ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"] diff --git a/docker/Dockerfile.nrUE.ubuntu b/docker/Dockerfile.nrUE.ubuntu index a395004cc1..3b55a64acd 100644 --- a/docker/Dockerfile.nrUE.ubuntu +++ b/docker/Dockerfile.nrUE.ubuntu @@ -119,6 +119,8 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai /usr/local/lib/libuhd.so.4.8.0 WORKDIR /opt/oai-nr-ue + +COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq COPY --from=nr-ue-base /tini /tini CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"] ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"] From 662c6e1aec738562a47248135cefd1c6c02bf422 Mon Sep 17 00:00:00 2001 From: Sagar Arora Date: Thu, 13 Nov 2025 12:49:34 +0100 Subject: [PATCH 02/30] Install yaml-cpp-dev for CU-UP and rocky Co-authored-by: Robert Schmidt Signed-off-by: Sagar Arora --- docker/Dockerfile.gNB.aw2s.rocky | 3 ++- docker/Dockerfile.gNB.fhi72.rocky | 3 ++- docker/Dockerfile.gNB.rocky | 3 ++- docker/Dockerfile.nr-cuup.rhel9 | 7 ++++++- docker/Dockerfile.nr-cuup.rocky | 4 +++- docker/Dockerfile.nr-cuup.ubuntu | 4 +++- docker/Dockerfile.nrUE.rocky | 3 ++- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/docker/Dockerfile.gNB.aw2s.rocky b/docker/Dockerfile.gNB.aw2s.rocky index 8fbd6cc91d..d1f567cb42 100644 --- a/docker/Dockerfile.gNB.aw2s.rocky +++ b/docker/Dockerfile.gNB.aw2s.rocky @@ -51,7 +51,8 @@ RUN dnf update -y && \ lksctp-tools \ tzdata \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf diff --git a/docker/Dockerfile.gNB.fhi72.rocky b/docker/Dockerfile.gNB.fhi72.rocky index 2dd7848d38..ba7861d1bf 100644 --- a/docker/Dockerfile.gNB.fhi72.rocky +++ b/docker/Dockerfile.gNB.fhi72.rocky @@ -49,7 +49,8 @@ RUN dnf update -y && \ python3 \ python3-pip \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ pip3 install six && \ pip3 install requests && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ diff --git a/docker/Dockerfile.gNB.rocky b/docker/Dockerfile.gNB.rocky index 2f646cf1b3..641dddfc0b 100644 --- a/docker/Dockerfile.gNB.rocky +++ b/docker/Dockerfile.gNB.rocky @@ -47,7 +47,8 @@ RUN dnf update -y && \ python3 \ python3-pip \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ pip3 install six && \ pip3 install requests && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ diff --git a/docker/Dockerfile.nr-cuup.rhel9 b/docker/Dockerfile.nr-cuup.rhel9 index a9c5f0d65a..e21c084c52 100644 --- a/docker/Dockerfile.nr-cuup.rhel9 +++ b/docker/Dockerfile.nr-cuup.rhel9 @@ -35,6 +35,9 @@ RUN cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypo FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-nr-cuup ENV TZ=Europe/Paris +# Install EPEL +RUN dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm + RUN yum repolist --disablerepo=* && \ yum update -y && \ yum install -y \ @@ -42,7 +45,8 @@ RUN yum repolist --disablerepo=* && \ lksctp-tools \ tzdata \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf @@ -55,6 +59,7 @@ COPY --from=gnb-build \ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ COPY --from=gnb-base \ diff --git a/docker/Dockerfile.nr-cuup.rocky b/docker/Dockerfile.nr-cuup.rocky index 8bbd206381..4e87797fd0 100644 --- a/docker/Dockerfile.nr-cuup.rocky +++ b/docker/Dockerfile.nr-cuup.rocky @@ -43,7 +43,8 @@ RUN yum repolist --disablerepo=* && \ lksctp-tools \ tzdata \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf @@ -56,6 +57,7 @@ COPY --from=gnb-build \ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ COPY --from=gnb-base \ diff --git a/docker/Dockerfile.nr-cuup.ubuntu b/docker/Dockerfile.nr-cuup.ubuntu index 1455dc1397..33fd01ab0e 100644 --- a/docker/Dockerfile.nr-cuup.ubuntu +++ b/docker/Dockerfile.nr-cuup.ubuntu @@ -42,7 +42,8 @@ RUN apt-get update && \ libconfig9 \ iproute2 \ net-tools \ - openssl && \ + openssl \ + libyaml-cpp-dev && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ libasan8 \ @@ -61,6 +62,7 @@ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ RUN ldconfig && ldd /opt/oai-gnb/bin/nr-cuup diff --git a/docker/Dockerfile.nrUE.rocky b/docker/Dockerfile.nrUE.rocky index 8d9057a0ed..6575d1e3bf 100644 --- a/docker/Dockerfile.nrUE.rocky +++ b/docker/Dockerfile.nrUE.rocky @@ -48,7 +48,8 @@ RUN dnf update -y && \ python3 \ python3-pip \ libXpm \ - libX11 && \ + libX11 \ + yaml-cpp-devel && \ pip3 install six && \ pip3 install requests && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ From a1b4220a916a1c67c2e63b0b9e11abe261aa82f2 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 27 Nov 2025 14:39:01 +0100 Subject: [PATCH 03/30] Exclusively use OAI_RNGSEED env variable everywhere Hide normal table initialization of Ziggurat generator from outside to force the usage of randominit() for RNG initialization. In this step, remove the randominit() seed parameter and only rely on OAI_RNGSEED for a consistent RNG initialization, as this parameter was used differently ("0" as fixed number or to force a random seed). Now, only use OAI_RNGSEED env variable to force the usage of a fixed seed. --- doc/environment-variables.md | 3 +- executables/lte-softmodem.c | 1 - executables/lte-uesoftmodem.c | 1 - executables/nr-softmodem.c | 1 - executables/nr-uesoftmodem.c | 1 - openair1/PHY/CODING/TESTBENCH/ldpctest.c | 2 +- openair1/PHY/CODING/TESTBENCH/ltetest.c | 4 +-- openair1/PHY/CODING/TESTBENCH/pdcch_test.c | 5 ++-- openair1/PHY/CODING/TESTBENCH/polartest.c | 2 +- .../PHY/CODING/TESTBENCH/smallblocktest.c | 2 +- openair1/PHY/INIT/lte_param_init.c | 2 +- openair1/PHY/TOOLS/tests/test_dft.c | 1 + openair1/SIMULATION/LTE_PHY/framegen.c | 2 +- openair1/SIMULATION/LTE_PHY/syncsim.c | 2 +- openair1/SIMULATION/LTE_PHY/test.c | 2 +- openair1/SIMULATION/LTE_PHY/ulsim.c | 3 +- openair1/SIMULATION/LTE_PHY/ulsim2.c | 2 +- openair1/SIMULATION/NR_PHY/dlschsim.c | 2 +- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/pbchsim.c | 28 ++++--------------- openair1/SIMULATION/NR_PHY/prachsim.c | 2 +- openair1/SIMULATION/NR_PHY/psbchsim.c | 6 ++-- openair1/SIMULATION/NR_PHY/pucchsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulschsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- openair1/SIMULATION/RF/rf.c | 2 +- openair1/SIMULATION/TOOLS/ch_desc_proto.c | 2 +- openair1/SIMULATION/TOOLS/random_channel.c | 5 ---- openair1/SIMULATION/TOOLS/rangen_double.c | 25 +++++++++-------- openair1/SIMULATION/TOOLS/sim.h | 3 +- radio/rfsimulator/simulator.c | 16 +---------- 31 files changed, 47 insertions(+), 88 deletions(-) diff --git a/doc/environment-variables.md b/doc/environment-variables.md index 767afa6db4..6fb7b884ae 100644 --- a/doc/environment-variables.md +++ b/doc/environment-variables.md @@ -9,7 +9,8 @@ OAI uses/supports a number of environment variables, documented in the following - `NVRAM_DIR`: directory to read/write NVRAM data in (5G) `nvram` tool; if not defined, will use `PWD` (working directory) - `OAI_CONFIGMODULE`: can be used to pass the configuration file instead of `-O` - `OAI_GDBSTACKS`: if defined when hitting an assertion (`DevAssert()`, `AssertFatal()`, ...), OAI will load `gdb` and provide a backtrace for every thread -- `OAI_RNGSEED`: overwrites any seed for random number generators (RNG) in simulators +- `OAI_RNGSEED`: provide a fixed seed for random number generators (RNG). If + this variable is absent, a random seed will be read (from `/dev/urandom`). - `USIM_DIR`: directory to read/write USIM data in (4G) `usim` tool; if not defined, will use `PWD` (working directory) Furthermore, these variables appear in code that is not maintained and maybe not even compiled anywhere: diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 6ff535fb5b..e2c4144707 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -405,7 +405,6 @@ int main ( int argc, char **argv ) #if T_TRACER T_Config_Init(); #endif - //randominit (0); set_taus_seed (0); printf("configuring for RAU/RRU\n"); diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index f36bdde2b5..fc741ec300 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -492,7 +492,6 @@ int main( int argc, char **argv ) { #if T_TRACER T_Config_Init(); #endif - //randominit (0); set_taus_seed (0); cpuf=get_cpu_freq_GHz(); pthread_cond_init(&sync_cond,NULL); diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 125bfbd898..ee20c68efe 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -546,7 +546,6 @@ int main( int argc, char **argv ) { #if T_TRACER T_Config_Init(); #endif - //randominit (0); set_taus_seed (0); cpuf=get_cpu_freq_GHz(); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index ca6c48dbef..f1cc659cae 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -340,7 +340,6 @@ int main(int argc, char **argv) T_Config_Init(); #endif initTpool(get_softmodem_params()->threadPoolConfig, &(nrUE_params.Tpool), cpumeas(CPUMEAS_GETSTATE)); - //randominit (0); set_taus_seed (0); if (!has_cap_sys_nice()) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 97b39beaf8..4dddaf7e7e 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -438,7 +438,7 @@ int main(int argc, char *argv[]) int n_trials = 1; double SNR_step = 0.1; - randominit(0); + randominit(); int test_uncoded = 0; n_iter_stats_t dec_iter[400] = {0}; diff --git a/openair1/PHY/CODING/TESTBENCH/ltetest.c b/openair1/PHY/CODING/TESTBENCH/ltetest.c index 45abec1697..97d66de486 100644 --- a/openair1/PHY/CODING/TESTBENCH/ltetest.c +++ b/openair1/PHY/CODING/TESTBENCH/ltetest.c @@ -72,7 +72,7 @@ void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmi PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); mac_xface = malloc(sizeof(MAC_xface)); - randominit(0); + randominit(); set_taus_seed(0); lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); @@ -367,7 +367,7 @@ int main(int argc, char *argv[]) int num_pdcch_symbols = 1; int subframe = 6; - randominit(0); + randominit(); logInit(); lte_param_init(1,1,1,0,0,3); diff --git a/openair1/PHY/CODING/TESTBENCH/pdcch_test.c b/openair1/PHY/CODING/TESTBENCH/pdcch_test.c index 873e9e19bc..2a752bfee8 100644 --- a/openair1/PHY/CODING/TESTBENCH/pdcch_test.c +++ b/openair1/PHY/CODING/TESTBENCH/pdcch_test.c @@ -47,7 +47,7 @@ void lte_param_init(unsigned char N_tx, unsigned char N_rx) PHY_config = malloc(sizeof(PHY_CONFIG)); mac_xface = malloc(sizeof(MAC_xface)); - randominit(0); + randominit(); set_taus_seed(0); lte_frame_parms = &(PHY_config->lte_frame_parms); @@ -241,8 +241,7 @@ int main(int argc, char *argv[]) PHY_vars = malloc(sizeof(PHY_VARS)); mac_xface = malloc(sizeof(MAC_xface)); - - randominit(0); + randominit(); set_taus_seed(0); ccodelte_init(); diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c index e84a62775b..cb51f85aca 100644 --- a/openair1/PHY/CODING/TESTBENCH/polartest.c +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) cpu_meas_enabled = 1; reset_meas(&timeEncoder); reset_meas(&timeDecoder); - randominit(0); + randominit(); crcTableInit(); if (polarMessageType == 0) { // PBCH diff --git a/openair1/PHY/CODING/TESTBENCH/smallblocktest.c b/openair1/PHY/CODING/TESTBENCH/smallblocktest.c index a701a49d1a..275262428c 100644 --- a/openair1/PHY/CODING/TESTBENCH/smallblocktest.c +++ b/openair1/PHY/CODING/TESTBENCH/smallblocktest.c @@ -13,7 +13,7 @@ int main(int argc, char *argv[]) cpu_meas_enabled = 1; reset_meas(&timeEncoder); reset_meas(&timeDecoder); - randominit(0); + randominit(); int ret = 1; int arguments, iterations = 1000, messageLength = 11; diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c index 81177a63cb..d2d963ade4 100644 --- a/openair1/PHY/INIT/lte_param_init.c +++ b/openair1/PHY/INIT/lte_param_init.c @@ -77,7 +77,7 @@ void lte_param_init(PHY_VARS_eNB **eNBp, eNB->RU_list[0] = ru; ru->num_eNB=1; srand(0); - randominit(0); + randominit(); set_taus_seed(0); frame_parms = &(eNB->frame_parms); frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz diff --git a/openair1/PHY/TOOLS/tests/test_dft.c b/openair1/PHY/TOOLS/tests/test_dft.c index 8b4c344c6c..abcb0c05f7 100644 --- a/openair1/PHY/TOOLS/tests/test_dft.c +++ b/openair1/PHY/TOOLS/tests/test_dft.c @@ -70,6 +70,7 @@ void math_dft(cd_t *in, cd_t *out, int len) int main(void) { int ret = 0; + randominit(); load_dftslib(); c16_t *d16 = malloc16(12 * dftFtab[sizeofArray(dftFtab) - 1].size * sizeof(*d16)); c16_t *o16 = malloc16(12 * dftFtab[sizeofArray(dftFtab) - 1].size * sizeof(*d16)); diff --git a/openair1/SIMULATION/LTE_PHY/framegen.c b/openair1/SIMULATION/LTE_PHY/framegen.c index fe1c4b49b7..30fc6d5745 100644 --- a/openair1/SIMULATION/LTE_PHY/framegen.c +++ b/openair1/SIMULATION/LTE_PHY/framegen.c @@ -378,7 +378,7 @@ void lte_param_init( unsigned char transmission_mode, mac_xface->get_dci_sdu = get_dci; mac_xface->get_dlsch_sdu = get_DLSCH_pdu; - randominit(0); + randominit(); set_taus_seed(0); lte_frame_parms = &(PHY_vars_eNB_g[0]->lte_frame_parms); diff --git a/openair1/SIMULATION/LTE_PHY/syncsim.c b/openair1/SIMULATION/LTE_PHY/syncsim.c index ccdac230f8..456bc53a2c 100644 --- a/openair1/SIMULATION/LTE_PHY/syncsim.c +++ b/openair1/SIMULATION/LTE_PHY/syncsim.c @@ -249,7 +249,7 @@ void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmi PHY_vars_UE[1] = malloc(sizeof(PHY_VARS_UE)); //PHY_config = malloc(sizeof(PHY_CONFIG)); mac_xface = malloc(sizeof(MAC_xface)); - randominit(0); + randominit(); set_taus_seed(0); lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz diff --git a/openair1/SIMULATION/LTE_PHY/test.c b/openair1/SIMULATION/LTE_PHY/test.c index 6b78dad4e7..b292279860 100644 --- a/openair1/SIMULATION/LTE_PHY/test.c +++ b/openair1/SIMULATION/LTE_PHY/test.c @@ -174,7 +174,7 @@ int main(int argc, char **argv) for (i = 0; i<4; i++) ch[i] = (struct complexd*) malloc(channel_length * sizeof(struct complexd)); - randominit(0); + randominit(); set_taus_seed(0); #ifdef RF diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 76cc2e0716..7a442a4082 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -839,8 +839,7 @@ int main(int argc, char **argv) { ack_errors=0; cqi_crc_falsepositives=0; cqi_crc_falsenegatives=0; - round=0; - //randominit(0); + round = 0; harq_pid = subframe2harq_pid(&UE->frame_parms,proc_rxtx_ue->frame_tx,subframe); input_buffer_length = UE->ulsch[0]->harq_processes[harq_pid]->TBS/8; diff --git a/openair1/SIMULATION/LTE_PHY/ulsim2.c b/openair1/SIMULATION/LTE_PHY/ulsim2.c index e994d4fc36..32c0d4d8e9 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim2.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim2.c @@ -232,7 +232,7 @@ int main(int argc, char **argv) //LOG_M("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); // multipath channel - randominit(0); + randominit(); for (i=0; inb_antennas_tx; aa++) { diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index ea4a068b6e..d760e2394b 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -141,7 +141,7 @@ int main(int argc, char **argv) } // logInit(); - randominit(0); + randominit(); int c; while ((c = getopt(argc, argv, "--:O:df:hpVg:i:j:n:l:m:r:s:S:y:z:M:N:F:R:P:L:X:")) != -1) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 82984657d3..78ba2c6096 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -393,7 +393,7 @@ int main(int argc, char **argv) exit_fun("[NR_DLSIM] Error, configuration module init failed\n"); } - randominit(0); + randominit(); int print_perf = 0; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index c86744afaa..30905619a7 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -176,8 +176,6 @@ int main(int argc, char **argv) float target_error_rate = 0.01; - int seed = 0; - cpuf = get_cpu_freq_GHz(); if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) { @@ -185,8 +183,7 @@ int main(int argc, char **argv) } int c; - while ((c = getopt (argc, argv, "--:O:c:F:g:hIL:m:M:n:N:o:P:r:R:s:S:x:y:z:")) != -1) { - + while ((c = getopt(argc, argv, "--:O:c:F:g:hIL:m:M:n:N:o:P:R:s:S:x:y:z:")) != -1) { /* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */ /* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */ if (c == 1 || c == '-' || c == 'O') @@ -312,20 +309,6 @@ int main(int argc, char **argv) printf("Illegal PBCH phase (0-3) got %d\n",pbch_phase); break; - /* - case 'r': - ricean_factor = pow(10,-.1*atof(optarg)); - if (ricean_factor>1) { - printf("Ricean factor must be between 0 and 1\n"); - exit(-1); - } - break; - */ - - case 'r': - seed = atoi(optarg); - break; - case 'R': N_RB_DL = atoi(optarg); break; @@ -379,8 +362,10 @@ int main(int argc, char **argv) default: case 'h': - printf("%s -F input_filename -g channel_mod -h(elp) -I(nitial sync) -L log_lvl -n n_frames -M SSBs -n frames -N cell_id -o FO -P phase -r seed -R RBs -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant\n", - argv[0]); + printf( + "OAI_RNGSEED=xxx ./%s -F input_filename -g channel_mod -h(elp) -I(nitial sync) -L log_lvl -n n_frames -M SSBs -n frames " + "-N cell_id -o FO -P phase -R RBs -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant\n", + argv[0]); //printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n"); printf("-c SSB subcarrier offset\n"); //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n"); @@ -401,7 +386,6 @@ int main(int argc, char **argv) //printf("-O oversampling factor (1,2,4,8,16)\n"); //printf("-p Use extended prefix mode\n"); printf("-P PBCH phase, allowed values 0-3\n"); - printf("-r set the random number generator seed (default: 0 = current time)\n"); printf("-R N_RB_DL\n"); printf("-s Starting SNR, runs from SNR0 to SNR0 + 10 dB if not -S given. If -n 1, then just SNR is simulated\n"); printf("-S Ending SNR, runs from SNR0 to SNR1\n"); @@ -414,7 +398,7 @@ int main(int argc, char **argv) } } - randominit(seed); + randominit(); logInit(); set_glog(loglvl); diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index aba532a80d..9fd9757f9d 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -162,7 +162,7 @@ int main(int argc, char **argv){ exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); } - randominit(0); + randominit(); int c; while ((c = getopt (argc, argv, "--:O:hHaA:Cc:l:r:p:g:m:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) { diff --git a/openair1/SIMULATION/NR_PHY/psbchsim.c b/openair1/SIMULATION/NR_PHY/psbchsim.c index 17c3473eb8..fc5280559e 100644 --- a/openair1/SIMULATION/NR_PHY/psbchsim.c +++ b/openair1/SIMULATION/NR_PHY/psbchsim.c @@ -325,15 +325,13 @@ int main(int argc, char **argv) // int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; - int seed = 0; - cpuf = get_cpu_freq_GHz(); if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) { exit_fun("[NR_PSBCHSIM] Error, configuration module init failed\n"); } - randominit(0); + randominit(); int c; while ((c = getopt(argc, argv, "--:O:c:hn:o:s:FIL:N:R:S:T:")) != -1) { @@ -456,7 +454,7 @@ int main(int argc, char **argv) } } - randominit(seed); + randominit(); logInit(); set_glog(loglvl); diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 8c9f2961c4..21d43f48ad 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -151,7 +151,7 @@ int main(int argc, char **argv) exit_fun("[NR_PUCCHSIM] Error, configuration module init failed\n"); } - randominit(0); + randominit(); logInit(); int c; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 77a0046e1f..3705df3b2c 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -139,7 +139,7 @@ int main(int argc, char **argv) } //logInit(); - randominit(0); + randominit(); int c; while ((c = getopt(argc, argv, "--:O:hg:n:s:S:py:z:M:N:R:F:m:l:q:r:W:")) != -1) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 85c165b00d..04b3521cf0 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -348,7 +348,7 @@ int main(int argc, char *argv[]) } int ul_proc_error = 0; // uplink processing checking status flag //logInit(); - randominit(0); + randominit(); /* initialize the sin-cos table */ InitSinLUT(); diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c index 081a102bbb..e9b49ed8f2 100644 --- a/openair1/SIMULATION/RF/rf.c +++ b/openair1/SIMULATION/RF/rf.c @@ -248,7 +248,7 @@ int main(int argc, char* argv[]) channel_desc_t *channel; srand(0); - randominit(0); + randominit(); set_taus_seed(0); channel = new_channel_desc_scm(nb_antennas, diff --git a/openair1/SIMULATION/TOOLS/ch_desc_proto.c b/openair1/SIMULATION/TOOLS/ch_desc_proto.c index b1e71fcfb4..dbc77a9b9b 100644 --- a/openair1/SIMULATION/TOOLS/ch_desc_proto.c +++ b/openair1/SIMULATION/TOOLS/ch_desc_proto.c @@ -93,7 +93,7 @@ int main() { {3420,2820},{1580,3940},{660,2100},{2740,1180},{2500,2500}, {3580,3580},{3740,3140},{3020,3020},{4340,4140},{980,4300} }; - randominit(0); + randominit(); ///////////////////////////////////////////////////////////////////////////////////////////////// int tabl_len=0; double local_table[MCS_COUNT][9][9]; diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index d13cfd8921..bed23968e4 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -572,11 +572,6 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, double path_loss_dB, float noise_power_dB) { - // To create tables for normal distribution - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - tableNor((long) (t.tv_nsec % INT_MAX)); - channel_desc_t *chan_desc = (channel_desc_t *)calloc(1,sizeof(channel_desc_t)); for(int i=0; ichannelmod > 0) { // create channel simulation model for this mode reception - static bool init_done = false; - - if (!init_done) { - uint64_t rand; - FILE *h = fopen("/dev/random", "r"); - - if (1 != fread(&rand, sizeof(rand), 1, h)) - LOG_W(HW, "Can't read /dev/random\n"); - - fclose(h); - randominit(rand); - tableNor(rand); - init_done = true; - } char modelname[30]; snprintf(modelname, sizeofArray(modelname), @@ -1170,7 +1156,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1, "epoll_create1() failed, errno(%d)", errno); // we need to call randominit() for telnet server (use gaussdouble=>uniformrand) - randominit(0); + randominit(); set_taus_seed(0); /* look for telnet server, if it is loaded, add the channel modeling commands to it */ add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); From ce7cb165dd6e0382661479eb51bad888cac3e84c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 29 Nov 2025 16:52:14 +0100 Subject: [PATCH 04/30] Fix OAI_RNGSEED to capture unsigned long atoi() used previously does not capture all of unsigned long (so we could not reproduce a high seed), and its use is discouraged as it does not detect errors. Use strtoul() instead, which allows to also use other bases (so we can e.g., write OAI_RNGSEED=0x1234) --- openair1/SIMULATION/TOOLS/rangen_double.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openair1/SIMULATION/TOOLS/rangen_double.c b/openair1/SIMULATION/TOOLS/rangen_double.c index 5f6f898066..9c38e33ce9 100644 --- a/openair1/SIMULATION/TOOLS/rangen_double.c +++ b/openair1/SIMULATION/TOOLS/rangen_double.c @@ -56,7 +56,14 @@ void randominit() unsigned long seed; const char* str_oai_rngseed = getenv("OAI_RNGSEED"); if (str_oai_rngseed != NULL) { - seed = atoi(str_oai_rngseed); + char *end; + seed = strtoul(str_oai_rngseed, &end, 0); /* 0: any base in hex, dec, oct */ + AssertFatal(*end == '\0' || *end == '\n', + "could not read seed %s at char '%c' (%d), pos %ld\n", + str_oai_rngseed, + *end, + *end, + end - str_oai_rngseed); } else { fill_random(&seed, sizeof(seed)); } From ad1c92af4f87fca50f2fe61519b17c18b92f54a1 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 25 Nov 2025 16:59:33 +0100 Subject: [PATCH 05/30] Refactor NG UE Context Release Request 1) Remove UE Context Release Response code: there is no such thing in the specs, it is either UE Context Release Request (NG-RAN node initiated) or UE Context Release (AMF initiated) (3GPP TS 38.413). The former message has only the request, no response is defined by the specs. The code in the stack had no purpose at all and was removed. 2) The UE Context Release Request message only contains a PDU Session Resource List (optional) of PDU Session IDs, therefore the use of pdusession_release_t was wrong and was refactored --- openair2/COMMON/ngap_messages_def.h | 1 - openair2/COMMON/ngap_messages_types.h | 39 ++++++++++--------- openair2/RRC/NR/rrc_gNB.c | 4 -- openair2/RRC/NR/rrc_gNB_NGAP.c | 33 ++-------------- .../ngap_gNB_context_management_procedures.c | 2 +- 5 files changed, 25 insertions(+), 54 deletions(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 98c1f82260..26f607f884 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -64,7 +64,6 @@ MESSAGE_DEF(NGAP_UE_CAPABILITIES_IND , MESSAGE_PRIORITY_MED, ngap_ue_cap_i MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_resp_t, ngap_initial_context_setup_resp) MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_FAIL, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_fail_t, ngap_initial_context_setup_fail) MESSAGE_DEF(NGAP_NAS_NON_DELIVERY_IND , MESSAGE_PRIORITY_MED, ngap_nas_non_delivery_ind_t , ngap_nas_non_delivery_ind) -MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_RESP , MESSAGE_PRIORITY_MED, ngap_ue_release_resp_t , ngap_ue_release_resp) MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, ngap_ue_release_complete_t , ngap_ue_release_complete) MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_resp_t , ngap_ue_ctxt_modification_resp) MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_fail_t , ngap_ue_ctxt_modification_fail) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 5be5e316ef..92ea721705 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -47,7 +47,6 @@ #define NGAP_UE_CAPABILITIES_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_cap_info_ind #define NGAP_INITIAL_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_resp #define NGAP_INITIAL_CONTEXT_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_fail -#define NGAP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_resp #define NGAP_NAS_NON_DELIVERY_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_nas_non_delivery_ind #define NGAP_UE_CTXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_resp #define NGAP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_fail @@ -733,12 +732,6 @@ typedef struct ngap_ue_ctxt_modification_resp_s { uint32_t gNB_ue_ngap_id; } ngap_ue_ctxt_modification_resp_t; -typedef struct ngap_ue_release_complete_s { - uint32_t gNB_ue_ngap_id; - int num_pdu_sessions; - uint32_t pdu_session_id[256]; -} ngap_ue_release_complete_t; - //-------------------------------------------------------------------------------------------// // NGAP -> RRC messages typedef struct ngap_downlink_nas_s { @@ -862,20 +855,24 @@ typedef struct ngap_ue_release_command_s { //-------------------------------------------------------------------------------------------// // NGAP <-- RRC messages -typedef struct pdusession_release_s { - /* Unique pdusession_id for the UE. */ - uint8_t pdusession_id; - byte_array_t data; -} pdusession_release_t; - typedef struct ngap_ue_release_req_s { - uint32_t gNB_ue_ngap_id; - /* Number of pdusession resource in the list */ + // RAN UE NGAP ID (mandatory) + uint32_t gNB_ue_ngap_id; + // PDU Session Resource List (optional) uint16_t nb_of_pdusessions; - /* list of pdusession resource by RRC layers */ - pdusession_release_t pdusessions[NGAP_MAX_PDU_SESSION]; + uint8_t pdusession_ids[NGAP_MAX_PDU_SESSION]; + // Cause (mandatory) ngap_cause_t cause; -} ngap_ue_release_req_t, ngap_ue_release_resp_t; +} ngap_ue_release_req_t; + +typedef struct { + // RAN UE NGAP ID (mandatory) + uint32_t gNB_ue_ngap_id; + // PDU Session Resource List (optional) + uint16_t num_pdu_sessions; + // PDU Session ID (mandatory) + uint8_t pdu_session_id[NGAP_MAX_PDU_SESSION]; +} ngap_ue_release_complete_t; typedef struct ngap_pdusession_modify_req_s { /* AMF UE id */ @@ -905,6 +902,12 @@ typedef struct ngap_pdusession_modify_resp_s { pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_modify_resp_t; +typedef struct pdusession_release_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + byte_array_t data; +} pdusession_release_t; + typedef struct ngap_pdusession_release_command_s { /* AMF UE id */ uint64_t amf_ue_ngap_id; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b18e820e91..6d9d07401a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -3187,10 +3187,6 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_dc_overall_timeout(instance, &X2AP_ENDC_DC_OVERALL_TIMEOUT(msg_p)); break; - case NGAP_UE_CONTEXT_RELEASE_REQ: - rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(msg_p, instance); - break; - case NGAP_UE_CONTEXT_RELEASE_COMMAND: rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p, instance); break; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 8ba7b3e950..fdd424df52 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1049,7 +1049,8 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE return 0; } -//------------------------------------------------------------------------------ +/** @brief Send UE Context Release Request (NG-RAN node initiated) + * Direction: NG-RAN node -> AMF (8.3.2.2 3GPP TS 38.413) */ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(const module_id_t gnb_mod_idP, const rrc_gNB_ue_context_t *const ue_context_pP, const ngap_cause_t causeP) @@ -1068,40 +1069,12 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(const module_id_t gnb_mod_idP, // PDU Session Resource List (optional) FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, session, &UE->pduSessions) { DevAssert(req->nb_of_pdusessions < NGAP_MAX_PDU_SESSION); - req->pdusessions[req->nb_of_pdusessions].pdusession_id = session->param.pdusession_id; + req->pdusession_ids[req->nb_of_pdusessions] = session->param.pdusession_id; req->nb_of_pdusessions++; } itti_send_msg_to_task(TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_mod_idP), msg); } } -/*------------------------------------------------------------------------------*/ -int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t instance) -{ - uint32_t gNB_ue_ngap_id; - gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_REQ(msg_p).gNB_ue_ngap_id; - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], gNB_ue_ngap_id); - - if (ue_context_p == NULL) { - /* Can not associate this message to an UE index, send a failure to ngAP and discard it! */ - MessageDef *msg_fail_p; - LOG_W(RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_REQ: unknown UE from gNB_ue_ngap_id (%u)\n", - instance, - gNB_ue_ngap_id); - msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); /* TODO change message ID. */ - NGAP_UE_CONTEXT_RELEASE_RESP(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; - // TODO add failure cause when defined! - itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p); - return (-1); - } else { - - /* Send the response */ - MessageDef *msg_resp_p; - msg_resp_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); - NGAP_UE_CONTEXT_RELEASE_RESP(msg_resp_p).gNB_ue_ngap_id = gNB_ue_ngap_id; - itti_send_msg_to_task(TASK_NGAP, instance, msg_resp_p); - return (0); - } -} /** @brief Sends the NG Handover Failure from the Target NG-RAN to the AMF */ void rrc_gNB_send_NGAP_HANDOVER_FAILURE(gNB_RRC_INST *rrc, ngap_handover_failure_t *msg) diff --git a/openair3/NGAP/ngap_gNB_context_management_procedures.c b/openair3/NGAP/ngap_gNB_context_management_procedures.c index 7f114d5bf6..57b7780d4f 100644 --- a/openair3/NGAP/ngap_gNB_context_management_procedures.c +++ b/openair3/NGAP/ngap_gNB_context_management_procedures.c @@ -191,7 +191,7 @@ int ngap_ue_context_release_req(instance_t instance, for (int i = 0; i < ue_release_req_p->nb_of_pdusessions; i++) { NGAP_PDUSessionResourceItemCxtRelReq_t *item; item = (NGAP_PDUSessionResourceItemCxtRelReq_t *)calloc(1,sizeof(NGAP_PDUSessionResourceItemCxtRelReq_t)); - item->pDUSessionID = ue_release_req_p->pdusessions[i].pdusession_id; + item->pDUSessionID = ue_release_req_p->pdusession_ids[i]; asn1cSeqAdd(&ie->value.choice.PDUSessionResourceListCxtRelReq.list, item); } } From 9e45f38fbd95e69197f8ab9887f48fe42e144225 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 25 Nov 2025 17:35:40 +0100 Subject: [PATCH 06/30] fix PDU Sesion Release response: add missing PDUSessionResourceReleaseResponseTransfer IE The PDUSessionResourceReleaseResponse message was missing the mandatory pDUSessionResourceReleaseResponseTransfer IE in each released PDU session item. This caused Open5GS to send an error indication. Changes: - Add encode_ngap_pdusession_release_response_transfer() function to properly encode the transfer structure (empty since Secondary RAT Usage Information is optional and not used, per 9.3.4.21) - Always include the mandatory PDUSessionResourceReleasedListRelRes IE - Always encode the pDUSessionResourceReleaseResponseTransfer for each PDU session item - Fix Release Command handler to decode and log Cause from command transfer: instead of incorrectly copying command data to response: the 2 transfer IEs in the Command and the Response messages are different and should not be mixed - Split Command/Response struct type definitions - Add missing includes --- common/utils/telnetsrv/telnetsrv_ci.c | 4 +-- openair2/COMMON/ngap_messages_types.h | 19 ++++++------- openair2/RRC/NR/rrc_gNB_NGAP.c | 4 +-- openair3/NGAP/ngap_gNB_handlers.c | 17 +++++++++-- openair3/NGAP/ngap_gNB_nas_procedures.c | 38 ++++++++++++++++++++----- openair3/NGAP/ngap_msg_includes.h | 2 ++ 6 files changed, 60 insertions(+), 24 deletions(-) diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 8b00d529c5..54c650dd0f 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -348,7 +348,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu if (sid < 1 || sid > 255) { ERROR_MSG_RET("Invalid pdusession_id(int): %s (must be between 1 and 255)\n", tokens[i]); } - msg->pdusession_release_params[nb_sessions++].pdusession_id = sid; + msg->pdusession_ids[nb_sessions++] = sid; } msg->nb_pdusessions_torelease = nb_sessions; @@ -356,7 +356,7 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu if (prnt) { prnt("Triggering NGAP PDU Session Release for gNB_ue_ngap_id=%d: releasing pdusession_id=%d", gNB_ue_ngap_id); for (int i = 0; i < nb_sessions; ++i) { - prnt(" %d,", msg->pdusession_release_params[i].pdusession_id); + prnt(" %d,", msg->pdusession_ids[i]); } prnt("\n"); } diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 92ea721705..ed93cdaadf 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -902,12 +902,6 @@ typedef struct ngap_pdusession_modify_resp_s { pdusession_failed_t pdusessions_failed[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_modify_resp_t; -typedef struct pdusession_release_s { - /* Unique pdusession_id for the UE. */ - uint8_t pdusession_id; - byte_array_t data; -} pdusession_release_t; - typedef struct ngap_pdusession_release_command_s { /* AMF UE id */ uint64_t amf_ue_ngap_id; @@ -918,14 +912,19 @@ typedef struct ngap_pdusession_release_command_s { /* The NAS PDU should be forwarded by the RRC layer to the NAS layer */ byte_array_t nas_pdu; - /* Number of pdusession to be released in the list */ + // PDU Session Resource to Release List (mandatory) uint16_t nb_pdusessions_torelease; - - /* PDUSession release command */ - pdusession_release_t pdusession_release_params[NGAP_MAX_PDU_SESSION]; + uint16_t pdusession_ids[NGAP_MAX_PDU_SESSION]; } ngap_pdusession_release_command_t; +typedef struct pdusession_release_s { + // PDU Session ID (mandatory) + uint8_t pdusession_id; + // PDU Session Resource Release Response Transfer (mandatory) + byte_array_t pdusession_release_response_transfer; +} pdusession_release_t; + typedef struct ngap_pdusession_release_resp_s { // AMF UE NGAP ID uint64_t amf_ue_ngap_id; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index fdd424df52..a546b5eb33 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1526,9 +1526,9 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_comm cmd->nb_pdusessions_torelease); e1ap_bearer_mod_req_t req = {0}; for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { - rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id); + rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_ids[pdusession]); if (!pduSession) { - LOG_E(NR_RRC, "Failed to release non-existing PDU Session %d\n", cmd->pdusession_release_params[pdusession].pdusession_id); + LOG_E(NR_RRC, "Failed to release non-existing PDU Session %d\n", cmd->pdusession_ids[pdusession]); continue; } if (pduSession->status == PDU_SESSION_STATUS_TORELEASE) { diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 95c2dd45a7..a58c98508b 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -1390,9 +1390,20 @@ static int ngap_gNB_handle_pdusession_release_command(sctp_assoc_t assoc_id, uin for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) { NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p; item_p = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i]; - pdusession_release_t *r = &msg->pdusession_release_params[i]; - r->pdusession_id = item_p->pDUSessionID; - r->data = create_byte_array(item_p->pDUSessionResourceReleaseCommandTransfer.size, item_p->pDUSessionResourceReleaseCommandTransfer.buf); + msg->pdusession_ids[i] = item_p->pDUSessionID; + + /* PDUSessionResourceReleaseCommandTransfer (Mandatory) */ + void *decoded = decode_pdusession_transfer(&asn_DEF_NGAP_PDUSessionResourceReleaseCommandTransfer, + item_p->pDUSessionResourceReleaseCommandTransfer); + if (!decoded) { + NGAP_ERROR("Failed to decode PDUSessionResourceReleaseCommandTransfer for PDU Session %d\n", msg->pdusession_ids[i]); + return -1; + } + NGAP_PDUSessionResourceReleaseCommandTransfer_t *transfer = decoded; + ngap_cause_t cause = decode_ngap_cause(&transfer->cause); + NGAP_INFO("PDU Session %d release command: Cause type=%d value=%d\n", msg->pdusession_ids[i], cause.type, cause.value); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseCommandTransfer, transfer); + free(transfer); } itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 7dd6359b7a..2218155c61 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -594,6 +594,24 @@ static byte_array_t encode_ngap_pdusession_setup_response_transfer(const pdusess return out; } +/** @brief PDU Session Resource Release Response Transfer encoding (9.3.4.21 3GPP TS 38.413) + * The transfer structure contains only an optional Secondary RAT Usage Information IE. + * Since we don't use secondary RAT (MR-DC), we encode an empty structure. */ +static byte_array_t encode_ngap_pdusession_release_response_transfer(void) +{ + NGAP_PDUSessionResourceReleaseResponseTransfer_t pdusessionTransfer = {0}; + + // Encode + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, + ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, + &pdusessionTransfer); + AssertFatal(res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceReleaseResponseTransfer, &pdusessionTransfer); + byte_array_t out = {.buf = res.buffer, .len = res.result.encoded}; + return out; +} + //------------------------------------------------------------------------------ int ngap_gNB_initial_ctxt_resp(instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p) //------------------------------------------------------------------------------ @@ -1200,22 +1218,28 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id; } - /* optional */ - if (pdusession_release_resp_p->nb_of_pdusessions_released > 0) { + /* PDU Session Resource Released List (mandatory) */ + { asn1cSequenceAdd(out->protocolIEs.list, NGAP_PDUSessionResourceReleaseResponseIEs_t, ie); ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; ie->criticality = NGAP_Criticality_ignore; ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; - + for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { - asn1cSequenceAdd(ie->value.choice.PDUSessionResourceReleasedListRelRes.list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item); + NGAP_PDUSessionResourceReleasedListRelRes_t *list = &ie->value.choice.PDUSessionResourceReleasedListRelRes; + asn1cSequenceAdd(list->list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item); pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i]; + /* PDU Session ID (mandatory) */ item->pDUSessionID = r->pdusession_id; - OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)r->data.buf, r->data.len); - NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID); + /* PDU Session Resource Release Response Transfer (mandatory) */ + // Empty transfer is valid since Secondary RAT Usage Information is optional and not used + byte_array_t transfer = encode_ngap_pdusession_release_response_transfer(); + OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)transfer.buf, transfer.len); + free_byte_array(transfer); + NGAP_DEBUG("PDU Session Resource Release Response: pdusession ID %ld\n", item->pDUSessionID); } } - + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode release response\n"); /* Encode procedure has failed... */ diff --git a/openair3/NGAP/ngap_msg_includes.h b/openair3/NGAP/ngap_msg_includes.h index 816cdfb979..2a861e2e32 100644 --- a/openair3/NGAP/ngap_msg_includes.h +++ b/openair3/NGAP/ngap_msg_includes.h @@ -58,6 +58,8 @@ #include "NGAP_PDUSessionResourceSetupResponseTransfer.h" #include "NGAP_PDUSessionResourceSetupUnsuccessfulTransfer.h" #include "NGAP_PDUSessionResourceToReleaseItemRelCmd.h" +#include "NGAP_PDUSessionResourceReleaseCommandTransfer.h" +#include "NGAP_PDUSessionResourceReleaseResponseTransfer.h" #include "NGAP_PLMNSupportItem.h" #include "NGAP_ProtocolIE-Field.h" #include "NGAP_QosFlowAddOrModifyResponseItem.h" From 5af58cc6865807bd253aed0f47143ca6f446685b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 2 Dec 2025 13:35:47 +0100 Subject: [PATCH 07/30] RFemulator: initialize RNG when using noise device After !3786, we always have to initialize the RNG when using random numbers. This was not done for RFemulator and has been added here. --- radio/emulator/rf_emulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/emulator/rf_emulator.c b/radio/emulator/rf_emulator.c index 861daab2ba..e73e9bf3d6 100644 --- a/radio/emulator/rf_emulator.c +++ b/radio/emulator/rf_emulator.c @@ -364,6 +364,8 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) device->trx_read_func = emulator_read; emulator_readconfig(emulator_state); + if (emulator_state->enable_noise) + randominit(); // for noise device return 0; } From f35a1cd775dd2e28a4d2f174a4940c4723fb28f9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 2 Dec 2025 13:29:23 +0100 Subject: [PATCH 08/30] Increase Aerial-based L2 test core number Testing has revealed that if PDCP drops some packets, the scheduler falls behind with handling Slot.indication. It could be that we don't have enough cores, which was reduced previously (from total 8 -> 2). Reincrease to four cores to have a bit more headroom. See-also: a18a4888ec90 ("Change number of cores used for OAI gNB from 8 to 2") --- ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml | 2 +- doc/Aerial_FAPI_Split_Tutorial.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml index f04beeb6c2..4050fa5310 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -33,7 +33,7 @@ services: timeout: 5s retries: 5 oai-gnb-aerial: - cpuset: "13-14" + cpuset: "13-16" image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-aerial}:${TAG:-develop} depends_on: nv-cubb: diff --git a/doc/Aerial_FAPI_Split_Tutorial.md b/doc/Aerial_FAPI_Split_Tutorial.md index 6eef02dc34..23ce37312d 100644 --- a/doc/Aerial_FAPI_Split_Tutorial.md +++ b/doc/Aerial_FAPI_Split_Tutorial.md @@ -82,7 +82,7 @@ of the FAPI 10.04 version of the SRS PDU, and RX_Beamforming PDU. | Applicative Threads | Allocated CPUs | |------------------------|----------------| | PTP & PHC2SYS Services | 41 | -| OAI `nr-softmodem` | 13-14 | +| OAI `nr-softmodem` | 13-16 | ## PTP configuration From 388ad30f6bded180aa62474ff82bac8ebaf89e74 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 2 Dec 2025 11:25:17 +0100 Subject: [PATCH 09/30] Fix missing E2SM-RC message forward E2SM-RC RRC message forwarding (e.g., to signal a new UE, measurement reports, ...) was broken since commit d6c29b2d2c4a, as we accidentally removed the E2_AGENT compilation definition from RRC layer. Although this commit fixes the mentioned issue, it also causes undefined references to functions defined in ran_func_rc.c file. Therefore, we add a hack that provides the definition, and abort if we ever hit these functions, which in theory should not happen. Future cleanup should avoid linking in RRC and other layers into simulators. Fixes: d6c29b2d2c4a ("Fix E2_AGENT linking w.r.t. simulators ") --- CMakeLists.txt | 9 +++++++++ openair1/SIMULATION/NR_PHY/dlsim.c | 9 +++++++++ openair1/SIMULATION/NR_PHY/ulsim.c | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f8a6006bf..70ea409d36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,6 +464,9 @@ target_include_directories(f1ap PUBLIC F1AP_DIR) target_link_libraries(f1ap PUBLIC asn1_f1ap GTPV1U) target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib) target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib) +if(E2_AGENT) + target_compile_definitions(f1ap PRIVATE E2_AGENT) +endif() # LPP ############## @@ -1288,6 +1291,9 @@ add_library(L2 ) target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap) target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +if(E2_AGENT) + target_compile_definitions(L2 PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT) +endif() add_library(MAC_UE_NR ${MAC_NR_SRC_UE}) target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs PUBLIC nr_ue_power_procedures nr_ue_ra_procedures) @@ -1303,6 +1309,9 @@ add_library(L2_NR target_link_libraries(L2_NR PRIVATE ds alg) target_link_libraries(L2_NR PRIVATE f1ap_lib) target_include_directories(L2_NR PRIVATE ${F1AP_DIR}/lib) +if(E2_AGENT) + target_compile_definitions(L2_NR PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT) +endif() add_library(e1_if ${NR_RRC_DIR}/cucp_cuup_direct.c diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 82984657d3..9a2b834ae3 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -118,6 +118,15 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t { } +/* this is a hack, but necessary for E2 agent. We compile in all of RRC + * (because of CMakeLists.txt), but we don't need it (only nr_radio_config.c). + * however, if E2 agent is defined, the following functions are used in + * rrc_gNB.c, but defined in RAN functions. In order to avoid pulling this in + * here as well, only provide a prototype (and abort if they are ever called). */ +void signal_rrc_msg(void /*const nr_rrc_class_e nr_channel, const uint32_t rrc_msg_id, const byte_array_t rrc_ba*/ ) { abort(); } +void signal_rrc_state_changed_to(void /* const gNB_RRC_UE_t *rrc_ue_context, const rrc_state_e2sm_rc_e rrc_state */) { abort(); } +void signal_ue_id(void /* const gNB_RRC_UE_t *rrc_ue_context, const uint16_t class, const uint32_t msg_id */) { abort(); } + /* Function to set or overwrite PTRS DL RRC parameters */ static void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, long *ptrsNrb, long *ptrsMcs, long *epre_Ratio, long *reOffset) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 85c165b00d..6be851c0a6 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -120,6 +120,15 @@ void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t { } +/* this is a hack, but necessary for E2 agent. We compile in all of RRC + * (because of CMakeLists.txt), but we don't need it (only nr_radio_config.c). + * however, if E2 agent is defined, the following functions are used in + * rrc_gNB.c, but defined in RAN functions. In order to avoid pulling this in + * here as well, only provide a prototype (and abort if they are ever called). */ +void signal_rrc_msg(void /*const nr_rrc_class_e nr_channel, const uint32_t rrc_msg_id, const byte_array_t rrc_ba*/ ) { abort(); } +void signal_rrc_state_changed_to(void /* const gNB_RRC_UE_t *rrc_ue_context, const rrc_state_e2sm_rc_e rrc_state */) { abort(); } +void signal_ue_id(void /* const gNB_RRC_UE_t *rrc_ue_context, const uint16_t class, const uint32_t msg_id */) { abort(); } + extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); } From d28ae49eee62bbfea8ea2f19691332e4d545f406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Wed, 3 Dec 2025 10:48:49 +0100 Subject: [PATCH 10/30] Fix FAPI WLS slot.indication slot ahead Current FAPI slot_ahead value for WLS is too low for UL, as we see these errors: [NR_MAC] Unexpected ULSCH HARQ PID 14 (have 3) for RNTI 0xa68e [NR_MAC] UE a68e expected HARQ pid 3 feedback at 586. 7, but is at 587.17 instead (HARQ feedback is in the past) Similarly to nFAPI, scale it by mu (for mu=1 => slot_ahead=2) to give additional time, which removes these warnings at the VNF. --- nfapi/oai_integration/nfapi_pnf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 7a6e4f7657..8b07bea297 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2315,7 +2315,7 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_resp) #ifndef ENABLE_WLS int slot_ahead = 2 << mu; #else - int slot_ahead = 1; + int slot_ahead = 1 << mu; #endif uint16_t sfn_tx = sfn; uint16_t slot_tx = slot; From 18edbc0f156244e4b149d0d19c71484f6ac3141d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 Dec 2025 12:31:53 +0100 Subject: [PATCH 11/30] Fix UL throughput counter in periodic PNF logs Function pointer send_p7_msg() returns a bool, so correctly set the type, and interpret it correspondingly. --- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index af02ef7a4e..d2006170f0 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -268,8 +268,8 @@ int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_ pnf_p7_t* _this = (pnf_p7_t*)(config); AssertFatal(_this->_public.send_p7_msg, "Function pointer must be configured|"); - int ret = _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); - if (ret == 0) { + bool ret = _this->_public.send_p7_msg(_this, (nfapi_nr_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); + if (ret) { for (int i = 0; i < ind->number_of_pdus; ++i) _this->nr_stats.ul.bytes += ind->pdu_list[i].pdu_length; } From 0e7e0309075172df2213f9f2eb925573cb35e1ca Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 15 Sep 2025 18:09:11 +0200 Subject: [PATCH 12/30] Fix clean_bwp_structures Also zero out the pointer in spCellConfigDedicated to avoid use-after-free. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a68c12092b..86735466de 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3472,9 +3472,9 @@ void clean_bwp_structures(NR_SpCellConfig_t *spCellConfig) asn_sequence_del(&rel_dl->list, i, 1); } if (rel_dl->list.count == 0) - free_and_zero(rel_dl); + free_and_zero(spCellConfigDedicated->downlinkBWP_ToReleaseList); if (add_dl->list.count == 0) - free_and_zero(add_dl); + free_and_zero(spCellConfigDedicated->downlinkBWP_ToAddModList); } if (spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList) { struct NR_UplinkConfig__uplinkBWP_ToReleaseList *rel_ul = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList; @@ -3492,9 +3492,9 @@ void clean_bwp_structures(NR_SpCellConfig_t *spCellConfig) asn_sequence_del(&rel_ul->list, i, 1); } if (rel_ul->list.count == 0) - free_and_zero(rel_ul); + free_and_zero(spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList); if (add_ul->list.count == 0) - free_and_zero(add_ul); + free_and_zero(spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList); } } From aa7d3668e32c5ed84823489634048fffccf785f2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 23 Sep 2025 11:13:25 +0200 Subject: [PATCH 13/30] Fix for segfault caused by freed csi_MeasConfig --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 6 ++++-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 8 ++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 86735466de..48768750e0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3922,7 +3922,7 @@ bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t * return false; } -void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id) +void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id) { DevAssert(UE->CellGroup != NULL); NR_CellGroupConfig_t *cellGroup_for_UE = NULL; @@ -3930,7 +3930,8 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_ AssertFatal(UE->current_DL_BWP.bwp_id == UE->current_UL_BWP.bwp_id, "We only support same BWP for UL and DL\n"); if (new_bwp_id == UE->current_DL_BWP.bwp_id) LOG_E(NR_MAC, "Source BWP ID and target BWP ID are the same, can't perform switch\n"); - else + else { + UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup, &nrmac->radio_config, UE->capability, @@ -3938,6 +3939,7 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_ UE->uid, UE->current_DL_BWP.bwp_id, new_bwp_id); + } } uint8_t buf[2048]; asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index e280a8cbe2..d5626c24df 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -478,7 +478,7 @@ void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpac void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl); bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl); -void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id); +void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id); bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c); nr_lc_config_t *nr_mac_get_lc_config(NR_UE_sched_ctrl_t* sched_ctrl, int lcid); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 3d0e3ed246..a828ec7930 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3367,10 +3367,14 @@ static NR_CSI_MeasConfig_t *get_csiMeasConfig(const NR_ServingCellConfig_t *conf pdsch_Config = configDedicated->initialDownlinkBWP->pdsch_Config; curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); } else { - NR_BWP_Downlink_t *bwp = configDedicated->downlinkBWP_ToAddModList->list.array[0]; + NR_BWP_Downlink_t *bwp = NULL; + for (int i = 0; i < configDedicated->downlinkBWP_ToAddModList->list.count; i++) { + if (bwp_id == configDedicated->downlinkBWP_ToAddModList->list.array[i]->bwp_Id) + bwp = configDedicated->downlinkBWP_ToAddModList->list.array[i]; + } + AssertFatal(bwp, "BWP ID doesn't match\n"); pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - AssertFatal(bwp_id == bwp->bwp_Id, "BWP ID doesn't match\n"); } const int pdsch_AntennaPorts = From ca041936801da51a8aece17cea8aeb448a788d4e Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 23 Sep 2025 17:36:37 +0200 Subject: [PATCH 14/30] Remove hardcoded max_rank = 1 in PUSCH configuration and set it with appropriate function --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 96 +++++++++----------- 1 file changed, 45 insertions(+), 51 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index a828ec7930..40b235e81c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1505,10 +1505,38 @@ static NR_PTRS_UplinkConfig_t *config_ulptrs(const nr_ptrs_config_t *ptrs) return ulptrs; } -static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS, +long ue_supported_ul_layers(const NR_UE_NR_Capability_t *uecap) +{ + long ul_max_layers = 1; + if (uecap + && uecap->featureSets + && uecap->featureSets->featureSetsUplinkPerCC + && uecap->featureSets->featureSetsUplinkPerCC->list.count > 0) { + NR_FeatureSetUplinkPerCC_t *ul_feature_setup_per_cc = uecap->featureSets->featureSetsUplinkPerCC->list.array[0]; + if (ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { + switch (*ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { + case NR_MIMO_LayersUL_twoLayers: + ul_max_layers = 2; + break; + case NR_MIMO_LayersUL_fourLayers: + ul_max_layers = 4; + break; + default: + ul_max_layers = 1; + } + } + } + return ul_max_layers; +} + +static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap) +{ + return min(ue_supported_ul_layers(uecap), configuration->pusch_AntennaPorts); +} + +static NR_SetupRelease_PUSCH_Config_t *config_pusch(const nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc, - const NR_UE_NR_Capability_t *uecap, - const nr_ptrs_config_t *ptrs) + const NR_UE_NR_Capability_t *uecap) { NR_SetupRelease_PUSCH_Config_t *setup_puschconfig = calloc(1, sizeof(*setup_puschconfig)); setup_puschconfig->present = NR_SetupRelease_PUSCH_Config_PR_setup; @@ -1526,8 +1554,8 @@ static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS, if (!pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup) pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - if (ptrs) { - NR_PTRS_UplinkConfig_t *ptrs_config = config_ulptrs(ptrs); + if (configuration->ptrs) { + NR_PTRS_UplinkConfig_t *ptrs_config = config_ulptrs(configuration->ptrs); NR_SetupRelease_PTRS_UplinkConfig_t *phaseTrackingRS = calloc(1, sizeof(*phaseTrackingRS)); phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup; phaseTrackingRS->choice.setup = ptrs_config; @@ -1569,7 +1597,7 @@ static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS, asn1cSeqAdd(&pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList->list, plrefRS); pusch_Config->pusch_PowerControl->pathlossReferenceRSToReleaseList = NULL; pusch_Config->pusch_PowerControl->twoPUSCH_PC_AdjustmentStates = NULL; - if (use_deltaMCS) { + if (configuration->use_deltaMCS) { if (!pusch_Config->pusch_PowerControl->deltaMCS) pusch_Config->pusch_PowerControl->deltaMCS = calloc(1, sizeof(*pusch_Config->pusch_PowerControl->deltaMCS)); *pusch_Config->pusch_PowerControl->deltaMCS = NR_PUSCH_PowerControl__deltaMCS_enabled; @@ -1582,14 +1610,14 @@ static NR_SetupRelease_PUSCH_Config_t *config_pusch(const bool use_deltaMCS, pusch_Config->resourceAllocation = NR_PUSCH_Config__resourceAllocation_resourceAllocationType1; pusch_Config->pusch_TimeDomainAllocationList = NULL; pusch_Config->pusch_AggregationFactor = NULL; - set_ul_mcs_table(uecap, scc, pusch_Config); + set_ul_mcs_table(configuration->force_UL256qam_off ? NULL : uecap, scc, pusch_Config); pusch_Config->transformPrecoder = NULL; if (!pusch_Config->codebookSubset) pusch_Config->codebookSubset = calloc(1, sizeof(*pusch_Config->codebookSubset)); *pusch_Config->codebookSubset = NR_PUSCH_Config__codebookSubset_nonCoherent; if (!pusch_Config->maxRank) pusch_Config->maxRank = calloc(1, sizeof(*pusch_Config->maxRank)); - *pusch_Config->maxRank = 1; + *pusch_Config->maxRank = set_ul_max_layers(configuration, uecap); pusch_Config->rbg_Size = NULL; pusch_Config->uci_OnPUSCH = NULL; pusch_Config->tp_pi2BPSK = NULL; @@ -1855,10 +1883,7 @@ static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop, scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing); set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, ubwp->bwp_Common->genericParameters.subcarrierSpacing); - ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration->use_deltaMCS, - scc, - configuration->force_UL256qam_off ? NULL : uecap, - configuration->ptrs); + ubwp->bwp_Dedicated->pusch_Config = config_pusch(configuration, scc, uecap); ubwp->bwp_Dedicated->srs_Config = get_config_srs(scc, NULL, @@ -3268,6 +3293,7 @@ static void fill_harq_IEs(NR_ServingCellConfig_t *scc, int num_dlharq, int num_u static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *configuration, int maxMIMO_Layers, + const NR_UE_NR_Capability_t *uecap, int id) { NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1, sizeof(*initialUplinkBWP)); @@ -3282,14 +3308,14 @@ static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellCo pucch_Config->resourceToAddModList = calloc(1, sizeof(*pucch_Config->resourceToAddModList)); pucch_Config->resourceToReleaseList = NULL; int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); - config_pucch_resset0(pucch_Config, id, curr_bwp, num_pucch2, NULL); - config_pucch_resset1(pucch_Config, id, num_pucch2, NULL); + config_pucch_resset0(pucch_Config, id, curr_bwp, num_pucch2, uecap); + config_pucch_resset1(pucch_Config, id, num_pucch2, uecap); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); - initialUplinkBWP->pusch_Config = config_pusch(configuration->use_deltaMCS, scc, NULL, configuration->ptrs); + initialUplinkBWP->pusch_Config = config_pusch(configuration, scc, uecap); // We are using do_srs = 0 here because the periodic SRS will only be enabled in update_cellGroupConfig() if do_srs == 1 - initialUplinkBWP->srs_Config = get_config_srs(scc, NULL, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0); + initialUplinkBWP->srs_Config = get_config_srs(scc, uecap, curr_bwp, id, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0); scheduling_request_config(scc, pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing); set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, genericParameters->subcarrierSpacing); @@ -3510,7 +3536,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_bwp); asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp); if (first_active_bwp == 0) { - uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, uid); + uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, NULL, uid); configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); } else { configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); @@ -3743,35 +3769,6 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, return cellGroupConfig; } -long ue_supported_ul_layers(const NR_UE_NR_Capability_t *uecap) -{ - long ul_max_layers = 1; - if (uecap - && uecap->featureSets - && uecap->featureSets->featureSetsUplinkPerCC - && uecap->featureSets->featureSetsUplinkPerCC->list.count > 0) { - NR_FeatureSetUplinkPerCC_t *ul_feature_setup_per_cc = uecap->featureSets->featureSetsUplinkPerCC->list.array[0]; - if (ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { - switch (*ul_feature_setup_per_cc->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) { - case NR_MIMO_LayersUL_twoLayers: - ul_max_layers = 2; - break; - case NR_MIMO_LayersUL_fourLayers: - ul_max_layers = 4; - break; - default: - ul_max_layers = 1; - } - } - } - return ul_max_layers; -} - -static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap) -{ - return min(ue_supported_ul_layers(uecap), configuration->pusch_AntennaPorts); -} - NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap, @@ -3821,7 +3818,7 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ configDedicated->initialDownlinkBWP = calloc_or_fail(1, sizeof(*configDedicated->initialDownlinkBWP)); if (!uplinkConfig->initialUplinkBWP) uplinkConfig->initialUplinkBWP = calloc_or_fail(1, sizeof(*uplinkConfig->initialUplinkBWP)); - uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, ul_maxMIMO_Layers, uid); + uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, ul_maxMIMO_Layers, uecap, uid); configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); } else { if (!configDedicated->downlinkBWP_ToAddModList) @@ -4059,10 +4056,7 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC ulConfig->initialUplinkBWP = initialUplinkBWP; initialUplinkBWP->pucch_Config = NULL; - initialUplinkBWP->pusch_Config = config_pusch(configuration->use_deltaMCS, - servingcellconfigcommon, - uecap, - configuration->ptrs); + initialUplinkBWP->pusch_Config = config_pusch(configuration, servingcellconfigcommon, uecap); long maxMIMO_Layers = set_ul_max_layers(configuration, uecap); int curr_bwp = NRRIV2BW(servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, From eb9ac76f4d68635fe00b90d093a57a472ead6215 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Sep 2025 09:11:04 +0200 Subject: [PATCH 15/30] Set MCS table also in initial BWP function --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 40b235e81c..91a9180ba0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3325,6 +3325,7 @@ static NR_BWP_UplinkDedicated_t *configure_initial_ul_bwp(const NR_ServingCellCo static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCellConfigCommon_t *scc, const int pdsch_AntennaPorts, uint64_t bitmap, + const NR_UE_NR_Capability_t *uecap, const nr_mac_config_t *configuration) { NR_BWP_DownlinkDedicated_t *bwp_Dedicated = calloc(1, sizeof(*bwp_Dedicated)); @@ -3356,6 +3357,11 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell bwp_Dedicated->pdcch_Config->choice.setup = pdcch_Config; bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts, configuration->ptrs); + // we might call configuration of initial BWP for BWP switch when we already have UE capabilities + set_dl_mcs_table(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing, + configuration->force_256qam_off ? NULL : uecap, + bwp_Dedicated, + scc); return bwp_Dedicated; } @@ -3537,7 +3543,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp); if (first_active_bwp == 0) { uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, maxMIMO_Layers, NULL, uid); - configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); + configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, NULL, configuration); } else { configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); NR_BWP_Downlink_t *bwp = config_downlinkBWP(scc, @@ -3819,7 +3825,7 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ if (!uplinkConfig->initialUplinkBWP) uplinkConfig->initialUplinkBWP = calloc_or_fail(1, sizeof(*uplinkConfig->initialUplinkBWP)); uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, ul_maxMIMO_Layers, uecap, uid); - configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, configuration); + configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, uecap, configuration); } else { if (!configDedicated->downlinkBWP_ToAddModList) configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); From b547dfe056720a39ea467e2bad1ef75a0166d3a8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 10 Oct 2025 11:36:17 +0200 Subject: [PATCH 16/30] apply new configuration after receiving ACK for RRCreconfiguration message --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 19 +++++++++++++++++++ .../NR_MAC_gNB/gNB_scheduler_primitives.c | 1 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 13 ++++++------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 10 +++++++--- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 7 ++++++- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 86eed9d575..34a8519bdb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -592,6 +592,19 @@ static bool allocate_dl_retransmission(gNB_MAC_INST *nr_mac, return true; } +static void ack_reconfig(gNB_MAC_INST *mac, NR_UE_info_t *UE) +{ + if (UE->reconfigSpCellConfig) { + // in case of reestablishment, the spCellConfig had to be released + // temporarily. Reapply now before doing the reconfiguration. + UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig; + // UE->reconfigSpCellConfig to be NULLed after receiving reconfiguration complete + } + NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; + configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); + UE->await_reconfig = false; +} + typedef struct UEsched_s { float coef; NR_UE_info_t * UE; @@ -866,6 +879,12 @@ static void pf_dl(gNB_MAC_INST *mac, .tda_info = tda_info, }; + sched_pdsch.action = NULL; + int srb1 = 1; + /* everything that's only 3 bytes is an ack. To be safe, use a bit more. */ + if (iterator->UE->await_reconfig && sched_ctrl->rlc_status[srb1].bytes_in_buffer > 10) + sched_pdsch.action = ack_reconfig; + // Fix me: currently, the RLC does not give us the total number of PDUs // awaiting. Therefore, for the time being, we put a fixed overhead of 12 // (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 48768750e0..00bcdded3b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3948,6 +3948,7 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, buf, sizeof(buf)); AssertFatal(enc_rval.encoded > 0, "ASN1 encoding of CellGroupConfig failed, failed type %s\n", enc_rval.failed_type->name); + UE->await_reconfig = true; du_to_cu_rrc_information_t du2cu = { .cellGroupConfig = buf, .cellGroupConfig_length = (enc_rval.encoded + 7) >> 3, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 27ecbdcbd0..7d73234350 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -393,16 +393,15 @@ int get_pucch_resourceid(NR_PUCCH_Config_t *pucch_Config, int O_uci, int pucch_r return *resource_id; } -static void handle_dl_harq(NR_UE_info_t * UE, - int8_t harq_pid, - bool success, - int harq_round_max) +static void handle_dl_harq(gNB_MAC_INST *mac, NR_UE_info_t * UE, int8_t harq_pid, bool success, int harq_round_max) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[harq_pid]; harq->feedback_slot = -1; harq->is_waiting = false; if (success) { + if (harq->sched_pdsch.action) + harq->sched_pdsch.action(mac, UE); finish_nr_dl_harq(sched_ctrl, harq_pid); } else if (harq->round >= harq_round_max - 1) { abort_nr_dl_harq(UE, harq_pid); @@ -873,7 +872,7 @@ static NR_UE_harq_t *find_harq(frame_t frame, slot_t slot, NR_UE_info_t * UE, in frame, slot); remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - handle_dl_harq(UE, pid, 0, harq_round_max); + handle_dl_harq(NULL, UE, pid, false, harq_round_max); pid = sched_ctrl->feedback_dl_harq.head; if (pid < 0) return NULL; @@ -930,7 +929,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value); nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0); bool success = harq_value == 0 && harq_confidence == 0; - handle_dl_harq(UE, pid, success, nrmac->dl_bler.harq_round_max); + handle_dl_harq(nrmac, UE, pid, success, nrmac->dl_bler.harq_round_max); if (is_ra) { bool ue_rejected = nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success); if (ue_rejected) { @@ -1009,7 +1008,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit, pid, acknack); - handle_dl_harq(UE, pid, uci_234->harq.harq_crc != 1 && acknack, nrmac->dl_bler.harq_round_max); + handle_dl_harq(nrmac, UE, pid, uci_234->harq.harq_crc != 1 && acknack, nrmac->dl_bler.harq_round_max); } free(uci_234->harq.harq_payload); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 8f98aabbee..ddec1b648e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -770,9 +770,12 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) } else if (req->reconfig_compl) { LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n"); if (UE->reconfigSpCellConfig) { - // in case of reestablishment, the spCellConfig had to be released - // temporarily. Reapply now before doing the reconfiguration. - UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig; + if (UE->await_reconfig) { + // in case of reestablishment, the spCellConfig had to be released + // temporarily. Reapply now before doing the reconfiguration. + UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig; + UE->await_reconfig = false; + } UE->reconfigSpCellConfig = NULL; for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) { nr_lc_config_t *c = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i); @@ -971,6 +974,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) * reconfiguration has succeeded (indicated by the CU) */ UE->reconfigSpCellConfig = UE->CellGroup->spCellConfig; UE->CellGroup->spCellConfig = NULL; + UE->await_reconfig = true; mac_remove_nr_ue(mac, *dl_rrc->old_gNB_DU_ue_id); pthread_mutex_unlock(&mac->sched_lock); nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index aa8b2b8644..745c7165ba 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -475,6 +475,9 @@ typedef struct NR_pdsch_dmrs { NR_PTRS_DownlinkConfig_t *phaseTrackingRS; } NR_pdsch_dmrs_t; +struct NR_UE_info; +struct gNB_MAC_INST_s; +typedef void (*feedback_action_t)(struct gNB_MAC_INST_s *mac, struct NR_UE_info *ue); typedef struct NR_sched_pdsch { /// RB allocation within active BWP uint16_t rbSize; @@ -501,6 +504,7 @@ typedef struct NR_sched_pdsch { // time_domain_allocation is the index of a list of tda int time_domain_allocation; NR_tda_info_t tda_info; + feedback_action_t action; } NR_sched_pdsch_t; typedef struct NR_UE_harq { @@ -772,7 +776,7 @@ typedef struct measgap_config { } measgap_config_t; /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ -typedef struct { +typedef struct NR_UE_info { rnti_t rnti; uid_t uid; // unique ID of this UE /// scheduling control info @@ -795,6 +799,7 @@ typedef struct { float dl_thr_ue; long pdsch_HARQ_ACK_Codebook; bool is_redcap; + bool await_reconfig; NR_RA_t *ra; } NR_UE_info_t; From 88d1964f9c964c3dba53d6b5693cf0ccf3dfaa6d Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 12 Oct 2025 10:46:01 +0200 Subject: [PATCH 17/30] Validate BWP switch Return from triggering reconfiguration with BWP switch if BWP is the same as before the switch, and add check to verify if BWP triggered by switch command exists --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 00bcdded3b..21e28dbe98 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3922,14 +3922,32 @@ bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t * return false; } +static bool verify_bwp_switch(const NR_UE_info_t *UE, const nr_mac_config_t *configuration, int new_bwp_id) +{ + if (new_bwp_id == UE->current_DL_BWP.bwp_id) { + LOG_E(NR_MAC, "Source BWP ID and target BWP ID are the same, can't perform switch\n"); + return false; + } + + if (new_bwp_id == 0) + return true; + for (int i = 0; i < configuration->num_additional_bwps; i++) { + const nr_bwp_config_t *bwp_config = &configuration->bwp_config[i]; + if (bwp_config->id == new_bwp_id) + return true; + } + LOG_E(NR_MAC, "New BWP %d does not belong to the list of configured BWPs, can't perform switch\n", new_bwp_id); + return false; +} + void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id) { DevAssert(UE->CellGroup != NULL); NR_CellGroupConfig_t *cellGroup_for_UE = NULL; if (new_bwp_id >= 0) { AssertFatal(UE->current_DL_BWP.bwp_id == UE->current_UL_BWP.bwp_id, "We only support same BWP for UL and DL\n"); - if (new_bwp_id == UE->current_DL_BWP.bwp_id) - LOG_E(NR_MAC, "Source BWP ID and target BWP ID are the same, can't perform switch\n"); + if (!verify_bwp_switch(UE, &nrmac->radio_config, new_bwp_id)) + return; else { UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup, From b2878f4ab1d4053ee1bfadd68064a60b1daf4463 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 12 Oct 2025 10:50:53 +0200 Subject: [PATCH 18/30] fix BWP start for ULSCH at UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index bd9ea09041..e566f3db9e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -586,11 +586,10 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->pusch_uci.harq_ack_bit_length = 0; + pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart; if (dci_format == NR_UL_DCI_FORMAT_0_0 && ss_type == NR_SearchSpace__searchSpaceType_PR_common) { - pusch_config_pdu->bwp_start = sc_info->initial_ul_BWPStart; pusch_config_pdu->bwp_size = sc_info->initial_ul_BWPSize; } else { - pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart; pusch_config_pdu->bwp_size = current_UL_BWP->BWPSize; } From 3e5d868018c9bf8ef9849dd65af93a01640cf47c Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 21 Oct 2025 16:48:29 +0200 Subject: [PATCH 19/30] set coresetID !=0 for dedicated BWP (needed if CSET0 doesn't fit that BWP) --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 91a9180ba0..a154335b10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1771,7 +1771,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; - ss = rrc_searchspace_config(true, searchspaceid, 0, agg_level_candidates); + ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, agg_level_candidates); } asn1cSeqAdd(&bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss); @@ -1812,7 +1812,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t verify_agg_levels(num_cces, configuration->num_agg_level_candidates, coreset2->controlResourceSetId, rrc_num_agg_level_candidates); searchspaceid = 10 + bwp->bwp_Id; - NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, is_SA ? 0 : coreset2->controlResourceSetId, agg_level_candidates); + NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, searchspaceid, coreset2->controlResourceSetId, agg_level_candidates); asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2); searchspaceid = 20 + bwp->bwp_Id; From b137478dc8b3aefdb254fd8aa438c22332636c84 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 3 Dec 2025 16:00:10 +0100 Subject: [PATCH 20/30] doc: FAPI WLS: provide information on performance optimization --- doc/nfapi.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/nfapi.md b/doc/nfapi.md index b901b15269..7ddd97e023 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -173,6 +173,26 @@ After installing WLS, you can run the build command as shown below: Refer to the above steps in [Quickstart](#quickstart), but run the PNF first as it is the WLS "master". +To optimize the performance of your setup, you can provide the option +`--thread-pool ` in the PNF command line. This allows +you to pin PNF processing threads to specific CPU cores, as they might +otherwise interfere with DPDK used by WLS. + +Before selecting which CPU cores to allocate: run `nr-softmodem` without the +`--thread-pool` option and use a process monitoring tool such as htop to check +CPU availability. Check for lightly loaded cores, and use them in the +thread-pool for the PNF. + +Example commands for running an OTA test with USRP B200 on 40MHz: + +Run PNF + + sudo NFAPI_TRACE_LEVEL=info ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf --nfapi PNF --continuous-tx -E --thread-pool 1,2,3,4,5 + +Run VNF + + sudo NFAPI_TRACE_LEVEL=info ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf --nfapi VNF + #### How to run OAI PNF with OSC/Radisys O-DU Set up the hugepages for DPDK (1GB page size, 6 pages; this only needs to be From 2230606f423fd4968cbe2769dfb4e3f433b1e6aa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 Dec 2025 16:02:47 +0100 Subject: [PATCH 21/30] doc: (n)FAPI: Correct header levels to also match transport --- doc/nfapi.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/nfapi.md b/doc/nfapi.md index 7ddd97e023..6198307220 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -1,3 +1,5 @@ +# FAPI/nFAPI split in OAI + This document describes the SmallCellForum (SCF) (n)FAPI split in 5G, i.e., between the MAC/L2 and PHY/L1. It also describes how to make use of the multiple transport mechanisms between the 2. @@ -10,7 +12,7 @@ about nFAPI can be found in SCF 225.2.0. [[_TOC_]] -# Quickstart +## Quickstart Compile OAI as normal. Start the CN and make sure that the VNF configuration matches the PLMN/IP addresses. Then, run the VNF @@ -29,7 +31,7 @@ VNF!) You should not observe a difference between nFAPI split and monolithic. -# Status +## Status All FAPI message can be transferred between VNF and PNF. This is because OAI uses FAPI with its corresponding messages internally, whether a split is in use @@ -54,7 +56,7 @@ When using RFsim, the system might run slower than in monolithic. This is because the PNF needs to slow down the execution time of a specific slot, because it has to send a Slot.indication to the VNF for scheduling. -# Configuration +## Configuration Both PNF and VNF are run through the `nr-softmodem` executable. The type of mode is switched through the `--nfapi` switch, with options `MONOLITHIC` @@ -256,7 +258,7 @@ Run the OAI-UE sudo ./nr-uesoftmodem -r 273 --numerology 1 --band 78 -C 3400140000 --ssb 1518 --uicc0.imsi 001010000000001 --rfsim -# nFAPI logging system +## nFAPI logging system nFAPI has its own logging system, independent of OAI's. It can be activated by setting the `NFAPI_TRACE_LEVEL` environment variable to an appropriate value; From 5d4e17f8ca59a2b330e0a2ad0f14a136d43e7f1a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 Dec 2025 16:16:42 +0100 Subject: [PATCH 22/30] doc: nFAPI: add Troubleshoot section and explain ra_responseWindow --- doc/nfapi.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/doc/nfapi.md b/doc/nfapi.md index 6198307220..5f2d8a35da 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -285,3 +285,26 @@ done over virtual time, i.e., frames/slots as executed by the 5G Systems. For instance, these numbers might be slightly higher or slower in RFsim than in wall-clock time, depending if the system advances faster or slower than wall-clock time. + +## Troubleshoot + +When operating using the FAPI split, the PNF needs to give the VNF extra time +to schedule the next slot. Especially since the current nFAPI split still +relies on slot indications, extra time due to transport delays need to be +accounted for. Currently, this delay is set conservatively, meaning that it +should work for most systems, but can create problems during random access: + + [NR_MAC] exceeded RA window: preamble at 411.19 now 413.0 (diff 21), ra_ResponseWindow 5/20 slots + [NR_MAC] sfn: 413.0 UE RA-RNTI 010b TC-RNTI 5d82: exceeded RA window, cannot schedule Msg2 + +means that the VNF received a preamble (411.19), but the current slot to be +scheduled (413.0) is beyond the random access response window (20 slots). In +this case, try one of the following: + +- If the radio allows, reduce the L1 TX advance `RUs.[0].sl_ahead` by some + slots, but note that this could make the system less stable. +- Change the code to reduce `sl_ahead` inside function `handle_nr_slot_ind()`, + to reduce the FAPI scheduling slot time budget. +- Non-standard: You can manually increase the response window by setting + `gNBs.[0].servingCellConfigCommon.[0].ra_ResponseWindow` to, e.g., 6. Note + that the maximum allowed response window is 10ms. From 98618a7dc8c2c9bdf7fc3d2c789f57658cbd46d1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 28 Oct 2025 10:29:14 +0100 Subject: [PATCH 23/30] The network must configure BWPs with consecutive IDs from 1 ... so if we want to have 1 BWP configured at any given time we need to reconfigure BWP 1 every time. This means that since the gNB has more than 1 BWPs (for use for different UEs), that there is a "gNB BWP ID" (as used by the gNB), which can be any BWP ID X, and one "UE BWP ID", which is always 1. This commit implements this distinction. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 1 - openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 1 - .../NR_MAC_UE/nr_ue_dci_configuration.c | 3 - openair2/LAYER2/NR_MAC_gNB/config.c | 5 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 - .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 1 - .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 3 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 109 ++++---------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 10 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 1 - openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 - .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 5 + openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 138 ++++++------------ openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 14 +- 15 files changed, 101 insertions(+), 194 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 13f2eca955..563b3f2ca2 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2781,7 +2781,6 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, nr_dci_format_t format, nr_rnti_type_t rnti_type, NR_ControlResourceSet_t *coreset, - int bwp_id, int ss_type, uint16_t cset0_bwp_size, uint16_t alt_size) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index f76f54b158..8f795452b8 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -159,7 +159,6 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, nr_dci_format_t format, nr_rnti_type_t rnti_type, NR_ControlResourceSet_t *coreset, - int bwp_id, int ss_type, uint16_t cset0_bwp_size, uint16_t alt_size); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 8a2074422e..7d630c3002 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -198,7 +198,6 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac, NR_UL_DCI_FORMAT_0_0, rnti_type, coreset, - dl_bwp_id, ss->searchSpaceType->present, mac->type0_PDCCH_CSS_config.num_rbs, 0); @@ -211,7 +210,6 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac, NR_DL_DCI_FORMAT_1_0, rnti_type, coreset, - dl_bwp_id, ss->searchSpaceType->present, mac->type0_PDCCH_CSS_config.num_rbs, 0); @@ -225,7 +223,6 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac, dci_format[i], rnti_type, coreset, - dl_bwp_id, ss->searchSpaceType->present, mac->type0_PDCCH_CSS_config.num_rbs, alt_size); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 893a94147e..8b30bf78f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -1116,8 +1116,9 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t NR_SCHED_LOCK(&nrmac->sched_lock); NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup); - DevAssert(UE->uid < MAX_MOBILES_PER_GNB); // test-mode: we assume we can always create a UE - free_and_zero(UE->ra); // test-mode (sims, phy-test): UE will not do RA + DevAssert(UE->uid < MAX_MOBILES_PER_GNB); // physical simulators: we assume we can always create a UE + free_and_zero(UE->ra); // physical simulators: UE will not do RA + UE->local_bwp_id = 1; // for physical simulators bool res = add_connected_nr_ue(nrmac, UE); if (!res) { LOG_E(NR_MAC, "Error adding UE %04x\n", rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index f8df95f679..e50358ae10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -958,7 +958,6 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, &uldci_payload, NR_UL_DCI_FORMAT_0_0, TYPE_TC_RNTI_, - ul_bwp->bwp_id, ss, coreset, 0, // parameter not needed for DCI 0_0 @@ -1385,7 +1384,6 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, &dci_payload, NR_DL_DCI_FORMAT_1_0, rnti_type, - dl_bwp->bwp_id, sched_ctrl->search_space, coreset, 0, // parameter not needed for DCI 1_0 diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 1f6fb64181..eb063b48ef 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -473,7 +473,6 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, &dci_payload, dci_format, rnti_type, - 0, search_space, coreset, 0, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 34a8519bdb..e5aa8398b4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -601,6 +601,8 @@ static void ack_reconfig(gNB_MAC_INST *mac, NR_UE_info_t *UE) // UE->reconfigSpCellConfig to be NULLed after receiving reconfiguration complete } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; + /* clean BWP structures */ + clean_bwp_structures(UE->CellGroup->spCellConfig); configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); UE->await_reconfig = false; } @@ -1210,7 +1212,6 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE &dci_payload, current_BWP->dci_format, rnti_type, - bwp_id, sched_ctrl->search_space, sched_ctrl->coreset, UE->pdsch_HARQ_ACK_Codebook, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 21e28dbe98..14dedb1de9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -907,8 +907,10 @@ dci_pdu_rel15_t prepare_dci_dl_payload(const gNB_MAC_INST *gNB_mac, dci_payload.dai[0].val = pucch ? (pucch->dai_c - 1) & 3 : 0; // bwp indicator // as per table 7.3.1.1.2-1 in 38.212 - if (dl_BWP) - dci_payload.bwp_indicator.val = UE->sc_info.n_dl_bwp < 4 ? dl_BWP->bwp_id : dl_BWP->bwp_id - 1; + if (dl_BWP) { + int ext_bwp_id = dl_BWP->bwp_id ? 1 : 0; // BWP-ID sent to the UE is always 1 except for BWP 0 + dci_payload.bwp_indicator.val = UE->sc_info.n_dl_bwp < 4 ? ext_bwp_id : ext_bwp_id - 1; + } return dci_payload; } @@ -1182,7 +1184,6 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, NR_UE_UL_BWP_t *ul_bwp, NR_SearchSpace__searchSpaceType_PR ss_type) { - int bwp_id = ul_bwp->bwp_id; nr_dci_format_t dci_format = ul_bwp->dci_format; // 3GPP TS 38.214 Section 6.1.2.2.2 Uplink resource allocation type 1 @@ -1214,7 +1215,8 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, LOG_D(NR_MAC,"Configuring DCI Format 0_1\n"); dci_pdu_rel15->dai[0].val = 0; //TODO // bwp indicator as per table 7.3.1.1.2-1 in 38.212 - dci_pdu_rel15->bwp_indicator.val = sc_info->n_ul_bwp < 4 ? bwp_id : bwp_id - 1; + int ext_bwp_id = ul_bwp->bwp_id ? 1 : 0; // BWP-ID sent to the UE is always 1 except for BWP 0 + dci_pdu_rel15->bwp_indicator.val = sc_info->n_ul_bwp < 4 ? ext_bwp_id : ext_bwp_id - 1; // SRS resource indicator if (pusch_Config && pusch_Config->txConfig != NULL) { AssertFatal(*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook, @@ -1640,7 +1642,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo, dci_pdu_rel15_t *dci_pdu_rel15, int dci_format, int rnti_type, - int bwp_id, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, long pdsch_HARQ_ACK_Codebook, @@ -1671,7 +1672,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo, NR_UL_DCI_FORMAT_0_0, rnti_type, coreset, - bwp_id, ss->searchSpaceType->present, cset0_bwp_size, 0); @@ -1685,7 +1685,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo, NR_DL_DCI_FORMAT_1_0, rnti_type, coreset, - bwp_id, ss->searchSpaceType->present, cset0_bwp_size, 0); @@ -1702,10 +1701,10 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo, dci_format, rnti_type, coreset, - bwp_id, ss->searchSpaceType->present, cset0_bwp_size, alt_size); + if (dci_size == 0) return; pdcch_dci_pdu->PayloadSizeBits = dci_size; @@ -2703,38 +2702,26 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, AssertFatal(dl_bwp_switch == ul_bwp_switch, "Different UL and DL BWP not supported\n"); DL_BWP->bwp_id = dl_bwp_switch; UL_BWP->bwp_id = ul_bwp_switch; + UE->local_bwp_id = dl_bwp_switch; // assuming they are the same } else { - // (re)configuring BWP - // TODO BWP switching not via RRC reconfiguration - // via RRC if firstActiveXlinkBWP_Id is NULL, MAC stays on the same BWP as before - if (servingCellConfig->firstActiveDownlinkBWP_Id) - DL_BWP->bwp_id = *servingCellConfig->firstActiveDownlinkBWP_Id; - if (servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id) - UL_BWP->bwp_id = *servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id; + DL_BWP->bwp_id = UE->local_bwp_id; + UL_BWP->bwp_id = UE->local_bwp_id; } const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList; if(bwpList) - sc_info->n_dl_bwp = bwpList->list.count; - if (DL_BWP->bwp_id>0) { - for (int i=0; ilist.count; i++) { - dl_bwp = bwpList->list.array[i]; - if(dl_bwp->bwp_Id == DL_BWP->bwp_id) - break; - } - AssertFatal(dl_bwp!=NULL,"Couldn't find DLBWP corresponding to BWP ID %ld\n",DL_BWP->bwp_id); + sc_info->n_dl_bwp = 1; + if (DL_BWP->bwp_id > 0) { + dl_bwp = bwpList->list.array[0]; + AssertFatal(dl_bwp, "Couldn't find DLBWP corresponding to BWP ID %ld\n", DL_BWP->bwp_id); } const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList; if(ubwpList) - sc_info->n_ul_bwp = ubwpList->list.count; - if (UL_BWP->bwp_id>0) { - for (int i=0; ilist.count; i++) { - ul_bwp = ubwpList->list.array[i]; - if(ul_bwp->bwp_Id == UL_BWP->bwp_id) - break; - } - AssertFatal(ul_bwp!=NULL,"Couldn't find ULBWP corresponding to BWP ID %ld\n",UL_BWP->bwp_id); + sc_info->n_ul_bwp = 1; + if (UL_BWP->bwp_id > 0) { + ul_bwp = ubwpList->list.array[0]; + AssertFatal(ul_bwp, "Couldn't find ULBWP corresponding to BWP ID %ld\n", UL_BWP->bwp_id); } // selection of dedicated BWPs @@ -2762,12 +2749,12 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, } // TDA lists - if (DL_BWP->bwp_id>0) + if (DL_BWP->bwp_id > 0) DL_BWP->tdaList_Common = dl_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; else DL_BWP->tdaList_Common = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; - if(UL_BWP->bwp_id>0) + if(UL_BWP->bwp_id > 0) UL_BWP->tdaList_Common = ul_bwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; else UL_BWP->tdaList_Common = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; @@ -3217,9 +3204,10 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt NR_NZP_CSI_RS_ResourceSetId_t *nzp = NULL; for (int csi_list=0; csi_listcsi_ResourceConfigToAddModList->list.count; csi_list++) { NR_CSI_ResourceConfig_t *csires = csi_measconfig->csi_ResourceConfigToAddModList->list.array[csi_list]; - if(csires->bwp_Id == dl_bwp->bwp_id && - csires->csi_RS_ResourceSetList.present == NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB && - csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList) { + if (csires->bwp_Id > 1) + LOG_E(NR_MAC, "Invalid CSI resource BWP ID %ld, we only configure BWP up to 1\n", csires->bwp_Id); + else if (csires->csi_RS_ResourceSetList.present == NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB && + csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList) { nzp = csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0]; } } @@ -3456,46 +3444,11 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot void clean_bwp_structures(NR_SpCellConfig_t *spCellConfig) { NR_ServingCellConfig_t *spCellConfigDedicated = spCellConfig->spCellConfigDedicated; - if (spCellConfigDedicated->downlinkBWP_ToReleaseList) { - struct NR_ServingCellConfig__downlinkBWP_ToReleaseList *rel_dl = spCellConfigDedicated->downlinkBWP_ToReleaseList; - struct NR_ServingCellConfig__downlinkBWP_ToAddModList *add_dl = spCellConfigDedicated->downlinkBWP_ToAddModList; - int num_rel = rel_dl->list.count; - int num_add = add_dl->list.count; - for (int i = 0; i < num_rel; i++) { - NR_BWP_Id_t *rel_id = rel_dl->list.array[i]; - for (int j = 0; j < num_add; j++) { - NR_BWP_Downlink_t *dl_bwp = add_dl->list.array[j]; - if (*rel_id == dl_bwp->bwp_Id) { - asn_sequence_del(&add_dl->list, j, 1); - } - } - asn_sequence_del(&rel_dl->list, i, 1); - } - if (rel_dl->list.count == 0) - free_and_zero(spCellConfigDedicated->downlinkBWP_ToReleaseList); - if (add_dl->list.count == 0) - free_and_zero(spCellConfigDedicated->downlinkBWP_ToAddModList); - } - if (spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList) { - struct NR_UplinkConfig__uplinkBWP_ToReleaseList *rel_ul = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList; - struct NR_UplinkConfig__uplinkBWP_ToAddModList *add_ul = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList; - int num_rel = rel_ul->list.count; - int num_add = add_ul->list.count; - for (int i = 0; i < num_rel; i++) { - NR_BWP_Id_t *rel_id = rel_ul->list.array[i]; - for (int j = 0; j < num_add; j++) { - NR_BWP_Uplink_t *ul_bwp = add_ul->list.array[j]; - if (*rel_id == ul_bwp->bwp_Id) { - asn_sequence_del(&add_ul->list, j, 1); - } - } - asn_sequence_del(&rel_ul->list, i, 1); - } - if (rel_ul->list.count == 0) - free_and_zero(spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList); - if (add_ul->list.count == 0) - free_and_zero(spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList); - } + if (spCellConfigDedicated->downlinkBWP_ToAddModList && spCellConfigDedicated->downlinkBWP_ToAddModList->list.count > 1) + asn_sequence_del(&spCellConfigDedicated->downlinkBWP_ToAddModList->list, 0, 1); + if (spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList + && spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count > 1) + asn_sequence_del(&spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list, 0, 1); } void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) @@ -3517,8 +3470,6 @@ void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) /* remove reestablishRLC, we don't need it anymore */ for (int i = 0; i < cell_group->rlc_BearerToAddModList->list.count; ++i) free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC); - /* clean BWP structures */ - clean_bwp_structures(spCellConfig); } int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs) @@ -3818,6 +3769,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, &mac->radio_config, &mac->rlc_config); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = cellGroupConfig; + UE->local_bwp_id = mac->radio_config.first_active_bwp; if (!cellGroupConfig) return true; @@ -3950,6 +3902,7 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, return; else { UE->sc_info.csi_MeasConfig = NULL; // to avoid segfault when freeing csi_MeasConfig in configDedicated + UE->local_bwp_id = new_bwp_id; cellGroup_for_UE = update_cellGroupConfig_for_BWP_switch(UE->CellGroup, &nrmac->radio_config, UE->capability, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 7d73234350..eb32fde2e6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -253,9 +253,10 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot) "Only periodic CSI reporting is implemented currently\n"); const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; - if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id) + if(pucchcsires->uplinkBandwidthPartId > 1) { + LOG_E(NR_MAC, "Invalid PUCCH BWP ID %ld, we only configure BWP up to 1\n", pucchcsires->uplinkBandwidthPartId); continue; - + } // we schedule CSI reporting max_fb_time slots in advance int period, offset; csi_period_offset(csirep, NULL, &period, &offset); @@ -748,7 +749,6 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR reportQuantity_type_r16 = NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_NOTHING; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; const int n_slots_frame = nrmac->frame_structure.numb_slots_frame; int cumul_bits = 0; @@ -763,8 +763,10 @@ static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_CSI_ReportConfig_t *csirep = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; uint8_t cqi_table = (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_1 && csirep->cqi_Table) ? *csirep->cqi_Table : NR_CSI_ReportConfig__cqi_Table_table1; const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; - if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id) + if(pucchcsires->uplinkBandwidthPartId > 1) { + LOG_E(NR_MAC, "Invalid PUCCH BWP ID %ld, we only configure BWP up to 1\n", pucchcsires->uplinkBandwidthPartId); continue; + } int period, offset; csi_period_offset(csirep, NULL, &period, &offset); // verify if report with current id has been scheduled for this frame and slot diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 9904067aa5..3faeee66b2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2606,7 +2606,6 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE &uldci_payload, current_BWP->dci_format, TYPE_C_RNTI_, - current_BWP->bwp_id, ss, coreset, UE->pdsch_HARQ_ACK_Codebook, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index d5626c24df..af0d102212 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -258,7 +258,6 @@ void fill_dci_pdu_rel15(const NR_UE_ServingCell_Info_t *servingCellInfo, dci_pdu_rel15_t *dci_pdu_rel15, int dci_format, int rnti_type, - int bwp_id, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, long pdsch_HARQ_ACK_Codebook, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index ddec1b648e..6d105078b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -576,6 +576,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc, mac->frame); // TODO: in NSA we assign capabilities here, otherwise outside => not logic UE->capability = cap; + UE->local_bwp_id = 1; // get_default_secondaryCellGroup sets 1st active BWP as 1 } // note: we don't pass the cellGroupConfig to add_new_nr_ue() because we need // the uid to create the CellGroupConfig (which is in the UE context created diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 745c7165ba..1a4ea9f3af 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -801,6 +801,11 @@ typedef struct NR_UE_info { bool is_redcap; bool await_reconfig; NR_RA_t *ra; + // 3GPP mandates that BWPs are enumerated consecutively, but we only send one (dedicated) + // BWP to the UE (and modify that BWP on reconfiguration); consequently, the BWP ID for a + // dedicated BWP is always 1 from the UE's point of view, even if the gNB has multiple BWPs. + // The below ID is the "true" (non-consecutive) BWP ID from the gNB's point of view + NR_BWP_Id_t local_bwp_id; } NR_UE_info_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index a154335b10..3cd448b216 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1724,20 +1724,18 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t const NR_UE_NR_Capability_t *uecap, int dl_antenna_ports, bool force_256qam_off, - int bwp_loop, bool is_SA, const nr_mac_config_t *configuration) { NR_BWP_Downlink_t *bwp = calloc_or_fail(1, sizeof(*bwp)); + bwp->bwp_Id = 1; bwp->bwp_Common = calloc(1,sizeof(*bwp->bwp_Common)); - if(configuration->num_additional_bwps > 0) { - const nr_bwp_config_t *bwp_config = &configuration->bwp_config[bwp_loop]; - bwp->bwp_Id = bwp_config->id; + if(configuration->num_additional_bwps > 0 && configuration->first_active_bwp > 0) { + const nr_bwp_config_t *bwp_config = &configuration->bwp_config[configuration->first_active_bwp - 1]; bwp->bwp_Common->genericParameters.locationAndBandwidth = bwp_config->location_and_bw; bwp->bwp_Common->genericParameters.subcarrierSpacing = bwp_config->scs; bwp->bwp_Common->genericParameters.cyclicPrefix = NULL; } else { - bwp->bwp_Id=bwp_loop+1; bwp->bwp_Common->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,0); bwp->bwp_Common->genericParameters.subcarrierSpacing = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing; bwp->bwp_Common->genericParameters.cyclicPrefix = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.cyclicPrefix; @@ -1830,8 +1828,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t return bwp; } -static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop, - bool is_SA, +static NR_BWP_Uplink_t *config_uplinkBWP(bool is_SA, int uid, int maxMIMO_Layers, const nr_mac_config_t *configuration, @@ -1839,14 +1836,14 @@ static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop, const NR_UE_NR_Capability_t *uecap) { NR_BWP_Uplink_t *ubwp = calloc_or_fail(1, sizeof(*ubwp)); + ubwp->bwp_Id = 1; ubwp->bwp_Common = calloc(1, sizeof(*ubwp->bwp_Common)); - if(configuration->num_additional_bwps > 0) { - ubwp->bwp_Id = configuration->bwp_config[bwp_loop].id; - ubwp->bwp_Common->genericParameters.locationAndBandwidth = configuration->bwp_config[bwp_loop].location_and_bw; - ubwp->bwp_Common->genericParameters.subcarrierSpacing = configuration->bwp_config[bwp_loop].scs; + if(configuration->num_additional_bwps > 0 && configuration->first_active_bwp > 0) { + int bwp_idx = configuration->first_active_bwp - 1; + ubwp->bwp_Common->genericParameters.locationAndBandwidth = configuration->bwp_config[bwp_idx].location_and_bw; + ubwp->bwp_Common->genericParameters.subcarrierSpacing = configuration->bwp_config[bwp_idx].scs; ubwp->bwp_Common->genericParameters.cyclicPrefix = NULL; } else { - ubwp->bwp_Id=bwp_loop+1; ubwp->bwp_Common->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,0); ubwp->bwp_Common->genericParameters.subcarrierSpacing = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; ubwp->bwp_Common->genericParameters.cyclicPrefix = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.cyclicPrefix; @@ -1889,7 +1886,7 @@ static NR_BWP_Uplink_t *config_uplinkBWP(long bwp_loop, NULL, curr_bwp, uid, - bwp_loop + 1, + ubwp->bwp_Id, maxMIMO_Layers, configuration->minRXTXTIME, configuration->do_SRS); @@ -3537,7 +3534,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, uint64_t bitmap = get_ssb_bitmap(scc); int first_active_bwp = 0; if (configuration->num_additional_bwps > 0) - first_active_bwp = configuration->first_active_bwp; + first_active_bwp = configuration->first_active_bwp > 0 ? 1 : 0; asn1cCallocOne(configDedicated->firstActiveDownlinkBWP_Id, first_active_bwp); asn1cCallocOne(uplinkConfig->firstActiveUplinkBWP_Id, first_active_bwp); @@ -3550,12 +3547,11 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, NULL, 0, false, - first_active_bwp - 1, true, configuration); asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); uplinkConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList)); - NR_BWP_Uplink_t *ubwp = config_uplinkBWP(first_active_bwp - 1, true, uid, maxMIMO_Layers, configuration, scc, NULL); + NR_BWP_Uplink_t *ubwp = config_uplinkBWP(true, uid, maxMIMO_Layers, configuration, scc, NULL); asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ubwp); } @@ -3775,46 +3771,22 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, return cellGroupConfig; } -NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, - const nr_mac_config_t *configuration, - const NR_UE_NR_Capability_t *uecap, - const NR_ServingCellConfigCommon_t *scc, - int uid, - int old_bwp, - int new_bwp) +NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, + const nr_mac_config_t *configuration, + const NR_UE_NR_Capability_t *uecap, + const NR_ServingCellConfigCommon_t *scc, + int uid, + int old_bwp, + int new_bwp) { NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig; NR_ServingCellConfig_t *configDedicated = spCellConfig->spCellConfigDedicated; - *configDedicated->firstActiveDownlinkBWP_Id = new_bwp; + *configDedicated->firstActiveDownlinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0 NR_UplinkConfig_t *uplinkConfig = configDedicated->uplinkConfig; - *uplinkConfig->firstActiveUplinkBWP_Id = new_bwp; + *uplinkConfig->firstActiveUplinkBWP_Id = new_bwp != 0; // 1 for any BWP != 0 + nr_mac_config_t local_config = *configuration; long ul_maxMIMO_Layers = set_ul_max_layers(configuration, uecap); - - // release old BWP - struct NR_ServingCellConfig__downlinkBWP_ToAddModList *dl_BWP_list = configDedicated->downlinkBWP_ToAddModList; - struct NR_UplinkConfig__uplinkBWP_ToAddModList *ul_BWP_list = uplinkConfig->uplinkBWP_ToAddModList; - if (old_bwp > 0) { // we need to remove old BWP only if it is not the initial - AssertFatal(dl_BWP_list, "Source BWP %d should be present in the list\n", old_bwp); - AssertFatal(ul_BWP_list, "Source BWP %d should be present in the list\n", old_bwp); - NR_BWP_Id_t id = dl_BWP_list->list.array[0]->bwp_Id; - if (!configDedicated->downlinkBWP_ToReleaseList) - configDedicated->downlinkBWP_ToReleaseList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToReleaseList)); - asn1cSequenceAdd(configDedicated->downlinkBWP_ToReleaseList->list, NR_BWP_Id_t, rel_id); - *rel_id = id; - AssertFatal(configDedicated->downlinkBWP_ToReleaseList->list.count == 1, - "logic error: there shouldn't be more than 1 BWP to release, but downlinkBWP_ToReleaseList has %d\n", - configDedicated->downlinkBWP_ToReleaseList->list.count); - - id = ul_BWP_list->list.array[0]->bwp_Id; - if (!uplinkConfig->uplinkBWP_ToReleaseList) - uplinkConfig->uplinkBWP_ToReleaseList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToReleaseList)); - asn1cSequenceAdd(uplinkConfig->uplinkBWP_ToReleaseList->list, NR_BWP_Id_t, ul_rel_id); - *ul_rel_id = id; - AssertFatal(uplinkConfig->uplinkBWP_ToReleaseList->list.count == 1, - "logic error: there shouldn't be more than 1 BWP to release, but uplinkBWP_ToReleaseList has %d\n", - uplinkConfig->uplinkBWP_ToReleaseList->list.count); - } - + local_config.first_active_bwp = new_bwp; uint64_t bitmap = get_ssb_bitmap(scc); const int pdsch_AntennaPorts = configuration->pdsch_AntennaPorts.N1 * configuration->pdsch_AntennaPorts.N2 * configuration->pdsch_AntennaPorts.XP; @@ -3824,23 +3796,22 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ configDedicated->initialDownlinkBWP = calloc_or_fail(1, sizeof(*configDedicated->initialDownlinkBWP)); if (!uplinkConfig->initialUplinkBWP) uplinkConfig->initialUplinkBWP = calloc_or_fail(1, sizeof(*uplinkConfig->initialUplinkBWP)); - uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, configuration, ul_maxMIMO_Layers, uecap, uid); - configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, uecap, configuration); + uplinkConfig->initialUplinkBWP = configure_initial_ul_bwp(scc, &local_config, ul_maxMIMO_Layers, uecap, uid); + configDedicated->initialDownlinkBWP = configure_initial_dl_bwp(scc, pdsch_AntennaPorts, bitmap, uecap, &local_config); } else { if (!configDedicated->downlinkBWP_ToAddModList) configDedicated->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); NR_BWP_Downlink_t *dl_bwp = config_downlinkBWP(scc, uecap, pdsch_AntennaPorts, - configuration->force_256qam_off, - new_bwp - 1, + local_config.force_256qam_off, true, - configuration); + &local_config); asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, dl_bwp); if (!uplinkConfig->uplinkBWP_ToAddModList) uplinkConfig->uplinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*uplinkConfig->uplinkBWP_ToAddModList)); - NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(new_bwp - 1, true, uid, ul_maxMIMO_Layers, configuration, scc, uecap); + NR_BWP_Uplink_t *ul_bwp = config_uplinkBWP(true, uid, ul_maxMIMO_Layers, &local_config, scc, uecap); asn1cSeqAdd(&uplinkConfig->uplinkBWP_ToAddModList->list, ul_bwp); } @@ -3848,9 +3819,9 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ configDedicated->csi_MeasConfig->choice.setup = get_csiMeasConfig(configDedicated, uecap, scc, - configuration, + &local_config, uid, - new_bwp, + *uplinkConfig->firstActiveUplinkBWP_Id, bitmap); // we temporarily need to keep both the old and the new BWP in the CG used by the gNB @@ -4077,44 +4048,27 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC configuration->do_SRS); // Downlink BWPs - int n_dl_bwp = 1; int firstActiveDownlinkBWP_Id = 1; - if (configuration->num_additional_bwps > 0) { - n_dl_bwp = configuration->num_additional_bwps; - firstActiveDownlinkBWP_Id = configuration->first_active_bwp; - } configDedicated->downlinkBWP_ToAddModList = calloc(1, sizeof(*configDedicated->downlinkBWP_ToAddModList)); - for (int bwp_loop = 0; bwp_loop < n_dl_bwp; bwp_loop++) { - NR_BWP_Downlink_t *bwp = config_downlinkBWP(servingcellconfigcommon, - uecap, - dl_antenna_ports, - configuration->force_256qam_off, - bwp_loop, - false, - configuration); - asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); - configDedicated->firstActiveDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->firstActiveDownlinkBWP_Id)); - *configDedicated->firstActiveDownlinkBWP_Id = firstActiveDownlinkBWP_Id; - configDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->defaultDownlinkBWP_Id)); - *configDedicated->defaultDownlinkBWP_Id = 1; - } + NR_BWP_Downlink_t *bwp = config_downlinkBWP(servingcellconfigcommon, + uecap, + dl_antenna_ports, + configuration->force_256qam_off, + false, + configuration); + asn1cSeqAdd(&configDedicated->downlinkBWP_ToAddModList->list, bwp); + configDedicated->firstActiveDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->firstActiveDownlinkBWP_Id)); + *configDedicated->firstActiveDownlinkBWP_Id = firstActiveDownlinkBWP_Id; + configDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*configDedicated->defaultDownlinkBWP_Id)); + *configDedicated->defaultDownlinkBWP_Id = 1; // Uplink BWPs - int n_ul_bwp = 1; int firstActiveUplinkBWP_Id = 1; - if (configuration->num_additional_bwps > 0) { - n_ul_bwp = configuration->num_additional_bwps; - firstActiveUplinkBWP_Id = configuration->first_active_bwp; - } - if (n_ul_bwp > 0) { - ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList)); - for (int bwp_loop = 0; bwp_loop < n_ul_bwp; bwp_loop++) { - NR_BWP_Uplink_t *ubwp = config_uplinkBWP(bwp_loop, false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap); - asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp); - } - ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id)); - *ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id; - } + ulConfig->uplinkBWP_ToAddModList = calloc(1, sizeof(*ulConfig->uplinkBWP_ToAddModList)); + NR_BWP_Uplink_t *ubwp = config_uplinkBWP(false, uid, maxMIMO_Layers, configuration, servingcellconfigcommon, uecap); + asn1cSeqAdd(&ulConfig->uplinkBWP_ToAddModList->list, ubwp); + ulConfig->firstActiveUplinkBWP_Id = calloc(1, sizeof(*ulConfig->firstActiveUplinkBWP_Id)); + *ulConfig->firstActiveUplinkBWP_Id = firstActiveUplinkBWP_Id; configDedicated->bwp_InactivityTimer = NULL; configDedicated->downlinkBWP_ToReleaseList = NULL; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 270aed4b71..b776d667d6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -124,13 +124,13 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, NR_RLC_Config_PR rlc_conf, long priority, const nr_rlc_configuration_t *default_rlc_config); -NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, - const nr_mac_config_t *configuration, - const NR_UE_NR_Capability_t *uecap, - const NR_ServingCellConfigCommon_t *scc, - int uid, - int old_bwp, - int new_bwp); +NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, + const nr_mac_config_t *configuration, + const NR_UE_NR_Capability_t *uecap, + const NR_ServingCellConfigCommon_t *scc, + int uid, + int old_bwp, + int new_bwp); NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len); measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime); int encode_measgap_config(const measgap_config_t *c, uint8_t *buf); From ca0cc079a6307d20d96c6c1dda00c1a88c26a7a2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 24 Nov 2025 15:49:40 +0100 Subject: [PATCH 24/30] avoid having negative BWP size if BWP start > BWP size --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 7 ++++--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index e5aa8398b4..d5c1048ad6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -398,7 +398,8 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) // except for the case when DCI format 1_0 is decoded in any common search space in which case the size of CORESET 0 shall be // used if CORESET 0 is configured for the cell and the size of initial DL bandwidth part shall be used if CORESET 0 is not // configured for the cell. - if (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0 && sched_ctrl->search_space->searchSpaceType + if (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0 + && sched_ctrl->search_space->searchSpaceType && sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) { if (sched_ctrl->coreset->controlResourceSetId == 0) { bwp_info.bwpStart = nr_mac->cset0_bwp_start; @@ -406,9 +407,9 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) bwp_info.bwpStart = dl_bwp->BWPStart + sched_ctrl->sched_pdcch.rb_start; } if (nr_mac->cset0_bwp_size > 0) { - bwp_info.bwpSize = min(dl_bwp->BWPSize - bwp_info.bwpStart, nr_mac->cset0_bwp_size); + bwp_info.bwpSize = min(dl_bwp->BWPSize, nr_mac->cset0_bwp_size); } else { - bwp_info.bwpSize = min(dl_bwp->BWPSize - bwp_info.bwpStart, UE->sc_info.initial_dl_BWPSize); + bwp_info.bwpSize = min(dl_bwp->BWPSize, UE->sc_info.initial_dl_BWPSize); } } else { bwp_info.bwpSize = dl_bwp->BWPSize; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 3faeee66b2..f72c1c88ee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -163,7 +163,8 @@ bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) // contiguously allocated non-interleaved virtual resource blocks within the active bandwidth part of size PRBs except for the // case when DCI format 0_0 is decoded in any common search space in which case the size of the initial UL bandwidth part shall // be used. - if (ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_0 && sched_ctrl->search_space->searchSpaceType + if (ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_0 + && sched_ctrl->search_space->searchSpaceType && sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) { bwp_info.bwpSize = min(ul_bwp->BWPSize, UE->sc_info.initial_ul_BWPSize); } else { From 805c968b594d83095e733678495971bdf7ea2cde Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 27 Nov 2025 15:16:46 +0100 Subject: [PATCH 25/30] Add a check for BWP start and size validity in configuration --- openair2/GNB_APP/gnb_config.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 081ce8607f..1f641fc6d9 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1368,7 +1368,7 @@ void nfapi_stop_l1() } } -static void get_bwp_config(nr_mac_config_t *configuration) +static void get_bwp_config(nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc) { char path[MAX_OPTNAME_SIZE * 2 + 8]; snprintf(path, sizeof(path), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); @@ -1377,10 +1377,13 @@ static void get_bwp_config(nr_mac_config_t *configuration) AssertFatal(configuration->num_additional_bwps >= 0 && configuration->num_additional_bwps <= 4, "Invalid number of additional BWPs %d\n", configuration->num_additional_bwps); + int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; for (int i = 0; i < configuration->num_additional_bwps; i++) { configuration->bwp_config[i].id = i + 1; int bwp_start = *BWPParamList.paramarray[i][GNB_BWP_START_IDX].iptr; + AssertFatal(bwp_start >= 0 && bwp_start < bw, "Invalid BWP start value %d\n", bwp_start); int bwp_size = *BWPParamList.paramarray[i][GNB_BWP_SIZE_IDX].iptr; + AssertFatal(bwp_start + bwp_size <= bw, "BWP start %d and BWP size %d exceeds full BW %d\n", bwp_start, bwp_size, bw); configuration->bwp_config[i].location_and_bw = PRBalloc_to_locationandbandwidth(bwp_size, bwp_start); configuration->bwp_config[i].scs = *BWPParamList.paramarray[i][GNB_BWP_SCS_IDX].iptr; LOG_I(GNB_APP, @@ -1418,12 +1421,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) config.pdsch_AntennaPorts.XP, config.pusch_AntennaPorts); - // BWP - get_bwp_config(&config); - AssertFatal(config.num_additional_bwps <= 4, "Impossible to configure more than 4 additional BWPs\n"); - config.first_active_bwp = *GNBParamList.paramarray[0][GNB_1ST_ACTIVE_BWP_IDX].iptr; - AssertFatal(config.first_active_bwp <= config.num_additional_bwps, "1st active BWP does not belog to the configured BWPs\n"); - // RU GET_PARAMS_LIST(RUParamList, RUParams, RUPARAMS_DESC, CONFIG_STRING_RU_LIST, NULL); int num_tx = 0; @@ -1524,7 +1521,11 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) config.num_agg_level_candidates[PDCCH_AGG_LEVEL16]); NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME, config.do_SRS); - //xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc); + // BWP + get_bwp_config(&config, scc); + AssertFatal(config.num_additional_bwps <= 4, "Impossible to configure more than 4 additional BWPs\n"); + config.first_active_bwp = *GNBParamList.paramarray[0][GNB_1ST_ACTIVE_BWP_IDX].iptr; + AssertFatal(config.first_active_bwp <= config.num_additional_bwps, "1st active BWP does not belog to the configured BWPs\n"); if (MacRLC_ParamList.numelt > 0) { /* NR RLC config is needed by mac_top_init_gNB() */ From 5c3c374c1bc9b8b69a9085cb9a032b4d12094163 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Oct 2025 14:44:36 +0200 Subject: [PATCH 26/30] Add implementation to trigger BWP switch from external source --- openair2/LAYER2/NR_MAC_gNB/config.c | 18 ++++++++++++++++++ openair2/LAYER2/NR_MAC_gNB/mac_config.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 8b30bf78f0..35b6fa509a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -1065,6 +1065,24 @@ bool nr_update_sib19(const gnb_sat_position_update_t *sat_position) return true; } +bool nr_trigger_bwp_switch(uint16_t rnti, int bwp_id) +{ + gNB_MAC_INST *nrmac = RC.nrmac[0]; + NR_SCHED_LOCK(&nrmac->sched_lock); + NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, rnti); + bool success = false; + if (!UE) { + LOG_W(NR_MAC, "could not find UE for RNTI %04x\n", rnti); + } else if (UE->current_DL_BWP.bwp_id == bwp_id) { + LOG_W(NR_MAC, "UE %04x is already on BWP ID %d, not triggering reconfiguration\n", rnti, bwp_id); + } else { // UE != NULL && current_DL_BWP.bwp_id != bwp_id + nr_mac_trigger_reconfiguration(nrmac, UE, bwp_id); + success = true; + } + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return success; +} + void prepare_du_configuration_update(gNB_MAC_INST *mac, f1ap_served_cell_info_t *info, NR_BCCH_BCH_Message_t *mib, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_config.h b/openair2/LAYER2/NR_MAC_gNB/mac_config.h index 1fdbe62115..6089d39975 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_config.h @@ -43,4 +43,6 @@ typedef struct gnb_sat_position_update_s { bool nr_update_sib19(const gnb_sat_position_update_t *sat_position); +bool nr_trigger_bwp_switch(uint16_t rnti, int bwp_id); + #endif /*__LAYER2_NR_MAC_CONFIG_H__*/ From 8d2478662d7e129c11996b02ea77083bea978e5b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Oct 2025 14:44:53 +0200 Subject: [PATCH 27/30] Add BWP switch test in CI Trigger various BWP switches through telnet, and test traffic after each switch. --- .../gnb-du.sa.band78.106prb.usrpb200.conf | 6 +- .../container_sa_e1_b200_quectel.xml | 125 ++++++++++++------ common/utils/telnetsrv/telnetsrv_ci.c | 22 +++ 3 files changed, 110 insertions(+), 43 deletions(-) diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 4daf7c62fd..58ba62696a 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -146,7 +146,11 @@ gNBs = ); first_active_bwp = 1; - bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;}); + bwp_list = ( + { scs = 1; bwpStart = 0; bwpSize = 106;}, + { scs = 1; bwpStart = 0; bwpSize = 36;}, + { scs = 1; bwpStart = 36; bwpSize = 70;} + ); # ------- SCTP definitions SCTP : diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml index 89a5ebfd6c..836143431a 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -30,20 +30,28 @@ 310000 800813 330101 - 330102 - 330103 310001 400001 350000 - 370001 - 370000 - 370002 370003 370004 + 370002 360001 100002 360002 350000 + 410002 + 370012 + 400002 + 410003 + 370013 + 400003 + 410000 + 350000 + 400000 + 410001 + 350000 + 400001 310011 310002 330201 @@ -88,24 +96,10 @@ Deploy_Object - Deploy gNB-CU-CP in a container + Deploy gNB-CU-CP/gNB-CU-UP/gNB-DU (TDD/n76/40MHz/B200) ofqot ci-scripts/yaml_files/sa_e1_b200_gnb - gnb_cucp - - - Deploy_Object - Deploy gNB-CU-UP in a container - ofqot - ci-scripts/yaml_files/sa_e1_b200_gnb - gnb_cuup - - - Deploy_Object - Deploy gNB-DU (TDD/Band78/40MHz/B200) in a container - ofqot - ci-scripts/yaml_files/sa_e1_b200_gnb - gnb_du_tdd + gnb_cucp gnb_cuup gnb_du_tdd @@ -132,16 +126,6 @@ 25 - - Iperf - iperf (DL/80Mbps/UDP)(30 sec) - -u -b 80M -t 30 -R - idefix - sabox-nepes - 10 - 95 - - Custom_Command Check UE is on dedicated BWP ID 1 @@ -149,19 +133,76 @@ echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 1 (dedicated) UL BWP ID 1 (dedicated)' - + + Custom_Command + Switch to dedicated BWP ID 1 + ofqot + echo ci trigger_bwp_switch 1 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 1 for UE' + + + + Custom_Command + Check UE is on initial BWP ID 0 + ofqot + echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 0 (initial) UL BWP ID 0 (initial)' + + + + Custom_Command + Switch to dedicated BWP ID 2 + ofqot + echo ci trigger_bwp_switch 2 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 2 for UE' + + + Iperf - iperf (UL/8Mbps/UDP)(30 sec) - -u -b 8M -t 30 + iperf (DL/TCP)(10 sec)(single-ue profile) + -t 10 -R idefix sabox-nepes - 1 - 95 + 35 + + + + Custom_Command + Check UE is on dedicated BWP ID 2 + ofqot + echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 2 (dedicated) UL BWP ID 2 (dedicated)' + + + + Custom_Command + Switch to dedicated BWP ID 3 + ofqot + echo ci trigger_bwp_switch 3 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 3 for UE' + + + + Iperf + iperf (DL/TCP)(10 sec)(single-ue profile) + -t 10 -R + idefix + sabox-nepes + 85 + + + + Custom_Command + Check UE is on dedicated BWP ID 3 + ofqot + echo ci get_current_bwp | nc -N 127.0.0.1 9091 | grep 'DL BWP ID 3 (dedicated) UL BWP ID 3 (dedicated)' + + + + Custom_Command + Switch to initial BWP ID 0 + ofqot + echo ci trigger_bwp_switch 0 | nc -N 127.0.0.1 9091 | grep 'triggered BWP switch to BWP ID 0 for UE' Iperf - iperf (BIDIR TCP)(10 sec)(single-ue profile) + iperf (BIDIR TCP)(20 sec)(single-ue profile) -t 20 --bidir idefix sabox-nepes @@ -169,17 +210,17 @@ Iperf - iperf (DL/TCP)(30 sec)(single-ue profile) - -t 30 -R + iperf (DL/TCP)(20 sec)(single-ue profile) + -t 20 -R idefix sabox-nepes - 30 + 140 Iperf - iperf (UL/TCP)(30 sec)(single-ue profile) - -t 30 + iperf (UL/TCP)(20 sec)(single-ue profile) + -t 20 idefix sabox-nepes 15 diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 8b00d529c5..11c8ce5dc1 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -38,6 +38,7 @@ #include "openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_config.h" #include "openair2/RRC/NR/rrc_gNB_mobility.h" #include "openair3/NGAP/ngap_gNB_ue_context.h" @@ -276,6 +277,8 @@ static int get_current_bwp(char *buf, int debug, telnet_printfunc_t prnt) if (rnti < 0) ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n"); NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti); + if (!UE) + ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti); int dl_bwp = UE->current_DL_BWP.bwp_id; const char *dl_bwp_text = dl_bwp > 0 ? "dedicated" : "initial"; int ul_bwp = UE->current_UL_BWP.bwp_id; @@ -365,6 +368,24 @@ static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfu return 0; } +static int trigger_bwp_switch(char *buf, int debug, telnet_printfunc_t prnt) +{ + char *sbwpId = strtok(buf, " "); + int bwpId = atoi(sbwpId); + char *srnti = strtok(NULL, " "); + prnt("bwpId %d rnti %s\n", bwpId, srnti); + int rnti = fetch_rnti(srnti, prnt); + if (rnti < 0) + ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n"); + if (!nr_trigger_bwp_switch(rnti, bwpId)) { + prnt("failed trigger BWP switch for UE %04x BWP ID %d\n", rnti, bwpId); + return -1; + } else { + prnt("triggered BWP switch to BWP ID %d for UE %04x\n", bwpId, rnti); + return 0; + } +} + static telnetshell_cmddef_t cicmds[] = { {"get_single_rnti", "", get_single_rnti}, {"force_reestab", "[rnti(hex,opt)]", trigger_reestab}, @@ -374,6 +395,7 @@ static telnetshell_cmddef_t cicmds[] = { {"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho}, {"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id}, {"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp}, + {"trigger_bwp_switch", "newBWPId [rnti(hex,opt)]", trigger_bwp_switch}, {"trigger_n2_ho", "[neighbour_pci(uint32_t),ueId(uint32_t)]", rrc_gNB_trigger_n2_ho}, {"pdu_session_release", "[gNB_ue_ngap_id(int,opt)]", trigger_ngap_pdu_session_release}, {"", "", NULL}, From f5b885e8030c64d58157c30208be25fc6fc402ea Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 25 Nov 2025 14:43:31 +0100 Subject: [PATCH 28/30] Move BWP doc into mac-usage.md --- doc/MAC/mac-usage.md | 26 ++++++++++++++++++++++ doc/RUN_NR_multiple_BWPs.md | 44 ------------------------------------- 2 files changed, 26 insertions(+), 44 deletions(-) delete mode 100644 doc/RUN_NR_multiple_BWPs.md diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index a3b174f50c..2fa56c2ce4 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -420,3 +420,29 @@ Note that you should increase the aggregation level candidates as described in [the corresponding section above](#pdcch-aggregation-level). This is because the scheduler has to schedule multiple DCIs in a single DL slots for multiple UL slots. As a suggestion, you could try `uess_agg_levels = [4, 2, 2, 0, 0]`. + +## Multiple Dedicated BWPs + +A maximum of 4 dedicated BWPs can be configured for a UE per standard, but only +1 BWP can be active in UL and DL direction at a given time. In the code we +only configure a single BWP for the UE at a given time and we would switch by +reconfiguring this BWP. All this procedure is transparent for users and LOGs +mark BWP switching according to the configuration file enumeration. It is +possible to configure multiple dedicated BWPs and 1st active BWP via +configuration file. + +### Setup of the Configuration files ## + +In the configuration file you have the option to select the 1st active BWP, the +BWP location and SCS of each BWP in the following way (example with 2 +additional BWPs): + +``` + first_active_bwp = 1; + bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;}, + { scs = 1; bwpStart = 0; bwpSize = 24;}); +``` + +This example configures 3 additional BWPs, with IDs from 1 to 3. A similar +example can be found in configuration file +`ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf` tested in CI. diff --git a/doc/RUN_NR_multiple_BWPs.md b/doc/RUN_NR_multiple_BWPs.md deleted file mode 100644 index e8598a0445..0000000000 --- a/doc/RUN_NR_multiple_BWPs.md +++ /dev/null @@ -1,44 +0,0 @@ -# Procedure to add dedicated Bandwidth part (BWP) - -## Contributed by 5G Testbed IISc - -### Developers: Abhijith A, Shruthi S - -# Terminology # - -## Bandwidth part (BWP) ## -Bandwidth Part (BWP) is a set of contiguous Resource Blocks in the resource grid. - -Parameters of a BWP are communicated to UE using RRC parameters: BWP-Downlink and BWP-Uplink. - -A UE can be configured with a set of 4 BWPs in uplink (UL) and downlink (DL) direction (3GPP TS 38.331 Annex B.2 Description of BWP configuration options). But only 1 BWP can be active in UL and DL direction at a given time. - -# Procedure to run multiple dedicated BWPs # - -A maximum of 4 dedicated BWPs can be configured for a UE. - -To configure multiple BWPs, add the following parameters in the physical parameters section: - -## Setup of the Configuration files ## - -In the configuration file you have the option to select the 1st active BWP, the RIV and SCS of each BWP in the following way (example with 3 additional BWPs): -``` - first_active_bwp = 1; - bwp_list = ({ scs = 1; bwpStart = 0; bwpSize = 106;}, - { scs = 1; bwpStart = 0; bwpSize = 51;}, - { scs = 1; bwpStart = 0; bwpSize = 24;}); -``` - -This example configures 3 additional BWPs, with IDs from 1 to 3. Find these parameters in this configuration file: "ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf" - -# Testing gNB and UE in RF simulator - -## gNB command: -``` - sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf --rfsim --rfsimulator.serveraddr server -``` - -## UE command: -``` - sudo ./nr-uesoftmodem -C 3319680000 -r 106 --numerology 1 --ssb 516 --band 78 --rfsim --rfsimulator.serveraddr 127.0.0.1 -``` From f46ddb6aa8f59818e27107f9bb17567135edb78d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 1 Dec 2025 16:18:09 +0100 Subject: [PATCH 29/30] Fix: CFRA: UE can always use dedicated search space In all cases (CFRA in SA for HO, or CFRA in NSA/do-ra for access), the UE has the full configuration already. We can therefore directly switch to a dedicated search space, as it is already known to the UE. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index f72c1c88ee..abe5cd8361 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -773,10 +773,9 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, nr_mac_reset_ul_failure(sched_ctrl); reset_dl_harq_list(sched_ctrl); reset_ul_harq_list(sched_ctrl); - // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA - // in NSA (or do-ra) there is no reconfiguration in NR - int ss_type = IS_SA_MODE(get_softmodem_params()) ? NR_SearchSpace__searchSpaceType_PR_common - : NR_SearchSpace__searchSpaceType_PR_ue_Specific; + // we configure the UE using dedicated search space: In SA (CFRA used for + // handover) and NSA (or do-ra), the UE has the full config already. + int ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); // initialize ta_frame in case there is no Msg3 received UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER; From e54153ef5c3cce858057f71e4020bcb1e1d40fea Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 Dec 2025 22:25:56 +0100 Subject: [PATCH 30/30] Add release notes v2.4.0 --- CHANGELOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b355d079..c807b7f86a 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,71 @@ # RELEASE NOTES: # +## [v2.4.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.4.0) -> December 2025. ## + +General new features and improvements (both RAN and UE): +- Rework LDPC BBdev/AAL interface and support both AMD T2/Intel vRAN Boost + (VRB) 1 accelerators +- Add a taps client for vrtsim real-time simulator (check: vrtsim release?) +- Add new RFemulator virtual radio driver to emulate radio (including noise + generation) for gNB/UE standalone operation +- RLC AM reception improvements for high-throughput scenarios (!3512) +- Small NTN fixes (!3659, !3666, !3581, !3652) +- Improvements to imScope + +Stability and bug fixes: +- RFsimulator: fix concurrency problems during multi-client connection +- USRP driver: support synchronization of USRP B200 +- MAC scheduler improvements +- General L1 improvements for efficiency and stability +- Correct PRS bug and test in CI +- Upgrade Ubuntu container images to Ubuntu 24.04 +- All build system targets compile (`make/ninja all`) +- Minor cleanup, harmonization, and performance improvements all over the stack +- Simplify CI code + +RAN changes (gNB/CU/CU-CP/CU-UP/DU/DU-high/DU-low): +- Support of N2 handover +- Support of "UL-heavy" TDD patterns, e.g., DSUUU +- Open Fronthaul M-plane: CM improvements, PM implementation, and additional + v16.01 support +- Improve interoperability with Nvidia Aerial L1 to support 2 layer UL +- Add O-RAN OSC WLS library as FAPI transport and enable L1/L2 shared memory + split +- Implement FAPI Stop exchange +- Improve interoperability with srsRAN_Project DU +- Add new synchronized real-time data recording application (!3462) +- Support for measurement gaps and general handover fixes +- Support of RRC PDU session release procedure +- Add CU-UP load tester +- Correct BWP scheduling and support multiple BWPs per UE + +nrUE changes: +- Support one additional PDU session (see !3486) +- L3 measurements for A2 measurement reports +- Support for type0 PDSCH frequency allocation +- UE symbol based PDCCH receiver + +Regression or removals: +- No known regressions +- Unused L2 simulator code has been removed +- Unused Benetel radio driver code (not FHI 7.2!) has been removed + +Configuration file changes: +- `gNBs.[0].servingCellConfigCommon.[0].ra_ResponseWindow` is automatically + computed and can be removed +- `gNBs.[0].bwp_list` has been added (moved from entries in + `gNBs.[0].servingCellConfigDedicated`) +- `gNBs.[0].phaseTrackingRS` has been added (moved from entries in + `gNBs.[0].servingCellConfigDedicated`) +- `gNBs.[0].local_s_portc` and `gNBs.[0].remote_s_portc` have no effect and + should be removed +- `gNBs.[0].CSI_report_type` has been added +- `MACRLCs.[0].ulsch_max_frame_inactivity` is automatically computed and can be + removed +- `MACRLCs.[0].local_n_portc` and `MACRLCs.[0].remote_n_portc` have no effect and + should be removed +- `MACRLCs.[0].stats_max_ue` has been added + ## [v2.3.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.3.0) -> July 2025. ## General new features and improvements (both RAN and UE):