diff --git a/CMakeLists.txt b/CMakeLists.txt index b00ca296cd..25bc56b79a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -823,6 +823,7 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c ${OPENAIR1_DIR}/PHY/TOOLS/lut.c ${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c + ${OPENAIR1_DIR}/PHY/TOOLS/get_sin_cos.c ) set(PHY_SRC diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 4d1a87ddba..64432f6188 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -77,8 +77,8 @@ oc-cn5g-20897: Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72" LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72 %%log_dir%%" -oc-cn5g-20897-aerial2: - Host: aerial2 +oc-cn5g-20897-aerial: + Host: gracehopper1-oai NetworkScript: echo "inet 172.21.6.105" RunIperf3Server: False Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-nvidia-aerial" diff --git a/ci-scripts/cls_corenetwork.py b/ci-scripts/cls_corenetwork.py index 7bb508d86b..579bad585b 100644 --- a/ci-scripts/cls_corenetwork.py +++ b/ci-scripts/cls_corenetwork.py @@ -49,7 +49,7 @@ class CoreNetwork: self._host = c.get('Host').strip() if self._host == "%%current_host%%": if node is None: - raise Exception(f"core network {self} requires node, but none provided (cannot replace %%current_host%%)") + raise Exception(f"core network {cn_name} requires node, but none provided (cannot replace %%current_host%%)") self._host = node if d is not None: raise Exception("directory handling not implemented") @@ -66,7 +66,7 @@ class CoreNetwork: logging.info(f'initialized core {self} from {filename}') def __str__(self): - return f"{self._cn_name}@{self._host} [IP: {self.getIP()}]" + return f"{self._cn_name}@{self._host}" def __repr__(self): return self.__str__() @@ -162,6 +162,9 @@ class CoreNetwork: def getCmdPrefix(self): return self._cmd_prefix or "" + def getName(self): + return self._cn_name + def getHost(self): return self._host diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 51a7108875..cd40c807e1 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -464,7 +464,7 @@ class OaiCiTest(): return (False, f"UE {ue.getName()} has no IP address") svrIP = cn.getIP() if not svrIP: - return (False, f"Iperf server {ue.getName()} has no IP address") + return (False, f"Iperf server {cn.getName()} has no IP address") iperf_opt = self.iperf_args jsonReport = "--json" @@ -862,7 +862,7 @@ class OaiCiTest(): success, output = cn.deploy() logging.info(f"deployment core network {core_name} success {success}, output:\n{output}") if success: - msg = f"Started {cn}" + msg = f"Started {cn} [{cn.getIP()}]" HTML.CreateHtmlTestRowQueue(core_name, 'OK', [msg]) else: msg = f"deployment of core network {core_name} FAILED" diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf index 2d2120b038..be2e0404e3 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf @@ -186,8 +186,8 @@ gNBs = NETWORK_INTERFACES : { - GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.131"; - GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.131"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.202"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.202"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf index 7a47d90975..fc591cd464 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf @@ -20,6 +20,8 @@ gNBs = min_rxtxtime = 6; num_dlharq = 32; num_ulharq = 32; + cu_sibs = [2]; + du_sibs = [19]; servingCellConfigCommon = ( { @@ -235,15 +237,6 @@ RUs = ( } ); -THREAD_STRUCT = ( - { - #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" - parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; - #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" - worker_config = "WORKER_DISABLE"; - } -); - rfsimulator : { serveraddr = "server"; @@ -296,6 +289,4 @@ log_config : rlc_log_level ="info"; pdcp_log_level ="info"; rrc_log_level ="info"; - ngap_log_level ="debug"; - f1ap_log_level ="debug"; }; diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf index 1d0bba606d..198ac12833 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf @@ -19,6 +19,8 @@ gNBs = sib1_tda = 5; min_rxtxtime = 6; disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; servingCellConfigCommon = ( { @@ -48,7 +50,7 @@ gNBs = initialDLBWPsubcarrierSpacing = 0; #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 2; - initialDLBWPsearchSpaceZero = 0; + initialDLBWPsearchSpaceZero = 2; #uplinkConfigCommon #frequencyInfoUL diff --git a/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf new file mode 100644 index 0000000000..d8ad297180 --- /dev/null +++ b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf @@ -0,0 +1,35 @@ +uicc0 = { + imsi = "208990100001100"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} + +position0 = { + x = 0.0; + y = 0.0; + z = 6377900.0; +} + +thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + +#/* configuration for channel modelisation */ +#/* To be included in main config file when */ +#/* channel modelisation is used (rfsimulator with chanmod options enabled) */ +channelmod = { + max_chan = 10; + modellist = "modellist_rfsimu_1"; + modellist_rfsimu_1 = ( + { # DL, modify on UE side + model_name = "rfsimu_channel_enB0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + }, + { # UL, modify on gNB side + model_name = "rfsimu_channel_ue0" + type = "SAT_LEO_TRANS"; + noise_power_dB = -100; + } + ); +}; diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml new file mode 100644 index 0000000000..2846fc016e --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml @@ -0,0 +1,118 @@ + + + rfsim-5gnr-ntn-Leo + Monolithic SA NTN LEO gNB + wrench + + 111111 + 100001 + 800813 + 000001 + 000002 + 000003 + 020001 + 020002 + 100001 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb-asan oai-nr-ue-asan + + + + Create_Workspace + Create new Workspace + 0 + 0 + + + Deploy_Object + Deploy OAI 5G CoreNetwork + ci-scripts/yaml_files/5g_rfsimulator_ntn_leo + mysql oai-amf oai-smf oai-upf oai-ext-dn + 0 + 0 + + + + Deploy_Object + Deploy OAI 5G gNB+nrUE RF sim SA + ci-scripts/yaml_files/5g_rfsimulator_ntn_leo + oai-gnb oai-nr-ue + 0 + 0 + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + cacofonix + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + cacofonix + rfsim5g_ext_dn + cacofonix + -c 20 -i 0.25 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + cacofonix + rfsim5g_ue + cacofonix + -c 20 -i 0.25 + 5 + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + ci-scripts/yaml_files/5g_rfsimulator_ntn_leo + 0 + 0 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + 0 + oai-gnb-asan oai-nr-ue-asan + + + diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel.xml b/ci-scripts/xml_files/container_sa_aerial_quectel.xml index 07c0c095a2..ccb9500a91 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel.xml @@ -44,7 +44,7 @@ DeployCoreNetwork Initialize 5G Core - oc-cn5g-20897-aerial2 + oc-cn5g-20897-aerial @@ -52,6 +52,7 @@ Pull Images from Local Registry 0 oai-gnb-aerial + arm_ @@ -89,16 +90,16 @@ Ping Ping: 100pings in 20sec up2-aerial - oc-cn5g-20897-aerial2 + oc-cn5g-20897-aerial -c 100 -i 0.2 5 Iperf - iperf (DL/UDP/600M)(30 sec)(single-ue profile) - -u -b 600M -t 30 -R - oc-cn5g-20897-aerial2 + iperf (DL/UDP/500M)(30 sec)(single-ue profile) + -u -b 500M -t 30 -R + oc-cn5g-20897-aerial up2-aerial 25 80 @@ -106,9 +107,9 @@ Iperf - iperf (UL/UDP/50M)(30 sec)(single-ue profile) - -u -b 50M -t 30 - oc-cn5g-20897-aerial2 + iperf (UL/UDP/40M)(30 sec)(single-ue profile) + -u -b 40M -t 30 + oc-cn5g-20897-aerial up2-aerial 25 80 @@ -144,7 +145,7 @@ UndeployCoreNetwork true Terminate 5G Core - oc-cn5g-20897-aerial2 + oc-cn5g-20897-aerial diff --git a/ci-scripts/xml_files/container_sa_gh_aerial_quectel.xml b/ci-scripts/xml_files/container_sa_gh_aerial_quectel.xml deleted file mode 100644 index ea60cb2b6f..0000000000 --- a/ci-scripts/xml_files/container_sa_gh_aerial_quectel.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - TEST-GH-AERIAL-SA - Gracehopper AERIAL 100 MHz TDD SA - tasks - - 111111 - 333333 - - - - - Pull_Local_Registry - Pull Images from Local Registry - 0 - oai-gnb-aerial - arm_ - - - - Clean_Test_Server_Images - true - Clean Test Images on Test Server - 0 - oai-gnb-aerial - - - diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index 193b3a9064..0414910077 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -110,7 +110,7 @@ services: - NET_ADMIN # for interface bringup - NET_RAW # for ping environment: - USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --num-ul-actors 1 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml new file mode 100644 index 0000000000..0cb382710e --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml @@ -0,0 +1,151 @@ +services: + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.0.0 + environment: + - TZ=Europe/paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml + depends_on: + - mysql + networks: + public_net: + ipv4_address: 192.168.71.132 + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oaisoftwarealliance/oai-smf:v2.0.0 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml + depends_on: + - oai-amf + networks: + public_net: + ipv4_address: 192.168.71.133 + oai-upf: + container_name: "rfsim5g-oai-upf" + image: oaisoftwarealliance/oai-upf:v2.0.0 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml + depends_on: + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + networks: + public_net: + ipv4_address: 192.168.71.134 + traffic_net: + ipv4_address: 192.168.72.134 + oai-ext-dn: + privileged: true + container_name: rfsim5g-oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:focal + entrypoint: /bin/bash -c \ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-upf + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + oai-gnb: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 + depends_on: + - oai-ext-dn + networks: + public_net: + ipv4_address: 192.168.71.140 + volumes: + - ../../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: + --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 + --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod + --rfsimulator.serveraddr 192.168.71.140 + --time-sync-I 0.1 --ntn-initial-time-drift -46 + --autonomous-ta --initial-fo 57340 --cont-fo-comp 2 + --log_config.global_log_options level,nocolor,time + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.uicc.ntn-leo.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh b/ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh index 857f815290..e0fea22190 100755 --- a/ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh +++ b/ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh @@ -24,7 +24,7 @@ sudo -E echo start_server -uid 0 | sudo -E nvidia-cuda-mps-control # Check if an argument is provided if [ $# -eq 0 ]; then # No argument provided, use default value - argument="P5G_FXN" + argument="P5G_FXN_GH" else # Argument provided, use it argument="$1" 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 1bc99ff4ba..d5677ac239 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -23,7 +23,7 @@ services: - ../../../cmake_targets/share:/opt/cuBB/share userns_mode: host ipc: "shareable" - image: cubb-build:24-1 + image: cubb-build:24-3 environment: - cuBB_SDK=/opt/nvidia/cuBB command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh" diff --git a/cmake_targets/macros.cmake b/cmake_targets/macros.cmake index 25ba5cb2b8..eafee3a0c1 100644 --- a/cmake_targets/macros.cmake +++ b/cmake_targets/macros.cmake @@ -107,3 +107,18 @@ or directly with ") endif() endfunction() + +function(run_asn1c ASN1C_GRAMMAR ASN1C_PREFIX) + set(options "") + set(oneValueArgs COMMENT) + set(multiValueArgs OUTPUT OPTIONS) + cmake_parse_arguments(ASN1C "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + get_filename_component(GRAMMAR_FILE ${ASN1C_GRAMMAR} NAME) + set(LOGFILE "${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_FILE}.log") + add_custom_command(OUTPUT ${ASN1C_OUTPUT} + COMMAND ASN1C_PREFIX=${ASN1C_PREFIX} ${ASN1C_EXEC} ${ASN1C_OPTIONS} -D ${CMAKE_CURRENT_BINARY_DIR} ${ASN1C_GRAMMAR} > ${LOGFILE} 2>&1 || cat ${LOGFILE} + DEPENDS ${ASN1C_GRAMMAR} + COMMENT "Generating ${ASN1C_COMMENT} from ${GRAMMAR_FILE}" + ) +endfunction() diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 61003857ab..1fe2280c15 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -157,14 +157,19 @@ int write_file_matlab(const char *fname, const char *vname, void *data, int leng //printf("Writing %d elements of type %d to %s\n",length,format,fname); + const int fname_len = strlen(fname); + char write_file_name[fname_len + 10]; + const char *fn_format = (format & MATLAB_RAW) ? "%s.bin" : "%s"; + snprintf(write_file_name, sizeof(write_file_name), fn_format, fname); + if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) { - fp = fopen(fname,"a+"); + fp = fopen(write_file_name, "a+"); } else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) { - fp = fopen(fname,"w+"); + fp = fopen(write_file_name, "w+"); } if (fp== NULL) { - printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n",fname); + printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n", write_file_name); return(-1); } diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index fdb3cc7ffc..ef04daaad1 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -38,6 +38,7 @@ #include "assertions.h" #include "common/utils/utils.h" +#define MAX_SI_GROUPS 3 #define NR_MAX_PDSCH_TBS 3824 #define MAX_NUM_BEAM_PERIODS 4 #define MAX_BWP_SIZE 275 @@ -93,6 +94,12 @@ static inline const char *rnti_types(nr_rnti_type_t rr) // the total shift is 2 * 15, in dB scale thats 10log10(2^(15*2)) #define SQ15_SQUARED_NORM_FACTOR_DB 90.3089986992 +typedef struct { + uint8_t *SIB_buffer; + int SIB_size; + int SIB_type; +} nr_SIBs_t; + typedef struct nr_bandentry_s { int16_t band; uint64_t ul_min; diff --git a/doc/Aerial_FAPI_Split_Tutorial.md b/doc/Aerial_FAPI_Split_Tutorial.md index 03e917ac06..8d4ea54c3d 100644 --- a/doc/Aerial_FAPI_Split_Tutorial.md +++ b/doc/Aerial_FAPI_Split_Tutorial.md @@ -24,8 +24,11 @@ The hardware on which we have tried this tutorial: |----------------------------------------------------------------------------|----------------------------------|--------------------------------------------------| | Gigabyte Edge E251-U70 (Intel Xeon Gold 6240R, 2.4GHz, 24C48T, 96GB DDR4) |Ubuntu 22.04.3 LTS (5.15.0-72-lowlatency)| NVIDIA ConnectX®-6 Dx 22.38.1002 | | Dell PowerEdge R750 (Dual Intel Xeon Gold 6336Y CPU @ 2.4G, 24C/48T (185W), 512GB RDIMM, 3200MT/s) |Ubuntu 22.04.3 LTS (5.15.0-72-lowlatency)| NVIDIA Converged Accelerator A100X (24.39.2048) | +| Supermicro Grace Hopper MGX ARS-111GL-NHR (Neoverse-V2, 3.4GHz, 72C/72T, 576GB LPDDR5) | Ubuntu 22.04.5 LTS (6.5.0-1019-nvidia-64k) |NVIDIA BlueField3 (32.41.1000)| -**NOTE**: These are not minimum hardware requirements. This is the configuration of our servers. The NIC card should support hardware PTP time stamping. +**NOTE**: +- These are not minimum hardware requirements. This is the configuration of our servers. The NIC card should support hardware PTP time stamping. +- Starting from tag [2025.w13](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/2025.w13?ref_type=tags) of OAI, we are only testing with the Grace Hopper server. PTP enabled switches and grandmaster clock we have tested with: @@ -42,6 +45,7 @@ These are the radio units we've used for testing: |-------------|------------------| | Foxconn RPQN-7801E RU | 2.6.9r254 | | Foxconn RPQN-7801E RU | 3.1.15_0p4 | +| Foxconn RPQN-7801E RU | v3.2.0q.551.12.E.rc2.srs-AIO | The UEs that have been tested and confirmed working with Aerial are the following: @@ -54,35 +58,30 @@ The UEs that have been tested and confirmed working with Aerial are the followin | Apaltec | Tributo 5G-Dongle | | OnePlus | Nord (AC2003) | | Apple iPhone | 14 Pro (MQ0G3RX/A) (iOS 17.3) | +| Samsung | S23 Ultra | ## Configure your server -The first step is to obtain the NVIDIA Aerial SDK, you'll need to request access [here](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/aerial-sdk). - -After obtaining access to the SDK, you can refer to [this instructions page](https://docs.nvidia.com/aerial/aerial-ran-colab-ota/current/index.html) to setup the L1 components using NVIDIAs' SDK manager, or to [this instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html) in order to setup and install the components manually. - -The currently used Aerial Version is 24-1, which is also the one currently used by the SDK Manager. +To set up the L1 and install the components manually refer to this [instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html). +**Note**: +- To configure the Gigabyte server please refer to these [instructions](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/2025.w13/doc/Aerial_FAPI_Split_Tutorial.md) +- The last release to support the Gigabyte server is **Aerial CUDA-Accelerated RAN 24-1**. ### CPU allocation -Currently, the CPU isolation is setup the following: +| Server brand | Model | Nº of CPU Cores | Isolated CPUs | +|------------------|---------------|:---------------:|:--------------:| +| Grace Hopper MGX | ARS-111GL-NHR | 72 | 4-64 | -| Server brand | Model | Nº of CPU Cores | Isolated CPUs | -|--------------|-----------|:---------------:|:--------------:| -| Gigabyte | Edge E251-U70 | 24 | 2-10 | - - -**Gigabyte Edge E251-U70** +**Grace Hopper MGX ARS-111GL-NHR** | Applicative Threads | Allocated CPUs | |------------------------|----------------| -| Aerial L1 | 2,3,4,5,6,7,8 | -| PTP & PHC2SYS Services | 9 | +| PTP & PHC2SYS Services | 41 | | OAI `nr-softmodem` | 13-20 | - ## PTP configuration 1. You need to install the `linuxptp` debian package. It will install both ptp4l and phc2sys. @@ -99,14 +98,10 @@ Once installed you can use this configuration file for ptp4l (`/etc/ptp4l.conf`) domainNumber 24 slaveOnly 1 time_stamping hardware -tx_timestamp_timeout 1 -logging_level 6 -summary_interval 0 -#priority1 127 +tx_timestamp_timeout 30 [your_PTP_ENABLED_NIC] network_transport L2 -hybrid_e2e 0 ``` @@ -120,7 +115,7 @@ Documentation=man:ptp4l Restart=always RestartSec=5s Type=simple -ExecStart=taskset -c 9 /usr/sbin/ptp4l -f /etc/ptp.conf +ExecStart=taskset -c 41 /usr/sbin/ptp4l -f /etc/ptp.conf [Install] WantedBy=multi-user.target @@ -149,17 +144,16 @@ WantedBy=multi-user.target # Build OAI gNB -If installing with the Aerial SDK, you should already have the repository cloned in `~/openairinterface5g`, if -Clone OAI code base in a suitable repository, here we are cloning in `~/openairinterface5g` directory, - +If it's not already cloned, the first step is to clone OAI repository ```bash git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g cd ~/openairinterface5g/ ``` ## Get nvIPC sources from the L1 container -The library used for communication between L1 and L2 components is called nvIPC, and was developed by NVIDIA, as such, it is not open-source and can't be freely distributed. -In order to be able to use this library to achieve communication, we need to obtain the nvIPC source files from the L1 container (cuBB) and place it in out gNB project directory `~/openairinterface5g`. + +The library used for communication between L1 and L2 components is called nvIPC, and is developed by NVIDIA. It is not open-source and can't be freely distributed. +In order to achieve this communication, we need to obtain the nvIPC source files from the L1 container (cuBB) and place it in the gNB project directory `~/openairinterface5g`. This allows us to build and install this library when building the L2 docker container. Check whether your L1 container is running: @@ -177,7 +171,7 @@ cuBB aerial@c_aerial_aerial:/opt/nvidia/cuBB# ``` -After logging into the container, we need to pack the nvIPC sources and copy them to the host ( the command creates a tar.gz file with the following name format: nvipc_src.YYYY.MM.DD.tar.gz) +After logging into the container, you need to pack the nvIPC sources and copy them to the host ( the command creates a `tar.gz` file with the following name format: `nvipc_src.YYYY.MM.DD.tar.gz`) ```bash ~$ docker exec -it cuBB bash aerial@c_aerial_aerial:/opt/nvidia/cuBB# cd cuPHY-CP/gt_common_libs @@ -216,7 +210,7 @@ With the nvIPC sources in the project directory, the docker image can be built. ## Building OAI gNB docker image -In order to build the final image, there is an intermediary image to be built (ran-base) +In order to build the target image (`oai-gnb-aerial`), first you should build a common shared image (`ran-base`) ```bash ~$ cd ~/openairinterface5g/ ~/openairinterface5g$ docker build . -f docker/Dockerfile.base.ubuntu22 --tag ran-base:latest @@ -224,21 +218,23 @@ In order to build the final image, there is an intermediary image to be built (r ``` -## Running the setup -In order to use Docker compose to automatically start and stop the setup, we need to first create a ready-made image of the L1, after compiling the L1 software and making the necessary adjustments to its configuration files. -The process of preparing the L1 is covered on NVIDIAs' documentation, and falls outside the scope of this document. +# Running the setup -### Prepare the L1 image -After preparing the L1 software, the container needs to be committed in order for an image in which the L1 is ready to be executed, and that can be referenced by a docker-compose.yaml file later: -*Note:* In preparing the L1 image, the default L1 configuration file is cuphycontroller_P5G_FXN.yaml, located in `/opt/nvidia/cuBB/cuPHY-CP/cuphycontroller/config/`. -This is the file where the RU MAC address needs to be applied before commiting the image +In order to use Docker Compose to automatically start and stop the setup, we first need to create a pre-built image of L1 after compiling the L1 software and making the necessary adjustments to its configuration files. +The process of preparing L1 is covered in NVIDIA's documentation and falls outside the scope of this document. + +## Prepare the L1 image +After preparing the L1 software, the container needs to be committed to create an image where L1 is ready for execution, which can later be referenced by a `docker-compose.yaml` file. + +*Note:* The default L1 configuration file is `cuphycontroller_P5G_FXN_GH.yaml`, located in `/opt/nvidia/cuBB/cuPHY-CP/cuphycontroller/config/`. +In this file the RU MAC address needs to be specified before commiting the image. ```bash -~$ docker commit nv-cubb cubb-build:24-1 +~$ docker commit nv-cubb cubb-build:24-3 ~$ docker image ls .. -cubb-build 24-1 824156e0334c 2 weeks ago 40.1GB -.. +cubb-build 24-3 824156e0334c 2 weeks ago 23.9GB +-.. ``` ## Adapt the OAI-gNB configuration file to your system/workspace @@ -255,14 +251,12 @@ The default amf_ip_address:ipv4 value is 192.168.70.132, when installing the CN5 Both 'GNB_IPV4_ADDRESS_FOR_NG_AMF' and 'GNB_IPV4_ADDRESS_FOR_NGU' need to be set to the IP address of the NIC referenced previously. -### Running docker compose -#### Aerial L1 entrypoint script -Before running docker-compose, we can check which L1 configuration file is to be used by cuphycontroller_scf. -This is set in the script [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh), which is used by the L1 container in order to start the L1 software. -The script begins by setting up some environment variables, restarting NVIDIA MPS, and finally running cuphycontroller_scf. -The L1 software is run with an argument that indicates which configuration file is to be used. -This argument may be changed by providing an argument to the [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh) call in [`docker-compose.yaml`](../ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml). -When no argument is provided (this is the default behaviour), it uses "P5G_FXN" as the cuphycontroller_scf argument. +## Running docker compose +### Aerial L1 entrypoint script +The `aerial_l1_entrypoint` script is used by the L1 container to start the L1 software and is called in the Docker Compose file. +It begins by setting up environment variables, restarting NVIDIA MPS, and finally running `cuphycontroller_scf`. + +The L1 software is executed with an argument that specifies which configuration file to use. If not modified, the default argument is set to `P5G_FXN_GH`. After building the gNB image, and preparing the configuration file, the setup can be run with the following command: @@ -271,17 +265,18 @@ cd ci-scripts/yaml_files/sa_gnb_aerial/ docker compose up -d ``` -This will start both containers, beginning with 'nv-cubb' and only after it being ready it starts 'oai-gnb-aerial'. +This will start both containers, beginning with `nv-cubb`, and `oai-gnb-aerial` will start only after it is ready. -The gNB logs can be followed with: +The logs can be followed using these commands: ```bash docker logs -f oai-gnb-aerial +docker logs -f nv-cubb ``` -#### Running with multiple L2s +### Running with multiple L2s One L1 instance can support multiple L2 instances. See also the [aerial documentation](https://developer.nvidia.com/docs/gputelecom/aerial-sdk/text/cubb_quickstart/running_cubb-end-to-end.html#run-multiple-l2-instances-with-single-l1-instance) for more details. -In OAI the share memory prefix must be configured in the configuration file. +In OAI the shared memory prefix must be configured in the configuration file. ```bash tr_s_preference = "aerial"; @@ -289,9 +284,9 @@ In OAI the share memory prefix must be configured in the configuration file. ``` -### Stopping the setup +## Stopping the setup -Running the following command, will stop both containers, leaving the system ready to be run later: +Run the following command to stop and remove both containers, leaving the system ready to be restarted later: ```bash cd ci-scripts/yaml_files/sa_gnb_aerial/ docker compose down diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 5dd5d8b8b3..3c7490d937 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -105,7 +105,7 @@ These modes of operation are supported: - MAC -> PHY configuration using NR FAPI P5 interface - MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU -- Scheduler procedures for SIB1 +- Generation of and scheduler procedures for MIB/SIB1 - Scheduler procedures for RA - 4-Step RA - Contention Free RA procedure @@ -140,6 +140,7 @@ These modes of operation are supported: - MAC scheduling of SR reception - Intra-frequency handover - Initial support for RedCap +- Scheduling of SIBs (2, 19) ## gNB RLC @@ -174,7 +175,7 @@ These modes of operation are supported: - NR RRC (38.331) Rel 17 messages using new [asn1c](https://github.com/mouse07410/asn1c) - LTE RRC (36.331) also updated to Rel 15 -- Generation of MIB/SIB1 (received from DU) +- Generation of system information (SIB2) - RRC can configure PDCP, RLC, MAC - Interface with GTP-U (tunnel creation/handling for S1-U (NSA), N3 (SA), F1 interfaces) - Integration of RRC messages and procedures supporting UE 5G SA connection diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index 6804ca4543..e4d6ebc098 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -232,7 +232,9 @@ In the `MACRLCs` section of the gNB/DU configuration file: In the `gNBs` section of the gNB/DU configuration file: some of the parameters affect RRC configuration (CellGroupConfig) of a UE, and are therefore listed -here, *also they pertain to the DU*, i.e., the scheduler. +here, *also they pertain to the DU*, i.e., the scheduler. Note also that some +SIBs are configured at the DU and some at the CU; please consult the [RRC +configuration](../RRC/rrc-usage.md) as well for SIB configuration. * `pdsch_AntennaPorts_XP` (default 1): number of XP logical antenna ports in PDSCH (see also [`RUNMODEM.md`](../RUNMODEM.md)) @@ -267,6 +269,8 @@ here, *also they pertain to the DU*, i.e., the scheduler. options are 2, 4, 6, 8, 10, 12, 32; **32 is a Rel-17 features**) * `num_ulharq` (default 16): as `num_dlharq` for UL (other valid option is 32; **32 is i Rel-17 feature**) +- `du_sibs` (default `[]`): list of SIBs to transmit in the cell. Currently, + SIB19 (for NTN) is supported. ## ServingCellConfigCommon parameters diff --git a/doc/RRC/rrc-usage.md b/doc/RRC/rrc-usage.md index 668c106a0d..09c8952889 100644 --- a/doc/RRC/rrc-usage.md +++ b/doc/RRC/rrc-usage.md @@ -67,6 +67,9 @@ RRC-specific configuration ### cell-specific options +Note that some SIBS are configured at the CU and some at the DU; please consult +the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration. + - `gNB_ID` and `gNB_name`: ID and name of the gNB - `tracking_area_code`: the current tracking area code in the range `[0x0001, 0xfffd]` @@ -84,6 +87,8 @@ RRC-specific configuration - `enable_sdap` (default: false): enable the use of the SDAP layer. If deactivated, a transparent SDAP header is prepended to packets, but no further processing is being done. +- `cu_sibs` (default: `[]`) list of SIBs to give to the DU for transmission. + Currently, SIB2 is supported. ### UE-specific configuration diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index b24b4940e5..f2e71390c7 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -136,7 +136,15 @@ Here are some useful command line options for the NR UE: | Parameter | Description | |--------------------------|---------------------------------------------------------------------------------------------------------------| | `--ue-scan-carrier` | Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. | -| `--ue-fo-compensation` | Enables the frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. | +| `--ue-fo-compensation` | Enables the initial frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. | +| `--cont-fo-comp` | Enables the continuous frequency offset (FO) estimation and compensation. Parameter value `1` specifies that the main FO contribution comes from the local oscillator's (LO) accuracy. Parameter value `2` specifies that the main FO contribution comes from Doppler shift. | +| `--initial-fo` | Sets the known initial frequency offset. Useful especially with large Doppler frequency, e.g. LEO satellite. | +| `--freq-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the continuous frequency offset compensation. Default value 0.01. | +| `--freq-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the continuous frequency offset compensation. Default value 0.001. | +| `--ntn-initial-time-drift` | Sets the initial NTN DL time drift (feeder link and service link), given in µs/s. | +| `--autonomous-ta` | Enables the autonomous TA update, based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite). | +| `--time-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the time synchronization. Default value 0.5. | +| `--time-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the time synchronization. Default value 0.0. | | `--usrp-args` | Equivalent to the `sdr_addrs` field in the gNB config file. Used to identify the USRP and set some basic parameters (like the clock source). | | `--clock-source` | Sets the clock source (internal or external). | | `--time-source` | Sets the time source (internal or external). | @@ -349,10 +357,16 @@ For LEO satellite scenarios, the parameter `--ntn-initial-time-drift` must be pr This parameter provides the drift rate of the complete DL timing (incl. feeder link and service link) in µs/s. Also, to perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` should be added in case of a LEO satellite scenario. +For LEO satellite scenario we assume the LO to be very accurate and the main FO contribution comes from Doppler shift. +Therefore, we use the command line parameter `--cont-fo-comp 2` to continuously compensate the DL Doppler and pre-compensate the UL Doppler. +The initial Doppler frequency offset must be provided via command line with the parameter `--initial-fo`. + +For other information on optional NR UE command line options, please refer [here](#optional-nr-ue-command-line-options). + So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent LEO satellite 5G NR NTN is this: ``` cd cmake_targets -sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta +sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta --initial-fo 57340 --cont-fo-comp 2 ``` # Specific OAI modes diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 3a7a1f8f67..53d54e45ec 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -19,10 +19,10 @@ | starsky | Starsky | eNB (B40) | b200mini (30A3E3C) | | carabe | Carabe | UE (B7UE) | B200mini (30AE8C9) | | avra | Avra | gNB (n78) | AW2S Jaguar (192.168.80.239) | -| aerial2 | Aerial2 | gNB (PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial SDK integrated_ | | cacofonix | Cacofonix | gNB (n78, FHI7.2) | -- | | matix | Matix | gNB (n77) | N310 | -| gracehopper1-oai | Gracehopper1 | build, gNB/Aerial | _Nvidia Aerial SDK integrated_ | +| gracehopper1-oai | Gracehopper1 | gNB (n78, PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial integration_ | +| gracehopper3-oai | Gracehopper3 | build | -- | Note: The available resources, and their current usage, is indicated here: - [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/): @@ -127,7 +127,7 @@ information on how the images are built. - build unit tests from `ci-scripts/docker/Dockerfile.unittest.ubuntu22`, and run them - [RAN-Ubuntu-ARM-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-ARM-Image-Builder/) ~BUILD-ONLY ~4G-LTE ~5G-NR - - gracehopper1-oai: ARM Ubuntu 22 image build using docker + - gracehopper3-oai: ARM Ubuntu 22 image build using docker - base image from `Dockerfile.base.ubuntu22` - build image from `Dockerfile.build.ubuntu22`, followed by - target image from `Dockerfile.gNB.ubuntu22` @@ -199,7 +199,7 @@ information on how the images are built. - OpenShift cluster for CN deployment and container images for gNB and UE deployment - [RAN-SA-AERIAL-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AERIAL-CN5G/) ~5G-NR - - 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on Aerial2 + Foxconn RU, up2 + COTS UE (Quectel RM520N), OAI CN5G + - 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on gracehopper1-oai + Foxconn RU, up2 + COTS UE (Quectel RM520N), OAI CN5G - container images for gNB deployment - [RAN-SA-2x2-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-2x2-Module-CN5G/) ~5G-NR diff --git a/doc/dev_tools/sanitizers.md b/doc/dev_tools/sanitizers.md index 6e6376ee08..96fc5317f7 100644 --- a/doc/dev_tools/sanitizers.md +++ b/doc/dev_tools/sanitizers.md @@ -29,6 +29,25 @@ cd cmake_targets/ran_build/build sudo LD_LIBRARY_PATH=. ./nr-softmodem ... ``` +### Possible problems + +On some systems with specific ASan versions, executing a program compiled with +ASan might fail with an error `DEADLYSIGNAL`, or simply a segmentation fault. +Note that since OAI compiles and runs some programs _during compilation_ (for +code generation), typically already the build is impacted. + +The issue is related to Address Space Layout Randomization (ASLR) settings +in Linux, a security feature designed to make it more difficult for attackers +to predict the locations of processes in memory. In this case, it is possible +to avoid the bug by running + +``` +sudo sysctl vm.mmap_rnd_bits=30 +``` + +which reduces the number of bits for memory mappings used to randomize mmap +base addresses. _This reduces the security of the system._ + ## Undefined Behavior Sanitizer (UBSAN) [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) (UBSAN) is a runtime undefined behavior checker. It uses compile-time instrumentation to catch undefined behavior by inserting code that performs specific checks before operations that may cause it. UBSAN can be activated with the `--sanitize-undefined` option or `-fsanitize=undefined`. diff --git a/doc/testbenches_doc_resources/5g-ota-bench.pdf b/doc/testbenches_doc_resources/5g-ota-bench.pdf new file mode 100644 index 0000000000..ff5b9ab88d Binary files /dev/null and b/doc/testbenches_doc_resources/5g-ota-bench.pdf differ diff --git a/doc/testbenches_doc_resources/5g-ota-bench.png b/doc/testbenches_doc_resources/5g-ota-bench.png index e72263629d..e2997f63a1 100644 Binary files a/doc/testbenches_doc_resources/5g-ota-bench.png and b/doc/testbenches_doc_resources/5g-ota-bench.png differ diff --git a/doc/testbenches_doc_resources/5g-ota-bench.tex b/doc/testbenches_doc_resources/5g-ota-bench.tex index 818d10f0fe..04ecf288d6 100644 --- a/doc/testbenches_doc_resources/5g-ota-bench.tex +++ b/doc/testbenches_doc_resources/5g-ota-bench.tex @@ -13,15 +13,15 @@ duplexer/.style={draw,fill=white}, ] - \node[label=above:porcepix] (porcepix) + \node[label=above:cluster] (cluster) {\includegraphics[width=1.2cm]{server}}; - \node[above right=-0.8cm and 2cm of porcepix, label=above:aerial2] (aerial2) + \node[above right=-0.6cm and 2cm of cluster, label=above:gracehopper1-oai] (gracehopper1-oai) {\includegraphics[width=1.2cm]{server}} - edge (porcepix); - \node[right=0.3cm of aerial2, label=above:Foxconn, draw, + edge (cluster); + \node[right=0.3cm of gracehopper1-oai, label=above:Foxconn, draw, minimum width=1.7cm, minimum height=0.8cm] (foxconn) - {O-RU} edge (aerial2); + {O-RU} edge (gracehopper1-oai); \node[below right=+0.45cm and 0.35cm of foxconn.east] (antf1) {\includegraphics[width=0.3cm]{antenna}} edge (foxconn.east); \node[below right=-0.1cm and 0.35cm of foxconn.east] (antf2) @@ -31,7 +31,7 @@ \node[above right=+0.45cm and 0.35cm of foxconn.east] (antf4) {\includegraphics[width=0.3cm]{antenna}} edge (foxconn.east); - \node[above right=+1.3cm and 2cm of porcepix, label=above:matix] (matix) + \node[above right=+1.5cm and 2cm of cluster, label=above:matix] (matix) {\includegraphics[width=1.2cm]{server}}; \node[right=0.3cm of matix, label=above:N310] (n310a) {\includegraphics[width=1.5cm]{n310}} edge (matix); @@ -41,22 +41,9 @@ \node[above right=-0.1cm and 0.35cm of b77o.east] (anto2) {\includegraphics[width=0.3cm]{antenna}} edge (b77o); - \node[below right=-0.6cm and 2cm of porcepix, label=above:obelix] (obelix) + \node[below right=-0.4cm and 2cm of cluster, label=above:cacofonix] (cacofonix) {\includegraphics[width=1.2cm]{server}} - edge (porcepix); - \node[right=0.3cm of obelix, label=above:N310] (n310o) - {\includegraphics[width=1.5cm]{n310}} edge (obelix); - \node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o); - \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1) - {\includegraphics[width=0.3cm]{antenna}} edge (b78o); - \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) - {\includegraphics[width=0.3cm]{antenna}} edge (b78o); - - \node[below=2cm of porcepix, label=above:Cluster] (cluster) - {\includegraphics[width=1.2cm]{server}}; - \node[right=2cm of cluster, label=above:cacofonix] (cacofonix) - {\includegraphics[width=1.2cm]{server}} - edge (cluster); + edge (cluster); \node[right=0.3cm of cacofonix, label=above:VVDN, draw, minimum width=1.7cm, minimum height=0.8cm] (vvdn) {O-RU} edge (cacofonix); @@ -69,7 +56,28 @@ \node[above right=+0.45cm and 0.35cm of vvdn.east] (antv4) {\includegraphics[width=0.3cm]{antenna}} edge (vvdn.east); - \node[above right=+0.0cm and 5.0cm of n310o.east, label=above:RM520N-GL] (quectel) + \node[below=2cm of cluster, label=above:porcepix] (porcepix) + {\includegraphics[width=1.2cm]{server}}; + \node[right=2cm of porcepix, label=above:obelix] (obelix) + {\includegraphics[width=1.2cm]{server}} + edge (porcepix); + \node[right=0.3cm of obelix, label=above:N310] (n310o) + {\includegraphics[width=1.5cm]{n310}} edge (obelix); + \node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o); + \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1) + {\includegraphics[width=0.3cm]{antenna}} edge (b78o); + \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) + {\includegraphics[width=0.3cm]{antenna}} edge (b78o); + + %\node[right=0.3cm of cacofonix, label=above:N310] (n310o) + % {\includegraphics[width=1.5cm]{n310}} edge (cacofonix); + \node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o); + \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1) + {\includegraphics[width=0.3cm]{antenna}} edge (b78o); + \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) + {\includegraphics[width=0.3cm]{antenna}} edge (b78o); + + \node[above right=+0.0cm and 5.0cm of vvdn.east, label=above:RM520N-GL] (quectel) {\includegraphics[height=1.2cm]{quectel}}; \node[above left=-0.1cm and 0.8cm of quectel.west] (aq2) {\includegraphics[width=0.3cm]{antenna}} edge (quectel); diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 482da9a1cf..4f9ae49c42 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -464,23 +464,14 @@ int start_L1L2(module_id_t gnb_id) NR_BCCH_BCH_Message_t *mib = mac->common_channels[0].mib; const NR_BCCH_DL_SCH_Message_t *sib1 = mac->common_channels[0].sib1; - - /* update existing config in F1 Setup request structures */ f1ap_setup_req_t *sr = mac->f1_config.setup_req; DevAssert(sr->num_cells_available == 1); f1ap_served_cell_info_t *info = &sr->cell[0].info; DevAssert(info->mode == F1AP_MODE_TDD); + /* update existing config in F1 Setup request structures */ DevAssert(scc->tdd_UL_DL_ConfigurationCommon != NULL); info->tdd = read_tdd_config(scc); /* updates radio config */ - /* send gNB-DU configuration update to RRC */ - f1ap_gnb_du_configuration_update_t update = { - .transaction_id = 1, - .num_cells_to_modify = 1, - }; - update.cell_to_modify[0].old_nr_cellid = info->nr_cellid; - update.cell_to_modify[0].info = *info; - update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1); - mac->mac_rrc.gnb_du_configuration_update(&update); + prepare_du_configuration_update(mac, info, mib, sib1); init_NR_RU(config_get_if(), NULL); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index d34e710cec..f2716c099e 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -41,6 +41,7 @@ #include "instrumentation.h" #include "common/utils/threadPool/notified_fifo.h" #include "position_interface.h" +#include "nr_phy_common.h" /* * NR SLOT PROCESSING SEQUENCE @@ -104,7 +105,9 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg); static void start_process_slot_tx(void* arg) { notifiedFIFO_elt_t *newTx = arg; nr_rxtx_thread_data_t *curMsgTx = NotifiedFifoData(newTx); - pushNotifiedFIFO(&curMsgTx->UE->ul_actor.fifo, newTx); + int num_ul_actors_to_use = + get_nrUE_params()->num_ul_actors == 0 ? NUM_UL_ACTORS : min(get_nrUE_params()->num_ul_actors, NUM_UL_ACTORS); + pushNotifiedFIFO(&curMsgTx->UE->ul_actors[curMsgTx->proc.nr_slot_tx % num_ul_actors_to_use].fifo, newTx); } static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len) @@ -436,9 +439,13 @@ static void UE_synch(void *arg) { ((ret.rx_offset << 1) / fp->samples_per_subframe * fp->slots_per_subframe) + round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0); - // rerun with new cell parameters and frequency-offset - // todo: the freq_offset computed on DL shall be scaled before being applied to UL - nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset); + if (get_nrUE_params()->cont_fo_comp) { + UE->freq_offset = freq_offset; + } else { + // rerun with new cell parameters and frequency-offset + nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset); + UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0); + } if (get_nrUE_params()->agc) { nr_ue_adjust_rx_gain(UE, cfg0, UE->adjust_rxgain); @@ -452,7 +459,6 @@ static void UE_synch(void *arg) { cfg0->rx_freq[0], cfg0->tx_freq[0]); - UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0); UE->is_synchronized = 1; } else { int gain_change = 0; @@ -551,6 +557,15 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) writeBlockSize -= dummyBlockSize; } + // pre-compensate UL frequency offset + if (flags != TX_BURST_INVALID && get_nrUE_params()->cont_fo_comp) { + double ul_freq_offset = -UE->freq_offset * ((double)fp->ul_CarrierFreq / (double)fp->dl_CarrierFreq); + if (get_nrUE_params()->cont_fo_comp == 2) // different from LO frequency error compensation, Doppler UL pre-compensation has to be negative + ul_freq_offset = -ul_freq_offset; + for (int i = 0; i < fp->nb_antennas_tx; i++) + nr_fo_compensation(ul_freq_offset, fp->samples_per_subframe, writeTimestamp, txp[i], writeBlockSize); + } + int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, txp, writeBlockSize, fp->nb_antennas_tx, flags); AssertFatal(tmp == writeBlockSize, ""); } @@ -585,6 +600,7 @@ void processSlotTX(void *arg) UE->if_inst->sl_indication(&sl_indication); stop_meas(&UE->ue_ul_indication_stats); } + dynamic_barrier_join(rxtxD->next_barrier); if (phy_data.sl_tx_action) { @@ -611,12 +627,14 @@ void processSlotTX(void *arg) UE->if_inst->ul_indication(&ul_indication); stop_meas(&UE->ue_ul_indication_stats); } + dynamic_barrier_join(rxtxD->next_barrier); phy_procedures_nrUE_TX(UE, proc, &phy_data); } + } else { + dynamic_barrier_join(rxtxD->next_barrier); } RU_write(rxtxD, sl_tx_action); - dynamic_barrier_join(rxtxD->next_barrier); TracyCZoneEnd(ctx); } @@ -656,7 +674,9 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) for (int i = 0; i < NUM_DL_ACTORS; i++) { flush_actor(UE->dl_actors + i); } - flush_actor(&UE->ul_actor); + for (int i = 0; i < NUM_UL_ACTORS; i++) { + flush_actor(UE->ul_actors + i); + } clean_UE_harq(UE); UE->is_synchronized = 0; @@ -861,13 +881,12 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) { static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, NR_DL_FRAME_PARMS *fp, int slot_nr, - bool *update_ntn_system_information, int *duration_rx_to_tx, int *timing_advance, int *ntn_koffset) { - if (*update_ntn_system_information) { - *update_ntn_system_information = false; + if (UE->ntn_config_message->update) { + UE->ntn_config_message->update = false; double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms; UE->timing_advance = fp->samples_per_subframe * total_ta_ms; @@ -913,6 +932,8 @@ void *UE_thread(void *arg) if (usrp_tx_thread == 1) UE->rfdevice.trx_write_init(&UE->rfdevice); + InitSinLUT(); + notifiedFIFO_t nf; initNotifiedFIFO(&nf); @@ -947,13 +968,9 @@ void *UE_thread(void *arg) double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift; int ntn_koffset = 0; - int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX; - int nr_slot_tx_offset = 0; - bool update_ntn_system_information = false; while (!oai_exit) { - nr_slot_tx_offset = 0; if (syncRunning) { notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf); @@ -1078,12 +1095,6 @@ void *UE_thread(void *arg) absolute_slot++; TracyCFrameMark; - if (UE->ntn_config_message->update) { - UE->ntn_config_message->update = false; - update_ntn_system_information = true; - nr_slot_tx_offset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset << fp->numerology_index; - } - int slot_nr = absolute_slot % nb_slot_frame; nr_rxtx_thread_data_t curMsg = {0}; curMsg.UE=UE; @@ -1173,8 +1184,8 @@ void *UE_thread(void *arg) shiftForNextFrame = ret; pushNotifiedFIFO(&UE->dl_actors[curMsg.proc.nr_slot_rx % NUM_DL_ACTORS].fifo, newRx); - // apply new duration next run to avoid thread dead lock - apply_ntn_config(UE, fp, slot_nr, &update_ntn_system_information, &duration_rx_to_tx, &timing_advance, &ntn_koffset); + // apply new NTN timing information + apply_ntn_config(UE, fp, slot_nr, &duration_rx_to_tx, &timing_advance, &ntn_koffset); // Start TX slot processing here. It runs in parallel with RX slot processing // in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot @@ -1185,7 +1196,6 @@ void *UE_thread(void *arg) curMsgTx->writeBlockSize = writeBlockSize; curMsgTx->proc.timestamp_tx = writeTimestamp; curMsgTx->UE = UE; - curMsgTx->proc.nr_slot_tx_offset = nr_slot_tx_offset; int slot = curMsgTx->proc.nr_slot_tx; int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index c0142ce896..931ffc3f31 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -224,6 +224,8 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->chest_freq = nrUE_params.chest_freq; UE->chest_time = nrUE_params.chest_time; UE->no_timing_correction = nrUE_params.no_timing_correction; + UE->initial_fo = nrUE_params.initial_fo; + UE->cont_fo_comp = nrUE_params.cont_fo_comp; LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n", UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time); @@ -508,7 +510,9 @@ int main(int argc, char **argv) for (int i = 0; i < NUM_DL_ACTORS; i++) { init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1); } - init_actor(&UE[CC_id]->ul_actor, "UL_", -1); + for (int i = 0; i < NUM_UL_ACTORS; i++) { + init_actor(&UE[CC_id]->ul_actors[i], "UL_", -1); + } init_nr_ue_vars(UE[CC_id], inst); if (UE[CC_id]->sl_mode) { @@ -578,7 +582,9 @@ int main(int argc, char **argv) for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id]; if (phy_vars) { - shutdown_actor(&phy_vars->ul_actor); + for (int i = 0; i < NUM_UL_ACTORS; i++) { + shutdown_actor(&phy_vars->ul_actors[i]); + } for (int i = 0; i < NUM_DL_ACTORS; i++) { shutdown_actor(&phy_vars->dl_actors[i]); } diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index f7e3b42a72..1bc447cb44 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -14,7 +14,12 @@ #define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n" #define CONFIG_HLP_NTN_INIT_TIME_DRIFT "Initial NTN DL time drift (feeder link and service link), given in µs/s\n" #define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n" +#define CONFIG_HLP_INITIAL_FO "Initially compensated DL frequency offset (e.g. known Doppler shift in NTN LEO scenario)\n" +#define CONFIG_HLP_FREQ_SYNC_P "coefficient for Proportional part of continuous frequency offset compensation PI controller\n" +#define CONFIG_HLP_FREQ_SYNC_I "coefficient for Integrating part of continuous frequency offset compensation PI controller\n" +#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift)\n" #define CONFIG_HLP_AGC "Rx Gain control used for UE\n" +#define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to use the default value\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument @@ -65,7 +70,12 @@ {"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.0, TYPE_DOUBLE, 0}, \ {"ntn-initial-time-drift", CONFIG_HLP_NTN_INIT_TIME_DRIFT, 0, .dblptr=&(nrUE_params.ntn_init_time_drift), .defdblval=0.0, TYPE_DOUBLE, 0}, \ {"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \ + {"initial-fo", CONFIG_HLP_INITIAL_FO, 0, .dblptr=&(nrUE_params.initial_fo), .defdblval=0.0, TYPE_DOUBLE, 0}, \ + {"freq-sync-P", CONFIG_HLP_FREQ_SYNC_P, 0, .dblptr=&(nrUE_params.freq_sync_P), .defdblval=0.01, TYPE_DOUBLE, 0}, \ + {"freq-sync-I", CONFIG_HLP_FREQ_SYNC_I, 0, .dblptr=&(nrUE_params.freq_sync_I), .defdblval=0.001, TYPE_DOUBLE, 0}, \ + {"cont-fo-comp", CONFIG_HLP_CONT_FO_COMP, 0, .iptr=&(nrUE_params.cont_fo_comp), .defintval=0, TYPE_INT, 0}, \ {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ + {"num-ul-actors", CONFIG_HLP_NUM_UL_ACTORS, 0, .iptr=&nrUE_params.num_ul_actors, .defintval=0, TYPE_INT, 0}, \ } // clang-format on @@ -89,6 +99,10 @@ typedef struct { double time_sync_I; double ntn_init_time_drift; int autonomous_ta; + double initial_fo; + double freq_sync_P; + double freq_sync_I; + int cont_fo_comp; int agc; char *usrp_args; char *tx_subdev; @@ -101,6 +115,7 @@ typedef struct { double rx_gain_off; int vcdflag; int tx_max_power; + int num_ul_actors; } nrUE_params_t; extern uint64_t get_nrUE_optmask(void); extern uint64_t set_nrUE_optmask(uint64_t bitmask); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 19816e215f..9f8a463ec7 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -171,7 +171,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) NR_DL_FRAME_PARMS *const fp = &ue->frame_parms; NR_UE_COMMON *const common_vars = &ue->common_vars; NR_UE_PRACH **const prach_vars = ue->prach_vars; - NR_UE_SRS **const srs_vars = ue->srs_vars; LOG_I(PHY, "Initializing UE vars for gNB TXant %u, UE RXant %u\n", fp->nb_antennas_tx, fp->nb_antennas_rx); @@ -257,8 +256,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) // DLSCH for (int gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { prach_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_PRACH)); - srs_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_SRS)); - srs_vars[gNB_id]->active = false; // ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32) ue->nr_csi_info = malloc16_clear(sizeof(nr_csi_info_t)); @@ -318,8 +315,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) free_and_zero(ue->nr_srs_info); - free_and_zero(ue->srs_vars[gNB_id]); - free_and_zero(ue->prach_vars[gNB_id]); } @@ -487,7 +482,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE) for (int harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) { NR_UL_UE_HARQ_t *ul_harq_process = &UE->ul_harq_processes[harq_pid]; ul_harq_process->tx_status = NEW_TRANSMISSION_HARQ; - ul_harq_process->ULstatus = SCH_IDLE; ul_harq_process->round = 0; } } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index bd61d100f8..201101a39a 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -25,6 +25,7 @@ #include "nr_modulation.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include //#define DEBUG_FEP @@ -108,6 +109,12 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, rxdata_ptr = (int16_t *)tmp_dft_in; } + if (ue && ue->cont_fo_comp) { + start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS); + nr_fo_compensation(ue->freq_offset, frame_parms->samples_per_subframe, rx_offset, (c16_t *)rxdata_ptr, frame_parms->ofdm_symbol_size); + stop_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS); + } + if (ue) start_meas_nr_ue_phy(ue, RX_DFT_STATS); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 30ce9cdc5e..aed99ff358 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -730,7 +730,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC #endif } uint32_t dmrs_idx = rel15->rbStart; - if (rel15->rnti != SI_RNTI) + if (rel15->refPoint == 0) dmrs_idx += rel15->BWPStart; dmrs_idx *= dmrs_Type == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; c16_t txdataF_precoding[rel15->nrOfLayers][symbol_sz] __attribute__((aligned(64))); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 5b91a068ed..7bcd8264f8 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -47,7 +47,7 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); // search for maximum position within the cyclic prefix - for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) { + for (int i = -frame_parms->nb_prefix_samples; i < frame_parms->nb_prefix_samples; i++) { int temp = 0; int j = (i < 0) ? (i + frame_parms->ofdm_symbol_size) : i; diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 36bd5a1ce7..bc87b3de7f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -640,6 +640,9 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, { int e_rx_cand_idx = 0; *dci_ind = (fapi_nr_dci_indication_t){.SFN = proc->frame_rx, .slot = proc->nr_slot_rx}; + // if DCI for SIB we don't break after finding 1st DCI with that RNTI + // there might be SIB1 and otherSIB in the same slot with the same length + bool is_SI = rel15->rnti == SI_RNTI; for (int j = 0; j < rel15->number_of_candidates; j++) { int CCEind = rel15->CCE[j]; @@ -653,7 +656,7 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, int dci_length = rel15->dci_length_options[k]; int ind; for (ind = 0; ind < dci_ind->number_of_dcis; ind++) { - if (rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) { + if (!is_SI && rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) { break; } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 503f58fb36..74543a250d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -766,10 +766,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, for (int a = 0; a < nbRx; a++) { int offset = (void *)rxdataF_comp[0][a] - (void *)rxdataF_comp[0] + symbol * rx_size_symbol * sizeof(c16_t); memcpy(ue->phy_sim_pdsch_rxdataF_comp + offset, rxdataF_comp[0][a] + symbol * rx_size_symbol, sizeof(c16_t) * rx_size_symbol); - memcpy(ue->phy_sim_pdsch_dl_ch_estimates + offset, dl_ch_estimates, pdsch_est_size * sizeof(c16_t)); + memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates + pdsch_est_size * a, dl_ch_estimates, pdsch_est_size * sizeof(c16_t)); } if (ue->phy_sim_pdsch_dl_ch_estimates_ext) - memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol, dl_ch_estimates_ext, sizeof(dl_ch_estimates_ext)); + memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol, + dl_ch_estimates_ext, + sizeof(dl_ch_estimates_ext)); return (0); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 3143333a3c..dc634584f6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -199,6 +199,9 @@ void nr_scan_ssb(void *arg) // initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame // only one frame is used for simulation tools for (int frame_id = 0; frame_id < ssbInfo->nFrames && !ssbInfo->syncRes.cell_detected; frame_id++) { + if (ssbInfo->freqOffset) + compensate_freq_offset(rxdata, fp, ssbInfo->freqOffset, frame_id); + /* process pss search on received buffer */ ssbInfo->syncRes.frame_id = frame_id; int nid2; @@ -268,7 +271,7 @@ void nr_scan_ssb(void *arg) phase_tdd_ncp, ssbInfo->syncRes.rx_offset); #endif - ssbInfo->freqOffset = freq_offset_pss + freq_offset_sss; + ssbInfo->freqOffset += freq_offset_pss + freq_offset_sss; if (ssbInfo->syncRes.cell_detected) { // we got sss channel ssbInfo->syncRes.cell_detected = nr_pbch_detection(ssbInfo->proc, @@ -319,6 +322,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, .syncRes.cell_detected = false, .nFrames = n_frames, .foFlag = ue->UE_fo_compensation, + .freqOffset = ue->initial_fo, .targetNidCell = ue->target_Nid_cell}; ssbInfo->rxdata = malloc16_clear(fp->nb_antennas_rx * sizeof(c16_t *)); for (int ant = 0; ant < fp->nb_antennas_rx; ant++) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 1de1996126..a570f0a433 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -525,3 +525,21 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, TracyCZoneEnd(ctx); return 0; } + +double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms, + int estimateSz, + const c16_t dl_ch_estimates[][estimateSz]) +{ + const int i_ssb = frame_parms->ssb_index; + const int symbol_offset = nr_get_ssb_start_symbol(frame_parms, i_ssb) % frame_parms->symbols_per_slot; + const c16_t *dl_ch_est_symb1 = &dl_ch_estimates[0][(symbol_offset + 1) * frame_parms->ofdm_symbol_size]; + const c16_t *dl_ch_est_symb3 = &dl_ch_estimates[0][(symbol_offset + 3) * frame_parms->ofdm_symbol_size]; + const int nb_re = 240; + const c32_t dot_prod_res = dot_product(dl_ch_est_symb1, dl_ch_est_symb3, nb_re, 8); + const double res_phase = atan2(dot_prod_res.i, dot_prod_res.r); + const int samples_per_symbol = frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples; + const double t_ofdm = samples_per_symbol / (frame_parms->samples_per_subframe * 1000.0); // symbol duration in sec + const double freq_offset = res_phase / (2 * M_PI * (3 - 1) * t_ofdm); + + return freq_offset; +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index c2953dd196..f0ee943817 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -68,7 +68,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t int Ncp = 0; int prach_start, prach_sequence_length, prach_len, dftlen, mu, n_ra_prb, k, prachStartSymbol, sample_offset_slot; - fd_occasion = 0; + fd_occasion = prach_pdu->num_ra; prach_len = 0; dftlen = 0; first_nonzero_root_idx = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index dc075753ef..bf68a69492 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -204,6 +204,10 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, int rxdataFSize, const struct complex16 rxdataF[][rxdataFSize]); +double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms, + int estimateSz, + const c16_t dl_ch_estimates[][estimateSz]); + #ifndef modOrder #define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 07917b9075..ce7f41d2b9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -46,8 +46,6 @@ typedef enum { typedef struct { /// HARQ tx status harq_result_t tx_status; - /// Status Flag indicating for this ULSCH (idle,active,disabled) - SCH_status_t ULstatus; /// Last TPC command uint8_t TPC; /// Length of ACK information (bits) @@ -87,6 +85,7 @@ typedef struct { } NR_UL_UE_HARQ_t; typedef struct { + SCH_status_t status; /// NDAPI struct for UE nfapi_nr_ue_pusch_pdu_t pusch_pdu; // UL number of harq processes diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index bd4ea90df8..be7a8101db 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -471,7 +471,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; - if (UE->ul_harq_processes[harq_pid].ULstatus != ACTIVE) + if (phy_data->ulsch.status != ACTIVE) return; start_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); @@ -542,8 +542,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////ULSCH coding///////////////////////// if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) { - NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid]; - harq_process_ulsch->ULstatus = SCH_IDLE; stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); return; } @@ -820,12 +818,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } // symbol loop } // port loop - NR_UL_UE_HARQ_t *harq_process_ulsch = NULL; - harq_process_ulsch = &UE->ul_harq_processes[harq_pid]; - harq_process_ulsch->ULstatus = SCH_IDLE; - stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); - } uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c index 17dc69cd4f..44be6a578e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c @@ -426,14 +426,15 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu, int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF, + nr_phy_data_tx_t *phy_data, bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) { - if(!ue->srs_vars[0]->active) { + if(phy_data->srs_vars.active == false) { return -1; } - ue->srs_vars[0]->active = false; - nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t*)&ue->srs_vars[0]->srs_config_pdu; + // TODO: This is wrong: casting from UE fapi to gNB NFAPI srs pdu + nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t *)&phy_data->srs_vars.srs_config_pdu; int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position; // Num consecutive SRS symbols according to 38.211 6.4.1.4.1 diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h index fc785c7aec..1bbe3a27ef 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h @@ -78,7 +78,10 @@ int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, @param rxtx context @param current gNB_id identifier @returns 0 if srs is transmitted -1 otherwise */ - -int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF, bool was_symbol_used[14]); +int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t **txdataF, + nr_phy_data_tx_t *phy_data, + bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); #endif /* SRS_MODULATION_NR_H */ diff --git a/openair1/PHY/TOOLS/get_sin_cos.c b/openair1/PHY/TOOLS/get_sin_cos.c new file mode 100644 index 0000000000..1795b36554 --- /dev/null +++ b/openair1/PHY/TOOLS/get_sin_cos.c @@ -0,0 +1,70 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include "tools_defs.h" + +#define LUT_SIN_RESOL 128 +// look-up table for the sine (cosine) function +static uint16_t LUTSin[LUT_SIN_RESOL + 1]; + +void InitSinLUT(void) +{ + for (int i = 0; i < (LUT_SIN_RESOL + 1); i++) { + LUTSin[i] = round(sin((M_PI * i) / (2 * LUT_SIN_RESOL)) * (1 << 14)); // Format: Q14 + } +} + +// fast calculation of e^{i*2*pi*phase} +// ret.r == cosinus << 14 +// ret.i == sinus << 14 +c16_t get_sin_cos(double phase) +{ + int index; + if (phase < 0) { + index = (int)(-phase * 4 * LUT_SIN_RESOL + 0.5) % (4 * LUT_SIN_RESOL); + index = 4 * LUT_SIN_RESOL - index; + } else { + index = (int)(phase * 4 * LUT_SIN_RESOL + 0.5) % (4 * LUT_SIN_RESOL); + } + + c16_t ret; + if (index < 2 * LUT_SIN_RESOL) { // check for 1st and 2nd Quadrant + if (index < LUT_SIN_RESOL) { // 1st Quadrant + ret.r = LUTSin[LUT_SIN_RESOL - index]; + ret.i = LUTSin[index]; + } else { // 2nd Quadrant + ret.r = -LUTSin[index - LUT_SIN_RESOL]; + ret.i = LUTSin[2 * LUT_SIN_RESOL - index]; + } + } else { // 3rd and 4th Quadrant + if (index < 3 * LUT_SIN_RESOL) { // 3rd Quadrant + ret.r = -LUTSin[3 * LUT_SIN_RESOL - index]; + ret.i = -LUTSin[index - 2 * LUT_SIN_RESOL]; + } else { // 4th Quadrant + ret.r = LUTSin[index - 3 * LUT_SIN_RESOL]; + ret.i = -LUTSin[4 * LUT_SIN_RESOL - index]; + } + } + + return ret; +} diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 93b07a60de..34d7b73fc7 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -792,6 +792,13 @@ double interp(double x, double *xs, double *ys, int count); void simde_mm128_separate_real_imag_parts(simde__m128i *out_re, simde__m128i *out_im, simde__m128i in0, simde__m128i in1); void simde_mm256_separate_real_imag_parts(simde__m256i *out_re, simde__m256i *out_im, simde__m256i in0, simde__m256i in1); +void InitSinLUT(void); + +// fast calculation of e^{i*2*pi*phase} +// ret.r == cosinus << 14 +// ret.i == sinus << 14 +c16_t get_sin_cos(double phase); + #ifdef __cplusplus } #endif diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 2cb2b3d8e6..a617784e64 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -82,6 +82,7 @@ /// suppress compiler warning for unused arguments #define UNUSED(x) (void)x; #define NUM_DL_ACTORS 4 +#define NUM_UL_ACTORS 2 // Set the number of barriers for processSlotTX to 512. This value has to be at least 483 for NTN where // DL-to-UL offset is up to 483. The selected value is also half of the frame range so that @@ -401,7 +402,6 @@ typedef struct PHY_VARS_NR_UE_s { nr_synch_request_t synch_request; NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX]; - NR_UE_SRS *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE]; uint8_t prs_active_gNBs; NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES]; @@ -460,6 +460,11 @@ typedef struct PHY_VARS_NR_UE_s { int64_t max_pos_iir; /// Timing offset IIR filter int max_pos_acc; /// Timing offset accumuluated error for PI filter + double initial_fo; /// initial frequency offset provided by the user + int cont_fo_comp; /// flag enabling the continuous frequency offset estimation and compensation + double freq_offset; /// currently compensated frequency offset + double freq_off_acc; /// accumulated frequency error (for PI controller) + /// Timing Advance updates variables /// Timing advance update computed from the TA command signalled from gNB int timing_advance; @@ -514,7 +519,7 @@ typedef struct PHY_VARS_NR_UE_s { sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS; Actor_t sync_actor; Actor_t dl_actors[NUM_DL_ACTORS]; - Actor_t ul_actor; + Actor_t ul_actors[NUM_UL_ACTORS]; ntn_config_message_t* ntn_config_message; pthread_t main_thread; pthread_t stat_thread; @@ -525,10 +530,6 @@ typedef struct { int gNB_id; /// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission int nr_slot_tx; - /// NR slot index tx offset to resume - /// in case of NTN, tx_offset can be changed dynamically via SIB19 - /// we need to notify the right tx thread slot based on TX offset change - int nr_slot_tx_offset; int rx_slot_type; /// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission int nr_slot_rx; @@ -571,6 +572,7 @@ typedef struct { typedef struct nr_phy_data_tx_s { NR_UE_ULSCH_t ulsch; NR_UE_PUCCH pucch_vars; + NR_UE_SRS srs_vars; // Sidelink Rx action decided by MAC sl_nr_tx_config_type_enum_t sl_tx_action; @@ -597,7 +599,7 @@ typedef struct nr_rxtx_thread_data_s { PHY_VARS_NR_UE *UE; int writeBlockSize; nr_phy_data_t phy_data; - dynamic_barrier_t *next_barrier; + dynamic_barrier_t* next_barrier; } nr_rxtx_thread_data_t; typedef struct LDPCDecode_ue_s { diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 9ae785d8ff..225388cb0d 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -80,4 +80,6 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal); void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay); unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb); +void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size); + #endif diff --git a/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h b/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h index 09e66e8adf..9f91274bae 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h +++ b/openair1/PHY/nr_phy_common/inc/nr_ue_phy_meas.h @@ -28,6 +28,7 @@ #define FOREACH_NR_PHY_CPU_MEAS(FN) \ FN(RX_PDSCH_STATS),\ FN(DLSCH_RX_PDCCH_STATS),\ + FN(RX_FO_COMPENSATION_STATS),\ FN(RX_DFT_STATS),\ FN(DLSCH_CHANNEL_ESTIMATION_STATS),\ FN(DLSCH_DECODING_STATS),\ diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index e1580ca9f0..700721e69f 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -453,3 +453,40 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, in } return (0); } + +void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size) +{ + const double phase_inc = -fo_Hz / (samples_per_ms * 1000); + double phase = sample_offset * phase_inc; + phase -= (int)phase; +#if 1 + // The bottleneck is the calculation of the complex rotation values using get_sin_cos(). + // This code path does not compute these values for the complete OFDM symbol, but only for a smaller CHUNK size. + // After applying the rotation to a CHUNK size of the output, these rotation values are efficiently rotated further by `rot_vec`. + // Unfortunately, this propagates small errors from one chunk to the next. + // Therefore, there is a tradeoff between speed (better with small CHUNK sizes) and accuracy (better with large CHUNK sizes). +#define CHUNK 128 + c16_t rot[CHUNK] __attribute__((aligned(32))); + for (int i = 0; i < CHUNK; i++) { + rot[i] = get_sin_cos(phase); + phase += phase_inc; + } + const c16_t rot_vec = get_sin_cos(CHUNK * phase_inc); + while (size > CHUNK) { + mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, CHUNK, 14); + rxdata_ptr += CHUNK; + rotate_cpx_vector(rot, &rot_vec, rot, CHUNK, 14); + size -= CHUNK; + } + mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, size, 14); +#else + // This code path computes the complex rotation values for the complete OFDM symbol using get_sin_cos(). + // This is more accurate, but also slower than the code path above. + c16_t rot[size] __attribute__((aligned(32))); + for (int i = 0; i < size; i++) { + rot[i] = get_sin_cos(phase); + phase += phase_inc; + } + mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, size, 14); +#endif +} diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index ba4ad4a0f7..6bb7ed3e4c 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -518,7 +518,7 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r pdu->pusch_config_pdu.tx_request_body.pdu_length); } - harq_process_ul_ue->ULstatus = ACTIVE; + phy_data->ulsch.status = ACTIVE; pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more } break; @@ -549,8 +549,8 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r case FAPI_NR_UL_CONFIG_TYPE_SRS: // srs config pdu - phy->srs_vars[0]->srs_config_pdu = pdu->srs_config_pdu; - phy->srs_vars[0]->active = true; + phy_data->srs_vars.srs_config_pdu = pdu->srs_config_pdu; + phy_data->srs_vars.active = true; pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more break; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 37593bb9a7..d427e9721c 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -290,7 +290,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used); - ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, was_symbol_used); + ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, phy_data, was_symbol_used); pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used); @@ -929,6 +929,17 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ sampleShift = nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384); } + + if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) { + double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates); + LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz, accumulated frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset, ue->freq_off_acc); + + // PI controller + const double PID_P = get_nrUE_params()->freq_sync_P; + const double PID_I = get_nrUE_params()->freq_sync_I; + ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I; + ue->freq_off_acc += freq_offset; + } } LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__); nr_ue_rrc_measurements(ue, proc, rxdataF); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 7b1b34c93f..2ce428fc8a 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -958,6 +958,13 @@ printf("%d\n", slot); fprintf(csv_file,"avg_round,eff_rate,eff_throughput,TBS\n"); } //--------------- + + Sched_INFO = malloc(sizeof(*Sched_INFO)); + if (Sched_INFO == NULL) { + LOG_E(PHY, "out of memory\n"); + exit(1); + } + for (SNR = snr0; SNR < snr1 && !stop; SNR += .2) { varArray_t *table_tx=initVarArray(1000,sizeof(double)); @@ -988,6 +995,9 @@ printf("%d\n", slot); n_false_positive = 0; if (n_trials== 1) num_rounds = 1; + NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; + for (trial = 0; trial < n_trials && !stop; trial++) { errors_bit = 0; @@ -1003,19 +1013,11 @@ printf("%d\n", slot); int harq_pid = slot; NR_DL_UE_HARQ_t *UE_harq_process = &UE->dl_harq_processes[0][harq_pid]; - NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; - UE_harq_process->decodeResult = false; round = 0; UE_harq_process->DLround = round; UE_harq_process->first_rx = 1; - Sched_INFO = malloc(sizeof(*Sched_INFO)); - if (Sched_INFO == NULL) { - LOG_E(PHY, "out of memory\n"); - exit(1); - } memset(Sched_INFO, 0, sizeof(*Sched_INFO)); Sched_INFO->sched_response_id = -1; @@ -1109,10 +1111,10 @@ printf("%d\n", slot); sprintf(filename,"txsig%d.m", aa);//LOG_M LOG_M(filename,"txs", &txdata[aa][slot_offset +frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1); } - } - if (output_fd) { - printf("writing txdata to binary file\n"); - fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd); + if (output_fd) { + printf("writing txdata to binary file\n"); + fwrite(txdata[0], sizeof(int32_t), frame_length_complex_samples, output_fd); + } } int txlev[n_tx]; @@ -1296,15 +1298,38 @@ printf("%d\n", slot); } if (n_trials == 1) { + unsigned int op_format = 1; + unsigned int dec = 1; + if (output_fd) { // Write in bin format + op_format |= MATLAB_RAW; + } - LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1); + LOG_M("rxsig0.m", "rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, dec, op_format); if (UE->frame_parms.nb_antennas_rx>1) - LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1); - LOG_M("rxF0.m","rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, 1, 1); - LOG_M("rxF_ext.m","rxFe",UE->phy_sim_pdsch_rxdataF_ext,g_rbSize*12*14,1,1); - LOG_M("chestF0.m","chF0",UE->phy_sim_pdsch_dl_ch_estimates_ext,g_rbSize*12*14,1,1); - write_output("rxF_comp.m","rxFc",UE->phy_sim_pdsch_rxdataF_comp,N_RB_DL*12*14,1,1); - LOG_M("rxF_llr.m","rxFllr",UE->phy_sim_pdsch_llr,available_bits,1,0); + LOG_M("rxsig1.m", "rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, dec, op_format); + LOG_M("rxF0.m", "rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, dec, op_format); + LOG_M("rxF_ext.m", "rxFe", UE->phy_sim_pdsch_rxdataF_ext, g_rbSize * 12 * 14, dec, op_format); + const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15); + const uint32_t numValidReSym = g_rbSize * 12; + { + const int s = rel15->StartSymbolIndex; + const int n = rel15->NrOfSymbols; + for (int i = s; i < s + n; i++) { + char fName[50]; + snprintf(fName, sizeof(fName), "chestF0_ext_s%d.m", i); + LOG_M(fName, + "chF0_ext", + ((c16_t *)UE->phy_sim_pdsch_dl_ch_estimates_ext) + (i * numReSym), + numValidReSym, + dec, + op_format); + snprintf(fName, sizeof(fName), "rxF_comp_s%d.m", i); + LOG_M(fName, "rxFc", ((c16_t *)UE->phy_sim_pdsch_rxdataF_comp) + (i * numReSym), numValidReSym, dec, op_format); + } + } + LOG_M("chestF0.m", "chF0", UE->phy_sim_pdsch_dl_ch_estimates, frame_parms->ofdm_symbol_size * 14, dec, op_format); + op_format = (op_format & (~1)); + LOG_M("rxF_llr.m", "rxFllr", UE->phy_sim_pdsch_llr, available_bits, dec, op_format); break; } @@ -1316,6 +1341,8 @@ printf("%d\n", slot); n_errs = n_errors[0]; } // NSR + free(Sched_INFO); + free_channel_desc_scm(gNB2UE); for (i = 0; i < n_tx; i++) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 599efbbd6b..7b58853fbe 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -239,6 +239,7 @@ int main(int argc, char *argv[]) int threadCnt=0; int max_ldpc_iterations = 5; int num_antennas_per_thread = 1; + uint32_t log_format = 0; if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) { exit_fun("[NR_ULSIM] Error, configuration module init failed\n"); } @@ -250,8 +251,7 @@ int main(int argc, char *argv[]) InitSinLUT(); int c; - while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:k:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) { - + while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:jk:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -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') @@ -345,7 +345,11 @@ int main(int argc, char *argv[]) i+=2; } while (optarg[i-1] == ','); break; - + + case 'j': + log_format |= MATLAB_RAW; + break; + case 'k': printf("Setting threequarter_fs_flag\n"); openair0_cfg[0].threequarter_fs= 1; @@ -523,6 +527,7 @@ int main(int argc, char *argv[]) printf("-g Channel model configuration. Arguments list: Number of arguments = 3, {Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300}, {Correlation: [l] Low, [m] Medium, [h] High}, {Maximum Doppler shift} e.g. -g A,l,10\n"); printf("-h This message\n"); printf("-i Change channel estimation technique. Arguments list: Number of arguments=2, Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}. e.g. -i 1,0\n"); + printf("-j Save signal buffers in binary format."); printf("-k 3/4 sampling\n"); printf("-m MCS value\n"); printf("-n Number of trials to simulate\n"); @@ -559,7 +564,7 @@ int main(int argc, char *argv[]) } } - + logInit(); set_glog(loglvl); @@ -1214,12 +1219,12 @@ int main(int argc, char *argv[]) phy_procedures_nrUE_TX(UE, &UE_proc, &phy_data); if (n_trials == 1) { - LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1); + LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1 | log_format); if (precod_nbr_layers > 1) { - LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1); - if (precod_nbr_layers == 4) { - LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1); - LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1); + LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1 | log_format); + if (precod_nbr_layers == 4) { + LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1 | log_format); + LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1 | log_format); } } } @@ -1293,16 +1298,16 @@ int main(int argc, char *argv[]) ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot, &UL_INFO); if (n_trials == 1 && round == 0) { - LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1); - LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1); + LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1 | log_format); + LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format); if (precod_nbr_layers > 1) { LOG_M("rxsig1.m", "rx1", &rxdata[1][slot_offset], slot_length, 1, 1); - LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1); + LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format); if (precod_nbr_layers == 4) { LOG_M("rxsig2.m", "rx2", &rxdata[2][slot_offset], slot_length, 1, 1); LOG_M("rxsig3.m", "rx3", &rxdata[3][slot_offset], slot_length, 1, 1); - LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1); - LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1); + LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format); + LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format); } } } @@ -1316,71 +1321,69 @@ int main(int argc, char *argv[]) &pusch_vars->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, - 1); + 1 | log_format); LOG_M("rxsigF0_comp.m", "rxsF0_comp", &pusch_vars->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, - 1); + 1 | log_format); if (precod_nbr_layers == 2) { - LOG_M("chestF3.m", "chF3", &pusch_vars->ul_ch_estimates[3][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, - 1); + 1 | log_format); LOG_M("rxsigF2_comp.m", "rxsF2_comp", &pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, - 1); + 1 | log_format); } if (precod_nbr_layers == 4) { - LOG_M("chestF5.m", "chF5", &pusch_vars->ul_ch_estimates[5][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, - 1); + 1 | log_format); LOG_M("chestF10.m", "chF10", &pusch_vars->ul_ch_estimates[10][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, - 1); + 1 | log_format); LOG_M("chestF15.m", "chF15", &pusch_vars->ul_ch_estimates[15][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, - 1); + 1 | log_format); LOG_M("rxsigF4_comp.m", "rxsF4_comp", &pusch_vars->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, - 1); + 1 | log_format); LOG_M("rxsigF8_comp.m", "rxsF8_comp", &pusch_vars->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, - 1); + 1 | log_format); LOG_M("rxsigF12_comp.m", "rxsF12_comp", &pusch_vars->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, - 1); + 1 | log_format); } LOG_M("rxsigF0_llr.m", @@ -1388,7 +1391,7 @@ int main(int argc, char *argv[]) &pusch_vars->llr[0], precod_nbr_layers * (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, - 0); + 0 | log_format); } if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) { diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index de616bf86c..f17c2166a3 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -143,31 +143,6 @@ void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *des #else -void add_noise(c16_t **rxdata, - const double **r_re, - const double **r_im, - const double sigma, - const int length, - const int slot_offset, - const double ts, - const int delay, - const uint16_t pdu_bit_map, - const uint16_t ptrs_bit_map, - const uint8_t nb_antennas_rx) -{ - for (int i = 0; i < length; i++) { - for (int ap = 0; ap < nb_antennas_rx; ap++) { - c16_t *rxd = &rxdata[ap][slot_offset + i + delay]; - rxd->r = r_re[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); // convert to fixed point - rxd->i = r_im[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); - /* Add phase noise if enabled */ - if (pdu_bit_map & ptrs_bit_map) { - phase_noise(ts, &rxdata[ap][slot_offset + i + delay].r, &rxdata[ap][slot_offset + i + delay].i); - } - } - } -} - void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *desc, double *tx_sig_re[NB_ANTENNAS_TX], double *tx_sig_im[NB_ANTENNAS_TX], diff --git a/openair1/SIMULATION/TOOLS/phase_noise.c b/openair1/SIMULATION/TOOLS/phase_noise.c index 8c2b36dfec..5bb6df3b5e 100644 --- a/openair1/SIMULATION/TOOLS/phase_noise.c +++ b/openair1/SIMULATION/TOOLS/phase_noise.c @@ -23,47 +23,41 @@ #include "sim.h" -static uint16_t LUTSin[ResolSinCos+1]; /* linear phase noise model */ -void phase_noise(double ts, int16_t * InRe, int16_t * InIm) +void phase_noise(double ts, int16_t *InRe, int16_t *InIm) { static uint64_t i=0; - int32_t x=0 ,y=0; double fd = 300;//0.01*30000 - int16_t SinValue = 0, CosValue= 0; - double IdxDouble = (double)(i*fd * ts * ResolSinCos * 4); - int16_t IdxModulo = ((int32_t)(IdxDouble>0 ? IdxDouble+0.5 : IdxDouble-0.5)) % (ResolSinCos*4); - IdxModulo = IdxModulo<0 ? IdxModulo+ResolSinCos*4 : IdxModulo; - - if(IdxModulo<2*ResolSinCos) {//< 2 check for 1st and 2nd - if(IdxModulo < ResolSinCos) {// 1st Quadrant - SinValue = LUTSin[IdxModulo]; - CosValue = LUTSin[ResolSinCos-IdxModulo]; - } - else {// 2nd Quadrant - SinValue = LUTSin[2*ResolSinCos-IdxModulo]; - CosValue = -LUTSin[IdxModulo-ResolSinCos]; - } - } - else {// 3rd and 4th Quadrant - if(IdxModulo < 3*ResolSinCos) {// 3rd Quadrant - SinValue = -LUTSin[IdxModulo-2*ResolSinCos]; - CosValue = -LUTSin[3*ResolSinCos-IdxModulo]; - } - else {//4th Quadrant - SinValue = -LUTSin[4*ResolSinCos-IdxModulo]; - CosValue = LUTSin[IdxModulo-3*ResolSinCos]; - } - } - x = ( ((int32_t)InRe[0] * CosValue) - ((int32_t)InIm[0] * SinValue )); - y = ( ((int32_t)InIm[0] * CosValue) + ((int32_t)InRe[0] * SinValue )); - InRe[0]= (int16_t)(x>>14); - InIm[0]= (int16_t)(y>>14); + double phase = (double)(i * fd * ts); + c16_t rot = get_sin_cos(phase); + c16_t val = {.r = *InRe, .i = *InIm}; + val = c16mulShift(val, rot, 14); + *InRe = val.r; + *InIm = val.i; i++; } -/* Initialisation function for SIN table values */ -void InitSinLUT( void ) { - for ( int i=0; i<(ResolSinCos+1); i++ ) { - LUTSin[i] = sin((double)(M_PI*i)/(2*ResolSinCos)) * (1<<14); //Format: Q14 + +void add_noise(c16_t **rxdata, + const double **r_re, + const double **r_im, + const double sigma, + const int length, + const int slot_offset, + const double ts, + const int delay, + const uint16_t pdu_bit_map, + const uint16_t ptrs_bit_map, + const uint8_t nb_antennas_rx) +{ + for (int i = 0; i < length; i++) { + for (int ap = 0; ap < nb_antennas_rx; ap++) { + c16_t *rxd = &rxdata[ap][slot_offset + i + delay]; + rxd->r = r_re[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); // convert to fixed point + rxd->i = r_im[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); + /* Add phase noise if enabled */ + if (pdu_bit_map & ptrs_bit_map) { + phase_noise(ts, &rxdata[ap][slot_offset + i + delay].r, &rxdata[ap][slot_offset + i + delay].i); + } + } } } diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index b9ae9e3fff..d13cfd8921 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -1663,7 +1663,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, maxDoppler = 0; chan_desc->sat_height = 600e3; chan_desc->enable_dynamic_delay = true; - chan_desc->enable_dynamic_Doppler = false; // TODO: requires UE to support continuous Doppler estimation, compensation and pre-compensation + chan_desc->enable_dynamic_Doppler = true; fill_channel_desc(chan_desc,nb_tx, nb_rx, nb_taps, @@ -1762,6 +1762,11 @@ void set_channeldesc_name(channel_desc_t *cdesc,char *modelname) { cdesc->model_name=strdup(modelname); } +void set_channeldesc_direction(channel_desc_t *cdesc, bool is_uplink) +{ + cdesc->is_uplink = is_uplink; +} + #ifdef DEBUG_CH_POWER double accumulated_ch_power = 0; int ch_power_count = 0; diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 34cae4ba55..98b4fb26c6 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -139,6 +139,8 @@ typedef struct { float Doppler_phase_inc; /// current Doppler phase of each RX antenna (for continuous phase from one block to the next) float *Doppler_phase_cur; + /// flag indicating if channel direction is UL or DL + bool is_uplink; } channel_desc_t; typedef struct { @@ -358,6 +360,7 @@ void free_channel_desc_scm(channel_desc_t *ch); \param module_id identifies the channel model. should be define as a macro in simu.h */ void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id); + /** \brief This function set a model name to a model descriptor, can be later used to identify a allocated channel model \param cdesc points to the model descriptor @@ -365,6 +368,13 @@ void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_i */ void set_channeldesc_name(channel_desc_t *cdesc,char *modelname); +/** +\brief This function set a channel model direction to either uplink or downlink +\param cdesc points to the model descriptor +\param is_uplink indicates if this channel is applied in uplink (not downlink) direction +*/ +void set_channeldesc_direction(channel_desc_t *cdesc, bool is_uplink); + /** \fn void get_cexp_doppler(struct complexd *cexp_doppler, channel_desc_t *chan_desc, const uint32_t length) \brief This routine generates the complex exponential to apply the Doppler shift \param cexp_doppler Output with the complex exponential of Doppler shift @@ -379,32 +389,6 @@ void get_cexp_doppler(struct complexd *cexp_doppler, channel_desc_t *chan_desc, */ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); -/** -\brief Add AWGN noise and phase noise if enabled -\param rxdata output data with noise -\param r_re real part of input data without noise -\param r_im imaginary part of input data without noise -\param sigma noise power -\param length number of samples to apply the noise -\param slot_offset slot offset to start applying the noise -\param ts sampling time -\param delay introduce delay in terms of number of samples -\param pdu_bit_map bitmap indicating presence of optional PDUs -\param ptrs_bit_map -\param nb_antennas_rx number of receive antennas -*/ -void add_noise(c16_t **rxdata, - const double **r_re, - const double **r_im, - const double sigma, - const int length, - const int slot_offset, - const double ts, - const int delay, - const uint16_t pdu_bit_map, - const uint16_t ptrs_bit_map, - const uint8_t nb_antennas_rx); - /**\fn void multipath_channel(channel_desc_t *desc, double tx_sig_re[NB_ANTENNAS_TX], double tx_sig_im[NB_ANTENANS_TX], @@ -570,16 +554,38 @@ double N_RB2sampling_rate(uint16_t N_RB); double N_RB2channel_bandwidth(uint16_t N_RB); /* Linear phase noise model */ -/*! +/** \brief This function produce phase noise and add to input signal - \param ts Sampling time + \param ts Sampling time \param *Re *Im Real and Imag part of the signal */ -//look-up table for the sine (cosine) function -#define ResolSinCos 100 -void InitSinLUT( void ); -void phase_noise(double ts, int16_t * InRe, int16_t * InIm); +void phase_noise(double ts, int16_t *InRe, int16_t *InIm); +/** +\brief Add AWGN noise and phase noise if enabled +\param rxdata output data with noise +\param r_re real part of input data without noise +\param r_im imaginary part of input data without noise +\param sigma noise power +\param length number of samples to apply the noise +\param slot_offset slot offset to start applying the noise +\param ts sampling time +\param delay introduce delay in terms of number of samples +\param pdu_bit_map bitmap indicating presence of optional PDUs +\param ptrs_bit_map +\param nb_antennas_rx number of receive antennas +*/ +void add_noise(c16_t **rxdata, + const double **r_re, + const double **r_im, + const double sigma, + const int length, + const int slot_offset, + const double ts, + const int delay, + const uint16_t pdu_bit_map, + const uint16_t ptrs_bit_map, + const uint8_t nb_antennas_rx); void do_DL_sig(sim_t *sim, uint16_t subframe, diff --git a/openair2/E1AP/MESSAGES/CMakeLists.txt b/openair2/E1AP/MESSAGES/CMakeLists.txt index 0657740e93..5d79f8dc3d 100644 --- a/openair2/E1AP/MESSAGES/CMakeLists.txt +++ b/openair2/E1AP/MESSAGES/CMakeLists.txt @@ -9,10 +9,11 @@ else() message(FATAL_ERROR "unknown E1AP_RELEASE ${E1AP_RELEASE}") endif() -add_custom_command(OUTPUT ${e1ap_source} ${e1ap_headers} - COMMAND ASN1C_PREFIX=E1AP_ ${ASN1C_EXEC} -gen-APER -gen-UPER -no-gen-JER -no-gen-BER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR} - COMMENT "Generating E1AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR} + "E1AP_" + OUTPUT ${e1ap_source} ${e1ap_headers} + OPTIONS -gen-APER -gen-UPER -no-gen-JER -no-gen-BER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps + COMMENT "E1AP source files" ) add_library(asn1_e1ap ${e1ap_source}) diff --git a/openair2/F1AP/MESSAGES/CMakeLists.txt b/openair2/F1AP/MESSAGES/CMakeLists.txt index 2b17d09ddd..0274b3a6cc 100644 --- a/openair2/F1AP/MESSAGES/CMakeLists.txt +++ b/openair2/F1AP/MESSAGES/CMakeLists.txt @@ -8,10 +8,11 @@ else() message(FATAL_ERROR "unknown F1AP_RELEASE ${F1AP_RELEASE}") endif() -add_custom_command(OUTPUT ${f1ap_source} ${f1ap_headers} - COMMAND ASN1C_PREFIX=F1AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR} - COMMENT "Generating F1AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR} + "F1AP_" + OUTPUT ${f1ap_source} ${f1ap_headers} + OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps + COMMENT "F1AP source files" ) add_library(asn1_f1ap ${f1ap_source}) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 4d8c4fcccf..5767a06d95 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -653,11 +653,9 @@ static void encode_cells_to_activate(const served_cells_to_activate_t *cell, F1A &cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; const f1ap_sib_msg_t *SI_msg = &cell->SI_msg[n]; if (SI_msg->SI_container != NULL) { - if (SI_msg->SI_type > 6 && SI_msg->SI_type != 9) { - asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); - sib_item->sIBtype = SI_msg->SI_type; - OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length); - } + asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); + sib_item->sIBtype = SI_msg->SI_type; + OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length); } } } @@ -1221,7 +1219,7 @@ f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg) const f1ap_sib_msg_t *b_SI_msg = &msg_cell->SI_msg[j]; cp_SI_msg->SI_container_length = b_SI_msg->SI_container_length; cp_SI_msg->SI_container = malloc_or_fail(cp_SI_msg->SI_container_length); - *cp_SI_msg->SI_container = *b_SI_msg->SI_container; + memcpy(cp_SI_msg->SI_container, b_SI_msg->SI_container, b_SI_msg->SI_container_length); cp_SI_msg->SI_type = b_SI_msg->SI_type; } } @@ -2109,8 +2107,12 @@ f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_a for (int i = 0; i < cp.num_cells_to_activate; i++) { cp.cells_to_activate[i] = msg->cells_to_activate[i]; for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) { - cp.cells_to_activate[i].SI_msg[s].SI_container = calloc_or_fail(1, sizeof(*cp.cells_to_activate[i].SI_msg[s].SI_container)); - *cp.cells_to_activate[i].SI_msg[s].SI_container = *msg->cells_to_activate[i].SI_msg[s].SI_container; + f1ap_sib_msg_t *cp_sib = &cp.cells_to_activate[i].SI_msg[s]; + const f1ap_sib_msg_t *msg_sib = &msg->cells_to_activate[i].SI_msg[s]; + cp_sib->SI_type = msg_sib->SI_type; + cp_sib->SI_container_length = msg_sib->SI_container_length; + cp_sib->SI_container = calloc_or_fail(cp_sib->SI_container_length, sizeof(*cp_sib->SI_container)); + memcpy(cp_sib->SI_container, msg_sib->SI_container, cp_sib->SI_container_length); } } return cp; diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index a1d860c86c..e4eaa52804 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -63,14 +63,15 @@ #define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER "dl_bler_target_lower" +#define CONFIG_STRING_MACRLC_DL_MIN_MCS "dl_min_mcs" #define CONFIG_STRING_MACRLC_DL_MAX_MCS "dl_max_mcs" #define CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER "ul_bler_target_upper" #define CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER "ul_bler_target_lower" +#define CONFIG_STRING_MACRLC_UL_MIN_MCS "ul_min_mcs" #define CONFIG_STRING_MACRLC_UL_MAX_MCS "ul_max_mcs" #define CONFIG_STRING_MACRLC_DL_HARQ_ROUND_MAX "dl_harq_round_max" #define CONFIG_STRING_MACRLC_UL_HARQ_ROUND_MAX "ul_harq_round_max" #define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb" -#define CONFIG_STRING_MACRLC_MIN_GRANT_MCS "min_grant_mcs" #define CONFIG_STRING_MACRLC_IDENTITY_PM "identity_precoding_matrix" #define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming" #define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration" @@ -81,14 +82,15 @@ #define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not" #define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS" #define HLP_MACRLC_DL_BLER_LO "Lower threshold of BLER to increase DL MCS" +#define HLP_MACRLC_DL_MIN_MCS "Minimum DL MCS that should be used" #define HLP_MACRLC_DL_MAX_MCS "Maximum DL MCS that should be used" #define HLP_MACRLC_UL_BLER_UP "Upper threshold of BLER to decrease UL MCS" #define HLP_MACRLC_UL_BLER_LO "Lower threshold of BLER to increase UL MCS" +#define HLP_MACRLC_UL_MIN_MCS "Minimum UL MCS that should be used" #define HLP_MACRLC_UL_MAX_MCS "Maximum UL MCS that should be used" #define HLP_MACRLC_DL_HARQ_MAX "Maximum number of DL HARQ rounds" #define HLP_MACRLC_UL_HARQ_MAX "Maximum number of UL HARQ rounds" #define HLP_MACRLC_MIN_GRANT_PRB "Minimal Periodic ULSCH Grant PRBs" -#define HLP_MACRLC_MIN_GRANT_MCS "Minimal Periodic ULSCH Grant MCS" #define HLP_MACRLC_IDENTITY_PM "Flag to use only identity matrix in DL precoding" #define HLP_MACRLC_AB "Flag to enable analog beamforming" #define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams" @@ -125,14 +127,15 @@ {CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, .iptr=NULL, .defintval=10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, HLP_MACRLC_DL_BLER_UP, 0, .dblptr=NULL, .defdblval=0.15, TYPE_DOUBLE, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER, HLP_MACRLC_DL_BLER_LO, 0, .dblptr=NULL, .defdblval=0.05, TYPE_DOUBLE, 0}, \ + {CONFIG_STRING_MACRLC_DL_MIN_MCS, HLP_MACRLC_DL_MIN_MCS, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_DL_MAX_MCS, HLP_MACRLC_DL_MAX_MCS, 0, .u8ptr=NULL, .defintval=28, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER, HLP_MACRLC_UL_BLER_UP, 0, .dblptr=NULL, .defdblval=0.15, TYPE_DOUBLE, 0}, \ {CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER, HLP_MACRLC_UL_BLER_LO, 0, .dblptr=NULL, .defdblval=0.05, TYPE_DOUBLE, 0}, \ + {CONFIG_STRING_MACRLC_UL_MIN_MCS, HLP_MACRLC_UL_MIN_MCS, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_UL_MAX_MCS, HLP_MACRLC_UL_MAX_MCS, 0, .u8ptr=NULL, .defintval=28, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_DL_HARQ_ROUND_MAX, HLP_MACRLC_DL_HARQ_MAX, 0, .u8ptr=NULL, .defintval=4, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_UL_HARQ_ROUND_MAX, HLP_MACRLC_UL_HARQ_MAX, 0, .u8ptr=NULL, .defintval=4, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_MIN_GRANT_PRB, HLP_MACRLC_MIN_GRANT_PRB, 0, .u8ptr=NULL, .defintval=5, TYPE_UINT8, 0}, \ - {CONFIG_STRING_MACRLC_MIN_GRANT_MCS, HLP_MACRLC_MIN_GRANT_MCS, 0, .u8ptr=NULL, .defintval=9, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_IDENTITY_PM, HLP_MACRLC_IDENTITY_PM, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \ {CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \ @@ -170,23 +173,24 @@ #define MACRLC_PUSCHFAILURETHRES_IDX 20 #define MACRLC_DL_BLER_TARGET_UPPER_IDX 21 #define MACRLC_DL_BLER_TARGET_LOWER_IDX 22 -#define MACRLC_DL_MAX_MCS_IDX 23 -#define MACRLC_UL_BLER_TARGET_UPPER_IDX 24 -#define MACRLC_UL_BLER_TARGET_LOWER_IDX 25 -#define MACRLC_UL_MAX_MCS_IDX 26 -#define MACRLC_DL_HARQ_ROUND_MAX_IDX 27 -#define MACRLC_UL_HARQ_ROUND_MAX_IDX 28 -#define MACRLC_MIN_GRANT_PRB_IDX 29 -#define MACRLC_MIN_GRANT_MCS_IDX 30 -#define MACRLC_IDENTITY_PM_IDX 31 -#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 32 -#define MACRLC_TRANSPORT_S_SHM_PREFIX 33 -#define MACRLC_TRANSPORT_S_POLL_CORE 34 -#define MACRLC_ANALOG_BEAMFORMING_IDX 35 -#define MACRLC_ANALOG_BEAM_DURATION_IDX 36 -#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 37 -#define MACRLC_PUSCH_RSSI_THRES_IDX 38 -#define MACRLC_PUCCH_RSSI_THRES_IDX 39 +#define MACRLC_DL_MIN_MCS_IDX 23 +#define MACRLC_DL_MAX_MCS_IDX 24 +#define MACRLC_UL_BLER_TARGET_UPPER_IDX 25 +#define MACRLC_UL_BLER_TARGET_LOWER_IDX 26 +#define MACRLC_UL_MIN_MCS_IDX 27 +#define MACRLC_UL_MAX_MCS_IDX 28 +#define MACRLC_DL_HARQ_ROUND_MAX_IDX 29 +#define MACRLC_UL_HARQ_ROUND_MAX_IDX 30 +#define MACRLC_MIN_GRANT_PRB_IDX 31 +#define MACRLC_IDENTITY_PM_IDX 32 +#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 33 +#define MACRLC_TRANSPORT_S_SHM_PREFIX 34 +#define MACRLC_TRANSPORT_S_POLL_CORE 35 +#define MACRLC_ANALOG_BEAMFORMING_IDX 36 +#define MACRLC_ANALOG_BEAM_DURATION_IDX 37 +#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 38 +#define MACRLC_PUSCH_RSSI_THRES_IDX 39 +#define MACRLC_PUCCH_RSSI_THRES_IDX 40 #define MACRLCPARAMS_CHECK { \ { .s5 = { NULL } }, \ @@ -212,14 +216,15 @@ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s2 = { config_check_intrange, {0, 31} } }, /* DL min MCS */ \ + { .s2 = { config_check_intrange, {0, 31} } }, /* DL max MCS */ \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ + { .s2 = { config_check_intrange, {0, 31} } }, /* UL min MCS */ \ + { .s2 = { config_check_intrange, {0, 31} } }, /* UL max MCS */ \ { .s2 = { config_check_intrange, {1, 8} } }, /* DL max HARQ rounds */ \ { .s2 = { config_check_intrange, {1, 8} } }, /* UL max HARQ rounds */ \ { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ { .s2 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index deb8835157..cbb46f0132 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1141,7 +1141,7 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1; } else { css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; } css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; @@ -1312,7 +1312,7 @@ static f1ap_fdd_info_t read_fdd_config(const NR_ServingCellConfigCommon_t *scc) return fdd; } -f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1) +f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1, seq_arr_t *du_SIBs) { int buf_len = 3; f1ap_gnb_du_system_info_t *sys_info = calloc_or_fail(1, sizeof(*sys_info)); @@ -1329,15 +1329,24 @@ f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCC AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); sys_info->sib1_length = (enc_rval.encoded + 7) / 8; + if (du_SIBs) { + for (int i = 0; i < du_SIBs->size; i++) { + nr_SIBs_t *si = (nr_SIBs_t *)seq_arr_at(du_SIBs, i); + // other SIB in gNB-DU System Information not implemented yet + // only DU SIB not included in this message is SIB19 + AssertFatal(si->SIB_type == 19, "Cannot handle SIB%d in gNB-DU System Information\n", si->SIB_type); + } + } return sys_info; } -f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, +static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, const char *name, const f1ap_served_cell_info_t *info, const NR_ServingCellConfigCommon_t *scc, NR_BCCH_BCH_Message_t *mib, - const NR_BCCH_DL_SCH_Message_t *sib1) + const NR_BCCH_DL_SCH_Message_t *sib1, + seq_arr_t *du_SIBs) { f1ap_setup_req_t *req = calloc(1, sizeof(*req)); AssertFatal(req != NULL, "out of memory\n"); @@ -1381,7 +1390,7 @@ f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, if (IS_SA_MODE(get_softmodem_params())) { // in NSA we don't transmit SIB1, so cannot fill DU system information // so cannot send MIB either - req->cell[0].sys_info = get_sys_info(mib, sib1); + req->cell[0].sys_info = get_sys_info(mib, sib1, du_SIBs); } int num = read_version(TO_STRING(NR_RRC_VERSION), &req->rrc_ver[0], &req->rrc_ver[1], &req->rrc_ver[2]); @@ -1421,6 +1430,31 @@ static nr_redcap_config_t *get_redcap_config(int gnb_idx) return rc; } +static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray) +{ + if (NODE_IS_DU(get_node_type())) + AssertFatal(GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0, "This is DU, do not input CU SIBs\n"); + + if (!config_isparamset(GNBparamarray, GNB_DU_SIBS_IDX)) + return NULL; + + seq_arr_t *du_SIBs = malloc(sizeof(seq_arr_t)); + seq_arr_init(du_SIBs, sizeof(nr_SIBs_t)); + for (int i = 0; i < GNBparamarray[GNB_DU_SIBS_IDX].numelt; i++) { + int sib_value = GNBparamarray[GNB_DU_SIBS_IDX].iptr[i]; + // SIB10, SIB12, SIB13, SIB14, SIB15, SIB17, SIB18, SIB19 and SIB20 are generated by the DU + // all the rest in the DU + AssertFatal((sib_value > 9 && sib_value < 21) && sib_value != 11 && sib_value != 16, + "SIB%d is not a DU SIB, to be configured in DU section\n", + sib_value); + nr_SIBs_t *du_sib = calloc_or_fail(1, sizeof(nr_SIBs_t)); + du_sib->SIB_type = sib_value; + LOG_I(GNB_APP, "activate SIB%d at DU\n", sib_value); + seq_arr_push_back(du_SIBs, du_sib, sizeof(nr_SIBs_t)); + } + return du_SIBs; +} + void RCconfig_nr_macrlc(configmodule_interface_t *cfg) { int j = 0; @@ -1650,6 +1684,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler; dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr); dl_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr); + dl_bler_options->min_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MIN_MCS_IDX].u8ptr); dl_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr); if (config.disable_harq) dl_bler_options->harq_round_max = 1; @@ -1658,13 +1693,13 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) NR_bler_options_t *ul_bler_options = &RC.nrmac[j]->ul_bler; ul_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_UPPER_IDX].dblptr); ul_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_LOWER_IDX].dblptr); + ul_bler_options->min_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MIN_MCS_IDX].u8ptr); ul_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MAX_MCS_IDX].u8ptr); if (config.disable_harq) ul_bler_options->harq_round_max = 1; else ul_bler_options->harq_round_max = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_HARQ_ROUND_MAX_IDX].u8ptr); RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr); - RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr); RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr); // PRB Blacklist uint16_t prbbl[MAX_BWP_SIZE] = {0}; @@ -1692,17 +1727,18 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) f1ap_served_cell_info_t info; read_du_cell_info(cfg, NODE_IS_DU(node_type), &gnb_id, &gnb_du_id, &name, &info, 1); - if (IS_SA_MODE(get_softmodem_params())) { + NR_COMMON_channels_t *cc = &RC.nrmac[0]->common_channels[0]; + cc->du_SIBs = fill_du_sibs(GNBParamList.paramarray[0]); + + if (IS_SA_MODE(get_softmodem_params())) nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac); - if (scc->ext2 && scc->ext2->ntn_Config_r17) - nr_mac_configure_sib19(RC.nrmac[0]); - } // read F1 Setup information from config and generated MIB/SIB1 // and store it at MAC for sending later NR_BCCH_BCH_Message_t *mib = RC.nrmac[0]->common_channels[0].mib; const NR_BCCH_DL_SCH_Message_t *sib1 = RC.nrmac[0]->common_channels[0].sib1; - f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1); + seq_arr_t *du_SIBs = RC.nrmac[0]->common_channels[0].du_SIBs; + f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1, du_SIBs); AssertFatal(req != NULL, "could not read F1 Setup information\n"); RC.nrmac[0]->f1_config.setup_req = req; RC.nrmac[0]->f1_config.gnb_id = gnb_id; @@ -1846,6 +1882,31 @@ static int sort_neighbour_cell_config_by_cell_id(const void *a, const void *b) return 0; } +static seq_arr_t *fill_cu_sibs(paramdef_t *GNBparamarray) +{ + if (NODE_IS_CU(get_node_type())) + AssertFatal(GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0, "This is CU, do not input DU SIBs\n"); + + if (!config_isparamset(GNBparamarray, GNB_CU_SIBS_IDX)) + return NULL; + + seq_arr_t *SIBs = malloc(sizeof(seq_arr_t)); + seq_arr_init(SIBs, sizeof(nr_SIBs_t)); + for (int i = 0; i < GNBparamarray[GNB_CU_SIBS_IDX].numelt; i++) { + int sib_value = GNBparamarray[GNB_CU_SIBS_IDX].iptr[i]; + // SIB10, SIB12, SIB13, SIB14, SIB15, SIB17, SIB18, SIB19 and SIB20 are generated by the DU + // all the rest in the CU + AssertFatal((sib_value > 1 && sib_value < 10) || sib_value == 11 || sib_value == 16, + "SIB%d is not a CU SIB, to be configured in DU section\n", + sib_value); + nr_SIBs_t *cu_sib = calloc_or_fail(1, sizeof(*cu_sib)); + cu_sib->SIB_type = sib_value; + LOG_I(GNB_APP, "activate SIB%d at CU\n", sib_value); + seq_arr_push_back(SIBs, cu_sib, sizeof(nr_SIBs_t)); + } + return SIBs; +} + static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc) { char gnbpath[MAX_OPTNAME_SIZE + 8]; @@ -2085,6 +2146,8 @@ gNB_RRC_INST *RCconfig_NRRRC() fill_measurement_configuration(k, rrc); + rrc->SIBs = fill_cu_sibs(GNBParamList.paramarray[i]); + paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC; paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0}; diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index baf4ad5d94..f9d23ccba4 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -95,14 +95,8 @@ gNB_RRC_INST *RCconfig_NRRRC(); int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i); int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i); void wait_f1_setup_response(void); -f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, - const char *name, - const f1ap_served_cell_info_t *info, - const NR_ServingCellConfigCommon_t *scc, - NR_BCCH_BCH_Message_t *mib, - const NR_BCCH_DL_SCH_Message_t *sib1); f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc); -f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1); +f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1, seq_arr_t *du_SIBs); int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); MessageDef *RCconfig_NR_CU_E1(const E1_t *entity); ngran_node_t get_node_type(void); diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 7f7fccbd8f..c76b6bc143 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -139,6 +139,8 @@ typedef enum { #define GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES "num_ulharq" #define GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST "beam_weights" #define GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST "uess_agg_levels" +#define GNB_CONFIG_STRING_CU_SIB_LIST "cu_sibs" +#define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs" #define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n" #define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support" @@ -150,6 +152,8 @@ typedef enum { #define GNB_CONFIG_HLP_NUM_DL_HARQ "Set Num DL harq processes. Valid values 2,4,6,8,10,12,16,32. Default 16" #define GNB_CONFIG_HLP_NUM_UL_HARQ "Set Num UL harq processes. Valid values 16,32. Default 16" #define GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST "List of aggregation levels with number of candidates per level. Element 0 - aggregation level 1" +#define GNB_CONFIG_HLP_CU_SIBS "List of CU generated SIBs to be transmitted" +#define GNB_CONFIG_HLP_DU_SIBS "List of DU generated SIBs to be transmitted" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ @@ -195,6 +199,8 @@ typedef enum { {GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ {GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST, \ GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST, 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \ +{GNB_CONFIG_STRING_CU_SIB_LIST, GNB_CONFIG_HLP_CU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ +{GNB_CONFIG_STRING_DU_SIB_LIST, GNB_CONFIG_HLP_DU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ } // clang-format on @@ -236,6 +242,8 @@ typedef enum { #define GNB_NUM_UL_HARQ_IDX 34 #define GNB_BEAMWEIGHTS_IDX 35 #define GNB_UESS_AGG_LEVEL_LIST_IDX 36 +#define GNB_CU_SIBS_IDX 37 +#define GNB_DU_SIBS_IDX 38 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32} @@ -279,6 +287,8 @@ typedef enum { { .s1 = { config_check_intval, NUM_UL_HARQ_OKVALUES,2 } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ } /*-------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 38b65a8158..44c6673f2f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1505,6 +1505,74 @@ void find_aggregation_candidates(uint8_t *aggregation_level, } } +void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset) +{ + switch(ss->monitoringSlotPeriodicityAndOffset->present) { + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1: + *period = 1; + *offset = 0; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2: + *period = 2; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4: + *period = 4; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5: + *period = 5; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8: + *period = 8; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10: + *period = 10; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16: + *period = 16; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20: + *period = 20; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40: + *period = 40; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80: + *period = 80; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160: + *period = 160; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320: + *period = 320; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640: + *period = 640; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280: + *period = 1280; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280; + break; + case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560: + *period = 2560; + *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560; + break; + default: + AssertFatal(1==0,"Invalid monitoring slot periodicity value\n"); + break; + } +} void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss, uint16_t period, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 487e81ac40..8e0e57d3a6 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -213,6 +213,7 @@ uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx); uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx); uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset); +void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset); uint32_t nr_compute_tbslbrm(uint16_t table, uint16_t nb_rb, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 1b5518f0bc..46e126ed97 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -936,10 +936,7 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source) target->intraFreqReselection = source->intraFreqReselection; } -void nr_rrc_mac_config_req_mib(module_id_t module_id, - int cc_idP, - NR_MIB_t *mib, - int sched_sib) +void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -952,8 +949,8 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, mac->phy_config.CC_id = cc_idP; if (sched_sib == 1) mac->get_sib1 = true; - else if (sched_sib == 2) - mac->get_otherSI = true; + else if (sched_sib > 1) + mac->get_otherSI[sched_sib - 2] = true; nr_ue_decode_mib(mac, cc_idP); ret = pthread_mutex_unlock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 838d1989f0..3241235bd3 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -539,7 +539,7 @@ typedef struct NR_UE_MAC_INST_s { int servCellIndex; long physCellId; bool get_sib1; - bool get_otherSI; + bool get_otherSI[MAX_SI_GROUPS]; NR_MIB_t *mib; si_schedInfo_t si_SchedInfo; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index a2b2e0f777..693ce4eb5a 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -68,12 +68,12 @@ void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch); \param sibs_mask sibs mask \param pduP pointer to pdu \param pdu_length length of pdu */ -int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, - int cc_id, - unsigned int gNB_index, - uint8_t ack_nack, - uint8_t *pduP, - uint32_t pdu_len); +void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, + int cc_id, + unsigned int gNB_index, + uint8_t ack_nack, + uint8_t *pduP, + uint32_t pdu_len); void release_dl_BWP(NR_UE_MAC_INST_t *mac, int index); void release_ul_BWP(NR_UE_MAC_INST_t *mac, int index); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 6c744e8275..1ca4168b6f 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -56,7 +56,8 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id); nr_ue_reset_sync_state(mac); mac->get_sib1 = false; - mac->get_otherSI = false; + for (int i = 0; i < MAX_SI_GROUPS; i++) + mac->get_otherSI[i] = false; memset(&mac->phy_config, 0, sizeof(mac->phy_config)); mac->si_SchedInfo.si_window_start = -1; mac->servCellIndex = 0; 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 8457cad135..34ef533884 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -343,76 +343,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, dl_config->number_pdus += 1; } - -void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset) -{ - switch(ss->monitoringSlotPeriodicityAndOffset->present) { - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1: - *period = 1; - *offset = 0; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2: - *period = 2; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4: - *period = 4; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5: - *period = 5; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8: - *period = 8; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10: - *period = 10; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16: - *period = 16; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20: - *period = 20; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40: - *period = 40; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80: - *period = 80; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160: - *period = 160; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320: - *period = 320; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640: - *period = 640; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280: - *period = 1280; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560: - *period = 2560; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560; - break; - default: - AssertFatal(1==0,"Invalid monitoring slot periodicity value\n"); - break; - } -} - bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss) { if (!ss) @@ -445,7 +375,6 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac, if (((frame * slots_per_frame + slot - offset - i) % period) == 0) { int N = mac->ssb_list.nb_tx_ssb; int K = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb]; - // numbering current frame and slot in terms of monitoring occasions in window int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start; int current_monitor_occasion = (rel_slot % period) + (duration * rel_slot / period); @@ -469,44 +398,41 @@ bool is_window_valid(NR_UE_MAC_INST_t *mac, int window_slots, int abs_slot) return true; } -bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac, - const NR_SearchSpace_t *ss, - const int slots_per_frame, - const int frame, - const int slot) +static bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac, + const NR_SearchSpace_t *ss, + const int si_idx, + const int slots_per_frame, + const int frame, + const int slot) { // according to 5.2.2.3.2 in 331 const int abs_slot = frame * slots_per_frame + slot; - for (int i = 0; i < mac->si_SchedInfo.si_SchedInfo_list.count; i++) { - si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[i]; - int window_slots = 5 << mac->si_SchedInfo.si_WindowLength; - int x = (config->si_WindowPosition - 1) * window_slots; - int T = 8 << config->si_Periodicity; // radio frame periodicity - bool check_valid; - switch (config->type) { - case NR_SI_INFO : - if (mac->si_SchedInfo.si_window_start == -1) { - if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0)) - mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number - } - check_valid = is_window_valid(mac, window_slots, abs_slot); - if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame)) - return true; - break; - case NR_SI_INFO_v1700 : - if (mac->si_SchedInfo.si_window_start == -1) { - if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame)) - mac->si_SchedInfo.si_window_start = abs_slot; - } - window_slots = 10; // TODO window length hardcoded to 10 at gNB for NTN - check_valid = is_window_valid(mac, window_slots, abs_slot); - if (check_valid && (config->si_WindowPosition - 1) == slot) - return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame); - break; - default : - AssertFatal(false, "Invalid SI-SchedulingInfo case\n"); - } + si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[si_idx]; + int window_slots = 5 << mac->si_SchedInfo.si_WindowLength; + int x = (config->si_WindowPosition - 1) * window_slots; + int T = 8 << config->si_Periodicity; // radio frame periodicity + bool check_valid; + switch (config->type) { + case NR_SI_INFO : + if (mac->si_SchedInfo.si_window_start == -1) { + if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0)) + mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number + } + check_valid = is_window_valid(mac, window_slots, abs_slot); + if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame)) + return true; + break; + case NR_SI_INFO_v1700 : + if (mac->si_SchedInfo.si_window_start == -1) { + if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame)) + mac->si_SchedInfo.si_window_start = abs_slot; + } + if (is_window_valid(mac, window_slots, abs_slot)) + return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame); + break; + default : + AssertFatal(false, "Invalid SI-SchedulingInfo case\n"); } return false; } @@ -549,13 +475,15 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, mac->search_space_zero); } } - if (mac->get_otherSI) { + for (int i = 0; i < MAX_SI_GROUPS; i++) { + if (!mac->get_otherSI[i]) + continue; // If searchSpaceOtherSystemInformation is set to zero, // PDCCH monitoring occasions for SI message reception in SI-window // are same as PDCCH monitoring occasions for SIB1 const NR_SearchSpace_t *ss = pdcch_config->otherSI_SS ? pdcch_config->otherSI_SS : mac->search_space_zero; // TODO configure SI-window - if (monitor_dci_for_other_SI(mac, ss, slots_per_frame, frame, slot)) { + if (monitor_dci_for_other_SI(mac, ss, i, slots_per_frame, frame, slot)) { LOG_D(NR_MAC_DCI, "Monitoring DCI for other SIs in frame %d slot %d\n", frame, slot); config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 20745a5e25..572202d044 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -300,18 +300,22 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc } } -int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, - int cc_id, - unsigned int gNB_index, - uint8_t ack_nack, - uint8_t *pduP, - uint32_t pdu_len) +void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, + int cc_id, + unsigned int gNB_index, + uint8_t ack_nack, + uint8_t *pduP, + uint32_t pdu_len) { if(ack_nack) { LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); - mac->get_sib1 = false; - mac->get_otherSI = false; + if (mac->get_sib1) + mac->get_sib1 = false; + for (int i = 0; i < MAX_SI_GROUPS; i++) { + if (mac->get_otherSI[i]) + mac->get_otherSI[i] = false; + } T(T_NRUE_MAC_DL_PDU_WITH_DATA, T_INT(SI_RNTI), T_INT(-1 /* frame, unavailable here */), @@ -319,9 +323,10 @@ int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, T_INT(0 /* harq_pid */), T_BUFFER(pduP, pdu_len)); } - else + else { LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI"); - return 0; + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0); + } } /* @@ -742,8 +747,10 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } + dlsch_pdu->rb_offset = dlsch_pdu->start_rb + dlsch_pdu->BWPStart; - if (mac->get_sib1 || mac->get_otherSI) + + if (mac->get_sib1) dlsch_pdu->rb_offset -= dlsch_pdu->BWPStart; /* TIME_DOM_RESOURCE_ASSIGNMENT */ @@ -2993,7 +3000,7 @@ static void extract_10_ra_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc EXTRACT_DCI_ITEM(dci_pdu_rel15->tb_scaling, 2); } -static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB) +static uint8_t extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB) { LOG_D(NR_MAC_DCI, "Received dci 1_0 SI rnti\n"); @@ -3009,6 +3016,7 @@ static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2); // System information indicator 1 bit EXTRACT_DCI_ITEM(dci_pdu_rel15->system_info_indicator, 1); + return dci_pdu_rel15->system_info_indicator; } static bool extract_10_c_rnti(NR_UE_MAC_INST_t *mac, @@ -3312,7 +3320,10 @@ static nr_dci_format_t nr_extract_dci_00_10(NR_UE_MAC_INST_t *mac, n_RB = get_nrb_for_dci(mac, format, ss_type); if (n_RB == 0) return NR_DCI_NONE; - extract_10_si_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB); + uint8_t sys_info = extract_10_si_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB); + // sys info = 0 for SIB1 and 1 for other SIB + if (mac->get_sib1 == 0 && sys_info == 0) + return NR_DCI_NONE; break; case TYPE_C_RNTI_ : // Identifier for DCI formats diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 19efd1d401..26319a6049 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -38,6 +38,7 @@ #include "BIT_STRING.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include "GNB_APP/gnb_config.h" #include "NR_MIB.h" #include "NR_MAC_gNB/nr_mac_gNB.h" #include "NR_BCCH-BCH-Message.h" @@ -863,30 +864,98 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c NR_RA_t *ra = &cc->ra[n]; nr_clear_ra_proc(ra); } - - nr_fill_sched_osi(nrmac, scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon); NR_SCHED_UNLOCK(&nrmac->sched_lock); if (IS_SA_MODE(get_softmodem_params())) config_sched_ctrlCommon(nrmac); } -void nr_fill_sched_osi(gNB_MAC_INST *nrmac, const struct NR_SetupRelease_PDCCH_ConfigCommon *pdcch_ConfigCommon) +bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]) { - NR_SearchSpaceId_t *osi_SearchSpace = pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation; - if (osi_SearchSpace) { - nrmac->sched_osi = CALLOC(1, sizeof(*nrmac->sched_osi)); + NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; + seq_arr_t *du_SIBs = nrmac->common_channels[0].du_SIBs; + int num_du_sib = 0; + if (du_SIBs) + num_du_sib = du_SIBs->size; + if (num_cu_sib + num_du_sib == 0) + return false; /* no updates */ - struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = - pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); - for (int i = 0; i < commonSearchSpaceList->list.count; i++) { - NR_SearchSpace_t *ss = commonSearchSpaceList->list.array[i]; - if (ss->searchSpaceId == *osi_SearchSpace) - nrmac->sched_osi->search_space = ss; + int config_sibs[num_cu_sib + num_du_sib]; + NR_SystemInformation_IEs_t *sysInfo = calloc(1, sizeof(*sysInfo)); //for SIB up to 14 included + NR_SystemInformation_IEs_t *sysInfov17 = calloc(1, sizeof(*sysInfov17)); // for othersibs + for (int i = 0; i < num_cu_sib; i++) { + config_sibs[i] = cu_sib[i].SI_type; + switch (config_sibs[i]) { + case 2: { + struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type = calloc(1, sizeof(*type)); + type->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2; + // SIB2 coming from CU need to decode it + NR_SIB2_t *sib2 = NULL; + asn_dec_rval_t dec_rval = uper_decode(NULL, + &asn_DEF_NR_SIB2, + (void **)&sib2, + cu_sib[i].SI_container, + cu_sib[i].SI_container_length, + 0, + 0); + if (dec_rval.code != RC_OK) { + LOG_E(NR_MAC, "cannot decode SIB%d from CU\n", config_sibs[i]); + ASN_STRUCT_FREE(asn_DEF_NR_SIB2, cu_sib[i].SI_container); + } + type->choice.sib2 = sib2; + add_sib_to_systeminformation(sysInfo, type); + break; + } + default : + AssertFatal(false, "Invalid or not supported SIB%d\n", config_sibs[i]); } - AssertFatal(nrmac->sched_osi->search_space != NULL, "SearchSpace cannot be null for OSI\n"); } + + for (int i = 0; i < num_du_sib; i++) { + nr_SIBs_t *si = (nr_SIBs_t *)seq_arr_at(du_SIBs, i); + int sib_idx = i + num_cu_sib; + config_sibs[sib_idx] = si->SIB_type; + switch (config_sibs[sib_idx]) { + case 19: { + struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type_du = calloc(1, sizeof(*type_du)); + type_du->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700; + NR_SIB19_r17_t *sib19 = get_SIB19_NR(cc->ServingCellConfigCommon); + type_du->choice.sib19_v1700 = sib19; + add_sib_to_systeminformation(sysInfov17, type_du); + break; + } + default : + AssertFatal(false, "Invalid or not supported SIB%d\n", sib_idx); + } + } + + update_SIB1_NR_SI(cc->sib1, num_cu_sib + num_du_sib, config_sibs); + cc->sib1_bcch_length = encode_SIB_NR(cc->sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu)); + AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n"); + + // generate otherSIB payloads + cc->other_sib_bcch_length[0] = encode_sysinfo_ie(sysInfo, cc->other_sib_bcch_pdu[0], sizeof(cc->other_sib_bcch_pdu[0])); + cc->other_sib_bcch_length[1] = encode_sysinfo_ie(sysInfov17, cc->other_sib_bcch_pdu[1], sizeof(cc->other_sib_bcch_pdu[1])); + + ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfo); + ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfov17); + return true; +} + +void prepare_du_configuration_update(gNB_MAC_INST *mac, + f1ap_served_cell_info_t *info, + NR_BCCH_BCH_Message_t *mib, + const NR_BCCH_DL_SCH_Message_t *sib1) +{ + /* send gNB-DU configuration update to RRC */ + f1ap_gnb_du_configuration_update_t update = { + .transaction_id = 1, + .num_cells_to_modify = 1, + }; + update.cell_to_modify[0].old_nr_cellid = info->nr_cellid; + update.cell_to_modify[0].info = *info; + update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1, NULL); + mac->mac_rrc.gnb_du_configuration_update(&update); } void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_t cellID, int tac) @@ -897,21 +966,10 @@ void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_ NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, plmn, cellID, tac, &nrmac->radio_config); cc->sib1 = sib1; - cc->sib1_bcch_length = encode_SIB1_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu)); + cc->sib1_bcch_length = encode_SIB_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu)); AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n"); } -void nr_mac_configure_sib19(gNB_MAC_INST *nrmac) -{ - AssertFatal(IS_SA_MODE(get_softmodem_params()), "error: SIB19 only applicable for SA\n"); - NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_BCCH_DL_SCH_Message_t *sib19 = get_SIB19_NR(scc); - cc->sib19 = sib19; - cc->sib19_bcch_length = encode_SIB19_NR(sib19, cc->sib19_bcch_pdu, sizeof(cc->sib19_bcch_pdu)); - AssertFatal(cc->sib19_bcch_length > 0, "could not encode SIB19\n"); -} - bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) { /* ideally, instead of this function, "users" of this function should call diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 65928fbea3..e14004edc3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -219,8 +219,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo // SIB19 will be scheduled if ntn_Config_r17 is initialized if (IS_SA_MODE(get_softmodem_params())) { schedule_nr_sib1(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); - if (cc->sib19) - schedule_nr_sib19(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req, cc->sib19_bcch_length, cc->sib19_bcch_pdu); + schedule_nr_other_sib(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); } // This schedule PRACH if we are not in phy_test mode diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 147b8abc6c..017dc3cd4f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -878,7 +878,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; ul_dci_req->numPdus += 1; - nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch, false); + nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch); nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; } @@ -1250,81 +1250,11 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } - -static void find_monitoring_periodicity_offset_common(const NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset) -{ - switch (ss->monitoringSlotPeriodicityAndOffset->present) { - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1: - *slot_period = 1; - *offset = 0; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2: - *slot_period = 2; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4: - *slot_period = 4; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5: - *slot_period = 5; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8: - *slot_period = 8; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10: - *slot_period = 10; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16: - *slot_period = 16; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20: - *slot_period = 20; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40: - *slot_period = 40; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80: - *slot_period = 80; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160: - *slot_period = 160; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320: - *slot_period = 320; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640: - *slot_period = 640; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280: - *slot_period = 1280; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280; - break; - case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560: - *slot_period = 2560; - *offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560; - break; - default: - AssertFatal(1 == 0, "Invalid monitoring slot periodicity and offset value\n"); - break; - } -} - static bool check_msg2_monitoring(const NR_RA_t *ra, int slots_per_frame, int current_frame, int current_slot) { // check if the slot is not among the PDCCH monitored ones (38.213 10.1) - uint16_t monitoring_slot_period, monitoring_offset; - find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset); + int monitoring_slot_period, monitoring_offset; + get_monitoring_period_offset(ra->ra_ss, &monitoring_slot_period, &monitoring_offset); if ((current_frame * slots_per_frame + current_slot - monitoring_offset) % monitoring_slot_period != 0) return false; return true; @@ -1432,7 +1362,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch, false); + nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch); nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 32647cbe65..71ebc7d8a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -274,76 +274,75 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi } } -uint32_t get_tbs(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - NR_sched_pdsch_t *pdsch, - uint32_t num_total_bytes, - uint16_t *vrb_map) +static uint32_t get_tbs_bch(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + NR_sched_pdsch_t *pdsch, + uint32_t num_total_bytes, + uint16_t *vrb_map) { NR_tda_info_t *tda_info = &pdsch->tda_info; - const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs; - int rbStart = type0_PDCCH_CSS_config->cset_start_rb; - // Calculate number of PRB_DMRS uint8_t N_PRB_DMRS = pdsch->dmrs_parms.N_PRB_DMRS; - uint16_t dmrs_length = pdsch->dmrs_parms.N_DMRS_SLOT; LOG_D(MAC, "dlDmrsSymbPos %x\n", pdsch->dmrs_parms.dl_dmrs_symb_pos); int mcsTableIdx = 0; - int rbSize = 0; uint32_t TBS = 0; - do { - if (rbSize < bwpSize && !(vrb_map[rbStart + rbSize] & SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols))) - rbSize++; + const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); + int bwpSize = type0_PDCCH_CSS_config->num_rbs; + int bwpStart = type0_PDCCH_CSS_config->cset_start_rb; + int rbStop = bwpSize - 1; + int rbStart = 0; + uint16_t rbSize = 0; + while (rbStart < rbStop) { + if (vrb_map[rbStart + bwpStart] & slbitmap) + rbStart++; else { - if (pdsch->mcs < 10) - pdsch->mcs++; - else - break; - } - TBS = nr_compute_tbs(nr_get_Qm_dl(pdsch->mcs, mcsTableIdx), - nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx), - rbSize, - tda_info->nrOfSymbols, - N_PRB_DMRS * dmrs_length, - 0, - 0, - 1) - >> 3; - } while (TBS < num_total_bytes); + int max_rbSize = 0; + while (rbStart + max_rbSize <= rbStop && !(vrb_map[rbStart + max_rbSize + bwpStart] & slbitmap)) + max_rbSize++; - if (TBS < num_total_bytes) { - for (int rb = 0; rb < bwpSize; rb++) - LOG_I(NR_MAC, "vrb_map[%d] %x\n", rbStart + rb, vrb_map[rbStart + rb]); + bool res = false; + while (res == false && pdsch->mcs < 10) { + res = nr_find_nb_rb(nr_get_Qm_dl(pdsch->mcs, mcsTableIdx), + nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx), + 1, // no transform precoding for DL + 1, // single layer + tda_info->nrOfSymbols, + pdsch->dmrs_parms.N_PRB_DMRS * pdsch->dmrs_parms.N_DMRS_SLOT, + num_total_bytes, + 1, // min_rbSize + max_rbSize, + &TBS, + &rbSize); + if (!res) + pdsch->mcs++; + } + break; + } } - AssertFatal( - TBS >= num_total_bytes, - "Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d SLmask %x - [%d,%d])\n", - num_total_bytes, - rbStart, - rbSize, - bwpSize, - SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols), - tda_info->startSymbolIndex, - tda_info->nrOfSymbols); + AssertFatal(TBS >= num_total_bytes, + "Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d)\n", + num_total_bytes, + rbStart, + rbSize, + bwpSize); pdsch->rbSize = rbSize; - pdsch->rbStart = 0; + pdsch->rbStart = rbStart; - LOG_D( - NR_MAC, - "mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n", - pdsch->mcs, - tda_info->startSymbolIndex, - tda_info->nrOfSymbols, - pdsch->rbSize, - TBS, - dmrs_length, - N_PRB_DMRS, - tda_info->mapping_type); + LOG_D(NR_MAC, + "mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n", + pdsch->mcs, + tda_info->startSymbolIndex, + tda_info->nrOfSymbols, + rbSize, + TBS, + pdsch->dmrs_parms.N_DMRS_SLOT, + N_PRB_DMRS, + tda_info->mapping_type); return TBS; } -static uint32_t schedule_control_sib1(module_id_t module_id, +static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, int CC_id, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, int time_domain_allocation, @@ -353,7 +352,6 @@ static uint32_t schedule_control_sib1(module_id_t module_id, int beam, uint16_t num_total_bytes) { - gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n"); NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; uint16_t *vrb_map = cc->vrb_map[beam]; @@ -382,7 +380,10 @@ static uint32_t schedule_control_sib1(module_id_t module_id, AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n"); - uint32_t TBS = get_tbs(type0_PDCCH_CSS_config, &gNB_mac->sched_ctrlCommon->sched_pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map); + uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config, + &gNB_mac->sched_ctrlCommon->sched_pdsch, + gNB_mac->sched_ctrlCommon->num_total_bytes, + vrb_map); // Mark the corresponding RBs as used fill_pdcch_vrb_map(gNB_mac, @@ -397,92 +398,22 @@ static uint32_t schedule_control_sib1(module_id_t module_id, return TBS; } -static uint32_t schedule_control_other_si(module_id_t module_id, - int CC_id, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - NR_pdsch_dmrs_t *dmrs_parms, - NR_tda_info_t *tda_info, - uint8_t candidate_idx, - int beam, - uint16_t num_total_bytes) +static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, + NR_sched_pdsch_t *pdsch, + NR_sched_pdcch_t *pdcch, + NR_SearchSpace_t *search_space, + NR_ControlResourceSet_t *coreset, + int aggregation_level, + int cce_index, + nfapi_nr_dl_tti_request_body_t *dl_req, + int pdu_index, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + uint32_t TBS, + int StartSymbolIndex, + int NrOfSymbols, + bool is_sib1, + int beam_index) { - gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; - NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - uint16_t *vrb_map = cc->vrb_map[beam]; - - if (!gNB_mac->sched_osi->coreset) { - gNB_mac->sched_osi->coreset = - get_coreset(gNB_mac, scc, NULL, gNB_mac->sched_osi->search_space, NR_SearchSpace__searchSpaceType_PR_common); - gNB_mac->sched_osi->sched_pdcch = - set_pdcch_structure(NULL, gNB_mac->sched_osi->search_space, gNB_mac->sched_osi->coreset, scc, NULL, type0_PDCCH_CSS_config); - } - - NR_sched_pdsch_t *pdsch = &gNB_mac->sched_osi->sched_pdsch; - pdsch->time_domain_allocation = time_domain_allocation; - pdsch->dmrs_parms = *dmrs_parms; - pdsch->tda_info = *tda_info; - pdsch->mcs = 0; // starting from mcs 0 - gNB_mac->sched_osi->num_total_bytes = num_total_bytes; - - uint8_t nr_of_candidates; - - for (int i = 0; i < 3; i++) { - find_aggregation_candidates(&gNB_mac->sched_osi->aggregation_level, - &nr_of_candidates, - gNB_mac->sched_ctrlCommon->search_space, - 4 << i); - if (nr_of_candidates > 0) - break; // choosing the lower value of aggregation level available - } - AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n"); - gNB_mac->sched_osi->cce_index = find_pdcch_candidate(gNB_mac, - CC_id, - gNB_mac->sched_osi->aggregation_level, - nr_of_candidates, - beam, - &gNB_mac->sched_osi->sched_pdcch, - gNB_mac->sched_osi->coreset, - 0); - - AssertFatal(gNB_mac->sched_osi->cce_index >= 0, "Could not find CCE for coreset0\n"); - - // Calculate number of PRB_DMRS - uint32_t TBS = get_tbs(type0_PDCCH_CSS_config, &gNB_mac->sched_osi->sched_pdsch, gNB_mac->sched_osi->num_total_bytes, vrb_map); - // Mark the corresponding RBs as used - fill_pdcch_vrb_map(gNB_mac, - CC_id, - &gNB_mac->sched_osi->sched_pdcch, - gNB_mac->sched_osi->cce_index, - gNB_mac->sched_osi->aggregation_level, - beam); - for (int rb = 0; rb < pdsch->rbSize; rb++) { - vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); - } - return TBS; -} - -static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP, - NR_UE_sched_osi_ctrl_t *sched_osi, - NR_UE_sched_ctrl_t *sched_ctrlCommon, - nfapi_nr_dl_tti_request_body_t *dl_req, - int pdu_index, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - uint32_t TBS, - int StartSymbolIndex, - int NrOfSymbols, - int beam_index) -{ - // will set data according to SIB type (SIB1/OtherSI) - NR_sched_pdsch_t *pdsch = (sched_ctrlCommon ? &sched_ctrlCommon->sched_pdsch : &sched_osi->sched_pdsch); - NR_sched_pdcch_t *pdcch = (sched_ctrlCommon ? &sched_ctrlCommon->sched_pdcch : &sched_osi->sched_pdcch); - NR_SearchSpace_t *search_space = (sched_ctrlCommon ? sched_ctrlCommon->search_space : sched_osi->search_space); - NR_ControlResourceSet_t *coreset = (sched_ctrlCommon ? sched_ctrlCommon->coreset : sched_osi->coreset); - uint8_t aggregation_level = (sched_ctrlCommon ? sched_ctrlCommon->aggregation_level : sched_osi->aggregation_level); - int cce_index = (sched_ctrlCommon ? sched_ctrlCommon->cce_index : sched_osi->cce_index); - - gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; NR_COMMON_channels_t *cc = gNB_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; int mcsTableIdx = 0; @@ -493,10 +424,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP, dl_tti_pdcch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(pdcch_pdu_rel15, - coreset, - pdcch, - sched_ctrlCommon ? false : true); + nr_configure_pdcch(pdcch_pdu_rel15, coreset, pdcch); nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset(dl_tti_pdsch_pdu, 0, sizeof(*dl_tti_pdcch_pdu)); @@ -532,7 +460,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP, pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = 1; pdsch_pdu_rel15->transmissionScheme = 0; - pdsch_pdu_rel15->refPoint = 1; + pdsch_pdu_rel15->refPoint = is_sib1; pdsch_pdu_rel15->dmrsConfigType = 0; pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; pdsch_pdu_rel15->SCID = 0; @@ -598,7 +526,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP, dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0; dci_payload.antenna_ports.val = 0; dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; - dci_payload.system_info_indicator = sched_ctrlCommon ? 0 : 1; + dci_payload.system_info_indicator = is_sib1 ? 0 : 1; int dci_format = NR_DL_DCI_FORMAT_1_0; int rnti_type = TYPE_SI_RNTI_; @@ -696,7 +624,8 @@ void schedule_nr_sib1(module_id_t module_idP, NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; // Configure sched_ctrlCommon for SIB1 - uint32_t TBS = schedule_control_sib1(module_idP, CC_id, + uint32_t TBS = schedule_control_sib1(gNB_mac, + CC_id, type0_PDCCH_CSS_config, time_domain_allocation, &dmrs_parms, @@ -707,17 +636,21 @@ void schedule_nr_sib1(module_id_t module_idP, nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; int pdu_index = gNB_mac->pdu_index[0]++; - LOG_D(NR_MAC, "%s() %4d.%2d\n", __func__, frameP, slotP); - nr_fill_nfapi_dl_SIB_pdu(module_idP, - NULL, - gNB_mac->sched_ctrlCommon, - dl_req, - pdu_index, - type0_PDCCH_CSS_config, - TBS, - tda_info.startSymbolIndex, - tda_info.nrOfSymbols, - beam_index); + nr_fill_nfapi_dl_SIB_pdu(gNB_mac, + &gNB_mac->sched_ctrlCommon->sched_pdsch, + &gNB_mac->sched_ctrlCommon->sched_pdcch, + gNB_mac->sched_ctrlCommon->search_space, + gNB_mac->sched_ctrlCommon->coreset, + gNB_mac->sched_ctrlCommon->aggregation_level, + gNB_mac->sched_ctrlCommon->cce_index, + dl_req, + pdu_index, + type0_PDCCH_CSS_config, + TBS, + tda_info.startSymbolIndex, + tda_info.nrOfSymbols, + true, + beam_index); const int ntx_req = TX_req->Number_of_PDUs; nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; @@ -762,133 +695,227 @@ struct NR_SchedulingInfo2_r17 *find_sib19_sched_info(const struct NR_SI_Scheduli return NULL; } -void schedule_nr_sib19(module_id_t module_idP, - frame_t frameP, - slot_t slotP, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req, - int sib19_bcch_length, - uint8_t *sib19_bcch_pdu) +static void other_sib_sched_control(module_id_t module_idP, + frame_t frame, + slot_t slot, + int beam_index, + NR_SearchSpace_t *ss, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req, + int payload_idx) { - /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ - - const int CC_id = 0; - uint8_t candidate_idx = 0; - gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; - NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; + NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon; + int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame; + NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, beam_index, n_slots_frame); + AssertFatal(beam.idx >= 0, "Cannot allocate otherSIB corresponding for SSB number %d in any available beam\n", beam_index); + LOG_D(NR_MAC, "(%d.%d) otherSIB payload %d transmission for ssb number %d\n", frame, slot, payload_idx, beam_index); + NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[cc->ssb_index[beam_index]]; + AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n"); + NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup; + int time_domain_allocation = 1; + NR_tda_info_t tda_info = set_tda_info_from_list(pdsch_ConfigCommon->pdsch_TimeDomainAllocationList, time_domain_allocation); + LOG_D(NR_MAC,"tda_info.startSymbolIndex: %d, tda_info.nrOfSymbols: %d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols); - // there is no reason to execute further if sched_osi not initialized - if (!gNB_mac->sched_osi) - return; + NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1); - // get sib19 scheduling info from sib1 - struct NR_SI_SchedulingInfo_v1700 *si_schedulinginfo2_r17 = cc->sib1->message.choice.c1->choice.systemInformationBlockType1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->si_SchedulingInfo_v1700; - if (!si_schedulinginfo2_r17) { - LOG_E(GNB_APP, "SIB1 does not contain si_SchedulingInfo_v1700\n"); - return; + uint8_t aggregation_level = 0; + uint8_t nr_of_candidates = 0; + for (int i = 0; i < 5; i++) { + find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 16 >> i); + if (nr_of_candidates > 0) + break; // choosing the higher value of aggregation level available } - struct NR_SchedulingInfo2_r17 *sib19_sched_info = find_sib19_sched_info(si_schedulinginfo2_r17); - if (!sib19_sched_info) { - LOG_D(GNB_APP, "SIB1 does not contain scheduling info for SIB19\n"); + AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n"); + NR_ControlResourceSet_t *coreset = get_coreset(gNB_mac, scc, NULL, ss, NR_SearchSpace__searchSpaceType_PR_common); + if (!gNB_mac->sched_pdcch_otherSI) { + gNB_mac->sched_pdcch_otherSI = calloc(1, sizeof(*gNB_mac->sched_pdcch_otherSI)); + *gNB_mac->sched_pdcch_otherSI = set_pdcch_structure(gNB_mac, ss, coreset, scc, NULL, type0_PDCCH_CSS_config); + } + int cce_index = find_pdcch_candidate(gNB_mac, + 0, + aggregation_level, + nr_of_candidates, + beam.idx, + gNB_mac->sched_pdcch_otherSI, + coreset, + 0); + + AssertFatal(cce_index >= 0, "Could not find CCE for otherSIB DCI\n"); + + // Mark the corresponding RBs as used + fill_pdcch_vrb_map(gNB_mac, 0, gNB_mac->sched_pdcch_otherSI, cce_index, aggregation_level, beam.idx); + + NR_sched_pdsch_t sched_pdsch_otherSI = {0}; + sched_pdsch_otherSI.time_domain_allocation = time_domain_allocation; + sched_pdsch_otherSI.dmrs_parms = dmrs_parms; + sched_pdsch_otherSI.tda_info = tda_info; + sched_pdsch_otherSI.mcs = 0; // starting from mcs 0 + + uint16_t *vrb_map = cc->vrb_map[beam.idx]; + uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx]; + int num_total_bytes = cc->other_sib_bcch_length[payload_idx]; + uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config, &sched_pdsch_otherSI, num_total_bytes, vrb_map); + + for (int rb = 0; rb < sched_pdsch_otherSI.rbSize; rb++) { + vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); + } + + int pdu_index = gNB_mac->pdu_index[0]++; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; + nr_fill_nfapi_dl_SIB_pdu(gNB_mac, + &sched_pdsch_otherSI, + gNB_mac->sched_pdcch_otherSI, + ss, + coreset, + aggregation_level, + cce_index, + dl_req, + pdu_index, + type0_PDCCH_CSS_config, + TBS, + tda_info.startSymbolIndex, + tda_info.nrOfSymbols, + false, + beam_index); + + const int ntx_req = TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; + + // Data to be transmitted + memcpy(tx_req->TLVs[0].value.direct, sib_bcch_pdu, TBS); + + tx_req->PDU_length = TBS; + tx_req->PDU_index = pdu_index; + tx_req->num_TLV = 1; + tx_req->TLVs[0].length = TBS + 2; + TX_req->Number_of_PDUs++; + TX_req->SFN = frame; + TX_req->Slot = slot; + + T(T_GNB_MAC_DL_PDU_WITH_DATA, + T_INT(module_idP), + T_INT(0), + T_INT(SI_RNTI), + T_INT(frame), + T_INT(slot), + T_INT(0), // harq_pid + T_BUFFER(sib_bcch_pdu, num_total_bytes)); +} + +// This function verifies if we need to schedule otherSIB in frame and slot +static bool test_other_sib_sched_occasion(int window_pos, + int window_len, + int period, + int n_slots_frame, + int frame, + int slot, + int rel_frame, + int rel_slot) +{ + int x = window_pos * window_len; + int T = 8 << period; + int test_frame = (frame - rel_frame) % MAX_FRAME_NUMBER; + int si_slot = (x % n_slots_frame) + rel_slot; + bool res = ((test_frame % T) != (x / n_slots_frame)) || (si_slot != slot); + return res; +} + +void schedule_nr_other_sib(module_id_t module_idP, + frame_t frame, + slot_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ + gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; + NR_SIB1_t *sib1 = cc->sib1->message.choice.c1->choice.systemInformationBlockType1; + NR_SI_SchedulingInfo_t *schedInfo = sib1->si_SchedulingInfo; + if (!schedInfo) return; + + NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon; + NR_PDCCH_ConfigCommon_t *pdcch_common = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup; + NR_SearchSpaceId_t *ss_id = pdcch_common->searchSpaceOtherSystemInformation; + AssertFatal(ss_id, "searchSpaceOtherSystemInformation not present\n"); + NR_SearchSpace_t *ss = NULL; + for (int i = 0; i < pdcch_common->commonSearchSpaceList->list.count; i++) { + if (pdcch_common->commonSearchSpaceList->list.array[i]->searchSpaceId == *ss_id) + ss = pdcch_common->commonSearchSpaceList->list.array[i]; + } + AssertFatal(ss, "searchSpaceOtherSystemInformation not found\n"); + + NR_SI_SchedulingInfo_v1700_t *schedInfo17 = NULL; + if (sib1->nonCriticalExtension) { + NR_SIB1_v1610_IEs_t *sib1_v1610 = sib1->nonCriticalExtension; + if (sib1_v1610 && sib1_v1610->nonCriticalExtension && sib1_v1610->nonCriticalExtension->nonCriticalExtension) { + NR_SIB1_v1700_IEs_t *sib1_v17 = sib1_v1610->nonCriticalExtension->nonCriticalExtension; + schedInfo17 = sib1_v17->si_SchedulingInfo_v1700; + } } - // convert periodicity enum type into actual frames number - int frame = 8 << sib19_sched_info->si_Periodicity_r17; - - int time_domain_allocation = 1; // row 0 of pdsch tda common table - int L_max; - switch (scc->ssb_PositionsInBurst->present) { - case 1: - L_max = 4; - break; - case 2: - L_max = 8; - break; - case 3: - L_max = 64; - break; - default: - AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n", - scc->ssb_PositionsInBurst->present); + int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame; + int window_length_sl = 5 << schedInfo->si_WindowLength; + int window_length_f = (window_length_sl / n_slots_frame) + ((window_length_sl % n_slots_frame) > 0); + int num_ssb = cc->num_active_ssb; + // number of PDCCH monitoring occasions in SI-window + int period, offset; + get_monitoring_period_offset(ss, &period, &offset); + // The UE assumes that, in the SI window, PDCCH for an SI message is transmitted + // in at least one PDCCH monitoring occasion corresponding to each transmitted SSB + // frame and slot relative to start of window + // The [x×N+K]th PDCCH monitoring occasion(s) for SI message in SI-window corresponds to the Kth transmitted SSB + // in our implmentation we transmit only once per SSB per window so N = 1 + // Section 5.2.2.3.2 of 38.331 + int temp_slot = offset % n_slots_frame; + int temp_frame = offset / n_slots_frame; + int rel_slot[num_ssb]; + int rel_frame[num_ssb]; + int ssb = 0; + while (ssb < num_ssb) { + AssertFatal(temp_frame < window_length_f, "Couldn't fit %d SSB in window length of %d slots\n", num_ssb, window_length_sl); + if (is_dl_slot(temp_slot, &gNB_mac->frame_structure)) { + rel_slot[ssb] = temp_slot; + rel_frame[ssb] = temp_frame; + ssb++; + } + temp_frame += (temp_slot + period) / n_slots_frame; + temp_slot = (temp_slot + period) % n_slots_frame; } - const int window_length = 10; - for (int i = 0; i < L_max; i++) { + for (int ssb = 0; ssb < num_ssb; ssb++) { + for (int i = 0; i < schedInfo->schedulingInfoList.list.count; i++) { + NR_SchedulingInfo_t *schedulingInfo = schedInfo->schedulingInfoList.list.array[i]; + if (test_other_sib_sched_occasion(i, + window_length_sl, + schedulingInfo->si_Periodicity, + n_slots_frame, + frame, + slot, + rel_frame[ssb], + rel_slot[ssb])) + continue; - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i]; - if(((frameP - 1) % frame == 0) && - (slotP == ((sib19_sched_info->si_WindowPosition_r17 % window_length) - 1)) && - (type0_PDCCH_CSS_config->num_rbs > 0)) { + other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 0); + } + if (!schedInfo17) + continue; + for (int i = 0; i < schedInfo17->schedulingInfoList2_r17.list.count; i++) { + NR_SchedulingInfo2_r17_t *schedulingInfo2_r17 = schedInfo17->schedulingInfoList2_r17.list.array[i]; + if (test_other_sib_sched_occasion(schedulingInfo2_r17->si_WindowPosition_r17, + window_length_sl, + schedulingInfo2_r17->si_Periodicity_r17, + n_slots_frame, + frame, + slot, + rel_frame[ssb], + rel_slot[ssb])) + continue; - const int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame; - int beam_index = get_fapi_beamforming_index(gNB_mac, i); - NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, beam_index, n_slots_frame); - AssertFatal(beam.idx >= 0, "Cannot allocate SIB19 corresponding to SSB %d in any available beam\n", i); - LOG_D(NR_MAC,"(%d.%d) SIB19 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index); - - NR_tda_info_t tda_info = set_tda_info_from_list(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList, time_domain_allocation); - LOG_D(NR_MAC,"tda_info.startSymbolIndex: %d, tda_info.nrOfSymbols: %d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols); - - AssertFatal((tda_info.startSymbolIndex + tda_info.nrOfSymbols) < 14, "SIB19 TDA %d would cause overlap with CSI-RS. Please select a different SIB1 TDA.\n", time_domain_allocation); - - NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, - NULL, - &tda_info, - 1); - - // Configure sched_osi for SIB19 - uint32_t TBS = schedule_control_other_si(module_idP, - CC_id, - type0_PDCCH_CSS_config, - time_domain_allocation, - &dmrs_parms, - &tda_info, - candidate_idx, - beam.idx, - sib19_bcch_length); - - nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; - int pdu_index = gNB_mac->pdu_index[0]++; - - nr_fill_nfapi_dl_SIB_pdu(module_idP, - gNB_mac->sched_osi, - NULL, - dl_req, - pdu_index, - type0_PDCCH_CSS_config, - TBS, - tda_info.startSymbolIndex, - tda_info.nrOfSymbols, - beam_index); - - const int ntx_req = TX_req->Number_of_PDUs; - nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; - - // Data to be transmitted - memcpy(tx_req->TLVs[0].value.direct, sib19_bcch_pdu, TBS); - - tx_req->PDU_length = TBS; - tx_req->PDU_index = pdu_index; - tx_req->num_TLV = 1; - tx_req->TLVs[0].length = TBS + 2; - TX_req->Number_of_PDUs++; - TX_req->SFN = frameP; - TX_req->Slot = slotP; - - type0_PDCCH_CSS_config->active = false; - - T(T_GNB_MAC_DL_PDU_WITH_DATA, - T_INT(module_idP), - T_INT(CC_id), - T_INT(SI_RNTI), - T_INT(frameP), - T_INT(slotP), - T_INT(0 /* harq_pid */), - T_BUFFER(sib19_bcch_pdu, sib19_bcch_length)); + other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 1); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 2a5b979f5a..b69490fbc9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1045,7 +1045,7 @@ void nr_schedule_ue_spec(module_id_t module_id, pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %04x, bwp %d, cs %d\n", UE->rnti, bwp_id, coresetid); NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; - nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch, false); + nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch); gNB_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 3c7c9ebd39..4e292b916b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -281,8 +281,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx) NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, const NR_UE_DL_BWP_t *dl_bwp, const NR_tda_info_t *tda_info, - const int Layers) { - + const int Layers) +{ NR_pdsch_dmrs_t dmrs = {0}; int frontloaded_symb = 1; // default value nr_dci_format_t dci_format = dl_bwp ? dl_bwp->dci_format : NR_DL_DCI_FORMAT_1_0; @@ -732,12 +732,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, int max_mcs, frame_t frame) { - /* first call: everything is zero. Initialize to sensible default */ - if (bler_stats->last_frame == 0 && bler_stats->mcs == 0) { - bler_stats->last_frame = frame; - bler_stats->mcs = 9; - bler_stats->bler = (bler_options->lower + bler_options->upper) / 2.0f; - } int diff = frame - bler_stats->last_frame; if (diff < 0) // wrap around diff += 1024; @@ -756,11 +750,11 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, int new_mcs = old_mcs; if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && num_dl_sched > 3) new_mcs += 1; - else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold - || (num_dl_sched <= 3 && old_mcs > 9)) // no activity + else if (bler_stats->bler > bler_options->upper || num_dl_sched <= 3) // above threshold or no activity new_mcs -= 1; // else we are within threshold boundaries + new_mcs = max(new_mcs, bler_options->min_mcs); bler_stats->last_frame = frame; bler_stats->mcs = new_mcs; memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds)); @@ -865,12 +859,8 @@ int nr_get_default_pucch_res(int pucch_ResourceCommon) { return(default_pucch_csset[pucch_ResourceCommon]); } -void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, - NR_ControlResourceSet_t *coreset, - NR_sched_pdcch_t *pdcch, - bool otherSI) { - - +void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *pdcch) +{ pdcch_pdu->BWPSize = pdcch->BWPSize; pdcch_pdu->BWPStart = pdcch->BWPStart; pdcch_pdu->SubcarrierSpacing = pdcch->SubcarrierSpacing; @@ -879,19 +869,23 @@ void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, pdcch_pdu->DurationSymbols = coreset->duration; - for (int i=0;i<6;i++) + for (int i = 0; i < 6; i++) pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i]; - LOG_D(MAC,"Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %d\n", - pdcch_pdu->BWPStart,pdcch_pdu->BWPSize,(int)pdcch_pdu->SubcarrierSpacing,(int)coreset->frequencyDomainResources.buf[0],(int)coreset->duration); + LOG_D(NR_MAC, + "Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %ld\n", + pdcch_pdu->BWPStart, + pdcch_pdu->BWPSize, + pdcch_pdu->SubcarrierSpacing, + coreset->frequencyDomainResources.buf[0], + coreset->duration); pdcch_pdu->CceRegMappingType = pdcch->CceRegMappingType; pdcch_pdu->RegBundleSize = pdcch->RegBundleSize; pdcch_pdu->InterleaverSize = pdcch->InterleaverSize; pdcch_pdu->ShiftIndex = pdcch->ShiftIndex; - pdcch_pdu->CoreSetType = - (otherSI || coreset->controlResourceSetId != 0) ? NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG : NFAPI_NR_CSET_CONFIG_MIB_SIB1; + pdcch_pdu->CoreSetType = coreset->controlResourceSetId != 0 ? NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG : NFAPI_NR_CSET_CONFIG_MIB_SIB1; //precoderGranularity pdcch_pdu->precoderGranularity = coreset->precoderGranularity; @@ -2492,6 +2486,13 @@ void reset_srs_stats(NR_UE_info_t *UE) { } } +static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats_t *bler_stats, frame_t frame) +{ + bler_stats->last_frame = frame; + bler_stats->mcs = bler_options->min_mcs; + bler_stats->bler = (float)(bler_options->lower + bler_options->upper) / 2.0f; +} + //------------------------------------------------------------------------------ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup) { @@ -2522,6 +2523,10 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf sched_ctrl->sched_srs.slot = -1; sched_ctrl->pdcch_cl_adjust = 0; + // Initialize bler_stats + init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame); + init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame); + // initialize LCID structure seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t)); @@ -3322,7 +3327,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) int CC_id = 0; int srb_id = 1; const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon; - const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig; + const NR_ServingCellConfig_t *sccd = UE->is_redcap ? NULL : mac->common_channels[CC_id].pre_ServingCellConfig; NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = cellGroupConfig; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 7cad2d883d..2b5cc97ffe 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -100,7 +100,7 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot, #define MIN_RSRP_VALUE -141 #define MAX_RSRP_VALUE -43 -//Measured RSRP Values Table 10.1.16.1-1 from 36.133 +//Measured RSRP Values Table 10.1.16.1-1 from 38.133 //Stored all the upper limits[Max RSRP Value of corresponding index] //stored -1 for invalid values static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { @@ -119,7 +119,7 @@ static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { -1, -1, -1, -1, -1, -1, -1, -1 // 120 - 127 }; -//Differential RSRP values Table 10.1.6.1-2 from 36.133 +//Differential RSRP values Table 10.1.6.1-2 from 38.133 //Stored the upper limits[MAX RSRP Value] static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { 0, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index b6e86fa6b7..c4cfd4181e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -350,6 +350,7 @@ static int nr_process_mac_pdu(instance_t module_idP, if (lcid == UL_SCH_LCID_CCCH_48_BITS_REDCAP) { LOG_I(MAC, "UE with RNTI %04x is RedCap\n", UE->rnti); + UE->is_redcap = true; } if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) { @@ -2050,7 +2051,6 @@ static void pf_ul(module_id_t module_id, fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; - sched_pusch->mcs = max(nrmac->min_grant_mcs, sched_pusch->mcs); update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm); sched_pusch->rbStart = rbStart; sched_pusch->rbSize = min_rb; @@ -2680,7 +2680,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ ul_dci_request_pdu->PDUSize = (uint8_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; ul_dci_req->numPdus += 1; - nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch, false); + nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch); pdcch_pdu_coreset[coresetid] = pdcch_pdu; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 65c5aba9f1..c8b809a8cb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -54,10 +54,8 @@ void mac_top_init_gNB(ngran_node_t node_type, void nr_mac_send_f1_setup_req(void); void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *mac_config); -void nr_fill_sched_osi(gNB_MAC_INST *nrmac, const struct NR_SetupRelease_PDCCH_ConfigCommon *pdcch_ConfigCommon); void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_t cellID, int tac); -void nr_mac_configure_sib19(gNB_MAC_INST *nrmac); - +bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]); bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); @@ -97,13 +95,11 @@ void schedule_nr_sib1(module_id_t module_idP, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req); -void schedule_nr_sib19(module_id_t module_idP, - frame_t frameP, - slot_t slotP, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req, - int sib19_bcch_length, - uint8_t *sib19_bcch_pdu); +void schedule_nr_other_sib(module_id_t module_idP, + frame_t frame, + slot_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); struct NR_SchedulingInfo2_r17* find_sib19_sched_info(const struct NR_SI_SchedulingInfo_v1700*); @@ -215,10 +211,7 @@ void find_search_space(int ss_type, NR_BWP_Downlink_t *bwp, NR_SearchSpace_t *ss); -void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, - NR_ControlResourceSet_t *coreset, - NR_sched_pdcch_t *pdcch, - bool otherSI); +void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *pdcch); NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, NR_SearchSpace_t *ss, @@ -474,4 +467,8 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid); bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti); void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected); +void prepare_du_configuration_update(gNB_MAC_INST *mac, + f1ap_served_cell_info_t *info, + NR_BCCH_BCH_Message_t *mib, + const NR_BCCH_DL_SCH_Message_t *sib1); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ 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 25a182dddb..ca07d1555a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -165,7 +165,15 @@ void f1_setup_response(const f1ap_setup_resp_t *resp) AssertFatal(check_plmn_identity(&du_cell->plmn, &cu_cell->plmn), "PLMN mismatch\n"); AssertFatal(du_cell->nr_pci == cu_cell->nrpci, "PCI mismatch: DU %d vs CU %d\n", du_cell->nr_pci, cu_cell->nrpci); - AssertFatal(cu_cell->num_SI == 0, "handling of CU-provided SIBs: not implemented\n"); + // we can configure other SIB only after having received the ones generated by CU + bool update = nr_mac_configure_other_sib(mac, cu_cell->num_SI, cu_cell->SI_msg); + if (update) { + f1ap_setup_req_t *sr = mac->f1_config.setup_req; + DevAssert(sr->num_cells_available == 1); + f1ap_served_cell_info_t *info = &sr->cell[0].info; + NR_COMMON_channels_t *cc = &mac->common_channels[0]; + prepare_du_configuration_update(mac, info, cc->mib, cc->sib1); + } mac->f1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp)); AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 65812ae0f5..3a01ecfbfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -276,7 +276,7 @@ typedef struct { frame_type_t frame_type; NR_BCCH_BCH_Message_t *mib; NR_BCCH_DL_SCH_Message_t *sib1; - NR_BCCH_DL_SCH_Message_t *sib19; + seq_arr_t *du_SIBs; NR_ServingCellConfigCommon_t *ServingCellConfigCommon; /// pre-configured ServingCellConfig that is default for every UE NR_ServingCellConfig_t *pre_ServingCellConfig; @@ -285,9 +285,9 @@ typedef struct { /// Outgoing BCCH pdu for PHY uint8_t sib1_bcch_pdu[NR_MAX_SIB_LENGTH / 8]; int sib1_bcch_length; - /// used for sib19 data - uint8_t sib19_bcch_pdu[NR_MAX_SIB_LENGTH / 8]; - int sib19_bcch_length; + /// used for otherSIB data + uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8]; + int other_sib_bcch_length[2]; /// Template for RA computations NR_RA_t ra[NR_NB_RA_PROC_MAX]; /// VRB map for common channels @@ -691,19 +691,6 @@ typedef struct { float pdcch_cl_adjust; } NR_UE_sched_ctrl_t; -typedef struct { - NR_SearchSpace_t *search_space; - NR_ControlResourceSet_t *coreset; - - NR_sched_pdcch_t sched_pdcch; - NR_sched_pdsch_t sched_pdsch; - - uint32_t num_total_bytes; - - int cce_index; - uint8_t aggregation_level; -} NR_UE_sched_osi_ctrl_t; - typedef struct { uicc_t *uicc; } NRUEcontext_t; @@ -738,6 +725,7 @@ typedef struct NR_mac_stats { typedef struct NR_bler_options { double upper; double lower; + uint8_t min_mcs; uint8_t max_mcs; uint8_t harq_round_max; } NR_bler_options_t; @@ -783,6 +771,7 @@ typedef struct { float ul_thr_ue; float dl_thr_ue; long pdsch_HARQ_ACK_Codebook; + bool is_redcap; } NR_UE_info_t; typedef struct { @@ -927,9 +916,8 @@ typedef struct gNB_MAC_INST_s { nr_mac_config_t radio_config; - NR_UE_sched_osi_ctrl_t *sched_osi; NR_UE_sched_ctrl_t *sched_ctrlCommon; - + NR_sched_pdcch_t *sched_pdcch_otherSI; uint16_t cset0_bwp_start; uint16_t cset0_bwp_size; NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config[64]; @@ -938,7 +926,6 @@ typedef struct gNB_MAC_INST_s { NR_bler_options_t dl_bler; NR_bler_options_t ul_bler; uint8_t min_grant_prb; - uint8_t min_grant_mcs; bool identity_pm; int precoding_matrix_size[NR_MAX_NB_LAYERS]; int fapi_beam_index[MAX_NUM_OF_SSB]; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index a5ef870749..b5de4c2b44 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -155,13 +155,13 @@ typedef struct nr_pdcp_entity_t { stream_security_context_t *security_context; void (*cipher)(stream_security_context_t *security_context, unsigned char *buffer, int length, - int bearer, int count, int direction); + int bearer, uint32_t count, int direction); void (*free_security)(stream_security_context_t *security_context); stream_security_context_t *integrity_context; void (*integrity)(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, - int bearer, int count, int direction); + int bearer, uint32_t count, int direction); void (*free_integrity)(stream_security_context_t *integrity_context); /* security/integrity algorithms need to know uplink/downlink information * which is reverse for gnb and ue, so we need to know if this diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c index d21c98610e..cbcad2b401 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c @@ -42,7 +42,7 @@ stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_ void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, - int bearer, int count, int direction) + int bearer, uint32_t count, int direction) { nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)integrity_context; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h index 89f6d9156a..da6b7a835e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h @@ -29,7 +29,7 @@ stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_ void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, - int bearer, int count, int direction); + int bearer, uint32_t count, int direction); void nr_pdcp_integrity_nia1_free_integrity(stream_security_context_t *integrity_context); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c index f6db1b10a6..f74353e8b9 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c @@ -39,14 +39,13 @@ stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16] return (stream_security_context_t *)ctx; } -void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction) +void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, uint32_t count, int direction) { DevAssert(integrity_context != NULL); DevAssert(out != NULL); DevAssert(buffer != NULL); DevAssert(length > -1); DevAssert(bearer > 0 && bearer < 33); - DevAssert(count > -1); cbc_cmac_ctx_t *ctx = (cbc_cmac_ctx_t *)integrity_context; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h index c9bd6cd881..7483b2c4b0 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h @@ -31,7 +31,7 @@ stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16] void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, - int bearer, int count, int direction); + int bearer, uint32_t count, int direction); void nr_pdcp_integrity_nia2_free_integrity(stream_security_context_t *integrity_context); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c index 1cb29b3a81..d6df244e0c 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c @@ -43,7 +43,7 @@ void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, - int count, + uint32_t count, int direction) { nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)security_context; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h index 1338739298..508b4430f6 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h @@ -30,7 +30,7 @@ void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, - int count, + uint32_t count, int direction); void nr_pdcp_security_nea1_free_security(stream_security_context_t *security_context); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c index 617d5c3372..27027d5324 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c @@ -36,14 +36,13 @@ stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_k return (stream_security_context_t *)ciphering_key; } -void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, int count, int direction) +void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, uint32_t count, int direction) { DevAssert(security_context != NULL); DevAssert(buffer != NULL); DevAssert(length > 0); DevAssert(bearer > -1 && bearer < 32); DevAssert(direction > -1 && direction < 2); - DevAssert(count > -1); aes_128_t p = {0}; const uint8_t *ciphering_key = (uint8_t const *)security_context; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h index 4550e7290d..cec7bc3bf1 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h @@ -28,7 +28,7 @@ stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_k void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, - int bearer, int count, int direction); + int bearer, uint32_t count, int direction); void nr_pdcp_security_nea2_free_security(stream_security_context_t *security_context); diff --git a/openair2/M2AP/MESSAGES/CMakeLists.txt b/openair2/M2AP/MESSAGES/CMakeLists.txt index 2142655ac2..5a436a06e6 100644 --- a/openair2/M2AP/MESSAGES/CMakeLists.txt +++ b/openair2/M2AP/MESSAGES/CMakeLists.txt @@ -18,10 +18,11 @@ else() message(FATAL_ERROR "unknown M2AP_RELEASE ${M2AP_RELEASE}") endif() -add_custom_command(OUTPUT ${m2ap_source} ${m2ap_headers} - COMMAND ASN1C_PREFIX=M2AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR} - COMMENT "Generating M2AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR} + "M2AP_" + OUTPUT ${m2ap_source} ${m2ap_headers} + OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps + COMMENT "M2AP source files" ) add_library(asn1_m2ap ${m2ap_source}) diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 14916062b2..dfb0a0d942 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1108,7 +1108,8 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac, uint8_t *pduP, uint32_t pdu_len) { - return nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len); + nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len); + return 0; } // L2 Abstraction Layer diff --git a/openair2/RRC/LTE/MESSAGES/CMakeLists.txt b/openair2/RRC/LTE/MESSAGES/CMakeLists.txt index 162463dc46..776983068a 100644 --- a/openair2/RRC/LTE/MESSAGES/CMakeLists.txt +++ b/openair2/RRC/LTE/MESSAGES/CMakeLists.txt @@ -10,10 +10,11 @@ else() message(FATAL_ERROR "unknown LTE_RRC_RELEASE ${LTE_RRC_RELEASE}") endif() -add_custom_command(OUTPUT ${lte_rrc_source} ${lte_rrc_headers} - COMMAND ASN1C_PREFIX=LTE_ ${ASN1C_EXEC} -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR} - COMMENT "Generating LTE RRC source file from ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR} + "LTE_" + OUTPUT ${lte_rrc_source} ${lte_rrc_headers} + OPTIONS -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example + COMMENT "LTE RRC source files" ) # Many other targets include LTE RRC ASN.1 headers, without actually needing diff --git a/openair2/RRC/NR/MESSAGES/CMakeLists.txt b/openair2/RRC/NR/MESSAGES/CMakeLists.txt index f85c39bf73..8854801e1c 100644 --- a/openair2/RRC/NR/MESSAGES/CMakeLists.txt +++ b/openair2/RRC/NR/MESSAGES/CMakeLists.txt @@ -10,10 +10,11 @@ else() message(FATAL_ERROR "unknown NR_RRC_RELEASE ${NR_RRC_RELEASE}") endif() -add_custom_command(OUTPUT ${nr_rrc_source} ${nr_rrc_headers} - COMMAND ASN1C_PREFIX=NR_ ${ASN1C_EXEC} -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -findirect-choice -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR} - COMMENT "Generating NR RRC source file from ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR} + "NR_" + OUTPUT ${nr_rrc_source} ${nr_rrc_headers} + OPTIONS -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -findirect-choice + COMMENT "NR RRC source files" ) # Many other targets include NR RRC ASN.1 headers, without actually needing the diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index beb8de2e3a..07343488a2 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -197,51 +197,37 @@ int xer_nr_sprint(char *string, size_t string_size, asn_TYPE_descriptor_t *td, v //------------------------------------------------------------------------------ -int do_SIB23_NR(rrc_gNB_carrier_data_t *carrier) +int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc) { - asn_enc_rval_t enc_rval; - SystemInformation_IEs__sib_TypeAndInfo__Member *sib2 = NULL; - SystemInformation_IEs__sib_TypeAndInfo__Member *sib3 = NULL; + NR_SIB2_t *sib2 = calloc(1, sizeof(*sib2)); + sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB0; + struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars *speed = calloc(1, sizeof(*speed)); + NR_MobilityStateParameters_t mobilityStateParameters = {0}; + mobilityStateParameters.t_Evaluation = NR_MobilityStateParameters__t_Evaluation_s30; + mobilityStateParameters.t_HystNormal = NR_MobilityStateParameters__t_HystNormal_s30; + mobilityStateParameters.n_CellChangeMedium = 1; + mobilityStateParameters.n_CellChangeHigh = 2; + speed->mobilityStateParameters = mobilityStateParameters; + struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF qhyst = {0}; + qhyst.sf_Medium = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_Medium_dB_4; + qhyst.sf_High = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_High_dB_6; + speed->q_HystSF = qhyst; + sib2->cellReselectionInfoCommon.speedStateReselectionPars = speed; + sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 0; // INTEGER (0..7) + sib2->cellReselectionServingFreqInfo.threshServingLowP = 0; + NR_ReselectionThresholdQ_t *threshServingLowQ = calloc(1, sizeof(*threshServingLowQ)); + *threshServingLowQ = 0; + sib2->cellReselectionServingFreqInfo.threshServingLowQ = threshServingLowQ; + sib2->intraFreqCellReselectionInfo.q_RxLevMin = -56; // INTEGER (-70..-22) + sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 22; // INTEGER (0..31) + sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 1; // INTEGER (0..7) + sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true; + sib2->intraFreqCellReselectionInfo.smtc = ssbmtc; - NR_BCCH_DL_SCH_Message_t *sib_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t)); - sib_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1; - sib_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1)); - sib_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation; - sib_message->message.choice.c1->choice.systemInformation = CALLOC(1,sizeof(struct NR_SystemInformation)); - - struct NR_SystemInformation *sib = sib_message->message.choice.c1->choice.systemInformation; - sib->criticalExtensions.present = NR_SystemInformation__criticalExtensions_PR_systemInformation; - sib->criticalExtensions.choice.systemInformation = CALLOC(1, sizeof(struct NR_SystemInformation_IEs)); - - struct NR_SystemInformation_IEs *ies = sib->criticalExtensions.choice.systemInformation; - sib2 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member)); - sib2->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2; - sib2->choice.sib2 = CALLOC(1, sizeof(struct NR_SIB2)); - sib2->choice.sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB1; - sib2->choice.sib2->cellReselectionServingFreqInfo.threshServingLowP = 2; // INTEGER (0..31) - sib2->choice.sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 2; // INTEGER (0..7) - sib2->choice.sib2->intraFreqCellReselectionInfo.q_RxLevMin = -50; // INTEGER (-70..-22) - sib2->choice.sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 2; // INTEGER (0..31) - sib2->choice.sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 2; // INTEGER (0..7) - sib2->choice.sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true; - asn1cSeqAdd(&ies->sib_TypeAndInfo.list, sib2); - - sib3 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member)); - sib3->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3; - sib3->choice.sib3 = CALLOC(1, sizeof(struct NR_SIB3)); - asn1cSeqAdd(&ies->sib_TypeAndInfo.list, sib3); - - //encode SIB to data - // carrier->SIB23 = (uint8_t *) malloc16(128); - enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message, - NULL, - (void *)sib_message, - carrier->SIB23, - 100); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_DL_SCH_Message, sib_message); - return((enc_rval.encoded+7)/8); + ssize_t size = uper_encode_to_new_buffer(&asn_DEF_NR_SIB2, NULL, (void *)sib2, (void **)msg_SIB2); + AssertFatal (size > 0, "ASN1 message encoding failed (encoded %lu bytes)!\n", size); + ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2); + return size; } int do_RRCReject(uint8_t *const buffer) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index a6c5e25aec..2d703912e2 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -66,7 +66,7 @@ struct asn_TYPE_descriptor_s; */ int xer_sprint_NR(char *string, size_t string_size, struct asn_TYPE_descriptor_s *td, void *sptr); -int do_SIB23_NR(rrc_gNB_carrier_data_t *carrier); +int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc); int do_RRCReject(uint8_t *const buffer); diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 8a84a7f85d..ff89f61160 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -53,10 +53,7 @@ static void f1_setup_response_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_resp_ MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_SETUP_RESP); msg->ittiMsgHeader.originInstance = assoc_id; f1ap_setup_resp_t *f1ap_msg = &F1AP_SETUP_RESP(msg); - *f1ap_msg = *resp; - if (resp->gNB_CU_name != NULL) - f1ap_msg->gNB_CU_name = strdup(resp->gNB_CU_name); - free_f1ap_setup_response(resp); + *f1ap_msg = cp_f1ap_setup_response(resp); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } @@ -65,7 +62,7 @@ static void f1_setup_failure_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_failur MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_SETUP_FAILURE); msg->ittiMsgHeader.originInstance = assoc_id; f1ap_setup_failure_t *f1ap_msg = &F1AP_SETUP_FAILURE(msg); - *f1ap_msg = *fail; + *f1ap_msg = cp_f1ap_setup_failure(fail); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } @@ -74,7 +71,7 @@ static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1 MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE); msg->ittiMsgHeader.originInstance = assoc_id; f1ap_gnb_du_configuration_update_acknowledge_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg); - *f1ap_msg = *ack; + *f1ap_msg = cp_f1ap_du_configuration_update_acknowledge(ack); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index e39dd3581f..d377b2aff3 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -277,7 +277,6 @@ NR_SearchSpace_t *rrc_searchspace_config(bool is_common, ss->nrofCandidates->aggregationLevel4 = num_agg_level_candidates[PDCCH_AGG_LEVEL4]; ss->nrofCandidates->aggregationLevel8 = num_agg_level_candidates[PDCCH_AGG_LEVEL8]; ss->nrofCandidates->aggregationLevel16 = num_agg_level_candidates[PDCCH_AGG_LEVEL16]; - ss->searchSpaceType = calloc(1,sizeof(*ss->searchSpaceType)); if (is_common) { ss->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; @@ -2349,6 +2348,107 @@ static long get_NR_UE_TimersAndConstants_t319(const nr_mac_timers_t *timer_confi } } +void add_sib_to_systeminformation(NR_SystemInformation_IEs_t *si, struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type) +{ + asn1cSeqAdd(&si->sib_TypeAndInfo.list, type); +} + +void update_SIB1_NR_SI(NR_BCCH_DL_SCH_Message_t *sib1_bcch, int num_sibs, int sibs[num_sibs]) +{ + NR_SIB1_t *sib1 = sib1_bcch->message.choice.c1->choice.systemInformationBlockType1; + //si-SchedulingInfo + NR_SI_SchedulingInfo_t *info = calloc(1, sizeof(*info)); + // TODO need to compute optimal SI-windowlength automatically + // based on the number of SSBs, TDD configuration and SS configuration + info->si_WindowLength = NR_SI_SchedulingInfo__si_WindowLength_s10; + NR_SchedulingInfo_t *schedulingInfo = calloc(1, sizeof(*schedulingInfo)); + schedulingInfo->si_BroadcastStatus = NR_SchedulingInfo__si_BroadcastStatus_broadcasting; + schedulingInfo->si_Periodicity = NR_SchedulingInfo__si_Periodicity_rf16; + bool reg_sib = false; + NR_SI_SchedulingInfo_v1700_t *si_schedulingInfo_v17 = NULL; + NR_SchedulingInfo2_r17_t *schedulingInfo2_r17 = NULL; + bool v17_sib = false; + for (int i = 0; i < num_sibs; i++) { + int sib_num = sibs[i]; + AssertFatal(sib_num > 1 && sib_num < 21, "other SIB invalid type\n"); + if (sib_num < 15) { + reg_sib = true; + NR_SIB_TypeInfo_t *mapping = calloc(1, sizeof(*mapping)); + // NR_SIB_TypeInfo__type_sibType2 = 0 + // NR_SIB_TypeInfo__type_sibType3 = 1 + // and so on + mapping->type = sib_num - 2; + // The field is mandatory present if the type is different from SIB6, SIB7 or SIB8. For SIB6, SIB7 and SIB8 it is absent. + if (sib_num != 6 && sib_num != 7 && sib_num != 8) { + mapping->valueTag = calloc(1, sizeof(*mapping->valueTag)); + *mapping->valueTag = 0; + } + asn1cSeqAdd(&schedulingInfo->sib_MappingInfo.list, mapping); + } else { + if (v17_sib == false) { + si_schedulingInfo_v17 = calloc(1, sizeof(*si_schedulingInfo_v17)); + schedulingInfo2_r17 = calloc(1, sizeof(*schedulingInfo2_r17)); + schedulingInfo2_r17->si_BroadcastStatus_r17 = NR_SchedulingInfo2_r17__si_BroadcastStatus_r17_broadcasting; + schedulingInfo2_r17->si_Periodicity_r17 = NR_SchedulingInfo2_r17__si_Periodicity_r17_rf16; + schedulingInfo2_r17->si_WindowPosition_r17 = 2; + } + NR_SIB_TypeInfo_v1700_t *mapping17 = calloc(1, sizeof(*mapping17)); + mapping17->sibType_r17.present = NR_SIB_TypeInfo_v1700__sibType_r17_PR_type1_r17; + // NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType15 = 0 + // and so on + mapping17->sibType_r17.choice.type1_r17 = sib_num - 15; + mapping17->valueTag_r17 = calloc(1, sizeof(*mapping17->valueTag_r17)); + *mapping17->valueTag_r17 = 0; + asn1cSeqAdd(&schedulingInfo2_r17->sib_MappingInfo_r17.list, mapping17); + } + } + AssertFatal(reg_sib, "At least 1 SIB from SchedulingInfo (SIB2 to SIB14 included) needs to be present\n"); + asn1cSeqAdd(&info->schedulingInfoList.list, schedulingInfo); + sib1->si_SchedulingInfo = info; + if (si_schedulingInfo_v17) { + asn1cSeqAdd(&si_schedulingInfo_v17->schedulingInfoList2_r17.list, schedulingInfo2_r17); + NR_SIB1_v1610_IEs_t *sib1_v1610 = NULL; + if (sib1->nonCriticalExtension) + sib1_v1610 = sib1->nonCriticalExtension; + else { + sib1_v1610 = calloc_or_fail(1, sizeof(*sib1_v1610)); + sib1->nonCriticalExtension = sib1_v1610; + } + NR_SIB1_v1630_IEs_t *sib1_v1630 = NULL; + if (sib1_v1610->nonCriticalExtension) + sib1_v1630 = sib1_v1610->nonCriticalExtension; + else { + sib1_v1630 = calloc_or_fail(1, sizeof(*sib1_v1630)); + sib1_v1610->nonCriticalExtension = sib1_v1630; + } + NR_SIB1_v1700_IEs_t *sib1_v17 = NULL; + if (sib1_v1630->nonCriticalExtension) + sib1_v17 = sib1_v1630->nonCriticalExtension; + else { + sib1_v17 = calloc_or_fail(1, sizeof(*sib1_v17)); + sib1_v1630->nonCriticalExtension = sib1_v17; + } + sib1_v17->si_SchedulingInfo_v1700 = si_schedulingInfo_v17; + } + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message, sib1_bcch); + } +} + +int encode_sysinfo_ie(NR_SystemInformation_IEs_t *sysInfo, uint8_t *buf, int len) +{ + if (sysInfo->sib_TypeAndInfo.list.count == 0) + return 0; + NR_SystemInformation_t si = {.criticalExtensions.present = NR_SystemInformation__criticalExtensions_PR_systemInformation}; + si.criticalExtensions.choice.systemInformation = sysInfo; + struct NR_BCCH_DL_SCH_MessageType__c1 c1 = {.present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation}; + c1.choice.systemInformation = &si; + NR_BCCH_DL_SCH_MessageType_t message_type = {.present = NR_BCCH_DL_SCH_MessageType_PR_c1}; + message_type.choice.c1 = &c1; + NR_BCCH_DL_SCH_Message_t sib_message = {.message = message_type}; + return encode_SIB_NR(&sib_message, buf, len); +} + static bool is_ntn_band(int band) { // TS 3GPP 38.101-5 V1807 Section 5.2.2 @@ -2378,7 +2478,7 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, sib1_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1; sib1_message->message.choice.c1->choice.systemInformationBlockType1 = CALLOC(1,sizeof(struct NR_SIB1)); AssertFatal(sib1_message->message.choice.c1->choice.systemInformationBlockType1 != NULL, "out of memory\n"); - struct NR_SIB1 *sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1; + NR_SIB1_t *sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1; // cellSelectionInfo sib1->cellSelectionInfo = CALLOC(1,sizeof(*sib1->cellSelectionInfo)); @@ -2429,37 +2529,6 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, // connEstFailureControl // TODO: add connEstFailureControl - //si-SchedulingInfo - /*sib1->si_SchedulingInfo = CALLOC(1,sizeof(struct NR_SI_SchedulingInfo)); - asn_set_empty(&sib1->si_SchedulingInfo->schedulingInfoList.list); - sib1->si_SchedulingInfo->si_WindowLength = NR_SI_SchedulingInfo__si_WindowLength_s40; - struct NR_SchedulingInfo *schedulingInfo = CALLOC(1,sizeof(struct NR_SchedulingInfo)); - schedulingInfo->si_BroadcastStatus = NR_SchedulingInfo__si_BroadcastStatus_broadcasting; - schedulingInfo->si_Periodicity = NR_SchedulingInfo__si_Periodicity_rf8; - asn_set_empty(&schedulingInfo->sib_MappingInfo.list); - - NR_SIB_TypeInfo_t *sib_type3 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); - sib_type3->type = NR_SIB_TypeInfo__type_sibType3; - sib_type3->valueTag = CALLOC(1,sizeof(sib_type3->valueTag)); - asn1cSeqAdd(&schedulingInfo->sib_MappingInfo.list,sib_type3); - - NR_SIB_TypeInfo_t *sib_type5 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); - sib_type5->type = NR_SIB_TypeInfo__type_sibType5; - sib_type5->valueTag = CALLOC(1,sizeof(sib_type5->valueTag)); - asn1cSeqAdd(&schedulingInfo->sib_MappingInfo.list,sib_type5); - - NR_SIB_TypeInfo_t *sib_type4 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); - sib_type4->type = NR_SIB_TypeInfo__type_sibType4; - sib_type4->valueTag = CALLOC(1,sizeof(sib_type4->valueTag)); - asn1cSeqAdd(&schedulingInfo->sib_MappingInfo.list,sib_type4); - - NR_SIB_TypeInfo_t *sib_type2 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); - sib_type2->type = NR_SIB_TypeInfo__type_sibType2; - sib_type2->valueTag = CALLOC(1,sizeof(sib_type2->valueTag)); - asn1cSeqAdd(&schedulingInfo->sib_MappingInfo.list,sib_type2); - - asn1cSeqAdd(&sib1->si_SchedulingInfo->schedulingInfoList.list,schedulingInfo);*/ - // servingCellConfigCommon asn1cCalloc(sib1->servingCellConfigCommon, ServCellCom); NR_BWP_DownlinkCommon_t *initialDownlinkBWP = &ServCellCom->downlinkConfigCommon.initialDownlinkBWP; @@ -2685,29 +2754,9 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, *sib1_1700->intraFreqReselectionRedCap_r17 = redcap_config->intraFreqReselectionRedCap_r17; } - // sib19 scheduling info - // ensure ntn-config is initialized - if (scc->ext2 && scc->ext2->ntn_Config_r17) { - struct NR_SI_SchedulingInfo_v1700 *sib_v17_scheduling_info = CALLOC(1, sizeof(struct NR_SI_SchedulingInfo_v1700)); - - struct NR_SchedulingInfo2_r17 *si_schedulinginfo2_r17 = CALLOC(1, sizeof(struct NR_SchedulingInfo2_r17)); - si_schedulinginfo2_r17->si_BroadcastStatus_r17 = NR_SchedulingInfo2_r17__si_BroadcastStatus_r17_broadcasting; - si_schedulinginfo2_r17->si_WindowPosition_r17 = 2; - si_schedulinginfo2_r17->si_Periodicity_r17 = NR_SchedulingInfo2_r17__si_Periodicity_r17_rf8; - - struct NR_SIB_TypeInfo_v1700 *sib_type_info = CALLOC(1, sizeof(struct NR_SIB_TypeInfo_v1700)); - sib_type_info->sibType_r17.present = NR_SIB_TypeInfo_v1700__sibType_r17_PR_type1_r17; - sib_type_info->sibType_r17.choice.type1_r17 = NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19; - - asn1cSeqAdd(&si_schedulinginfo2_r17->sib_MappingInfo_r17.list, sib_type_info); - asn1cSeqAdd(&sib_v17_scheduling_info->schedulingInfoList2_r17.list, si_schedulinginfo2_r17); - sib1_1700->si_SchedulingInfo_v1700 = sib_v17_scheduling_info; - - if (is_ntn_band(band)) { - // If cell provides NTN access, set cellBarredNTN to notBarred. - sib1_1700->cellBarredNTN_r17 = CALLOC(1, sizeof(long)); - *sib1_1700->cellBarredNTN_r17 = NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred; - } + if (is_ntn_band(band)) { + // If cell provides NTN access, set cellBarredNTN to notBarred. + asn1cCallocOne(sib1_1700->cellBarredNTN_r17, NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred); } } @@ -2723,57 +2772,23 @@ void free_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1) ASN_STRUCT_FREE(asn_DEF_NR_BCCH_DL_SCH_Message, sib1); } -int encode_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1, uint8_t *buffer, int max_buffer_size) +int encode_SIB_NR(NR_BCCH_DL_SCH_Message_t *sib, uint8_t *buffer, int max_buffer_size) { AssertFatal(max_buffer_size <= NR_MAX_SIB_LENGTH / 8, - "%s(): maximum buffer size too large: 3GPP TS 38.331 section 5.2.1 - The physical layer imposes a limit to the " - "maximum size a SIB can take. The maximum SIB1 or SI message size is 2976 bits.\n", - __func__); - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message, NULL, sib1, buffer, max_buffer_size); + "Maximum buffer size too large: 3GPP TS 38.331 section 5.2.1 - The physical layer imposes a limit to the " + "maximum size a SIB can take. The maximum SIB1 or SI message size is 2976 bits.\n"); + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message, NULL, sib, buffer, max_buffer_size); AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded <= max_buffer_size * 8, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); return (enc_rval.encoded + 7) / 8; } -NR_BCCH_DL_SCH_Message_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc) +NR_SIB19_r17_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc) { - NR_BCCH_DL_SCH_Message_t *sib_message = CALLOC(1, sizeof(NR_BCCH_DL_SCH_Message_t)); - sib_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1; - sib_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1)); - sib_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation; - sib_message->message.choice.c1->choice.systemInformation = CALLOC(1,sizeof(struct NR_SystemInformation)); - - struct NR_SystemInformation *sib = sib_message->message.choice.c1->choice.systemInformation; - sib->criticalExtensions.present = NR_SystemInformation__criticalExtensions_PR_systemInformation; - sib->criticalExtensions.choice.systemInformation = CALLOC(1, sizeof(struct NR_SystemInformation_IEs)); - - struct NR_SystemInformation_IEs *ies = sib->criticalExtensions.choice.systemInformation; - - SystemInformation_IEs__sib_TypeAndInfo__Member *sib19 = NULL; - sib19 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member)); - sib19->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700; - sib19->choice.sib19_v1700 = CALLOC(1, sizeof(struct NR_SIB19_r17)); - + NR_SIB19_r17_t *sib19 = calloc(1, sizeof(*sib19)); // use ntn-config from NR_ServingCellConfigCommon_t - const int copy_result = asn_copy(&asn_DEF_NR_NTN_Config_r17, (void **) &sib19->choice.sib19_v1700->ntn_Config_r17, scc->ext2->ntn_Config_r17); + const int copy_result = asn_copy(&asn_DEF_NR_NTN_Config_r17, (void **) &sib19->ntn_Config_r17, scc->ext2->ntn_Config_r17); AssertFatal(copy_result == 0, "Was unable to copy ntn_Config_r17 from scc to SIB19 structure\n"); - - asn1cSeqAdd(&ies->sib_TypeAndInfo.list, sib19); - - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { - xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message, sib_message); - } - - return sib_message; -} - -int encode_SIB19_NR(NR_BCCH_DL_SCH_Message_t *sib19, uint8_t *buffer, int max_buffer_size) -{ - asn_enc_rval_t enc_rval; - - enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message, NULL, sib19, buffer, 150); - AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - - return ((enc_rval.encoded + 7) / 8); + return sib19; } void free_SIB19_NR(NR_BCCH_DL_SCH_Message_t *sib19) diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index 707e46cd66..d56db4b0cf 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -83,12 +83,12 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, uint64_t cellID, int tac, const nr_mac_config_t *mac_config); +void update_SIB1_NR_SI(NR_BCCH_DL_SCH_Message_t *sib1, int num_sibs, int sibs[num_sibs]); +int encode_sysinfo_ie(NR_SystemInformation_IEs_t *sysInfo, uint8_t *buf, int len); void free_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1); -int encode_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1, uint8_t *buffer, int max_buffer_size); - -NR_BCCH_DL_SCH_Message_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc); -int encode_SIB19_NR(NR_BCCH_DL_SCH_Message_t *sib19, uint8_t *buffer, int max_buffer_size); -void free_SIB19_NR(NR_BCCH_DL_SCH_Message_t *sib19); +int encode_SIB_NR(NR_BCCH_DL_SCH_Message_t *sib, uint8_t *buffer, int max_buffer_size); +void add_sib_to_systeminformation(NR_SystemInformation_IEs_t *si, struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type); +NR_SIB19_r17_t *get_SIB19_NR(const NR_ServingCellConfigCommon_t *scc); NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index c30f8856bc..f0dfc2ec02 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -268,15 +268,6 @@ typedef struct rrc_gNB_ue_context_s { struct gNB_RRC_UE_s ue_context; } rrc_gNB_ue_context_t; -typedef struct { - - uint8_t *SIB23; - int sizeof_SIB23; - -} rrc_gNB_carrier_data_t; -//--------------------------------------------------- - - typedef struct { /* nea0 = 0, nea1 = 1, ... */ int ciphering_algorithms[4]; @@ -378,7 +369,6 @@ typedef struct gNB_RRC_INST_s { char *node_name; int module_id; eth_params_t eth_params_s; - rrc_gNB_carrier_data_t carrier; uid_allocator_t uid_allocator; RB_HEAD(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s) rrc_ue_head; // ue_context tree key search by rnti /// NR cell id @@ -386,6 +376,7 @@ typedef struct gNB_RRC_INST_s { // RRC configuration gNB_RrcConfigurationReq configuration; + seq_arr_t *SIBs; // gNB N3 GTPU instance instance_t e1_inst; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 7eef21c810..b93e08e79f 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -215,29 +215,6 @@ static void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, #endif } -///---------------------------------------------------------------------------------------------------------------/// -///---------------------------------------------------------------------------------------------------------------/// - -static void init_NR_SI(gNB_RRC_INST *rrc) -{ - if (!NODE_IS_DU(rrc->node_type)) { - rrc->carrier.SIB23 = (uint8_t *) malloc16(100); - AssertFatal(rrc->carrier.SIB23 != NULL, "cannot allocate memory for SIB"); - rrc->carrier.sizeof_SIB23 = do_SIB23_NR(&rrc->carrier); - LOG_I(NR_RRC, "do_SIB23_NR, size %d\n", rrc->carrier.sizeof_SIB23); - AssertFatal(rrc->carrier.sizeof_SIB23 != 255,"FATAL, RC.nrrrc[mod].carrier[CC_id].sizeof_SIB23 == 255"); - } - - if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { - AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n"); - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc); - LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p); - if (!NODE_IS_CU(rrc->node_type)) { - rrc_add_nsa_user(rrc,ue_context_p,NULL); - } - } -} - static void rrc_gNB_CU_DU_init(gNB_RRC_INST *rrc) { switch (rrc->node_type) { @@ -277,8 +254,15 @@ void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *c RB_INIT(&rrc->cuups); RB_INIT(&rrc->dus); rrc->configuration = *configuration; - /// System Information INIT - init_NR_SI(rrc); + + if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { + AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n"); + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc); + LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p); + if (!NODE_IS_CU(rrc->node_type)) { + rrc_add_nsa_user(rrc,ue_context_p,NULL); + } + } } static void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 6c7c157374..f34ca13e6c 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -61,6 +61,15 @@ int get_ssb_scs(const struct f1ap_served_cell_info_t *cell_info) return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs; } +static NR_SSB_MTC_t *get_ssb_mtc(const NR_MeasurementTimingConfiguration_t *mtc) +{ + // TODO verify which element of the list to pick + NR_MeasTimingList_t *mtlist = mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; + NR_SSB_MTC_t *ssb_mtc = calloc(1, sizeof(*ssb_mtc)); + *ssb_mtc = mtlist->list.array[0]->frequencyAndTiming->ssb_MeasurementTimingConfiguration; + return ssb_mtc; +} + static int ssb_arfcn_mtc(const NR_MeasurementTimingConfiguration_t *mtc) { /* format has been verified when accepting MeasurementTimingConfiguration */ @@ -397,6 +406,26 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) .num_SI = 0, }; + // Encode CU SIBs and configure setup response with sysinfo + seq_arr_t *sibs = rrc->SIBs; + if (sibs) { + for (int i = 0; i < sibs->size; i++) { + nr_SIBs_t *sib = (nr_SIBs_t *)seq_arr_at(sibs, i); + switch (sib->SIB_type) { + case 2: { + NR_SSB_MTC_t *ssbmtc = get_ssb_mtc(mtc); + sib->SIB_size = do_SIB2_NR(&sib->SIB_buffer, ssbmtc); + cell.SI_msg[cell.num_SI].SI_container = sib->SIB_buffer; + cell.SI_msg[cell.num_SI].SI_container_length = sib->SIB_size; + cell.SI_msg[cell.num_SI].SI_type = sib->SIB_type; + cell.num_SI++; + } break; + default: + AssertFatal(false, "SIB%d not handled yet\n", sib->SIB_type); + } + } + } + if (du->mib != NULL && du->sib1 != NULL) label_intra_frequency_neighbours(rrc, du, cell_info); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 3bfe1d34e0..7202943322 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -59,15 +59,19 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, const sdu_size_t pdu_len) { sdu_size_t sdu_size = 0; - + MessageDef *message_p; switch(channel) { case NR_BCCH_BCH: case NR_BCCH_DL_SCH: - if (pdu_len>0) { - LOG_T(NR_RRC, "[UE %d] Received SDU for NR-BCCH-DL-SCH on SRB %u from gNB %d\n", module_id, channel & RAB_OFFSET, + message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_BCCH_DATA_IND); + memset(NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE); + if (pdu_len > 0) { + LOG_T(NR_RRC, + "[UE %d] Received SDU for NR-BCCH-DL-SCH on SRB %u from gNB %d\n", + module_id, + channel & RAB_OFFSET, gNB_index); - MessageDef *message_p; int msg_sdu_size = BCCH_SDU_SIZE; if (pdu_len > msg_sdu_size) { @@ -77,25 +81,23 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, sdu_size = pdu_len; } - message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_BCCH_DATA_IND); - memset(NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE); memcpy(NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, pduP, sdu_size); - NR_RRC_MAC_BCCH_DATA_IND (message_p).frame = frame; //frameP - NR_RRC_MAC_BCCH_DATA_IND (message_p).slot = slot; NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = sdu_size; - NR_RRC_MAC_BCCH_DATA_IND (message_p).gnb_index = gNB_index; - NR_RRC_MAC_BCCH_DATA_IND (message_p).phycellid = cellid; - NR_RRC_MAC_BCCH_DATA_IND (message_p).ssb_arfcn = arfcn; - NR_RRC_MAC_BCCH_DATA_IND (message_p).is_bch = (channel == NR_BCCH_BCH); - itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); } + else { + NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = 0; + } + NR_RRC_MAC_BCCH_DATA_IND (message_p).frame = frame; //frameP + NR_RRC_MAC_BCCH_DATA_IND (message_p).slot = slot; + NR_RRC_MAC_BCCH_DATA_IND (message_p).gnb_index = gNB_index; + NR_RRC_MAC_BCCH_DATA_IND (message_p).phycellid = cellid; + NR_RRC_MAC_BCCH_DATA_IND (message_p).ssb_arfcn = arfcn; + NR_RRC_MAC_BCCH_DATA_IND (message_p).is_bch = (channel == NR_BCCH_BCH); + itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); break; - case NR_SBCCH_SL_BCH: if (pdu_len > 0) { LOG_T(NR_RRC, "[UE %d] Received SL-MIB for NR_SBCCH_SL_BCH.\n", module_id); - - MessageDef *message_p; int msg_sdu_size = BCCH_SDU_SIZE; if (pdu_len > msg_sdu_size) { @@ -115,9 +117,8 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); } break; - default: - break; + AssertFatal(false, "Invalid channel in data indication\n"); } } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index dc1cb72baa..57ba669aeb 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -185,62 +185,62 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, for (int i = 0; i < si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count; i++) { SystemInformation_IEs__sib_TypeAndInfo__Member *typeandinfo; typeandinfo = si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.array[i]; - LOG_I(NR_RRC, "Found SIB%d\n", typeandinfo->present + 1); + LOG_A(NR_RRC, "Found SIB%d\n", typeandinfo->present + 1); switch(typeandinfo->present) { case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2: - SI_info->sib2_validity = SIB_VALID; + SI_info->sib2_validity = true; nr_timer_start(&SI_info->sib2_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3: - SI_info->sib3_validity = SIB_VALID; + SI_info->sib3_validity = true; nr_timer_start(&SI_info->sib3_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib4: - SI_info->sib4_validity = SIB_VALID; + SI_info->sib4_validity = true; nr_timer_start(&SI_info->sib4_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib5: - SI_info->sib5_validity = SIB_VALID; + SI_info->sib5_validity = true; nr_timer_start(&SI_info->sib5_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib6: - SI_info->sib6_validity = SIB_VALID; + SI_info->sib6_validity = true; nr_timer_start(&SI_info->sib6_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib7: - SI_info->sib7_validity = SIB_VALID; + SI_info->sib7_validity = true; nr_timer_start(&SI_info->sib7_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib8: - SI_info->sib8_validity = SIB_VALID; + SI_info->sib8_validity = true; nr_timer_start(&SI_info->sib8_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib9: - SI_info->sib9_validity = SIB_VALID; + SI_info->sib9_validity = true; nr_timer_start(&SI_info->sib9_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib10_v1610: - SI_info->sib10_validity = SIB_VALID; + SI_info->sib10_validity = true; nr_timer_start(&SI_info->sib10_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib11_v1610: - SI_info->sib11_validity = SIB_VALID; + SI_info->sib11_validity = true; nr_timer_start(&SI_info->sib11_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib12_v1610: - SI_info->sib12_validity = SIB_VALID; + SI_info->sib12_validity = true; nr_timer_start(&SI_info->sib12_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib13_v1610: - SI_info->sib13_validity = SIB_VALID; + SI_info->sib13_validity = true; nr_timer_start(&SI_info->sib13_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib14_v1610: - SI_info->sib14_validity = SIB_VALID; + SI_info->sib14_validity = true; nr_timer_start(&SI_info->sib14_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700: - SI_info->SInfo_r17.sib19_validity = SIB_VALID; + SI_info->SInfo_r17.sib19_validity = true; if (g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) xer_fprint(stdout, &asn_DEF_NR_SIB19_r17, (const void *)typeandinfo->choice.sib19_v1700); sib19 = typeandinfo->choice.sib19_v1700; @@ -282,28 +282,34 @@ static void nr_rrc_ue_prepare_RRCSetupRequest(NR_UE_RRC_INST_t *rrc) } static void nr_rrc_configure_default_SI(NR_UE_RRC_SI_INFO *SI_info, - struct NR_SI_SchedulingInfo *si_SchedulingInfo, - struct NR_SI_SchedulingInfo_v1700 *si_SchedulingInfo_v1700) + NR_SI_SchedulingInfo_t *si_SchedulingInfo, + NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700) { + for (int i = 0; i < MAX_SI_GROUPS; i++) + SI_info->default_otherSI_map[i] = 0; + int nb_groups = 0; if (si_SchedulingInfo) { - SI_info->default_otherSI_map = 0; - for (int i = 0; i < si_SchedulingInfo->schedulingInfoList.list.count; i++) { - struct NR_SchedulingInfo *schedulingInfo = si_SchedulingInfo->schedulingInfoList.list.array[i]; + nb_groups = si_SchedulingInfo->schedulingInfoList.list.count; + AssertFatal(nb_groups <= MAX_SI_GROUPS, "Exceeding max number of SI groups configured\n"); + for (int i = 0; i < nb_groups; i++) { + NR_SchedulingInfo_t *schedulingInfo = si_SchedulingInfo->schedulingInfoList.list.array[i]; for (int j = 0; j < schedulingInfo->sib_MappingInfo.list.count; j++) { - struct NR_SIB_TypeInfo *sib_Type = schedulingInfo->sib_MappingInfo.list.array[j]; - SI_info->default_otherSI_map |= 1 << sib_Type->type; + NR_SIB_TypeInfo_t *sib_Type = schedulingInfo->sib_MappingInfo.list.array[j]; + SI_info->default_otherSI_map[i] |= 1 << sib_Type->type; } } } if (si_SchedulingInfo_v1700) { - SI_info->SInfo_r17.default_otherSI_map_r17 = 0; + int start_idx = nb_groups; + nb_groups += si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.count; + AssertFatal(nb_groups <= MAX_SI_GROUPS, "Exceeding max number of SI groups configured\n"); for (int i = 0; i < si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.count; i++) { - struct NR_SchedulingInfo2_r17 *schedulingInfo2 = si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.array[i]; + NR_SchedulingInfo2_r17_t *schedulingInfo2 = si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.array[i]; for (int j = 0; j < schedulingInfo2->sib_MappingInfo_r17.list.count; j++) { - struct NR_SIB_TypeInfo_v1700 *sib_TypeInfo_v1700 = schedulingInfo2->sib_MappingInfo_r17.list.array[j]; + NR_SIB_TypeInfo_v1700_t *sib_TypeInfo_v1700 = schedulingInfo2->sib_MappingInfo_r17.list.array[j]; if (sib_TypeInfo_v1700->sibType_r17.present == NR_SIB_TypeInfo_v1700__sibType_r17_PR_type1_r17) { - SI_info->SInfo_r17.default_otherSI_map_r17 |= 1 << sib_TypeInfo_v1700->sibType_r17.choice.type1_r17; + SI_info->default_otherSI_map[start_idx + i] |= 1 << (sib_TypeInfo_v1700->sibType_r17.choice.type1_r17 + 13); } } } @@ -318,11 +324,14 @@ static bool verify_NTN_access(const NR_UE_RRC_SI_INFO *SI_info, const NR_SIB1_v1 && *sib1_v1700->cellBarredNTN_r17 == NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred) ntn_access = true; - uint32_t sib19_mask = 1 << NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19; - int sib19_present = SI_info->SInfo_r17.default_otherSI_map_r17 & sib19_mask; - + uint32_t sib19_mask = 1 << (NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19 + 13); + int sib19_present = false; + for (int i = 0; i < MAX_SI_GROUPS; i++) { + sib19_present = SI_info->default_otherSI_map[i] & sib19_mask; + if (sib19_present) + break; + } AssertFatal(!ntn_access || sib19_present, "NTN cell, but SIB19 not configured.\n"); - return ntn_access && sib19_present; } @@ -332,7 +341,7 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) sib1); LOG_A(NR_RRC, "SIB1 decoded\n"); nr_timer_start(&SI_info->sib1_timer); - SI_info->sib1_validity = SIB_VALID; + SI_info->sib1_validity = true; if (rrc->nrRrcState == RRC_STATE_IDLE_NR) { rrc->ra_trigger = RRC_CONNECTION_SETUP; } @@ -649,82 +658,56 @@ bool check_si_validity(NR_UE_RRC_SI_INFO *SI_info, int si_type) { switch (si_type) { case NR_SIB_TypeInfo__type_sibType2: - if (SI_info->sib2_validity == SIB_NOT_VALID) { - SI_info->sib2_validity = SIB_REQUESTED; + if (!SI_info->sib2_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType3: - if (SI_info->sib3_validity == SIB_NOT_VALID) { - SI_info->sib3_validity = SIB_REQUESTED; + if (!SI_info->sib3_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType4: - if (SI_info->sib4_validity == SIB_NOT_VALID) { - SI_info->sib4_validity = SIB_REQUESTED; + if (!SI_info->sib4_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType5: - if (SI_info->sib5_validity == SIB_NOT_VALID) { - SI_info->sib5_validity = SIB_REQUESTED; + if (!SI_info->sib5_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType6: - if (SI_info->sib6_validity == SIB_NOT_VALID) { - SI_info->sib6_validity = SIB_REQUESTED; + if (!SI_info->sib6_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType7: - if (SI_info->sib7_validity == SIB_NOT_VALID) { - SI_info->sib7_validity = SIB_REQUESTED; + if (!SI_info->sib7_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType8: - if (SI_info->sib8_validity == SIB_NOT_VALID) { - SI_info->sib8_validity = SIB_REQUESTED; + if (!SI_info->sib8_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType9: - if (SI_info->sib9_validity == SIB_NOT_VALID) { - SI_info->sib9_validity = SIB_REQUESTED; + if (!SI_info->sib9_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType10_v1610: - if (SI_info->sib10_validity == SIB_NOT_VALID) { - SI_info->sib10_validity = SIB_REQUESTED; + if (!SI_info->sib10_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType11_v1610: - if (SI_info->sib11_validity == SIB_NOT_VALID) { - SI_info->sib11_validity = SIB_REQUESTED; + if (!SI_info->sib11_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType12_v1610: - if (SI_info->sib12_validity == SIB_NOT_VALID) { - SI_info->sib12_validity = SIB_REQUESTED; + if (!SI_info->sib12_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType13_v1610: - if (SI_info->sib13_validity == SIB_NOT_VALID) { - SI_info->sib13_validity = SIB_REQUESTED; + if (!SI_info->sib13_validity) return false; - } break; case NR_SIB_TypeInfo__type_sibType14_v1610: - if (SI_info->sib14_validity == SIB_NOT_VALID) { - SI_info->sib14_validity = SIB_REQUESTED; + if (!SI_info->sib14_validity) return false; - } break; default : AssertFatal(false, "Invalid SIB type %d\n", si_type); @@ -736,46 +719,32 @@ bool check_si_validity_r17(NR_UE_RRC_SI_INFO_r17 *SI_info, int si_type) { switch (si_type) { case NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType15: - if (SI_info->sib15_validity == SIB_NOT_VALID) { - SI_info->sib15_validity = SIB_REQUESTED; + if (!SI_info->sib15_validity) return false; - } break; case NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType16: - if (SI_info->sib16_validity == SIB_NOT_VALID) { - SI_info->sib16_validity = SIB_REQUESTED; + if (!SI_info->sib16_validity) return false; - } break; case NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType17: - if (SI_info->sib17_validity == SIB_NOT_VALID) { - SI_info->sib17_validity = SIB_REQUESTED; + if (!SI_info->sib17_validity) return false; - } break; case NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType18: - if (SI_info->sib18_validity == SIB_NOT_VALID) { - SI_info->sib18_validity = SIB_REQUESTED; + if (!SI_info->sib18_validity) return false; - } break; case NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19: - if (SI_info->sib19_validity == SIB_NOT_VALID) { - SI_info->sib19_validity = SIB_REQUESTED; + if (!SI_info->sib19_validity) return false; - } break; case NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType20: - if (SI_info->sib20_validity == SIB_NOT_VALID) { - SI_info->sib20_validity = SIB_REQUESTED; + if (!SI_info->sib20_validity) return false; - } break; case NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType21: - if (SI_info->sib21_validity == SIB_NOT_VALID) { - SI_info->sib21_validity = SIB_REQUESTED; + if (!SI_info->sib21_validity) return false; - } break; default : AssertFatal(false, "Invalid SIB r17 type %d\n", si_type); @@ -783,39 +752,28 @@ bool check_si_validity_r17(NR_UE_RRC_SI_INFO_r17 *SI_info, int si_type) return true; } -int check_si_status(NR_UE_RRC_SI_INFO *SI_info) +static int check_si_status(NR_UE_RRC_SI_INFO *SI_info) { // schedule reception of SIB1 if RRC doesn't have it - if (SI_info->sib1_validity == SIB_NOT_VALID) { - SI_info->sib1_validity = SIB_REQUESTED; + if (!SI_info->sib1_validity) return 1; - } else { - if (SI_info->default_otherSI_map) { + for (int j = 0; j < MAX_SI_GROUPS; j++) { + if (!SI_info->default_otherSI_map[j]) + continue; // Check if RRC has configured default SI - // from SIB2 to SIB14 as current ASN1 version // TODO can be used for on demand SI when (if) implemented - for (int i = 2; i < 15; i++) { - int si_index = i - 2; - if ((SI_info->default_otherSI_map >> si_index) & 0x01) { - // if RRC has no valid version of one of the default configured SI - // Then schedule reception of otherSI - if (!check_si_validity(SI_info, si_index)) - return 2; - } - } - } - - // Check if RRC has configured default SI - // from SIB15 to SIB21 as current r17 version - if (SI_info->SInfo_r17.default_otherSI_map_r17) { - for (int i = 15; i < 22; i++) { - int si_index = i - 15; - if ((SI_info->SInfo_r17.default_otherSI_map_r17 >> si_index) & 0x01) { - // if RRC has no valid version of one of the default configured SI - // Then schedule reception of otherSI - if (!check_si_validity_r17(&SI_info->SInfo_r17, si_index)) - return 2; + for (int i = 2; i < 22; i++) { + if (!((SI_info->default_otherSI_map[j] >> (i - 2)) & 0x01)) + continue; + // if RRC has no valid version of one of the default configured SI + // Then schedule reception of otherSI + if (i < 15) { + if (!check_si_validity(SI_info, i - 2)) + return 2 + j; + } else { + if (!check_si_validity_r17(&SI_info->SInfo_r17, i - 15)) + return 2 + j; } } } @@ -861,12 +819,17 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, // not used } + NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; int get_sib = 0; - if (IS_SA_MODE(get_softmodem_params()) && bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib - && bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred && rrc->nrRrcState != RRC_STATE_DETACH_NR) { - NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; + if (IS_SA_MODE(get_softmodem_params()) + && !SI_info->sib_pending + && bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib + && bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred + && rrc->nrRrcState != RRC_STATE_DETACH_NR) { // to schedule MAC to get SI if required get_sib = check_si_status(SI_info); + if (get_sib) + SI_info->sib_pending = true; } if (bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_MIB); @@ -956,18 +919,20 @@ static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti) } } -static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, - const uint8_t gNB_index, - uint8_t *const Sdu, - const uint8_t Sdu_len, - const uint8_t rsrq, - const uint8_t rsrp) +static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, + const uint8_t gNB_index, + uint8_t *const Sdu, + const uint8_t Sdu_len, + const uint8_t rsrq, + const uint8_t rsrp) { - NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN); + SI_info->sib_pending = false; + if (Sdu_len == 0) // decoding failed in L2 + return; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN); + NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_BCCH_DL_SCH_Message, (void **)&bcch_message, @@ -980,7 +945,7 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, // free the memory SEQUENCE_free(&asn_DEF_NR_BCCH_DL_SCH_Message, (void *)bcch_message, 1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); - return -1; + return; } if (LOG_DEBUGFLAG(DEBUG_ASN1)) { @@ -1006,7 +971,6 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, } SEQUENCE_free(&asn_DEF_NR_BCCH_DL_SCH_Message, bcch_message, ASFM_FREE_EVERYTHING); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); - return 0; } static void nr_rrc_signal_maxrtxindication(int ue_id) @@ -2617,27 +2581,28 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, rrcPerNB_t *nb = &rrc->perNB[i]; NR_UE_RRC_SI_INFO *SI_info = &nb->SInfo; init_SI_timers(SI_info); - SI_info->sib1_validity = SIB_NOT_VALID; - SI_info->sib2_validity = SIB_NOT_VALID; - SI_info->sib3_validity = SIB_NOT_VALID; - SI_info->sib4_validity = SIB_NOT_VALID; - SI_info->sib5_validity = SIB_NOT_VALID; - SI_info->sib6_validity = SIB_NOT_VALID; - SI_info->sib7_validity = SIB_NOT_VALID; - SI_info->sib8_validity = SIB_NOT_VALID; - SI_info->sib9_validity = SIB_NOT_VALID; - SI_info->sib10_validity = SIB_NOT_VALID; - SI_info->sib11_validity = SIB_NOT_VALID; - SI_info->sib12_validity = SIB_NOT_VALID; - SI_info->sib13_validity = SIB_NOT_VALID; - SI_info->sib14_validity = SIB_NOT_VALID; - SI_info->SInfo_r17.sib15_validity = SIB_NOT_VALID; - SI_info->SInfo_r17.sib16_validity = SIB_NOT_VALID; - SI_info->SInfo_r17.sib17_validity = SIB_NOT_VALID; - SI_info->SInfo_r17.sib18_validity = SIB_NOT_VALID; - SI_info->SInfo_r17.sib19_validity = SIB_NOT_VALID; - SI_info->SInfo_r17.sib20_validity = SIB_NOT_VALID; - SI_info->SInfo_r17.sib21_validity = SIB_NOT_VALID; + SI_info->sib_pending = false; + SI_info->sib1_validity = false; + SI_info->sib2_validity = false; + SI_info->sib3_validity = false; + SI_info->sib4_validity = false; + SI_info->sib5_validity = false; + SI_info->sib6_validity = false; + SI_info->sib7_validity = false; + SI_info->sib8_validity = false; + SI_info->sib9_validity = false; + SI_info->sib10_validity = false; + SI_info->sib11_validity = false; + SI_info->sib12_validity = false; + SI_info->sib13_validity = false; + SI_info->sib14_validity = false; + SI_info->SInfo_r17.sib15_validity = false; + SI_info->SInfo_r17.sib16_validity = false; + SI_info->SInfo_r17.sib17_validity = false; + SI_info->SInfo_r17.sib18_validity = false; + SI_info->SInfo_r17.sib19_validity = false; + SI_info->SInfo_r17.sib20_validity = false; + SI_info->SInfo_r17.sib21_validity = false; } if (rrc->nrRrcState == RRC_STATE_DETACH_NR) { diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index ee46a343d7..d300d2a7b8 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -104,59 +104,53 @@ typedef enum RA_trigger_e { BEAM_FAILURE_RECOVERY, } RA_trigger_t; -typedef enum { - SIB_NOT_VALID, - SIB_VALID, - SIB_REQUESTED, -} SIB_validity_t; - typedef struct UE_RRC_SI_INFO_NR_r17_s { - uint32_t default_otherSI_map_r17; - SIB_validity_t sib15_validity; + bool sib15_validity; NR_timer_t sib15_timer; - SIB_validity_t sib16_validity; + bool sib16_validity; NR_timer_t sib16_timer; - SIB_validity_t sib17_validity; + bool sib17_validity; NR_timer_t sib17_timer; - SIB_validity_t sib18_validity; + bool sib18_validity; NR_timer_t sib18_timer; - SIB_validity_t sib19_validity; + bool sib19_validity; NR_timer_t sib19_timer; - SIB_validity_t sib20_validity; + bool sib20_validity; NR_timer_t sib20_timer; - SIB_validity_t sib21_validity; + bool sib21_validity; NR_timer_t sib21_timer; } NR_UE_RRC_SI_INFO_r17; typedef struct UE_RRC_SI_INFO_NR_s { - uint32_t default_otherSI_map; - SIB_validity_t sib1_validity; + bool sib_pending; + uint32_t default_otherSI_map[MAX_SI_GROUPS]; + bool sib1_validity; NR_timer_t sib1_timer; - SIB_validity_t sib2_validity; + bool sib2_validity; NR_timer_t sib2_timer; - SIB_validity_t sib3_validity; + bool sib3_validity; NR_timer_t sib3_timer; - SIB_validity_t sib4_validity; + bool sib4_validity; NR_timer_t sib4_timer; - SIB_validity_t sib5_validity; + bool sib5_validity; NR_timer_t sib5_timer; - SIB_validity_t sib6_validity; + bool sib6_validity; NR_timer_t sib6_timer; - SIB_validity_t sib7_validity; + bool sib7_validity; NR_timer_t sib7_timer; - SIB_validity_t sib8_validity; + bool sib8_validity; NR_timer_t sib8_timer; - SIB_validity_t sib9_validity; + bool sib9_validity; NR_timer_t sib9_timer; - SIB_validity_t sib10_validity; + bool sib10_validity; NR_timer_t sib10_timer; - SIB_validity_t sib11_validity; + bool sib11_validity; NR_timer_t sib11_timer; - SIB_validity_t sib12_validity; + bool sib12_validity; NR_timer_t sib12_timer; - SIB_validity_t sib13_validity; + bool sib13_validity; NR_timer_t sib13_timer; - SIB_validity_t sib14_validity; + bool sib14_validity; NR_timer_t sib14_timer; NR_UE_RRC_SI_INFO_r17 SInfo_r17; } NR_UE_RRC_SI_INFO; diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 39e73fa5a4..6629055b3a 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -43,33 +43,83 @@ void init_SI_timers(NR_UE_RRC_SI_INFO *SInfo) nr_timer_setup(&SInfo->SInfo_r17.sib19_timer, 10800000, 10); } -static SIB_validity_t check_sib_timer_validity(SIB_validity_t sib_validity, NR_timer_t *sib_timer) -{ - if (sib_validity == SIB_VALID) { - bool sib_expired = nr_timer_tick(sib_timer); - if (sib_expired) - return SIB_NOT_VALID; - } - return sib_validity; -} - void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo) { - SInfo->sib1_validity = check_sib_timer_validity(SInfo->sib1_validity, &SInfo->sib1_timer); - SInfo->sib2_validity = check_sib_timer_validity(SInfo->sib2_validity, &SInfo->sib2_timer); - SInfo->sib3_validity = check_sib_timer_validity(SInfo->sib3_validity, &SInfo->sib3_timer); - SInfo->sib4_validity = check_sib_timer_validity(SInfo->sib4_validity, &SInfo->sib4_timer); - SInfo->sib5_validity = check_sib_timer_validity(SInfo->sib5_validity, &SInfo->sib5_timer); - SInfo->sib6_validity = check_sib_timer_validity(SInfo->sib6_validity, &SInfo->sib6_timer); - SInfo->sib7_validity = check_sib_timer_validity(SInfo->sib7_validity, &SInfo->sib7_timer); - SInfo->sib8_validity = check_sib_timer_validity(SInfo->sib8_validity, &SInfo->sib8_timer); - SInfo->sib9_validity = check_sib_timer_validity(SInfo->sib9_validity, &SInfo->sib9_timer); - SInfo->sib10_validity = check_sib_timer_validity(SInfo->sib10_validity, &SInfo->sib10_timer); - SInfo->sib11_validity = check_sib_timer_validity(SInfo->sib11_validity, &SInfo->sib11_timer); - SInfo->sib12_validity = check_sib_timer_validity(SInfo->sib12_validity, &SInfo->sib12_timer); - SInfo->sib13_validity = check_sib_timer_validity(SInfo->sib13_validity, &SInfo->sib13_timer); - SInfo->sib14_validity = check_sib_timer_validity(SInfo->sib14_validity, &SInfo->sib14_timer); - SInfo->SInfo_r17.sib19_validity = check_sib_timer_validity(SInfo->SInfo_r17.sib19_validity, &SInfo->SInfo_r17.sib19_timer); + if (SInfo->sib1_validity) { + bool sib1_expired = nr_timer_tick(&SInfo->sib1_timer); + if (sib1_expired) + SInfo->sib1_validity = false; + } + if (SInfo->sib2_validity) { + bool sib2_expired = nr_timer_tick(&SInfo->sib2_timer); + if (sib2_expired) + SInfo->sib2_validity = false; + } + if (SInfo->sib3_validity) { + bool sib3_expired = nr_timer_tick(&SInfo->sib3_timer); + if (sib3_expired) + SInfo->sib3_validity = false; + } + if (SInfo->sib4_validity) { + bool sib4_expired = nr_timer_tick(&SInfo->sib4_timer); + if (sib4_expired) + SInfo->sib4_validity = false; + } + if (SInfo->sib5_validity) { + bool sib5_expired = nr_timer_tick(&SInfo->sib5_timer); + if (sib5_expired) + SInfo->sib5_validity = false; + } + if (SInfo->sib6_validity) { + bool sib6_expired = nr_timer_tick(&SInfo->sib6_timer); + if (sib6_expired) + SInfo->sib6_validity = false; + } + if (SInfo->sib7_validity) { + bool sib7_expired = nr_timer_tick(&SInfo->sib7_timer); + if (sib7_expired) + SInfo->sib7_validity = false; + } + if (SInfo->sib8_validity) { + bool sib8_expired = nr_timer_tick(&SInfo->sib8_timer); + if (sib8_expired) + SInfo->sib8_validity = false; + } + if (SInfo->sib9_validity) { + bool sib9_expired = nr_timer_tick(&SInfo->sib9_timer); + if (sib9_expired) + SInfo->sib9_validity = false; + } + if (SInfo->sib10_validity) { + bool sib10_expired = nr_timer_tick(&SInfo->sib10_timer); + if (sib10_expired) + SInfo->sib10_validity = false; + } + if (SInfo->sib11_validity) { + bool sib11_expired = nr_timer_tick(&SInfo->sib11_timer); + if (sib11_expired) + SInfo->sib11_validity = false; + } + if (SInfo->sib12_validity) { + bool sib12_expired = nr_timer_tick(&SInfo->sib12_timer); + if (sib12_expired) + SInfo->sib12_validity = false; + } + if (SInfo->sib13_validity) { + bool sib13_expired = nr_timer_tick(&SInfo->sib13_timer); + if (sib13_expired) + SInfo->sib13_validity = false; + } + if (SInfo->sib14_validity) { + bool sib14_expired = nr_timer_tick(&SInfo->sib14_timer); + if (sib14_expired) + SInfo->sib14_validity = false; + } + if (SInfo->SInfo_r17.sib19_validity) { + bool sib19_expired = nr_timer_tick(&SInfo->SInfo_r17.sib19_timer); + if (sib19_expired) + SInfo->SInfo_r17.sib19_validity = false; + } } void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) diff --git a/openair2/X2AP/MESSAGES/CMakeLists.txt b/openair2/X2AP/MESSAGES/CMakeLists.txt index 679ab8aca2..755a13c7c1 100644 --- a/openair2/X2AP/MESSAGES/CMakeLists.txt +++ b/openair2/X2AP/MESSAGES/CMakeLists.txt @@ -9,10 +9,11 @@ else() message(FATAL_ERROR "unknown X2AP_RELEASE ${X2AP_RELEASE}") endif() -add_custom_command(OUTPUT ${x2ap_source} ${x2ap_headers} - COMMAND ASN1C_PREFIX=X2AP_ ${ASN1C_EXEC} -pdu=all -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${X2AP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${X2AP_GRAMMAR} - COMMENT "Generating X2AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${X2AP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${X2AP_GRAMMAR} + "X2AP_" + OUTPUT ${x2ap_source} ${x2ap_headers} + OPTIONS -pdu=all -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps + COMMENT "X2AP source files" ) add_library(asn1_x2ap ${x2ap_source}) diff --git a/openair2/XNAP/MESSAGES/CMakeLists.txt b/openair2/XNAP/MESSAGES/CMakeLists.txt index 078388e3c0..92528fc73f 100644 --- a/openair2/XNAP/MESSAGES/CMakeLists.txt +++ b/openair2/XNAP/MESSAGES/CMakeLists.txt @@ -9,11 +9,12 @@ else() message(FATAL_ERROR "unknown XNAP_RELEASE ${XNAP_RELEASE}") endif() -add_custom_command(OUTPUT ${xnap_source} ${xnap_headers} - COMMAND ASN1C_PREFIX=XNAP_ ${ASN1C_EXEC} -pdu=all -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -findirect-choice -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${XNAP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${XNAP_GRAMMAR} - COMMENT "Generating XNAP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${XNAP_GRAMMAR}" - ) +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${XNAP_GRAMMAR} + "XNAP_" + OUTPUT ${xnap_source} ${xnap_headers} + OPTIONS -pdu=all -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -findirect-choice + COMMENT "XnAP source files" +) add_library(asn1_xnap ${xnap_source}) target_include_directories(asn1_xnap PUBLIC "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/openair3/LPP/MESSAGES/CMakeLists.txt b/openair3/LPP/MESSAGES/CMakeLists.txt index 0ffdf87113..b340a6ad51 100644 --- a/openair3/LPP/MESSAGES/CMakeLists.txt +++ b/openair3/LPP/MESSAGES/CMakeLists.txt @@ -9,10 +9,11 @@ include(ASN1/37355-g60.cmake) # message(FATAL_ERROR "unknown LPP_RELEASE ${LPP_RELEASE}") #endif() -add_custom_command(OUTPUT ${lpp_source} ${lpp_headers} - COMMAND ASN1C_PREFIX=LPP_ ${ASN1C_EXEC} -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${LPP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${LPP_GRAMMAR} - COMMENT "Generating LPP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${LPP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${LPP_GRAMMAR} + "LPP_" + OUTPUT ${lpp_source} ${lpp_headers} + OPTIONS -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps + COMMENT "LPP source files" ) add_library(asn1_lpp ${lpp_source}) diff --git a/openair3/M3AP/MESSAGES/CMakeLists.txt b/openair3/M3AP/MESSAGES/CMakeLists.txt index 8b5512919d..52007b629d 100644 --- a/openair3/M3AP/MESSAGES/CMakeLists.txt +++ b/openair3/M3AP/MESSAGES/CMakeLists.txt @@ -16,10 +16,11 @@ else() message(FATAL_ERROR "unknown M3AP_RELEASE ${M3AP_RELEASE}") endif() -add_custom_command(OUTPUT ${m3ap_source} ${m3ap_headers} - COMMAND ASN1C_PREFIX=M3AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${M3AP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${M3AP_GRAMMAR} - COMMENT "Generating M3AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${M3AP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${M3AP_GRAMMAR} + "M3AP_" + OUTPUT ${m3ap_source} ${m3ap_headers} + OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps + COMMENT "M3AP source files" ) add_library(asn1_m3ap ${m3ap_source}) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt index 6947a3421c..c1a28a18f3 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(fgs_5gmm_lib OBJECT fgmm_lib.c fgs_service_request.c fgmm_service_accept.c + fgmm_service_reject.c RegistrationRequest.c RegistrationAccept.c FGSIdentityResponse.c diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c index e21bc141c4..323cffe7e7 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.c @@ -143,6 +143,14 @@ int decode_gprs_timer_ie(gprs_timer_t *timer, const byte_array_t *buffer) return decoded; } +/** @brief Equality check for GPRS Timer */ +bool eq_gprs_timer(const gprs_timer_t *a, const gprs_timer_t *b) +{ + _NAS_EQ_CHECK_INT(a->value, b->value); + _NAS_EQ_CHECK_INT(a->unit, b->unit); + return true; +} + /* Decode EAP Message (todo) */ int decode_eap_msg_ie(const byte_array_t *buffer) { diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h index b09f19b828..b757620506 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_lib.h @@ -151,6 +151,8 @@ static const text_info_t sa_iei_s[] = {FOREACH_SA_IEI(TO_TEXT)}; typedef enum { FOREACH_CAUSE(TO_ENUM) } cause_id_t; +static const text_info_t fgmm_cause_s[] = {FOREACH_CAUSE(TO_TEXT)}; + /* 10.5.7.3 3GPP TS 24.008 */ typedef struct { uint8_t value; @@ -161,6 +163,7 @@ int encode_pdu_session_ie(byte_array_t *buffer, nas_service_IEI_t iei, const uin int decode_pdu_session_ie(uint8_t *psi, const byte_array_t *buffer); int encode_gprs_timer_ie(byte_array_t *buffer, nas_service_IEI_t iei, const gprs_timer_t *timer); int decode_gprs_timer_ie(gprs_timer_t *timer, const byte_array_t *buffer); +bool eq_gprs_timer(const gprs_timer_t *a, const gprs_timer_t *b); int decode_eap_msg_ie(const byte_array_t *buffer); #endif /* FGS_LIB_H */ \ No newline at end of file diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c index 7130586326..797deede84 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_accept.c @@ -172,8 +172,8 @@ bool eq_service_accept(const fgs_service_accept_msg_t *a, const fgs_service_acce PRINT_NAS_ERROR("t3448 equality check failed\n"); return false; } - _NAS_EQ_CHECK_INT(a->t3448->value, b->t3448->value); - _NAS_EQ_CHECK_INT(a->t3448->unit, b->t3448->unit); + if (!eq_gprs_timer(a->t3448, b->t3448)) + return false; } return true; } diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c new file mode 100644 index 0000000000..74175fda36 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.c @@ -0,0 +1,154 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "fgmm_service_reject.h" +#include +#include // For htons and ntohs +#include // For malloc and free +#include "common/utils/ds/byte_array.h" +#include "common/utils/utils.h" +#include "fgmm_lib.h" + +#define SERVICE_REJECT_MIN_LEN 1 // 1 octet + +/** @brief Encode Service Reject (8.2.18 of 3GPP TS 24.501) */ +int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg_t *msg) +{ + if (buffer->len < SERVICE_REJECT_MIN_LEN) { + PRINT_NAS_ERROR("Failed to encode Service Reject: missing Cause IE!\n"); + return -1; + } + + byte_array_t ba = *buffer; // Local copy of buffer + int encoded = 0; + + // 5GMM cause (Mandatory) + buffer->buf[encoded++] = msg->cause; + UPDATE_BYTE_ARRAY(ba, 1); + + // PDU Session Status (Optional) + if (msg->has_psi_status) { + ENCODE_NAS_IE(ba, encode_pdu_session_ie(&ba, IEI_PDU_SESSION_STATUS, msg->psi_status), encoded); + } + + // T3446 Timer (Optional) + if (msg->t3446) { + ENCODE_NAS_IE(ba, encode_gprs_timer_ie(&ba, IEI_T3446_VALUE, msg->t3446), encoded); + } + + // T3448 Timer (Optional) + if (msg->t3448) { + ENCODE_NAS_IE(ba, encode_gprs_timer_ie(&ba, IEI_T3448_VALUE, msg->t3448), encoded); + } + + return encoded; +} + +/** @brief Decode Service Reject (8.2.18 of 3GPP TS 24.501) */ +int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer) +{ + if (buffer->len < SERVICE_REJECT_MIN_LEN) { + PRINT_NAS_ERROR("Nothing to decode: missing Cause IE!\n"); + return -1; + } + + byte_array_t ba = *buffer; // Local copy of buffer to be used in the decoding sub-functions + uint32_t decoded = 0; + + // Cause (Mandatory) + msg->cause = buffer->buf[decoded++]; + UPDATE_BYTE_ARRAY(ba, 1); + + // Decode Optional IEs + while (decoded < buffer->len) { + uint8_t iei = buffer->buf[decoded++]; + UPDATE_BYTE_ARRAY(ba, 1); // Skip IEI + + switch (iei) { + case IEI_PDU_SESSION_STATUS: + msg->has_psi_status = true; + DECODE_NAS_IE(ba, decode_pdu_session_ie(msg->psi_status, &ba), decoded); + break; + + case IEI_T3448_VALUE: + msg->t3448 = malloc_or_fail(sizeof(*msg->t3448)); + DECODE_NAS_IE(ba, decode_gprs_timer_ie(msg->t3448, (const byte_array_t *)&ba), decoded); + break; + + case IEI_T3446_VALUE: + msg->t3446 = malloc_or_fail(sizeof(*msg->t3446)); + DECODE_NAS_IE(ba, decode_gprs_timer_ie(msg->t3446, (const byte_array_t *)&ba), decoded); + break; + + case IEI_EAPMSG: + DECODE_NAS_IE(ba, decode_eap_msg_ie((const byte_array_t *)&ba), decoded); + break; + + case IEI_CAG_INFO_LIST: { + int cag_list_len = (buffer->buf[decoded] << 8) | buffer->buf[decoded + 1]; + int cag_len = cag_list_len + 2; // encoded content + 2 octets for the length IE + decoded += cag_len; + UPDATE_BYTE_ARRAY(ba, cag_len); + PRINT_NAS_ERROR("CAG information list IE in NAS Service Reject is not handled\n"); + } break; + + default: + PRINT_NAS_ERROR("Uknown or invalid NAS Service Reject IEI %d\n", iei); + return -1; + } + } + + return decoded; +} + +/** @brief Equality check for Service Reject (enc/dec) */ +bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reject_msg_t *b) +{ + _NAS_EQ_CHECK_INT(a->cause, b->cause); + _NAS_EQ_CHECK_INT(a->has_psi_status, b->has_psi_status); + if (a->has_psi_status && b->has_psi_status) { + for (int i = 0; i < MAX_NUM_PSI; i++) + _NAS_EQ_CHECK_INT(a->psi_status[i], b->psi_status[i]); + } + if (a->t3448 != NULL || b->t3448 != NULL) { + if (a->t3448 == NULL || b->t3448 == NULL) { + PRINT_NAS_ERROR("t3448 equality check failed\n"); + return false; + } + if (!eq_gprs_timer(a->t3448, b->t3448)) + return false; + } + if (a->t3446 != NULL || b->t3446 != NULL) { + if (a->t3446 == NULL || b->t3446 == NULL) { + PRINT_NAS_ERROR("t3448 equality check failed\n"); + return false; + } + if (!eq_gprs_timer(a->t3446, b->t3446)) + return false; + } + return true; +} + +void free_fgs_service_reject(fgs_service_reject_msg_t *msg) +{ + free(msg->t3446); + free(msg->t3448); +} diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h new file mode 100644 index 0000000000..61337d8525 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgmm_service_reject.h @@ -0,0 +1,45 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef FGS_service_reject_H +#define FGS_service_reject_H + +#include +#include "fgmm_lib.h" + +typedef struct { + // 5GMM cause (Mandatory) + cause_id_t cause; + // T3346 Value (Optional) + gprs_timer_t *t3446; + // PDU Session Status (Optional) + uint8_t psi_status[MAX_NUM_PSI]; + bool has_psi_status; + // T3448 Value (Optional) + gprs_timer_t *t3448; +} fgs_service_reject_msg_t; + +int decode_fgs_service_reject(fgs_service_reject_msg_t *msg, const byte_array_t *buffer); +int encode_fgs_service_reject(byte_array_t *buffer, const fgs_service_reject_msg_t *msg); +void free_fgs_service_reject(fgs_service_reject_msg_t *msg); +bool eq_service_reject(const fgs_service_reject_msg_t *a, const fgs_service_reject_msg_t *b); + +#endif /* FGS_service_reject_H */ diff --git a/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c b/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c index 12e69c1581..a73ee9b2be 100644 --- a/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c +++ b/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c @@ -5,6 +5,7 @@ #include "common/utils/ds/byte_array.h" #include "fgs_service_request.h" #include "fgmm_service_accept.h" +#include "fgmm_service_reject.h" #include "nr_nas_msg.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) @@ -127,9 +128,52 @@ static void test_service_accept(void) free_fgs_service_accept(&orig); } +/** @brief Test NAS Service Reject enc/dec */ +static void test_service_reject(void) +{ + // Dummy NAS Service Reject message + fgs_service_reject_msg_t orig = { + .cause = Illegal_UE, + .has_psi_status = true, + .t3446 = malloc_or_fail(sizeof(*orig.t3446)), + .t3448 = malloc_or_fail(sizeof(*orig.t3448)), + }; + orig.psi_status[1] = PDU_SESSION_INACTIVE; // PDU Session 1 + orig.psi_status[2] = PDU_SESSION_ACTIVE; // PDU Session 2 + orig.t3446->value = 10; + orig.t3446->unit = TWO_SECONDS; + orig.t3448->value = 1; + orig.t3448->unit = ONE_MINUTE; + + // Expected encoded data + uint8_t expected_enc[] = {0x03, 0x50, 0x02, 0x04, 0x00, 0x5F, 0x01, 0x0A, 0x6B, 0x01, 0x21}; + + // Buffer + uint8_t buf[64] = {0}; + byte_array_t buffer = {.buf = &buf[0], .len = sizeof(expected_enc)}; + + // Encode NAS Service Reject + int encoded_length = encode_fgs_service_reject(&buffer, &orig); + AssertFatal(encoded_length == sizeofArray(expected_enc), "encode_fgs_service_reject() failed: %d != %ld\n", encoded_length, sizeofArray(expected_enc)); + + // Compare the raw encoded buffer with expected encoded data + AssertFatal(memcmp(buffer.buf, expected_enc, buffer.len) == 0, "Encoding mismatch!\n"); + + // Decode NAS Service Reject + fgs_service_reject_msg_t dec = {0}; + int decoded_length = decode_fgs_service_reject(&dec, &buffer); + AssertFatal(decoded_length >= 0, "decode_fgs_service_reject() failed\n"); + + // Compare original and decoded messages + AssertFatal(eq_service_reject(&orig, &dec), "test_service_reject() failed: original and decoded messages do not match\n"); + free_fgs_service_reject(&dec); + free_fgs_service_reject(&orig); +} + int main() { test_service_request(); test_service_accept(); + test_service_reject(); return 0; } diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index b9b90ab339..941e0d7cdc 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -66,6 +66,7 @@ #include "openair2/SDAP/nr_sdap/nr_sdap.h" #include "fgs_nas_utils.h" #include "fgmm_service_accept.h" +#include "fgmm_service_reject.h" #define MAX_NAS_UE 4 @@ -1531,6 +1532,17 @@ static void handle_service_accept(nr_ue_nas_t *nas, const byte_array_t *buffer) print_info(msg.cause->cause, cause_text_info, sizeofArray(cause_text_info))); } +static void handle_service_reject(nr_ue_nas_t *nas, const byte_array_t *buffer) +{ + fgs_service_reject_msg_t msg = {0}; + decode_fgs_service_reject(&msg, buffer); + // Extract timer t3448 in seconds (optional IE) + nas->t3448 = process_gprs_timer(msg.t3448); + // Extract timer t3446 in seconds (optional IE) + nas->t3446 = process_gprs_timer(msg.t3446); + LOG_E(NAS, "Received NAS Service Reject message with cause %s\n", fgmm_cause_s[msg.cause].text); +} + void *nas_nrue(void *args_p) { // Wait for a message or an event @@ -1737,6 +1749,13 @@ void *nas_nrue(void *args_p) handle_service_accept(nas, &buffer); break; } + + case FGS_SERVICE_REJECT: { + byte_array_t buffer = {.buf = pdu_buffer, .len = pdu_length}; + handle_service_reject(nas, &buffer); + break; + } + default: LOG_W(NR_RRC, "unknown message type %d\n", msg_type); break; diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index 3bba6b1cec..c4f1d04e28 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -100,6 +100,8 @@ typedef struct { int t3512; // Timer t3448 in seconds (-1 = disabled) int t3448; + // Timer t3446 in seconds (-1 = disabled) + int t3446; } nr_ue_nas_t; nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); diff --git a/openair3/NGAP/MESSAGES/CMakeLists.txt b/openair3/NGAP/MESSAGES/CMakeLists.txt index 06148b6c5a..e5cfe07956 100644 --- a/openair3/NGAP/MESSAGES/CMakeLists.txt +++ b/openair3/NGAP/MESSAGES/CMakeLists.txt @@ -9,10 +9,11 @@ else() message(FATAL_ERROR "unknown NGAP_RELEASE ${NGAP_RELEASE}") endif() -add_custom_command(OUTPUT ${ngap_source} ${ngap_headers} - COMMAND ASN1C_PREFIX=NGAP_ ${ASN1C_EXEC} -pdu=all -fcompound-names -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -no-gen-example -fno-include-deps -findirect-choice -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${NGAP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${NGAP_GRAMMAR} - COMMENT "Generating NGAP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${NGAP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${NGAP_GRAMMAR} + "NGAP_" + OUTPUT ${ngap_source} ${ngap_headers} + OPTIONS -pdu=all -fcompound-names -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -no-gen-example -fno-include-deps -findirect-choice + COMMENT "NGAP source files" ) add_library(asn1_ngap ${ngap_source}) diff --git a/openair3/NRPPA/MESSAGES/CMakeLists.txt b/openair3/NRPPA/MESSAGES/CMakeLists.txt index 840553a62d..997fb70a9c 100644 --- a/openair3/NRPPA/MESSAGES/CMakeLists.txt +++ b/openair3/NRPPA/MESSAGES/CMakeLists.txt @@ -9,10 +9,11 @@ include(ASN1/38455.cmake) # message(FATAL_ERROR "unknown NRPPA_RELEASE ${NRPPA_RELEASE}") #endif() -add_custom_command(OUTPUT ${nrppa_source} ${nrppa_headers} - COMMAND ASN1C_PREFIX=NRPPA_ ${ASN1C_EXEC} -gen-APER -gen-UPER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${NRPPA_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${NRPPA_GRAMMAR} - COMMENT "Generating NRPPA source files from ${CMAKE_CURRENT_SOURCE_DIR}/${NRPPA_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${NRPPA_GRAMMAR} + "NRPPA_" + OUTPUT ${nrppa_source} ${nrppa_headers} + OPTIONS -gen-APER -gen-UPER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps + COMMENT "NRPPA source files" ) add_library(asn1_nrppa ${nrppa_source}) diff --git a/openair3/S1AP/MESSAGES/CMakeLists.txt b/openair3/S1AP/MESSAGES/CMakeLists.txt index bb1526b659..f38a3a93a6 100644 --- a/openair3/S1AP/MESSAGES/CMakeLists.txt +++ b/openair3/S1AP/MESSAGES/CMakeLists.txt @@ -9,10 +9,11 @@ else() message(FATAL_ERROR "unknown S1AP_RELEASE ${S1AP_RELEASE}") endif() -add_custom_command(OUTPUT ${s1ap_source} ${s1ap_headers} - COMMAND ASN1C_PREFIX=S1AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${S1AP_GRAMMAR} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${S1AP_GRAMMAR} - COMMENT "Generating S1AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${S1AP_GRAMMAR}" +run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${S1AP_GRAMMAR} + "S1AP_" + OUTPUT ${s1ap_source} ${s1ap_headers} + OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps + COMMENT "S1AP source files" ) add_library(asn1_s1ap ${s1ap_source}) diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c index 60d3afbe83..efeb03b25c 100644 --- a/radio/rfsimulator/apply_channelmod.c +++ b/radio/rfsimulator/apply_channelmod.c @@ -50,6 +50,8 @@ void rxAddInput(const c16_t *input_sig, uint32_t CirSize, bool add_noise) { + static uint64_t last_TS = 0; + if ((channelDesc->sat_height > 0) && (channelDesc->enable_dynamic_delay || channelDesc->enable_dynamic_Doppler)) { // model for transparent satellite on circular orbit /* assumptions: - The Earth is spherical, the ground station is static, and that the Earth does not rotate. @@ -82,42 +84,76 @@ void rxAddInput(const c16_t *input_sig, const double pos_ue_y = 0; const double pos_ue_z = radius_earth; - const double dir_sat_ue_x = pos_ue_x - pos_sat_x; - const double dir_sat_ue_y = pos_ue_y - pos_sat_y; - const double dir_sat_ue_z = pos_ue_z - pos_sat_z; - - const double dist_sat_ue = sqrt(dir_sat_ue_x * dir_sat_ue_x + dir_sat_ue_y * dir_sat_ue_y + dir_sat_ue_z * dir_sat_ue_z); - const double vel_sat_ue = (vel_sat_x * dir_sat_ue_x + vel_sat_y * dir_sat_ue_y + vel_sat_z * dir_sat_ue_z) / dist_sat_ue; - - double dist_gnb_sat = 0; - double vel_gnb_sat = 0; - if (channelDesc->modelid == SAT_LEO_TRANS) { - const double pos_gnb_x = 0; - const double pos_gnb_y = 0; - const double pos_gnb_z = radius_earth; - - const double dir_gnb_sat_x = pos_sat_x - pos_gnb_x; - const double dir_gnb_sat_y = pos_sat_y - pos_gnb_y; - const double dir_gnb_sat_z = pos_sat_z - pos_gnb_z; - - dist_gnb_sat = sqrt(dir_gnb_sat_x * dir_gnb_sat_x + dir_gnb_sat_y * dir_gnb_sat_y + dir_gnb_sat_z * dir_gnb_sat_z); - vel_gnb_sat = (vel_sat_x * dir_gnb_sat_x + vel_sat_y * dir_gnb_sat_y + vel_sat_z * dir_gnb_sat_z) / dist_gnb_sat; - } - const double c = 299792458; // m/s - const double prop_delay = (dist_gnb_sat + dist_sat_ue) / c; - if (channelDesc->enable_dynamic_delay) - channelDesc->channel_offset = prop_delay * channelDesc->sampling_rate; - const double f_Doppler_shift_sat_ue = (vel_sat_ue / (c - vel_sat_ue)) * channelDesc->center_freq; - const double f_Doppler_shift_gnb_sat = (-vel_gnb_sat / c) * channelDesc->center_freq; - if (channelDesc->enable_dynamic_Doppler) - channelDesc->Doppler_phase_inc = 2 * M_PI * (f_Doppler_shift_gnb_sat + f_Doppler_shift_sat_ue) / channelDesc->sampling_rate; + if (channelDesc->is_uplink) { + const double dir_ue_sat_x = pos_sat_x - pos_ue_x; + const double dir_ue_sat_y = pos_sat_y - pos_ue_y; + const double dir_ue_sat_z = pos_sat_z - pos_ue_z; - static uint64_t last_TS = 0; - if(TS - last_TS >= channelDesc->sampling_rate) { - last_TS = TS; - LOG_I(HW, "Satellite orbit: time %f s, Doppler: gNB->SAT %f kHz, SAT->UE %f kHz, Delay %f ms\n", t, f_Doppler_shift_gnb_sat / 1000, f_Doppler_shift_sat_ue / 1000, prop_delay * 1000); + const double dist_ue_sat = sqrt(dir_ue_sat_x * dir_ue_sat_x + dir_ue_sat_y * dir_ue_sat_y + dir_ue_sat_z * dir_ue_sat_z); + const double vel_ue_sat = (vel_sat_x * dir_ue_sat_x + vel_sat_y * dir_ue_sat_y + vel_sat_z * dir_ue_sat_z) / dist_ue_sat; + + double dist_sat_gnb = 0; + if (channelDesc->modelid == SAT_LEO_TRANS) { + const double pos_gnb_x = 0; + const double pos_gnb_y = 0; + const double pos_gnb_z = radius_earth; + + const double dir_sat_gnb_x = pos_gnb_x - pos_sat_x; + const double dir_sat_gnb_y = pos_gnb_y - pos_sat_y; + const double dir_sat_gnb_z = pos_gnb_z - pos_sat_z; + + dist_sat_gnb = sqrt(dir_sat_gnb_x * dir_sat_gnb_x + dir_sat_gnb_y * dir_sat_gnb_y + dir_sat_gnb_z * dir_sat_gnb_z); + } + + const double prop_delay = (dist_ue_sat + dist_sat_gnb) / c; + if (channelDesc->enable_dynamic_delay) + channelDesc->channel_offset = prop_delay * channelDesc->sampling_rate; + + const double f_Doppler_shift_ue_sat = (-vel_ue_sat / c) * channelDesc->center_freq; + if (channelDesc->enable_dynamic_Doppler) + channelDesc->Doppler_phase_inc = 2 * M_PI * f_Doppler_shift_ue_sat / channelDesc->sampling_rate; + + if(TS - last_TS >= channelDesc->sampling_rate) { + last_TS = TS; + LOG_D(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); + LOG_D(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000); + } + } else { + const double dir_sat_ue_x = pos_ue_x - pos_sat_x; + const double dir_sat_ue_y = pos_ue_y - pos_sat_y; + const double dir_sat_ue_z = pos_ue_z - pos_sat_z; + + const double dist_sat_ue = sqrt(dir_sat_ue_x * dir_sat_ue_x + dir_sat_ue_y * dir_sat_ue_y + dir_sat_ue_z * dir_sat_ue_z); + const double vel_sat_ue = (vel_sat_x * dir_sat_ue_x + vel_sat_y * dir_sat_ue_y + vel_sat_z * dir_sat_ue_z) / dist_sat_ue; + + double dist_gnb_sat = 0; + if (channelDesc->modelid == SAT_LEO_TRANS) { + const double pos_gnb_x = 0; + const double pos_gnb_y = 0; + const double pos_gnb_z = radius_earth; + + const double dir_gnb_sat_x = pos_sat_x - pos_gnb_x; + const double dir_gnb_sat_y = pos_sat_y - pos_gnb_y; + const double dir_gnb_sat_z = pos_sat_z - pos_gnb_z; + + dist_gnb_sat = sqrt(dir_gnb_sat_x * dir_gnb_sat_x + dir_gnb_sat_y * dir_gnb_sat_y + dir_gnb_sat_z * dir_gnb_sat_z); + } + + const double prop_delay = (dist_gnb_sat + dist_sat_ue) / c; + if (channelDesc->enable_dynamic_delay) + channelDesc->channel_offset = prop_delay * channelDesc->sampling_rate; + + const double f_Doppler_shift_sat_ue = (vel_sat_ue / (c - vel_sat_ue)) * channelDesc->center_freq; + if (channelDesc->enable_dynamic_Doppler) + channelDesc->Doppler_phase_inc = 2 * M_PI * f_Doppler_shift_sat_ue / channelDesc->sampling_rate; + + if(TS - last_TS >= channelDesc->sampling_rate) { + last_TS = TS; + LOG_D(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z); + LOG_D(HW, "Downlink delay %f ms, Doppler shift SAT->UE %f kHz\n", prop_delay * 1000, f_Doppler_shift_sat_ue / 1000); + } } } @@ -131,6 +167,8 @@ void rxAddInput(const c16_t *input_sig, const double noise_per_sample = add_noise ? pow(10,channelDesc->noise_power_dB/10.0) * 256 : 0; const uint64_t dd = channelDesc->channel_offset; const int nbTx=channelDesc->nb_tx; + double Doppler_phase_cur = channelDesc->Doppler_phase_cur[rxAnt]; + Doppler_phase_cur -= 2 * M_PI * round(Doppler_phase_cur / (2 * M_PI)); for (int i=0; iDoppler_phase_cur[rxAnt] * I); + double complex out = in * cexp(Doppler_phase_cur * I); rx_tmp.r = creal(out); rx_tmp.i = cimag(out); - channelDesc->Doppler_phase_cur[rxAnt] += channelDesc->Doppler_phase_inc; + Doppler_phase_cur += channelDesc->Doppler_phase_inc; } out_ptr->r += rx_tmp.r * pathLossLinear + noise_per_sample * gaussZiggurat(0.0, 1.0); @@ -172,6 +210,8 @@ void rxAddInput(const c16_t *input_sig, out_ptr++; } + channelDesc->Doppler_phase_cur[rxAnt] = Doppler_phase_cur; + if ( (TS*nbTx)%CirSize+nbSamples <= CirSize ) // Cast to a wrong type for compatibility ! LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n", diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index ca01a1768c..8070bf837e 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -274,6 +274,7 @@ static int allocCirBuf(rfsimulator_state_t *bridge, int sock) } set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID); + set_channeldesc_direction(ptr->channel_model, bridge->role == SIMU_ROLE_SERVER); random_channel(ptr->channel_model,false); LOG_I(HW, "Random channel %s in rfsimulator activated\n", modelname); } @@ -467,6 +468,7 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, t->chan_pathloss, 0); // noise_power set_channeldesc_owner(newmodel, RFSIMU_MODULEID); + set_channeldesc_direction(newmodel, t->role == SIMU_ROLE_SERVER); set_channeldesc_name(newmodel,modelname); random_channel(newmodel,false); channel_desc_t *oldmodel=b->channel_model; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf index 67be3dbb44..dd3307d32c 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf @@ -19,6 +19,8 @@ gNBs = sib1_tda = 5; min_rxtxtime = 6; disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; servingCellConfigCommon = ( { @@ -47,8 +49,8 @@ gNBs = # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 0; - initialDLBWPsearchSpaceZero = 0; + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 2; #uplinkConfigCommon #frequencyInfoUL diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf index 5a14f4fae6..7c2c3805ee 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf @@ -19,6 +19,8 @@ gNBs = sib1_tda = 5; min_rxtxtime = 6; disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; servingCellConfigCommon = ( { @@ -47,8 +49,8 @@ gNBs = # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 0; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 0; - initialDLBWPsearchSpaceZero = 0; + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 2; #uplinkConfigCommon #frequencyInfoUL diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf index c4213eb0d3..b720d6d720 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf @@ -19,6 +19,8 @@ gNBs = sib1_tda = 5; min_rxtxtime = 6; disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; servingCellConfigCommon = ( { @@ -47,8 +49,8 @@ gNBs = # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 0; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 0; - initialDLBWPsearchSpaceZero = 0; + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 2; #uplinkConfigCommon #frequencyInfoUL diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf index f9a0dfc372..a5e9841772 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -177,7 +177,7 @@ MACRLCs = ( pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; min_grant_prb = 20; - min_grant_mcs = 16; + ul_min_mcs = 16; dl_max_mcs = 10; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.51PRB.usrpb210.redcap.yaml b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml similarity index 93% rename from targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.51PRB.usrpb210.redcap.yaml rename to targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml index b3f43bfbd7..01c40ca3d7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.51PRB.usrpb210.redcap.yaml +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml @@ -35,7 +35,7 @@ gNBs: # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 dl_subcarrierSpacing: 1 - dl_carrierBandwidth: 51 + dl_carrierBandwidth: 106 #initialDownlinkBWP #genericParameters # this is RBstart=0,L=51 (275*(L-1))+RBstart @@ -54,7 +54,7 @@ gNBs: # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 ul_subcarrierSpacing: 1 - ul_carrierBandwidth: 51 + ul_carrierBandwidth: 106 pMax: 20 #initialUplinkBWP #genericParameters @@ -134,6 +134,18 @@ gNBs: nrofUplinkSymbols: 4 ssPBCH_BlockPower: -25 + + servingCellConfigDedicated: + - dl_bwp-Id_1: 1 + dl_bwp1_locationAndBandwidth: 28875 + dl_bwp1_subcarrierSpacing: 1 + firstActiveDownlinkBWP-Id: 1 + defaultDownlinkBWP-Id: 1 + ul_bwp-Id_1: 1 + ul_bwp1_locationAndBandwidth: 28875 + ul_bwp1_subcarrierSpacing: 1 + firstActiveUplinkBWP-Id: 1 + RedCap: cellBarredRedCap1Rx_r17: 1 cellBarredRedCap2Rx_r17: 1 diff --git a/tools/plots/README.md b/tools/plots/README.md index 5d5175a882..39f9fab6f1 100644 --- a/tools/plots/README.md +++ b/tools/plots/README.md @@ -19,3 +19,16 @@ Same goes for any software modifications of `nr_ulsim` - the cache is not aware the data - remember to clear your cache manually if you are comparing different `nr_ulsim` versions. The script also allows to skip usage of the cache with `--rerun` option. + +## `dl_graph.py` + +This generates plots from data saved from nr_dlsim. It takes data in two formats: + +1. Plots frequency domain channel estimates, constellation diagram and LLRs from data read in binary format. The data is generated from `nr_dlsim -w` +2. Plots BER (other also possible) from CSV data generated by `nr_dlsim -Z`. + +The plots are saved in three formats: `.png`, `.pdf` and `.svg`. + +### Example graphs: +#### BER +![image](./ber_compare.svg) diff --git a/tools/plots/ber_compare.svg b/tools/plots/ber_compare.svg new file mode 100644 index 0000000000..90d6827aad --- /dev/null +++ b/tools/plots/ber_compare.svg @@ -0,0 +1,1506 @@ + + + + + + + + 2025-03-27T13:43:33.593313 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/plots/dl_graph.py b/tools/plots/dl_graph.py new file mode 100644 index 0000000000..0fd1a8bc2b --- /dev/null +++ b/tools/plots/dl_graph.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# coding: utf-8 +import numpy as np +import matplotlib.pyplot as plt +import argparse +import pandas + +def save_fig(fig:plt.figure, figName:str): + fig.savefig(figName + '.pdf') + fig.savefig(figName + '.png') + fig.savefig(figName + '.svg') + +# Channel Frequency Response +def channel_est(dataPath): + binfile = dataPath + 'chestF0_ext_s1.m.bin' + data = np.fromfile(binfile,dtype=np.int16) + dataCmp = data[0::2] + 1j*data[1::2] + fig = plt.gcf() + plt.plot(np.abs(dataCmp)) + save_fig(fig, 'channel_est') + plt.close(fig) + +# Constellation +def constellation(dataPath): + binfile = dataPath + 'rxF_comp_s1.m.bin' + data = np.fromfile(binfile,dtype=np.int16) + dataCmp = data[0::2] + 1j*data[1::2] + fig = plt.gcf() + plt.scatter(np.real(dataCmp),np.imag(dataCmp)) + save_fig(fig, 'constellation') + plt.close(fig) + +# LLR +def llr(dataPath): + binfile = dataPath + 'rxF_llr.m.bin' + data = np.fromfile(binfile,dtype=np.int16) + fig = plt.gcf() + plt.plot(data,'*') + save_fig(fig, 'llr') + plt.close(fig) + +# BER from data in CSV files generated by nr_dlsim +def ber(dataPath, csvFiles): + d0 = pandas.read_csv(dataPath + csvFiles[0] + '.csv') + ax = d0.plot(x='SNR',y='channel_ber_0',logy=True,label=csvFiles[0]) + plt.ylabel('BER') + for i in range(1,len(csvFiles)): + d = pandas.read_csv(dataPath + csvFiles[i] + '.csv') + d.plot(ax=ax,x='SNR',y='channel_ber_0',logy=True,label=csvFiles[i],grid=True) + + fig = ax.figure + save_fig(fig, 'ber_compare') + plt.close(fig) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="DL plot generator") + parser.add_argument('--data-path', help='Path to directory containing data', default='../../cmake_targets/ran_build/build/') + parser.add_argument('--csv-data', nargs='+' ,help='CSV file name without extension (generated from nr_dlsim with -Z option)') + parser.add_argument('--ber-compare', help='Compare BER from multiple CSV files', action='store_true') + + args = parser.parse_args() + + channel_est(args.data_path) + constellation(args.data_path) + llr(args.data_path) + if args.ber_compare: + ber(args.data_path, args.csv_data)