diff --git a/CMakeLists.txt b/CMakeLists.txt index b8a1b3a082..1cb3e09736 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -517,6 +517,17 @@ add_library(x2ap target_link_libraries(x2ap PUBLIC asn1_x2ap) target_link_libraries(x2ap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +#XNAP +############## +set(XNAP_DIR ${OPENAIR2_DIR}/XNAP) +add_library(xnap + ${XNAP_DIR}/xnap_common.c + ) +target_include_directories(xnap PUBLIC XNAP_DIR) +target_link_libraries(xnap PUBLIC asn1_xnap) +target_link_libraries(xnap PRIVATE nr_rrc xnap_lib) +target_include_directories(xnap PRIVATE ${XNAP_DIR}/lib) + # F1AP ############## set(F1AP_DIR ${OPENAIR2_DIR}/F1AP) diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 65fd678b0f..3335658795 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -20,7 +20,7 @@ Ref : Slot Indication : 5.0 feprx : 43.0 feptx_ofdm (per port, half_slot) : 30 - feptx_total : 57 + feptx_total : 43 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 diff --git a/ci-scripts/xml_files/container_5g_vrtsim_multiue_gh.xml b/ci-scripts/xml_files/container_5g_vrtsim_multiue_gh.xml new file mode 100644 index 0000000000..c2da848374 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_vrtsim_multiue_gh.xml @@ -0,0 +1,183 @@ + + + vrtsim-5gnr-multiue-gh + Multi-UE gNB vrtsim + CIRDB + wrench + + + Pull_Local_Registry + Pull Images from Local Registry + localhost + oai-gnb oai-nr-ue + arm_ + + + + Create_Workspace + Create new Workspace + localhost + + + + Deploy_Object + Deploy OAI 5G CoreNetwork + localhost + ci-scripts/yaml_files/5g_vrtsim_multiue + mysql oai-amf oai-smf oai-upf oai-ext-dn + + + + Deploy_Object + Deploy OAI 5G gNB+UE RF sim SA + localhost + ci-scripts/yaml_files/5g_vrtsim_multiue + oai-gnb oai-nr-ue0 oai-nr-ue1 + + + + Attach_UE + Attach OAI UE 1 (Wait for IP) + rfsim5g_ue + localhost + + + + Attach_UE + Attach OAI UE 2 (Wait for IP) + rfsim5g_ue2 + localhost + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + -c 20 -i 0.25 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + localhost + rfsim5g_ue + localhost + -c 20 -i 0.25 + 5 + + + + Iperf + Iperf UE 1 (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 30 -R + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Iperf + Iperf UE 1 (UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Ping + Ping ext-dn from UE 2 + rfsim5g_ue2 + localhost + rfsim5g_ext_dn + localhost + -c 20 -i 0.25 + 5 + + + + Ping + Ping UE 2 from ext-dn + rfsim5g_ext_dn + localhost + rfsim5g_ue2 + localhost + -c 20 -i 0.25 + 5 + + + + Iperf + Iperf UE 2 (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 30 -R + rfsim5g_ue2 + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Iperf + Iperf UE 2 (UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 + rfsim5g_ue2 + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + localhost + ci-scripts/yaml_files/5g_vrtsim_multiue + + oai-gnb=EndsWithBye oai-nr-ue0 oai-nr-ue1 + + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + localhost + oai-gnb oai-nr-ue + + + diff --git a/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml new file mode 100644 index 0000000000..c87be3a998 --- /dev/null +++ b/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml @@ -0,0 +1,212 @@ +services: + # CIR Generator service - generates CIRDB files on every CI run + cir-generator: + image: oaisoftwarealliance/cir-generator:test + environment: + GENERATOR_ARGS: "--demo" + OUTPUT: "--out /opt/output/cir_db.bin" + volumes: + - cirdb_data:/opt/output + + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + init: true + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + start_period: 10s + start_interval: 500ms + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.1.10 + 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.1.10 + 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.1.10 + init: true + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml + depends_on: + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + networks: + public_net: + ipv4_address: 192.168.71.134 + interface_name: eth0 + traffic_net: + ipv4_address: 192.168.72.134 + interface_name: eth1 + + oai-ext-dn: + privileged: true + container_name: rfsim5g-oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:latest + init: true + entrypoint: /bin/bash -c \ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-upf + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + + oai-gnb: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.num_ues 2 --vrtsim.cirdb 1 --vrtsim.cirdb_file /cirdb/cir_db.bin --vrtsim.cirdb_yaml /cirdb/cir_db.yaml --vrtsim.ue_config.[0].antennas 1x2 --vrtsim.ue_config.[0].model_id 0 --vrtsim.ue_config.[0].ds_ns 10.0 --vrtsim.ue_config.[0].speed_mps 1.5 --vrtsim.ue_config.[1].antennas 2x2 --vrtsim.ue_config.[1].model_id 1 --vrtsim.ue_config.[1].ds_ns 10.0 --vrtsim.ue_config.[1].speed_mps 1.5 --gNBs.[0].min_rxtxtime 8 + depends_on: + cir-generator: + condition: service_completed_successfully + oai-ext-dn: + condition: service_started + networks: + public_net: + ipv4_address: 192.168.71.140 + volumes: + - ../../conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml:/opt/oai-gnb/etc/gnb.yaml + - cirdb_data:/cirdb:ro + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + start_period: 10s + start_interval: 500ms + retries: 5 + ipc: host + + oai-nr-ue0: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN + - NET_RAW + environment: + USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 0 --ue-nb-ant-tx 1 --ue-nb-ant-rx 2 + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.vrtsim.chanmod.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + ipc: host + + oai-nr-ue1: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue2 + cap_drop: + - ALL + cap_add: + - NET_ADMIN + - NET_RAW + environment: + USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001101 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 1 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.151 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.vrtsim.chanmod.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + ipc: host + +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" + +volumes: + tmp_data: + cirdb_data: diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 2652b29634..48be9ec905 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -325,7 +325,7 @@ install_bladerf_driver_from_source(){ rm -rf /tmp/bladeRF git clone https://github.com/Nuand/bladeRF.git cd bladeRF - git checkout tags/2016.06 + git checkout tags/2025.10 mkdir -p build cd build $CMAKE ../ @@ -337,14 +337,12 @@ install_bladerf_driver_from_source(){ check_install_bladerf_driver(){ if [[ "$OS_BASEDISTRO" == "debian" ]]; then - $SUDO apt-get install -y bladerf libbladerf-dev - $SUDO apt-get install -y bladerf-firmware-fx3 - $SUDO apt-get install -y bladerf-fpga-hostedx40 - elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then - install_bladerf_driver_from_source - else - echo_error "BladeRF Installer for OAI does not support automatic build. Install BladeRF compiling sources manually from BladeRF website" - fi + $SUDO apt-get update + $SUDO apt-get install -y libcurl4-openssl-dev + elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then + $SUDO dnf -y install libcurl-devel + fi + install_bladerf_driver_from_source } check_install_lmssdr_driver(){ @@ -358,8 +356,6 @@ check_install_lmssdr_driver(){ echo_info "https://wiki.myriadrf.org/Lime_Suite" echo_fatal "Cannot compile lmssdr device" fi - - } install_soapy_from_source(){ diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index 837c6897a6..b8ccedffbe 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -162,6 +162,7 @@ static const char *const flag_name[] = {FOREACH_FLAG(FLAG_TEXT) ""}; COMP_DEF(USIM, log) \ COMP_DEF(F1U, ) \ COMP_DEF(X2AP, ) \ + COMP_DEF(XNAP, ) \ COMP_DEF(M2AP, ) \ COMP_DEF(M3AP, ) \ COMP_DEF(NGAP, ) \ diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 818b30b7d0..432ad30262 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -628,6 +628,27 @@ ID = LEGACY_X2AP_TRACE GROUP = ALL:LEGACY_X2AP:LEGACY_GROUP_TRACE:LEGACY FORMAT = string,log +ID = LEGACY_XNAP_INFO + DESC = XNAP legacy logs - info level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_INFO:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_ERROR + DESC = XNAP legacy logs - error level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_ERROR:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_WARNING + DESC = XNAP legacy logs - warning level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_WARNING:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_DEBUG + DESC = XNAP legacy logs - debug level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_DEBUG:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_TRACE + DESC = XNAP legacy logs - trace level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_TRACE:LEGACY + FORMAT = string,log + ID = LEGACY_M2AP_INFO DESC = M2AP legacy logs - info level GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_INFO:LEGACY diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 5fc6a8c1a9..a0273bcf56 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -178,92 +178,97 @@ uint8_t set_ssb_case(int scs, int nr_band) return ssb_case; } -// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) (Rel.17) +// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) (Rel.18) // Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) // Notes: -// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL // - Frequencies are expressed in KHz -// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster -const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, - {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, - {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, - {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, - {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, - {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, - {12, 699000, 716000, 729000, 746000, 20, 145800, 100}, - {13, 777000, 787000, 746000, 756000, 20, 149200, 100}, - {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, - {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, - {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, - {24, 1627500, 1656500, 1526000, 1536000, 20, 305000, 100}, - {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, - {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, - {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, - {29, 000, 000, 717000, 728000, 20, 143400, 100}, - {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, - {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, - {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, - {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, - {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, - {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {46, 5150000, 5925000, 5150000, 5925000, 1, 743334, 15}, - {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, - {48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, - {48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, - {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, - {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, - {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, - {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, - {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, - {67, 000, 000, 738000, 758000, 20, 147600, 100}, - {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, - {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, - {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, - {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, - {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, - {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, - {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, - {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, - {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, - {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, - {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, - {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {81, 880000, 915000, 000, 000, 20, 176000, 100}, - {82, 832000, 862000, 000, 000, 20, 166400, 100}, - {83, 703000, 748000, 000, 000, 20, 140600, 100}, - {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, - {85, 698000, 716000, 728000, 746000, 20, 145600, 100}, - {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {89, 824000, 849000, 000, 000, 20, 342000, 100}, - {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, - {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, - {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, - {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, - {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, - {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, - {96, 5925000, 7125000, 5925000, 7125000, 1, 795000, 15}, - {100, 874400, 880000, 919400, 925000, 20, 174880, 100}, - {101, 1900000, 1910000, 1900000, 1910000, 20, 380000, 100}, - {102, 5925000, 6425000, 5925000, 6425000, 1, 795000, 15}, - {104, 6425000, 7125000, 6425000, 7125000, 1, 828334, 15}, - {104, 6425000, 7125000, 6425000, 7125000, 2, 828334, 30}, - {254, 1610000, 1626500, 2483500, 2500000, 20, 496700, 100}, - {254, 1610000, 1626500, 2483500, 2500000, 2, 496700, 10}, - {255, 1626500, 1660500, 1525000, 1559000, 20, 305000, 100}, - {255, 1626500, 1660500, 1525000, 1559000, 2, 305000, 10}, - {256, 1980000, 2010000, 2170000, 2200000, 20, 434000, 100}, - {256, 1980000, 2010000, 2170000, 2200000, 2, 434000, 10}, - {257, 26500020, 29500000, 26500020, 29500000, 1, 2054166, 60}, - {257, 26500080, 29500000, 26500080, 29500000, 2, 2054167, 120}, - {258, 24250080, 27500000, 24250080, 27500000, 1, 2016667, 60}, - {258, 24250080, 27500000, 24250080, 27500000, 2, 2016667, 120}, - {260, 37000020, 40000000, 37000020, 40000000, 1, 2229166, 60}, - {260, 37000080, 40000000, 37000080, 40000000, 2, 2229167, 120}, - {261, 27500040, 28350000, 27500040, 28350000, 1, 2070833, 60}, - {261, 27500040, 28350000, 27500040, 28350000, 2, 2070833, 120}}; +// - col: NR_band ul_min ul_max dl_min dl_max ul_stepsize dl_stepsize N_OFFs_UL N_OFFs_DL deltaf_raster +const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 20, 20, 384000, 422000, 100}, + {2, 1850000, 1910000, 1930000, 1990000, 20, 20, 370000, 386000, 100}, + {3, 1710000, 1785000, 1805000, 1880000, 20, 20, 342000, 361000, 100}, + {5, 824000, 849000, 869000, 894000, 20, 20, 164800, 173800, 100}, + {7, 2500000, 2570000, 2620000, 2690000, 20, 20, 500000, 524000, 100}, + {8, 880000, 915000, 925000, 960000, 20, 20, 176000, 185000, 100}, + {12, 699000, 716000, 729000, 746000, 20, 20, 139800, 145800, 100}, + {13, 777000, 787000, 746000, 756000, 20, 20, 155400, 149200, 100}, + {14, 788000, 798000, 758000, 768000, 20, 20, 157600, 151600, 100}, + {18, 815000, 830000, 860000, 875000, 20, 20, 163000, 172000, 100}, + {20, 832000, 862000, 791000, 821000, 20, 20, 166400, 158200, 100}, + {24, 1626500, 1660500, 1525000, 1559000, 20, 20, 325300, 305000, 100}, + {25, 1850000, 1915000, 1930000, 1995000, 20, 20, 370000, 386000, 100}, + {26, 814000, 849000, 859000, 894000, 20, 20, 162800, 171800, 100}, + {28, 703000, 748000, 758000, 803000, 20, 20, 140600, 151600, 100}, + {29, 000, 000, 717000, 728000, 0, 20, 0, 143400, 100}, + {30, 2305000, 2315000, 2350000, 2360000, 20, 20, 461000, 470000, 100}, + {34, 2010000, 2025000, 2010000, 2025000, 20, 20, 402000, 402000, 100}, + {38, 2570000, 2620000, 2570000, 2620000, 20, 20, 514000, 514000, 100}, + {39, 1880000, 1920000, 1880000, 1920000, 20, 20, 376000, 376000, 100}, + {40, 2300000, 2400000, 2300000, 2400000, 20, 20, 460000, 460000, 100}, + {41, 2496000, 2690000, 2496000, 2690000, 3, 3, 499200, 499200, 15}, + {41, 2496000, 2690000, 2496000, 2690000, 6, 6, 499200, 499200, 30}, + {46, 5150000, 5925000, 5150000, 5925000, 1, 1, 743334, 743334, 15}, + {47, 5855000, 5925000, 5855000, 5925000, 1, 1, 790334, 790334, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 1, 1, 636667, 636667, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 2, 2, 636668, 636668, 30}, + {50, 1432000, 1517000, 1432000, 1517000, 20, 20, 286400, 286400, 100}, + {51, 1427000, 1432000, 1427000, 1432000, 20, 20, 285400, 285400, 100}, + {53, 2483500, 2495000, 2483500, 2495000, 20, 20, 496700, 496700, 100}, + {65, 1920000, 2010000, 2110000, 2200000, 20, 20, 384000, 422000, 100}, + {66, 1710000, 1780000, 2110000, 2200000, 20, 20, 342000, 422000, 100}, + {67, 000, 000, 738000, 758000, 0, 20, 0, 147600, 100}, + {70, 1695000, 1710000, 1995000, 2020000, 20, 20, 339000, 399000, 100}, + {71, 663000, 698000, 617000, 652000, 20, 20, 132600, 123400, 100}, + {74, 1427000, 1470000, 1475000, 1518000, 20, 20, 285400, 295000, 100}, + {75, 000, 000, 1432000, 1517000, 0, 20, 0, 286400, 100}, + {76, 000, 000, 1427000, 1432000, 0, 20, 0, 285400, 100}, + {77, 3300000, 4200000, 3300000, 4200000, 1, 1, 620000, 620000, 15}, + {77, 3300000, 4200000, 3300000, 4200000, 2, 2, 620000, 620000, 30}, + {78, 3300000, 3800000, 3300000, 3800000, 1, 1, 620000, 620000, 15}, + {78, 3300000, 3800000, 3300000, 3800000, 2, 2, 620000, 620000, 30}, + {79, 4400000, 5000000, 4400000, 5000000, 1, 1, 693334, 693334, 15}, + {79, 4400000, 5000000, 4400000, 5000000, 2, 2, 693334, 693334, 30}, + {80, 1710000, 1785000, 000, 000, 20, 0, 342000, 0, 100}, + {81, 880000, 915000, 000, 000, 20, 0, 176000, 0, 100}, + {82, 832000, 862000, 000, 000, 20, 0, 166400, 0, 100}, + {83, 703000, 748000, 000, 000, 20, 0, 140600, 0, 100}, + {84, 1920000, 1980000, 000, 000, 20, 0, 384000, 0, 100}, + {85, 698000, 716000, 728000, 746000, 20, 20, 139600, 145600, 100}, + {86, 1710000, 1780000, 000, 000, 20, 0, 342000, 0, 100}, + {89, 824000, 849000, 000, 000, 20, 0, 342000, 0, 100}, + {90, 2496000, 2690000, 2496000, 2690000, 3, 3, 499200, 499200, 15}, + {90, 2496000, 2690000, 2496000, 2690000, 6, 6, 499200, 499200, 30}, + {90, 2496000, 2690000, 2496000, 2690000, 20, 20, 499200, 499200, 100}, + {91, 832000, 862000, 1427000, 1432000, 20, 20, 166400, 285400, 100}, + {92, 832000, 862000, 1432000, 1517000, 20, 20, 166400, 286400, 100}, + {93, 880000, 915000, 1427000, 1432000, 20, 20, 176000, 285400, 100}, + {94, 880000, 915000, 1432000, 1517000, 20, 20, 176000, 286400, 100}, + {95, 2010000, 2025000, 000, 000, 20, 20, 402000, 402000, 100}, + {96, 5925000, 7125000, 5925000, 7125000, 1, 1, 795000, 795000, 15}, + {100, 874400, 880000, 919400, 925000, 20, 20, 174880, 174880, 100}, + {101, 1900000, 1910000, 1900000, 1910000, 20, 20, 380000, 380000, 100}, + {102, 5925000, 6425000, 5925000, 6425000, 1, 1, 795000, 795000, 15}, + {104, 6425000, 7125000, 6425000, 7125000, 1, 1, 828334, 828334, 15}, + {104, 6425000, 7125000, 6425000, 7125000, 2, 2, 828334, 828334, 30}, + {254, 1610000, 1626500, 2483500, 2500000, 20, 20, 322000, 496700, 100}, + {254, 1610000, 1626500, 2483500, 2500000, 2, 2, 322000, 496700, 10}, + {255, 1626500, 1660500, 1525000, 1559000, 20, 20, 325300, 305000, 100}, + {255, 1626500, 1660500, 1525000, 1559000, 2, 2, 325300, 305000, 10}, + {256, 1980000, 2010000, 2170000, 2200000, 20, 20, 396000, 434000, 100}, + {256, 1980000, 2010000, 2170000, 2200000, 2, 2, 396000, 434000, 10}, + {257, 26500020, 29500000, 26500020, 29500000, 1, 1, 2054166, 2054166, 60}, + {257, 26500080, 29500000, 26500080, 29500000, 2, 2, 2054167, 2054167, 120}, + {258, 24250080, 27500000, 24250080, 27500000, 1, 1, 2016667, 2016667, 60}, + {258, 24250080, 27500000, 24250080, 27500000, 2, 2, 2016667, 2016667, 120}, + {260, 37000020, 40000000, 37000020, 40000000, 1, 1, 2229166, 2229166, 60}, + {260, 37000080, 40000000, 37000080, 40000000, 2, 2, 2229167, 2229167, 120}, + {261, 27500040, 28350000, 27500040, 28350000, 1, 1, 2070833, 2070833, 60}, + {261, 27500040, 28350000, 27500040, 28350000, 2, 2, 2070833, 2070833, 120}, + {510, 27500000, 28350000, 17300000, 20200000, 1, 4, 2070833, 1553336, 60}, + {510, 27500000, 28350000, 17300000, 20200000, 2, 8, 2070833, 1553336, 120}, + {511, 28350000, 30000000, 17300000, 20200000, 1, 4, 2084999, 1553336, 60}, + {511, 28350000, 30000000, 17300000, 20200000, 2, 8, 2084999, 1553336, 120}, + {512, 27500000, 30000000, 17300000, 20200000, 1, 4, 2070833, 1553336, 60}, + {512, 27500000, 30000000, 17300000, 20200000, 2, 8, 2070833, 1553336, 120}}; // synchronization raster per band tables (Rel.17) // (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1) @@ -341,6 +346,13 @@ const sync_raster_t sync_raster[] = { {260, 4, 22996, 2, 23164}, {261, 3, 22446, 1, 22492}, {261, 4, 22446, 2, 22490}, + {510, 3, 17448, 12, 19428}, + {510, 4, 17472, 24, 19416}, + {511, 3, 17448, 12, 19428}, + {511, 4, 17472, 24, 19416}, + {512, 3, 17448, 12, 19428}, + {512, 4, 17472, 24, 19416}, +/***************************/ }; // clang-format on @@ -542,14 +554,6 @@ int get_nb_periods_per_frame(uint8_t tdd_period) return nb_periods_per_frame; } -void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs) -{ - uint32_t delta_arfcn = nrarfcn - N_OFFs; - - if(delta_arfcn % (nr_bandtable[i].step_size) != 0) - LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %lu\n", nrarfcn, nr_bandtable[i].step_size); -} - uint32_t to_nrarfcn(uint64_t CarrierFreq) { uint64_t CarrierFreq_by_1k = CarrierFreq / 1000; @@ -580,7 +584,6 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn) int deltaFglobal = 5; uint32_t N_REF_Offs = 0; uint64_t F_REF_Offs_khz = 0; - uint64_t N_OFFs, frequency, freq_min; int i = get_nr_table_idx(nr_bandP, scs_index); if (nrarfcn > 599999 && nrarfcn < 2016667) { @@ -594,42 +597,30 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn) F_REF_Offs_khz = 24250080; } - int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index); + // First check if the ARFCN is on the RASTER + uint32_t stepsize = nr_bandtable[i].dl_stepsize; + uint32_t N_OFFs = nr_bandtable[i].N_OFFs_DL; - if (delta_duplex <= 0){ // DL band >= UL band - if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL - N_OFFs = nr_bandtable[i].N_OFFs_DL; - freq_min = nr_bandtable[i].dl_min; - } else {// is FDD UL - N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal; - freq_min = nr_bandtable[i].ul_min; - } - } else { // UL band > DL band - if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal){ // is FDD UL - N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal; - freq_min = nr_bandtable[i].ul_min; - } else { // is FDD DL - N_OFFs = nr_bandtable[i].N_OFFs_DL; - freq_min = nr_bandtable[i].dl_min; + if (nrarfcn >= nr_bandtable[i].N_OFFs_UL) { + if (nr_bandtable[i].N_OFFs_UL > N_OFFs || nrarfcn < N_OFFs) { + N_OFFs = nr_bandtable[i].N_OFFs_UL; + stepsize = nr_bandtable[i].ul_stepsize; } } - LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n", - N_OFFs, - delta_duplex, - deltaFglobal); + LOG_D(NR_MAC, "N_OFFs %u, deltaFglobal %d KHz, stepsize:%d\n", N_OFFs, deltaFglobal, stepsize); - AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs); - get_delta_arfcn(i, nrarfcn, N_OFFs); + AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %u\n", nrarfcn, nr_bandtable[i].band, N_OFFs); - frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal); + if ((nrarfcn - N_OFFs) % stepsize != 0) + LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %u. N_OFFS:%d\n", + nrarfcn, stepsize, N_OFFs); - LOG_D(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n", + uint64_t frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal); + LOG_I(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz, NR band %d\n", (unsigned long long)nrarfcn, (unsigned long long)frequency/1000, - (unsigned long long)freq_min, - nr_bandP, - (unsigned long long)N_OFFs); + nr_bandP); return frequency; } @@ -1049,12 +1040,13 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB, // only difference wrt NR-ARFCN is delta frequency 5kHz if f < 3 GHz for ARFCN uint32_t absolute_diff = (absoluteFrequencySSB - absoluteFrequencyPointA); const int scaling_5khz = absoluteFrequencyPointA < 600000 ? 3 : 1; - const int scaling = frequency_range == FR2 ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing; + const int scaling = (absoluteFrequencyPointA >= 2016667) ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing; const int scaled_abs_diff = absolute_diff / (scaling_5khz * scaling); // absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total - const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * scaling; + const int ssb_offset_scaling = (frequency_range == FR2) ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing; + const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * ssb_offset_scaling; // Offset to point A needs to be divisible by scaling - AssertFatal(ssb_offset_point_a % scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); + AssertFatal(ssb_offset_point_a % ssb_offset_scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); AssertFatal(ssb_offset_point_a >= 0, "ssb offset is negative %d for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); return ssb_offset_point_a; } @@ -1358,11 +1350,14 @@ long rrc_get_max_nr_csrs(const int max_rbs, const long b_SRS) frequency_range_t get_freq_range_from_freq(uint64_t freq) { - // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // 3GPP TS 38.101-1,38.101-5 Version 19.0.0 Table 5.1-1: Definition of frequency ranges if (freq >= 410000000 && freq <= 7125000000) return FR1; - - if (freq >= 24250000000 && freq <= 71000000000) + // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 is from 24250 MHz –to 71000 MHz + // 3GPP TS 38.101-5 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 for NTN is from 17300 Mhz to 30000 MHz + if (freq >= 17300000000 && freq <= 71000000000) return FR2; AssertFatal(false, "Undefined Frequency Range for frequency %ld Hz\n", freq); @@ -1373,8 +1368,11 @@ frequency_range_t get_freq_range_from_arfcn(uint32_t arfcn) // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges if (arfcn >= 82000 && arfcn <= 875000) return FR1; - - if (arfcn >= 2016667 && arfcn <= 2795832) + // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 is from 24250 MHz –to 71000 MHz (from ARFCN 2016667) + // 3GPP TS 38.101-5 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 for NTN is from 17300 Mhz to 30000 MHz, from ARFCN 1553336 (Table 5.4.2.3-3) + if (arfcn >= 1553336 && arfcn <= 2795832) return FR2; AssertFatal(false, "Undefined Frequency Range for ARFCN %d\n", arfcn); diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 58dad544cc..2197fe91a7 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -84,8 +84,8 @@ static inline const char *rnti_types(nr_rnti_type_t rr) #define MU_SCS(m) (15 << m) #define MAX_GSCN_BAND 620 // n78 has the highest GSCN range of 619 -#define NR_NUMBER_OF_SYMBOLS_PER_SLOT 14 -#define NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP 12 +#define NR_SYMBOLS_PER_SLOT 14 +#define NR_SYMBOLS_PER_SLOT_EXTENDED_CP 12 #define NR_MAX_NB_LAYERS 4 // 8 #define NR_MAX_CSI_PORTS 12 @@ -107,8 +107,10 @@ typedef struct nr_bandentry_s { uint64_t ul_max; uint64_t dl_min; uint64_t dl_max; - uint64_t step_size; - uint64_t N_OFFs_DL; + uint8_t ul_stepsize; + uint8_t dl_stepsize; + uint32_t N_OFFs_UL; + uint32_t N_OFFs_DL; uint8_t deltaf_raster; } nr_bandentry_t; diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 407a6b73b9..61bff2310c 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -561,7 +561,7 @@ int process_command(char *buf, int iteration) } rt=CMDSTATUS_NOTFOUND; - j = sscanf(buf,"%19s %19s %m[^\t\n]",modulename,cmd,&cmdb); + j = sscanf(buf,"%19s %63s %m[^\t\n]",modulename,cmd,&cmdb); if (telnetparams.telnetdbg > 0) printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n", j, modulename, cmd, (cmdb == NULL) ? "" : cmdb); @@ -947,6 +947,12 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde telnetparams.CmdParsers[i].cmd = cmd; telnetparams.CmdParsers[i].var = var; for (int j = 0; cmd[j].cmdfunc != NULL; j++) { + size_t cmdnamelen = strnlen(cmd[j].cmdname, TELNET_CMD_MAXSIZE); + AssertFatal(cmdnamelen < TELNET_CMD_MAXSIZE, + "cmdname %s too long: %ld >= %d", + cmd[j].cmdname, + cmdnamelen, + TELNET_CMD_MAXSIZE); if (cmd[j].cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) { if (afifo == NULL) { afifo = calloc_or_fail(1, sizeof(notifiedFIFO_t)); diff --git a/common/utils/telnetsrv/telnetsrv.h b/common/utils/telnetsrv/telnetsrv.h index b841905cae..bd90513cd1 100644 --- a/common/utils/telnetsrv/telnetsrv.h +++ b/common/utils/telnetsrv/telnetsrv.h @@ -35,8 +35,8 @@ #define TELNET_MAX_MSGLENGTH 2048 #define TELNET_PROMPT_PREFIX "softmodem" -#define TELNET_MAXCMD 20 -#define TELNET_CMD_MAXSIZE 20 +#define TELNET_MAXCMD 64 +#define TELNET_CMD_MAXSIZE 64 #define TELNET_HELPSTR_SIZE 80 /* status return by the command parser after it analysed user input */ diff --git a/docker/Dockerfile.gNB.ubuntu b/docker/Dockerfile.gNB.ubuntu index ded38324d7..bdf5783860 100644 --- a/docker/Dockerfile.gNB.ubuntu +++ b/docker/Dockerfile.gNB.ubuntu @@ -83,6 +83,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_bladerfdevif.so \ /oai-ran/cmake_targets/ran_build/build/libcoding.so \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ @@ -104,6 +105,9 @@ COPY --from=gnb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai- ## Copy E2 SM models COPY --from=gnb-build /usr/local/lib/flexric /usr/local/lib/flexric +# Copy BladeRF runtime from base image +COPY --from=gnb-base /usr/local/lib/libbladeRF* /usr/local/lib/ + RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ ldconfig && \ echo "---- ldd on nr-softmodem ----" && \ @@ -112,6 +116,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai ldd /usr/local/lib/liboai_eth_transpro.so \ /usr/local/lib/librfsimulator.so \ /usr/local/lib/liboai_usrpdevif.so \ + /usr/local/lib/liboai_bladerfdevif.so \ /usr/local/lib/libcoding.so \ /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ diff --git a/docker/Dockerfile.nrUE.ubuntu b/docker/Dockerfile.nrUE.ubuntu index c75acf3b41..c54a78a110 100644 --- a/docker/Dockerfile.nrUE.ubuntu +++ b/docker/Dockerfile.nrUE.ubuntu @@ -89,6 +89,7 @@ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_bladerfdevif.so \ /oai-ran/cmake_targets/ran_build/build/libcoding.so \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ @@ -112,6 +113,9 @@ COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin COPY --from=nr-ue-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib COPY --from=nr-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin +# Copy BladeRF runtime from base image +COPY --from=nr-ue-base /usr/local/lib/libbladeRF* /usr/local/lib/ + RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ ldconfig && \ echo "---- ldd on nr-uesoftmodem ----" && \ @@ -120,6 +124,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai ldd /usr/local/lib/liboai_eth_transpro.so \ /usr/local/lib/librfsimulator.so \ /usr/local/lib/liboai_usrpdevif.so \ + /usr/local/lib/liboai_bladerfdevif.so \ /usr/local/lib/libcoding.so \ /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index e2c4144707..0c9fb0884d 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -101,7 +101,7 @@ int oai_exit = 0; int NB_UE_INST = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int UE_scan = 1; int UE_scan_carrier = 0; diff --git a/executables/lte-softmodem.h b/executables/lte-softmodem.h index 6642141526..0d05c9ba9d 100644 --- a/executables/lte-softmodem.h +++ b/executables/lte-softmodem.h @@ -114,7 +114,7 @@ extern uint16_t ue_id_g; extern uint16_t node_number; extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; -extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int rx_input_level_dBm; extern openair0_config_t openair0_cfg[MAX_CARDS]; diff --git a/executables/lte-ue.c b/executables/lte-ue.c index 1a187ad51f..8cbf9b903f 100644 --- a/executables/lte-ue.c +++ b/executables/lte-ue.c @@ -437,8 +437,10 @@ static void *UE_thread_synch(void *arg) { printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min); if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) { - for (i=0; i<4; i++) - uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min; + for (i=0; i<4; i++) { + int32_t delta = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min; + uplink_frequency_offset[CC_id][i] = delta; + } found = 1; break; @@ -473,8 +475,8 @@ static void *UE_thread_synch(void *arg) { for (i=0; irf_map.card].rx_num_channels; i++) { downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = - bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; + int32_t delta = bands_to_scan.band_info[CC_id].ul_min - bands_to_scan.band_info[CC_id].dl_min; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = delta; openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; @@ -517,7 +519,8 @@ static void *UE_thread_synch(void *arg) { for (i=0; irf_map.card].rx_num_channels; i++) { downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; + int32_t delta = bands_to_scan.band_info[current_band].ul_min - bands_to_scan.band_info[0].dl_min + current_offset; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = delta; openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index 322fecae98..030db0b72f 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -92,7 +92,7 @@ unsigned int mmapped_dma=0; UE_MAC_INST *UE_mac_inst = NULL; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; diff --git a/executables/main_nr_ru.c b/executables/main_nr_ru.c index 1aab4e95f6..352102498e 100644 --- a/executables/main_nr_ru.c +++ b/executables/main_nr_ru.c @@ -55,7 +55,7 @@ extern void set_function_spec_param(RU_t *ru); extern void start_NR_RU(); extern void init_NR_RU(configmodule_interface_t *cfg, char *); -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; void nfapi_setmode(nfapi_mode_t nfapi_mode) { diff --git a/executables/main_ru.c b/executables/main_ru.c index 3579c26f7a..6cd48d9b13 100644 --- a/executables/main_ru.c +++ b/executables/main_ru.c @@ -84,7 +84,7 @@ extern void init_RU_proc(RU_t *ru); extern void kill_RU_proc(RU_t *ru); extern void set_function_spec_param(RU_t *ru); -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; void nfapi_setmode(nfapi_mode_t nfapi_mode) { return; } diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index df2f633d95..661059afaa 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -36,7 +36,7 @@ RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int oai_exit = 0; instance_t CUuniqInstance = 0; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 7c5a87a0b0..1d1b3ca014 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -538,7 +538,7 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp) if(slot_type == NR_MIXED_SLOT) { int txsymb = 0; - for(int symbol_count = 0; symbol_countsymbols_per_slot; symbol_count++) { if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) txsymb++; } diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 938bbeee88..25177bbfc7 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -101,7 +101,7 @@ int oai_exit = 0; unsigned int mmapped_dma=0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; char *uecap_file; runmode_t mode = normal_txrx; diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 75814596d3..f52f418732 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -281,7 +281,7 @@ static int nr_ue_slot_select(const fapi_nr_config_request_t *cfg, int nr_slot) if (current_slot->max_num_of_symbol_per_slot_list[0].slot_config == 2) return NR_MIXED_SLOT; - for (int i = 1; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT; i++) { + for (int i = 1; i < NR_SYMBOLS_PER_SLOT; i++) { // if the 1st symbol is DL and any other is not, the slot is mixed if (current_slot->max_num_of_symbol_per_slot_list[i].slot_config != 0) { return NR_MIXED_SLOT; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index df4088a87d..633cc80b3a 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -103,7 +103,7 @@ RAN_CONTEXT_t RC; int oai_exit = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t sidelink_frequency[MAX_NUM_CCs][4]; // UE and OAI config variables diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 1018716bb7..ee737310c9 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -138,8 +138,8 @@ extern int usrp_tx_thread; {"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \ {"time-source", CONFIG_HLP_TME, 0, .uptr=&TIMING_SOURCE, .defintval=0, TYPE_UINT, 0}, \ {"tune-offset", CONFIG_HLP_TUNE_OFFSET, 0, .dblptr=&TUNE_OFFSET, .defintval=0, TYPE_DOUBLE, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, .u64ptr=&(downlink_frequency[0][0]), .defint64val=0, TYPE_UINT64, 0}, \ - {"CO" , CONFIG_HLP_ULF, 0, .iptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, .u64ptr=&(downlink_frequency[0][0]), .defuintval=0, TYPE_UINT64, 0}, \ + {"CO" , CONFIG_HLP_ULF, 0, .i64ptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT64, 0}, \ {"a" , CONFIG_HLP_CHOFF, 0, .iptr=&CHAIN_OFFSET, .defintval=0, TYPE_INT, 0}, \ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, .uptr=&do_forms, .defintval=0, TYPE_UINT, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, .iptr=&cpu_meas_enabled, .defintval=0, TYPE_INT, 0}, \ @@ -330,7 +330,7 @@ char *get_softmodem_function(void); #define SOFTMODEM_RTSIGNAL (SIGRTMIN+1) void set_softmodem_sighandler(void); extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; -extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int usrp_tx_thread; extern int sf_ahead; extern int oai_exit; diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index bbb0d66900..53717ffdaf 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -355,7 +355,7 @@ void *epoll_recv_task(void *arg) void create_recv_thread(int8_t affinity) { pthread_t thread_id; - threadCreate(&thread_id, epoll_recv_task, NULL, "vnf_nvipc_aerial", affinity, OAI_PRIORITY_RT); + threadCreate(&thread_id, epoll_recv_task, NULL, "vnf_nvipc_aerial", affinity, OAI_PRIORITY_RT_MAX); } int load_hard_code_config(nv_ipc_config_t *config, int module_type, nv_ipc_transport_t _transport) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index d8b34b2598..9f1ddf8f92 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -185,7 +185,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) for (int i = 0; i < common_vars->num_beams_period; i++) { common_vars->txdataF[i] = (c16_t**)malloc16_clear(Ptx * sizeof(c16_t*)); for (int j = 0; j < Ptx; j++) - common_vars->txdataF[i][j] = (c16_t*)malloc16_clear(fp->samples_per_frame_wCP * sizeof(c16_t)); + common_vars->txdataF[i][j] = (c16_t*)malloc16_clear(fp->samples_per_slot_wCP * sizeof(c16_t)); } common_vars->debugBuff = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)*100); common_vars->debugBuff_sample_offset = 0; @@ -435,8 +435,8 @@ void init_nr_transport(PHY_VARS_gNB *gNB) fp->slots_per_frame; int nb_ul_slots_period = 0; if (cfg->cell_config.frame_duplex_type.value) { - for(int i=0; isymbols_per_slot; j++) { if(cfg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[j].slot_config.value == 1) { // UL symbol nb_ul_slots_period++; break; diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 48621afee4..1092545705 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -97,13 +97,14 @@ void nr_phy_init_RU(RU_t *ru) ru->common.txdataF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*)); // [hna] samples_per_frame without CP for(int i = 0; i < ru->nb_tx; ++i) - ru->common.txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP * sizeof(int32_t)); + ru->common.txdataF[i] = (int32_t *)malloc16_clear(fp->samples_per_slot_wCP * sizeof(int32_t)); // allocate IFFT input buffers (TX) ru->common.txdataF_BF = (int32_t **)malloc16(nb_tx_streams * sizeof(int32_t*)); LOG_D(PHY, "[INIT] common.txdata_BF= %p (%lu bytes)\n", ru->common.txdataF_BF, nb_tx_streams * sizeof(int32_t *)); for (int i = 0; i < nb_tx_streams; i++) { - ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP * sizeof(int32_t)); + ru->common.txdataF_BF[i] = + (int32_t *)malloc16_clear(fp->samples_per_slot_wCP * sizeof(int32_t)); LOG_D(PHY, "txdataF_BF[%d] %p for RU %d\n", i, ru->common.txdataF_BF[i], ru->idx); } // allocate FFT output buffers (RX) diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 19977b01e3..68066f8a86 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -265,7 +265,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) ue->nr_csi_info->csi_rs_generated_signal = malloc16(NR_MAX_CSI_PORTS * sizeof(*ue->nr_csi_info->csi_rs_generated_signal)); for (int i = 0; i < NR_MAX_CSI_PORTS; i++) { ue->nr_csi_info->csi_rs_generated_signal[i] = - malloc16_clear(fp->samples_per_frame_wCP * sizeof(**ue->nr_csi_info->csi_rs_generated_signal)); + malloc16_clear(fp->samples_per_slot_wCP * sizeof(**ue->nr_csi_info->csi_rs_generated_signal)); } ue->nr_srs_info = malloc16_clear(sizeof(nr_srs_info_t)); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 0e39e19d9e..f22da3d204 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -409,7 +409,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fapi_nr_config_request_t* conf set_scs_parameters(fp, fp->numerology_index, N_RB, config->ssb_table.ssb_case); fp->slots_per_frame = 10* fp->slots_per_subframe; - fp->symbols_per_slot = ((Ncp == NR_NORMAL)? 14 : 12); // to redefine for different slot formats + fp->symbols_per_slot = ((Ncp == NR_NORMAL)? NR_SYMBOLS_PER_SLOT : NR_SYMBOLS_PER_SLOT_EXTENDED_CP); fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP; fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size; @@ -469,7 +469,7 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, const nrUE_cell_p set_Lmax(frame_parms); frame_parms->slots_per_frame = 10* frame_parms->slots_per_subframe; - frame_parms->symbols_per_slot = ((frame_parms->Ncp == NR_NORMAL)? 14 : 12); // to redefine for different slot formats + frame_parms->symbols_per_slot = ((frame_parms->Ncp == NR_NORMAL)? NR_SYMBOLS_PER_SLOT : NR_SYMBOLS_PER_SLOT_EXTENDED_CP); frame_parms->samples_per_subframe_wCP = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot * frame_parms->slots_per_subframe; frame_parms->samples_per_frame_wCP = 10 * frame_parms->samples_per_subframe_wCP; frame_parms->samples_per_slot_wCP = frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; @@ -570,7 +570,7 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, sl_set_scs_parameters(fp, fp->numerology_index, fp->N_RB_SL); fp->slots_per_frame = 10 * fp->slots_per_subframe; - fp->symbols_per_slot = ((fp->Ncp == NR_NORMAL) ? 14 : 12); // to redefine for different slot formats + fp->symbols_per_slot = ((fp->Ncp == NR_NORMAL) ? NR_SYMBOLS_PER_SLOT : NR_SYMBOLS_PER_SLOT_EXTENDED_CP); fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP; fp->samples_per_slot_wCP = fp->symbols_per_slot * fp->ofdm_symbol_size; diff --git a/openair1/PHY/MODULATION/modulation_common.h b/openair1/PHY/MODULATION/modulation_common.h index 2973c36257..3e418594bc 100644 --- a/openair1/PHY/MODULATION/modulation_common.h +++ b/openair1/PHY/MODULATION/modulation_common.h @@ -53,7 +53,7 @@ void nr_normal_prefix_mod(c16_t *txdataF, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms); diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 9e8ac3ba3c..030ab3b36f 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -105,6 +105,7 @@ void nr_beam_precoding(c16_t **txdataF, void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, c16_t *txdataF, + bool is_flat_buff, const c16_t *symbol_rotation, int slot, int nb_rb, @@ -118,7 +119,7 @@ void nr_ofdm_demod_and_rx_rotation(c16_t **rxdata, int slot, int slot_offsetF, enum nr_Link linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); void perform_symbol_rotation(NR_DL_FRAME_PARMS *fp, double f0, c16_t *symbol_rotation); @@ -161,4 +162,12 @@ void nr_layer_precoder_simd(const int n_layers, const int sc_offset, const int re_cnt, c16_t *txdataF_precoded); + +void fft_shift(const c16_t *in, + uint32_t in_symb_sz, + uint16_t num_prb, + c16_t *out, + uint16_t fft_size_out, + uint16_t start_symb, + uint16_t num_symb); #endif diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index c3311fb78a..d7f07f397f 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -72,7 +72,7 @@ void nr_normal_prefix_mod(c16_t *txdataF, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { // This function works only slot wise. For more generic symbol generation refer nr_feptx0() if (frame_parms->numerology_index != 0) { // case where numerology != 0 @@ -288,6 +288,7 @@ void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_s void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, c16_t *txdataF, + bool is_flat_buff, const c16_t *symbol_rotation, int slot, int nb_rb, @@ -309,20 +310,39 @@ void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, this_rotation->r, this_rotation->i); - if (nb_rb & 1) { - rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - (nb_rb + 1) * 6, 15); - rotate_cpx_vector(this_symbol + fp->first_carrier_offset - 6, - this_rotation, - this_symbol + fp->first_carrier_offset - 6, - (nb_rb + 1) * 6, 15); - } else { - rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - nb_rb * 6, 15); - rotate_cpx_vector(this_symbol + fp->first_carrier_offset, - this_rotation, - this_symbol + fp->first_carrier_offset, - nb_rb * 6, 15); + if (is_flat_buff) + rotate_cpx_vector(this_symbol, this_rotation, this_symbol, nb_rb * NR_NB_SC_PER_RB, 15); + else { + c16_t *this_symbol_neg = this_symbol + fp->first_carrier_offset; + if (nb_rb & 1) { + this_symbol_neg -= 6; + nb_rb += 1; + } + rotate_cpx_vector(this_symbol, this_rotation, this_symbol, nb_rb * 6, 15); + rotate_cpx_vector(this_symbol_neg, this_rotation, this_symbol_neg, nb_rb * 6, 15); } } } + +/* Do FFT-shift for symbols in the provided in buffer and writes to out buffer. */ +void fft_shift(const c16_t *in, + uint32_t in_symb_sz, + uint16_t num_prb, + c16_t *out, + uint16_t fft_size_out, + uint16_t start_symb, + uint16_t num_symb) +{ + const int num_samp_half = num_prb * NR_NB_SC_PER_RB / 2; + const int first_carrier_offset = fft_size_out - num_samp_half; + for (int s = start_symb; s < start_symb + num_symb; s++) { + // Copy negative freq component + uint16_t out_offset = s * fft_size_out + first_carrier_offset; + uint16_t in_offset = s * in_symb_sz; + memcpy(out + out_offset, in + in_offset, num_samp_half * sizeof(int32_t)); + // Copy positive freq component + out_offset = s * fft_size_out; + in_offset = s * in_symb_sz + num_samp_half; + memcpy(out + out_offset, in + in_offset, num_samp_half * sizeof(int32_t)); + } +} diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 99cbf1c652..b690657ad5 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -227,7 +227,7 @@ void nr_ofdm_demod_and_rx_rotation(c16_t **rxdata, int slot, int slot_offsetF, enum nr_Link linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { for (int aa = 0; aa < nb_antennas; aa++) { for (uint8_t symbol = 0; symbol < fp->symbols_per_slot; symbol++) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 12bff45dee..a4f5c80989 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -53,7 +53,6 @@ static void nr_pdcch_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint3 void nr_generate_dci(PHY_VARS_gNB *gNB, const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - int txdataF_offset, NR_DL_FRAME_PARMS *frame_parms, int slot) { @@ -68,7 +67,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, if (pdcch_pdu_rel15->CoreSetType == 1) additional_offset = (pdcch_pdu_rel15->BWPStart + 5) / 6 * 6 - pdcch_pdu_rel15->BWPStart; int rb_offset = cset_start + additional_offset; - uint16_t cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; + uint16_t cset_start_sc = (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; int idx1 = pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols; int idx2 = (((n_rb + rb_offset + pdcch_pdu_rel15->BWPStart) * 3) + 15) & ~15; c16_t mod_dmrs[idx1][idx2] __attribute__((aligned(16))); @@ -179,9 +178,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, /// Resource mapping uint16_t amp = gNB->TX_AMP; - c16_t *txdataF = gNB->common_vars.txdataF[beam_nb][0] + txdataF_offset; - if (cset_start_sc >= frame_parms->ofdm_symbol_size) - cset_start_sc -= frame_parms->ofdm_symbol_size; + c16_t *txdataF = gNB->common_vars.txdataF[beam_nb][0]; int num_regs = dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols; /*Mapping the encoded DCI along with the DMRS */ @@ -190,8 +187,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, for (int reg_count = 0; reg_count < num_regs; reg_count++) { int k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB; LOG_D(NR_PHY_DCI, "REG %d k %d\n", reg_list[d][reg_count], k); - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; int l = cset_start_symb + symbol_idx; @@ -227,9 +222,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, } k++; - - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; } // m } // reg_count } // symbol_idx diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.h b/openair1/PHY/NR_TRANSPORT/nr_dci.h index 57651f03a2..5a237ba80d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.h @@ -28,7 +28,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - int txdataF_offset, NR_DL_FRAME_PARMS *frame_parms, int slot); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 24cf6b72b6..1810cec6a0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -86,8 +86,7 @@ static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, printf("k %d \t txdataF: %d %d\n", k, txF[k].r, txF[k].i); #endif } - if (++k >= symbol_sz) - k -= symbol_sz; + k++; } return in - tx_layer; } @@ -294,7 +293,7 @@ static inline int dmrs_case00(c16_t *output, else { output[k] = (c16_t){0}; } - k = (k + 1) % symbol_sz; + k++; } // RE loop return in - txl; } @@ -355,12 +354,6 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, { c16_t *txl = txl_start; const uint sz = rel15->rbSize * NR_NB_SC_PER_RB; - int upper_limit = sz; - int remaining_re = 0; - if (start_sc + upper_limit > symbol_sz) { - upper_limit = symbol_sz - start_sc; - remaining_re = sz - upper_limit; - } /* calculate if current symbol is PTRS symbols */ int ptrs_symbol = 0; @@ -385,47 +378,39 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, if (rel15->numDmrsCdmGrpsNoData == 2) { switch (dmrs_port & 3) { case 0: - txl += interleave_with_0_signal_first(output + start_sc, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_with_0_signal_first(output, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_signal_first(output + start_sc, dmrs_start, amp_dmrs, sz); break; case 1: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_with_0_signal_first(output + start_sc, dmrs, amp_dmrs, upper_limit); - txl += interleave_with_0_signal_first(output, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_signal_first(output + start_sc, dmrs, amp_dmrs, sz); } break; case 2: - txl += interleave_with_0_start_with_0(output + start_sc, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_with_0_start_with_0(output, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_start_with_0(output + start_sc, dmrs_start, amp_dmrs, sz); break; case 3: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_with_0_start_with_0(output + start_sc, dmrs, amp_dmrs, upper_limit); - txl += interleave_with_0_start_with_0(output, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_start_with_0(output + start_sc, dmrs, amp_dmrs, sz); } break; } } else if (rel15->numDmrsCdmGrpsNoData == 1) { switch (dmrs_port & 3) { case 0: - txl += interleave_signals(output + start_sc, txl, amp, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_signals(output, txl, amp, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_signals(output + start_sc, txl, amp, dmrs_start, amp_dmrs, sz); break; case 1: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_signals(output + start_sc, txl, amp, dmrs, amp_dmrs, upper_limit); - txl += interleave_signals(output, txl, amp, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_signals(output + start_sc, txl, amp, dmrs, amp_dmrs, sz); } break; case 2: - txl += interleave_signals(output + start_sc, dmrs_start, amp_dmrs, txl, amp, upper_limit); - txl += interleave_signals(output, dmrs_start + upper_limit / 2, amp_dmrs, txl, amp, remaining_re); + txl += interleave_signals(output + start_sc, dmrs_start, amp_dmrs, txl, amp, sz); break; case 3: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_signals(output + start_sc, dmrs, amp_dmrs, txl, amp, upper_limit); - txl += interleave_signals(output, dmrs + upper_limit / 2, amp_dmrs, txl, amp, remaining_re); + txl += interleave_signals(output + start_sc, dmrs, amp_dmrs, txl, amp, sz); } break; } } else @@ -445,8 +430,7 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, rel15->numDmrsCdmGrpsNoData); } // generic DMRS case } else { // no PTRS or DMRS in this symbol - txl += no_ptrs_dmrs_case(output + start_sc, txl, amp, upper_limit); - txl += no_ptrs_dmrs_case(output, txl, amp, remaining_re); + txl += no_ptrs_dmrs_case(output + start_sc, txl, amp, sz); } // no DMRS/PTRS in symbol return txl - txl_start; } @@ -477,30 +461,13 @@ static inline void do_txdataF(c16_t **txdataF, const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0; const int re_cnt = NR_NB_SC_PER_RB * rb_step; if (pmi == 0) { // unitary Precoding - if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC - if (ant < rel15->nrOfLayers) - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - re_cnt * sizeof(**txdataF)); - else - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); - } else { // RB does cross DC - const int neg_length = symbol_sz - subCarrier; - const int pos_length = re_cnt - neg_length; - if (ant < rel15->nrOfLayers) { - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - neg_length * sizeof(**txdataF)); - memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant], pos_length * sizeof(**txdataF)); - } else { - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF)); - memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF)); - } - } + if (ant < rel15->nrOfLayers) + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[ant][subCarrier], + re_cnt * sizeof(**txdataF)); + else + memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); subCarrier += re_cnt; - if (subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } } else { // non-unitary Precoding AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n"); // get the precoding matrix weights: @@ -514,38 +481,21 @@ static inline void do_txdataF(c16_t **txdataF, "Number of layers %d doesn't match to the one in precoding matrix %d\n", rel15->nrOfLayers, pmi_pdu->numLayers); - if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe - nr_layer_precoder_simd(rel15->nrOfLayers, - symbol_sz, - txdataF_precoding, - ant, - pmi_pdu, - subCarrier, - re_cnt, - &txdataF[ant][txdataF_offset_per_symbol]); - subCarrier += re_cnt; - } else { // crossing ofdm_symbol_size, use simple arithmetic operations - for (int i = 0; i < re_cnt; i++) { - txdataF[ant][txdataF_offset_per_symbol + subCarrier] = - nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier); -#ifdef DEBUG_DLSCH_MAPPING - printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", - ant, - l_symbol, - subCarrier, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i); -#endif - if (++subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } - } - } // else{ // crossing ofdm_symbol_size, use simple arithmetic operations + nr_layer_precoder_simd(rel15->nrOfLayers, + symbol_sz, + txdataF_precoding, + ant, + pmi_pdu, + subCarrier, + re_cnt, + &txdataF[ant][txdataF_offset_per_symbol]); + subCarrier += re_cnt; } // else { // non-unitary Precoding rb += rb_step; } // RB loop: while(rb < rel15->rbSize) } + static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot) { const int16_t amp = gNB->TX_AMP; @@ -554,7 +504,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC time_stats_t *dlsch_scrambling_stats = &gNB->dlsch_scrambling_stats; time_stats_t *dlsch_modulation_stats = &gNB->dlsch_modulation_stats; const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; - const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB; + const int layerSz = frame_parms->N_RB_DL * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB; const int symbol_sz=frame_parms->ofdm_symbol_size; const int dmrs_Type = rel15->dmrsConfigType; const int nb_re_dmrs = rel15->numDmrsCdmGrpsNoData * (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); @@ -641,11 +591,8 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC start_meas(&gNB->dlsch_pdsch_generation_stats); /// Resource mapping // Non interleaved VRB to PRB mapping - uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB; - if (start_sc >= symbol_sz) - start_sc -= symbol_sz; + uint16_t start_sc = (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB; - const uint32_t txdataF_offset = slot * frame_parms->samples_per_slot_wCP; #ifdef DEBUG_DLSCH_MAPPING printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", start_sc, @@ -756,7 +703,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC start_meas(&gNB->dlsch_precoding_stats); for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) { - const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz + txdataF_offset; + const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz; do_txdataF(txdataF, symbol_sz, txdataF_precoding, gNB, rel15, ant, start_sc, txdataF_offset_per_symbol); } stop_meas(&gNB->dlsch_precoding_stats); @@ -765,7 +712,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC /* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits) * should remain a multiple of 8 * 64 with enough offset to fit each dlsch */ - uint32_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; + uint32_t size_output_tb = rel15->rbSize * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; return ((size_output_tb + 511) >> 9) << 6; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index b2e7772a36..c2af8481c3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -55,7 +55,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM dlsch->b = NULL; } if (dlsch->f) { - free16(dlsch->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + free16(dlsch->f, N_RB * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); dlsch->f = NULL; } for (int r = 0; r < a_segments; r++) { @@ -94,9 +94,9 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) bzero(dlsch.c[r], 8448); } - dlsch.f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + dlsch.f = malloc16(N_RB * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); AssertFatal(dlsch.f, "cannot allocate dlsch->f\n"); - bzero(dlsch.f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + bzero(dlsch.f, N_RB * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); return (dlsch); } @@ -262,7 +262,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, /* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits) * => dlsch_offset should remain a multiple of 8 * 64 with enough offset to fit each dlsch */ - const size_t dlsch_size = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * rel15->qamModOrder[0] * rel15->nrOfLayers; + const size_t dlsch_size = rel15->rbSize * gNB->frame_parms.symbols_per_slot * NR_NB_SC_PER_RB * rel15->qamModOrder[0] * rel15->nrOfLayers; dlsch_offset += ceil_mod(dlsch_size, 8 * 64); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 159e040d11..4acda03b91 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -71,7 +71,7 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, /// Resource mapping // PBCH DMRS are mapped within the SSB block on every fourth subcarrier starting from nushift of symbols 1, 2, 3 ///symbol 1 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l = ssb_start_symbol + 1; for (int m = 0; m < 60; m++) { @@ -80,13 +80,10 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #endif txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 2 [0+u:4:44+nushift ; 192+nu:4:236+nushift] -- 24 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l++; for (int m = 60; m < 84; m++) { @@ -100,13 +97,10 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif k+=(m==71)?148:4; // Jump from 44+nu to 192+nu - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 3 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l++; for (int m = 84; m < NR_PBCH_DMRS_LENGTH; m++) { @@ -115,9 +109,6 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #endif txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef DEBUG_PBCH_DMRS @@ -334,7 +325,7 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, nushift = config->cell_config.phy_cell_id.value &3; // PBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PBCH DMRS ///symbol 1 [0:239] -- 180 mod symbols - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + int k = frame_parms->ssb_start_subcarrier; int l = ssb_start_symbol + 1; int m = 0; int16_t amp = gNB->TX_AMP; @@ -351,13 +342,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 2 [0:47 ; 192:239] -- 72 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + k = frame_parms->ssb_start_subcarrier; l++; m=180; @@ -373,16 +361,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } k += 144; - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - m=216; for (int ssb_sc_idx = 192; ssb_sc_idx < 240; ssb_sc_idx++) { @@ -397,13 +379,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 3 [0:239] -- 180 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + k = frame_parms->ssb_start_subcarrier; l++; m=252; @@ -419,9 +398,5 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index e42c02953c..7b306e547a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -105,7 +105,7 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n fapi_beam_idx, &gNB->common_vars, Slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prs.c b/openair1/PHY/NR_TRANSPORT/nr_prs.c index 207a94447d..87edffdc7d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prs.c @@ -51,9 +51,9 @@ int nr_generate_prs(int slot, c16_t *txdataF, int16_t amp, prs_config_t *prs_cfg else if (prs_cfg->CombSize == 12){ k_prime = k_prime_table[3][symInd]; } - - k = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset*12 + frame_parms->first_carrier_offset; - + + k = (prs_cfg->REOffset + k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset * 12; + // QPSK modulation uint32_t *gold = nr_gold_prs(prs_cfg->NPRSID, slot, l); for (int m = 0; m < (12/prs_cfg->CombSize) * prs_cfg->NumRB; m++) { @@ -66,10 +66,7 @@ int nr_generate_prs(int slot, c16_t *txdataF, int16_t amp, prs_config_t *prs_cfg txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_prs[m], amp, 15); k = k + prs_cfg->CombSize; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - } + } } #ifdef DEBUG_PRS_MAP LOG_M("nr_prs.m", "prs",(int16_t *)&txdataF[prs_cfg->SymbolStart*frame_parms->ofdm_symbol_size],prs_cfg->NumPRSSymbols*frame_parms->ofdm_symbol_size, 1, 1); diff --git a/openair1/PHY/NR_TRANSPORT/nr_pss.c b/openair1/PHY/NR_TRANSPORT/nr_pss.c index 965ac51c21..6b219dba90 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pss.c @@ -49,8 +49,7 @@ int nr_generate_pss( c16_t *txdataF, /// Resource mapping // PSS occupies a predefined position (subcarriers 56-182, symbol 0) within the SSB block starting from - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and - if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; + int k = frame_parms->ssb_start_subcarrier + 56; int l = ssb_start_symbol; @@ -61,9 +60,6 @@ int nr_generate_pss( c16_t *txdataF, // printf("pss: writing position k %d / %d\n",k,frame_parms->ofdm_symbol_size); ((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_pss) >> 15; k++; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef NR_PSS_DEBUG diff --git a/openair1/PHY/NR_TRANSPORT/nr_sss.c b/openair1/PHY/NR_TRANSPORT/nr_sss.c index 45835f8206..71bae9a065 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sss.c @@ -59,16 +59,13 @@ int nr_generate_sss( c16_t *txdataF, /// Resource mapping // SSS occupies a predefined position (subcarriers 56-182, symbol 2) within the SSB block starting from - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and + int k = frame_parms->ssb_start_subcarrier + 56; int l = ssb_start_symbol + 2; for (int i = 0; i < NR_SSS_LENGTH; i++) { int16_t d_sss = (1 - 2*x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2*x1[(i + m1) % NR_SSS_LENGTH] ) * 23170; ((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_sss) >> 15; k++; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef NR_SSS_DEBUG // write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index b963b7d970..991dc12992 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -160,7 +160,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t fapi_beam_idx, &gNB->common_vars, slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } ulsch->frame = frame; diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index aa3a6e5907..08ac27fde1 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -73,7 +73,7 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t fapi_beam_idx, &gNB->common_vars, slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); @@ -1069,7 +1069,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // first compute DMRS component const int scramble = pucch_pdu->dmrs_scrambling_id * 2; uint32_t x2 = - ((1ULL << 17) * ((NR_NUMBER_OF_SYMBOLS_PER_SLOT * slot + pucch_pdu->start_symbol_index + symb + 1) * (scramble + 1)) + ((1ULL << 17) * ((frame_parms->symbols_per_slot * slot + pucch_pdu->start_symbol_index + symb + 1) * (scramble + 1)) + scramble) % (1U << 31); // c_init calculation according to TS38.211 subclause #ifdef DEBUG_NR_PUCCH_RX diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index 0637a8abce..a5c7455274 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -63,7 +63,7 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu fapi_beam_idx, &gNB->common_vars, slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t)); diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 3004728091..71f529c5ca 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -281,7 +281,6 @@ static int nr_csi_rs_channel_estimation( int16_t *log2_maxh, uint32_t *noise_power) { - const int dataF_offset = proc->nr_slot_rx * fp->samples_per_slot_wCP; *noise_power = 0; int maxh = 0; int count = 0; @@ -316,7 +315,7 @@ static int nr_csi_rs_channel_estimation( for (int lp = 0; lp <= csi_mapping->lprime; lp++) { uint16_t symb = lp + csi_mapping->loverline[cdm_id]; uint64_t symbol_offset = symb * fp->ofdm_symbol_size; - const c16_t *tx_csi_rs_signal = &csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; + const c16_t *tx_csi_rs_signal = &csi_rs_generated_signal[port_tx][symbol_offset]; const c16_t *rx_csi_rs_signal = &csi_rs_received_signal[ant_rx][symbol_offset]; c16_t tmp = c16MulConjShift(tx_csi_rs_signal[k], rx_csi_rs_signal[k], nr_csi_info->csi_rs_generated_signal_bits); // This is not just the LS estimation for each (k,l), but also the sum of the different contributions @@ -330,7 +329,7 @@ static int nr_csi_rs_channel_estimation( } #ifdef NR_CSIRS_DEBUG - for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { + for(int symb = 0; symb < fp->symbols_per_slot; symb++) { if(!is_csi_rs_in_symbol(*csirs_config_pdu,symb)) { continue; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 65a0247046..46b88aa354 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -345,8 +345,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, // generate pilot c16_t pilot[(n_rb + dmrs_ref) * 3] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS - const uint32_t *gold = - nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, proc->nr_slot_rx, symbol); + const uint32_t *gold = nr_gold_pdcch(fp->N_RB_DL, fp->symbols_per_slot, scrambling_id, proc->nr_slot_rx, symbol); nr_pdcch_dmrs_ref(gold, pilot, n_rb + dmrs_ref); nr_pdcch_channel_estimation(ue, n_rb, @@ -363,7 +362,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size]; - nr_pdcch_extract_rbs_single(ue->frame_parms.ofdm_symbol_size, + nr_pdcch_extract_rbs_single(fp->ofdm_symbol_size, rxdataF, pdcch_est_size, pdcch_dl_ch_estimates, @@ -401,16 +400,18 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, nr_pdcch_llr(llr_size_symbol, rxdataF_comp[0], llr); } -bool is_start_symbol_in_ss(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, const int symbol) +static bool is_start_symbol_in_ss(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, const int symbol, const int nb_symb_slot) { - return ((ss->coreset.StartSymbolBitmap >> (NR_SYMBOLS_PER_SLOT - 1 - symbol)) & 1); + return ((ss->coreset.StartSymbolBitmap >> (nb_symb_slot - 1 - symbol)) & 1); } -int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]) +static int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, + int nb_symb_slot, + uint8_t start_symb[nb_symb_slot]) { int sum = 0; - for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) { - if (is_start_symbol_in_ss(ss, s)) { + for (int s = 0; s < nb_symb_slot; s++) { + if (is_start_symbol_in_ss(ss, s, nb_symb_slot)) { if (start_symb != NULL) start_symb[sum] = s; sum++; @@ -420,22 +421,22 @@ int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, return sum; } -int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config) +int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb_slot) { int monOcc = 0; for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) { - monOcc = max(monOcc, get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss], NULL)); + monOcc = max(monOcc, get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss], nb_symb_slot, NULL)); } return monOcc; } -void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb) +void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb_slot, int *first_symb, int *last_symb) { - *first_symb = NR_SYMBOLS_PER_SLOT; // max first pdcch symbol + *first_symb = nb_symb_slot; // max first pdcch symbol *last_symb = 0; // min last pdcch symbol for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) { - for (int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { - if (is_start_symbol_in_ss(&phy_pdcch_config->pdcch_config[ss], symb)) { + for (int symb = 0; symb < nb_symb_slot; symb++) { + if (is_start_symbol_in_ss(&phy_pdcch_config->pdcch_config[ss], symb, nb_symb_slot)) { const int duration = phy_pdcch_config->pdcch_config[ss].coreset.duration; *first_symb = min(*first_symb, symb); *last_symb = max(*last_symb, symb + duration - 1); @@ -460,7 +461,9 @@ void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue, // Loop over search spaces for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) { uint8_t start_symb[NR_SYMBOLS_PER_SLOT] = {0}; - const int num_monOcc = get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss_idx], start_symb); + const int num_monOcc = get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss_idx], + ue->frame_parms.symbols_per_slot, + start_symb); // Loop over monitoring occations within the slot in this ss for (int occ = 0; occ < num_monOcc; occ++) { const int first_symb = start_symb[occ]; @@ -609,7 +612,7 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc, for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) { fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[ss_idx]; uint8_t unused_start_symb[NR_SYMBOLS_PER_SLOT] = {0}; - const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, unused_start_symb); + const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, ue->frame_parms.symbols_per_slot, unused_start_symb); const int llr_stride = llr_size / rel15->coreset.duration; int n_rb, cset_start; get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index b46d89943c..8e893226a3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -701,7 +701,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, UEunlockScopeData(ue, pdschRxdataF_comp) } } else { - UEscopeCopy(ue, pdschRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), nbRx, rx_size_symbol * NR_SYMBOLS_PER_SLOT, 0); + UEscopeCopy(ue, pdschRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), nbRx, rx_size_symbol * fp->symbols_per_slot, 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 6872306dfe..d77a168c41 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -69,11 +69,9 @@ typedef struct pdsch_scope_req_s { void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations); void nr_conjch0_mult_ch1(c16_t *ch0, c16_t *ch1, c16_t *ch0conj_ch1, unsigned short nb_rb, unsigned char output_shift0); -void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb); +void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int symb_slot, int *first_symb, int *last_symb); -int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]); - -int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config); +int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb_slot); /** \brief This is the alternative top-level entry point for DLSCH decoding in UE. It handles all the HARQ processes in only one call. The routine first @@ -162,25 +160,25 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint8_t slot, nr_phy_data_tx_t *phy_data, c16_t **txdataF, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); /** \brief This function does IFFT for PUSCH */ -uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, - const NR_DL_FRAME_PARMS *frame_parms, - const uint8_t n_antenna_ports, - c16_t **txdataF, - c16_t **txdata, - uint32_t linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT], - bool no_phase_pre_comp); +void nr_tx_rotation_and_ofdm_mod(const uint8_t slot, + const NR_DL_FRAME_PARMS *frame_parms, + const uint8_t n_antenna_ports, + c16_t **txdataF, + c16_t **txdata, + uint32_t linktype, + bool was_symbol_used[NR_SYMBOLS_PER_SLOT], + bool no_phase_pre_comp); bool 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]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); void clean_UE_harq(PHY_VARS_NR_UE *UE); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 881ce016bc..260259cf6b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1027,11 +1027,11 @@ static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_ if (!pusch_pdu || !codeword || codeword_len == 0 || !template) return NULL; const uint8_t n_symbols = pusch_pdu->nr_of_symbols; - if (n_symbols == 0 || n_symbols > NR_NUMBER_OF_SYMBOLS_PER_SLOT) + if (n_symbols == 0 || n_symbols > NR_SYMBOLS_PER_SLOT) return NULL; - uint32_t m_ulsch_initial[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; - uint32_t m_uci_current[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; // This holds RE counts, not bit counts + uint32_t m_ulsch_initial[NR_SYMBOLS_PER_SLOT] = {0}; + uint32_t m_uci_current[NR_SYMBOLS_PER_SLOT] = {0}; // This holds RE counts, not bit counts if (initialize_mapping_resources(pusch_pdu, m_ulsch_initial, m_uci_current) != 0) { LOG_E(PHY, "Failed to initialize mapping resources\n"); @@ -1048,8 +1048,8 @@ static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_ memset(template, 0, codeword_len * sizeof(uci_on_pusch_bit_type_t)); - uint32_t positions_by_sym[NR_NUMBER_OF_SYMBOLS_PER_SLOT][MAX_UCI_CODED_BITS] = {0}; - uint32_t count_by_sym[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; + uint32_t positions_by_sym[NR_SYMBOLS_PER_SLOT][MAX_UCI_CODED_BITS] = {0}; + uint32_t count_by_sym[NR_SYMBOLS_PER_SLOT] = {0}; struct map_uci_common_arg map_arg = {.template = template, .n_symbols = pusch_pdu->nr_of_symbols, @@ -1094,7 +1094,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint8_t slot, nr_phy_data_tx_t *phy_data, c16_t **txdataF, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; @@ -1603,30 +1603,37 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); } -uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, - const NR_DL_FRAME_PARMS *frame_parms, - const uint8_t n_antenna_ports, - c16_t **txdataF, - c16_t **txdata, - uint32_t linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT], - bool no_phase_pre_comp) +void nr_tx_rotation_and_ofdm_mod(const uint8_t slot, + const NR_DL_FRAME_PARMS *frame_parms, + const uint8_t n_antenna_ports, + c16_t **txdataF, + c16_t **txdata, + uint32_t linktype, + bool was_symbol_used[NR_SYMBOLS_PER_SLOT], + bool no_phase_pre_comp) { int N_RB = (linktype == link_type_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_UL; if (!no_phase_pre_comp) { - for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT; i++) { + for (int i = 0; i < frame_parms->symbols_per_slot; i++) { if (was_symbol_used[i] == false) continue; for (int ap = 0; ap < n_antenna_ports; ap++) { - apply_nr_rotation_TX(frame_parms, txdataF[ap], frame_parms->symbol_rotation[linktype], slot, N_RB, i, 1); + apply_nr_rotation_TX(frame_parms, + txdataF[ap], + false, + frame_parms->symbol_rotation[linktype], + slot, + N_RB, + i, + 1); } } } for (int ap = 0; ap < n_antenna_ports; ap++) { if (frame_parms->Ncp == 1) { // extended cyclic prefix - for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP; i++) { + for (int i = 0; i < frame_parms->symbols_per_slot; i++) { if (was_symbol_used[i] == false) { memset(&txdata[ap][(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples) * i], 0, @@ -1641,11 +1648,7 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, CYCLIC_PREFIX); } } else { // normal cyclic prefix - nr_normal_prefix_mod(txdataF[ap], txdata[ap], NR_NUMBER_OF_SYMBOLS_PER_SLOT, frame_parms, slot, was_symbol_used); + nr_normal_prefix_mod(txdataF[ap], txdata[ap], frame_parms->symbols_per_slot, frame_parms, slot, was_symbol_used); } } - - /////////// - //////////////////////////////////////////////////// - return 0; } diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c index 05420672ad..0f5a76183e 100644 --- a/openair1/PHY/TOOLS/calibration_test.c +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -11,7 +11,7 @@ unsigned int mmapped_dma=0; uint32_t timing_advance; int8_t threequarter_fs; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int cpu_meas_enabled; THREAD_STRUCT thread_struct; uint32_t target_ul_mcs = 9; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 20fc744f57..4b6737a4ed 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -42,8 +42,6 @@ #define MAX_NUM_SUBCARRIER_SPACING 5 #define NR_MAX_OFDM_SYMBOL_SIZE 8192 -#define NR_SYMBOLS_PER_SLOT NR_NUMBER_OF_SYMBOLS_PER_SLOT - #define ONE_OVER_SQRT2_Q15 23170 #define NR_MOD_TABLE_SIZE_SHORT 686 diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c index 557214c63f..a0db67e50d 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c @@ -25,8 +25,6 @@ static void csi_rs_resource_mapping(c16_t **dataF, int csi_rs_length, int16_t mod_csi[][csi_rs_length >> 1], int ofdm_symbol_size, - int dataF_offset, - int start_sc, const csi_mapping_parms_t *mapping_parms, int start_rb, int nb_rbs, @@ -44,7 +42,7 @@ static void csi_rs_resource_mapping(c16_t **dataF, int p = s + mapping_parms->j[ji] * gs; // port index for (int kp = 0; kp <= mapping_parms->kprime; kp++) { // loop over frequency resource elements within a group // frequency index of current resource element - int k = (start_sc + (n * NR_NB_SC_PER_RB) + mapping_parms->koverline[ji] + kp) % (ofdm_symbol_size); + int k = ((n * NR_NB_SC_PER_RB) + mapping_parms->koverline[ji] + kp); // wf according to tables 7.4.5.3-2 to 7.4.5.3-5 int wf = kp == 0 ? 1 : (-2 * (s % 2) + 1); int na = n * alpha; @@ -66,7 +64,7 @@ static void csi_rs_resource_mapping(c16_t **dataF, else wt = -1; } - int index = (l * ofdm_symbol_size + k) + dataF_offset; + int index = (l * ofdm_symbol_size + k); dataF[p][index].r = (beta * wt * wf * mod_csi[l][mprime << 1]) >> 15; dataF[p][index].i = (beta * wt * wf * mod_csi[l][(mprime << 1) + 1]) >> 15; LOG_D(PHY, @@ -622,14 +620,10 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, // CDM group size from CDM type index const int gs = get_cdm_group_size(cdm_type); - const int dataF_offset = slot * frame_parms->samples_per_slot_wCP; - csi_rs_resource_mapping(dataF, frame_parms->N_RB_DL << 4, mod_csi, frame_parms->ofdm_symbol_size, - dataF_offset, - frame_parms->first_carrier_offset, phy_csi_parms, start_rb, nr_of_rbs, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c index f258b92205..547c4bdf18 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -30,18 +30,18 @@ static const uint16_t srs_max_number_cs[3] = {8, 12, 6}; //#define SRS_DEBUG -static int group_number_hopping(int slot_number, uint8_t n_ID_SRS, uint8_t l0, uint8_t l_line) +static int group_number_hopping(int slot_number, uint8_t n_ID_SRS, uint8_t l0, uint8_t l_line, int symb_slot) { // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 uint32_t cinit = n_ID_SRS; - uint8_t c_last_index = 8 * (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line) + 7; + uint8_t c_last_index = 8 * (slot_number * symb_slot + l0 + l_line) + 7; uint32_t *c_sequence = calloc(c_last_index + 1, sizeof(uint32_t)); pseudo_random_sequence(c_last_index + 1, c_sequence, cinit); // TS 38.211 - 6.4.1.4.2 Sequence generation uint32_t f_gh = 0; for (int m = 0; m <= 7; m++) { - f_gh += c_sequence[8 * (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line) + m] << m; + f_gh += c_sequence[8 * (slot_number * symb_slot + l0 + l_line) + m] << m; } f_gh = f_gh % 30; int u = (f_gh + n_ID_SRS) % U_GROUP_NUMBER; @@ -49,13 +49,13 @@ static int group_number_hopping(int slot_number, uint8_t n_ID_SRS, uint8_t l0, u return u; } -static int sequence_number_hopping(int slot_number, uint8_t n_ID_SRS, uint16_t M_sc_b_SRS, uint8_t l0, uint8_t l_line) +static int sequence_number_hopping(int slot_number, int n_ID_SRS, int M_sc_b_SRS, int l0, int l_line, int symb_slot) { int v = 0; if (M_sc_b_SRS > 6 * NR_NB_SC_PER_RB) { // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 uint32_t cinit = n_ID_SRS; - uint8_t c_last_index = (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line); + uint8_t c_last_index = (slot_number * symb_slot + l0 + l_line); uint32_t *c_sequence = calloc(c_last_index + 1, sizeof(uint32_t)); pseudo_random_sequence(c_last_index + 1, c_sequence, cinit); // TS 38.211 - 6.4.1.4.2 Sequence generation @@ -255,12 +255,12 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, v = 0; break; case groupHopping: - u = group_number_hopping(slot_number, nr_srs_info->n_ID_SRS, l0, l_line); + u = group_number_hopping(slot_number, nr_srs_info->n_ID_SRS, l0, l_line, frame_parms->symbols_per_slot); v = 0; break; case sequenceHopping: u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; - v = sequence_number_hopping(slot_number, nr_srs_info->n_ID_SRS, M_sc_b_SRS, l0, l_line); + v = sequence_number_hopping(slot_number, nr_srs_info->n_ID_SRS, M_sc_b_SRS, l0, l_line, frame_parms->symbols_per_slot); break; default: LOG_E(NR_PHY, "generate_srs: unknown hopping setting %d !\n", nr_srs_info->groupOrSequenceHopping); diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index ca712bbaf9..1b6b533778 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -145,19 +145,17 @@ void nr_feptx0(RU_t *ru, int tti_tx, int first_symbol, int num_symbols, int aa) void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) { nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; - int cyclic_prefix_type = NFAPI_CP_NORMAL; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; unsigned int aa=0; - int slot_sizeF = (fp->ofdm_symbol_size)* - ((cyclic_prefix_type == 1) ? 12 : 14); + int slot_sizeF = fp->ofdm_symbol_size * fp->symbols_per_slot; int slot = tti_tx; int *txdata = &ru->common.txdata[aa][get_samples_slot_timestamp(fp, slot)]; if (nr_slot_select(cfg,frame_tx,slot) == NR_UPLINK_SLOT) return; - nr_feptx0(ru,slot,0,NR_NUMBER_OF_SYMBOLS_PER_SLOT,aa); + nr_feptx0(ru, slot, 0, fp->symbols_per_slot, aa); LOG_D(PHY, "feptx_ofdm (TXPATH): frame %d, slot %d: txp (time %p) %d dB, txp (freq) %d dB\n", @@ -175,7 +173,6 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx) PHY_VARS_gNB *gNB = gNB_list[0]; nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - int txdataF_offset = slot_tx * fp->samples_per_slot_wCP; start_meas(&ru->precoding_stats); if (gNB->common_vars.analog_bf) { @@ -195,8 +192,8 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx) for (int b = 0; b < ru->num_beams_period; b++) { for (int i = 0; i < Ptx; ++i) { int tx_idx = i + b * ru->nb_tx; - memcpy((void*)ru->common.txdataF_BF[tx_idx], - (void*)&gNB->common_vars.txdataF[b][i][txdataF_offset], + memcpy((void *)ru->common.txdataF_BF[tx_idx], + (void *)gNB->common_vars.txdataF[b][i], fp->samples_per_slot_wCP * sizeof(int32_t)); } } @@ -218,9 +215,6 @@ void nr_feptx(void *arg) int startSymbol = feptx->startSymbol; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; int numSymbols = feptx->numSymbols; - int numSamples = feptx->numSymbols * fp->ofdm_symbol_size; - int txdataF_offset = (slot * fp->samples_per_slot_wCP) + startSymbol * fp->ofdm_symbol_size; - int txdataF_BF_offset = startSymbol * fp->ofdm_symbol_size; int tx_idx = aa + bb * ru->nb_tx; @@ -234,11 +228,17 @@ void nr_feptx(void *arg) } // If there is no digital beamforming we just need to copy the data to RU - if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) - memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], - (void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset], - numSamples * sizeof(int32_t)); - else { + if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) { + // FFT shift + const NR_DL_FRAME_PARMS *fp = &ru->gNB_list[0]->frame_parms; + fft_shift(ru->gNB_list[0]->common_vars.txdataF[bb][aa], + fp->ofdm_symbol_size, + fp->N_RB_DL, + (c16_t *)ru->common.txdataF_BF[tx_idx], + fp->ofdm_symbol_size, + startSymbol, + numSymbols); + } else { AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n"); } diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 4c2c19847c..811851b05c 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -74,9 +74,8 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs cfg->tdd_table.max_tdd_periodicity_list = calloc_or_fail(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t)); for (int slot = 0; slot < nb_slots_to_set; slot++) { nfapi_nr_max_tdd_periodicity_t *p_list = &cfg->tdd_table.max_tdd_periodicity_list[slot]; - p_list->max_num_of_symbol_per_slot_list = - calloc_or_fail(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); - for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + p_list->max_num_of_symbol_per_slot_list = calloc_or_fail(NR_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); + for (int sym = 0; sym < NR_SYMBOLS_PER_SLOT; sym++) { // for each symbol, assign the TLV tag for usage when packing p_list->max_num_of_symbol_per_slot_list[sym].slot_config.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG; } @@ -89,9 +88,9 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs nfapi_nr_max_tdd_periodicity_t *list = &cfg->tdd_table.max_tdd_periodicity_list[slot_number]; // FULL DOWNLINK SLOTS if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_DOWNLINK_SLOT) { - for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 0; - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { + for (int sym = 0; sym < NR_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_SYMBOLS_PER_SLOT].slot_config.value = 0; + if ((sym + 1) % NR_SYMBOLS_PER_SLOT == 0) { slot_number++; list += 1; } @@ -101,7 +100,7 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_MIXED_SLOT) { int nrofDLSymbolsInSlot = tdd_slot_bitmap[slot_index].num_dl_symbols; int nrofULSymbolsInSlot = tdd_slot_bitmap[slot_index].num_ul_symbols; - AssertFatal(nrofDLSymbolsInSlot + nrofULSymbolsInSlot < NR_NUMBER_OF_SYMBOLS_PER_SLOT, + AssertFatal(nrofDLSymbolsInSlot + nrofULSymbolsInSlot < NR_SYMBOLS_PER_SLOT, "illegal symbol configuration DL %d, UL %d\n", nrofDLSymbolsInSlot, nrofULSymbolsInSlot); @@ -110,11 +109,11 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 0; } // Flexible Symbols - for (int sym = nrofDLSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym++) { + for (int sym = nrofDLSymbolsInSlot; sym < NR_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym++) { list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 2; } // UL Symbols - for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + for (int sym = NR_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym < NR_SYMBOLS_PER_SLOT; sym++) { list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 1; } slot_number++; @@ -122,9 +121,9 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs } // FULL UPLINK SLOTS if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_UPLINK_SLOT) { - for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 1; - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { + for (int sym = 0; sym < NR_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_SYMBOLS_PER_SLOT].slot_config.value = 1; + if ((sym + 1) % NR_SYMBOLS_PER_SLOT == 0) { slot_number++; list += 1; } @@ -134,14 +133,14 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs // Dump 1 period on the output for (int s = 0; s < fs->numb_slots_period; s++) { if (tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT) { - char flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT + 1]; + char flexi_slot[NR_SYMBOLS_PER_SLOT + 1]; memset(flexi_slot, 0, sizeof(flexi_slot)); - for (int symb = 0; symb < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symb++) { + for (int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { uint8_t val = cfg->tdd_table.max_tdd_periodicity_list[s].max_num_of_symbol_per_slot_list[symb].slot_config.value; char *symb_type_s[] = {"D", "U", "F"}; flexi_slot[symb] = *symb_type_s[val]; } - flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = '\0'; + flexi_slot[NR_SYMBOLS_PER_SLOT] = '\0'; LOG_I(NR_PHY, "TDD period configuration: slot %d is FLEXIBLE: %s\n", s, flexi_slot); } else { LOG_I(NR_PHY, @@ -163,25 +162,25 @@ int nr_slot_select(const nfapi_nr_config_request_scf_t *cfg, int nr_frame, int n return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT); } - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 1) { check_slot++; } } - if (check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (check_slot == NR_SYMBOLS_PER_SLOT) { return (NR_UPLINK_SLOT); } check_slot = 0; - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) { check_slot++; } } - if (check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (check_slot == NR_SYMBOLS_PER_SLOT) { return (NR_DOWNLINK_SLOT); } else { return (NR_MIXED_SLOT); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 4e69f8fa69..97ad60cfff 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -146,7 +146,6 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n", frame, slot, ssb_start_symbol); const nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming; c16_t ***txdataF = gNB->common_vars.txdataF; - int txdataF_offset = slot * fp->samples_per_slot_wCP; // beam number in a scenario with multiple concurrent beams int bitmap = SL_to_bitmap(ssb_start_symbol, 4); // 4 ssb symbols int beam_nb = beam_index_allocation(gNB->enable_analog_das, @@ -156,15 +155,15 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n fp->symbols_per_slot, bitmap); - nr_generate_pss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp); + nr_generate_pss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp); + nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp); uint16_t slots_per_hf = (fp->slots_per_frame) >> 1; int n_hf = slot < slots_per_hf ? 0 : 1; int hf = fp->Lmax == 4 ? n_hf : 0; nr_generate_pbch_dmrs(nr_gold_pbch(fp->Lmax, gNB->gNB_config.cell_config.phy_cell_id.value, hf, ssb_index & 7), - &txdataF[beam_nb][0][txdataF_offset], + txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, @@ -182,7 +181,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n nr_generate_pbch(gNB, ssb_pdu, - &txdataF[beam_nb][0][txdataF_offset], + txdataF[beam_nb][0], ssb_start_symbol, n_hf, frame, @@ -246,7 +245,6 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, { const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - const int txdataF_offset = slot * fp->samples_per_slot_wCP; if ((cfg->cell_config.frame_duplex_type.value == TDD) && (nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return; @@ -254,7 +252,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, // clear the transmit data array and beam index for the current slot for (int i = 0; i < gNB->common_vars.num_beams_period; i++) { for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) { - memset(&gNB->common_vars.txdataF[i][aa][txdataF_offset], 0, fp->samples_per_slot_wCP * sizeof(***gNB->common_vars.txdataF)); + memset(gNB->common_vars.txdataF[i][aa], 0, fp->samples_per_slot_wCP * sizeof(***gNB->common_vars.txdataF)); } } @@ -268,13 +266,13 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, { int slot_prs = (slot - i * prs_config->PRSResourceTimeGap + fp->slots_per_frame) % fp->slots_per_frame; LOG_D(PHY,"gNB_TX: frame %d, slot %d, slot_prs %d, PRS Resource ID %d\n",frame, slot, slot_prs, rsc_id); - nr_generate_prs(slot_prs, &gNB->common_vars.txdataF[0][0][txdataF_offset], AMP, prs_config, fp); + nr_generate_prs(slot_prs, gNB->common_vars.txdataF[0][0], AMP, prs_config, fp); } } } for (int i = 0; i < UL_dci_req->numPdus; ++i) - nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, &gNB->frame_parms, slot); int num_pdsch = 0; for (int i = 0; i < DL_req->dl_tti_request_body.nPDUs; ++i) { @@ -284,7 +282,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, nr_common_signal_procedures(gNB, frame, slot, &dl_tti_pdu->ssb_pdu); break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, &gNB->frame_parms, slot); break; case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: nr_generate_csi_rs_gNB(gNB, slot, &dl_tti_pdu->csi_rs_pdu); @@ -321,7 +319,8 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) { if (gNB->phase_comp) { apply_nr_rotation_TX(fp, - &gNB->common_vars.txdataF[i][aa][txdataF_offset], + gNB->common_vars.txdataF[i][aa], + true, fp->symbol_rotation[0], slot, fp->N_RB_DL, @@ -333,7 +332,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, T_INT(frame), T_INT(slot), T_INT(aa), - T_BUFFER(&gNB->common_vars.txdataF[i][aa][txdataF_offset], fp->samples_per_slot_wCP * sizeof(int32_t))); + T_BUFFER(gNB->common_vars.txdataF[i][aa], fp->samples_per_slot_wCP * sizeof(int32_t))); } } stop_meas(&gNB->phase_comp_stats); @@ -980,7 +979,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const uint16_t ofdm_symbol_size = frame_parms->ofdm_symbol_size; - const int nb_symb = frame_parms->symbols_per_slot; const uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); { @@ -993,7 +991,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N int first_symb = 0, num_symb = 0; if (frame_parms->frame_type == TDD) - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < frame_parms->symbols_per_slot; symbol_count++) { if (slot_conf[symbol_count].slot_config.value == 1) { if (num_symb == 0) first_symb = symbol_count; @@ -1001,11 +999,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N } } else - num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT; + num_symb = frame_parms->symbols_per_slot; gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); } - const int soffset = (slot_rx & 3) * nb_symb * ofdm_symbol_size; + const int soffset = (slot_rx & 3) * frame_parms->symbols_per_slot * ofdm_symbol_size; start_meas(&gNB->phy_proc_rx); for (int i = 0; i < gNB->max_nb_pucch; i++) { @@ -1368,7 +1366,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), - T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], nb_symb * ofdm_symbol_size * 4)); + T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], frame_parms->symbols_per_slot * ofdm_symbol_size * 4)); } return pusch_DTX; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index cc6a2ee23b..fb99c29965 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -304,10 +304,10 @@ static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs * *********************************************************************/ bool 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]) + const UE_nr_rxtx_proc_t *proc, + c16_t **txdataF, + nr_phy_data_tx_t *phy_data, + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { if(phy_data->srs_vars.active == false) { return false; @@ -375,7 +375,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n T(T_UE_PHY_UL_TICK, T_INT(ue->Mod_id), T_INT(frame_tx % 1024), T_INT(slot_tx)); #endif - const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * ue->frame_parms.ofdm_symbol_size; + const int samplesF_per_slot = ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size; c16_t txdataF_buf[ue->frame_parms.nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32))); memset(txdataF_buf, 0, sizeof(txdataF_buf)); c16_t *txdataF[ue->frame_parms.nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */ @@ -383,7 +383,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n txdataF[i] = &txdataF_buf[i * samplesF_per_slot]; LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT] = {0}; start_meas_nr_ue_phy(ue, PHY_PROC_TX); @@ -618,7 +618,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, toFree2, dlsch[0].Nl, ue->frame_parms.nb_antennas_rx, - rx_size_symbol * NR_SYMBOLS_PER_SLOT, + rx_size_symbol * ue->frame_parms.symbols_per_slot, false); uint32_t nvar = 0; @@ -1027,22 +1027,21 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ /* process PDCCH */ LOG_D(PHY, " ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", proc->frame_rx % 1024, proc->nr_slot_rx); start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); - int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config); + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config, fp->symbols_per_slot); int max_nb_symb_pdcch = get_max_pdcch_symb(phy_pdcch_config); int llr_size_symbol = get_pdcch_max_rbs(phy_pdcch_config) * 9; c16_t pdcch_llr[phy_pdcch_config->nb_search_space][num_monitoring_occ][max_nb_symb_pdcch * llr_size_symbol]; - int start_symb_pdcch, last_symb_pdcch; - set_first_last_pdcch_symb(phy_pdcch_config, &start_symb_pdcch, &last_symb_pdcch); + set_first_last_pdcch_symb(phy_pdcch_config, fp->symbols_per_slot, &start_symb_pdcch, &last_symb_pdcch); /* Temporarily loop over symbols in the slot, perform OFDM demod and process PDCCH. When symbol based proc design is fully merged, this function will be called to process only one symbol and OFDM demod will be removed from here. */ - const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; - __attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; + const uint32_t rxdataF_sz = fp->samples_per_slot_wCP; + __attribute__((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz]; for (int symbol = start_symb_pdcch; symbol <= last_symb_pdcch; symbol++) { - NR_DL_FRAME_PARMS *fp = &ue->frame_parms; nr_slot_fep(ue, fp, proc->nr_slot_rx, symbol, rxdataF, link_type_dl, 0, ue->common_vars.rxdata); __attribute__((aligned(32))) c16_t rxdataF_symb[fp->nb_antennas_rx][((fp->ofdm_symbol_size + 7) / 8) * 8]; @@ -1058,7 +1057,7 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); TracyCZoneEnd(ctx); if (ue->phy_sim_rxdataF) - memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * max_nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size); + memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * max_nb_symb_pdcch * fp->ofdm_symbol_size); } int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) @@ -1248,7 +1247,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ // do procedures for CSI-RS if (phy_data->csirs_vars.active == 1) { - for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { + for(int symb = 0; symb < ue->frame_parms.symbols_per_slot; symb++) { if(is_csi_rs_in_symbol(phy_data->csirs_vars.csirs_config_pdu, symb)) { if (!slot_fep_map[symb]) { nr_slot_fep(ue, &ue->frame_parms, proc->nr_slot_rx, symb, rxdataF, link_type_dl, 0, ue->common_vars.rxdata); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index 9b17546f61..0441cf47c3 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -300,7 +300,7 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc tx_action = 1; } - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]; for (int i = 0; i < 14; i++) was_symbol_used[i] = true; if (tx_action) { diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index be1187f574..8d082a84aa 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -136,7 +136,7 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txdataF, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { const int nr_slot_tx = proc->nr_slot_tx; NR_UE_PUCCH *pucch_vars = &phy_data->pucch_vars; diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 6f4282f130..7e45cdd9b6 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -56,7 +56,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; UE_nr_rxtx_proc_t proc; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t downlink_frequency[MAX_NUM_CCs][4]; double cpuf; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b068936739..df97840e24 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -104,7 +104,7 @@ const char *__asan_default_options() PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; char *uecap_file; @@ -1123,40 +1123,53 @@ int main(int argc, char **argv) phy_procedures_gNB_TX(gNB, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req, frame, slot); stop_meas(&gNB->phy_proc_tx); - int txdataF_offset = slot * frame_parms->samples_per_slot_wCP; - if (n_trials==1) { LOG_M("txsigF0.m","txsF0=", - &gNB->common_vars.txdataF[0][0][txdataF_offset +2 * frame_parms->ofdm_symbol_size], + &gNB->common_vars.txdataF[0][0][2 * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); if (gNB->frame_parms.nb_antennas_tx>1) LOG_M("txsigF1.m","txsF1=", - &gNB->common_vars.txdataF[0][1][txdataF_offset + 2 * frame_parms->ofdm_symbol_size], + &gNB->common_vars.txdataF[0][1][2 * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); } if (n_trials == 1) - printf("slot_offset %d, txdataF_offset %d \n", slot_offset, txdataF_offset); + printf("slot_offset %d\n", slot_offset); //TODO: loop over slots for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - + c16_t fft_in_buff[frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot] __attribute__((aligned(64))); + memset(fft_in_buff, 0, sizeof(fft_in_buff)); if (cyclic_prefix_type == 1) { - PHY_ofdm_mod((int *)&gNB->common_vars.txdataF[0][aa][txdataF_offset], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 12); + PHY_ofdm_mod((int *)fft_in_buff, (int *)&txdata[aa][slot_offset], frame_parms->ofdm_symbol_size, 12, frame_parms->nb_prefix_samples, CYCLIC_PREFIX); } else { - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]; for (int i = 0; i < 14; i++) { was_symbol_used[i] = true; } - nr_normal_prefix_mod(&gNB->common_vars.txdataF[0][aa][txdataF_offset], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 14); + nr_normal_prefix_mod(fft_in_buff, &txdata[aa][slot_offset], 14, frame_parms, diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 5702be2cf9..e3281b1e49 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -55,7 +55,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; @@ -525,17 +525,28 @@ int main(int argc, char **argv) nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]); int samp = get_samples_slot_timestamp(frame_parms, slot); - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + for (aa = 0; aa < gNB->frame_parms.nb_antennas_tx; aa++) { + c16_t fft_in_buff[frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot] __attribute__((aligned(64))); + memset(fft_in_buff, 0, sizeof(fft_in_buff)); if (cyclic_prefix_type == 1) { apply_nr_rotation_TX(frame_parms, gNB->common_vars.txdataF[0][aa], + true, frame_parms->symbol_rotation[0], slot, frame_parms->N_RB_DL, 0, 12); - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 12); + + PHY_ofdm_mod((int *)fft_in_buff, (int *)&txdata[aa][samp], frame_parms->ofdm_symbol_size, 12, @@ -544,21 +555,30 @@ int main(int argc, char **argv) } else { apply_nr_rotation_TX(frame_parms, gNB->common_vars.txdataF[0][aa], + true, frame_parms->symbol_rotation[0], slot, frame_parms->N_RB_DL, 0, 14); - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], - (int*)&txdata[aa][samp], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 14); + + PHY_ofdm_mod((int *)fft_in_buff, + (int *)&txdata[aa][samp], frame_parms->ofdm_symbol_size, 1, frame_parms->nb_prefix_samples0, CYCLIC_PREFIX); - PHY_ofdm_mod((int *)&gNB->common_vars.txdataF[0][aa][frame_parms->ofdm_symbol_size], - (int*)&txdata[aa][samp + frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size], + PHY_ofdm_mod((int *)fft_in_buff + frame_parms->ofdm_symbol_size, + (int *)&txdata[aa][samp + frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 13, frame_parms->nb_prefix_samples, @@ -567,9 +587,9 @@ int main(int argc, char **argv) } } } - LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0][0],frame_length_complex_samples_no_prefix, 1, 1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[0][1],frame_length_complex_samples_no_prefix, 1, 1); + LOG_M("txsigF0.m", "txsF0", gNB->common_vars.txdataF[0][0], frame_parms->samples_per_slot_wCP, 1, 1); + if (gNB->frame_parms.nb_antennas_tx > 1) + LOG_M("txsigF1.m", "txsF1", gNB->common_vars.txdataF[0][1], frame_parms->samples_per_slot_wCP, 1, 1); } else { printf("Reading %d samples from file to antenna buffer %d\n",frame_length_complex_samples,0); diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 7966c74375..6f6d7c1102 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -79,7 +79,7 @@ RU_t *ru; double cpuf; //uint8_t nfapi_mode=0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint32_t N_RB_DL = 106; NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } diff --git a/openair1/SIMULATION/NR_PHY/psbchsim.c b/openair1/SIMULATION/NR_PHY/psbchsim.c index cb78915cbb..faf5826a48 100644 --- a/openair1/SIMULATION/NR_PHY/psbchsim.c +++ b/openair1/SIMULATION/NR_PHY/psbchsim.c @@ -71,7 +71,7 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, uint8_t *nb_dmrs_re_per } uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; THREAD_STRUCT thread_struct; instance_t DUuniqInstance = 0; instance_t CUuniqInstance = 0; @@ -246,7 +246,7 @@ static int freq_domain_loopback(PHY_VARS_NR_UE *UE_tx, PHY_VARS_NR_UE *UE_rx, in sl_ue2->sl_config.sl_sync_source.rx_slss_id); NR_DL_FRAME_PARMS *fp = &sl_ue1->sl_frame_params; - const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size; + const int samplesF_per_slot = fp->symbols_per_slot * fp->ofdm_symbol_size; c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32))); memset(txdataF_buf, 0, sizeof(txdataF_buf)); c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */ diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index bfa294a55f..9ddd76e038 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -53,7 +53,7 @@ THREAD_STRUCT thread_struct; PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t downlink_frequency[MAX_NUM_CCs][4]; double cpuf; diff --git a/openair1/SIMULATION/NR_PHY/srssim.c b/openair1/SIMULATION/NR_PHY/srssim.c index d68f925374..dff856e703 100644 --- a/openair1/SIMULATION/NR_PHY/srssim.c +++ b/openair1/SIMULATION/NR_PHY/srssim.c @@ -48,7 +48,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; char *uecap_file = NULL; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; uint64_t downlink_frequency[MAX_NUM_CCs][4]; @@ -496,7 +496,7 @@ int main(int argc, char *argv[]) proc.frame_tx = frame; proc.nr_slot_tx = slot; proc.nr_slot_rx = slot; - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT] = {0}; int slot_offset = get_samples_slot_timestamp(fp, slot); uint16_t ofdm_symbol_size = fp->ofdm_symbol_size; int slot_offsetF = (slot % RU_RX_SLOT_DEPTH) * fp->symbols_per_slot * ofdm_symbol_size; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index d15deb4277..93aae9c1d6 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -55,7 +55,7 @@ THREAD_STRUCT thread_struct; PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t downlink_frequency[MAX_NUM_CCs][4]; static softmodem_params_t softmodem_params; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index da6b901a11..fa8643023f 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -106,7 +106,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; char *uecap_file; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; //uint8_t nfapi_mode = 0; diff --git a/openair2/COMMON/xnap_messages_types.h b/openair2/COMMON/xnap_messages_types.h new file mode 100644 index 0000000000..bca8bc80f4 --- /dev/null +++ b/openair2/COMMON/xnap_messages_types.h @@ -0,0 +1,180 @@ +/* + * 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 XNAP_MESSAGES_TYPES_H_ +#define XNAP_MESSAGES_TYPES_H_ + +#include "common/5g_platform_types.h" + +typedef struct { + // PLMN Identity + plmn_id_t plmn; + // Number of supported S-NSSAIs + uint16_t num_nssai; + // List of supported S-NSSAIs + nssai_t *nssai; +} xnap_plmn_support_t; + +typedef struct { + // Tracking Area Code + uint32_t tac; + // Number of supported PLMNs + uint8_t num_plmn; + // List of supported PLMNs + xnap_plmn_support_t *plmn_support; +} xnap_tai_support_t; + +typedef struct { + // PLMN Identity + plmn_id_t plmn; + // AMF Region Identifier + uint8_t amf_region_id; +} xnap_amf_region_info_t; + +/* 3GPP TS 38.423 9.1.3.1 – Xn Setup Request */ +typedef struct { + // Global NG-RAN Node ID (gNB_id+plmn) (M) + uint32_t gNB_id; + plmn_id_t plmn; + // TAI Support List (M) + uint16_t num_tai; + xnap_tai_support_t *tai_support; + // AMF Region Information (M) + uint8_t num_amf_regions; + xnap_amf_region_info_t *amf_region_info; +} xnap_setup_req_t; + +/* 3GPP TS 38.423 9.1.3.2 – Xn Setup Response */ +typedef struct { + // Global NG-RAN Node ID (gNB_id+plmn) (M) + uint32_t gNB_id; + plmn_id_t plmn; + // TAI Support List (M) + uint16_t num_tai; + xnap_tai_support_t *tai_support; +} xnap_setup_resp_t; + +typedef enum xnap_cause_radio_network_e { + XNAP_CAUSE_RADIO_NETWORK_LAYER_CELL_NOT_AVAILABLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_HANDOVER_DESIRABLE_FOR_RADIO_REASONS, + XNAP_CAUSE_RADIO_NETWORK_LAYER_HANDOVER_TARGET_NOT_ALLOWED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_INVALID_AMF_SET_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NO_RADIO_RESOURCES_AVAILABLE_IN_TARGET_CELL, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PARTIAL_HANDOVER, + XNAP_CAUSE_RADIO_NETWORK_LAYER_REDUCE_LOAD_IN_SERVING_CELL, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCE_OPTIMISATION_HANDOVER, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TIME_CRITICAL_HANDOVER, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_RELOCOVERALL_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_RELOCPREP_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_GUAMI_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_LOCAL_NG_RAN_NODE_UE_XNAP_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_INCONSISTENT_REMOTE_NG_RAN_NODE_UE_XNAP_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_ENCRYPTION_AND_OR_INTEGRITY_PROTECTION_ALGORITHMS_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PROTECTION_ALGORITHMS_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_MULTIPLE_PDU_SESSION_ID_INSTANCES, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_PDU_SESSION_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_QOS_FLOW_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_MULTIPLE_QOS_FLOW_ID_INSTANCES, + XNAP_CAUSE_RADIO_NETWORK_LAYER_SWITCH_OFF_ONGOING, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NOT_SUPPORTED_5QI_VALUE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_DCOVERALL_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_DCPREP_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_ACTION_DESIRABLE_FOR_RADIO_REASONS, + XNAP_CAUSE_RADIO_NETWORK_LAYER_REDUCE_LOAD, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCE_OPTIMISATION, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TIME_CRITICAL_ACTION, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TARGET_NOT_ALLOWED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NO_RADIO_RESOURCES_AVAILABLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_INVALID_QOS_COMBINATION, + XNAP_CAUSE_RADIO_NETWORK_LAYER_ENCRYPTION_ALGORITHMS_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PROCEDURE_CANCELLED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RRM_PURPOSE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_IMPROVE_USER_BIT_RATE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_USER_INACTIVITY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RADIO_CONNECTION_WITH_UE_LOST, + XNAP_CAUSE_RADIO_NETWORK_LAYER_FAILURE_IN_THE_RADIO_INTERFACE_PROCEDURE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_BEARER_OPTION_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_INTEGRITY_PROTECTION_NOT_POSSIBLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_CONFIDENTIALITY_PROTECTION_NOT_POSSIBLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE_S, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UE_MAX_IP_DATA_RATE_REASON, + XNAP_CAUSE_RADIO_NETWORK_LAYER_CP_INTEGRITY_PROTECTION_FAILURE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_INTEGRITY_PROTECTION_FAILURE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_SLICE_NOT_SUPPORTED_BY_NG_RAN, + XNAP_CAUSE_RADIO_NETWORK_LAYER_MN_MOBILITY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_SN_MOBILITY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_COUNT_REACHES_MAX_VALUE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_OLD_NG_RAN_NODE_UE_XNAP_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PDCP_OVERLOAD, + XNAP_CAUSE_RADIO_NETWORK_LAYER_DRB_ID_NOT_AVAILABLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNSPECIFIED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UE_CONTEXT_ID_NOT_KNOWN, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NON_RELOCATION_OF_CONTEXT, + XNAP_CAUSE_RADIO_NETWORK_LAYER_CHO_CPC_RESOURCES_TOBECHANGED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RSN_NOT_AVAILABLE_FOR_THE_UP, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NPN_ACCESS_DENIED +} xnap_cause_radio_network_t; + +typedef enum xnap_cause_transport_layer_e { + XNAP_CAUSE_TRANSPORT_LAYER_TRANSPORT_RESOURCE_UNAVAILABLE, + XNAP_CAUSE_TRANSPORT_LAYER_UNSPECIFIED +} xnap_cause_transport_layer_t; + +typedef enum xnap_cause_protocol_e { + XNAP_CAUSE_PROTOCOL_TRANSFER_SYNTAX_ERROR, + XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_REJECT, + XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_IGNORE_AND_NOTIFY, + XNAP_CAUSE_PROTOCOL_MESSAGE_NOT_COMPATIBLE_WITH_RECEIVER_STATE, + XNAP_CAUSE_PROTOCOL_SEMANTIC_ERROR, + XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED, + XNAP_CAUSE_PROTOCOL_UNSPECIFIED +} xnap_cause_protocol_t; + +typedef enum xnap_cause_misc_e { + XNAP_CAUSE_MISC_CONTROL_PROCESSING_OVERLOAD, + XNAP_CAUSE_MISC_HARDWARE_FAILURE, + XNAP_CAUSE_MISC_O_AND_M_INTERVENTION, + XNAP_CAUSE_MISC_NOT_ENOUGH_USER_PLANE_PROCESSING_RESOURCES, + XNAP_CAUSE_MISC_UNSPECIFIED +} xnap_cause_misc_t; + +typedef enum xnap_cause_group_e { + XNAP_CAUSE_NOTHING, + XNAP_CAUSE_RADIO_NETWORK, + XNAP_CAUSE_TRANSPORT, + XNAP_CAUSE_PROTOCOL, + XNAP_CAUSE_MISC, +} xnap_cause_group_t; + +typedef struct xnap_cause_s { + /* Cause group (e.g. radioNetwork, transport, protocol, misc) */ + xnap_cause_group_t type; + /* Specific cause value within the selected cause group */ + uint8_t value; +} xnap_cause_t; + +/* 3GPP TS 38.423 9.1.3.3 – Xn Setup Failure */ +typedef struct { + // Cause (M) + xnap_cause_t cause; +} xnap_setup_failure_t; + +#endif /* XNAP_MESSAGES_TYPES_H_ */ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 11dac69484..b1765f7c38 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1184,6 +1184,7 @@ typedef struct { } nr_prach_info_3gpp_fr2_t; // Table 6.3.3.2-4: Random access configurations for FR2 and unpaired spectrum +// and NTN-FR2 and paired as defined in 38.211v18.06 static const nr_prach_info_3gpp_fr2_t table_6_3_3_2_4_prachConfig_Index[256] = { // format, format, x, y, y, SFN_nbr, star_symb, slots_sfn, occ_slot, // duration @@ -1458,7 +1459,8 @@ int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_ran if (frequency_range==FR1) format = table_6_3_3_2_2_prachConfig_Index[index].format; else - AssertFatal(0==1,"no paired spectrum for FR2\n"); + // Table defined for NTN-FR2 and paired in 3GPP Spec 38.211v18.06 + format = table_6_3_3_2_4_prachConfig_Index[index].format; } return format; } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index c42406149e..475badfdba 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -96,28 +96,28 @@ static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_str for (int i = 0; i < fs->numb_slots_period; i++) { fapi_nr_max_tdd_periodicity_t *period_list = &tdd_table->max_tdd_periodicity_list[i]; period_list->max_num_of_symbol_per_slot_list = - malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT * sizeof(*period_list->max_num_of_symbol_per_slot_list)); + malloc(NR_SYMBOLS_PER_SLOT * sizeof(*period_list->max_num_of_symbol_per_slot_list)); if (pc->tdd_slot_bitmap[i].slot_type == TDD_NR_DOWNLINK_SLOT) { - for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) { + for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 0; } } if (pc->tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) { - for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) { + for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 1; } } if (pc->tdd_slot_bitmap[i].slot_type == TDD_NR_MIXED_SLOT) { int dl_symb = pc->tdd_slot_bitmap[i].num_dl_symbols; int ul_symb = pc->tdd_slot_bitmap[i].num_ul_symbols; - int g_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT - dl_symb - ul_symb; + int g_symb = NR_SYMBOLS_PER_SLOT - dl_symb - ul_symb; for (int s = 0; s < dl_symb; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 0; } for (int s = dl_symb; s < dl_symb + g_symb; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 2; } - for (int s = dl_symb + g_symb; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) { + for (int s = dl_symb + g_symb; s < NR_SYMBOLS_PER_SLOT; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 1; } } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c index 809ce054f4..75273461b1 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c @@ -77,19 +77,19 @@ void sl_set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, for(int memory_alloc = 0 ; memory_alloc < nb_slots_per_period; memory_alloc++) tdd_table->max_tdd_periodicity_list[memory_alloc].max_num_of_symbol_per_slot_list = - (fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT*sizeof(fapi_nr_max_num_of_symbol_per_slot_t)); + (fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_SYMBOLS_PER_SLOT*sizeof(fapi_nr_max_num_of_symbol_per_slot_t)); int slot_number = (nb_slots_per_period - nrofUplinkSlots) - (nrofUplinkSymbols ? 1 : 0); if (nrofUplinkSymbols != 0) { - for(int number_of_symbol = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) { + for(int number_of_symbol = NR_SYMBOLS_PER_SLOT - nrofUplinkSymbols; number_of_symbol < NR_SYMBOLS_PER_SLOT; number_of_symbol++) { tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 1; } slot_number++; } while(slot_number < nb_slots_per_period) { - for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) { - tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config = 1; - if((number_of_symbol + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) + for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_SYMBOLS_PER_SLOT; number_of_symbol++) { + tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_SYMBOLS_PER_SLOT].slot_config = 1; + if((number_of_symbol + 1) % NR_SYMBOLS_PER_SLOT == 0) slot_number++; } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index a93ad9f8d2..1d534ee80d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -425,8 +425,8 @@ static bool check_mixed_slot_prach(frame_structure_t *fs, int slot, int start_pr tdd_bitmap_t *bitmap = &fs->period_cfg.tdd_slot_bitmap[slot % fs->numb_slots_period]; if (bitmap->num_ul_symbols == 0) return false; - int ul_end = NR_NUMBER_OF_SYMBOLS_PER_SLOT - 1; - int ul_start = NR_NUMBER_OF_SYMBOLS_PER_SLOT - bitmap->num_ul_symbols; + int ul_end = NR_SYMBOLS_PER_SLOT - 1; + int ul_start = NR_SYMBOLS_PER_SLOT - bitmap->num_ul_symbols; if (start_prach < ul_start || end_prach > ul_end) return false; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 2c3ee539fc..d60fd6bfd3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3898,6 +3898,8 @@ static int nr_ue_validate_successrar(uint8_t *pduP, int32_t pdu_len, NR_UE_MAC_I return n; } +#define MAX_NUM_DATA_IND 1024 + /////////////////////////////////// // brief: nr_ue_process_mac_pdu // function: parsing DL PDU header @@ -3962,6 +3964,9 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ pdu_len -= n; } + nr_rlc_data_ind_t data_ind[MAX_NUM_DATA_IND] = {0}; + int num_data_ind = 0; + while (!done && pdu_len > 0){ uint16_t mac_len = 0x0000; uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct @@ -3992,7 +3997,9 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ if (mac_len > 0) { LOG_DDUMP(NR_MAC, (void *)pduP, mac_subheader_len + mac_len, LOG_DUMP_CHAR, "DL_SCH_LCID_CCCH (e.g. RRCSetup) payload: "); - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); } break; case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: @@ -4104,15 +4111,20 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ // MAC SDU // From values 1 to 32 it equals to the identity of the logical channel case 1 ... 32: - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return; + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { + LOG_E(MAC, "get_mac_len(): invalid pdu_len %d (mac_len %d mac_subheader_len %d)\n", pdu_len, mac_len, mac_subheader_len); + done = 1; + break; + } // discard the received subPDU if RB is suspended if (is_lcid_suspended(mac, rx_lcid)) { LOG_W(NR_MAC, "Received PDU for a suspended RB, corresponding to LCID %d. Dropping it.\n", rx_lcid); break; } LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len); - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); break; default: LOG_W(MAC, "unknown lcid %02x\n", rx_lcid); @@ -4120,9 +4132,13 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ } pduP += (mac_subheader_len + mac_len); pdu_len -= (mac_subheader_len + mac_len); - if (pdu_len < 0) + if (pdu_len < 0) { LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", mac->ue_id, frameP, slot, pdu_len); + done = 1; + } } + + nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, data_ind, num_data_ind); } /** diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index cc933b50e4..071514cbaa 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1461,23 +1461,24 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent) static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP) { + logical_chan_id_t ch[NR_MAX_NUM_LCID] = {0}; + int n = 0; for (int i = 0; i < mac->lc_ordered_list.count; i++) { nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; if (lc_info->rb_suspended) continue; - int lcid = lc_info->lcid; + ch[n++] = lc_info->lcid; + } + + mac_rlc_status_resp_t ret[NR_MAX_NUM_LCID] = {0}; + nr_mac_rlc_status_ind(mac->ue_id, frameP, n, ch, ret); + for (int i = 0; i < n; ++i) { + const logical_chan_id_t lcid = ch[i]; + const rlc_buffer_occupancy_t b = ret[i].bytes_in_buffer; NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); - mac_rlc_status_resp_t rlc_status = nr_mac_rlc_status_ind(mac->ue_id, frameP, lcid); - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(NR_MAC, - "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", - mac->ue_id, - lcid, - rlc_status.bytes_in_buffer, - frameP, - slotP); - } - lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer; + if (b > 0) + LOG_D(NR_MAC, "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", mac->ue_id, lcid, b, frameP, slotP); + lc_sched_info->LCID_buffer_remain = b; } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c index 71e4c7fe25..9f22cbc882 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c @@ -63,9 +63,9 @@ static uint8_t sl_get_elapsed_slots(uint32_t slot, uint32_t sl_slot_bitmap) */ static uint8_t sl_determine_if_sidelink_slot(uint8_t sl_startsym, uint8_t sl_lensym, uint8_t num_ulsym) { - uint8_t ul_startsym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - num_ulsym; + uint8_t ul_startsym = NR_SYMBOLS_PER_SLOT - num_ulsym; - if ((sl_startsym >= ul_startsym) && (sl_lensym <= NR_NUMBER_OF_SYMBOLS_PER_SLOT)) { + if ((sl_startsym >= ul_startsym) && (sl_lensym <= NR_SYMBOLS_PER_SLOT)) { LOG_D(MAC, "MIXED SLOT is a SIDELINK SLOT. Sidelink Symbols: %d-%d, Uplink Symbols: %d-%d\n", sl_startsym, @@ -107,13 +107,13 @@ int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int slot, uint8_ const fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { if (current_slot->max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { ul_sym++; } } - if (ul_sym == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (ul_sym == NR_SYMBOLS_PER_SLOT) { slot_type = NR_SIDELINK_SLOT; } else if (ul_sym) { slot_type = sl_determine_if_sidelink_slot(cfg->sl_bwp_config.sl_start_symbol, cfg->sl_bwp_config.sl_num_symbols, ul_sym); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 99f0e9bb3c..fc563b56b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1024,7 +1024,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, int s = get_slot_idx_in_period(temp_slot, fs); const tdd_bitmap_t *bm = &fs->period_cfg.tdd_slot_bitmap[s]; bool is_mixed = is_mixed_slot(s, fs); - uint16_t slot_mask = is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - bm->num_ul_symbols, bm->num_ul_symbols) : 0x3fff; + uint16_t slot_mask = is_mixed ? SL_to_bitmap(NR_SYMBOLS_PER_SLOT - bm->num_ul_symbols, bm->num_ul_symbols) : 0x3fff; long startSymbolAndLength = tda_list->list.array[i]->startSymbolAndLength; int start, nr; SLIV2SL(startSymbolAndLength, &start, &nr); @@ -1699,21 +1699,23 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ int current_harq_pid = sched_ctrl->retrans_dl_harq.head; - logical_chan_id_t lcid = DL_SCH_LCID_CCCH; + logical_chan_id_t lcid = 0; if (current_harq_pid < 0) { - // Check for data on SRB0 (RRCSetup) - mac_rlc_status_resp_t srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); + const logical_chan_id_t lcid_l[2] = {DL_SCH_LCID_CCCH, DL_SCH_LCID_DCCH}; + mac_rlc_status_resp_t stat[2]; + nr_mac_rlc_status_ind(UE->rnti, frameP, 2, lcid_l, stat); - if (srb_status.bytes_in_buffer == 0) { - lcid = DL_SCH_LCID_DCCH; - // Check for data on SRB1 (RRCReestablishment, RRCReconfiguration) - srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); + if (stat[0].bytes_in_buffer > 0) { + // some data in SRB0 (likely RRCSetup) + mac_sdu_length = stat[0].bytes_in_buffer; + lcid = lcid_l[0]; + } else if (stat[1].bytes_in_buffer > 0) { + // some data in SRB1 (likely RRCReestablishmnt/RRCReconfiguration) + mac_sdu_length = stat[1].bytes_in_buffer; + lcid = lcid_l[1]; + } else { + return; // no data to forward } - - // Need to wait until data for Msg4 is ready - if (srb_status.bytes_in_buffer == 0) - return; - mac_sdu_length = srb_status.bytes_in_buffer; } const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index e511850414..c6d130cdaf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -101,7 +101,7 @@ static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc, uint16_t *vrb_map = cc[CC_id].vrb_map[beam]; const int extra_prb = ssb_subcarrier_offset > 0; for (int rb = 0; rb < 20 + extra_prb; rb++) - vrb_map[rbStart + rb] = SL_to_bitmap(symStart % NR_NUMBER_OF_SYMBOLS_PER_SLOT, 4); + vrb_map[rbStart + rb] = SL_to_bitmap(symStart % NR_SYMBOLS_PER_SLOT, 4); } static int encode_mib(NR_BCCH_BCH_Message_t *mib, frame_t frame, uint8_t *buffer, int buf_size) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 8ad9d4f6bc..dbf285e931 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -50,6 +50,8 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) +#define MAX_NUM_DATA_REQ 1024 + int get_dl_tda(const gNB_MAC_INST *nrmac, int slot) { /* we assume that this function is mutex-protected from outside */ @@ -326,31 +328,38 @@ static uint32_t update_dlsch_buffer(frame_t frame, slot_t slot, NR_UE_info_t *UE sched_ctrl->num_total_bytes = 0; sched_ctrl->dl_pdus_total = 0; + logical_chan_id_t ch[NR_MAX_NUM_LCID] = {0}; + int n = 0; /* loop over all activated logical channels */ - for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { - const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); - const int lcid = c->lcid; - const uint16_t rnti = UE->rnti; - LOG_D(NR_MAC, "UE %x: LCID %d\n", rnti, lcid); - memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); - if (c->suspended) + FOR_EACH_SEQ_ARR(const nr_lc_config_t *, c, &sched_ctrl->lc_config ) { + logical_chan_id_t lcid = c->lcid; + if (c->suspended || (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt))) { + memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); continue; - if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt)) - continue; - sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); + } + ch[n++] = lcid; + } - if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) + mac_rlc_status_resp_t ret[NR_MAX_NUM_LCID] = {0}; + nr_mac_rlc_status_ind(UE->rnti, frame, n, ch, ret); + + for (int i = 0; i < n; ++i) { + logical_chan_id_t lcid = ch[i]; + + if (ret[i].bytes_in_buffer == 0) continue; + sched_ctrl->rlc_status[lcid] = ret[i]; sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer; sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; LOG_D(MAC, - "%4d.%2d UE %04x LCID %d status: %d bytes, total buffer %d bytes %d PDUs\n", + "%4d.%2d UE %04x LCID %d status: %d bytes, %d PDUs, total buffer %d bytes %d PDUs\n", frame, slot, UE->rnti, lcid, - sched_ctrl->rlc_status[lcid].bytes_in_buffer, + ret[i].bytes_in_buffer, + ret[i].pdus_in_buffer, sched_ctrl->num_total_bytes, sched_ctrl->dl_pdus_total); } @@ -1289,47 +1298,25 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) continue; // no data for this LC tbs_size_t len = 0; - int lcid_bytes=0; - while (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) + 1 ) { - // we do not know how much data we will get from RLC, i.e., whether it - // will be longer than 256B or not. Therefore, reserve space for long header, then - // fetch data, then fill real length + + tb_size_t pdu_siz[MAX_NUM_DATA_REQ]; + int num = nr_mac_rlc_multi_data_req(module_id, rnti, true, lcid, bufEnd - buf, (char *)buf, pdu_siz, sizeofArray(pdu_siz)); + DevAssert(num <= sizeofArray(pdu_siz)); + + sdus += num; + int lcid_bytes = 0; + for (int j = 0; j < num; ++j) { NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; - /* limit requested number of bytes to what preprocessor specified, or - * such that TBS is full */ - const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - tbs_size_t len = nr_mac_rlc_data_req(module_id, - rnti, - true, - lcid, - ndata, - (char *)buf+sizeof(NR_MAC_SUBHEADER_LONG)); - LOG_D(NR_MAC, - "%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %ld)\n", - frame, - slot, - rnti, - len, - lcid < 4 ? "DCCH" : "DTCH", - lcid, - ndata, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - - if (len == 0) - break; - - T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(len * 8), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); header->R = 0; header->F = 1; header->LCID = lcid; - header->L = htons(len); - buf += len+sizeof(NR_MAC_SUBHEADER_LONG); - dlsch_total_bytes += len; - lcid_bytes += len; - sdus += 1; + header->L = htons(pdu_siz[j]); + buf += pdu_siz[j] + sizeof(NR_MAC_SUBHEADER_LONG); + dlsch_total_bytes += pdu_siz[j]; + lcid_bytes += pdu_siz[j]; } + T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(lcid_bytes), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); UE->mac_stats.dl.lc_bytes[lcid] += lcid_bytes; } } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index f23dfe8b30..08b8f6edc0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -104,7 +104,7 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); // select beam for PDSCH in current slot based on SSB beam - if ((ssb_start_symbol / NR_NUMBER_OF_SYMBOLS_PER_SLOT) == (slot % mac->frame_structure.numb_slots_period)) { + if ((ssb_start_symbol / NR_SYMBOLS_PER_SLOT) == (slot % mac->frame_structure.numb_slots_period)) { ssb_idx_beam = i_ssb; break; } @@ -144,11 +144,11 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) sched_ctrl->num_total_bytes = 0; DevAssert(seq_arr_size(&sched_ctrl->lc_config) == 1); const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, 0); - const int lcid = c->lcid; + const logical_chan_id_t lcid = c->lcid; const uint16_t rnti = UE->rnti; /* update sched_ctrl->num_total_bytes so that postprocessor schedules data, * if available */ - sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); + nr_mac_rlc_status_ind(rnti, frame, 1, &lcid, &sched_ctrl->rlc_status[lcid]); sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; int CCEIndex = get_cce_index(mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 1afa2d1502..4c7cf1acf1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -479,7 +479,7 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n"); uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE]; uint16_t num = 1 << srs_pdu->num_symbols; // 0,1,2 means 1,2,4 symbols, see 222.10.04 table 3-105 - const uint8_t l0 = NR_NUMBER_OF_SYMBOLS_PER_SLOT - 1 - srs_pdu->time_start_position; + const uint8_t l0 = NR_SYMBOLS_PER_SLOT - 1 - srs_pdu->time_start_position; uint16_t mask = SL_to_bitmap(l0, num); DevAssert(mask != 0); for (int i = 0; i < srs_pdu->bwp_size; ++i) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 481c0ea9f8..0998eb463b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -37,6 +37,7 @@ #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" //#define SRS_IND_DEBUG +#define MAX_NUM_DATA_IND 1024 /* \brief Get the number of UL TDAs that could be used in slot, reachable * via specific k2. The output parameter first_idx is a pointer to the first @@ -395,6 +396,8 @@ static int nr_process_mac_pdu(instance_t module_idP, log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n"); #endif + nr_rlc_data_ind_t data_ind[MAX_NUM_DATA_IND] = {0}; + int num_data_ind = 0; while (pdu_len > 0) { uint16_t mac_len = 0; uint8_t lcid = 0; @@ -416,7 +419,7 @@ static int nr_process_mac_pdu(instance_t module_idP, for (int i = 0; i < print_len; i++) printf("%02x ", pduP[i]); printf("\n"); - return 0; + break; } LOG_D(NR_MAC, @@ -456,7 +459,9 @@ static int nr_process_mac_pdu(instance_t module_idP, } if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) { - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, 0, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = 0, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); } else { LOG_E(NR_MAC, "prepare_initial_ul_rrc_message() returned false, cannot forward CCCH message\n"); } @@ -475,7 +480,9 @@ static int nr_process_mac_pdu(instance_t module_idP, if (!srbc || srbc->suspended) { LOG_I(NR_MAC, "RNTI %04x LCID %d: ignoring %d bytes\n", UE->rnti, lcid, mac_len); } else { - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); UE->mac_stats.ul.total_sdu_bytes += mac_len; UE->mac_stats.ul.lc_bytes[lcid] += mac_len; @@ -499,7 +506,9 @@ static int nr_process_mac_pdu(instance_t module_idP, } else { UE->mac_stats.ul.lc_bytes[lcid] += mac_len; - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); sdus += 1; /* Updated estimated buffer when receiving data */ @@ -530,7 +539,7 @@ static int nr_process_mac_pdu(instance_t module_idP, case UL_SCH_LCID_SINGLE_ENTRY_PHR: if (harq_pid < 0) { LOG_E(NR_MAC, "Invalid HARQ PID %d\n", harq_pid); - return 0; + continue; } NR_sched_pusch_t *sched_pusch = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; @@ -605,14 +614,18 @@ static int nr_process_mac_pdu(instance_t module_idP, case UL_SCH_LCID_PADDING: // End of MAC PDU, can ignore the rest. - return 0; + // 38.321 Sec 6.1.5: "Presence and length of padding is implicit based + // on TB size, size of MAC subPDU(s)." + mac_len = pdu_len - mac_subheader_len; // will make pdu_len go to 0 + break; default: LOG_E(NR_MAC, "RNTI %0x [%d.%d], received unknown MAC header (LCID = 0x%02x)\n", UE->rnti, frameP, slot, lcid); - return -1; + mac_len = pdu_len - mac_subheader_len; // will make pdu_len go to 0 break; } + #ifdef ENABLE_MAC_PAYLOAD_DEBUG if (lcid < 45 || lcid == 52 || lcid == 63) { LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, lcid); @@ -629,6 +642,8 @@ static int nr_process_mac_pdu(instance_t module_idP, pdu_len -= (mac_subheader_len + mac_len); } + nr_mac_rlc_data_ind(module_idP, UE->rnti, true, data_ind, num_data_ind); + UE->mac_stats.ul.num_mac_sdu += sdus; return 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 054703c2e2..4e2fcdd44e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1145,7 +1145,7 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; // make TDA for the mixed slot - long mixed_sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); + long mixed_sliv = get_SLIV(NR_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); int mixed_min_ul_symb = 3; // need at least two symbols PUSCH + PUCCH bool has_ul_mixed = ul_symb >= mixed_min_ul_symb; if (has_ul_mixed && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) { @@ -1207,10 +1207,16 @@ static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedbac long *delay[8]; for (int i = 0; i < 8; i++) { int curr_delay = i + min_feedback_time; + // dl-DataToUL-ACK SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) + if (curr_delay > 15) + break; delay[i] = calloc(1,sizeof(*delay[i])); *delay[i] = curr_delay; asn1cSeqAdd(&pucch_Config->dl_DataToUL_ACK->list,delay[i]); } + AssertFatal(pucch_Config->dl_DataToUL_ACK->list.count > 0, + "Minimum feedback time too high %d, cannot set any dl_DataToUL_ACK value\n", + min_feedback_time); } // PUCCH resource set 0 for configuration with O_uci <= 2 bits and/or a positive or negative SR (section 9.2.1 of 38.213) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 133aea8d15..9789e85a84 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -163,12 +163,12 @@ void nr_rlc_release_entity(int ue_id, logical_chan_id_t channel_id) void nr_mac_rlc_data_ind(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP) + const nr_rlc_data_ind_t *data, + int num_data) { if (gnb_flagP) - T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(ue_id), T_INT(channel_idP), T_INT(tb_sizeP)); + for (int i = 0; i < num_data; ++i) + T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(ue_id), T_INT(data[i].ch), T_INT(data[i].len)); nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); @@ -176,20 +176,65 @@ void nr_mac_rlc_data_ind(const module_id_t module_idP, if(ue == NULL) LOG_I(RLC, "RLC instance for the given UE was not found \n"); - nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); - - if (rb != NULL) { - LOG_D(RLC, "RB found! (channel ID %d) \n", channel_idP); - rb->set_time(rb, get_nr_rlc_current_time()); - rb->recv_pdu(rb, buffer_pP, tb_sizeP); - } else { - LOG_E(RLC, "Fatal: no RB found (channel ID %d UE ID %d)\n", channel_idP, ue_id); - // exit(1); + for (int i = 0; i < num_data; ++i) { + logical_chan_id_t ch = data[i].ch; + nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, ch); + if (rb != NULL) { + LOG_D(RLC, "RB found! (channel ID %d) \n", ch); + rb->set_time(rb, get_nr_rlc_current_time()); + rb->recv_pdu(rb, (char *)data[i].buf, data[i].len); + } else { + LOG_W(RLC, "no RB found (channel ID %d UE ID %d)\n", ch, ue_id); + } } nr_rlc_manager_unlock(nr_rlc_ue_manager); } +int nr_mac_rlc_multi_data_req(const module_id_t module_idP, + const uint16_t ue_id, + const bool gnb_flagP, + const logical_chan_id_t channel_idP, + tb_size_t tb_sizeP, + char *buffer_pP, + tb_size_t *pdu_siz, + int pdu_siz_len) +{ + int ret = 0; + + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); + + if (rb != NULL) { + rb->set_time(rb, get_nr_rlc_current_time()); + while (tb_sizeP - 3 > 0 && pdu_siz_len > 0) { + // fill PDU in buffer, store size of PDU + pdu_siz[0] = rb->generate_pdu(rb, buffer_pP + 3, tb_sizeP - 3); + if (pdu_siz[0] == 0) + break; + LOG_D(RLC, "MAC PDU created: channel_idP %d len %d\n", channel_idP, pdu_siz[0]); + // reserve header + tb_sizeP -= 3 + pdu_siz[0]; + buffer_pP += 3 + pdu_siz[0]; + pdu_siz++; + pdu_siz_len--; + ret++; + } + } else { + LOG_D(RLC, "MAC PDU failed to get created for channel_idP:%d \n", channel_idP); + ret = 0; + } + + nr_rlc_manager_unlock(nr_rlc_ue_manager); + + if (gnb_flagP) + T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(ue_id), + T_INT(channel_idP), T_INT(ret)); + + return ret; +} + tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, @@ -223,12 +268,10 @@ tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, return ret; } -mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t frame, const logical_chan_id_t channel_idP) +static mac_rlc_status_resp_t _nr_rlc_status_ind(nr_rlc_ue_t *ue, frame_t frame, logical_chan_id_t channel_idP) { mac_rlc_status_resp_t ret; - nr_rlc_manager_lock(nr_rlc_ue_manager); - nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); if (rb != NULL) { @@ -243,12 +286,10 @@ mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; } else { if (!(frame % 128) || channel_idP == 0) //to suppress this warning message - LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue_id); + LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue->ue_id); ret.bytes_in_buffer = 0; } - nr_rlc_manager_unlock(nr_rlc_ue_manager); - ret.pdus_in_buffer = 0; /* TODO: creation time may be important (unit: frame, as it seems) */ ret.head_sdu_creation_time = 0; @@ -257,6 +298,16 @@ mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t return ret; } +void nr_mac_rlc_status_ind(uint16_t ue_id, frame_t frame, int n_ch, const logical_chan_id_t *ch, mac_rlc_status_resp_t *ret) +{ + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + for (int i = 0; i < n_ch; ++i) { + ret[i] = _nr_rlc_status_ind(ue, frame, ch[i]); + } + nr_rlc_manager_unlock(nr_rlc_ue_manager); +} + rlc_op_status_t nr_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, @@ -1022,7 +1073,7 @@ bool nr_rlc_get_statistics(int ue_id, int srb_flag, int rb_id, nr_rlc_statistics // Patch buffer status using OAI results (no need to change anything in the RB) // rb->set_time(rb, get_nr_rlc_current_time()); - nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 1000*1000); + nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 256 * 1000); out->rxbuf_occ_bytes = oai_stat.status_size; out->txbuf_occ_bytes = oai_stat.tx_size + oai_stat.retx_size; } else { diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index 454a59b928..cf5d088834 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -41,12 +41,32 @@ struct NR_RLC_Config; struct NR_LogicalChannelConfig; int nr_rlc_module_init(nr_rlc_op_mode_t mode); +typedef struct nr_rlc_data_ind { + logical_chan_id_t ch; + uint8_t *buf; + tb_size_t len; +} nr_rlc_data_ind_t; void nr_mac_rlc_data_ind(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP); + const nr_rlc_data_ind_t *data, + int num_data); +/* \brief Fill up to pdu_siz_len RLC PDUs into buffer pointed to by buffer_pP, + * or until tb_sizeP is reached. Each PDU is preceded by 3 bytes (nothing is + * written) that have to be filled by the consumer (with a MAC sub-PDU + * subheader). This function fills up to an entire TB in a single call, unlike + * nr_mac_rlc_data_req() that fills only one RLC PDU in one step. */ +int nr_mac_rlc_multi_data_req(const module_id_t module_idP, + const uint16_t ue_id, + const bool gnb_flagP, + const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP, + char *buffer_pP, + tb_size_t *pdu_siz, + int pdu_siz_len); +/* \brief Fill one RLC PDU into buffer pointed to by buffer_pP, or until + * tb_sizeP is reached. Note that NO header is prepended (for a MAC sub-PDU + * subheader), and the user of the API has to fill the necessary data. */ tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, @@ -59,7 +79,7 @@ rlc_op_status_t nr_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, const mui_t muiP, sdu_size_t sdu_sizeP, uint8_t *sdu_pP); -mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t frame, const logical_chan_id_t channel_idP); +void nr_mac_rlc_status_ind(uint16_t ue_id, frame_t frame, int n_ch, const logical_chan_id_t *ch, mac_rlc_status_resp_t *ret); void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); diff --git a/openair2/RRC/NR_UE/verify_RRC.c b/openair2/RRC/NR_UE/verify_RRC.c index b33da53dae..83a325d255 100644 --- a/openair2/RRC/NR_UE/verify_RRC.c +++ b/openair2/RRC/NR_UE/verify_RRC.c @@ -252,9 +252,9 @@ static bool check_srs_config(NR_SRS_Config_t *srs_Config) if (srs_Config->srs_ResourceToAddModList) { for (int i = 0; i < srs_Config->srs_ResourceToAddModList->list.count; i++) { NR_SRS_Resource_t *res = srs_Config->srs_ResourceToAddModList->list.array[i]; - int start = NR_NUMBER_OF_SYMBOLS_PER_SLOT - res->resourceMapping.startPosition - 1; + int start = NR_SYMBOLS_PER_SLOT - res->resourceMapping.startPosition - 1; int num = 1 << res->resourceMapping.nrofSymbols; - if (start + num > NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (start + num > NR_SYMBOLS_PER_SLOT) { LOG_E(NR_RRC, "The configured SRS resource exceeds the slot boundary\n"); return false; } diff --git a/openair2/XNAP/CMakeLists.txt b/openair2/XNAP/CMakeLists.txt index d003732d8a..10576f8403 100644 --- a/openair2/XNAP/CMakeLists.txt +++ b/openair2/XNAP/CMakeLists.txt @@ -1,7 +1,9 @@ +add_subdirectory(lib) add_subdirectory(MESSAGES) -add_library(xnap xnap_common.c) -target_link_libraries(xnap - PUBLIC asn1_xnap - PRIVATE nr_rrc) -target_include_directories(xnap PUBLIC ${CMAKE_CURRENT_DIR}) + +if(ENABLE_TESTS) + add_subdirectory(tests) +endif() + + diff --git a/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake b/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake index cb0c762983..4a46649449 100644 --- a/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake +++ b/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake @@ -1,4 +1,4 @@ -set( XNAP_GRAMMAR ASN1/xnap_R16.2.0.asn) +set(XNAP_GRAMMAR ASN1/xnap_R16.2.0.asn) set(xnap_source ANY.c @@ -9,6 +9,7 @@ set(xnap_source asn_application.c asn_bit_data.c asn_codecs_prim.c + asn_codecs_prim_xer.c asn_internal.c asn_random_fill.c asn_SEQUENCE_OF.c @@ -16,20 +17,73 @@ set(xnap_source ber_tlv_length.c ber_tlv_tag.c BIT_STRING.c + BIT_STRING_print.c + BIT_STRING_rfill.c + BIT_STRING_uper.c + BIT_STRING_xer.c constraints.c constr_CHOICE.c + constr_CHOICE_aper.c + constr_CHOICE_rfill.c + constr_CHOICE_print.c + constr_CHOICE_uper.c + constr_CHOICE_xer.c constr_SEQUENCE.c + constr_SEQUENCE_aper.c constr_SEQUENCE_OF.c + constr_SEQUENCE_OF_aper.c + constr_SEQUENCE_OF_uper.c + constr_SEQUENCE_OF_xer.c + constr_SEQUENCE_print.c + constr_SEQUENCE_rfill.c + constr_SEQUENCE_uper.c + constr_SEQUENCE_xer.c constr_SET_OF.c + constr_SET_OF_aper.c + constr_SET_OF_print.c + constr_SET_OF_rfill.c + constr_SET_OF_uper.c + constr_SET_OF_xer.c constr_TYPE.c INTEGER.c + INTEGER_aper.c + INTEGER_print.c + INTEGER_rfill.c + INTEGER_uper.c + INTEGER_xer.c Makefile.am.libasncodec NativeEnumerated.c + NativeEnumerated_aper.c + NativeEnumerated_uper.c + NativeEnumerated_xer.c NativeInteger.c + NativeInteger_aper.c + NativeInteger_print.c + NativeInteger_rfill.c + NativeInteger_uper.c + NativeInteger_xer.c NULL.c + NULL_aper.c + NULL_print.c + NULL_rfill.c + NULL_uper.c + NULL_xer.c OBJECT_IDENTIFIER.c + OBJECT_IDENTIFIER_print.c + OBJECT_IDENTIFIER_rfill.c + OBJECT_IDENTIFIER_xer.c OCTET_STRING.c + OCTET_STRING_aper.c + OCTET_STRING_print.c + OCTET_STRING_rfill.c + OCTET_STRING_uper.c + OCTET_STRING_xer.c OPEN_TYPE.c + OPEN_TYPE_aper.c + OPEN_TYPE_uper.c + OPEN_TYPE_xer.c + per_opentype.c + per_encoder.c VisibleString.c xer_decoder.c xer_encoder.c @@ -819,14 +873,22 @@ set(xnap_source XNAP_XnUAddressIndication.c XNAP_XnUAddressInfoperPDUSession-Item.c XNAP_XnUAddressInfoperPDUSession-List.c + uper_encoder.c + uper_opentype.c + uper_support.c ) set(xnap_headers ANY.h + aper_decoder.h + aper_encoder.h + aper_opentype.h + aper_support.h asn_application.h asn_bit_data.h asn_codecs.h asn_codecs_prim.h + asn_codecs_prim_xer.h asn_internal.h asn_ioc.h asn_random_fill.h @@ -836,23 +898,72 @@ set(xnap_headers ber_tlv_length.h ber_tlv_tag.h BIT_STRING.h + BIT_STRING_print.h + BIT_STRING_rfill.h + BIT_STRING_uper.h + BIT_STRING_xer.h constraints.h constr_CHOICE.h + constr_CHOICE_aper.h + constr_CHOICE_print.h + constr_CHOICE_rfill.h + constr_CHOICE_uper.h + constr_CHOICE_xer.h constr_SEQUENCE.h + constr_SEQUENCE_aper.h constr_SEQUENCE_OF.h + constr_SEQUENCE_OF_aper.h + constr_SEQUENCE_OF_uper.h + constr_SEQUENCE_OF_xer.h + constr_SEQUENCE_print.h + constr_SEQUENCE_rfill.h + constr_SEQUENCE_uper.h + constr_SEQUENCE_xer.h constr_SET_OF.h + constr_SET_OF_aper.h + constr_SET_OF_print.h + constr_SET_OF_rfill.h + constr_SET_OF_uper.h + constr_SET_OF_xer.h constr_TYPE.h INTEGER.h + INTEGER_aper.h + INTEGER_print.h + INTEGER_rfill.h + INTEGER_uper.h + INTEGER_xer.h NativeEnumerated.h + NativeEnumerated_aper.h + NativeEnumerated_uper.h + NativeEnumerated_xer.h NativeInteger.h + NativeInteger_aper.h + NativeInteger_print.h + NativeInteger_rfill.h + NativeInteger_xer.h + NativeInteger_uper.h NULL.h + NULL_aper.h + NULL_print.h + NULL_rfill.h + NULL_uper.h + NULL_xer.h OBJECT_IDENTIFIER.h + OBJECT_IDENTIFIER_print.h + OBJECT_IDENTIFIER_rfill.h + OBJECT_IDENTIFIER_xer.h OCTET_STRING.h + OCTET_STRING_aper.h + OCTET_STRING_print.h + OCTET_STRING_rfill.h + OCTET_STRING_uper.h + OCTET_STRING_xer.h OPEN_TYPE.h - aper_decoder.h - aper_encoder.h - aper_opentype.h - aper_support.h + OPEN_TYPE_aper.h + OPEN_TYPE_uper.h + OPEN_TYPE_xer.h + per_encoder.h + per_opentype.h VisibleString.h xer_decoder.h xer_encoder.h @@ -1643,5 +1754,8 @@ set(xnap_headers XNAP_XnUAddressIndication.h XNAP_XnUAddressInfoperPDUSession-Item.h XNAP_XnUAddressInfoperPDUSession-List.h + uper_encoder.h + uper_opentype.h + uper_support.h ) diff --git a/openair2/XNAP/lib/CMakeLists.txt b/openair2/XNAP/lib/CMakeLists.txt new file mode 100644 index 0000000000..5e4d5124b0 --- /dev/null +++ b/openair2/XNAP/lib/CMakeLists.txt @@ -0,0 +1,10 @@ +add_library(xnap_lib OBJECT + xnap_lib_common.c + xnap_gNB_interface_management.c +) +target_link_libraries(xnap_lib PRIVATE asn1_xnap ds) + +if(ENABLE_TESTS) + target_compile_definitions(xnap_lib PRIVATE ENABLE_TESTS) +endif() + diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.c b/openair2/XNAP/lib/xnap_gNB_interface_management.c new file mode 100644 index 0000000000..f77543504d --- /dev/null +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.c @@ -0,0 +1,471 @@ +/* + * 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 + */ + +/* + * \brief xnap interface handler procedures for gNB + */ + +#include "xnap_gNB_interface_management.h" +#include "xnap_lib_common.h" +#include "xnap_lib_includes.h" + +/** + * @brief XnAP Setup Request encoding + */ +XNAP_XnAP_PDU_t *encode_xn_setup_request(const xnap_setup_req_t *msg) +{ + XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* PDU type */ + pdu->present = XNAP_XnAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup; + initMsg->criticality = XNAP_Criticality_reject; + initMsg->value.present = XNAP_InitiatingMessage__value_PR_XnSetupRequest; + + XNAP_XnSetupRequest_t *out = &initMsg->value.choice.XnSetupRequest; + + /* Global NG-RAN Node ID (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC1); + ieC1->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID; + ieC1->criticality = XNAP_Criticality_reject; + ieC1->value.present = XNAP_XnSetupRequest_IEs__value_PR_GlobalNG_RANNode_ID; + + XNAP_GlobalNG_RANNode_ID_t *global = &ieC1->value.choice.GlobalNG_RANNode_ID; + global->present = XNAP_GlobalNG_RANNode_ID_PR_gNB; + asn1cCalloc(global->choice.gNB, gnb); + + MCC_MNC_TO_PLMNID(msg->plmn.mcc, msg->plmn.mnc, msg->plmn.mnc_digit_length, &gnb->plmn_id); + gnb->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID; + MACRO_GNB_ID_TO_BIT_STRING(msg->gNB_id, &gnb->gnb_id.choice.gnb_ID); + + /* TAI Support List (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC2); + ieC2->id = XNAP_ProtocolIE_ID_id_TAISupport_list; + ieC2->criticality = XNAP_Criticality_reject; + ieC2->value.present = XNAP_XnSetupRequest_IEs__value_PR_TAISupport_List; + + for (int i = 0; i < msg->num_tai; i++) { + asn1cSequenceAdd(ieC2->value.choice.TAISupport_List.list, XNAP_TAISupport_Item_t, taiItem); + INT24_TO_OCTET_STRING(msg->tai_support[i].tac, &taiItem->tac); + + for (int j = 0; j < msg->tai_support[i].num_plmn; j++) { + const xnap_plmn_support_t *plmn = &msg->tai_support[i].plmn_support[j]; + asn1cSequenceAdd(taiItem->broadcastPLMNs.list, XNAP_BroadcastPLMNinTAISupport_Item_t, plmnItem); + MCC_MNC_TO_PLMNID(plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length, &plmnItem->plmn_id); + + for (int k = 0; k < plmn->num_nssai; k++) { + asn1cSequenceAdd(plmnItem->tAISliceSupport_List.list, XNAP_S_NSSAI_t, nssai); + INT8_TO_OCTET_STRING(plmn->nssai[k].sst, &nssai->sst); + if (plmn->nssai[k].sd) { asn1cCalloc(nssai->sd, sd); INT24_TO_OCTET_STRING(plmn->nssai[k].sd, sd); } + } + } + } + + /* AMF Region Information (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC3); + ieC3->id = XNAP_ProtocolIE_ID_id_AMF_Region_Information; + ieC3->criticality = XNAP_Criticality_reject; + ieC3->value.present = XNAP_XnSetupRequest_IEs__value_PR_AMF_Region_Information; + + for (int i = 0; i < msg->num_amf_regions; i++) { + const xnap_amf_region_info_t *amf = &msg->amf_region_info[i]; + asn1cSequenceAdd(ieC3->value.choice.AMF_Region_Information.list, XNAP_GlobalAMF_Region_Information_t, amfItem); + MCC_MNC_TO_PLMNID(amf->plmn.mcc, amf->plmn.mnc, amf->plmn.mnc_digit_length, &amfItem->plmn_ID); + INT8_TO_OCTET_STRING(amf->amf_region_id, &amfItem->amf_region_id); + } + + return pdu; +} + +/** + * @brief XnAP Setup Request decoding + */ +bool decode_xn_setup_request(xnap_setup_req_t *out, const XNAP_XnAP_PDU_t *pdu) +{ + /* Check presence of message type */ + _EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_initiatingMessage); + AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL"); + _EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, XNAP_ProcedureCode_id_xnSetup); + _EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, XNAP_InitiatingMessage__value_PR_XnSetupRequest); + /* XnSetupRequest container */ + XNAP_XnSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.XnSetupRequest; + + XNAP_XnSetupRequest_IEs_t *ie; + /* Check presence of mandatory IEs */ + XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true); + XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_TAISupport_list, true); + XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_AMF_Region_Information, true); + + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID: { + /* Global NG-RAN Node ID (M) */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_GlobalNG_RANNode_ID); + XNAP_GlobalNG_RANNode_ID_t *global_id = &ie->value.choice.GlobalNG_RANNode_ID; + AssertError(global_id->present == XNAP_GlobalNG_RANNode_ID_PR_gNB, return false, "Only gNB supported"); + AssertError(global_id->choice.gNB != NULL, return false, "gNB is NULL"); + /* Decode PLMN */ + PLMNID_TO_MCC_MNC(&global_id->choice.gNB->plmn_id, + out->plmn.mcc, + out->plmn.mnc, + out->plmn.mnc_digit_length); + /* Decode gNB ID */ + AssertError(global_id->choice.gNB->gnb_id.present == XNAP_GNB_ID_Choice_PR_gnb_ID, return false, "Unsupported gNB ID choice"); + MACRO_BIT_STRING_TO_GNB_ID(&global_id->choice.gNB->gnb_id.choice.gnb_ID, out->gNB_id); + } break; + + case XNAP_ProtocolIE_ID_id_TAISupport_list: { + /* TAI Support List (M) */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_TAISupport_List); + int tai_count = ie->value.choice.TAISupport_List.list.count; + out->num_tai = tai_count; + out->tai_support = calloc_or_fail(tai_count, sizeof(*out->tai_support)); + for (int m = 0; m < tai_count; m++) { + XNAP_TAISupport_Item_t *tai_item = ie->value.choice.TAISupport_List.list.array[m]; + /* TAC */ + OCTET_STRING_TO_INT24(&tai_item->tac, out->tai_support[m].tac); + /* PLMN list */ + out->tai_support[m].num_plmn = tai_item->broadcastPLMNs.list.count; + out->tai_support[m].plmn_support = calloc_or_fail(out->tai_support[m].num_plmn, sizeof(*out->tai_support[m].plmn_support)); + for (int j = 0; j < out->tai_support[m].num_plmn; j++) { + XNAP_BroadcastPLMNinTAISupport_Item_t *plmn_item = tai_item->broadcastPLMNs.list.array[j]; + xnap_plmn_support_t *plmn = &out->tai_support[m].plmn_support[j]; + PLMNID_TO_MCC_MNC(&plmn_item->plmn_id, + plmn->plmn.mcc, + plmn->plmn.mnc, + plmn->plmn.mnc_digit_length); + /* NSSAI */ + plmn->num_nssai = plmn_item->tAISliceSupport_List.list.count; + plmn->nssai = calloc_or_fail(plmn->num_nssai, sizeof(*plmn->nssai)); + for (int k = 0; k < plmn->num_nssai; k++) { + OCTET_STRING_TO_INT8(&plmn_item->tAISliceSupport_List.list.array[k]->sst, plmn->nssai[k].sst); + if (plmn_item->tAISliceSupport_List.list.array[k]->sd) { + OCTET_STRING_TO_INT24(plmn_item->tAISliceSupport_List.list.array[k]->sd, plmn->nssai[k].sd); + } + } + } + } + } break; + + case XNAP_ProtocolIE_ID_id_AMF_Region_Information: { + /* AMF Region Information (M) */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_AMF_Region_Information); + out->num_amf_regions = ie->value.choice.AMF_Region_Information.list.count; + out->amf_region_info = calloc_or_fail(out->num_amf_regions, sizeof(*out->amf_region_info)); + for (int a = 0; a < out->num_amf_regions; a++) { + XNAP_GlobalAMF_Region_Information_t *amf = ie->value.choice.AMF_Region_Information.list.array[a]; + PLMNID_TO_MCC_MNC(&amf->plmn_ID, + out->amf_region_info[a].plmn.mcc, + out->amf_region_info[a].plmn.mnc, + out->amf_region_info[a].plmn.mnc_digit_length); + OCTET_STRING_TO_INT8(&amf->amf_region_id, out->amf_region_info[a].amf_region_id); + } + } break; + + default: + AssertError(0, return false, "Unknown XnAP IE id %ld\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief XnAP Setup Request main equality check + */ +bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b) +{ + _EQ_CHECK_UINT32(a->gNB_id, b->gNB_id); + if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false; + + _EQ_CHECK_INT(a->num_tai, b->num_tai); + for (int i = 0; i < a->num_tai; i++) { + if (!eq_xnap_tai_support(&a->tai_support[i], &b->tai_support[i])) + return false; + } + + _EQ_CHECK_INT(a->num_amf_regions, b->num_amf_regions); + for (int i = 0; i < a->num_amf_regions; i++) { + if (!eq_xnap_plmn(&a->amf_region_info[i].plmn, &b->amf_region_info[i].plmn)) + return false; + _EQ_CHECK_INT(a->amf_region_info[i].amf_region_id, b->amf_region_info[i].amf_region_id); + } + + return true; +} + +static void free_xnap_plmn_support(xnap_plmn_support_t *plmn_support, uint8_t num_plmn) +{ + if (!plmn_support) return; + for (int i = 0; i < num_plmn; i++) { + free(plmn_support[i].nssai); + } + free(plmn_support); +} + +static void free_xnap_tai_support(xnap_tai_support_t *tai_support, uint16_t num_tai) +{ + if (!tai_support) return; + for (int i = 0; i < num_tai; i++) { + free_xnap_plmn_support(tai_support[i].plmn_support, + tai_support[i].num_plmn); + } + free(tai_support); +} + +/** + * @brief XnAP Setup Request memory management + */ +void free_xnap_setup_request(const xnap_setup_req_t *msg) +{ + DevAssert(msg != NULL); + free_xnap_tai_support(msg->tai_support, msg->num_tai); + free(msg->amf_region_info); +} + +/** + * @brief XnAP Setup Response encoding + */ +XNAP_XnAP_PDU_t *encode_xn_setup_response(const xnap_setup_resp_t *resp) +{ + XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* PDU type */ + pdu->present = XNAP_XnAP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, succMsg); + succMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup; + succMsg->criticality = XNAP_Criticality_reject; + succMsg->value.present = XNAP_SuccessfulOutcome__value_PR_XnSetupResponse; + + XNAP_XnSetupResponse_t *out = &succMsg->value.choice.XnSetupResponse; + + /* Global NG-RAN Node ID (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupResponse_IEs_t, ie1); + ie1->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID; + ie1->criticality = XNAP_Criticality_reject; + ie1->value.present = XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID; + + XNAP_GlobalNG_RANNode_ID_t *global = &ie1->value.choice.GlobalNG_RANNode_ID; + global->present = XNAP_GlobalNG_RANNode_ID_PR_gNB; + asn1cCalloc(global->choice.gNB, gnb); + + MCC_MNC_TO_PLMNID(resp->plmn.mcc, resp->plmn.mnc, resp->plmn.mnc_digit_length, &gnb->plmn_id); + gnb->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID; + MACRO_GNB_ID_TO_BIT_STRING(resp->gNB_id, &gnb->gnb_id.choice.gnb_ID); + + /* TAI Support List (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupResponse_IEs_t, ie2); + ie2->id = XNAP_ProtocolIE_ID_id_TAISupport_list; + ie2->criticality = XNAP_Criticality_reject; + ie2->value.present = XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List; + + for (int i = 0; i < resp->num_tai; i++) { + asn1cSequenceAdd(ie2->value.choice.TAISupport_List.list, XNAP_TAISupport_Item_t, taiItem); + INT24_TO_OCTET_STRING(resp->tai_support[i].tac, &taiItem->tac); + + for (int j = 0; j < resp->tai_support[i].num_plmn; j++) { + const xnap_plmn_support_t *plmn = &resp->tai_support[i].plmn_support[j]; + asn1cSequenceAdd(taiItem->broadcastPLMNs.list, XNAP_BroadcastPLMNinTAISupport_Item_t, plmnItem); + MCC_MNC_TO_PLMNID(plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length, &plmnItem->plmn_id); + + for (int k = 0; k < plmn->num_nssai; k++) { + asn1cSequenceAdd(plmnItem->tAISliceSupport_List.list, XNAP_S_NSSAI_t, nssai); + INT8_TO_OCTET_STRING(plmn->nssai[k].sst, &nssai->sst); + if (plmn->nssai[k].sd) { asn1cCalloc(nssai->sd, sd); INT24_TO_OCTET_STRING(plmn->nssai[k].sd, sd); } + } + } + } + + return pdu; +} + +/** + * @brief XnAP Setup Response decoding + */ +bool decode_xn_setup_response(xnap_setup_resp_t *out, const XNAP_XnAP_PDU_t *pdu) +{ + /* Check presence of message type */ + _EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_successfulOutcome); + AssertError(pdu->choice.successfulOutcome != NULL, return false, "successfulOutcome is NULL"); + _EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, XNAP_ProcedureCode_id_xnSetup); + _EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, XNAP_SuccessfulOutcome__value_PR_XnSetupResponse); + + /* XnSetupResponse container */ + XNAP_XnSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.XnSetupResponse; + XNAP_XnSetupResponse_IEs_t *ie; + + /* Check presence of mandatory IEs */ + XNAP_LIB_FIND_IE(XNAP_XnSetupResponse_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true); + XNAP_LIB_FIND_IE(XNAP_XnSetupResponse_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_TAISupport_list, true); + + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + + switch (ie->id) { + + case XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID: { + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID); + XNAP_GlobalNG_RANNode_ID_t *global = &ie->value.choice.GlobalNG_RANNode_ID; + AssertError(global->present == XNAP_GlobalNG_RANNode_ID_PR_gNB, return false, "Only gNB supported"); + AssertError(global->choice.gNB != NULL, return false, "gNB is NULL"); + + PLMNID_TO_MCC_MNC(&global->choice.gNB->plmn_id, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + AssertError(global->choice.gNB->gnb_id.present == XNAP_GNB_ID_Choice_PR_gnb_ID, return false, "Unsupported gNB ID"); + MACRO_BIT_STRING_TO_GNB_ID(&global->choice.gNB->gnb_id.choice.gnb_ID, out->gNB_id); + } break; + + case XNAP_ProtocolIE_ID_id_TAISupport_list: { + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List); + out->num_tai = ie->value.choice.TAISupport_List.list.count; + out->tai_support = calloc_or_fail(out->num_tai, sizeof(*out->tai_support)); + + for (int m = 0; m < out->num_tai; m++) { + XNAP_TAISupport_Item_t *tai = ie->value.choice.TAISupport_List.list.array[m]; + OCTET_STRING_TO_INT24(&tai->tac, out->tai_support[m].tac); + + out->tai_support[m].num_plmn = tai->broadcastPLMNs.list.count; + out->tai_support[m].plmn_support = calloc_or_fail(out->tai_support[m].num_plmn, sizeof(*out->tai_support[m].plmn_support)); + + for (int j = 0; j < out->tai_support[m].num_plmn; j++) { + XNAP_BroadcastPLMNinTAISupport_Item_t *plmn_item = tai->broadcastPLMNs.list.array[j]; + xnap_plmn_support_t *plmn = &out->tai_support[m].plmn_support[j]; + + PLMNID_TO_MCC_MNC(&plmn_item->plmn_id, plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length); + + plmn->num_nssai = plmn_item->tAISliceSupport_List.list.count; + plmn->nssai = calloc_or_fail(plmn->num_nssai, sizeof(*plmn->nssai)); + + for (int k = 0; k < plmn->num_nssai; k++) { + OCTET_STRING_TO_INT8(&plmn_item->tAISliceSupport_List.list.array[k]->sst, plmn->nssai[k].sst); + if (plmn_item->tAISliceSupport_List.list.array[k]->sd) { + OCTET_STRING_TO_INT24(plmn_item->tAISliceSupport_List.list.array[k]->sd, plmn->nssai[k].sd); + } + } + } + } + } break; + + default: + AssertError(0, return false, "Unknown XnAP IE id %ld\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief XnAP Setup Response main equality check + */ +bool eq_xnap_setup_response(const xnap_setup_resp_t *a, const xnap_setup_resp_t *b) +{ + _EQ_CHECK_UINT32(a->gNB_id, b->gNB_id); + if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false; + + _EQ_CHECK_INT(a->num_tai, b->num_tai); + for (int i = 0; i < a->num_tai; i++) { + if (!eq_xnap_tai_support(&a->tai_support[i], &b->tai_support[i])) + return false; + } + + return true; +} + +/** + * @brief XnAP Setup Response memory management + */ +void free_xnap_setup_response(const xnap_setup_resp_t *msg) +{ + DevAssert(msg != NULL); + free_xnap_tai_support(msg->tai_support, msg->num_tai); +} + +/** + * @brief XnAP Setup Failure encoding + */ +XNAP_XnAP_PDU_t *encode_xn_setup_failure(const xnap_setup_failure_t *fail) +{ + XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message type */ + pdu->present = XNAP_XnAP_PDU_PR_unsuccessfulOutcome; + asn1cCalloc(pdu->choice.unsuccessfulOutcome, failMsg); + failMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup; + failMsg->criticality = XNAP_Criticality_reject; + failMsg->value.present = XNAP_UnsuccessfulOutcome__value_PR_XnSetupFailure; + + XNAP_XnSetupFailure_t *out = &failMsg->value.choice.XnSetupFailure; + + /* Cause (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupFailure_IEs_t, ie1); + ie1->id = XNAP_ProtocolIE_ID_id_Cause; + ie1->criticality = XNAP_Criticality_ignore; + ie1->value.present = XNAP_XnSetupFailure_IEs__value_PR_Cause; + xnap_gNB_set_cause(&ie1->value.choice.Cause, &fail->cause); + + return pdu; +} + +/** + * @brief XnAP Setup Failure decoding + */ +bool decode_xn_setup_failure(xnap_setup_failure_t *out, const XNAP_XnAP_PDU_t *pdu) +{ + /* Check message type */ + _EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_unsuccessfulOutcome); + AssertError(pdu->choice.unsuccessfulOutcome != NULL, return false, "unsuccessfulOutcome is NULL"); + _EQ_CHECK_LONG(pdu->choice.unsuccessfulOutcome->procedureCode, XNAP_ProcedureCode_id_xnSetup); + _EQ_CHECK_INT(pdu->choice.unsuccessfulOutcome->value.present, XNAP_UnsuccessfulOutcome__value_PR_XnSetupFailure); + + /* XnSetupFailure container */ + XNAP_XnSetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.XnSetupFailure; + XNAP_XnSetupFailure_IEs_t *ie; + + /* Check presence of mandatory IE */ + XNAP_LIB_FIND_IE(XNAP_XnSetupFailure_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_Cause, true); + + /* Decode Cause */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupFailure_IEs__value_PR_Cause); + out->cause = decode_xnap_cause(&ie->value.choice.Cause); + + return true; +} + +/** + * @brief XnAP Setup Failure equality check + */ +bool eq_xnap_setup_failure(const xnap_setup_failure_t *a, const xnap_setup_failure_t *b) +{ + return eq_xnap_cause(&a->cause, &b->cause); +} + +/** + * @brief XnAP Setup Failure memory management + */ +void free_xnap_setup_failure(xnap_setup_failure_t *msg) +{ + // nothing to free +} diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.h b/openair2/XNAP/lib/xnap_gNB_interface_management.h new file mode 100644 index 0000000000..f1ffb8811c --- /dev/null +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.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 XNAP_GNB_INTERFACE_MANAGEMENT_H_ +#define XNAP_GNB_INTERFACE_MANAGEMENT_H_ + +#include +#include "xnap_messages_types.h" +typedef struct XNAP_XnAP_PDU XNAP_XnAP_PDU_t; + +XNAP_XnAP_PDU_t *encode_xn_setup_request(const xnap_setup_req_t *req); +XNAP_XnAP_PDU_t *encode_xn_setup_response(const xnap_setup_resp_t *resp); +XNAP_XnAP_PDU_t *encode_xn_setup_failure(const xnap_setup_failure_t *fail); + +bool decode_xn_setup_request(xnap_setup_req_t *req, const XNAP_XnAP_PDU_t *pdu); +bool decode_xn_setup_response(xnap_setup_resp_t *out, const XNAP_XnAP_PDU_t *pdu); +bool decode_xn_setup_failure(xnap_setup_failure_t *out, const XNAP_XnAP_PDU_t *pdu); + +bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b); +bool eq_xnap_setup_response(const xnap_setup_resp_t *a, const xnap_setup_resp_t *b); +bool eq_xnap_setup_failure(const xnap_setup_failure_t *a, const xnap_setup_failure_t *b); + +void free_xnap_setup_request(const xnap_setup_req_t *msg); +void free_xnap_setup_response(const xnap_setup_resp_t *msg); +void free_xnap_setup_failure(xnap_setup_failure_t *msg); + +#endif /* XNAP_GNB_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/XNAP/lib/xnap_lib_common.c b/openair2/XNAP/lib/xnap_lib_common.c new file mode 100644 index 0000000000..0d9b047ea9 --- /dev/null +++ b/openair2/XNAP/lib/xnap_lib_common.c @@ -0,0 +1,127 @@ +/* + * 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 "xnap_lib_common.h" +#include "common/utils/assertions.h" +#include "common/utils/utils.h" + +int xnap_gNB_set_cause(XNAP_Cause_t *cause_p,const xnap_cause_t *in) +{ + DevAssert(cause_p != NULL); + switch (in->type) { + case XNAP_CAUSE_RADIO_NETWORK: + cause_p->present = XNAP_Cause_PR_radioNetwork; + cause_p->choice.radioNetwork = in->value; + break; + case XNAP_CAUSE_TRANSPORT: + cause_p->present = XNAP_Cause_PR_transport; + cause_p->choice.transport = in->value; + break; + case XNAP_CAUSE_PROTOCOL: + cause_p->present = XNAP_Cause_PR_protocol; + cause_p->choice.protocol = in->value; + break; + case XNAP_CAUSE_MISC: + cause_p->present = XNAP_Cause_PR_misc; + cause_p->choice.misc = in->value; + break; + case XNAP_CAUSE_NOTHING: + default: + AssertFatal(false, "unknown cause value %d\n", in->type); + break; + } + return 0; +} + +xnap_cause_t decode_xnap_cause(const XNAP_Cause_t *in) +{ + xnap_cause_t out = {0}; + switch (in->present) { + case XNAP_Cause_PR_radioNetwork: + out.type = XNAP_CAUSE_RADIO_NETWORK; + out.value = in->choice.radioNetwork; + break; + + case XNAP_Cause_PR_transport: + out.type = XNAP_CAUSE_TRANSPORT; + out.value = in->choice.transport; + break; + + case XNAP_Cause_PR_protocol: + out.type = XNAP_CAUSE_PROTOCOL; + out.value = in->choice.protocol; + break; + + case XNAP_Cause_PR_misc: + out.type = XNAP_CAUSE_MISC; + out.value = in->choice.misc; + break; + case XNAP_Cause_PR_NOTHING: + default: + PRINT_ERROR("received illegal XNAP cause %d\n", in->present); + break; + } + return out; +} + +bool eq_xnap_cause(const xnap_cause_t *a, const xnap_cause_t *b) +{ + _EQ_CHECK_INT(a->type, b->type); + _EQ_CHECK_INT(a->value, b->value); + return true; +} + +bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b) +{ + _EQ_CHECK_INT(a->mcc, b->mcc); + _EQ_CHECK_INT(a->mnc, b->mnc); + _EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length); + return true; +} + +bool eq_xnap_snssai(const nssai_t *a, const nssai_t *b) +{ + _EQ_CHECK_INT(a->sst, b->sst); + _EQ_CHECK_UINT32(a->sd, b->sd); + return true; +} + +bool eq_xnap_plmn_support(const xnap_plmn_support_t *a, const xnap_plmn_support_t *b) +{ + if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false; + _EQ_CHECK_INT(a->num_nssai, b->num_nssai); + for (int i = 0; i < a->num_nssai; i++) { + if (!eq_xnap_snssai(&a->nssai[i], &b->nssai[i])) + return false; + } + return true; +} + +bool eq_xnap_tai_support(const xnap_tai_support_t *a, const xnap_tai_support_t *b) +{ + _EQ_CHECK_UINT32(a->tac, b->tac); + _EQ_CHECK_INT(a->num_plmn, b->num_plmn); + for (int i = 0; i < a->num_plmn; i++) { + if (!eq_xnap_plmn_support(&a->plmn_support[i], &b->plmn_support[i])) + return false; + } + return true; +} diff --git a/openair2/XNAP/lib/xnap_lib_common.h b/openair2/XNAP/lib/xnap_lib_common.h new file mode 100644 index 0000000000..6186f55471 --- /dev/null +++ b/openair2/XNAP/lib/xnap_lib_common.h @@ -0,0 +1,64 @@ +/* + * 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 XNAP_LIB_COMMON_H_ +#define XNAP_LIB_COMMON_H_ + +#include +#include +#include +#include +#include +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" +#include "common/utils/eq_check.h" +#include "xnap_messages_types.h" +#include "xnap_lib_includes.h" + +/* macro to look up XnAP IE. If mandatory and not found, macro will print + * descriptive debug message to stderr and force exit in calling function */ +#define XNAP_LIB_FIND_IE(IE_TYPE, ie, IE_LIST, IE_ID, mandatory) \ + do { \ + ie = NULL; \ + for (IE_TYPE **ptr = (IE_LIST)->array; ptr < &(IE_LIST)->array[(IE_LIST)->count]; ptr++) { \ + if ((*ptr)->id == IE_ID) { \ + ie = *ptr; \ + break; \ + } \ + } \ + if ((mandatory) && (ie == NULL)) { \ + fprintf(stderr, "%s(): could not find XnAP IE " #IE_ID " of type " #IE_TYPE "\n", __func__); \ + return false; \ + } \ + } while (0) + +/* Function Prototypes */ +bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b); +bool eq_xnap_snssai(const nssai_t *a, const nssai_t *b); +bool eq_xnap_tai_support(const xnap_tai_support_t *a, const xnap_tai_support_t *b); +bool eq_xnap_plmn_support(const xnap_plmn_support_t *a, const xnap_plmn_support_t *b); +bool eq_xnap_cause(const xnap_cause_t *a, const xnap_cause_t *b); + +int xnap_gNB_set_cause(XNAP_Cause_t *cause_p,const xnap_cause_t *in); +xnap_cause_t decode_xnap_cause(const XNAP_Cause_t *in); + +#endif /* XNAP_LIB_COMMON_H_ */ diff --git a/openair2/XNAP/lib/xnap_lib_includes.h b/openair2/XNAP/lib/xnap_lib_includes.h new file mode 100644 index 0000000000..5e90adbea6 --- /dev/null +++ b/openair2/XNAP/lib/xnap_lib_includes.h @@ -0,0 +1,44 @@ +/* + * 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 + */ + +/* + * \brief XnAP ASN.1 message definitions generated from specifications + */ + +#ifndef XNAP_LIB_INCLUDES_H +#define XNAP_LIB_INCLUDES_H + +#include "XNAP_XnAP-PDU.h" +#include "XNAP_ProtocolIE-Field.h" +#include "XNAP_InitiatingMessage.h" +#include "XNAP_SuccessfulOutcome.h" +#include "XNAP_UnsuccessfulOutcome.h" + +#include "XNAP_GlobalgNB-ID.h" +#include "XNAP_GlobalNG-RANNode-ID.h" +#include "XNAP_GlobalAMF-Region-Information.h" +#include "XNAP_TAISupport-Item.h" +#include "XNAP_S-NSSAI.h" +#include "XNAP_BroadcastPLMNinTAISupport-Item.h" +#include "XNAP_Cause.h" + +#endif // XNAP_LIB_INCLUDES_H + diff --git a/openair2/XNAP/tests/CMakeLists.txt b/openair2/XNAP/tests/CMakeLists.txt new file mode 100644 index 0000000000..7c6875b887 --- /dev/null +++ b/openair2/XNAP/tests/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(xnap_lib_test xnap_lib_test.c) +add_dependencies(tests xnap_lib_test) +add_test(NAME xnap_lib_test COMMAND xnap_lib_test) +target_link_libraries(xnap_lib_test PRIVATE xnap_lib ds LOG) +target_link_libraries(xnap_lib_test PRIVATE asn1_xnap) +target_include_directories(xnap_lib_test PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair2/XNAP/tests/xnap_lib_test.c b/openair2/XNAP/tests/xnap_lib_test.c new file mode 100644 index 0000000000..3c1ec3375a --- /dev/null +++ b/openair2/XNAP/tests/xnap_lib_test.c @@ -0,0 +1,292 @@ +/* + * 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 + */ + +/* + * \brief Test functions for XnAP encoding/decoding library + */ + +#include +#include +#include +#include +#include "common/utils/assertions.h" +#include "common/utils/utils.h" +#include "xnap_messages_types.h" +#include "openair2/XNAP/lib/xnap_lib_common.h" +#include "openair2/XNAP/lib/xnap_gNB_interface_management.h" + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + printf("detected error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +/* Helper for ASN.1 Encoding/Decoding loop */ +static XNAP_XnAP_PDU_t *xnap_encode_decode(const XNAP_XnAP_PDU_t *enc_pdu) +{ + //xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, enc_pdu); + DevAssert(enc_pdu != NULL); + char errbuf[1024]; + size_t errlen = sizeof(errbuf); + int ret = asn_check_constraints(&asn_DEF_XNAP_XnAP_PDU, enc_pdu, errbuf, &errlen); + AssertFatal(ret == 0, "asn_check_constraints() failed: %s\n", errbuf); + + uint8_t msgbuf[16384]; + // 1. Encode + asn_enc_rval_t enc = aper_encode_to_buffer(&asn_DEF_XNAP_XnAP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf)); + AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n"); + + // 2. Decode + XNAP_XnAP_PDU_t *dec_pdu = NULL; + asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; + asn_dec_rval_t dec = aper_decode(&st, &asn_DEF_XNAP_XnAP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0); + AssertFatal(dec.code == RC_OK, "aper_decode() failed\n"); + + //xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, dec_pdu); + + return dec_pdu; +} + +static void xnap_msg_free(XNAP_XnAP_PDU_t *pdu) +{ + ASN_STRUCT_FREE(asn_DEF_XNAP_XnAP_PDU, pdu); +} + +/** + * 1. Xn Setup Request + */ +static void test_xn_setup_request(void) +{ + /* ---------- Common PLMNs ---------- */ + plmn_id_t plmn0 = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 }; + plmn_id_t plmn1 = { .mcc = 208, .mnc = 93, .mnc_digit_length = 2 }; + + /* ---------- TAI support (2) ---------- */ + xnap_tai_support_t *tai_support = calloc_or_fail(2, sizeof(*tai_support)); + + /* ================= TAI 0 ================= */ + tai_support[0].tac = 1; + tai_support[0].num_plmn = 2; + tai_support[0].plmn_support = calloc_or_fail(2, sizeof(*tai_support[0].plmn_support)); + + /* ---- TAI 0 / PLMN 0 ---- */ + tai_support[0].plmn_support[0].plmn = plmn0; + tai_support[0].plmn_support[0].num_nssai = 3; + tai_support[0].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[0].nssai[0] = (nssai_t){ .sst = 1, .sd = 0x010203 }; + tai_support[0].plmn_support[0].nssai[1] = (nssai_t){ .sst = 1, .sd = 0x010204 }; + tai_support[0].plmn_support[0].nssai[2] = (nssai_t){ .sst = 1, .sd = 0x010205 }; + + /* ---- TAI 0 / PLMN 1 ---- */ + tai_support[0].plmn_support[1].plmn = plmn1; + tai_support[0].plmn_support[1].num_nssai = 3; + tai_support[0].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[1].nssai[0] = (nssai_t){ .sst = 2, .sd = 0x020203 }; + tai_support[0].plmn_support[1].nssai[1] = (nssai_t){ .sst = 2, .sd = 0x020204 }; + tai_support[0].plmn_support[1].nssai[2] = (nssai_t){ .sst = 2, .sd = 0x020205 }; + + /* ================= TAI 1 ================= */ + tai_support[1].tac = 2; + tai_support[1].num_plmn = 2; + tai_support[1].plmn_support = calloc_or_fail(2, sizeof(*tai_support[1].plmn_support)); + + /* ---- TAI 1 / PLMN 0 ---- */ + tai_support[1].plmn_support[0].plmn = plmn0; + tai_support[1].plmn_support[0].num_nssai = 3; + tai_support[1].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[0].nssai[0] = (nssai_t){ .sst = 3, .sd = 0x030203 }; + tai_support[1].plmn_support[0].nssai[1] = (nssai_t){ .sst = 3, .sd = 0x030204 }; + tai_support[1].plmn_support[0].nssai[2] = (nssai_t){ .sst = 3, .sd = 0x030205 }; + + /* ---- TAI 1 / PLMN 1 ---- */ + tai_support[1].plmn_support[1].plmn = plmn1; + tai_support[1].plmn_support[1].num_nssai = 3; + tai_support[1].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[1].nssai[0] = (nssai_t){ .sst = 4, .sd = 0x040203 }; + tai_support[1].plmn_support[1].nssai[1] = (nssai_t){ .sst = 4, .sd = 0x040204 }; + tai_support[1].plmn_support[1].nssai[2] = (nssai_t){ .sst = 4, .sd = 0x040205 }; + + /* ---------- AMF region info (2) ---------- */ + xnap_amf_region_info_t *amf_region_info = calloc_or_fail(2, sizeof(*amf_region_info)); + + amf_region_info[0].plmn = plmn0; + amf_region_info[0].amf_region_id = 1; + + amf_region_info[1].plmn = plmn1; + amf_region_info[1].amf_region_id = 2; + + /* ---------- create message ---------- */ + xnap_setup_req_t orig = { + .gNB_id = 0xABCDE, + .plmn = plmn0, + .num_tai = 2, + .tai_support = tai_support, + .num_amf_regions = 2, + .amf_region_info = amf_region_info, + }; + /* ---------- encode ---------- */ + XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_request(&orig); + XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc); + xnap_msg_free(xnenc); + + /* ---------- decode ---------- */ + xnap_setup_req_t decoded = {0}; + bool ret = decode_xn_setup_request(&decoded, xndec); + AssertFatal(ret, "decode_xn_setup_request failed"); + xnap_msg_free(xndec); + + /* ---------- equality ---------- */ + ret = eq_xnap_setup_request(&orig, &decoded); + AssertFatal(ret, "Xn Setup Req mismatch\n"); + free_xnap_setup_request(&decoded); + free_xnap_setup_request(&orig); + printf("%s() successful \n", __func__); +} + +/** + * 2. Xn Setup Response + */ +static void test_xn_setup_response(void) +{ + /* ---------- Common PLMNs ---------- */ + plmn_id_t plmn0 = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 }; + plmn_id_t plmn1 = { .mcc = 208, .mnc = 93, .mnc_digit_length = 2 }; + + /* ---------- TAI support (2) ---------- */ + xnap_tai_support_t *tai_support = calloc_or_fail(2, sizeof(*tai_support)); + + /* ================= TAI 0 ================= */ + tai_support[0].tac = 1; + tai_support[0].num_plmn = 2; + tai_support[0].plmn_support = calloc_or_fail(2, sizeof(*tai_support[0].plmn_support)); + + /* ---- TAI 0 / PLMN 0 ---- */ + tai_support[0].plmn_support[0].plmn = plmn0; + tai_support[0].plmn_support[0].num_nssai = 3; + tai_support[0].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[0].nssai[0] = (nssai_t){ .sst = 1, .sd = 0x010203 }; + tai_support[0].plmn_support[0].nssai[1] = (nssai_t){ .sst = 1, .sd = 0x010204 }; + tai_support[0].plmn_support[0].nssai[2] = (nssai_t){ .sst = 1, .sd = 0x010205 }; + + /* ---- TAI 0 / PLMN 1 ---- */ + tai_support[0].plmn_support[1].plmn = plmn1; + tai_support[0].plmn_support[1].num_nssai = 3; + tai_support[0].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[1].nssai[0] = (nssai_t){ .sst = 2, .sd = 0x020203 }; + tai_support[0].plmn_support[1].nssai[1] = (nssai_t){ .sst = 2, .sd = 0x020204 }; + tai_support[0].plmn_support[1].nssai[2] = (nssai_t){ .sst = 2, .sd = 0x020205 }; + + /* ================= TAI 1 ================= */ + tai_support[1].tac = 2; + tai_support[1].num_plmn = 2; + tai_support[1].plmn_support = calloc_or_fail(2, sizeof(*tai_support[1].plmn_support)); + + /* ---- TAI 1 / PLMN 0 ---- */ + tai_support[1].plmn_support[0].plmn = plmn0; + tai_support[1].plmn_support[0].num_nssai = 3; + tai_support[1].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[0].nssai[0] = (nssai_t){ .sst = 3, .sd = 0x030203 }; + tai_support[1].plmn_support[0].nssai[1] = (nssai_t){ .sst = 3, .sd = 0x030204 }; + tai_support[1].plmn_support[0].nssai[2] = (nssai_t){ .sst = 3, .sd = 0x030205 }; + + /* ---- TAI 1 / PLMN 1 ---- */ + tai_support[1].plmn_support[1].plmn = plmn1; + tai_support[1].plmn_support[1].num_nssai = 3; + tai_support[1].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[1].nssai[0] = (nssai_t){ .sst = 4, .sd = 0x040203 }; + tai_support[1].plmn_support[1].nssai[1] = (nssai_t){ .sst = 4, .sd = 0x040204 }; + tai_support[1].plmn_support[1].nssai[2] = (nssai_t){ .sst = 4, .sd = 0x040205 }; + + /* ---------- create message ---------- */ + xnap_setup_resp_t orig = { + .gNB_id = 0xABCDE, + .plmn = plmn0, + .num_tai = 2, + .tai_support = tai_support, + }; + /* ---------- encode ---------- */ + XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_response(&orig); + XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc); + xnap_msg_free(xnenc); + + /* ---------- decode ---------- */ + xnap_setup_resp_t decoded = {0}; + bool ret = decode_xn_setup_response(&decoded, xndec); + AssertFatal(ret, "decode_xn_setup_response failed"); + xnap_msg_free(xndec); + + /* ---------- equality ---------- */ + ret = eq_xnap_setup_response(&orig, &decoded); + AssertFatal(ret, "Xn Setup Response mismatch\n"); + free_xnap_setup_response(&decoded); + free_xnap_setup_response(&orig); + printf("%s() successful \n", __func__); +} + +/** + * 3. Xn Setup Failure + */ +static void test_xn_setup_failure(void) +{ + /* ---------- create message ---------- */ + xnap_setup_failure_t orig = { + .cause.type = XNAP_CAUSE_TRANSPORT, + .cause.value = XNAP_CAUSE_TRANSPORT_LAYER_TRANSPORT_RESOURCE_UNAVAILABLE, + }; + + /* ---------- encode ---------- */ + XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_failure(&orig); + XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc); + xnap_msg_free(xnenc); + + /* ---------- decode ---------- */ + xnap_setup_failure_t decoded = {0}; + bool ret = decode_xn_setup_failure(&decoded, xndec); + AssertFatal(ret, "decode_xn_setup_failure failed"); + xnap_msg_free(xndec); + + /* ---------- equality ---------- */ + ret = eq_xnap_setup_failure(&orig, &decoded); + AssertFatal(ret, "Xn Setup Failure mismatch\n"); + free_xnap_setup_failure(&decoded); + free_xnap_setup_failure(&orig); + printf("%s() successful \n", __func__); +} + +int main() { + printf("Starting XnAP Library Unit Tests...\n"); + + /* Xn Interface Testing */ + test_xn_setup_request(); + test_xn_setup_response(); + test_xn_setup_failure(); + + printf("All XnAP tests passed!\n"); + return 0; +} diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index b545d8eb8d..4715bf653b 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -497,6 +497,16 @@ do { \ (bITsTRING)->bits_unused = 4; \ } while(0) +#define MACRO_BIT_STRING_TO_GNB_ID(bITsTRING, oUT) \ +do { \ + uint8_t *_buf = (bITsTRING)->buf; \ + (oUT) = \ + ((uint32_t)_buf[0] << 20) | \ + ((uint32_t)_buf[1] << 12) | \ + ((uint32_t)_buf[2] << 4) | \ + (((uint32_t)_buf[3] & 0xF0) >> 4); \ +} while (0) + /* TS 36.413 v10.9.0 section 9.2.1.38: * E-UTRAN CGI/Cell Identity * The leftmost bits of the Cell diff --git a/radio/COMMON/common_lib.c b/radio/COMMON/common_lib.c index 4720347f20..5e12d11e2b 100644 --- a/radio/COMMON/common_lib.c +++ b/radio/COMMON/common_lib.c @@ -217,7 +217,7 @@ static void writerProcessWaitingQueue(nrue_ru_write_t nrue_ru_write, PHY_VARS_NR else wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); if (wroteSamples != nsamps) - LOG_E(HW, "Failed to write to rf\n"); + LOG_W(HW, "Failed to write to RF: wrote %d out of %d samples\n", wroteSamples, nsamps); } ctx->nextTS = timestamp + nsamps; pthread_mutex_lock(&ctx->mutex_store); @@ -258,6 +258,8 @@ int openair0_write_reorder_common(nrue_ru_write_t nrue_ru_write, wroteSamples = nrue_ru_write(UE, timestamp, txp, nsamps, nbAnt, flags); else wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); + if (wroteSamples != nsamps) + LOG_W(HW, "Failed to write to RF: wrote %d out of %d samples\n", wroteSamples, nsamps); } else wroteSamples = nsamps; ctx->nextTS = timestamp + nsamps; diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index f224b75354..7cd0f47ee0 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -553,7 +553,7 @@ static int trx_usrp_write(openair0_device_t *device, LOG_D(HW, "Signaling TX TS %llu\n", (unsigned long long)timestamp); pthread_cond_signal(&write_thread->cond_write); pthread_mutex_unlock(&write_thread->mutex_write); - return 0; + return nsamps; } } diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 047c216898..617243b0fd 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -566,17 +566,31 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) #if defined F_RELEASE numRB = pRbElm->UP_nRBSize; startRB = pRbElm->UP_nRBStart; + struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0]; #endif LOG_D(HW, "pPrbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, startRB, numRB); - if (first) { - // ant_id / no of antenna per beam gives the beam_nb - pRbElm->nBeamIndex = - ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; - // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. - if (pRbElm->nBeamIndex == -1) { - pRbElm->nBeamIndex = 0; - } else { - first = 0; + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. + if (fh_cfg->RunSlotPrbMapBySymbolEnable) { + if (sym_idx >= pRbElm->nStartSymb && sym_idx < pRbElm->nStartSymb + pRbElm->numSymb) { + if (!p_sec_desc->pCtrl) + continue; + // ant_id / no of antenna per beam gives the beam_nb + pRbElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (pRbElm->nBeamIndex == -1) + pRbElm->nBeamIndex = 0; + } + } else { + if (first) { + // ant_id / no of antenna per beam gives the beam_nb + pRbElm->nBeamIndex = + ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (pRbElm->nBeamIndex == -1) { + pRbElm->nBeamIndex = 0; + } else { + first = 0; + } } } } @@ -592,6 +606,34 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) if (!is_tdd_dl_guard_slot(frame_conf, slot)) { continue; } + + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable. Set nPrbElm if beam_id = -1 for all downlink symbols + if (fh_cfg->RunSlotPrbMapBySymbolEnable) { + bool beam_used = false; + uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; + struct xran_prb_map *pRbMap = pPrbMap; + int32_t dl_sym_end = 0; + for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + if (is_tdd_dl_symbol(frame_conf, slot, sym_idx)) { + if (ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx] != -1) + beam_used |= true; + } + else { + dl_sym_end = sym_idx; + break; + } + } + if (is_tdd_guard_slot(frame_conf, slot)) + pRbMap->nPrbElm = dl_sym_end; + else + pRbMap->nPrbElm = XRAN_NUM_OF_SYMBOL_PER_SLOT; + if (!beam_used) { + pRbMap->nPrbElm = 0; + continue; + } + } + // This loop would better be more inner to avoid confusion and maybe also errors. for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { /* skip UL and guard symbols. */ @@ -612,21 +654,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int num_totalRB = p_prbMapElm->nRBSize; int start_totalRB = p_prbMapElm->nRBStart; - int pos_len = 0; - int neg_len = 0; - - if (start_totalRB < (num_totalRB >> 1)) // there are PRBs left of DC - neg_len = min((num_totalRB * 6) - (start_totalRB * 12), num_totalRB * N_SC_PER_PRB); - pos_len = (num_totalRB * N_SC_PER_PRB) - neg_len; - // Calculation of the pointer for the section in the buffer. - // start of positive frequency component - uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((start_totalRB * N_SC_PER_PRB) - (num_totalRB * 6)) : 0]; - // start of negative frequency component - uint16_t *src2 = (uint16_t *)&pos[(start_totalRB * N_SC_PER_PRB) + fftsize - (num_totalRB * 6)]; - - uint32_t local_src[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); - memcpy((void *)local_src, (void *)src2, neg_len * 4); - memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); if (ptr && pos) { u8dptr = (uint8_t *)ptr; int16_t payload_len = 0; @@ -654,34 +681,65 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int16_t numRB = p_prbMapElm->UP_nRBSize; #endif - dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); - if (p_sec_desc == NULL) { printf("p_sec_desc == NULL\n"); exit(-1); } + + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. + if (fh_cfg->RunSlotPrbMapBySymbolEnable) { + /* skip, if not scheduled */ + if(sym_idx < p_prbMapElm->nStartSymb || sym_idx >= p_prbMapElm->nStartSymb + p_prbMapElm->numSymb){ + p_sec_desc->iq_buffer_offset = 0; + p_sec_desc->iq_buffer_len = 0; + continue; + } + // ant_id / no of antenna per beam gives the beam_nb + p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (p_prbMapElm->nBeamIndex == -1) + p_prbMapElm->nBeamIndex = 0; + } else { + if (sym_idx == 0) { + // ant_id / no of antenna per beam gives the beam_nb + p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (p_prbMapElm->nBeamIndex == -1) + p_prbMapElm->nBeamIndex = 0; + } + } + + dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); + uint16_t *dst16 = (uint16_t *)dst; + // Start of this section + int32_t *pos_start = pos + (start_totalRB + startRB) * N_SC_PER_PRB; + if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { payload_len = numRB * N_SC_PER_PRB * 4L; /* convert to Network order */ // NOTE: ggc 11 knows how to generate AVX2 for this! for (idx = 0; idx < (numRB * N_SC_PER_PRB) * 2; idx++) - ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx + startRB * N_SC_PER_PRB * 2]); + ((uint16_t *)dst16)[idx] = htons(((uint16_t *)pos_start)[idx]); } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { payload_len = (3 * p_prbMapElm->iqWidth + 1) * numRB; + /* Although arm intrinsics natively handle unaligned memory + access, we use a 64 byte aligned input here for maximum + performance. So the src_compr buffer is used for both x86 and arm. + */ + uint32_t src_compr[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); + + /* Copy from txdataF with current symbol's PRB start (nRBStart) + + current section's PRB start (UP_nPRBStart) */ + memcpy(src_compr, pos_start, (numRB * N_SC_PER_PRB) * sizeof(*pos_start)); + #if defined(__i386__) || defined(__x86_64__) struct xranlib_compress_request bfp_com_req = {}; struct xranlib_compress_response bfp_com_rsp = {}; - uint32_t src_compr[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); - if (numRB == num_totalRB) { - bfp_com_req.data_in = (int16_t *)local_src; - } else { - memcpy(src_compr, local_src + (startRB * N_SC_PER_PRB), (numRB * N_SC_PER_PRB) * sizeof(*local_src)); - bfp_com_req.data_in = (int16_t *)src_compr; - } + bfp_com_req.data_in = (int16_t *)src_compr; bfp_com_req.numRBs = numRB; bfp_com_req.len = payload_len; @@ -693,7 +751,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); #elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)local_src, (int8_t *)dst); + armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)src_compr, (int8_t *)dst); #else AssertFatal(1 == 0, "BFP compression not supported on this architecture"); #endif @@ -721,456 +779,3 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) } return (0); } - -#if defined F_RELEASE -/** @details Read PRACH and PUSCH data from xran buffers. If - * I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data - * before writing. Prints ON TIME counters every 128 frames. - * - * Function is blocking and waits for next frame/slot combination. It is unblocked - * by oai_xran_fh_rx_callback(). It writes the current slot into parameters - * frame/slot. */ -int xran_fh_rx_read_slot_BySymbol(ru_info_t *ru, int *frame, int *slot) -{ - void *ptr = NULL; - int32_t *pos = NULL; - int idx = 0; - - static int64_t old_rx_counter[XRAN_PORTS_NUM] = {0}; - static int64_t old_tx_counter[XRAN_PORTS_NUM] = {0}; - struct xran_common_counters x_counters[XRAN_PORTS_NUM]; - static int outcnt = 0; - #ifndef USE_POLLING - // pull next even from oran_sync_fifo - notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo); - - notifiedFIFO_elt_t *f; - while ((f = pollNotifiedFIFO(&oran_sync_fifo)) != NULL) { - oran_sync_info_t *old_info = NotifiedFifoData(res); - oran_sync_info_t *new_info = NotifiedFifoData(f); - LOG_E(HW, "Detected double sync message %d.%d => %d.%d\n", old_info->f, old_info->sl, new_info->f, new_info->sl); - delNotifiedFIFO_elt(res); - res = f; - } - - oran_sync_info_t *info = NotifiedFifoData(res); - - *slot = info->sl; - *frame = info->f; - delNotifiedFIFO_elt(res); -#else - *slot = oran_sync_info.sl; - *frame = oran_sync_info.f; - uint32_t tti_in = oran_sync_info.tti; - - static int last_slot = -1; - LOG_D(HW, "oran slot %d, last_slot %d\n", *slot, last_slot); - int cnt = 0; - // while (*slot == last_slot) { - while (tti_in == oran_sync_info.tti) { - //*slot = oran_sync_info.sl; - cnt++; - } - LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot); - last_slot = *slot; -#endif - // return(0); - - struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; - - int tti = slots_per_frame * (*frame) + (*slot); - - read_prach_data(ru, *frame, *slot); - - const struct xran_fh_init *fh_init = get_xran_fh_init(); - int nPRBs = fh_cfg->nULRBs; - int fftsize = 1 << fh_cfg->nULFftSize; - - int slot_offset_rxdata = 3 & (*slot); - uint32_t slot_size = 4 * 14 * fftsize; - uint8_t *rx_data = (uint8_t *)ru->rxdataF[0]; - uint8_t *start_ptr = NULL; - int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; - for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. - for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { - rx_data = (uint8_t *)ru->rxdataF[ant_id]; - start_ptr = rx_data + (slot_size * slot_offset_rxdata); - const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; - // skip processing this slot is TX (no RX in this slot) - if (!is_tdd_ul_guard_slot(frame_conf, *slot)) - continue; - bool sym_start_found = false; - int32_t sym_start = 0; - // This loop would better be more inner to avoid confusion and maybe also errors. - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - /* the callback is for mixed and UL slots. In mixed, we have to - * skip DL and guard symbols. */ - if (!is_tdd_ul_symbol(frame_conf, *slot, sym_idx)) - continue; - if (!sym_start_found) { - sym_start = sym_idx; - sym_start_found = true; - } - - uint8_t *pData; - oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); - uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - - struct xran_prb_map *pRbMap = pPrbMap; - for (int idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { - struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm]; - struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0]; - pData = p_sec_desc->pData; - ptr = pData; - pos = (int32_t *)(start_ptr + (4 * sym_idx * fftsize)); - if (ptr == NULL || pos == NULL) - continue; - - uint8_t *src = (uint8_t *)ptr; - - LOG_D(HW, "rx pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); - // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. - u_int8_t section_id_tmp = pPrbMap->nPrbElm < XRAN_NUM_OF_SYMBOL_PER_SLOT ? sym_idx - sym_start: sym_idx; - if (section_id_tmp != pRbElm->nSectId) { - LOG_D(HW, - "rx prbMap[%d] : PRBstart %d nPRBs %d nSectId %d != sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, - pRbMap->prbMap[idxElm].nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - continue; - } - LOG_D(HW, - "rx prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, - pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - - int pos_len = 0; - int neg_len = 0; - int num_prbu = p_sec_desc->num_prbu; - int start_prbu = p_sec_desc->start_prbu; - if (start_prbu < (nPRBs >> 1)) // there are PRBs left of DC - neg_len = min((nPRBs * 6) - (start_prbu * 12), num_prbu * N_SC_PER_PRB); - pos_len = (num_prbu * N_SC_PER_PRB) - neg_len; - - src = pData; - // Calculation of the pointer for the section in the buffer. - // positive half - uint8_t *dst1 = (uint8_t *)(pos + (neg_len == 0 ? ((start_prbu * N_SC_PER_PRB) - (nPRBs * 6)) : 0)); - // negative half - uint8_t *dst2 = (uint8_t *)(pos + (start_prbu * N_SC_PER_PRB) + fftsize - (nPRBs * 6)); - int32_t local_dst[num_prbu * N_SC_PER_PRB] __attribute__((aligned(64))); - if (pRbElm->compMethod == XRAN_COMPMETHOD_NONE) { - // NOTE: gcc 11 knows how to generate AVX2 for this! - for (idx = 0; idx < num_prbu * N_SC_PER_PRB * 2; idx++) - ((int16_t *)local_dst)[idx] = ((int16_t)ntohs(((uint16_t *)src)[idx])) >> 2; - memcpy((void *)dst2, (void *)local_dst, neg_len * 4); - memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4); - } else if (pRbElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { -#if defined(__i386__) || defined(__x86_64__) - struct xranlib_decompress_request bfp_decom_req = {}; - struct xranlib_decompress_response bfp_decom_rsp = {}; - - int16_t payload_len = (3 * pRbElm->iqWidth + 1) * num_prbu; - - bfp_decom_req.data_in = (int8_t *)src; - bfp_decom_req.numRBs = num_prbu; - bfp_decom_req.len = payload_len; - bfp_decom_req.compMethod = pRbElm->compMethod; - bfp_decom_req.iqWidth = pRbElm->iqWidth; - - bfp_decom_rsp.data_out = (int16_t *)local_dst; - bfp_decom_rsp.len = 0; - - xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp); -#elif defined(__arm__) || defined(__aarch64__) - armral_bfp_decompression(pRbElm->iqWidth, num_prbu, (int8_t *)src, (int16_t *)local_dst); -#else - AssertFatal(1 == 0, "BFP compression not supported on this architecture"); -#endif - memcpy((void *)dst2, (void *)local_dst, neg_len * 4); - memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4); - outcnt++; - } else { - printf("pRbElm->compMethod == %d is not supported\n", pRbElm->compMethod); - exit(-1); - } - } - } // sym_ind - } // ant_ind - } // vv_inf - if ((*frame & 0x7f) == 0 && *slot == 0 && xran_get_common_counters(gxran_handle, &x_counters[0]) == XRAN_STATUS_SUCCESS) { - for (int o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) { - LOG_I(HW, - "[%s%d][rx %7ld pps %7ld kbps %7ld][tx %7ld pps %7ld kbps %7ld][Total Msgs_Rcvd %ld]\n", - "o-du ", - o_xu_id, - x_counters[o_xu_id].rx_counter, - x_counters[o_xu_id].rx_counter - old_rx_counter[o_xu_id], - x_counters[o_xu_id].rx_bytes_per_sec * 8 / 1000L, - x_counters[o_xu_id].tx_counter, - x_counters[o_xu_id].tx_counter - old_tx_counter[o_xu_id], - x_counters[o_xu_id].tx_bytes_per_sec * 8 / 1000L, - x_counters[o_xu_id].Total_msgs_rcvd); - for (int rxant = 0; rxant < ru->nb_rx / fh_init->xran_ports; rxant++) - LOG_I(HW, - "[%s%d][pusch%d %7ld prach%d %7ld]\n", - "o_du", - o_xu_id, - rxant, - x_counters[o_xu_id].rx_pusch_packets[rxant], - rxant, - x_counters[o_xu_id].rx_prach_packets[rxant]); - if (x_counters[o_xu_id].rx_counter > old_rx_counter[o_xu_id]) - old_rx_counter[o_xu_id] = x_counters[o_xu_id].rx_counter; - if (x_counters[o_xu_id].tx_counter > old_tx_counter[o_xu_id]) - old_tx_counter[o_xu_id] = x_counters[o_xu_id].tx_counter; - } - } - return (0); -} - -/** @details Write PDSCH IQ-data from OAI txdataF_BF buffer to xran buffers. If - * I/Q compression (bitwidth < 16 bits) is configured, compresses the data - * before writing. */ -int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t timestamp) -{ - int tti = /*frame*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME+*/ 20 * frame - + slot; // commented out temporarily to check that compilation of oran 5g is working. - - void *ptr = NULL; - int32_t *pos = NULL; - int idx = 0; - - const struct xran_fh_init *fh_init = get_xran_fh_init(); - const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int nPRBs = fh_cfg->nDLRBs; - int fftsize = 1 << fh_cfg->nDLFftSize; - int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; - int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; - - // Handle CP UL packet here instead of at xran_fh_rx_read_slot() as oran_fh_if4p5_south_in() lags behind - // oran_fh_if4p5_south_out() (which is invoked at the right time slot) by 4 slots. - // Need to use --continuous-tx so that this routine will be triggered in RX slot. - for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. - for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { - const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; - // skip processing this slot is TX (no RX in this slot) - if (!is_tdd_ul_guard_slot(frame_conf, slot)) { - continue; - } - bool sym_start_found = false; - int32_t sym_start = 0; - // This loop would better be more inner to avoid confusion and maybe also errors. - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - /* the callback is for mixed and UL slots. In mixed, we have to - * skip DL and guard symbols. */ - if (!is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { - continue; - } - if (!sym_start_found) { - sym_start = sym_idx; - sym_start_found = true; - } - - oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); - uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - - struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0]; - - struct xran_prb_map *pRbMap = pPrbMap; - uint32_t idxElm = 0; - - LOG_D(HW, "tx0 pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); - for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { - LOG_D(HW, "prbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].nRBSize); - pRbElm = &pRbMap->prbMap[idxElm]; - // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. - u_int8_t section_id_tmp = pPrbMap->nPrbElm < XRAN_NUM_OF_SYMBOL_PER_SLOT ? sym_idx - sym_start: sym_idx; - if (section_id_tmp != pRbElm->nSectId) { - LOG_D(HW, - "tx0 prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d != sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, - pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - continue; - } - LOG_D(HW, - "tx0 prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, - pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - - // ant_id / no of antenna per beam gives the beam_nb - pRbElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; - // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. - if (pRbElm->nBeamIndex == -1) - pRbElm->nBeamIndex = 0; - } - } - } - } - - for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. - for (uint8_t ant_id = 0; ant_id < ru->nb_tx; ant_id++) { - oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_tx_per_ru); - const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_tx_per_ru)->frame_conf; - // skip processing this slot is TX (no TX in this slot) - if (!is_tdd_dl_guard_slot(frame_conf, slot)) { - continue; - } - - // Set nPrbElm if beam_id = -1 for all downlink symbols - bool beam_used = false; - uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - struct xran_prb_map *pRbMap = pPrbMap; - int32_t dl_sym_end = 0; - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - if (is_tdd_dl_symbol(frame_conf, slot, sym_idx)) { - if (ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx] != -1) - beam_used |= true; - } - else { - dl_sym_end = sym_idx; - break; - } - } - if (is_tdd_guard_slot(frame_conf, slot)) - pRbMap->nPrbElm = dl_sym_end; - else - pRbMap->nPrbElm = XRAN_NUM_OF_SYMBOL_PER_SLOT; - if (!beam_used) { - pRbMap->nPrbElm = 0; - continue; - } - - // This loop would better be more inner to avoid confusion and maybe also errors. - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - /* the callback is for mixed and UL slots. In mixed, we have to - * skip UL and guard symbols. */ - if (is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { - continue; - } - uint8_t *pData = - bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData; - uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - ptr = pData; - pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize]; - - uint8_t *u8dptr; - struct xran_prb_map *pRbMap = pPrbMap; - int32_t sym_id = sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT; - if (ptr && pos) { - uint32_t idxElm = 0; - u8dptr = (uint8_t *)ptr; - int16_t payload_len = 0; - - uint8_t *dst = (uint8_t *)u8dptr; - - struct xran_prb_elm *p_prbMapElm = &pRbMap->prbMap[idxElm]; - LOG_D(HW, "tx1 pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); - for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { - // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. - struct xran_section_desc *p_sec_desc = NULL; - p_prbMapElm = &pRbMap->prbMap[idxElm]; - if (sym_idx != p_prbMapElm->nSectId) - continue; - // ant_id / no of antenna per beam gives the beam_nb - p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx]; - // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. - if (p_prbMapElm->nBeamIndex == -1) - p_prbMapElm->nBeamIndex = 0; - - // assumes one fragment per symbol - p_sec_desc = &p_prbMapElm->sec_desc[sym_id][0]; - - dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); - - if (p_sec_desc == NULL) { - printf("p_sec_desc == NULL\n"); - exit(-1); - } - uint16_t *dst16 = (uint16_t *)dst; - - int pos_len = 0; - int neg_len = 0; - - if (p_prbMapElm->UP_nRBStart < (nPRBs >> 1)) // there are PRBs left of DC - neg_len = min((nPRBs * 6) - (p_prbMapElm->UP_nRBStart * 12), p_prbMapElm->UP_nRBSize * N_SC_PER_PRB); - pos_len = (p_prbMapElm->UP_nRBSize * N_SC_PER_PRB) - neg_len; - // Calculation of the pointer for the section in the buffer. - // start of positive frequency component - uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0]; - // start of negative frequency component - uint16_t *src2 = (uint16_t *)&pos[(p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6)]; - - uint32_t local_src[p_prbMapElm->UP_nRBSize * N_SC_PER_PRB] __attribute__((aligned(64))); - memcpy((void *)local_src, (void *)src2, neg_len * 4); - memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); - if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { - payload_len = p_prbMapElm->UP_nRBSize * N_SC_PER_PRB * 4L; - /* convert to Network order */ - // NOTE: ggc 11 knows how to generate AVX2 for this! - for (idx = 0; idx < (pos_len + neg_len) * 2; idx++) - ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx]); - } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { - payload_len = (3 * p_prbMapElm->iqWidth + 1) * p_prbMapElm->UP_nRBSize; - -#if defined(__i386__) || defined(__x86_64__) - struct xranlib_compress_request bfp_com_req = {}; - struct xranlib_compress_response bfp_com_rsp = {}; - - bfp_com_req.data_in = (int16_t *)local_src; - bfp_com_req.numRBs = p_prbMapElm->UP_nRBSize; - bfp_com_req.len = payload_len; - bfp_com_req.compMethod = p_prbMapElm->compMethod; - bfp_com_req.iqWidth = p_prbMapElm->iqWidth; - - bfp_com_rsp.data_out = (int8_t *)dst; - bfp_com_rsp.len = 0; - - xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); -#elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, p_prbMapElm->UP_nRBSize, (int16_t *)local_src, (int8_t *)dst); -#else - AssertFatal(1 == 0, "BFP compression not supported on this architecture"); -#endif - - } else { - printf("p_prbMapElm->compMethod == %d is not supported\n", p_prbMapElm->compMethod); - exit(-1); - } - - p_sec_desc->iq_buffer_offset = RTE_PTR_DIFF(dst, u8dptr); - p_sec_desc->iq_buffer_len = payload_len; - - dst += payload_len; - dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); - } - - // The tti should be updated as it increased. - pRbMap->tti_id = tti; - - } else { - printf("ptr ==NULL\n"); - exit(-1); // fails here?? - } - } - } - } - return (0); -} -#endif \ No newline at end of file diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 0ec4867299..d19d2c1f00 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -227,14 +227,7 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) int f, sl; LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]); start_meas(&ru->rx_fhaul); - struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int ret = 0; -#if defined F_RELEASE - if (fh_cfg->RunSlotPrbMapBySymbolEnable) - ret = xran_fh_rx_read_slot_BySymbol(&ru_info, &f, &sl); - else -#endif - ret = xran_fh_rx_read_slot(&ru_info, &f, &sl); + int ret = xran_fh_rx_read_slot(&ru_info, &f, &sl); stop_meas(&ru->rx_fhaul); LOG_D(HW, "Read %d.%d rxdataF %p,%p\n", f, sl, ru_info.rxdataF[0], ru_info.rxdataF[1]); if (ret != 0) { @@ -289,14 +282,7 @@ void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) // printf("south_out:\tframe=%d\tslot=%d\ttimestamp=%ld\n",frame,slot,timestamp); - struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int ret = 0; -#if defined F_RELEASE - if (fh_cfg->RunSlotPrbMapBySymbolEnable) - ret = xran_fh_tx_send_slot_BySymbol(&ru_info, frame, slot, timestamp); - else -#endif - ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp); + int ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp); if (ret != 0) { printf("ORAN: ORAN_fh_if4p5_south_out ERROR in TX function \n"); } diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index 44c9bee51d..6d7a47811b 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -61,13 +61,7 @@ typedef struct ru_info_s { * @param frame output of the frame which has been read. * @param slot output of the slot which has been read. */ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot); -#if defined F_RELEASE -int xran_fh_rx_read_slot_BySymbol(ru_info_t *ru, int *frame, int *slot); -#endif /** @brief Writes TX data (PDSCH) of given slot. */ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp); -#if defined F_RELEASE -int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t timestamp); -#endif #endif /* _ORAN_ISOLATE_H_ */ diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 9a0cd779dc..36780f3ae6 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "common_lib.h" #include "shm_td_iq_channel.h" #include "SIMULATION/TOOLS/sim.h" @@ -59,6 +60,7 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; #define MAX_NUM_ANTENNAS_TX 4 #define SAVED_SAMPLES_LEN 256 +#define MAX_NUM_UES MAX_MOBILES_PER_GNB #define ROLE_CLIENT_STRING "client" #define ROLE_SERVER_STRING "server" @@ -90,6 +92,8 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; {"cirdb_model_id", "Preferred TDL model id 0..4", 0, .iptr = &vrtsim_state->cirdb_model_id, .defintval = 0, TYPE_INT, 0}, \ {"cirdb_ds_ns", "Desired RMS delay spread in ns", 0, .dblptr = &vrtsim_state->cirdb_ds_ns, .defdblval = 10.0, TYPE_DOUBLE, 0}, \ {"cirdb_speed_mps", "Desired speed in m/s", 0, .dblptr = &vrtsim_state->cirdb_speed_mps, .defdblval = 1.5, TYPE_DOUBLE, 0}, \ + {"num_ues", "Number of UE slots (server only)\n", 0, .iptr = &vrtsim_state->num_ues, .defintval = 1, TYPE_INT, 0}, \ + {"ue_id", "UE slot index 0..num_ues-1 (client only)\n", 0, .iptr = &vrtsim_state->ue_id, .defintval = 0, TYPE_INT, 0}, \ }; // clang-format on @@ -113,6 +117,20 @@ typedef struct tx_timing_s { histogram_t tx_histogram; } tx_timing_t; +typedef struct { + int model_id; + double ds_ns; + double speed_mps; +} cirdb_conf_t; + +typedef struct { + int tx_ant; + int rx_ant; + int tx_offset; + int rx_offset; + cirdb_conf_t cir_conf; +} ue_conf_t; + typedef struct { int role; char *connection_descriptor; @@ -133,6 +151,8 @@ typedef struct { int tx_num_channels; int rx_num_channels; channel_desc_t *channel_desc; + channel_desc_t *channel_desc_per_ue[MAX_NUM_UES]; + pthread_mutex_t cirdb_mutex; Actor_t *channel_modelling_actors; char *taps_socket; int client_num_rx_antennas; @@ -145,6 +165,18 @@ typedef struct { int cirdb_model_id; double cirdb_ds_ns; double cirdb_speed_mps; + // Multi-UE support + int num_ues; + int ue_id; + + ue_conf_t ue_conf[MAX_NUM_UES]; + ue_conf_t ue; + + // Totals + int total_ul_streams; + int total_dl_streams; + sample_t *ul_combine_buffer; + size_t ul_combine_buffer_len; } vrtsim_state_t; static void histogram_add(histogram_t *histogram, double diff) @@ -251,10 +283,11 @@ static void *vrtsim_timing_job(void *arg) } typedef struct client_info_s { - int server_num_rx_antennas; - int client_num_rx_antennas; + int num_ues; + int gnb_num_tx_ant; + int gnb_num_rx_ant; + ue_conf_t ues[MAX_NUM_UES]; } client_info_t; - /** * @brief Publishes the client information information to a file for the client to read. * @@ -293,43 +326,174 @@ static client_info_t client_read_info(char *descriptor_file) return client_info; } +static void parse_ue_config(vrtsim_state_t *vrtsim_state) +{ + AssertFatal(vrtsim_state->num_ues > 0 && vrtsim_state->num_ues <= MAX_NUM_UES, + "num_ues=%d out of range (1..%d)\n", vrtsim_state->num_ues, MAX_NUM_UES); + + for (int i = 0; i < vrtsim_state->num_ues; i++) { + char prefix[64]; + snprintf(prefix, sizeof(prefix), "%s.ue_config.[%d]", VRTSIM_SECTION, i); + + char *antennas = NULL; + int model_id = vrtsim_state->cirdb_model_id; + double ds_ns = vrtsim_state->cirdb_ds_ns; + double speed_mps = vrtsim_state->cirdb_speed_mps; + + paramdef_t ue_params[] = { + {"antennas", "Antenna config e.g. \"1x2\"", 0, .strptr = &antennas, .defstrval = NULL, TYPE_STRING, 0}, + {"model_id", "TDL model id 0..4", 0, .iptr = &model_id, .defintval = vrtsim_state->cirdb_model_id, TYPE_INT, 0}, + {"ds_ns", "Delay spread in ns", 0, .dblptr = &ds_ns, .defdblval = vrtsim_state->cirdb_ds_ns, TYPE_DOUBLE, 0}, + {"speed_mps", "Speed in m/s", 0, .dblptr = &speed_mps, .defdblval = vrtsim_state->cirdb_speed_mps, TYPE_DOUBLE, 0}, + }; + config_get(config_get_if(), ue_params, sizeofArray(ue_params), prefix); + + if (antennas != NULL) { + int tx_ant, rx_ant; + AssertFatal(sscanf(antennas, "%dx%d", &tx_ant, &rx_ant) == 2, + "Invalid antenna format '%s' for UE %d, use e.g. '1x2'\n", antennas, i); + AssertFatal(tx_ant > 0 && tx_ant <= MAX_NUM_ANTENNAS_TX, + "Invalid TX antenna count %d for UE %d\n", tx_ant, i); + AssertFatal(rx_ant > 0 && rx_ant <= MAX_NUM_ANTENNAS_TX, + "Invalid RX antenna count %d for UE %d\n", rx_ant, i); + vrtsim_state->ue_conf[i].tx_ant = tx_ant; + vrtsim_state->ue_conf[i].rx_ant = rx_ant; + } else { + vrtsim_state->ue_conf[i].tx_ant = 1; + vrtsim_state->ue_conf[i].rx_ant = 1; + } + + AssertFatal(model_id >= 0 && model_id <= 4, + "Invalid model_id %d for UE %d (must be 0-4)\n", model_id, i); + AssertFatal(ds_ns > 0, + "Invalid ds_ns %.1f for UE %d (must be > 0)\n", ds_ns, i); + AssertFatal(speed_mps >= 0, + "Invalid speed_mps %.1f for UE %d (must be >= 0)\n", speed_mps, i); + + vrtsim_state->ue_conf[i].cir_conf.model_id = model_id; + vrtsim_state->ue_conf[i].cir_conf.ds_ns = ds_ns; + vrtsim_state->ue_conf[i].cir_conf.speed_mps = speed_mps; + + LOG_I(HW, "VRTSIM: UE %d - %dx%d antennas, Model %d (TDL-%c), DS %.1fns, Speed %.1fm/s\n", + i, + vrtsim_state->ue_conf[i].tx_ant, + vrtsim_state->ue_conf[i].rx_ant, + model_id, 'A' + model_id, ds_ns, speed_mps); + } +} + +static void compute_ue_antenna_offsets(vrtsim_state_t *vrtsim_state) +{ + int tx_offset = 0; + int rx_offset = 0; + + for (int i = 0; i < vrtsim_state->num_ues; i++) { + vrtsim_state->ue_conf[i].tx_offset = tx_offset; + vrtsim_state->ue_conf[i].rx_offset = rx_offset; + + LOG_I(HW, + "VRTSIM: UE %d - TX: %d antennas (offset %d), RX: %d antennas (offset %d)\n", + i, + vrtsim_state->ue_conf[i].tx_ant, + tx_offset, + vrtsim_state->ue_conf[i].rx_ant, + rx_offset); + + tx_offset += vrtsim_state->ue_conf[i].tx_ant; + rx_offset += vrtsim_state->ue_conf[i].rx_ant; + } + + vrtsim_state->total_ul_streams = tx_offset; + vrtsim_state->total_dl_streams = rx_offset; + + LOG_I(HW, "VRTSIM: Total streams - UL: %d, DL: %d\n", vrtsim_state->total_ul_streams, vrtsim_state->total_dl_streams); +} + static int vrtsim_connect(openair0_device_t *device) { vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; // Setup a shared memory channel if (vrtsim_state->role == ROLE_SERVER) { - vrtsim_state->peer_info.num_rx_antennas = vrtsim_state->client_num_rx_antennas; - vrtsim_state->channel = shm_td_iq_channel_create(DEFAULT_CHANNEL_NAME, - vrtsim_state->peer_info.num_rx_antennas, - device->openair0_cfg[0].rx_num_channels); - // Exchange peer info - client_info_t client_info = { - .server_num_rx_antennas = device->openair0_cfg[0].rx_num_channels, - .client_num_rx_antennas = vrtsim_state->client_num_rx_antennas, - }; - server_publish_client_info(client_info, vrtsim_state->connection_descriptor); + parse_ue_config(vrtsim_state); + compute_ue_antenna_offsets(vrtsim_state); + int ul_streams = (vrtsim_state->chanmod || vrtsim_state->taps_socket || vrtsim_state->use_cirdb) + ? vrtsim_state->num_ues * device->openair0_cfg[0].rx_num_channels + : vrtsim_state->total_ul_streams; + vrtsim_state->channel = + shm_td_iq_channel_create(DEFAULT_CHANNEL_NAME, ul_streams, vrtsim_state->total_dl_streams); + size_t max_nsamps = 7680 * 2; + vrtsim_state->ul_combine_buffer = calloc_or_fail(max_nsamps, sizeof(sample_t)); + vrtsim_state->ul_combine_buffer_len = max_nsamps; + // Exchange peer info + + client_info_t client_info = { + .num_ues = vrtsim_state->num_ues, + .gnb_num_tx_ant = device->openair0_cfg[0].tx_num_channels, + .gnb_num_rx_ant = device->openair0_cfg[0].rx_num_channels, + }; + + for (int i = 0; i < vrtsim_state->num_ues; i++) + client_info.ues[i] = vrtsim_state->ue_conf[i]; + + server_publish_client_info(client_info, vrtsim_state->connection_descriptor); + vrtsim_state->peer_info.num_rx_antennas = vrtsim_state->client_num_rx_antennas; + vrtsim_state->last_received_sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel); vrtsim_state->run_timing_thread = true; threadCreate(&vrtsim_state->timing_thread, vrtsim_timing_job, vrtsim_state, "vrtsim_timing", -1, OAI_PRIORITY_RT_MAX); } else { client_info_t client_info = client_read_info(vrtsim_state->connection_descriptor); - AssertFatal(client_info.server_num_rx_antennas > 0, "Server did not publish valid client info, aborting client connection\n"); - AssertFatal( - client_info.client_num_rx_antennas == device->openair0_cfg[0].rx_num_channels, - "Server expects different number of RX antennas. %d != %d. Use server command line option --client-num-rx-antennas\n", - client_info.client_num_rx_antennas, - device->openair0_cfg[0].rx_num_channels); + AssertFatal(client_info.num_ues > 0, "Server did not publish valid num_ues\n"); + AssertFatal(vrtsim_state->ue_id < client_info.num_ues, "ue_id %d >= num_ues %d\n", vrtsim_state->ue_id, client_info.num_ues); + + vrtsim_state->ue = client_info.ues[vrtsim_state->ue_id]; + + AssertFatal(vrtsim_state->ue.tx_ant == device->openair0_cfg[0].tx_num_channels, + "Server expects UE %d to have %d TX antennas, this UE has %d\n", + vrtsim_state->ue_id, + vrtsim_state->ue.tx_ant, + device->openair0_cfg[0].tx_num_channels); + AssertFatal(vrtsim_state->ue.rx_ant == device->openair0_cfg[0].rx_num_channels, + "Server expects UE %d to have %d RX antennas, this UE has %d\n", + vrtsim_state->ue_id, + vrtsim_state->ue.rx_ant, + device->openair0_cfg[0].rx_num_channels); + + LOG_I(HW, + "VRTSIM: UE %d/%d - %dx%d antennas, UL offset=%d, DL offset=%d\n", + vrtsim_state->ue_id, + client_info.num_ues, + vrtsim_state->ue.tx_ant, + vrtsim_state->ue.rx_ant, + vrtsim_state->ue.tx_offset, + vrtsim_state->ue.rx_offset); + if (vrtsim_state->use_cirdb) { + vrtsim_state->cirdb_model_id = vrtsim_state->ue.cir_conf.model_id; + vrtsim_state->cirdb_ds_ns = vrtsim_state->ue.cir_conf.ds_ns; + vrtsim_state->cirdb_speed_mps = vrtsim_state->ue.cir_conf.speed_mps; + + LOG_I(HW, + "VRTSIM: UE %d channel - Model %d (TDL-%c), DS %.1fns, Speed %.1fm/s\n", + vrtsim_state->ue_id, + vrtsim_state->cirdb_model_id, + 'A' + vrtsim_state->cirdb_model_id, + vrtsim_state->cirdb_ds_ns, + vrtsim_state->cirdb_speed_mps); + } vrtsim_state->channel = shm_td_iq_channel_connect(DEFAULT_CHANNEL_NAME, 10); - vrtsim_state->peer_info.num_rx_antennas = client_info.server_num_rx_antennas; + vrtsim_state->peer_info.num_rx_antennas = client_info.gnb_num_rx_ant; vrtsim_state->last_received_sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel); } // Handle channel modelling after number of RX antennas are known int num_tx_stats = 1; if (vrtsim_state->chanmod || vrtsim_state->taps_socket || vrtsim_state->use_cirdb) { - vrtsim_state->channel_modelling_actors = calloc_or_fail(vrtsim_state->peer_info.num_rx_antennas, sizeof(Actor_t)); - for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) { + int num_actors = (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) ? vrtsim_state->total_dl_streams + : vrtsim_state->peer_info.num_rx_antennas; + + vrtsim_state->channel_modelling_actors = calloc_or_fail(num_actors, sizeof(Actor_t)); + for (int i = 0; i < num_actors; i++) { init_actor(&vrtsim_state->channel_modelling_actors[i], "chanmod", -1); } if (vrtsim_state->taps_socket) { @@ -379,16 +543,55 @@ static int vrtsim_connect(openair0_device_t *device) sel.yaml_path ? sel.yaml_path : "(auto)", sel.bin_path ? sel.bin_path : "(auto)"); - cirdb_connect(0, - device->openair0_cfg[0].tx_num_channels, - vrtsim_state->peer_info.num_rx_antennas, - &sel, - &vrtsim_state->channel_desc); - LOG_A(HW, "VRTSIM: channel taps via CIR DB\n"); + // Multi-UE server: create per-UE channel descriptors + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + for (int u = 0; u < vrtsim_state->num_ues; u++) { + cirdb_select_opts_t ue_sel = sel; + ue_sel.want_model_id = vrtsim_state->ue_conf[u].cir_conf.model_id; + ue_sel.want_ds_ns = vrtsim_state->ue_conf[u].cir_conf.ds_ns; + ue_sel.want_speed_mps = vrtsim_state->ue_conf[u].cir_conf.speed_mps; + + AssertFatal(ue_sel.want_model_id >= 0 && ue_sel.want_model_id <= 4, + "Invalid CIRDB model_id=%d for UE %d\n", + ue_sel.want_model_id, + u); + + cirdb_connect(u, + device->openair0_cfg[0].tx_num_channels, + vrtsim_state->ue_conf[u].rx_ant, + &ue_sel, + &vrtsim_state->channel_desc_per_ue[u]); + + channel_desc_t *cd = vrtsim_state->channel_desc_per_ue[u]; + AssertFatal(cd != NULL, "CIRDB failed to create channel_desc for UE %d\n", u); + AssertFatal(cd->nb_tx == device->openair0_cfg[0].tx_num_channels, + "CIRDB shape mismatch UE%d: nb_tx=%d expected %d\n", + u, cd->nb_tx, device->openair0_cfg[0].tx_num_channels); + LOG_I(HW, "VRTSIM: UE %d channel_desc=%p ch_ps=%p ch=%p nb_tx=%d nb_rx=%d\n", + u, cd, cd->ch_ps, cd->ch, cd->nb_tx, cd->nb_rx); + LOG_I(HW, "VRTSIM: UE %d CIRDB - Model %d (TDL-%c), antennas %dx%d, nb_rx=%d\n", + u, ue_sel.want_model_id, 'A' + ue_sel.want_model_id, + device->openair0_cfg[0].tx_num_channels, vrtsim_state->ue_conf[u].rx_ant, cd->nb_rx); + } + vrtsim_state->channel_desc = vrtsim_state->channel_desc_per_ue[0]; + pthread_mutex_init(&vrtsim_state->cirdb_mutex, NULL); + LOG_A(HW, "VRTSIM: Multi-UE channel taps via CIR DB\n"); + } else { + cirdb_connect(0, + device->openair0_cfg[0].tx_num_channels, + vrtsim_state->peer_info.num_rx_antennas, + &sel, + &vrtsim_state->channel_desc); + LOG_A(HW, "VRTSIM: channel taps via CIR DB\n"); + } } else { load_channel_model(vrtsim_state); } num_tx_stats = vrtsim_state->peer_info.num_rx_antennas; + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + vrtsim_state->peer_info.num_rx_antennas = vrtsim_state->total_dl_streams; + num_tx_stats = vrtsim_state->total_dl_streams; + } } vrtsim_state->tx_timing = calloc_or_fail(num_tx_stats, sizeof(tx_timing_t)); for (int i = 0; i < num_tx_stats; i++) { @@ -451,15 +654,69 @@ static void perform_channel_modelling(void *arg) c16_t **input_samples = (c16_t **)channel_modelling_args->samples; channel_desc_t *channel_desc = vrtsim_state->channel_desc; + int local_aarx = aarx; + int global_aarx = aarx; + int target_ue = 0; + + if (vrtsim_state->role == ROLE_CLIENT) { + global_aarx = vrtsim_state->ue_id * vrtsim_state->peer_info.num_rx_antennas + aarx; + } + + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + if (aarx >= vrtsim_state->total_dl_streams) { + LOG_E(HW, "VRTSIM: aarx=%d >= total_dl_streams=%d\n", aarx, vrtsim_state->total_dl_streams); + return; + } + + bool found = false; + for (int u = 0; u < vrtsim_state->num_ues; u++) { + int offset = vrtsim_state->ue_conf[u].rx_offset; + int count = vrtsim_state->ue_conf[u].rx_ant; + if (aarx >= offset && aarx < offset + count) { + target_ue = u; + local_aarx = aarx - offset; + channel_desc = vrtsim_state->channel_desc_per_ue[u]; + found = true; + break; + } + } + + if (!found) { + LOG_E(HW, "VRTSIM: aarx=%d could not map to any UE (total_dl_streams=%d)\n", aarx, vrtsim_state->total_dl_streams); + return; + } + } if (channel_desc == NULL) { + LOG_E(HW, "VRTSIM: channel_desc is NULL for aarx=%d\n", aarx); + return; + } + + // Bounds check: ensure local_aarx is within channel_desc bounds + if (local_aarx >= channel_desc->nb_rx) { + LOG_E(HW, + "VRTSIM: UE%d local_aarx=%d >= nb_rx=%d (global aarx=%d). CIRDB shape mismatch.\n", + target_ue, + local_aarx, + channel_desc->nb_rx, + aarx); return; } if (vrtsim_state->use_cirdb) { double seconds = (double)channel_modelling_args->timestamp / vrtsim_state->sample_rate; uint64_t elapsed_ns = (uint64_t)(seconds * 1e9 + 0.5); + + // Lock for multi-UE to prevent concurrent CIRDB updates + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + pthread_mutex_lock(&vrtsim_state->cirdb_mutex); + } + cirdb_update(elapsed_ns); + + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + pthread_mutex_unlock(&vrtsim_state->cirdb_mutex); + } } cf_t channel_impulse_response[nb_tx_ant][channel_desc->channel_length]; @@ -468,7 +725,7 @@ static void perform_channel_modelling(void *arg) const float pathloss_linear = powf(10, channel_desc->path_loss_dB / 20.0); // Convert channel impulse response to float + apply pathloss for (int aatx = 0; aatx < nb_tx_ant; aatx++) { - const struct complexd *channelModel = channel_desc->ch[aarx + (aatx * channel_desc->nb_rx)]; + const struct complexd *channelModel = channel_desc->ch[local_aarx + (aatx * channel_desc->nb_rx)]; for (int i = 0; i < channel_desc->channel_length; i++) { channel_impulse_response[aatx][i].r = channelModel[i].r * pathloss_linear; channel_impulse_response[aatx][i].i = channelModel[i].i * pathloss_linear; @@ -477,7 +734,7 @@ static void perform_channel_modelling(void *arg) } } else { for (int aatx = 0; aatx < nb_tx_ant; aatx++) { - struct complexf *channelModel = channel_desc->ch_ps[aarx + (aatx * channel_desc->nb_rx)]; + struct complexf *channelModel = channel_desc->ch_ps[local_aarx + (aatx * channel_desc->nb_rx)]; channel_impulse_response_p[aatx] = channelModel; } } @@ -537,7 +794,7 @@ static void perform_channel_modelling(void *arg) channel_modelling_args->timestamp + start_sample, samples_out, num_samples, - aarx, + global_aarx, channel_modelling_args->flags, aarx); } @@ -623,8 +880,27 @@ static int vrtsim_write(openair0_device_t *device, timestamp -= device->openair0_cfg->command_line_sample_advance; vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; bool channel_modelling = vrtsim_state->chanmod || vrtsim_state->taps_socket || vrtsim_state->use_cirdb; - return channel_modelling ? vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags) - : vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, 0, flags, 0); + if (channel_modelling) { + return vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags); + } + if (vrtsim_state->role == ROLE_CLIENT) { + for (int aatx = 0; aatx < nbAnt; aatx++) { + int global_ul_ant = vrtsim_state->ue.tx_offset + aatx; + vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[aatx], nsamps, global_ul_ant, flags, 0); + } + return nsamps; + } else { + AssertFatal(nbAnt == 1, "Multi-TX gNB not yet supported in multi-UE no-chanmod mode\n"); + for (int u = 0; u < vrtsim_state->num_ues; u++) { + int rx_offset = vrtsim_state->ue_conf[u].rx_offset; + int num_rx_ant = vrtsim_state->ue_conf[u].rx_ant; + for (int aarx = 0; aarx < num_rx_ant; aarx++) { + int global_dl_ant = rx_offset + aarx; + vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, global_dl_ant, flags, 0); + } + } + return nsamps; + } } static int vrtsim_write_beams(openair0_device_t *device, @@ -665,12 +941,62 @@ static int vrtsim_read(openair0_device_t *device, openair0_timestamp_t *ptimesta } } } - - int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]); - if (ret == CHANNEL_ERROR_TOO_LATE) { - vrtsim_state->rx_samples_late += nsamps; - } else if (ret == CHANNEL_ERROR_TOO_EARLY) { - vrtsim_state->rx_early += 1; + if (vrtsim_state->role == ROLE_SERVER) { + if (vrtsim_state->num_ues > 1) { + /* Multi-UE UL combining */ + if (nsamps > vrtsim_state->ul_combine_buffer_len) { + sample_t *tmp = realloc(vrtsim_state->ul_combine_buffer, nsamps * sizeof(sample_t)); + AssertFatal(tmp != NULL, "Failed to realloc UL combine buffer\n"); + vrtsim_state->ul_combine_buffer = tmp; + vrtsim_state->ul_combine_buffer_len = nsamps; + } + for (int aarx = 0; aarx < nbAnt; aarx++) + memset(samplesVoid[aarx], 0, nsamps * sizeof(sample_t)); + for (int u = 0; u < vrtsim_state->num_ues; u++) { + for (int aarx = 0; aarx < nbAnt; aarx++) { + int stream = u * nbAnt + aarx; + int ret = shm_td_iq_channel_rx(vrtsim_state->channel, + vrtsim_state->last_received_sample, + nsamps, + stream, + vrtsim_state->ul_combine_buffer); + if (ret == CHANNEL_ERROR_TOO_LATE) { + vrtsim_state->rx_samples_late += nsamps; + } else if (ret == CHANNEL_ERROR_TOO_EARLY) { + vrtsim_state->rx_early += 1; + } + int16_t *out = (int16_t *)samplesVoid[aarx]; + int16_t *in = (int16_t *)vrtsim_state->ul_combine_buffer; + for (int i = 0; i < nsamps * 2; i++) { + int32_t sum = (int32_t)out[i] + (int32_t)in[i]; + out[i] = (int16_t)((sum > 32767) ? 32767 : (sum < -32768) ? -32768 : sum); + } + } + } + } else { + /* Single-UE server UL read */ + int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]); + if (ret == CHANNEL_ERROR_TOO_LATE) { + vrtsim_state->rx_samples_late += nsamps; + } else if (ret == CHANNEL_ERROR_TOO_EARLY) { + vrtsim_state->rx_early += 1; + } + for (int aarx = 1; aarx < nbAnt; aarx++) { + if (samplesVoid[aarx] != NULL) + memcpy(samplesVoid[aarx], samplesVoid[0], nsamps * sizeof(sample_t)); + } + } + } else { + for (int aarx = 0; aarx < nbAnt; aarx++) { + int global_dl_ant = vrtsim_state->ue.rx_offset + aarx; + int ret = + shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, global_dl_ant, samplesVoid[aarx]); + if (ret == CHANNEL_ERROR_TOO_LATE) { + vrtsim_state->rx_samples_late += nsamps; + } else if (ret == CHANNEL_ERROR_TOO_EARLY) { + vrtsim_state->rx_early += 1; + } + } } vrtsim_state->rx_samples_total += nsamps; *ptimestamp = vrtsim_state->last_received_sample; @@ -693,6 +1019,9 @@ static void vrtsim_end(openair0_device_t *device) shutdown_actor(&vrtsim_state->channel_modelling_actors[i]); } free(vrtsim_state->channel_modelling_actors); + if (vrtsim_state->use_cirdb && vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + pthread_mutex_destroy(&vrtsim_state->cirdb_mutex); + } for (int i = 1; i < vrtsim_state->peer_info.num_rx_antennas; i++) { histogram_merge(&tx_timing->tx_histogram, &tx_timing[i].tx_histogram); tx_timing->tx_early += tx_timing[i].tx_early; @@ -708,6 +1037,10 @@ static void vrtsim_end(openair0_device_t *device) taps_client_stop(); } } + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->ul_combine_buffer) { + free(vrtsim_state->ul_combine_buffer); + vrtsim_state->ul_combine_buffer = NULL; + } shm_td_iq_channel_abort(vrtsim_state->channel); sleep(1); shm_td_iq_channel_destroy(vrtsim_state->channel); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.132prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.132prb.rfsim.conf new file mode 100644 index 0000000000..446223843e --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.132prb.rfsim.conf @@ -0,0 +1,275 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + CSI_report_type = "ssb_sinr"; + min_rxtxtime = 6; + disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN + absoluteFrequencySSB = 1556256; + dl_frequencyBand = 512; + # This is SSB ARFCN - ((offset RBs accg to controlResourceSetZero + 10 rbs for half of SSB) * 12(num REs) * 8 (raster 120khz/15Khz)) + dl_absoluteFrequencyPointA = 1553952; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 132; + #initialDownlinkBWP + #genericParameters + # This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart + initialDLBWPlocationAndBandwidth = 36025; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + # Value 0 - 2symbols for coreset, 0 Rbs offset, does not work until code changed in nr_rrc_config_dl_tda + # as len_coreset is hard coded to 1 TBD to fix this + # Value 2 - 1 symbol for coreset, 14 rbs offset + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_absoluteFrequencyPointA = 2070987; + ul_frequencyBand = 512; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 132; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 36025; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 71; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -70; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 3; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 3; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; # GEO satellite + ta-Common-r17 = 58629850; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +rlc = { + srb = { + t_poll_retransmit = "ms2000" + } + drb_am = { + t_poll_retransmit = "ms2000" + } +} + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + sl_ahead = 10; + bands = [512]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 60; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal" +} +); + + +rfsimulator = ( +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + prop_delay = 238.74; + IQfile = "/tmp/rfsimulator.iqs"; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="info"; + f1ap_log_level ="info"; +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.32prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.32prb.rfsim.conf new file mode 100644 index 0000000000..7fb33a7a6e --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.32prb.rfsim.conf @@ -0,0 +1,276 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + + CSI_report_type = "ssb_sinr"; + min_rxtxtime = 6; + disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN + absoluteFrequencySSB = 1556256; + dl_frequencyBand = 512; + # This is SSB ARFCN - ((offset RBs accg to controlResourceSetZero + 10 rbs for half of SSB) * 12(num REs) * 8 (raster 120khz/15Khz)) + dl_absoluteFrequencyPointA = 1554496; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 32; + #initialDownlinkBWP + #genericParameters + # This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart + initialDLBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + # Value 0 - 2symbols for coreset, 0 Rbs offset, does not work until code changed in nr_rrc_config_dl_tda + # as len_coreset is hard coded to 1 TBD to fix this + # Value 2 - 1 symbol for coreset, 14 rbs offset + initialDLBWPcontrolResourceSetZero = 1; + initialDLBWPsearchSpaceZero = 2; // to push sib1 into slot other than 0, otherwise RBs are not enough + + #uplinkConfigCommon + #frequencyInfoUL + ul_absoluteFrequencyPointA = 2070833; + ul_frequencyBand = 512; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 32; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 58; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -70; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 3; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 3; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; # GEO satellite + ta-Common-r17 = 58629850; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + + +rlc = { + srb = { + t_poll_retransmit = "ms2000" + } + drb_am = { + t_poll_retransmit = "ms2000" + } +} + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + sl_ahead = 10; + bands = [512]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 60; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal" +} +); + +rfsimulator = ( +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + prop_delay = 238.74; + IQfile = "/tmp/rfsimulator.iqs"; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="info"; + f1ap_log_level ="info"; +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.66prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.66prb.rfsim.conf new file mode 100644 index 0000000000..3fddfd0890 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.66prb.rfsim.conf @@ -0,0 +1,276 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + CSI_report_type = "ssb_sinr"; + min_rxtxtime = 6; + disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + #GSCN + absoluteFrequencySSB = 1558560; + dl_frequencyBand = 512; + # This is SSB ARFCN - ((offset RBs accg to controlResourceSetZero + 10 rbs for half of SSB) * 12(num REs) * 8 (raster 120khz/15Khz)) + dl_absoluteFrequencyPointA = 1556064; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 66; + #initialDownlinkBWP + #genericParameters + # This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart + initialDLBWPlocationAndBandwidth = 17875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + # Value 0 - 2symbols for coreset, 0 Rbs offset, does not work until code changed in nr_rrc_config_dl_tda + # as len_coreset is hard coded to 1 TBD to fix this + # Value 2 - 1 symbol for coreset, 14 rbs offse + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_absoluteFrequencyPointA = 2070833; + ul_frequencyBand = 512; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 66; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 17875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 58; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -70; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 3; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 3; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; # GEO satellite + ta-Common-r17 = 58629850; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + + +rlc = { + srb = { + t_poll_retransmit = "ms2000" + } + drb_am = { + t_poll_retransmit = "ms2000" + } +} + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + sl_ahead = 10; + bands = [512]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 60; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal" +} +); + + +rfsimulator = ( +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + prop_delay = 238.74; + IQfile = "/tmp/rfsimulator.iqs"; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="info"; + f1ap_log_level ="info"; +}; diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index de784a3a16..ee8156343f 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -37,7 +37,7 @@ RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int oai_exit = 0; int gnb_id; int NB_UE_INST = 1;