diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index aabba119ec..7a6999f503 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -455,3 +455,93 @@ l2sim4g_ext_dn: Host: "%%current_host%%" NetworkScript: docker exec l2sim4g-trf-gen ip a show dev eth0 CmdPrefix: docker exec l2sim4g-trf-gen + +rfsim5g_multiue1: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue1 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue1 + AttachScript: docker start rfsim5g-oai-nr-ue + DetachScript: docker stop rfsim5g-oai-nr-ue + MTU: 1500 + +rfsim5g_multiue2: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue2 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue2 + AttachScript: true + DetachScript: true + MTU: 1500 + +rfsim5g_multiue3: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue3 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue3 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue4: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue4 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue4 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue5: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue5 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue5 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue6: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue6 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue6 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue7: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue7 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue7 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue8: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue8 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue8 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue9: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue9 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue9 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 + +rfsim5g_multiue10: + Host: "%%current_host%%" + NetworkScript: docker exec rfsim5g-oai-nr-ue ip a show dev oaitun_ue10 + CmdPrefix: docker exec rfsim5g-oai-nr-ue + IF: oaitun_ue10 + AttachScript: "true" + DetachScript: "true" + MTU: 1500 diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index 7b0d176b3d..643380bd0a 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -112,7 +112,7 @@ gNBs = # 0 = neither, 1= group hopping, 2=sequence hopping pucchGroupHopping = 0; hoppingId = 40; - p0_nominal = -70; + p0_nominal = -80; ssb_PositionsInBurst_Bitmap = 1; @@ -175,7 +175,7 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 180; + pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; } ); @@ -184,7 +184,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; - prach_dtx_threshold = 120; + prach_dtx_threshold = 130; #pucch0_dtx_threshold = 150; } ); @@ -198,7 +198,7 @@ RUs = ( att_rx = 0; bands = [78]; max_pdschReferenceSignalPower = -27; - max_rxgain = 65; + max_rxgain = 75; eNB_instances = [0]; sf_extension = 0 sdr_addrs = "addr=192.168.80.52,clock_source=internal,time_source=internal" diff --git a/ci-scripts/mbim_scripts/stop_quectel_mbim.sh b/ci-scripts/mbim_scripts/stop_quectel_mbim.sh index e7dbbaa43d..5115646b0d 100644 --- a/ci-scripts/mbim_scripts/stop_quectel_mbim.sh +++ b/ci-scripts/mbim_scripts/stop_quectel_mbim.sh @@ -1,3 +1,7 @@ set -x sudo mbimcli -p -d /dev/cdc-wdm0 --set-radio-state=off + +IF=wwan0 +sudo ip link set ${IF} down +sudo ip addr flush dev ${IF} diff --git a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml new file mode 100644 index 0000000000..79d85e154c --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml @@ -0,0 +1,210 @@ + + + rfsim-5gnr-tdd-multiue + Monolithic SA TDD gNB multiue + wrench + + 111111 + 800813 + 000001 + 000002 + 000003 + 000008 + 020001 + 020002 + 020003 + 020004 + 020105 + 444445 + 030001 + 030002 + 444444 + 100001 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb-asan oai-nr-ue + + + Create_Workspace + Create new Workspace + 0 + 0 + + + Deploy_Object + Deploy OAI 5G CoreNetwork + ci-scripts/yaml_files/5g_rfsimulator_multiue + mysql oai-amf oai-smf oai-upf oai-ext-dn + 0 + 0 + + + + Deploy_Object + Deploy OAI 5G gNB RF sim SA + ci-scripts/yaml_files/5g_rfsimulator_multiue + oai-gnb + 0 + 0 + + + + Deploy_Object + Deploy OAI 5G NR-UE RF sim SA + ci-scripts/yaml_files/5g_rfsimulator_multiue + oai-nr-ue + 0 + 0 + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 + acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_multiue1 + acamas + rfsim5g_ext_dn + acamas + -c 20 -i 0.25 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + acamas + rfsim5g_multiue1 + acamas + -c 20 -i 0.25 + 5 + + + + Ping + Ping ext-dn from Second NR-UE + rfsim5g_multiue2 + acamas + rfsim5g_ext_dn + acamas + -c 20 -i 0.25 + 5 + + + + Ping + Ping Second NR-UE from ext-dn + rfsim5g_ext_dn + acamas + rfsim5g_multiue2 + acamas + -c 20 -i 0.25 + 5 + + + + Ping + Ping ext-dn from both UEs + rfsim5g_multiue1 rfsim5g_multiue2 + acamas acamas + rfsim5g_ext_dn + acamas + -c 20 -i 0.25 + 5 + + + + Ping + Ping ext-dn from all UEs + rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 + acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas + rfsim5g_ext_dn + acamas + -c 20 -i 0.25 -s 1016 + 5 + + + + Iperf + Iperf (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 20 -R + rfsim5g_multiue1 + acamas + rfsim5g_ext_dn + acamas + 5 + 90 + + + + Iperf + Iperf (UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 20 + rfsim5g_multiue1 + acamas + rfsim5g_ext_dn + acamas + 5 + 90 + + + + Detach_UE + Detach OAI UEs + rfsim5g_multiue1 + acamas + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + ci-scripts/yaml_files/5g_rfsimulator_multiue + 1,0,0,0 + 1,0,0,0 + 0 + 0 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + 0 + oai-gnb-asan oai-nr-ue + + + diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index 541bde6372..18313d0559 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index 164a9bc0d4..9eec82a98b 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md index 7e0858457c..629d0860fd 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -37,9 +37,9 @@ Now pull images. ```bash $ docker pull mysql:8.0 -$ docker pull oaisoftwarealliance/oai-amf:v2.1.9 -$ docker pull oaisoftwarealliance/oai-smf:v2.1.9 -$ docker pull oaisoftwarealliance/oai-upf:v2.1.9 +$ docker pull oaisoftwarealliance/oai-amf:v2.1.10 +$ docker pull oaisoftwarealliance/oai-smf:v2.1.10 +$ docker pull oaisoftwarealliance/oai-upf:v2.1.10 $ docker pull oaisoftwarealliance/trf-gen-cn5g:focal $ docker pull oaisoftwarealliance/oai-gnb:develop @@ -52,7 +52,7 @@ $ docker logout **CAUTION: 2023/01/27 with the release `v1.5.0` of the `CN5G`, the previous version was not compatible any-more.** -**This new version is working only with the `v2.1.9` of the `CN5G`.** +**This new version is working only with `v2.1.9` or later of the `CN5G`.** # 2. Deploy containers # diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index d531b15270..ecdf79872b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 7b09c4a955..9cab11ea9e 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index ba7b9a86f4..778754fd58 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 53fa6a8181..9ccce2a8e1 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index aa0b9a6ca3..13d91d9090 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml new file mode 100644 index 0000000000..d0b76fc165 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml @@ -0,0 +1,146 @@ +services: + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.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 + 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:focal + entrypoint: /bin/bash -c \ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-upf + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + oai-gnb: + image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 + depends_on: + - oai-ext-dn + networks: + public_net: + ipv4_address: 192.168.71.140 + volumes: + - ../../conf_files/gnb.sa.band78.106prb.rfsim.yaml:/opt/oai-gnb/etc/gnb.yaml + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + oai-nr-ue: + image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time --num-ues 10 + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ./nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf b/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf new file mode 100644 index 0000000000..92ccf9dca2 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf @@ -0,0 +1,75 @@ +uicc0 = { + imsi = "208990100001100"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc1 = { + imsi = "208990100001101"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc2 = { + imsi = "208990100001102"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc3 = { + imsi = "208990100001103"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc4 = { + imsi = "208990100001104"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc5 = { + imsi = "208990100001105"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc6 = { + imsi = "208990100001106"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc7 = { + imsi = "208990100001107"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc8 = { + imsi = "208990100001108"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} +uicc9 = { + imsi = "208990100001109"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + dnn= "oai"; + nssai_sst=1; +} + + + +thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index f127fdc3b0..c83060b713 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml index a0c44153cd..5469b0b247 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml @@ -23,7 +23,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -35,7 +35,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -47,7 +47,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 environment: - TZ=Europe/Paris volumes: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index a1b873eb96..ed1701ef86 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -24,7 +24,7 @@ services: ipv4_address: 192.168.71.131 oai-amf: container_name: "rfsim5g-oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - TZ=Europe/paris volumes: @@ -36,7 +36,7 @@ services: ipv4_address: 192.168.71.132 oai-smf: container_name: "rfsim5g-oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - TZ=Europe/Paris volumes: @@ -48,7 +48,7 @@ services: ipv4_address: 192.168.71.133 oai-upf: container_name: "rfsim5g-oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + image: oaisoftwarealliance/oai-upf:v2.1.10 init: true environment: - TZ=Europe/Paris diff --git a/common/utils/T/.gitignore b/common/utils/T/.gitignore index 60264a9c4a..7ac6cc75bd 100644 --- a/common/utils/T/.gitignore +++ b/common/utils/T/.gitignore @@ -3,6 +3,7 @@ genids tracer/enb tracer/gnb +tracer/gnb_mac tracer/extract_config tracer/record tracer/replay diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 813226ec14..8dd5052714 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -92,9 +92,13 @@ ID = UE_PHY_INITIATE_RA_PROCEDURE GROUP = ALL:PHY:UE:WIRESHARK FORMAT = int,frame : int,subframe_or_slot : int,preamble : int,power ID = GNB_PHY_DL_TICK - DESC = gNodeB downlink tick - one tick per ms at start of downlink processing + DESC = gNodeB downlink tick - one tick per slot at start of downlink processing GROUP = ALL:PHY:GRAPHIC:GNB - FORMAT = int,gNB_ID : int,frame : int,subframe + FORMAT = int,gNB_ID : int,frame : int,slot +ID = GNB_PHY_UL_TICK + DESC = gNodeB uplink tick - one tick per slot at start of uplink processing + GROUP = ALL:PHY:GRAPHIC:GNB + FORMAT = int,gNB_ID : int,frame : int,slot ID = ENB_PHY_MIB DESC = MIB data GROUP = ALL:PHY:ENB:WIRESHARK @@ -221,6 +225,22 @@ ID = NRUE_MAC_DL_RAR_PDU_WITH_DATA DESC = NR MAC downlink PDU for RAR GROUP = ALL:MAC:UE:WIRESHARK FORMAT = int,rnti : int,frame : int,slot : buffer,data +ID = GNB_MAC_DL + DESC = NR MAC downlink scheduler decision for an UE + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,mcs : int,tbs +ID = GNB_MAC_LCID_DL + DESC = NR MAC downlink scheduler decision for an UE for a specific LCID + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,lcid : int,data_size : int,tx_list_occupancy +ID = GNB_MAC_UL + DESC = NR MAC uplink scheduler decision for an UE + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,mcs : int,tbs +ID = GNB_MAC_LCID_UL + DESC = NR MAC uplink traffic received for an UE for a specific LCID + GROUP = ALL:MAC:GNB + FORMAT = int,rnti : int,frame : int,slot : int,lcid : int,data_size #RLC logs ID = ENB_RLC_DL diff --git a/common/utils/T/tracer/CMakeLists.txt b/common/utils/T/tracer/CMakeLists.txt index e1c79ffdf6..56568c905e 100644 --- a/common/utils/T/tracer/CMakeLists.txt +++ b/common/utils/T/tracer/CMakeLists.txt @@ -62,9 +62,13 @@ if(T_TRACER_GUI) tracer_logger tracer_view tracer_events) target_link_libraries(gnb PRIVATE png) - add_executable(ue ue.c) - target_link_libraries(ue PRIVATE tracer_utils tracer_filter tracer_gui + add_executable(gnb_mac gnb_mac.c) + target_link_libraries(gnb_mac PRIVATE tracer_utils tracer_filter tracer_gui tracer_logger tracer_view tracer_events) + + add_executable(ue ue.c) + target_link_libraries(ue PRIVATE tracer_utils tracer_view tracer_gui + tracer_logger tracer_filter tracer_events) target_link_libraries(ue PRIVATE png) add_executable(vcd vcd.c) @@ -77,5 +81,5 @@ if(T_TRACER_GUI) add_subdirectory(gui) - add_dependencies(T_tools enb gnb ue vcd to_vcd) + add_dependencies(T_tools enb gnb gnb_mac ue vcd to_vcd) endif() diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 6777be7152..ce99eabbe8 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -8,7 +8,7 @@ XLIBS=-lX11 -lpng -lXft all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ extract_input_subframe extract_output_subframe to_vcd extract multi \ - gnb t_tracer_app_gnb t_tracer_app_ue + gnb t_tracer_app_gnb t_tracer_app_ue gnb_mac record: utils.o record.o database.o configuration.o $(CC) $(CFLAGS) -o record $^ $(LIBS) @@ -65,14 +65,18 @@ gnb: utils.o gnb.o database.o event.o handler.o configuration.o \ filter/filter.a $(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS) -t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o configuration.o \ - logger/logger.a filter/filter.a +t_tracer_app_gnb: utils.o t_tracer_app_gnb.o database.o event.o handler.o \ + configuration.o logger/logger.a filter/filter.a $(CC) $(CFLAGS) -o t_tracer_app_gnb $^ $(LIBS) $(XLIBS) -t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o configuration.o \ - logger/logger.a filter/filter.a +t_tracer_app_ue: utils.o t_tracer_app_ue.o database.o event.o handler.o \ + configuration.o logger/logger.a filter/filter.a $(CC) $(CFLAGS) -o t_tracer_app_ue $^ $(LIBS) $(XLIBS) +gnb_mac: gnb_mac.o gui/gui.a view/view.a logger/logger.a filter/filter.a \ + utils.o database.o configuration.o handler.o event.o + $(CC) $(CFLAGS) -o gnb_mac $^ $(LIBS) $(XLIBS) + multi.o: ../incgen/T_IDs.h ../incgen/T_IDs.h: ../T_messages.txt @@ -98,7 +102,8 @@ filter/filter.a: clean: rm -f *.o core tracer_remote textlog enb ue vcd record replay rm -f extract_config macpdu2wireshark extract_input_subframe - rm -f extract_output_subframe to_vcd extract multi gnb t_tracer_app_gnb t_tracer_app_ue + rm -f extract_output_subframe to_vcd extract multi gnb + rm -f t_tracer_app_gnb t_tracer_app_ue gnb_mac cd gui && $(MAKE) clean cd view && $(MAKE) clean cd logger && $(MAKE) clean diff --git a/common/utils/T/tracer/enb.c b/common/utils/T/tracer/enb.c index 5bb1cb87e2..f48f8e7dd7 100644 --- a/common/utils/T/tracer/enb.c +++ b/common/utils/T/tracer/enb.c @@ -340,12 +340,12 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -10, 80); l = new_ttilog(h, database, "ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "threshold", 0); - v = new_view_tti(10, g, w, new_color(g, "#ff0000")); + v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10); logger_add_view(l, v); e->pucch1_energy_ue_threshold_logger = l; l = new_ttilog(h, database, "ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "energy", 1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->pucch1_energy_ue_energy_logger = l; @@ -368,7 +368,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", "ENB_PHY_DLSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->dl_mcs_logger = l; @@ -379,7 +379,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", "ENB_PHY_ULSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->ul_mcs_logger = l; @@ -394,8 +394,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, col, w, -1); container_set_child_growable(g, col, w, 1); l = new_throughputlog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", - "ENB_PHY_DLSCH_UE_DCI", "TBS"); - v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2); + "ENB_PHY_DLSCH_UE_DCI", "TBS", 10); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 10); logger_add_view(l, v); /* UE x UL PHY (truly: DCI) throughput */ @@ -409,8 +409,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, col, w, -1); container_set_child_growable(g, col, w, 1); l = new_throughputlog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe", - "ENB_PHY_ULSCH_UE_DCI", "TBS"); - v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2); + "ENB_PHY_ULSCH_UE_DCI", "TBS", 10); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 10); logger_add_view(l, v); /* downlink/uplink UE DCIs */ diff --git a/common/utils/T/tracer/gnb_mac.c b/common/utils/T/tracer/gnb_mac.c new file mode 100644 index 0000000000..84f29b8f82 --- /dev/null +++ b/common/utils/T/tracer/gnb_mac.c @@ -0,0 +1,332 @@ +#include +#include +#include +#include + +#include "utils.h" +#include "gui/gui.h" +#include "view/view.h" +#include "logger/logger.h" +#include "filter/filter.h" +#include "database.h" +#include "configuration.h" +#include "handler.h" + +typedef struct { + int used; +} ue_list_item; + +typedef struct { + widget *container; +} gnb_gui; + +typedef struct { + int socket; + gui *g; + gnb_gui *gg; + event_handler *h; + void *database; + ue_list_item ues[65536]; + int rnti_arg; +} gnb_data; + +void *gui_thread(void *_g) +{ + gui *g = _g; + gui_loop(g); + return 0; +} + +void add_ue(gnb_data *gd, int rnti, int lcid) +{ + event_handler *h = gd->h; + void *database = gd->database; + gnb_gui *gg = gd->gg; + gui *g = gd->g; + widget *line; + widget *w, *w2, *col; + view *v; + logger *l; + + gd->ues[rnti].used = 1; + + line = new_container(g, HORIZONTAL); + widget_add_child(g, gg->container, line, -1); + + /* label */ + char s[512]; + sprintf(s, "UE %d", rnti); + widget *label = new_label(g, s); + widget_add_child(g, line, label, -1); + + /* DL MCS */ + w = new_xy_plot(g, 128, 55, "DL mcs", 20); + xy_plot_set_range(g, w, 0, 1024*20, -2, 30); + widget_add_child(g, line, w, -1); + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_DL", "mcs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_DL", "rnti"), + filter_int(rnti))); + + /* DL TBS */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + w = new_xy_plot(g, 70, 10, "DL tbs", 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1024*20, 0, 1000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_DL", "tbs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + view_tti_enable_automax(v, w2); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_DL", "rnti"), + filter_int(rnti))); + + /* DL lcid throughput */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + sprintf(s, "DL lcid %d", lcid); + w = new_xy_plot(g, 70, 10, s, 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1000, 0, 100000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_throughputlog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_LCID_DL", "data_size", 20); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_and( + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"), + filter_int(rnti)), + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"), + filter_int(lcid)))); + + /* UL MCS */ + w = new_xy_plot(g, 128, 55, "UL mcs", 20); + xy_plot_set_range(g, w, 0, 1024*20, -2, 30); + widget_add_child(g, line, w, -1); + /* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */ + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_UL", "mcs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_UL", "rnti"), + filter_int(rnti))); + + /* UL TBS */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + w = new_xy_plot(g, 70, 10, "UL tbs", 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1024*20, 0, 1000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + /* GNB_PHY_DL_TICK (and not UL) because GNB_MAC_UL is from DCI */ + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_UL", "tbs", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + view_tti_enable_automax(v, w2); + logger_add_view(l, v); + logger_set_filter(l, + filter_eq( + filter_evarg(database, "GNB_MAC_UL", "rnti"), + filter_int(rnti))); + + /* UL lcid throughput */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + sprintf(s, "UL lcid %d", lcid); + w = new_xy_plot(g, 70, 10, s, 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1000, 0, 100000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_throughputlog(h, database, "GNB_PHY_UL_TICK", "frame", "slot", + "GNB_MAC_LCID_UL", "data_size", 20); + v = new_view_scrolltti(10, g, w, new_color(g, "#0c0c72"), w2, 20); + logger_add_view(l, v); + logger_set_filter(l, + filter_and( + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_UL", "rnti"), + filter_int(rnti)), + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_UL", "lcid"), + filter_int(lcid)))); + + /* lcid RLC tx buffer occupancy */ + col = new_container(g, VERTICAL); + widget_add_child(g, line, col, -1); + sprintf(s, "rlc tx %d", lcid); + w = new_xy_plot(g, 70, 10, s, 35); + w2 = new_textarea(g, 70, 11, 64); + xy_plot_set_range(g, w, 0, 1024*20, 0, 1000); + xy_plot_set_tick_type(g, w, XY_PLOT_SCROLL_TICK); + widget_add_child(g, col, w2, -1); + widget_add_child(g, col, w, -1); + container_set_child_growable(g, col, w, 1); + l = new_ticked_ttilog(h, database, "GNB_PHY_DL_TICK", "frame", "slot", + "GNB_MAC_LCID_DL", "tx_list_occupancy", 0, -1); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 20); + view_tti_enable_automax(v, w2); + logger_add_view(l, v); + logger_set_filter(l, + filter_and( + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "rnti"), + filter_int(rnti)), + filter_eq( + filter_evarg(database, "GNB_MAC_LCID_DL", "lcid"), + filter_int(lcid)))); +} + +void build_gui(gnb_gui *gg, gui *g) +{ + widget *main_window; + + main_window = new_toplevel_window(g, 900, 1000, "gNB MAC tracer"); + gg->container = new_container(g, VERTICAL); + widget_add_child(g, main_window, gg->container, -1); +} + +void usage(void) +{ + printf( +"options:\n" +" -d this option is mandatory\n" +" -ip connect to given IP address (default %s)\n" +" -p connect to given port (default %d)\n", + DEFAULT_REMOTE_IP, + DEFAULT_REMOTE_PORT + ); + exit(1); +} + +void check_new_ue(void *_gd, event e) +{ + gnb_data *gd = _gd; + int rnti = e.e[gd->rnti_arg].i; + if (!gd->ues[rnti].used) + add_ue(gd, rnti, 4); +} + +int main(int n, char **v) +{ + gui *g; + gnb_gui gg; + gnb_data *gd; + char *database_filename = NULL; + void *database; + char *ip = DEFAULT_REMOTE_IP; + int port = DEFAULT_REMOTE_PORT; + event_handler *h; + int *is_on; + int number_of_events; + int i; + + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); + if (!strcmp(v[i], "-d")) { if (i > n-2) usage(); database_filename = v[++i]; continue; } + if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; } + if (!strcmp(v[i], "-p")) { if (i > n-2) usage(); port = atoi(v[++i]); continue; } + usage(); + } + + if (database_filename == NULL) { + printf("ERROR: provide a database file (-d)\n"); + exit(1); + } + + database = parse_database(database_filename); + + load_config_file(database_filename); + + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) abort(); + + on_off(database, "GNB_PHY_DL_TICK", is_on, 1); + on_off(database, "GNB_MAC_DL", is_on, 1); + on_off(database, "GNB_MAC_LCID_DL", is_on, 1); + on_off(database, "GNB_PHY_UL_TICK", is_on, 1); + on_off(database, "GNB_MAC_UL", is_on, 1); + on_off(database, "GNB_MAC_LCID_UL", is_on, 1); + + gd = calloc(1, sizeof(*gd)); if (!gd) abort(); + + h = new_handler(database); + + g = gui_init(); + new_thread(gui_thread, g); + + build_gui(&gg, g); + + gd->g = g; + gd->gg = ≫ + gd->h = h; + gd->database = database; + + /* get rnti_arg from event GNB_MAC_DL */ + int event_id = event_id_from_name(database, "GNB_MAC_DL"); + database_event_format f = get_format(database, event_id); + gd->rnti_arg = -1; + for (i = 0; i < f.count; i++) { + if (!strcmp(f.name[i], "rnti")) gd->rnti_arg = i; + } + if (gd->rnti_arg == -1) { + printf("fatal: event 'GNB_MAC_DL' does not have argument 'rnti'\n"); + exit(1); + } + if (strcmp(f.type[gd->rnti_arg], "int") != 0) { + printf("fatal: argument 'rnti' of event 'GNB_MAC_DL' is not 'int'\n"); + exit(1); + } + + register_handler_function(h, event_id, check_new_ue, gd); + + OBUF ebuf = {.osize = 0, .omaxsize = 0, .obuf = NULL}; + + gd->socket = -1; + +restart: + clear_remote_config(); + if (gd->socket != -1) close(gd->socket); + gd->socket = connect_to(ip, port); + + /* send the first message - activate selected traces */ + int t = 1; + if (socket_send(gd->socket, &t, 1) == -1 || + socket_send(gd->socket, &number_of_events, sizeof(int)) == -1 || + socket_send(gd->socket, is_on, number_of_events * sizeof(int)) == -1) + goto restart; + + while (1) { + event e; + e = get_event(gd->socket, &ebuf, database); + if (e.type == -1) goto restart; + handle_event(h, e); + } + + return 0; +} diff --git a/common/utils/T/tracer/gui/gui.h b/common/utils/T/tracer/gui/gui.h index 0fb96db325..b2fce32cff 100644 --- a/common/utils/T/tracer/gui/gui.h +++ b/common/utils/T/tracer/gui/gui.h @@ -54,6 +54,8 @@ void container_set_child_growable(gui *_gui, widget *_this, int xy_plot_new_plot(gui *gui, widget *this, int color); void xy_plot_set_range(gui *gui, widget *this, float xmin, float xmax, float ymin, float ymax); +void xy_plot_get_range(gui *gui, widget *this, + float *xmin, float *xmax, float *ymin, float *ymax); void xy_plot_set_points(gui *gui, widget *this, int plot, int npoints, float *x, float *y); void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height); diff --git a/common/utils/T/tracer/gui/xy_plot.c b/common/utils/T/tracer/gui/xy_plot.c index c10b76c6ee..cc198475c2 100644 --- a/common/utils/T/tracer/gui/xy_plot.c +++ b/common/utils/T/tracer/gui/xy_plot.c @@ -280,6 +280,22 @@ void xy_plot_set_range(gui *_gui, widget *_this, gunlock(g); } +void xy_plot_get_range(gui *_gui, widget *_this, + float *xmin, float *xmax, float *ymin, float *ymax) +{ + struct gui *g = _gui; + struct xy_plot_widget *this = _this; + + glock(g); + + *xmin = this->xmin; + *xmax = this->xmax; + *ymin = this->ymin; + *ymax = this->ymax; + + gunlock(g); +} + void xy_plot_set_points(gui *_gui, widget *_this, int plot, int npoints, float *x, float *y) { diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index d746161e70..b78fa1b359 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -15,8 +15,8 @@ logger *new_ticked_ttilog(void *event_handler, void *database, char *event_name, char *data_varname, int convert_to_dB, float empty_value); logger *new_throughputlog(void *event_handler, void *database, - char *tick_event_name, char *frame_varname, char *subframe_varname, - char *event_name, char *data_varname); + char *tick_event_name, char *frame_varname, char *tick_varname, + char *event_name, char *data_varname, int ticks_per_frame); logger *new_timelog(void *event_handler, void *database, char *event_name); logger *new_ticklog(void *event_handler, void *database, char *event_name, char *frame_name, char *subframe_name); diff --git a/common/utils/T/tracer/logger/throughputlog.c b/common/utils/T/tracer/logger/throughputlog.c index 8a2d46da91..5f066df343 100644 --- a/common/utils/T/tracer/logger/throughputlog.c +++ b/common/utils/T/tracer/logger/throughputlog.c @@ -13,13 +13,14 @@ struct throughputlog { struct logger common; void *database; int tick_frame_arg; - int tick_subframe_arg; + int tick_tick_arg; int data_frame_arg; - int data_subframe_arg; + int data_tick_arg; int data_arg; int last_tick_frame; - int last_tick_subframe; - unsigned long bits[1000]; + int last_tick_tick; + int ticks_per_frame; + unsigned long *bits; unsigned long total; int insert_point; char *tick_event_name; @@ -32,16 +33,16 @@ static void _event(void *p, event e) { struct throughputlog *l = p; int frame; - int subframe; + int tick; unsigned long value; if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0) return; frame = e.e[l->data_frame_arg].i; - subframe = e.e[l->data_subframe_arg].i; + tick = e.e[l->data_tick_arg].i; - if (frame != l->last_tick_frame || subframe != l->last_tick_subframe) { + if (frame != l->last_tick_frame || tick != l->last_tick_tick) { printf("WARNING: %s:%d: data comes without previous tick!\n", __FILE__, __LINE__); return; @@ -62,28 +63,34 @@ static void _tick_event(void *p, event e) struct throughputlog *l = p; int i; int frame; - int subframe; + int tick; if (l->tick_filter != NULL && filter_eval(l->tick_filter, e) == 0) return; frame = e.e[l->tick_frame_arg].i; - subframe = e.e[l->tick_subframe_arg].i; + tick = e.e[l->tick_tick_arg].i; for (i = 0; i < l->common.vsize; i++) - l->common.v[i]->append(l->common.v[i], frame, subframe, (double)l->total); + l->common.v[i]->append(l->common.v[i], frame, tick, (double)l->total); - l->insert_point = (l->insert_point + 1) % 1000; - l->total -= l->bits[l->insert_point]; - l->bits[l->insert_point] = 0; + while (l->last_tick_frame != frame || l->last_tick_tick != tick) { + l->insert_point = (l->insert_point + 1) % (100 * l->ticks_per_frame); + l->total -= l->bits[l->insert_point]; + l->bits[l->insert_point] = 0; + l->last_tick_tick++; + if (l->last_tick_tick == l->ticks_per_frame) { + l->last_tick_tick = 0; + l->last_tick_frame++; + l->last_tick_frame %= 1024; + } + } - l->last_tick_frame = frame; - l->last_tick_subframe = subframe; } logger *new_throughputlog(event_handler *h, void *database, - char *tick_event_name, char *frame_varname, char *subframe_varname, - char *event_name, char *data_varname) + char *tick_event_name, char *frame_varname, char *tick_varname, + char *event_name, char *data_varname, int ticks_per_frame) { struct throughputlog *ret; int event_id; @@ -106,21 +113,21 @@ logger *new_throughputlog(event_handler *h, void *database, f = get_format(database, event_id); - /* look for frame and subframe */ + /* look for frame and tick */ ret->tick_frame_arg = -1; - ret->tick_subframe_arg = -1; + ret->tick_tick_arg = -1; for (i = 0; i < f.count; i++) { if (!strcmp(f.name[i], frame_varname)) ret->tick_frame_arg = i; - if (!strcmp(f.name[i], subframe_varname)) ret->tick_subframe_arg = i; + if (!strcmp(f.name[i], tick_varname)) ret->tick_tick_arg = i; } if (ret->tick_frame_arg == -1) { printf("%s:%d: frame argument '%s' not found in event '%s'\n", __FILE__, __LINE__, frame_varname, event_name); abort(); } - if (ret->tick_subframe_arg == -1) { - printf("%s:%d: subframe argument '%s' not found in event '%s'\n", - __FILE__, __LINE__, subframe_varname, event_name); + if (ret->tick_tick_arg == -1) { + printf("%s:%d: tick argument '%s' not found in event '%s'\n", + __FILE__, __LINE__, tick_varname, event_name); abort(); } if (strcmp(f.type[ret->tick_frame_arg], "int") != 0) { @@ -128,9 +135,9 @@ logger *new_throughputlog(event_handler *h, void *database, __FILE__, __LINE__, frame_varname); abort(); } - if (strcmp(f.type[ret->tick_subframe_arg], "int") != 0) { + if (strcmp(f.type[ret->tick_tick_arg], "int") != 0) { printf("%s:%d: argument '%s' has wrong type (should be 'int')\n", - __FILE__, __LINE__, subframe_varname); + __FILE__, __LINE__, tick_varname); abort(); } @@ -141,13 +148,13 @@ logger *new_throughputlog(event_handler *h, void *database, f = get_format(database, event_id); - /* look for frame, subframe and data args */ + /* look for frame, tick and data args */ ret->data_frame_arg = -1; - ret->data_subframe_arg = -1; + ret->data_tick_arg = -1; ret->data_arg = -1; for (i = 0; i < f.count; i++) { if (!strcmp(f.name[i], frame_varname)) ret->data_frame_arg = i; - if (!strcmp(f.name[i], subframe_varname)) ret->data_subframe_arg = i; + if (!strcmp(f.name[i], tick_varname)) ret->data_tick_arg = i; if (!strcmp(f.name[i], data_varname)) ret->data_arg = i; } if (ret->data_frame_arg == -1) { @@ -155,9 +162,9 @@ logger *new_throughputlog(event_handler *h, void *database, __FILE__, __LINE__, frame_varname, event_name); abort(); } - if (ret->data_subframe_arg == -1) { - printf("%s:%d: subframe argument '%s' not found in event '%s'\n", - __FILE__, __LINE__, subframe_varname, event_name); + if (ret->data_tick_arg == -1) { + printf("%s:%d: tick argument '%s' not found in event '%s'\n", + __FILE__, __LINE__, tick_varname, event_name); abort(); } if (ret->data_arg == -1) { @@ -170,9 +177,9 @@ logger *new_throughputlog(event_handler *h, void *database, __FILE__, __LINE__, frame_varname); abort(); } - if (strcmp(f.type[ret->data_subframe_arg], "int") != 0) { + if (strcmp(f.type[ret->data_tick_arg], "int") != 0) { printf("%s:%d: argument '%s' has wrong type (should be 'int')\n", - __FILE__, __LINE__, subframe_varname); + __FILE__, __LINE__, tick_varname); abort(); } if (strcmp(f.type[ret->data_arg], "int") != 0 && @@ -183,6 +190,10 @@ logger *new_throughputlog(event_handler *h, void *database, abort(); } + ret->ticks_per_frame = ticks_per_frame; + ret->bits = calloc(100 * ticks_per_frame, sizeof(unsigned long)); + if (ret->bits == NULL) abort(); + return ret; } diff --git a/common/utils/T/tracer/ue.c b/common/utils/T/tracer/ue.c index b28f83b0f2..f4ea38f980 100644 --- a/common/utils/T/tracer/ue.c +++ b/common/utils/T/tracer/ue.c @@ -250,15 +250,15 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 1024*10, -130, 35); /*l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "rssi", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#720c0c")); + v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10); logger_add_view(l, v); e->phy_meas_logger = l;*/ l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "rsrp", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->phy_meas_logger = l; l = new_ticked_ttilog(h, database,"UE_PHY_DL_TICK", "frame", "subframe","UE_PHY_MEAS", "snr", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c720c")); + v = new_view_tti(10, g, w, new_color(g, "#0c720c"), 10); logger_add_view(l, v); e->phy_meas_logger = l; @@ -277,7 +277,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "UE_PHY_DL_TICK", "frame", "subframe", "UE_PHY_DLSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->dl_mcs_logger = l; @@ -288,7 +288,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, w, -1); l = new_ticked_ttilog(h, database, "UE_PHY_DL_TICK", "frame", "subframe", "UE_PHY_ULSCH_UE_DCI", "mcs", 0, -1); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->ul_mcs_logger = l; @@ -301,12 +301,12 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -30, 50); l = new_ttilog(h, database, "UE_PHY_PUSCH_TX_POWER", "frame", "subframe", "p0_pusch", 0); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->pusch_power_logger = l; l = new_ttilog(h, database, "UE_PHY_PUSCH_TX_POWER", "frame", "subframe", "ampl", 1); - v = new_view_tti(10, g, w, new_color(g, "#720c0c")); + v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10); logger_add_view(l, v); e->pusch_ampl_logger = l; @@ -319,12 +319,12 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -30, 50); l = new_ttilog(h, database, "UE_PHY_PUCCH_TX_POWER", "frame", "subframe", "p0_pucch", 0); - v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); + v = new_view_tti(10, g, w, new_color(g, "#0c0c72"), 10); logger_add_view(l, v); e->pucch_power_logger = l; l = new_ttilog(h, database, "UE_PHY_PUCCH_TX_POWER", "frame", "subframe", "ampl", 1); - v = new_view_tti(10, g, w, new_color(g, "#720c0c")); + v = new_view_tti(10, g, w, new_color(g, "#720c0c"), 10); logger_add_view(l, v); e->pucch_ampl_logger = l; @@ -335,22 +335,22 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -10, 80); l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level00", 1); - v = new_view_tti(10, g, w, new_color(g, "#ff0000")); + v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level01", 1); - v = new_view_tti(10, g, w, new_color(g, "#00ff00")); + v = new_view_tti(10, g, w, new_color(g, "#00ff00"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level10", 1); - v = new_view_tti(10, g, w, new_color(g, "#0f0f0f")); + v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level11", 1); - v = new_view_tti(10, g, w, new_color(g, "#0000ff")); + v = new_view_tti(10, g, w, new_color(g, "#0000ff"), 10); logger_add_view(l, v); e->pdsch_energy_logger = l; @@ -361,22 +361,22 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, xy_plot_set_range(g, w, 0, 1024*10, -10, 80); l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level00", 1); - v = new_view_tti(10, g, w, new_color(g, "#ff0000")); + v = new_view_tti(10, g, w, new_color(g, "#ff0000"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level01", 1); - v = new_view_tti(10, g, w, new_color(g, "#00ff00")); + v = new_view_tti(10, g, w, new_color(g, "#00ff00"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level10", 1); - v = new_view_tti(10, g, w, new_color(g, "#0f0f0f")); + v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; l = new_ttilog(h, database, "UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level11", 1); - v = new_view_tti(10, g, w, new_color(g, "#0000ff")); + v = new_view_tti(10, g, w, new_color(g, "#0000ff"), 10); logger_add_view(l, v); e->pdcch_energy_logger = l; diff --git a/common/utils/T/tracer/view/scrolltti.c b/common/utils/T/tracer/view/scrolltti.c index ad83cbc756..3bf1c93bd2 100644 --- a/common/utils/T/tracer/view/scrolltti.c +++ b/common/utils/T/tracer/view/scrolltti.c @@ -15,11 +15,14 @@ struct scrolltti { int plot; float refresh_rate; pthread_mutex_t lock; - unsigned long data[1000]; - unsigned long total; /* sum data[0..999] to have smoother value printed */ - float xout[1000]; - float yout[1000]; + int ticks_per_frame; + unsigned long *data; + unsigned long total; /* sum data[0..n] to have smoother value printed */ + float *xout; + float *yout; int insert_point; + int next_tick_frame; + int next_tick_tick; }; /* this array is used to get Y range 1000, 2000, 5000, 10000, ... */ @@ -38,21 +41,21 @@ static void *scrolltti_thread(void *_this) /* TODO: optimize */ p = this->insert_point; max = 0; - for (i = 0; i < 1000; i++) { + for (i = 0; i < this->ticks_per_frame * 100; i++) { this->xout[i] = i; this->yout[i] = this->data[p]; if (this->data[p] > max) max = this->data[p]; - p = (p + 1) % 1000; + p = (p + 1) % (this->ticks_per_frame * 100); } - bps(o, this->total/1000., "b/s"); + bps(o, this->total/(this->ticks_per_frame * 100.), "b/s"); textarea_set_text(this->g, this->throughput_textarea, o); /* for Y range we want 1000, 2000, 5000, 10000, 20000, 50000, etc. */ if (max < 1000) max = 1000; mlog = pow(10, floor(log10(max))); max = tolog[(int)ceil(max/mlog)] * mlog; - xy_plot_set_range(this->g, this->w, 0, 1000, 0, max); + xy_plot_set_range(this->g, this->w, 0, this->ticks_per_frame * 100, 0, max); xy_plot_set_points(this->g, this->w, this->plot, - 1000, this->xout, this->yout); + this->ticks_per_frame * 100, this->xout, this->yout); if (pthread_mutex_unlock(&this->lock)) abort(); sleepms(1000/this->refresh_rate); } @@ -65,20 +68,40 @@ static void clear(view *this) /* TODO */ } -static void append(view *_this, int frame, int subframe, double value) +static void insert(struct scrolltti *this, double value) +{ + this->total -= this->data[this->insert_point]; + this->data[this->insert_point] = value; + this->total += this->data[this->insert_point]; + this->insert_point = (this->insert_point + 1) % (this->ticks_per_frame * 100); +} + +static void next_tick(struct scrolltti *this) +{ + this->next_tick_tick++; + if (this->next_tick_tick == this->ticks_per_frame) { + this->next_tick_tick = 0; + this->next_tick_frame++; + this->next_tick_frame %= 1024; + } +} + +static void append(view *_this, int frame, int tick, double value) { struct scrolltti *this = (struct scrolltti *)_this; if (pthread_mutex_lock(&this->lock)) abort(); - this->total -= this->data[this->insert_point]; - this->data[this->insert_point] = value; - this->total += this->data[this->insert_point]; - this->insert_point = (this->insert_point + 1) % 1000; + while (this->next_tick_frame != frame || this->next_tick_tick != tick) { + insert(this, 0); + next_tick(this); + } + insert(this, value); + next_tick(this); if (pthread_mutex_unlock(&this->lock)) abort(); } view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color, - widget *throughput_textarea) + widget *throughput_textarea, int ticks_per_frame) { struct scrolltti *ret = calloc(1, sizeof(struct scrolltti)); if (ret == NULL) abort(); @@ -92,6 +115,14 @@ view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color, ret->throughput_textarea = throughput_textarea; ret->plot = xy_plot_new_plot(g, w, color); + ret->ticks_per_frame = ticks_per_frame; + ret->data = calloc(ticks_per_frame * 100, sizeof(unsigned long)); + if (ret->data == NULL) abort(); + ret->xout = calloc(ticks_per_frame * 100, sizeof(float)); + if (ret->xout == NULL) abort(); + ret->yout = calloc(ticks_per_frame * 100, sizeof(float)); + if (ret->yout == NULL) abort(); + if (pthread_mutex_init(&ret->lock, NULL)) abort(); new_thread(scrolltti_thread, ret); diff --git a/common/utils/T/tracer/view/tti.c b/common/utils/T/tracer/view/tti.c index ebf9fc657c..73d43b539b 100644 --- a/common/utils/T/tracer/view/tti.c +++ b/common/utils/T/tracer/view/tti.c @@ -5,31 +5,36 @@ #include #include #include +#include struct tti { view common; gui *g; widget *w; + int automax; + widget *w2; int plot; float refresh_rate; pthread_mutex_t lock; - float data[1024*10]; - int valid[1024*10]; - float xout[1024*10]; - float yout[1024*10]; + float *data; + int *valid; + float *xout; + float *yout; int last_insert_point; + int ticks_per_frame; }; -static int far_enough(int i, int last_insert, int plot_width) +static int far_enough(int i, int last_insert, int plot_width, + int ticks_per_frame) { int p1; int p2; int hole_size_px; int hole_size_tti; hole_size_px = 10; - hole_size_tti = 10240 * hole_size_px / plot_width; + hole_size_tti = 1024 * ticks_per_frame * hole_size_px / plot_width; p1 = last_insert; - p2 = (last_insert + hole_size_tti) % (1024*10); + p2 = (last_insert + hole_size_tti) % (1024 * ticks_per_frame); if (p1 < p2) { return !(i > p1 && i < p2); } @@ -48,15 +53,31 @@ static void *tti_thread(void *_this) if (pthread_mutex_lock(&this->lock)) abort(); xy_plot_get_dimensions(this->g, this->w, &plot_width, &plot_height); length = 0; + double max = 0; /* TODO: optimize */ - for (i = 0; i < 1024*10; i++) + for (i = 0; i < 1024 * this->ticks_per_frame; i++) /* do not take points too close after last insertion point */ if (this->valid[i] && - far_enough(i, this->last_insert_point, plot_width)) { + far_enough(i, this->last_insert_point, plot_width, + this->ticks_per_frame)) { this->xout[length] = i; this->yout[length] = this->data[i]; + if (this->data[i] > max) max = this->data[i]; length++; } + if (this->automax) { + char o[128]; + sprintf(o, "%d", (int)max); + textarea_set_text(this->g, this->w2, o); + /* for Y range we want 10, 20, 50, 100, 200, 500, etc. */ + if (max < 10) max = 10; + double mlog = pow(10, floor(log10(max))); + static int tolog[11] = { -1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10 }; + max = tolog[(int)ceil(max/mlog)] * mlog; + float xmin, xmax, ymin, ymax; + xy_plot_get_range(this->g, this->w, &xmin, &xmax, &ymin, &ymax); + xy_plot_set_range(this->g, this->w, xmin, xmax, 0, max); + } xy_plot_set_points(this->g, this->w, this->plot, length, this->xout, this->yout); if (pthread_mutex_unlock(&this->lock)) abort(); @@ -71,11 +92,11 @@ static void clear(view *this) /* TODO */ } -static void append(view *_this, int frame, int subframe, double value) +static void append(view *_this, int frame, int tick, double value) { struct tti *this = (struct tti *)_this; int i; - int index = frame * 10 + subframe; + int index = frame * this->ticks_per_frame + tick; if (pthread_mutex_lock(&this->lock)) abort(); @@ -84,10 +105,10 @@ static void append(view *_this, int frame, int subframe, double value) * this may be wrong if delay between two append is * greater than 1024 frames (something like that) */ - i = (this->last_insert_point + 1) % (1024*10); + i = (this->last_insert_point + 1) % (1024 * this->ticks_per_frame); while (i != index) { this->valid[i] = 0; - i = (i + 1) % (1024*10); + i = (i + 1) % (1024 * this->ticks_per_frame); } this->data[index] = value; @@ -98,7 +119,8 @@ static void append(view *_this, int frame, int subframe, double value) if (pthread_mutex_unlock(&this->lock)) abort(); } -view *new_view_tti(float refresh_rate, gui *g, widget *w, int color) +view *new_view_tti(float refresh_rate, gui *g, widget *w, int color, + int ticks_per_frame) { struct tti *ret = calloc(1, sizeof(struct tti)); if (ret == NULL) abort(); @@ -115,7 +137,24 @@ view *new_view_tti(float refresh_rate, gui *g, widget *w, int color) if (pthread_mutex_init(&ret->lock, NULL)) abort(); + ret->ticks_per_frame = ticks_per_frame; + ret->data = calloc(ticks_per_frame * 1024, sizeof(float)); + if (ret->data == NULL) abort(); + ret->valid = calloc(ticks_per_frame * 1024, sizeof(int)); + if (ret->valid == NULL) abort(); + ret->xout = calloc(ticks_per_frame * 1024, sizeof(float)); + if (ret->xout == NULL) abort(); + ret->yout = calloc(ticks_per_frame * 1024, sizeof(float)); + if (ret->yout == NULL) abort(); + new_thread(tti_thread, ret); return (view *)ret; } + +void view_tti_enable_automax(view *_tti, widget *w2) +{ + struct tti *tti = (struct tti *)_tti; + tti->automax = 1; + tti->w2 = w2; +} diff --git a/common/utils/T/tracer/view/view.h b/common/utils/T/tracer/view/view.h index 8167a00ccd..bc37e654d1 100644 --- a/common/utils/T/tracer/view/view.h +++ b/common/utils/T/tracer/view/view.h @@ -17,15 +17,16 @@ view *new_view_stdout(void); view *new_view_textlist(int maxsize, float refresh_rate, gui *g, widget *w); view *new_view_xy(int length, float refresh_rate, gui *g, widget *w, int color, enum xy_mode mode); -view *new_view_tti(float refresh_rate, gui *g, widget *w, - int color); +view *new_view_tti(float refresh_rate, gui *g, widget *w, int color, + int ticks_per_frame); view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, - int color, widget *throughput_label); + int color, widget *throughput_label, int ticks_per_frame); view *new_view_time(int number_of_seconds, float refresh_rate, gui *g, widget *w); view *new_subview_time(view *time, int line, int color, int size); view *new_view_ticktime(float refresh_rate, gui *g, widget *w); view *new_subview_ticktime(view *ticktime, int line, int color, int size); void ticktime_set_tick(view *ticktime, void *logger); +void view_tti_enable_automax(view *tti, widget *w2); #endif /* _VIEW_H_ */ diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 7954db7d54..265b680500 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1465,13 +1465,13 @@ frequency_range_t get_freq_range_from_band(uint16_t band) return band <= 256 ? FR1 : FR2; } -float get_beta_dmrs_pusch(int num_cdm_groups_no_data, pusch_dmrs_type_t dmrs_type) +float get_beta_dmrs(int num_cdm_groups_no_data, bool is_type2) { float beta_dmrs_pusch = 1.0; if (num_cdm_groups_no_data == 2) { beta_dmrs_pusch = powf(10.0, 3.0 / 20.0); } else if (num_cdm_groups_no_data == 3) { - if (dmrs_type == pusch_dmrs_type2) + if (is_type2) beta_dmrs_pusch = powf(10.0, 4.77 / 20.0); } return beta_dmrs_pusch; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 752d500c1b..6ab3f58dab 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -320,15 +320,15 @@ frequency_range_t get_freq_range_from_arfcn(uint32_t arfcn); frequency_range_t get_freq_range_from_band(uint16_t band); /** - * @brief Calculates the scaling factor for the ratio of PUSCH EPRE to DMRS EPRE. + * @brief Calculates the scaling factor for the ratio of PUSCH/PDSCH EPRE to DMRS EPRE. * * @param num_cdm_groups_no_data The number of CDM groups without data. - * @param dmrs_type The DMRS type. - * @return The calculated beta scaling factor for the ratio of PUSCH EPRE to DMRS EPRE. + * @param is_type2 true if calculating for DMRS configuration type 2 + * @return The calculated beta scaling factor for the ratio of PUSCH/PDSCH EPRE to DMRS EPRE. * - * @note The values are derived from TS 38.214 Table 6.2.2-1. + * @note The values are the same for PUSCH and PDSCH and are derived from TS 38.214 Table 6.2.2-1./4.1-1 */ -float get_beta_dmrs_pusch(int num_cdm_groups_no_data, pusch_dmrs_type_t dmrs_type); +float get_beta_dmrs(int num_cdm_groups_no_data, bool is_type2); #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index 5f190edc02..1a740adbe2 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -62,7 +62,7 @@ add_dependencies(telnetsrv telnetsrv_ci) message(STATUS "Add CI specific telnet functions for nrUE in telnetsrv_ciUE.so") add_library(telnetsrv_ciUE MODULE telnetsrv_ciUE.c) -target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) +target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) add_dependencies(telnetsrv telnetsrv_ciUE) message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so") diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index 7aff02f9df..1d7169f29f 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -1235,7 +1235,13 @@ You should be able to connect a UE now. # OAI Management Plane -We support Configuration Management in OAI gNB, where gNB configures CU-planes, interfaces, TX/RX antennas, and TX/RX carriers for the RU. +In OAI gNB, we support: +* Configuration Management: interface(s) creation, configuration of RU CU-planes, Tx/Rx antennas, and Tx/Rx carriers. +* Performance Management: activation/deactivation of available RU performance measurements and its notification reception with 10s periodicity: +```bash +[HW] [MPLANE] [PM: "192.168.80.9"][RX_ON_TIME 773428][RX_EARLY 0][RX_LATE 0][RX_TOTAL 878881][RX_ON_TIME_C 104744][RX_EARLY_C 0][RX_LATE_C 0][TX_TOTAL 435922] +``` + The reference specifications: * `O-RAN.WG4.MP.0-v05.00` * `O-RAN.WG4.MP-YANGs-v04.00` @@ -1375,7 +1381,7 @@ Once the mplane service is successfully enabled on the RU, two new users are bei oranbenetel:x:1000:1000::/home/oranbenetel:/bin/sh oranext:x:1001:1001::/home/oranext:/bin/sh ``` -Create `oranbenetel` home directory: +OAI gNB requires the `sudo` access group for NETCONF session. In the case of Benetel O-RUs, the corresponding user is `oranbenetel`. Therefore, please create its home directory: ```bash mkdir /home/oranbenetel && chown oranbenetel:oranbenetel /home/oranbenetel ``` @@ -1393,7 +1399,7 @@ The reference gNB configuration file for one Benetel RAN550: The reference DU configuration file for two Benetel RAN650: [gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf) -In order to run gNB/DU with M-plane, we need to modify the `fhi_72` section in the configuration file. +In order to run gNB/DU with M-plane, we need to modify Tx gain `att_tx` in RU section, as well as the `fhi_72` section in the configuration file. Example for one RU: ```bash fhi_72 = { @@ -1404,6 +1410,7 @@ fhi_72 = { du_key_pair = ("/.ssh/id_rsa.pub", "/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67"); # only one needed if one VF configured vlan_tag = (9, 9); # only one needed if one VF configured + ru_username = ("oranbenetel"); ru_ip_addr = ("192.168.80.9"); fh_config = ({ T1a_cp_dl = (419, 470); @@ -1423,6 +1430,7 @@ fhi_72 = { du_key_pair = ("/home/oaicicd/.ssh/id_rsa.pub", "/home/oaicicd/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67", "00:11:22:33:44:68", "00:11:22:33:44:69"); # only two needed if two VFs configured vlan_tag = (9, 9, 11, 11); # only two needed if two VFs configured + ru_username = ("oranbenetel", "oranbenetel"); ru_ip_addr = ("192.168.80.9", "192.168.80.10"); fh_config = ( # RAN550 #1 @@ -1451,6 +1459,7 @@ fhi_72 = { * `du_key_pair`: ssh public and private keys to authenticate RU with NETCONF * `du_addr`: DU MAC address(es) to create CU-plane interface(s) in the RU * `vlan_tag`: VLAN U and C plane tags to create CU-plane interface(s) in the RU + * `ru_username`: Username with `sudo` access to connect to the RU via M-plane * `ru_ip_addr`: RU IP address to connect to the RU via M-plane * `dpdk_mem_size`: [*] * `dpdk_iova_mode`: [*] @@ -1557,7 +1566,9 @@ sequenceDiagram note over du: DU configures xran - du->ru: 12. DU and RU exchange packets + du->ru: 12. DU activates Performance Measurements + + du->ru: 13. DU and RU exchange packets ``` @@ -1596,7 +1607,9 @@ sequenceDiagram Band sector ID 0 CC ID 0 RU port ID 0 + max Tx gain 24.0 [HW] [MPLANE] Successfully retrieved all the U-plane info - interface name, TX/RX carrier names, and TX/RX endpoint names. +[HW] [MPLANE] Successfully retreived all performance measurement names. [HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-yang-metadata". [HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "yang". [HW] [MPLANE] RPC request to RU "192.168.80.9" = for module "ietf-inet-types". @@ -1636,6 +1649,59 @@ sequenceDiagram 9 + + 10 + 10 + 10 + + RX_ON_TIME + false + RU + COUNT + + + RX_EARLY + false + RU + COUNT + + + RX_LATE + false + RU + COUNT + + + RX_TOTAL + false + RU + COUNT + + + RX_ON_TIME_C + false + RU + COUNT + + + RX_EARLY_C + false + RU + COUNT + + + RX_LATE_C + false + RU + COUNT + + + TX_TOTAL + false + RU + COUNT + + ETH-INTERFACE @@ -1729,8 +1795,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1746,8 +1814,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1763,8 +1833,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1780,8 +1852,10 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 61440 @@ -1797,9 +1871,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1807,6 +1887,7 @@ sequenceDiagram 15 0 + true LowLevelRxPrachEndpoint0 @@ -1814,9 +1895,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1824,6 +1911,7 @@ sequenceDiagram 15 4 + true LowLevelRxEndpoint1 @@ -1831,9 +1919,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1841,6 +1935,7 @@ sequenceDiagram 15 1 + true LowLevelRxPrachEndpoint1 @@ -1848,9 +1943,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1858,6 +1959,7 @@ sequenceDiagram 15 5 + true LowLevelRxEndpoint2 @@ -1865,9 +1967,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1875,6 +1983,7 @@ sequenceDiagram 15 2 + true LowLevelRxPrachEndpoint2 @@ -1882,9 +1991,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1892,6 +2007,7 @@ sequenceDiagram 15 6 + true LowLevelRxEndpoint3 @@ -1899,9 +2015,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1909,6 +2031,7 @@ sequenceDiagram 15 3 + true LowLevelRxPrachEndpoint3 @@ -1916,9 +2039,15 @@ sequenceDiagram 9 STATIC - 0 - 0 + 193 + NORMAL + 352 + 288 0 + + KHZ_30 + 0 + 61440 3840 @@ -1926,6 +2055,7 @@ sequenceDiagram 15 7 + true TxArray0 @@ -1933,7 +2063,7 @@ sequenceDiagram 3950400000 100000000 ACTIVE - 0.0 + 24.0 0 0 @@ -1957,7 +2087,7 @@ sequenceDiagram [HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.80.9". [HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore. [HW] [MPLANE] RPC reply = OK. -[HW] [MPLANE] Successfully commited CU-planes configuration into running datastore for RU "192.168.80.9". +[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.80.9". [HW] [MPLANE] Usage state = "idle" for RU "192.168.80.9". [HW] [MPLANE] Received notification from RU "192.168.80.9" at (2025-03-29T12:40:23.049085102+00:00) { @@ -2025,9 +2155,71 @@ sequenceDiagram "operation": "create" }, ... -} - [HW] [MPLANE] RU "192.168.80.9" is now ready. +[HW] [MPLANE] RPC request to RU "192.168.80.9" = : + + 10 + 10 + 10 + + RX_ON_TIME + true + RU + COUNT + + + RX_EARLY + true + RU + COUNT + + + RX_LATE + true + RU + COUNT + + + RX_TOTAL + true + RU + COUNT + + + RX_ON_TIME_C + true + RU + COUNT + + + RX_EARLY_C + true + RU + COUNT + + + RX_LATE_C + true + RU + COUNT + + + TX_TOTAL + true + RU + COUNT + + + +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully edited the candidate datastore for RU "192.168.80.9". +[HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.80.9". +[HW] [MPLANE] RPC request to RU "192.168.80.9" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.80.9". +[HW] [MPLANE] Sucessfully activated PM after start-up procedure for RU "192.168.80.9". ``` diff --git a/doc/nfapi.md b/doc/nfapi.md index 73aaf2e770..214aa2799f 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -171,7 +171,7 @@ After installing WLS, you can run the build command as shown below: #### How to run OAI PNF with OAI VNF -Refer to the above steps in [Quickstart](.#quickstart), but run the PNF first as it is the WLS "master". +Refer to the above steps in [Quickstart](#quickstart), but run the PNF first as it is the WLS "master". #### How to run OAI PNF with OSC/Radisys O-DU diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 24870544b8..1021aba1ce 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -174,6 +174,8 @@ static void rx_func(processingData_L1_t *info) int slot_rx = info->slot_rx; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; + T(T_GNB_PHY_UL_TICK, T_INT(gNB->Mod_id), T_INT(frame_rx), T_INT(slot_rx)); + // RX processing int rx_slot_type = nr_slot_select(cfg, frame_rx, slot_rx); if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { diff --git a/executables/nr-ru.c b/executables/nr-ru.c index de3a4b7875..20deff5725 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -878,11 +878,12 @@ static void fill_rf_config(RU_t *ru, char *rf_config_file) } } -static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_request_scf_t *config, int slots_per_frame, uint16_t ofdm_symbol_size) +static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_request_scf_t *config, const NR_DL_FRAME_PARMS *fp) { const nfapi_nr_prach_config_t *prach_config = &config->prach_config; const nfapi_nr_tdd_table_t *tdd_table = &config->tdd_table; const nfapi_nr_cell_config_t *cell_config = &config->cell_config; + const nfapi_nr_carrier_config_t *carrier_config = &config->carrier_config; DevAssert(prach_config->prach_ConfigurationIndex.tl.tag == NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG); split7->prach_index = prach_config->prach_ConfigurationIndex.value; @@ -893,7 +894,7 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_ if (cell_config->frame_duplex_type.value == 1 /* TDD */) { DevAssert(tdd_table->tdd_period.tl.tag == NFAPI_NR_CONFIG_TDD_PERIOD_TAG); int nb_periods_per_frame = get_nb_periods_per_frame(tdd_table->tdd_period.value); - split7->n_tdd_period = slots_per_frame / nb_periods_per_frame; + split7->n_tdd_period = fp->slots_per_frame / nb_periods_per_frame; for (int slot = 0; slot < split7->n_tdd_period; ++slot) { for (int sym = 0; sym < 14; ++sym) { split7->slot_dirs[slot].sym_dir[sym] = tdd_table->max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[sym].slot_config.value; @@ -901,7 +902,15 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_ } } - split7->fftSize = log2(ofdm_symbol_size); + split7->fftSize = log2(fp->ofdm_symbol_size); + + // M-plane related parameters + for (size_t i = 0; i < 5 ; i++) { + split7->dl_k0[i] = carrier_config->dl_k0[i].value; + split7->ul_k0[i] = carrier_config->ul_k0[i].value; + } + split7->cp_prefix0 = fp->nb_prefix_samples0; + split7->cp_prefix_other = fp->nb_prefix_samples; } /* this function maps the RU tx and rx buffers to the available rf chains. @@ -1044,7 +1053,7 @@ void *ru_thread(void *param) nr_dump_frame_parms(fp); nr_phy_init_RU(ru); fill_rf_config(ru, ru->rf_config_file); - fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp->slots_per_frame, fp->ofdm_symbol_size); + fill_split7_2_config(&ru->openair0_cfg.split7, &ru->config, fp); // Start IF device if any if (ru->nr_start_if) { diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 61823d43cd..8541135bb6 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -126,7 +126,6 @@ extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int oai_exit; -extern openair0_config_t openair0_cfg[MAX_CARDS]; extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; extern int sync_var; diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 0e5a308259..588465133b 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -414,7 +414,7 @@ static void UE_synch(void *arg) { syncData_t *syncD = (syncData_t *)arg; PHY_VARS_NR_UE *UE = syncD->UE; UE->is_synchronized = 0; - openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card]; + openair0_config_t *cfg0 = &UE->openair0_cfg[UE->rf_map.card]; if (UE->target_Nid_cell != -1) { LOG_W(NR_PHY, "Starting re-sync detection for target Nid_cell %i\n", UE->target_Nid_cell); @@ -523,7 +523,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx radio_tx_burst_flag_t flags = TX_BURST_INVALID; if (UE->received_config_request) { - if (openair0_cfg[0].duplex_mode == duplex_mode_FDD || get_softmodem_params()->continuous_tx) { + if (UE->openair0_cfg[0].duplex_mode == duplex_mode_FDD || get_softmodem_params()->continuous_tx) { flags = TX_BURST_MIDDLE; // In case of Sidelink, USRP write needed only in case transmission // needs to be done in this slot and not based on tdd ULDL configuration. @@ -696,8 +696,8 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) { fp->dl_CarrierFreq = dl_CarrierFreq; fp->ul_CarrierFreq = ul_CarrierFreq; - nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); - UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]); + nr_rf_card_config_freq(&UE->openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); + UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &UE->openair0_cfg[UE->rf_map.card]); init_symbol_rotation(fp); } @@ -731,12 +731,14 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; // process what RRC thread sent to MAC - MessageDef *msg = NULL; do { - itti_poll_msg(TASK_MAC_UE, &msg); - if (msg) - process_msg_rcc_to_mac(msg); - } while (msg); + notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&get_mac_inst(UE->Mod_id)->input_nf); + if (!elt) { + break; + } + process_msg_rcc_to_mac(NotifiedFifoData(elt), UE->Mod_id); + delNotifiedFIFO_elt(elt); + } while (true); if (UE->if_inst) UE->if_inst->slot_indication(UE->Mod_id, false); @@ -966,7 +968,7 @@ void *UE_thread(void *arg) void *rxp[NB_ANTENNAS_RX]; enum stream_status_e stream_status = STREAM_STATUS_UNSYNC; fapi_nr_config_request_t *cfg = &UE->nrUE_config; - int tmp = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]); + int tmp = openair0_device_load(&(UE->rfdevice), &UE->openair0_cfg[0]); AssertFatal(tmp == 0, "Could not load the device\n"); NR_DL_FRAME_PARMS *fp = &UE->frame_parms; sl_nr_phy_config_request_t *sl_cfg = NULL; @@ -1032,12 +1034,10 @@ void *UE_thread(void *arg) decoded_frame_rx = UE->SL_UE_PHY_PARAMS.sync_params.DFN; else { // We must wait the RRC layer decoded the MIB and sent us the frame number - MessageDef *msg = NULL; - itti_receive_msg(TASK_MAC_UE, &msg); - if (msg) - process_msg_rcc_to_mac(msg); - else - LOG_E(PHY, "It seems we arbort while trying to sync\n"); + notifiedFIFO_elt_t *elt = pullNotifiedFIFO(&mac->input_nf); + AssertFatal(elt != NULL, "fifo error while waiting for MIB"); + process_msg_rcc_to_mac(NotifiedFifoData(elt), UE->Mod_id); + delNotifiedFIFO_elt(elt); decoded_frame_rx = mac->mib_frame; } LOG_A(PHY, @@ -1284,20 +1284,19 @@ void *UE_thread(void *arg) void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconfig_file) { - NR_UE_RRC_INST_t *rrc_inst = nr_rrc_init_ue(uecap_file, nb_inst, get_nrUE_params()->nb_antennas_tx); - NR_UE_MAC_INST_t *mac_inst = nr_l2_init_ue(nb_inst); - AssertFatal(mac_inst, "Couldn't allocate MAC module\n"); + for (int instance_id = 0; instance_id < nb_inst; instance_id++) { + NR_UE_RRC_INST_t* rrc = nr_rrc_init_ue(uecap_file, instance_id, get_nrUE_params()->nb_antennas_tx); + NR_UE_MAC_INST_t *mac = nr_l2_init_ue(instance_id); - for (int i = 0; i < nb_inst; i++) { - NR_UE_MAC_INST_t *mac = get_mac_inst(i); - mac->if_module = nr_ue_if_module_init(i); + nr_rrc_set_mac_queue(instance_id, &mac->input_nf); + mac->if_module = nr_ue_if_module_init(instance_id); AssertFatal(mac->if_module, "can not initialize IF module\n"); if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) { - init_nsa_message(&rrc_inst[i], reconfig_file, rbconfig_file); - nr_rlc_activate_srb0(mac_inst[i].crnti, NULL, send_srb0_rrc); + init_nsa_message(rrc, reconfig_file, rbconfig_file); + nr_rlc_activate_srb0(mac->crnti, NULL, send_srb0_rrc); } //TODO: Move this call to RRC - start_sidelink((&rrc_inst[i])->ue_id); + start_sidelink(instance_id); } } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 8b331e4976..ac7b23382f 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -121,8 +121,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t sidelink_frequency[MAX_NUM_CCs][4]; // UE and OAI config variables - -openair0_config_t openair0_cfg[MAX_CARDS]; int16_t node_synch_ref[MAX_NUM_CCs]; int otg_enabled; double cpuf; @@ -249,41 +247,42 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ } -static void init_openair0() +void init_openair0(PHY_VARS_NR_UE *ue) { int card; int freq_off = 0; - NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; bool is_sidelink = (get_softmodem_params()->sl_mode) ? true : false; if (is_sidelink) - frame_parms = &PHY_vars_UE_g[0][0]->SL_UE_PHY_PARAMS.sl_frame_params; + frame_parms = &ue->SL_UE_PHY_PARAMS.sl_frame_params; for (card=0; cardopenair0_cfg[card]; uint64_t dl_carrier, ul_carrier; - openair0_cfg[card].configFilename = NULL; - openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; - openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame; + cfg->configFilename = NULL; + cfg->sample_rate = frame_parms->samples_per_subframe * 1e3; + cfg->samples_per_frame = frame_parms->samples_per_frame; if (frame_parms->frame_type==TDD) - openair0_cfg[card].duplex_mode = duplex_mode_TDD; + cfg->duplex_mode = duplex_mode_TDD; else - openair0_cfg[card].duplex_mode = duplex_mode_FDD; + cfg->duplex_mode = duplex_mode_FDD; - openair0_cfg[card].Mod_id = 0; - openair0_cfg[card].num_rb_dl = frame_parms->N_RB_DL; - openair0_cfg[card].clock_source = get_softmodem_params()->clock_source; - openair0_cfg[card].time_source = get_softmodem_params()->timing_source; - openair0_cfg[card].tune_offset = get_softmodem_params()->tune_offset; - openair0_cfg[card].tx_num_channels = min(4, frame_parms->nb_antennas_tx); - openair0_cfg[card].rx_num_channels = min(4, frame_parms->nb_antennas_rx); + cfg->Mod_id = 0; + cfg->num_rb_dl = frame_parms->N_RB_DL; + cfg->clock_source = get_softmodem_params()->clock_source; + cfg->time_source = get_softmodem_params()->timing_source; + cfg->tune_offset = get_softmodem_params()->tune_offset; + cfg->tx_num_channels = min(4, frame_parms->nb_antennas_tx); + cfg->rx_num_channels = min(4, frame_parms->nb_antennas_rx); LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", card, - openair0_cfg[card].sample_rate, - openair0_cfg[card].tx_num_channels, - openair0_cfg[card].rx_num_channels, - duplex_mode_txt[openair0_cfg[card].duplex_mode]); + cfg->sample_rate, + cfg->tx_num_channels, + cfg->rx_num_channels, + duplex_mode_txt[cfg->duplex_mode]); if (is_sidelink) { dl_carrier = frame_parms->dl_CarrierFreq; @@ -291,16 +290,18 @@ static void init_openair0() } else nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier); - nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off); + nr_rf_card_config_freq(cfg, ul_carrier, dl_carrier, freq_off); - nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off); + nr_rf_card_config_gain(cfg, rx_gain_off); - openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; - - if (get_nrUE_params()->usrp_args) openair0_cfg[card].sdr_addrs = get_nrUE_params()->usrp_args; - if (get_nrUE_params()->tx_subdev) openair0_cfg[card].tx_subdev = get_nrUE_params()->tx_subdev; - if (get_nrUE_params()->rx_subdev) openair0_cfg[card].rx_subdev = get_nrUE_params()->rx_subdev; + cfg->configFilename = get_softmodem_params()->rf_config_file; + if (get_nrUE_params()->usrp_args) + cfg->sdr_addrs = get_nrUE_params()->usrp_args; + if (get_nrUE_params()->tx_subdev) + cfg->tx_subdev = get_nrUE_params()->tx_subdev; + if (get_nrUE_params()->rx_subdev) + cfg->rx_subdev = get_nrUE_params()->rx_subdev; } } @@ -326,9 +327,11 @@ static void trigger_stop(int sig) static void trigger_deregistration(int sig) { if (!stop_immediately && IS_SA_MODE(get_softmodem_params())) { - MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_DEREGISTRATION_REQ); - NAS_DEREGISTRATION_REQ(msg).cause = AS_DETACH; - itti_send_msg_to_task(TASK_NAS_NRUE, 0, msg); + for (int ue_inst = 0; ue_inst < NB_UE_INST; ue_inst++) { + MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, ue_inst, NAS_DEREGISTRATION_REQ); + NAS_DEREGISTRATION_REQ(msg).cause = AS_DETACH; + itti_send_msg_to_task(TASK_NAS_NRUE, ue_inst, msg); + } stop_immediately = true; static const char m[] = "Press ^C again to trigger immediate shutdown\n"; __attribute__((unused)) int unused = write(STDOUT_FILENO, m, sizeof(m) - 1); @@ -386,7 +389,6 @@ int main(int argc, char **argv) } //set_softmodem_sighandler(); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); - memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS); memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); // initialize logging logInit(); @@ -425,12 +427,11 @@ int main(int argc, char **argv) char *pckg = strdup(OAI_PACKAGE_VERSION); LOG_I(HW, "Version: %s\n", pckg); - PHY_vars_UE_g = malloc(sizeof(*PHY_vars_UE_g) * NB_UE_INST); + PHY_vars_UE_g = calloc_or_fail(NB_UE_INST, sizeof(*PHY_vars_UE_g)); for (int inst = 0; inst < NB_UE_INST; inst++) { - PHY_vars_UE_g[inst] = malloc(sizeof(*PHY_vars_UE_g[inst]) * MAX_NUM_CCs); + PHY_vars_UE_g[inst] = calloc_or_fail(MAX_NUM_CCs, sizeof(*PHY_vars_UE_g[inst])); for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - PHY_vars_UE_g[inst][CC_id] = malloc(sizeof(*PHY_vars_UE_g[inst][CC_id])); - memset(PHY_vars_UE_g[inst][CC_id], 0, sizeof(*PHY_vars_UE_g[inst][CC_id])); + PHY_vars_UE_g[inst][CC_id] = calloc_or_fail(1, sizeof(*PHY_vars_UE_g[inst][CC_id])); // All instances use the same coding interface PHY_vars_UE_g[inst][CC_id]->nrLDPC_coding_interface = nrLDPC_coding_interface; } @@ -498,12 +499,14 @@ int main(int argc, char **argv) get_softmodem_params()->numerology, nr_band); } else { - MessageDef *msg = NULL; - do { - itti_poll_msg(TASK_MAC_UE, &msg); - if (msg) - process_msg_rcc_to_mac(msg); - } while (msg); + do { + notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&mac->input_nf); + if (!elt) { + break; + } + process_msg_rcc_to_mac(NotifiedFifoData(elt), inst); + delNotifiedFIFO_elt(elt); + } while (true); fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band); } @@ -538,10 +541,10 @@ int main(int argc, char **argv) get_nrUE_params()->ofdm_offset_divisor); sl_ue_phy_init(UE[CC_id]); } + init_openair0(UE[CC_id]); } } - init_openair0(); lock_memory_to_ram(); if (IS_SOFTMODEM_DOSCOPE) { diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index e5f2eb6571..3ceb3e479e 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -5,6 +5,7 @@ #include "common/utils/threadPool/thread-pool.h" #include "PHY/defs_nr_UE.h" +#define MAX_NUM_NR_UE_INST 32 extern int NB_UE_INST; extern uint16_t ue_id_g; diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c index fa0ed1bd8f..befd2c9dd3 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7.c @@ -2308,7 +2308,7 @@ uint8_t unpack_nr_srs_report_tlv_value(nfapi_srs_report_tlv_t *report_tlv, uint8 } } #else - const uint16_t last_idx = ((report_tlv->length + 3) / 4) - 1; + const int16_t last_idx = ((report_tlv->length + 3) / 4) - 1; for (int i = 0; i < last_idx; i++) { if (!pull32(ppReadPackedMsg, &report_tlv->value[i], end)) { return 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 383140ba88..3b644ba4d3 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -499,8 +499,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, pusch_pdu->scid, Ns, symbol); - pusch_dmrs_type_t dmrs_type = pusch_pdu->dmrs_config_type == NFAPI_NR_DMRS_TYPE1 ? pusch_dmrs_type1 : pusch_dmrs_type2; - float beta_dmrs_pusch = get_beta_dmrs_pusch(pusch_pdu->num_dmrs_cdm_grps_no_data, dmrs_type); + float beta_dmrs_pusch = get_beta_dmrs(pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dmrs_config_type == pusch_dmrs_type2); int16_t dmrs_scaling = (1 / beta_dmrs_pusch) * (1 << 14); nr_pusch_dmrs_rx(gNB, Ns, diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index e929fc5f3e..7fd703ea30 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -117,7 +117,8 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned short p, unsigned char lp, unsigned short nb_pdsch_rb, - uint8_t config_type) + uint8_t config_type, + int16_t dmrs_scaling) { typedef int array_of_w[2]; const array_of_w *wf = (config_type == NFAPI_NR_DMRS_TYPE1) ? wf1 : wf2; @@ -131,6 +132,7 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, for (int i = 0; i < nb_pdsch_rb * ((config_type == NFAPI_NR_DMRS_TYPE1) ? 6 : 4); i++) { int w = (wf[p - 1000][i & 1]) * (wt[p - 1000][lp]); output[i] = get_modulated(nr_gold_pdsch, i, w == 1); + output[i] = c16mulRealShift(output[i], dmrs_scaling, 14); #ifdef DEBUG_PDSCH printf("nr_pdsch_dmrs_rx dmrs config type %d port %d nb_pdsch_rb %d\n", config_type, p, nb_pdsch_rb); diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 7df105d05c..1d2d4b87ae 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -49,7 +49,8 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned short p, unsigned char lp, unsigned short nb_pdsch_rb, - uint8_t config_type); + uint8_t config_type, + int16_t dmrs_scaling); void sl_generate_pss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint8_t n_sl_id2, uint16_t scaling); void sl_generate_pss_ifft_samples(sl_nr_ue_phy_params_t *sl_ue_params, SL_NR_UE_INIT_PARAMS_t *sl_init_params); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 0e186a3bc3..8703c1c774 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -19,6 +19,7 @@ * contact@openairinterface.org */ +#include "nr_common.h" #include #include "SCHED_NR_UE/defs.h" #include "nr_estimation.h" @@ -448,12 +449,15 @@ int nr_prs_channel_estimation(uint8_t gNB_id, peak_estimator(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size, &prs_toa, &ch_pwr, mean_val); // adjusting the rx_gains for channel peak power - ch_pwr_dbm = 10 * log10(ch_pwr) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(frame_params->ofdm_symbol_size); + ch_pwr_dbm = 10 * log10(ch_pwr) + 30 - SQ15_SQUARED_NORM_FACTOR_DB + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) + - dB_fixed(frame_params->ofdm_symbol_size); - prs_meas[rxAnt]->rsrp_dBm = - 10 * log10(prs_meas[rxAnt]->rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + prs_meas[rxAnt]->rsrp_dBm = 10 * log10(prs_meas[rxAnt]->rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) + - dB_fixed(ue->frame_parms.ofdm_symbol_size); - //prs measurements + // prs measurements prs_meas[rxAnt]->gNB_id = gNB_id; prs_meas[rxAnt]->sfn = proc->frame_rx; prs_meas[rxAnt]->slot = proc->nr_slot_rx; @@ -1258,6 +1262,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short scrambling_id, unsigned short BWPStart, uint8_t config_type, + int n_dmrs_cdm_groups, uint16_t rb_offset, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch, @@ -1291,8 +1296,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pilot[3280] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS + float beta_dmrs_pdsch = get_beta_dmrs(n_dmrs_cdm_groups, config_type == NFAPI_NR_DMRS_TYPE2); + int16_t dmrs_scaling = (int16_t)((1 / beta_dmrs_pdsch) * (1 << 14)); const uint32_t *gold = nr_gold_pdsch(fp->N_RB_DL, fp->symbols_per_slot, scrambling_id, nscid, slot, symbol); - nr_pdsch_dmrs_rx(ue, slot, gold, pilot, 1000 + p, 0, nb_rb_pdsch + rb_offset, config_type); + nr_pdsch_dmrs_rx(ue, slot, gold, pilot, 1000 + p, 0, nb_rb_pdsch + rb_offset, config_type, dmrs_scaling); delay_t delay = {0}; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index da6fd31eb5..b327327113 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -87,6 +87,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short scrambling_id, unsigned short BWPStart, uint8_t config_type, + int n_dmrs_cdm_groups, uint16_t rb_offset, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch, @@ -151,6 +152,7 @@ float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index); int nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params, NR_DL_FRAME_PARMS *fp, c16_t rxdataF[][fp->samples_per_slot_wCP], - bool use_SSS); + bool use_SSS, + openair0_config_t *openair0_cfg); /** @}*/ #endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index b6aeba7f76..fcf5484ed7 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -157,7 +157,9 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, ue->measurements.rx_power_avg_dB[gNB_id] = dB_fixed( ue->measurements.rx_power_avg[gNB_id]); ue->measurements.wideband_cqi_tot[gNB_id] = ue->measurements.rx_power_tot_dB[gNB_id] - ue->measurements.n0_power_tot_dB; ue->measurements.wideband_cqi_avg[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] - dB_fixed(ue->measurements.n0_power_avg); - ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - SQ15_SQUARED_NORM_FACTOR_DB + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) + - dB_fixed(ue->frame_parms.ofdm_symbol_size); LOG_D(PHY, "[gNB %d] Slot %d, RSSI %d dB (%d dBm/RE), WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n", gNB_id, @@ -235,7 +237,7 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, uint32_t rsrp_avg = nr_ue_calculate_ssb_rsrp(fp, proc, rxdataF, symbol_offset, fp->ssb_start_subcarrier); float rsrp_db_per_re = 10 * log10(rsrp_avg); - openair0_config_t *cfg0 = &openair0_cfg[0]; + openair0_config_t *cfg0 = &ue->openair0_cfg[0]; ue->measurements.ssb_rsrp_dBm[ssb_index] = rsrp_db_per_re + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)cfg0->rx_gain[0] - (int)cfg0->rx_gain_offset[0]) @@ -271,8 +273,8 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, const uint8_t k_length = 8; uint8_t l_sss = (ue->symbol_offset + 2) % ue->frame_parms.symbols_per_slot; unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; - double rx_gain = openair0_cfg[0].rx_gain[0]; - double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0]; + double rx_gain = ue->openair0_cfg[0].rx_gain[0]; + double rx_gain_offset = ue->openair0_cfg[0].rx_gain_offset[0]; ue->measurements.n0_power_tot = 0; @@ -344,7 +346,8 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, int nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params, NR_DL_FRAME_PARMS *fp, c16_t rxdataF[][fp->samples_per_slot_wCP], - bool use_SSS) + bool use_SSS, + openair0_config_t *openair0_cfg) { SL_NR_UE_PSBCH_t *psbch_rx = &sl_phy_params->psbch; uint8_t numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP : SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP; diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index bb576460f6..295718e22c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -238,7 +238,7 @@ static int nr_get_csi_rs_signal(const PHY_VARS_NR_UE *ue, *rsrp = rsrp_sum/meas_count; *rsrp_dBm = dB_fixed(*rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); #ifdef NR_CSIRS_DEBUG LOG_I(NR_PHY, "RSRP = %i (%i dBm)\n", *rsrp, *rsrp_dBm); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 1da2ef8d45..e281e1851d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -80,7 +80,7 @@ unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{ /* compute the MMSE up to 4x4 matrices */ static void nr_dlsch_mmse(uint32_t rx_size_symbol, unsigned char n_rx, - unsigned char n_tx, // number of layer + unsigned char nl, // number of layer int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], c16_t dl_ch_mag[][n_rx][rx_size_symbol], c16_t dl_ch_magb[][n_rx][rx_size_symbol], @@ -203,7 +203,7 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol, uint32_t len, unsigned short nb_rb); static void nr_dlsch_detection_mrc(uint32_t rx_size_symbol, - short n_tx, + short nl, short n_rx, int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], int ***rho, @@ -1456,7 +1456,7 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, int length, uint32_t noise_var) { - uint32_t nb_rb_0 = length / 12 + ((length % 12) ? 1 : 0); + uint32_t nb_rb_0 = (length + 11) / 12; c16_t determ_fin[12 * nb_rb_0] __attribute__((aligned(32))); ///Allocate H^*H matrix elements and sub elements @@ -1513,7 +1513,7 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, determ_fin, // determin nb_rb_0, fp_flag, // fixed point flag - shift - (fp_flag == 1 ? 2 : 0)); // the out put is Q15 + shift - (fp_flag == 1 ? 1 : 0)); // the out put is Q15 // multiply Matrix inversion pf H_h_H by the rx signal vector c16_t outtemp[12 * nb_rb_0] __attribute__((aligned(32))); @@ -1531,7 +1531,7 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, (c16_t *)(rxdataF_comp[ctx][0] + symbol * rx_size_symbol), outtemp, sizeofArray(outtemp), - shift - (fp_flag == 1 ? 2 : 0)); + shift - (fp_flag == 1 ? 1 : 0)); nr_a_sum_b(rxdataF_zforcing[rtx], outtemp, nb_rb_0); // a = a + b } #ifdef DEBUG_DLSCH_DEMOD @@ -1582,13 +1582,9 @@ static void nr_dlsch_mmse(uint32_t rx_size_symbol, dl_ch_mag128b_0[0] = mmtmpD2; dl_ch_mag128r_0[0] = mmtmpD2; - dl_ch_mag128_0[0] = simde_mm_mulhi_epi16(dl_ch_mag128_0[0],QAM_amp128); - dl_ch_mag128_0[0] = simde_mm_slli_epi16(dl_ch_mag128_0[0],1); - - dl_ch_mag128b_0[0] = simde_mm_mulhi_epi16(dl_ch_mag128b_0[0],QAM_amp128b); - dl_ch_mag128b_0[0] = simde_mm_slli_epi16(dl_ch_mag128b_0[0],1); - dl_ch_mag128r_0[0] = simde_mm_mulhi_epi16(dl_ch_mag128r_0[0],QAM_amp128r); - dl_ch_mag128r_0[0] = simde_mm_slli_epi16(dl_ch_mag128r_0[0],1); + dl_ch_mag128_0[0] = simde_mm_mulhrs_epi16(dl_ch_mag128_0[0], QAM_amp128); + dl_ch_mag128b_0[0] = simde_mm_mulhrs_epi16(dl_ch_mag128b_0[0],QAM_amp128b); + dl_ch_mag128r_0[0] = simde_mm_mulhrs_epi16(dl_ch_mag128r_0[0],QAM_amp128r); determ_fin_128 += 1; dl_ch_mag128_0 += 1; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c index 2568a54a37..2a2200557e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -518,7 +518,7 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, sync_params->DFN, sync_params->slot_offset); - UE->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_ue, frame_parms, rxdataF, false); + UE->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_ue, frame_parms, rxdataF, false, UE->openair0_cfg); UE->init_sync_frame = sync_params->remaining_frames; result.rx_offset = sync_params->rx_offset; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index ebfd6f6352..435716919a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -91,8 +91,8 @@ The function pointers are set once before calling the mapping funcion for all symbols based on different parameters. Then the mapping is done for each symbol by calling the function pointers. */ -static void (*map_dmrs_ptr)(const unsigned int, const c16_t *, c16_t *); -static void (*map_data_dmrs_ptr)(const unsigned int num_cdm_no_data, const c16_t *, c16_t *); +typedef void (*map_dmrs_func_t)(const unsigned int, const c16_t *, c16_t *); +typedef void (*map_data_dmrs_func_t)(const unsigned int, const c16_t *, c16_t *); /* The following set of functions map dmrs and/or data REs in one RB based on @@ -191,7 +191,9 @@ static void map_over_dc(const unsigned int right_dc, const c16_t **ptrs, const c16_t **dmrs, const c16_t **data, - c16_t **out) + c16_t **out, + map_dmrs_func_t map_data_dmrs_ptr, + map_dmrs_func_t map_dmrs_ptr) { // if first RE is DC no need to map in this function if (right_dc == 0) @@ -277,7 +279,9 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, const c16_t *dmrs_seq, const c16_t *ptrs_seq, const c16_t **data, - c16_t *out) + c16_t *out, + map_dmrs_func_t map_dmrs_ptr, + map_data_dmrs_func_t map_data_dmrs_ptr) { const unsigned int abs_start_rb = p.bwp_start + p.start_rb; const unsigned int start_sc = (p.first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % p.fft_size; @@ -297,7 +301,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, // map RB at DC if (rb_over_dc) { // if DC is in middle of RB, the following function handles it. - map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, NULL, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, NULL, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { // else just move the pointer and following function will map the rb @@ -315,7 +319,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, for (unsigned int rb = 0; rb < p.nb_rb; rb++) { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -339,7 +343,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, if (rb < non_ptrs_rb || ptrs_idx_rb % p.K_ptrs) { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -351,7 +355,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, } else { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &p_mod_ptrs, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &p_mod_ptrs, NULL, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -370,7 +374,7 @@ static void map_current_symbol(const nr_phy_pxsch_params_t p, for (unsigned int rb = 0; rb < p.nb_rb; rb++) { if (rb == dc_rb) { if (rb_over_dc) { - map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp); + map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp, map_data_dmrs_ptr, map_dmrs_ptr); continue; } else { out_tmp -= p.fft_size; @@ -396,7 +400,7 @@ static void dmrs_amp_mult(const uint32_t dmrs_port, const pusch_dmrs_type_t dmrs_type, const unsigned int num_cdm_groups_no_data) { - float beta_dmrs_pusch = get_beta_dmrs_pusch(num_cdm_groups_no_data, dmrs_type); + float beta_dmrs_pusch = get_beta_dmrs(num_cdm_groups_no_data, dmrs_type == pusch_dmrs_type2); /* short array that hold amplitude for k_prime = 0 and k_prime = 1 */ int32_t alpha_dmrs[2] __attribute((aligned(16))); for (int_fast8_t i = 0; i < sizeofArray(alpha_dmrs); i++) { @@ -420,6 +424,8 @@ static void map_symbols(const nr_phy_pxsch_params_t p, c16_t *out) { // asign the function pointers + map_dmrs_func_t map_dmrs_ptr = NULL; + map_data_dmrs_func_t map_data_dmrs_ptr = NULL; if (p.dmrs_type == pusch_dmrs_type1) { map_dmrs_ptr = map_dmrs_type1_cdm1_rb; map_data_dmrs_ptr = (p.num_cdm_no_data == 1) ? map_data_dmrs_type1_cdm1_rb : NULL; @@ -460,7 +466,9 @@ static void map_symbols(const nr_phy_pxsch_params_t p, mod_dmrs_amp, mod_ptrs_amp, &cur_data, // increments every symbol - out + l * p.fft_size); + out + l * p.fft_size, + map_dmrs_ptr, + map_data_dmrs_ptr); } } diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 9d8683481d..6ae3ddc37a 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -336,6 +336,7 @@ typedef struct { /// Top-level PHY Data Structure for UE typedef struct PHY_VARS_NR_UE_s { + openair0_config_t openair0_cfg[MAX_CARDS]; /// \brief Module ID indicator for this instance uint8_t Mod_id; /// \brief Component carrier ID for this PHY instance diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b95c7b8f79..bd0e110565 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -553,6 +553,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, dlschCfg->dlDmrsScramblingId, dlschCfg->BWPStart, dlschCfg->dmrsConfigType, + dlschCfg->n_dmrs_cdm_groups, dlschCfg->rb_offset, ue->frame_parms.first_carrier_offset + (dlschCfg->BWPStart + dlschCfg->start_rb) * 12, dlschCfg->number_rbs, 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 13b081385d..bd2ac08b81 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -227,7 +227,7 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr sym = (sym == 0) ? 5 : sym + 1; } - ue->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_phy_params, fp, rxdataF, false); + ue->adjust_rxgain = nr_sl_psbch_rsrp_measurements(sl_phy_params, fp, rxdataF, false, ue->openair0_cfg); LOG_D(NR_PHY, " ------ Decode SL-MIB: frame.slot %d.%d ------ \n", frame_rx % 1024, nr_slot_rx); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 0f21fdb145..fdca90b094 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -924,8 +924,7 @@ printf("%d\n", slot); init_nr_ue_transport(UE); - nr_l2_init_ue(1); - UE_mac = get_mac_inst(0); + UE_mac = nr_l2_init_ue(0); ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu)); UE->if_inst = nr_ue_if_module_init(0); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index e5361a3e2d..466ffc6822 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -780,8 +780,7 @@ int main(int argc, char *argv[]) init_nr_ue_transport(UE); //Configure UE - nr_l2_init_ue(1); - NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0); + NR_UE_MAC_INST_t* UE_mac = nr_l2_init_ue(0); ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu)); diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index df295e2011..33d6b7b59e 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -85,14 +85,6 @@ MESSAGE_DEF(NAS_INIT_NOS1_IF, MESSAGE_PRIORITY_MED, nas_nos1_msg_t, nas_init_nos MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process) MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFrameProcess, nr_rrc_frame_process) -// UE: RRC -> MAC messages -MESSAGE_DEF(NR_MAC_RRC_CONFIG_RESET, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_reset_t, nr_mac_rrc_config_reset) -MESSAGE_DEF(NR_MAC_RRC_CONFIG_CG, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_cg_t, nr_mac_rrc_config_cg) -MESSAGE_DEF(NR_MAC_RRC_RESUME_RB, MESSAGE_PRIORITY_MED, nr_mac_rrc_resume_rb_t, nr_mac_rrc_resume_rb) -MESSAGE_DEF(NR_MAC_RRC_CONFIG_MIB, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_mib_t, nr_mac_rrc_config_mib) -MESSAGE_DEF(NR_MAC_RRC_CONFIG_SIB1, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_sib1_t, nr_mac_rrc_config_sib1) -MESSAGE_DEF(NR_MAC_RRC_CONFIG_OTHER_SIB, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_other_sib_t, nr_mac_rrc_config_other_sib) - // eNB: RLC -> RRC messages MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) MESSAGE_DEF(NAS_PDU_SESSION_REQ, MESSAGE_PRIORITY_MED, nas_pdu_session_req_t, nas_pdu_session_req) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 1d35619ecc..e1656a3d7f 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -105,12 +105,6 @@ #define NAS_OAI_TUN_NSA(mSGpTR) (mSGpTR)->ittiMsg.nas_oai_tun_nsa #define NAS_PDU_SESSION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdu_session_req -#define NR_MAC_RRC_CONFIG_RESET(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_reset -#define NR_MAC_RRC_CONFIG_CG(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_cg -#define NR_MAC_RRC_RESUME_RB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_resume_rb -#define NR_MAC_RRC_CONFIG_MIB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_mib -#define NR_MAC_RRC_CONFIG_SIB1(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_sib1 -#define NR_MAC_RRC_CONFIG_OTHER_SIB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_other_sib #define NR_RRC_RLC_MAXRTX(mSGpTR) (mSGpTR)->ittiMsg.nr_rlc_maxrtx_indication @@ -497,4 +491,25 @@ typedef struct { bool can_start_ra; } nr_mac_rrc_config_other_sib_t; +enum payload_type { + NR_MAC_RRC_CONFIG_RESET, + NR_MAC_RRC_CONFIG_CG, + NR_MAC_RRC_CONFIG_MIB, + NR_MAC_RRC_CONFIG_SIB1, + NR_MAC_RRC_CONFIG_OTHER_SIB, + NR_MAC_RRC_RESUME_RB +}; + +typedef struct { + enum payload_type payload_type; + union { + nr_mac_rrc_config_reset_t config_reset; + nr_mac_rrc_config_cg_t config_cg; + nr_mac_rrc_config_mib_t config_mib; + nr_mac_rrc_config_sib1_t config_sib1; + nr_mac_rrc_config_other_sib_t config_other_sib; + nr_mac_rrc_resume_rb_t resume_rb; + } payload; +} nr_mac_rrc_message_t; + #endif /* RRC_MESSAGES_TYPES_H_ */ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 2d88708bfe..d734870f52 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -654,6 +654,7 @@ typedef struct NR_UE_MAC_INST_s { bool msg3_C_RNTI; pthread_mutex_t if_mutex; ue_mac_stats_t stats; + notifiedFIFO_t input_nf; } NR_UE_MAC_INST_t; static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_ta, int scs) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index e189d7dcf9..1a43dd2972 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -38,7 +38,7 @@ #include "nr_rlc/nr_rlc_oai_api.h" #include "RRC/NR_UE/rrc_proto.h" #include -static NR_UE_MAC_INST_t *nr_ue_mac_inst; +static NR_UE_MAC_INST_t *nr_ue_mac_inst[MAX_NUM_NR_UE_INST] = {0}; void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data) { @@ -70,6 +70,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) mac->p_Max_alt = INT_MIN; mac->msg3_C_RNTI = false; mac->ntn_ta.ntn_params_changed = false; + initNotifiedFIFO(&mac->input_nf); reset_mac_inst(mac); // need to inizialize because might not been setup (optional timer) @@ -124,37 +125,38 @@ NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id) return mac->state; } -NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst) +NR_UE_MAC_INST_t *nr_l2_init_ue(int instance_id) { - //init mac here - nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(nb_inst, sizeof(NR_UE_MAC_INST_t)); - AssertFatal(nr_ue_mac_inst, "Couldn't allocate %d instances of MAC module\n", nb_inst); + AssertFatal(instance_id < MAX_NUM_NR_UE_INST, "instance_id %d is out of range\n", instance_id); + AssertFatal(nr_ue_mac_inst[instance_id] == NULL, "MAC instance %d already initialized\n", instance_id); + nr_ue_mac_inst[instance_id] = calloc_or_fail(1, sizeof(NR_UE_MAC_INST_t)); - for (int j = 0; j < nb_inst; j++) { - NR_UE_MAC_INST_t *mac = &nr_ue_mac_inst[j]; - mac->ue_id = j; - nr_ue_init_mac(mac); - int ret = pthread_mutex_init(&mac->if_mutex, NULL); - AssertFatal(ret == 0, "Mutex init failed\n"); - nr_ue_mac_default_configs(mac); - if (IS_SA_MODE(get_softmodem_params())) - ue_init_config_request(mac, get_slots_per_frame_from_scs(get_softmodem_params()->numerology)); + NR_UE_MAC_INST_t *mac = nr_ue_mac_inst[instance_id]; + mac->ue_id = instance_id; + nr_ue_init_mac(mac); + int ret = pthread_mutex_init(&mac->if_mutex, NULL); + AssertFatal(ret == 0, "Mutex init failed\n"); + nr_ue_mac_default_configs(mac); + if (IS_SA_MODE(get_softmodem_params())) + ue_init_config_request(mac, get_slots_per_frame_from_scs(get_softmodem_params()->numerology)); + + static bool initialized = false; + if (!initialized) { + int rc = nr_rlc_module_init(NR_RLC_OP_MODE_UE); + AssertFatal(rc == 0, "Could not initialize RLC layer\n"); + initialized = true; } - int rc = nr_rlc_module_init(NR_RLC_OP_MODE_UE); - AssertFatal(rc == 0, "Could not initialize RLC layer\n"); + nr_rlc_activate_srb0(instance_id, NULL, send_srb0_rrc); - for (int j = 0; j < nb_inst; j++) { - nr_rlc_activate_srb0(j, NULL, send_srb0_rrc); - } - - return (nr_ue_mac_inst); + return nr_ue_mac_inst[instance_id]; } NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id) { - NR_UE_MAC_INST_t *mac = &nr_ue_mac_inst[(int)module_id]; - AssertFatal(mac, "Couldn't get MAC inst %d\n", module_id); + AssertFatal(module_id < MAX_NUM_NR_UE_INST, "module_id %d is out of range\n", module_id); + NR_UE_MAC_INST_t *mac = nr_ue_mac_inst[module_id]; + if (mac == NULL) return NULL; AssertFatal(mac->ue_id == module_id, "MAC ID %d doesn't match with input %d\n", mac->ue_id, module_id); return mac; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 783ae0489f..741842319e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -755,8 +755,13 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; } else { dlsch_pdu->SubcarrierSpacing = current_DL_BWP->scs; - if (nr_timer_is_active(&mac->ra.response_window_timer) && rnti_type == TYPE_RA_RNTI_) { - dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; + if (rnti_type == TYPE_RA_RNTI_) { + if (nr_timer_is_active(&mac->ra.response_window_timer)) { + dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; + } else { + // Discard the DCI + return -1; + } } else { dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index c88ad3bd96..8befbe4833 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1314,6 +1314,7 @@ void nr_schedule_ue_spec(module_id_t module_id, 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; @@ -1387,6 +1388,7 @@ void nr_schedule_ue_spec(module_id_t module_id, T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, TBS)); + T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS)); } const int ntx_req = TX_req->Number_of_PDUs; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 4486be536d..09044e9170 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -485,6 +485,7 @@ static int nr_process_mac_pdu(instance_t module_idP, UE->mac_stats.ul.total_sdu_bytes += mac_len; UE->mac_stats.ul.lc_bytes[lcid] += mac_len; } + T(T_GNB_MAC_LCID_UL, T_INT(UE->rnti), T_INT(frameP), T_INT(slot), T_INT(lcid), T_INT(mac_len * 8)); break; case UL_SCH_LCID_DTCH ...(UL_SCH_LCID_DTCH + 28): @@ -512,6 +513,7 @@ static int nr_process_mac_pdu(instance_t module_idP, else sched_ctrl->estimated_ul_buffer = 0; } + T(T_GNB_MAC_LCID_UL, T_INT(UE->rnti), T_INT(frameP), T_INT(slot), T_INT(lcid), T_INT(mac_len * 8)); break; case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY: @@ -1498,8 +1500,17 @@ void handle_nr_srs_measurements(const module_id_t module_id, nfapi_nr_srs_indication_pdu_t *srs_ind) { gNB_MAC_INST *nrmac = RC.nrmac[module_id]; - NR_SCHED_LOCK(&nrmac->sched_lock); LOG_D(NR_MAC, "(%d.%d) Received SRS indication for UE %04x\n", frame, slot, srs_ind->rnti); + if (srs_ind->report_type == 0) { + //SCF 222.10.04 Table 3-129 Report type = 0 means a null report, we can skip unpacking it + return; + } + + if (srs_ind->timing_advance_offset == 0xFFFF) { + LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti); + return; + } + NR_SCHED_LOCK(&nrmac->sched_lock); #ifdef SRS_IND_DEBUG LOG_I(NR_MAC, "frame = %i\n", frame); @@ -1518,12 +1529,6 @@ void handle_nr_srs_measurements(const module_id_t module_id, return; } - if (srs_ind->timing_advance_offset == 0xFFFF) { - LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti); - NR_SCHED_UNLOCK(&nrmac->sched_lock); - return; - } - gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; NR_mac_stats_t *stats = &UE->mac_stats; nfapi_srs_report_tlv_t *report_tlv = &srs_ind->report_tlv; @@ -2467,6 +2472,8 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, sched_ctrl->tpc0); + T(T_GNB_MAC_UL, T_INT(UE->rnti), T_INT(frame), T_INT(slot), T_INT(sched_pusch->mcs), T_INT(sched_pusch->tb_size)); + /* PUSCH in a later slot, but corresponding DCI now! */ const int index = ul_buffer_index(sched_pusch->frame, sched_pusch->slot, diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c index 6103a7011a..e452981357 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c @@ -125,6 +125,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_am( ret->common.reestablishment = nr_rlc_entity_am_reestablishment; ret->common.delete_entity = nr_rlc_entity_am_delete; ret->common.available_tx_space = nr_rlc_entity_am_available_tx_space; + ret->common.tx_list_occupancy = nr_rlc_entity_am_tx_list_occupancy; ret->common.get_stats = nr_rlc_entity_get_stats; ret->common.deliver_sdu = deliver_sdu; @@ -186,6 +187,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_um( ret->common.reestablishment = nr_rlc_entity_um_reestablishment; ret->common.delete_entity = nr_rlc_entity_um_delete; ret->common.available_tx_space = nr_rlc_entity_um_available_tx_space; + ret->common.tx_list_occupancy = nr_rlc_entity_um_tx_list_occupancy; ret->common.get_stats = nr_rlc_entity_get_stats; ret->common.deliver_sdu = deliver_sdu; @@ -226,6 +228,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_tm( ret->common.reestablishment = nr_rlc_entity_tm_reestablishment; ret->common.delete_entity = nr_rlc_entity_tm_delete; ret->common.available_tx_space = nr_rlc_entity_tm_available_tx_space; + ret->common.tx_list_occupancy = nr_rlc_entity_tm_tx_list_occupancy; ret->common.get_stats = nr_rlc_entity_get_stats; ret->common.deliver_sdu = deliver_sdu; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h index dc0bf4907c..459e9f59a5 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h @@ -116,6 +116,7 @@ typedef struct nr_rlc_entity_t { void (*delete_entity)(struct nr_rlc_entity_t *entity); int (*available_tx_space)(struct nr_rlc_entity_t *entity); + int (*tx_list_occupancy)(struct nr_rlc_entity_t *entity); void (*get_stats)(struct nr_rlc_entity_t *entity, nr_rlc_statistics_t *out); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index a66ebe82e5..b1f87a7a05 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -2116,3 +2116,8 @@ int nr_rlc_entity_am_available_tx_space(nr_rlc_entity_t *_entity) return entity->tx_maxsize - entity->tx_size; } +int nr_rlc_entity_am_tx_list_occupancy(nr_rlc_entity_t *_entity) +{ + nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity; + return entity->tx_size; +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h index 6b61e84a2f..3ffcab6176 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h @@ -101,5 +101,6 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id); void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity); void nr_rlc_entity_am_delete(nr_rlc_entity_t *entity); int nr_rlc_entity_am_available_tx_space(nr_rlc_entity_t *entity); +int nr_rlc_entity_am_tx_list_occupancy(nr_rlc_entity_t *_entity); #endif /* _NR_RLC_ENTITY_AM_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c index 7b541c02ff..be20d574c1 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c @@ -221,3 +221,9 @@ int nr_rlc_entity_tm_available_tx_space(nr_rlc_entity_t *_entity) nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity; return entity->tx_maxsize - entity->tx_size; } + +int nr_rlc_entity_tm_tx_list_occupancy(nr_rlc_entity_t *_entity) +{ + nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity; + return entity->tx_size; +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h index 716b35d14d..2792017c34 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h @@ -56,5 +56,6 @@ void nr_rlc_entity_tm_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id); void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity); void nr_rlc_entity_tm_delete(nr_rlc_entity_t *entity); int nr_rlc_entity_tm_available_tx_space(nr_rlc_entity_t *entity); +int nr_rlc_entity_tm_tx_list_occupancy(nr_rlc_entity_t *_entity); #endif /* _NR_RLC_ENTITY_TM_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c index 75e407328b..4edee0ddab 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c @@ -765,3 +765,9 @@ int nr_rlc_entity_um_available_tx_space(nr_rlc_entity_t *_entity) nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity; return entity->tx_maxsize - entity->tx_size; } + +int nr_rlc_entity_um_tx_list_occupancy(nr_rlc_entity_t *_entity) +{ + nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity; + return entity->tx_size; +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h index 6395bfd47e..c32c5aaedf 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h @@ -80,5 +80,6 @@ void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id); void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity); void nr_rlc_entity_um_delete(nr_rlc_entity_t *entity); int nr_rlc_entity_um_available_tx_space(nr_rlc_entity_t *entity); +int nr_rlc_entity_um_tx_list_occupancy(nr_rlc_entity_t *_entity); #endif /* _NR_RLC_ENTITY_UM_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 88c8d5d377..e187541fd5 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -320,6 +320,25 @@ int nr_rlc_get_available_tx_space(const int ue_id, const logical_chan_id_t chann return ret; } +int nr_rlc_tx_list_occupancy(int ue_id, logical_chan_id_t lcid) +{ + int 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, lcid); + + if (rb != NULL) { + ret = rb->tx_list_occupancy(rb); + } else { + ret = 0; + } + + nr_rlc_manager_unlock(nr_rlc_ue_manager); + + return ret; +} + int nr_rlc_module_init(nr_rlc_op_mode_t mode) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index fec65796d9..454a59b928 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -80,6 +80,8 @@ void nr_rlc_reconfigure_entity(int ue_id, int lc_id, NR_RLC_Config_t *rlc_Config int nr_rlc_get_available_tx_space(const int ue_id, const logical_chan_id_t channel_idP); +int nr_rlc_tx_list_occupancy(int ue_id, logical_chan_id_t lcid); + void nr_rlc_activate_avg_time_to_tx(const int ue_id, const logical_chan_id_t channel_id, const bool is_on); void nr_rlc_srb_recv_sdu(const int ue_id, const logical_chan_id_t channel_id, unsigned char *buf, int size); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index de5ae571ca..dcd4a85f5d 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1312,7 +1312,7 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio // resume RAR response window timer if MSG2 decoding failed nr_timer_suspension(&mac->ra.response_window_timer); } else { - LOG_I(PHY, "RAR-Msg2 decoded\n"); + LOG_I(PHY, "[UE %d] RAR-Msg2 decoded\n", mac->ue_id); } ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR; break; diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 6271957f4f..b751f31670 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -121,42 +121,40 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, } } -void process_msg_rcc_to_mac(MessageDef *msg) +void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id) { - instance_t ue_id = ITTI_MSG_DESTINATION_INSTANCE(msg); - switch (ITTI_MSG_ID(msg)) { + switch (msg->payload_type) { case NR_MAC_RRC_CONFIG_RESET: - nr_rrc_mac_config_req_reset(ue_id, NR_MAC_RRC_CONFIG_RESET(msg).cause); + nr_rrc_mac_config_req_reset(instance_id, msg->payload.config_reset.cause); break; case NR_MAC_RRC_CONFIG_CG: - nr_rrc_mac_config_req_cg(ue_id, 0, NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig, NR_MAC_RRC_CONFIG_CG(msg).UE_NR_Capability); - asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig); + nr_rrc_mac_config_req_cg(instance_id, 0, msg->payload.config_cg.cellGroupConfig, msg->payload.config_cg.UE_NR_Capability); + asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, msg->payload.config_cg.cellGroupConfig); break; case NR_MAC_RRC_CONFIG_MIB: - nr_rrc_mac_config_req_mib(ue_id, + nr_rrc_mac_config_req_mib(instance_id, 0, - NR_MAC_RRC_CONFIG_MIB(msg).bcch->message.choice.mib, - NR_MAC_RRC_CONFIG_MIB(msg).get_sib, - NR_MAC_RRC_CONFIG_MIB(msg).access_barred); - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, NR_MAC_RRC_CONFIG_MIB(msg).bcch); + msg->payload.config_mib.bcch->message.choice.mib, + msg->payload.config_mib.get_sib, + msg->payload.config_mib.access_barred); + ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, msg->payload.config_mib.bcch); break; case NR_MAC_RRC_CONFIG_SIB1: { - NR_SIB1_t *sib1 = NR_MAC_RRC_CONFIG_SIB1(msg).sib1; - bool can_start_ra = NR_MAC_RRC_CONFIG_SIB1(msg).can_start_ra; - nr_rrc_mac_config_req_sib1(ue_id, 0, sib1, can_start_ra); - SEQUENCE_free(&asn_DEF_NR_SIB1, NR_MAC_RRC_CONFIG_SIB1(msg).sib1, ASFM_FREE_EVERYTHING); + NR_SIB1_t *sib1 = msg->payload.config_sib1.sib1; + bool can_start_ra = msg->payload.config_sib1.can_start_ra; + nr_rrc_mac_config_req_sib1(instance_id, 0, sib1, can_start_ra); + SEQUENCE_free(&asn_DEF_NR_SIB1, msg->payload.config_sib1.sib1, ASFM_FREE_EVERYTHING); } break; case NR_MAC_RRC_CONFIG_OTHER_SIB: { - bool can_start_ra = NR_MAC_RRC_CONFIG_OTHER_SIB(msg).can_start_ra; - nr_rrc_mac_config_other_sib(ue_id, NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19, can_start_ra); + bool can_start_ra = msg->payload.config_other_sib.can_start_ra; + nr_rrc_mac_config_other_sib(instance_id, msg->payload.config_other_sib.sib19, can_start_ra); } break; case NR_MAC_RRC_RESUME_RB: - nr_rrc_mac_resume_rb(ue_id, NR_MAC_RRC_RESUME_RB(msg).is_srb, NR_MAC_RRC_RESUME_RB(msg).rb_id); + nr_rrc_mac_resume_rb(instance_id, msg->payload.resume_rb.is_srb, msg->payload.resume_rb.rb_id); break; default: - LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", ITTI_MSG_ID(msg)); + LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", msg->payload_type); } - itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); } void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id) diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index e36f6d83fb..daaed50e65 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -42,6 +42,6 @@ void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_ void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success); void nsa_sendmsg_to_lte_ue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type); -void process_msg_rcc_to_mac(MessageDef *msg); +void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id); #endif diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 87cb68303a..52d9ecb50a 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -72,7 +72,7 @@ #include "nr_nas_msg.h" #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" -static NR_UE_RRC_INST_t *NR_UE_rrc_inst; +static NR_UE_RRC_INST_t *NR_UE_rrc_inst[MAX_NUM_NR_UE_INST] = {0}; /* NAS Attach request with IMSI */ static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = { 0x07, @@ -149,9 +149,29 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers); -NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance) +/** + * @brief Sends an RRC message to the connected UE MAC instance. + * + * @param rrc UE RRC instance structure + * @param msg RRC message to be sent to MAC + */ +static void nr_rrc_send_msg_to_mac(NR_UE_RRC_INST_t *rrc, nr_mac_rrc_message_t *msg) { - return &NR_UE_rrc_inst[instance]; + AssertFatal(rrc->mac_input_nf != NULL, "MAC input NF is NULL for UE %ld\n", rrc->ue_id); + notifiedFIFO_elt_t *nf_msg = newNotifiedFIFO_elt(sizeof(nr_mac_rrc_message_t), 0, NULL, NULL); + nr_mac_rrc_message_t *rrc_msg = NotifiedFifoData(nf_msg); + memcpy(rrc_msg, msg, sizeof(nr_mac_rrc_message_t)); + pushNotifiedFIFO(rrc->mac_input_nf, nf_msg); +} + +NR_UE_RRC_INST_t *get_NR_UE_rrc_inst(int instance) +{ + AssertFatal(instance >= 0 && instance < MAX_NUM_NR_UE_INST, "RRC instance %d out of bounds\n", instance); + NR_UE_RRC_INST_t *rrc = NR_UE_rrc_inst[instance]; + if (rrc == NULL) + return NULL; + AssertFatal(rrc->ue_id == instance, "RRC ID %d doesn't match with input %d\n", (int)rrc->ue_id, instance); + return rrc; } static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id) @@ -281,7 +301,6 @@ static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *S static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc, int frame) { - instance_t ue_id = rrc->ue_id; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN); // Dump contents @@ -365,10 +384,12 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, } if (sib19) { - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_OTHER_SIB); - asn_copy(&asn_DEF_NR_SIB19_r17, (void **)&NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19, sib19); - NR_MAC_RRC_CONFIG_OTHER_SIB(msg).can_start_ra = rrc->is_NTN_UE; - itti_send_msg_to_task(TASK_MAC_UE, ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_OTHER_SIB; + nr_mac_rrc_config_other_sib_t *sib19_msg = &rrc_msg.payload.config_other_sib; + asn_copy(&asn_DEF_NR_SIB19_r17, (void **)&sib19_msg->sib19, sib19); + sib19_msg->can_start_ra = rrc->is_NTN_UE; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT); } @@ -502,10 +523,13 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1); // RRC storage of SIB1 timers and constants (eg needed in re-establishment) UPDATE_IE(rrc->timers_and_constants.sib1_TimersAndConstants, sib1->ue_TimersAndConstants, NR_UE_TimersAndConstants_t); - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_SIB1); - NR_MAC_RRC_CONFIG_SIB1(msg).sib1 = sib1; - NR_MAC_RRC_CONFIG_SIB1(msg).can_start_ra = !rrc->is_NTN_UE; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_SIB1; + nr_mac_rrc_config_sib1_t *config_sib1 = &rrc_msg.payload.config_sib1; + config_sib1->sib1 = sib1; + config_sib1->can_start_ra = !rrc->is_NTN_UE; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) @@ -644,12 +668,12 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_CG); - // cellGroupConfig will be managed by MAC - NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig = cellGroupConfig; - // UE_NR_Capability remain a race condition between this rrc thread and mac thread - NR_MAC_RRC_CONFIG_CG(msg).UE_NR_Capability = rrc->UECap.UE_NR_Capability; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; + nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg; + config_cg->cellGroupConfig = cellGroupConfig; + config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } if (ie->measConfig) { LOG_I(NR_RRC, "RRCReconfiguration includes Measurement Configuration\n"); @@ -731,67 +755,63 @@ static bool verify_ue_cap(NR_UE_NR_Capability_t *UE_NR_Capability, int nb_antenn return true; } -NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx) +NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int instance_id, int num_ant_tx) { - NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)calloc(nb_inst, sizeof(NR_UE_RRC_INST_t)); - AssertFatal(NR_UE_rrc_inst, "Couldn't allocate %d instances of RRC module\n", nb_inst); + AssertFatal(instance_id < MAX_NUM_NR_UE_INST, "RRC instance %d out of bounds\n", instance_id); + AssertFatal(NR_UE_rrc_inst[instance_id] == NULL, "RRC instance %d already initialized\n", instance_id); + NR_UE_rrc_inst[instance_id] = calloc_or_fail(1, sizeof(NR_UE_RRC_INST_t)); + NR_UE_RRC_INST_t *rrc = NR_UE_rrc_inst[instance_id]; + rrc->ue_id = instance_id; + // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. + rrc->selected_plmn_identity = 1; + rrc->ra_trigger = RA_NOT_RUNNING; + rrc->dl_bwp_id = 0; + rrc->ul_bwp_id = 0; + rrc->as_security_activated = false; + rrc->detach_after_release = false; + rrc->reconfig_after_reestab = false; + /* 5G-S-TMSI */ + rrc->fiveG_S_TMSI = UINT64_MAX; + rrc->access_barred = false; - for(int nr_ue = 0; nr_ue < nb_inst; nr_ue++) { - NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[nr_ue]; - rrc->ue_id = nr_ue; - // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. - rrc->selected_plmn_identity = 1; - rrc->ra_trigger = RA_NOT_RUNNING; - rrc->dl_bwp_id = 0; - rrc->ul_bwp_id = 0; - rrc->as_security_activated = false; - rrc->detach_after_release = false; - rrc->reconfig_after_reestab = false; - /* 5G-S-TMSI */ - rrc->fiveG_S_TMSI = UINT64_MAX; - rrc->access_barred = false; - - FILE *f = NULL; - if (uecap_file) - f = fopen(uecap_file, "r"); - if (f) { - char UE_NR_Capability_xer[65536]; - size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); - if (size == 0 || size == sizeof UE_NR_Capability_xer) { - LOG_E(NR_RRC, "UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size); - } - else { - asn_dec_rval_t dec_rval = - xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&rrc->UECap.UE_NR_Capability, UE_NR_Capability_xer, size); - assert(dec_rval.code == RC_OK); - } - fclose(f); - /* Verify consistency of num PHY antennas vs UE Capabilities */ - verify_ue_cap(rrc->UECap.UE_NR_Capability, num_ant_tx); + FILE *f = NULL; + if (uecap_file) + f = fopen(uecap_file, "r"); + if (f) { + char UE_NR_Capability_xer[65536]; + size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); + if (size == 0 || size == sizeof UE_NR_Capability_xer) { + LOG_E(NR_RRC, "UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size); + } else { + asn_dec_rval_t dec_rval = + xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&rrc->UECap.UE_NR_Capability, UE_NR_Capability_xer, size); + assert(dec_rval.code == RC_OK); } - - memset(&rrc->timers_and_constants, 0, sizeof(rrc->timers_and_constants)); - set_default_timers_and_constants(&rrc->timers_and_constants); - - for (int j = 0; j < NR_NUM_SRB; j++) - rrc->Srb[j] = RB_NOT_PRESENT; - for (int j = 1; j <= MAX_DRBS_PER_UE; j++) - set_DRB_status(rrc, j, RB_NOT_PRESENT); - // SRB0 activated by default - rrc->Srb[0] = RB_ESTABLISHED; - for (int j = 0; j < NR_MAX_NUM_LCID; j++) - rrc->active_RLC_entity[j] = false; - - for (int i = 0; i < NB_CNX_UE; i++) { - rrcPerNB_t *ptr = &rrc->perNB[i]; - ptr->SInfo = (NR_UE_RRC_SI_INFO){0}; - init_SI_timers(&ptr->SInfo); - } - - init_sidelink(rrc); + fclose(f); + /* Verify consistency of num PHY antennas vs UE Capabilities */ + verify_ue_cap(rrc->UECap.UE_NR_Capability, num_ant_tx); } - return NR_UE_rrc_inst; + memset(&rrc->timers_and_constants, 0, sizeof(rrc->timers_and_constants)); + set_default_timers_and_constants(&rrc->timers_and_constants); + + for (int j = 0; j < NR_NUM_SRB; j++) + rrc->Srb[j] = RB_NOT_PRESENT; + for (int j = 1; j <= MAX_DRBS_PER_UE; j++) + set_DRB_status(rrc, j, RB_NOT_PRESENT); + // SRB0 activated by default + rrc->Srb[0] = RB_ESTABLISHED; + for (int j = 0; j < NR_MAX_NUM_LCID; j++) + rrc->active_RLC_entity[j] = false; + + for (int i = 0; i < NB_CNX_UE; i++) { + rrcPerNB_t *ptr = &rrc->perNB[i]; + ptr->SInfo = (NR_UE_RRC_SI_INFO){0}; + init_SI_timers(&ptr->SInfo); + } + + init_sidelink(rrc); + return rrc; } bool check_si_validity(NR_UE_RRC_SI_INFO *SI_info, int si_type) @@ -973,12 +993,13 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, SI_info->sib_pending = true; } if (bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib) { - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_MIB); - // mac will manage the pointer - NR_MAC_RRC_CONFIG_MIB(msg).bcch = bcch_message; - NR_MAC_RRC_CONFIG_MIB(msg).get_sib = get_sib; - NR_MAC_RRC_CONFIG_MIB(msg).access_barred = barred; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_MIB; + nr_mac_rrc_config_mib_t *config_mib = &rrc_msg.payload.config_mib; + config_mib->bcch = bcch_message; + config_mib->get_sib = get_sib; + config_mib->access_barred = barred; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } else { LOG_E(NR_RRC, "RRC-received BCCH message is not a MIB\n"); ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, bcch_message); @@ -1036,10 +1057,11 @@ static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti) nr_rlc_reconfigure_entity(rrc->ue_id, lc_id, NULL); // resume SRB1 rrc->Srb[srb_id] = RB_ESTABLISHED; - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); - NR_MAC_RRC_RESUME_RB(msg).is_srb = true; - NR_MAC_RRC_RESUME_RB(msg).rb_id = 1; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_RESUME_RB; + rrc_msg.payload.resume_rb.is_srb = true; + rrc_msg.payload.resume_rb.rb_id = 1; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); break; case DURING_HANDOVER: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); @@ -1260,10 +1282,12 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); LOG_D(RRC, "Sending CellGroupConfig to MAC the pointer will be managed by mac\n"); - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_CG); - NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig = cellGroupConfig; - NR_MAC_RRC_CONFIG_CG(msg).UE_NR_Capability = rrc->UECap.UE_NR_Capability; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; + nr_mac_rrc_config_cg_t *mac_msg = &rrc_msg.payload.config_cg; + mac_msg->cellGroupConfig = cellGroupConfig; + mac_msg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const uint8_t Transaction_id) @@ -1345,9 +1369,10 @@ static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) // default MAC Cell Group configuration and CCCH configuration // TODO to be completed NR_UE_MAC_reset_cause_t cause = RRC_SETUP_REESTAB_RESUME; - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); - NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); // indicate to upper layers fallback of the RRC connection // TODO @@ -1411,9 +1436,10 @@ static void nr_rrc_process_rrcreject(NR_UE_RRC_INST_t *rrc, const NR_RRCReject_t // reset MAC and release the default MAC Cell Group configuration NR_UE_MAC_reset_cause_t cause = REJECT; - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); - NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); // if waitTime is configured in the RRCReject: start timer T302, with the timer value set to the waitTime NR_RejectWaitTime_t *waitTime = NULL; @@ -2121,18 +2147,20 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, // resume SRB2 and DRBs that are suspended if (rrc->Srb[2] == RB_SUSPENDED) { rrc->Srb[2] = RB_ESTABLISHED; - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); - NR_MAC_RRC_RESUME_RB(msg).is_srb = true; - NR_MAC_RRC_RESUME_RB(msg).rb_id = 2; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_RESUME_RB; + rrc_msg.payload.resume_rb.is_srb = true; + rrc_msg.payload.resume_rb.rb_id = 2; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { if (get_DRB_status(rrc, i) == RB_SUSPENDED) { set_DRB_status(rrc, i, RB_ESTABLISHED); - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); - NR_MAC_RRC_RESUME_RB(msg).is_srb = false; - NR_MAC_RRC_RESUME_RB(msg).rb_id = i; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_RESUME_RB; + rrc_msg.payload.resume_rb.is_srb = true; + rrc_msg.payload.resume_rb.rb_id = i; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } } rrc->reconfig_after_reestab = false; @@ -2246,7 +2274,7 @@ void *rrc_nrue(void *notUsed) instance_t instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); LOG_D(NR_RRC, "[UE %ld] Received %s\n", instance, ITTI_MSG_NAME(msg_p)); - NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance]; + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); AssertFatal(instance == rrc->ue_id, "Instance %ld received from ITTI doesn't matach with UE-ID %ld\n", instance, rrc->ue_id); switch (ITTI_MSG_ID(msg_p)) { @@ -2335,11 +2363,11 @@ void *rrc_nrue(void *notUsed) case NR_RRC_DCCH_DATA_IND: nr_rrc_ue_decode_dcch(rrc, - NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, - NR_RRC_DCCH_DATA_IND(msg_p).sdu_p, - NR_RRC_DCCH_DATA_IND(msg_p).sdu_size, - NR_RRC_DCCH_DATA_IND(msg_p).gNB_index, - &NR_RRC_DCCH_DATA_IND(msg_p).msg_integrity); + NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, + NR_RRC_DCCH_DATA_IND(msg_p).sdu_p, + NR_RRC_DCCH_DATA_IND(msg_p).sdu_size, + NR_RRC_DCCH_DATA_IND(msg_p).gNB_index, + &NR_RRC_DCCH_DATA_IND(msg_p).msg_integrity); /* this is allocated by itti_malloc in PDCP task (deliver_sdu_srb) then passed to the RRC task and freed after use */ free(NR_RRC_DCCH_DATA_IND(msg_p).sdu_p); @@ -2511,9 +2539,10 @@ static void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, NR_Reestab // reset MAC // release spCellConfig, if configured // perform cell selection in accordance with the cell selection process - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); - NR_MAC_RRC_CONFIG_RESET(msg).cause = RE_ESTABLISHMENT; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = RE_ESTABLISHMENT; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, @@ -2541,7 +2570,7 @@ void *recv_msgs_from_lte_ue(void *args_p) LOG_E(NR_RRC, "%s: Received truncated message %d\n", __func__, recvLen); continue; } - process_lte_nsa_msg(NR_UE_rrc_inst, &msg, recvLen); + process_lte_nsa_msg(get_NR_UE_rrc_inst(0), &msg, recvLen); } return NULL; } @@ -2679,8 +2708,8 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l uint8_t *nr_RadioBearer_buffer = msg_buffer + offsetof(struct msg, buffer); uint8_t *nr_SecondaryCellGroup_buffer = nr_RadioBearer_buffer + nr_RadioBearer_size; - process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size); - process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size); + process_nsa_message(get_NR_UE_rrc_inst(0), nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size); + process_nsa_message(get_NR_UE_rrc_inst(0), nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size); LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id); uint8_t buffer[NR_RRC_BUF_SIZE]; size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id); @@ -2886,9 +2915,10 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, // reset MAC NR_UE_MAC_reset_cause_t cause = (rrc->nrRrcState == RRC_STATE_DETACH_NR) ? DETACH : GO_TO_IDLE; - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); - NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); // enter RRC_IDLE LOG_I(NR_RRC, "RRC moved into IDLE state\n"); @@ -2917,9 +2947,11 @@ void handle_t300_expiry(NR_UE_RRC_INST_t *rrc) // reset MAC, release the MAC configuration NR_UE_MAC_reset_cause_t cause = T300_EXPIRY; - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); - NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); + // TODO handle connEstFailureControl // TODO inform upper layers about the failure to establish the RRC connection } @@ -2935,16 +2967,17 @@ void handle_t430_expiry(NR_UE_RRC_INST_t *rrc) } // Indicate MAC that UL SYNC is LOST NR_UE_MAC_reset_cause_t cause = UL_SYNC_LOST_T430_EXPIRED; - MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); - NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; - itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_RESET; + rrc_msg.payload.config_reset.cause = cause; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } //This calls the sidelink preconf message after RRC, MAC instances are created. void start_sidelink(int instance) { - NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance]; + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); if (get_softmodem_params()->sl_mode == 2) { @@ -2953,3 +2986,9 @@ void start_sidelink(int instance) } } + +void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf) +{ + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance); + rrc->mac_input_nf = mac_input_nf; +} diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index c71f7697a2..bc645f7cc1 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -63,6 +63,7 @@ #include "RRC/NR/nr_rrc_common.h" #include "as_message.h" #include "common/utils/nr/nr_common.h" +#include "notified_fifo.h" #define NB_CNX_UE 2//MAX_MANAGED_RG_PER_MOBILE #define MAX_MEAS_OBJ 64 @@ -248,6 +249,7 @@ typedef struct NR_UE_RRC_INST_s { NR_SL_PreconfigurationNR_r16_t *sl_preconfig; // NTN params bool is_NTN_UE; + notifiedFIFO_t *mac_input_nf; } NR_UE_RRC_INST_t; #endif diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index bc7f7001af..ba853f546d 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -106,6 +106,8 @@ void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc, const sdu_size_t pdu_len, const uint16_t rx_slss_id); +void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf); + /** @}*/ #endif diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 615cc5a4f1..cf8b5dd0d6 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -76,9 +76,7 @@ #include "key_nas_deriver.h" #include "nr-uesoftmodem.h" -#define MAX_NAS_UE 4 - -static nr_ue_nas_t nr_ue_nas[MAX_NAS_UE] = {0}; +static nr_ue_nas_t nr_ue_nas[MAX_NUM_NR_UE_INST] = {0}; #define FOREACH_STATE(TYPE_DEF) \ TYPE_DEF(NAS_SECURITY_NO_SECURITY_CONTEXT, 0) \ @@ -676,7 +674,7 @@ static void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) { - DevAssert(module_id < MAX_NAS_UE); + AssertFatal(module_id < MAX_NUM_NR_UE_INST, "Invalid module_id %d\n", module_id); if (!nr_ue_nas[module_id].uicc) { nr_ue_nas[module_id].uicc = checkUicc(module_id); nr_ue_nas[module_id].UE_id = module_id; diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index f928d554a8..b87a6a8abf 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -198,6 +198,13 @@ typedef struct split7_config { } slot_dirs[160]; /*! this is the exponent in 2^X for the FFT size */ uint16_t fftSize; + + // M-plane related parameters + uint16_t dl_k0[5]; + uint16_t ul_k0[5]; + uint16_t cp_prefix0; + uint16_t cp_prefix_other; + } split7_config_t; /*! \brief RF frontend parameters set by application */ diff --git a/radio/fhi_72/mplane/config-mplane.c b/radio/fhi_72/mplane/config-mplane.c index 69ff1fd2b3..da28665023 100644 --- a/radio/fhi_72/mplane/config-mplane.c +++ b/radio/fhi_72/mplane/config-mplane.c @@ -21,14 +21,12 @@ #include "config-mplane.h" #include "rpc-send-recv.h" -#include "yang/get-yang.h" -#include "yang/create-yang-config.h" #include "common/utils/assertions.h" #include #include -bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const openair0_config_t *oai, const size_t num_rus) +static bool edit_config_mplane(ru_session_t *ru_session, const char *content) { int timeout = CLI_RPC_REPLY_TIMEOUT; struct nc_rpc *rpc; @@ -39,37 +37,21 @@ bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const open NC_RPC_EDIT_TESTOPT test = NC_RPC_EDIT_TESTOPT_UNKNOWN; NC_RPC_EDIT_ERROPT err = NC_RPC_EDIT_ERROPT_UNKNOWN; - bool success = false; - - struct ly_ctx *ctx = NULL; - success = load_yang_models(ru_session, buffer, &ctx); - AssertError(success, return false, "[MPLANE] Unable to continue.\n"); - - char *content = NULL; - success = configure_ru_from_yang(&ctx, ru_session, oai, num_rus, &content); - AssertError(success, return false, "[MPLANE] Unable to create content for RPC.\n"); - MP_LOG_I("RPC request to RU \"%s\" = :\n%s\n", ru_session->ru_ip_add, content); rpc = nc_rpc_edit(target, op, test, err, content, param); AssertError(rpc != NULL, return false, "[MPLANE] RPC creation failed.\n"); - success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL); + bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL); AssertError(success, return false, "[MPLANE] Failed to edit configuration for the candidate datastore.\n"); MP_LOG_I("Successfully edited the candidate datastore for RU \"%s\".\n", ru_session->ru_ip_add); nc_rpc_free(rpc); - free(content); -#ifdef MPLANE_V1 - ly_ctx_destroy(ctx, NULL); -#elif defined MPLANE_V2 - ly_ctx_destroy(ctx); -#endif return true; } -bool validate_config_mplane(ru_session_t *ru_session) +static bool validate_config_mplane(ru_session_t *ru_session) { int timeout = CLI_RPC_REPLY_TIMEOUT; struct nc_rpc *rpc; @@ -92,7 +74,7 @@ bool validate_config_mplane(ru_session_t *ru_session) return true; } -bool commit_config_mplane(ru_session_t *ru_session) +static bool commit_config_mplane(ru_session_t *ru_session) { int timeout = CLI_RPC_REPLY_TIMEOUT; struct nc_rpc *rpc; @@ -109,9 +91,25 @@ bool commit_config_mplane(ru_session_t *ru_session) bool success = rpc_send_recv((struct nc_session *)ru_session->session, rpc, wd, timeout, NULL); AssertError(success, return false, "[MPLANE] Failed to commit candidate datastore.\n"); - MP_LOG_I("Successfully commited CU-planes configuration into running datastore for RU \"%s\".\n", ru_session->ru_ip_add); + MP_LOG_I("Successfully commited configuration into running datastore for RU \"%s\".\n", ru_session->ru_ip_add); nc_rpc_free(rpc); return true; } + +bool edit_val_commmit_rpc(ru_session_t *ru_session, const char *content) +{ + bool success = false; + + success = edit_config_mplane(ru_session, content); + AssertError(success, return false, "[MPLANE] Unable to edit the RU configuration.\n"); + + success = validate_config_mplane(ru_session); + AssertError(success, return false, "[MPLANE] Unable to validate the RU configuration.\n"); + + success = commit_config_mplane(ru_session); + AssertError(success, return false, "[MPLANE] Unable to commit the RU configuration.\n"); + + return success; +} diff --git a/radio/fhi_72/mplane/config-mplane.h b/radio/fhi_72/mplane/config-mplane.h index c8451ca8a0..dae2dbea63 100644 --- a/radio/fhi_72/mplane/config-mplane.h +++ b/radio/fhi_72/mplane/config-mplane.h @@ -25,10 +25,6 @@ #include "ru-mplane-api.h" #include "radio/COMMON/common_lib.h" -bool edit_config_mplane(ru_session_t *ru_session, const char *buffer, const openair0_config_t *oai, const size_t num_rus); - -bool validate_config_mplane(ru_session_t *ru_session); - -bool commit_config_mplane(ru_session_t *ru_session); +bool edit_val_commmit_rpc(ru_session_t *ru_session, const char *content); #endif /* CONFIGURE_MPLANE_H */ diff --git a/radio/fhi_72/mplane/connect-mplane.c b/radio/fhi_72/mplane/connect-mplane.c index 08b758bef1..9744ce01e8 100644 --- a/radio/fhi_72/mplane/connect-mplane.c +++ b/radio/fhi_72/mplane/connect-mplane.c @@ -20,6 +20,7 @@ */ #include "connect-mplane.h" +#include "init-mplane.h" #include "common/utils/assertions.h" #include @@ -37,9 +38,8 @@ static int my_auth_hostkey_check(const char *hostname, ssh_session session, void bool connect_mplane(ru_session_t *ru_session) { int port = NC_PORT_SSH; - char *user = "oranbenetel"; - nc_client_ssh_set_username(user); + nc_client_ssh_set_username(ru_session->username); nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1); // ssh-key identification nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1); @@ -47,11 +47,11 @@ bool connect_mplane(ru_session_t *ru_session) nc_client_ssh_set_auth_hostkey_check_clb(my_auth_hostkey_check, "DATA"); // host-key identification - MP_LOG_I("RPC request to RU \"%s\" = with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, user, port); + MP_LOG_I("RPC request to RU \"%s\" = with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, ru_session->username, port); ru_session->session = nc_connect_ssh(ru_session->ru_ip_add, port, NULL); AssertError(ru_session->session != NULL, return false, "[MPLANE] RU IP address %s unreachable. Maybe M-plane is disabled on the RU?\n", ru_session->ru_ip_add); - MP_LOG_I("Successfuly connected to RU \"%s\" with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, user, port); + MP_LOG_I("Successfuly connected to RU \"%s\" with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, ru_session->username, port); return true; } @@ -64,9 +64,18 @@ void disconnect_mplane(void *rus_disconnect) ru_session_t *ru_session = &ru_session_list->ru_session[i]; if (ru_session->session == NULL) continue; + MP_LOG_I("Sending PM de-activation request for RU \"%s\".\n", ru_session->ru_ip_add); + bool success = pm_conf(ru_session, "false"); + if (success) + MP_LOG_I("Successfully de-activated PM for RU \"%s\".\n", ru_session->ru_ip_add); MP_LOG_I("Disconnecting from RU \"%s\".\n", ru_session->ru_ip_add); nc_session_free(ru_session->session, NULL); ru_session->session = NULL; +#ifdef MPLANE_V1 + ly_ctx_destroy((struct ly_ctx *)ru_session->ctx, NULL); +#elif defined MPLANE_V2 + ly_ctx_destroy((struct ly_ctx *)ru_session->ctx); +#endif } nc_client_destroy(); diff --git a/radio/fhi_72/mplane/init-mplane.c b/radio/fhi_72/mplane/init-mplane.c index 39e8cfb995..fc20ba5af4 100644 --- a/radio/fhi_72/mplane/init-mplane.c +++ b/radio/fhi_72/mplane/init-mplane.c @@ -25,6 +25,8 @@ #include "subscribe-mplane.h" #include "config-mplane.h" #include "xml/get-xml.h" +#include "yang/get-yang.h" +#include "yang/create-yang-config.h" #include #include @@ -94,11 +96,14 @@ bool init_mplane(ru_session_list_t *ru_session_list) char **ru_ip_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_IP_ADDR)->strlistptr; int num_rus = gpd(fhip, nump, ORAN_CONFIG_RU_IP_ADDR)->numelt; + char **ru_usernames = gpd(fhip, nump, ORAN_CONFIG_RU_USERNAME)->strlistptr; + int num_ru_users = gpd(fhip, nump, ORAN_CONFIG_RU_USERNAME)->numelt; char **du_mac_addr = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->strlistptr; int num_dus = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->numelt; int32_t *vlan_tag = gpd(fhip, nump, ORAN_CONFIG_VLAN_TAG)->iptr; int num_vlan_tags = gpd(fhip, nump, ORAN_CONFIG_VLAN_TAG)->numelt; + AssertError(num_rus == num_ru_users, return false, "[MPLANE] Number of RUs should be equal to the number of users, one for each.\n"); AssertError(num_dus == num_vlan_tags, return false, "[MPLANE] Number of DU MAC addresses should be equal to the number of VLAN tags.\n"); int num_cu_planes = num_dus / num_rus; @@ -110,6 +115,8 @@ bool init_mplane(ru_session_list_t *ru_session_list) ru_session->session = NULL; ru_session->ru_ip_add = calloc(strlen(ru_ip_addrs[i]) + 1, sizeof(char)); memcpy(ru_session->ru_ip_add, ru_ip_addrs[i], strlen(ru_ip_addrs[i]) + 1); + ru_session->username = calloc(strlen(ru_usernames[i]) + 1, sizeof(char)); + memcpy(ru_session->username, ru_usernames[i], strlen(ru_usernames[i]) + 1); // store DU MAC addresses and VLAN tags ru_session->ru_mplane_config.num_cu_planes = num_cu_planes; @@ -175,15 +182,21 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz success = get_uplane_info(operational_ds, &ru_session->ru_mplane_config); AssertError(success, return false, "[MPLANE] Unable to get U-plane info from RU operational datastore.\n"); + // Performance Management + success = get_pm_object_list(operational_ds, &ru_session->pm_stats); + AssertError(success, return false, "[MPLANE] Unable to retrieve performance measurement names from RU \"%s\".\n", ru_session->ru_ip_add); + + success = load_yang_models(ru_session, operational_ds); + AssertError(success, return false, "[MPLANE] Unable to load yang models.\n"); + if (ru_session->ru_notif.ptp_state) { - success = edit_config_mplane(ru_session, operational_ds, oai, num_rus); - AssertError(success, return false, "[MPLANE] Unable to edit the RU configuration.\n"); + char *content = NULL; + success = configure_ru_from_yang(ru_session, oai, num_rus, &content); + AssertError(success, return false, "[MPLANE] Unable to create content for RPC for start-up procedure.\n"); - success = validate_config_mplane(ru_session); - AssertError(success, return false, "[MPLANE] Unable to validate the RU configuration.\n"); - - success = commit_config_mplane(ru_session); - AssertError(success, return false, "[MPLANE] Unable to commit the RU configuration.\n"); + success = edit_val_commmit_rpc(ru_session, content); + AssertError(success, return false, "[MPLANE] Unable to continue.\n"); + free(content); } const char *usage_state = get_ru_xml_node(operational_ds, "usage-state"); @@ -203,3 +216,15 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz return true; } + +bool pm_conf(ru_session_t *ru_session, const char *active) +{ + char *content = get_pm_content(ru_session, active); + + bool success = edit_val_commmit_rpc(ru_session, content); + AssertError(success, return false, "[MPLANE] Cannot continue.\n"); + + free(content); + + return true; +} diff --git a/radio/fhi_72/mplane/init-mplane.h b/radio/fhi_72/mplane/init-mplane.h index 5077908d64..ef6e23610f 100644 --- a/radio/fhi_72/mplane/init-mplane.h +++ b/radio/fhi_72/mplane/init-mplane.h @@ -29,4 +29,6 @@ bool init_mplane(ru_session_list_t *ru_session_list); bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus); +bool pm_conf(ru_session_t *ru_session, const char *active); + #endif /* OAI_MPLANE_H */ diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c index d387a40864..df4bf3b8ba 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.c +++ b/radio/fhi_72/mplane/ru-mplane-api.c @@ -33,7 +33,7 @@ static void free_match_list(char **match_list, size_t count) free(match_list); } -static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t interface_mtu, const int16_t first_iq_width, const int max_num_ant) +static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t interface_mtu, const int16_t first_iq_width, const int max_num_ant, const char *model_name) { if (interface_mtu == 1500) { MP_LOG_I("Interface MTU %d unreliable/not correctly reported by Benetel O-RU, hardcoding to 9600.\n", interface_mtu); @@ -50,6 +50,14 @@ static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t inter } xran_mplane->prach_offset = max_num_ant; + + if (strcasecmp(model_name, "RAN550") == 0) { + xran_mplane->max_tx_gain = 24.0; + } else if (strcasecmp(model_name, "RAN650") == 0) { + xran_mplane->max_tx_gain = 35.0; + } else { + assert(false && "[MPLANE] Unknown Benetel model name.\n"); + } } bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane) @@ -61,7 +69,7 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ xran_mplane->ru_mac_addr = get_ru_xml_node(buffer, "mac-address"); // TODO: support for VVDN, as it defines multiple MAC addresses // MTU - const uint32_t interface_mtu = (uint32_t)atoi(get_ru_xml_node(buffer, "interface-mtu")); + const uint32_t interface_mtu = (uint32_t)atoi(get_ru_xml_node(buffer, "l2-mtu")); // IQ bitwidth char **match_list = NULL; @@ -91,8 +99,25 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ // RU port ID xran_mplane->ru_port = 0; + // Frame structure + match_list = NULL; + count = 0; + get_ru_xml_list(buffer, "supported-frame-structures", &match_list, &count); + xran_mplane->frame_str = (int16_t)atoi((char *)match_list[0]); + free_match_list(match_list, count); + + // Managed delay support + const char *managed_delay = get_ru_xml_node(buffer, "managed-delay-support"); + xran_mplane->managed_delay = (strcasecmp(managed_delay, "NON_MANAGED") == 0) ? false : true; + + // Store the max gain + xran_mplane->max_tx_gain = (double)atof(get_ru_xml_node(buffer, "max-gain")); + + // Model name + const char *model_name = get_ru_xml_node(buffer, "model-name"); + if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) { - fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant); + fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant, model_name); } else { AssertError(false, return false, "[MPLANE] %s RU currently not supported.\n", ru_vendor); } @@ -109,7 +134,8 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ DU port ID %d\n\ Band sector ID %d\n\ CC ID %d\n\ - RU port ID %d\n", + RU port ID %d\n\ + max Tx gain %.1f\n", xran_mplane->ru_mac_addr, xran_mplane->mtu, xran_mplane->iq_width, @@ -121,7 +147,8 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ xran_mplane->du_port, xran_mplane->band_sector, xran_mplane->ccid, - xran_mplane->ru_port); + xran_mplane->ru_port, + xran_mplane->max_tx_gain); return true; } @@ -155,3 +182,23 @@ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config) return true; } + +bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats) +{ + const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); + if (strcasecmp(ru_vendor, "BENETEL") == 0) { + pm_stats->start_up_timing = false; + } else { + pm_stats->start_up_timing = true; + } + + // Rx window + get_ru_xml_list(buffer, "rx-window-objects", &pm_stats->rx_window_meas, &pm_stats->rx_num); + + // Tx + get_ru_xml_list(buffer, "tx-stats-objects", &pm_stats->tx_meas, &pm_stats->tx_num); + + MP_LOG_I("Successfully retreived all performance measurement names.\n"); + + return true; +} diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index 70857adea6..85fac5515c 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -57,6 +57,10 @@ typedef struct { uint8_t band_sector; uint8_t ccid; uint8_t ru_port; + int16_t frame_str; // might be needed in the future xran releases + bool managed_delay; + + double max_tx_gain; } xran_mplane_t; @@ -78,11 +82,26 @@ typedef struct { } ru_mplane_config_t; typedef struct { + // activation if required at start-up timing + bool start_up_timing; + + size_t rx_num; + char **rx_window_meas; + + size_t tx_num; + char **tx_meas; + +} pm_stats_t; + +typedef struct { + char *username; char *ru_ip_add; ru_mplane_config_t ru_mplane_config; void *session; + void *ctx; xran_mplane_t xran_mplane; ru_notif_t ru_notif; + pm_stats_t pm_stats; } ru_session_t; @@ -97,4 +116,6 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config); +bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats); + #endif /* RU_MPLANE_API_H */ diff --git a/radio/fhi_72/mplane/subscribe-mplane.c b/radio/fhi_72/mplane/subscribe-mplane.c index 9a8e28c4c1..bec7e28a68 100644 --- a/radio/fhi_72/mplane/subscribe-mplane.c +++ b/radio/fhi_72/mplane/subscribe-mplane.c @@ -54,6 +54,37 @@ static void notif_clb_v1(struct nc_session *session, const struct nc_notif *noti recv_notif_v1(notif, answer); } #elif MPLANE_V2 +static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats) +{ + struct lyd_node *child, *field = NULL; + size_t len = 0; + char *meas_list[8], *count_list[8] = {}; + + LY_LIST_FOR(stats->child, child) { + // const char *type = child->schema->name; // e.g. "rx-window-stats", "tx-stats" + struct lyd_node_inner *stats_inner = (struct lyd_node_inner *)child; + LY_LIST_FOR(stats_inner->child, field) { + if (strcmp(field->schema->name, "measurement-object") == 0) { + meas_list[len] = (char *)lyd_get_value(field); + } else if (strcmp(field->schema->name, "count") == 0) { + count_list[len] = (char *)lyd_get_value(field); + len++; + } + } + } + + MP_LOG_I("[PM: \"%s\"][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s][%s %7s]\n", + ru_ip_add, + meas_list[0], count_list[0], + meas_list[1], count_list[1], + meas_list[2], count_list[2], + meas_list[3], count_list[3], + meas_list[4], count_list[4], + meas_list[5], count_list[5], + meas_list[6], count_list[6], + meas_list[7], count_list[7]); +} + static void recv_notif_v2(struct lyd_node_inner *op, ru_notif_t *answer) { const char *notif = op->schema->name; @@ -92,9 +123,14 @@ static void notif_clb_v2(struct nc_session *session, const struct lyd_node *envp char *subs_reply = NULL; lyd_print_mem(&subs_reply, op, output_format, LYD_PRINT_WITHSIBLINGS); const char *ru_ip_add = nc_session_get_host(session); + struct lyd_node_inner *op_inner = (struct lyd_node_inner *)op; + if (strcmp(op_inner->schema->name, "measurement-result-stats") == 0) { + log_v2_pm_info(ru_ip_add, op_inner); + return; + } MP_LOG_I("Received notification from RU \"%s\" at (%s)\n%s\n", ru_ip_add, ((struct lyd_node_opaq *)lyd_child(envp))->value, subs_reply); - recv_notif_v2((struct lyd_node_inner *)op, answer); + recv_notif_v2(op_inner, answer); } #endif diff --git a/radio/fhi_72/mplane/xml/get-xml.c b/radio/fhi_72/mplane/xml/get-xml.c index 616d2e480f..6456219293 100644 --- a/radio/fhi_72/mplane/xml/get-xml.c +++ b/radio/fhi_72/mplane/xml/get-xml.c @@ -68,7 +68,8 @@ static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_li xmlNode *name_node = NULL; for (xmlNode *cur_node2 = cur_node->children; cur_node2; cur_node2 = cur_node2->next) { - if (cur_node2->type == XML_ELEMENT_NODE && strcmp((const char *)cur_node2->name, "name") == 0) { + const char *name_node_str = (const char *)cur_node2->name; + if (cur_node2->type == XML_ELEMENT_NODE && (strcmp(name_node_str, "name") == 0 || strcmp(name_node_str, "measurement-object") == 0)) { name_node = cur_node2; break; } diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 7276b9fae0..187fe5b7c1 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -23,13 +23,14 @@ #include "common/utils/nr/nr_common.h" #define VERIFY_SUCCESS(var, message, args...) AssertError(var, return false, message, ##args) +const char *scs_name[] = {"KHZ_15", "KHZ_30", "KHZ_60", "KHZ_120", "KHZ_240", NULL}; #ifdef MPLANE_V2 -static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) +static bool create_cu_interface_v2(const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; - ret = lyd_new_path(NULL, *ctx, "/ietf-interfaces:interfaces", NULL, 0, root); + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/ietf-interfaces:interfaces", NULL, 0, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"interfaces\" node.\n"); struct lyd_node *interface_node = NULL; @@ -43,7 +44,7 @@ static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_s ret = lyd_new_term(interface_node, NULL, "enabled", "true", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"enabled\" node.\n"); - const struct lys_module *oran_int_mod = ly_ctx_get_module_implemented(*ctx, "o-ran-interfaces"); + const struct lys_module *oran_int_mod = ly_ctx_get_module_implemented((struct ly_ctx *)ru_session->ctx, "o-ran-interfaces"); VERIFY_SUCCESS(oran_int_mod != NULL, "[MPLANE] Failed to get \"o-ran-interfaces\" module.\n"); struct lyd_node *base_int = NULL; @@ -63,11 +64,11 @@ static bool create_cu_interface_v2(struct ly_ctx **ctx, const ru_session_t *ru_s return true; } -static bool create_proc_elem_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) +static bool create_proc_elem_v2(const ru_session_t *ru_session, const size_t idx, const char *int_name, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; - ret = lyd_new_path(NULL, *ctx, "/o-ran-processing-element:processing-elements", NULL, 0, root); + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-processing-element:processing-elements", NULL, 0, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"processing-elements\" node.\n"); ret = lyd_new_term(*root, NULL, "transport-session-type", "ETH-INTERFACE", 0, NULL); @@ -104,20 +105,42 @@ static bool create_proc_elem_v2(struct ly_ctx **ctx, const ru_session_t *ru_sess return true; } -static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx, struct lyd_node **root) +typedef enum { UP_CH_RX, UP_CH_TX } uplane_dir_t; + +static LY_ERR fill_uplane_ch_common_v2(const uplane_dir_t dir, const xran_mplane_t *xran_mplane, const openair0_config_t *oai, const size_t idx, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; - ret = lyd_new_term(*root, NULL, "cp-length", "0", 0, NULL); + char frame_str[8]; + snprintf(frame_str, sizeof(frame_str), "%d", (oai->split7.fftSize << 4) + oai->nr_scs_for_raster); // 3GPP TS 38.211 + ret = lyd_new_term(*root, NULL, "frame-structure", frame_str, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"frame-structure\" node.\n"); + + // EXTENDED not supported + // 3GPP TS 38.211 + const char cp_type[] = "NORMAL"; + ret = lyd_new_term(*root, NULL, "cp-type", cp_type, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-type\" node.\n"); + + char cp_len[8]; + snprintf(cp_len, sizeof(cp_len), "%d", oai->split7.cp_prefix0); + ret = lyd_new_term(*root, NULL, "cp-length", cp_len, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length\" node.\n"); - - ret = lyd_new_term(*root, NULL, "cp-length-other", "0", 0, NULL); + + char cp_len_other[8]; + snprintf(cp_len_other, sizeof(cp_len_other), "%d", oai->split7.cp_prefix_other); + ret = lyd_new_term(*root, NULL, "cp-length-other", cp_len_other, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"cp-length-other\" node.\n"); - - // to we actually store this from DU config file? - ret = lyd_new_term(*root, NULL, "offset-to-absolute-frequency-center", "0", 0, NULL); + + char freq_offset[8]; + if (dir == UP_CH_RX) { + snprintf(freq_offset, sizeof(freq_offset), "%d", oai->split7.ul_k0[oai->nr_scs_for_raster]); + } else { + snprintf(freq_offset, sizeof(freq_offset), "%d", oai->split7.dl_k0[oai->nr_scs_for_raster]); + } + ret = lyd_new_term(*root, NULL, "offset-to-absolute-frequency-center", freq_offset, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"offset-to-absolute-frequency-center\" node.\n"); - + struct lyd_node *compression_node = NULL; ret = lyd_new_inner(*root, NULL, "compression", 0, &compression_node); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression\" node.\n"); @@ -126,15 +149,15 @@ static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx snprintf(iq_width_str, sizeof(iq_width_str), "%d", xran_mplane->iq_width); ret = lyd_new_term(compression_node, NULL, "iq-bitwidth", iq_width_str, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"iq-bitwidth\" node.\n"); - + if (xran_mplane->iq_width < 16) { ret = lyd_new_term(compression_node, NULL, "compression-type", "STATIC", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression-type\" node.\n"); - + // ret = lyd_new_term(compression_node, NULL, "compression-method", "BLOCK_FLOATING_POINT", 0, NULL); // VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"compression-method\" node.\n"); } - + struct lyd_node *eaxc_conf = NULL; ret = lyd_new_inner(*root, NULL, "e-axcid", 0, &eaxc_conf); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"e-axcid\" node.\n"); @@ -143,12 +166,12 @@ static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx snprintf(eaxc_id, sizeof(eaxc_id), "%ld", idx); ret = lyd_new_term(eaxc_conf, NULL, "eaxc-id", eaxc_id, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"eaxc-id\" node.\n"); - + char du_port_bitmask[16]; snprintf(du_port_bitmask, sizeof(du_port_bitmask), "%d", xran_mplane->du_port_bitmask); ret = lyd_new_term(eaxc_conf, NULL, "o-du-port-bitmask", du_port_bitmask, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"o-du-port-bitmask\" node.\n"); - + char band_sector_bitmask[8]; snprintf(band_sector_bitmask, sizeof(band_sector_bitmask), "%d", xran_mplane->band_sector_bitmask); ret = lyd_new_term(eaxc_conf, NULL, "band-sector-bitmask", band_sector_bitmask, 0, NULL); @@ -164,15 +187,50 @@ static bool fill_uplane_ch_v2(const xran_mplane_t *xran_mplane, const size_t idx ret = lyd_new_term(eaxc_conf, NULL, "ru-port-bitmask", ru_port_bitmask, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ru-port-bitmask\" node.\n"); + return LY_SUCCESS; +} + +static bool fill_uplane_ch_rx_v2(const xran_mplane_t *xran_mplane, const openair0_config_t *oai, const size_t idx, struct lyd_node **root) +{ + LY_ERR ret = LY_SUCCESS; + + ret = fill_uplane_ch_common_v2(UP_CH_RX, xran_mplane, oai, idx, root); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); + + const char *managed_delay = xran_mplane->managed_delay ? "true" : "false"; + ret = lyd_new_term(*root, NULL, "non-time-managed-delay-enabled", managed_delay, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"non-time-managed-delay-enabled\" node.\n"); + + struct lyd_node *fft_offset = NULL; + ret = lyd_new_list(*root, NULL, "ul-fft-sampling-offsets", 0, &fft_offset, scs_name[oai->nr_scs_for_raster]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ul-fft-sampling-offsets\" node.\n"); + + // Note: set of allowed values is restricted by SCS derived from values in supported-frame-structures. + char ul_fft_offset[8]; + const int frame = (oai->split7.fftSize << 4) + oai->nr_scs_for_raster; + snprintf(ul_fft_offset, sizeof(ul_fft_offset), "%d", frame - xran_mplane->frame_str); + ret = lyd_new_term(fft_offset, NULL, "ul-fft-sampling-offset", ul_fft_offset, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"ul-fft-sampling-offset\" node.\n"); + return true; } -static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, const char *u_proc_elem, struct lyd_node **root) +static bool fill_uplane_ch_tx_v2(const xran_mplane_t *xran_mplane, const openair0_config_t *oai, const size_t idx, struct lyd_node **root) +{ + LY_ERR ret = LY_SUCCESS; + + ret = fill_uplane_ch_common_v2(UP_CH_TX, xran_mplane, oai, idx, root); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create common nodes.\n"); + + return true; +} + +static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, const char *u_proc_elem, struct lyd_node **root) { LY_ERR ret = LY_SUCCESS; bool success = true; - ret = lyd_new_path(NULL, *ctx, "/o-ran-uplane-conf:user-plane-configuration", NULL, 0, root); + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-uplane-conf:user-plane-configuration", NULL, 0, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"user-plane-configuration\" node.\n"); if (ru_session->ru_mplane_config.rx_carriers.num != 1 || ru_session->ru_mplane_config.tx_carriers.num !=1) @@ -204,7 +262,8 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_term(rx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n"); - // oai->rx_gain_offset is this the correction? if yes, test it later + // gain offset applied uniformly across all array elements or layers + // needs to be within ret = lyd_new_term(rx_carrier_node, NULL, "gain-correction", "0", 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain-correction\" node.\n"); @@ -234,8 +293,12 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_term(tx_carrier_node, NULL, "channel-bandwidth", tx_bw, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n"); - // oai->tx_gain to be tested - ret = lyd_new_term(tx_carrier_node, NULL, "gain", "0", 0, NULL); + // oai->tx_gain takes the value of att_tx from the RU section of gNB config file + // we assume the same gain is applied to all channels; same as above for the frequency + const double tx_gain_value = ((oai->tx_gain[0] * 10000) < ru_session->xran_mplane.max_tx_gain) ? (oai->tx_gain[0] * 10000) : ru_session->xran_mplane.max_tx_gain; + char tx_gain_str[8]; + snprintf(tx_gain_str, sizeof(tx_gain_str), "%.f", tx_gain_value); + ret = lyd_new_term(tx_carrier_node, NULL, "gain", tx_gain_str, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain\" node.\n"); ret = lyd_new_term(tx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL); @@ -254,7 +317,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &pusch_node, ru_session->ru_mplane_config.rx_endpoints.name[i]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n"); - success = fill_uplane_ch_v2(&ru_session->xran_mplane, i, &pusch_node); + success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, oai, i, &pusch_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[i]); const size_t prach_endpoint_name_offset = i + (ru_session->ru_mplane_config.rx_endpoints.num / 2); @@ -262,7 +325,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &prach_node, ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-rx-endpoints\" node.\n"); - success = fill_uplane_ch_v2(&ru_session->xran_mplane, i + ru_session->xran_mplane.prach_offset, &prach_node); + success = fill_uplane_ch_rx_v2(&ru_session->xran_mplane, oai, i + ru_session->xran_mplane.prach_offset, &prach_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-rx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.rx_endpoints.name[prach_endpoint_name_offset]); } @@ -273,7 +336,7 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se ret = lyd_new_list(*root, NULL, "low-level-tx-endpoints", 0, &pdsch_node, ru_session->ru_mplane_config.tx_endpoints.name[i]); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"low-level-tx-endpoints\" node.\n"); - success = fill_uplane_ch_v2(&ru_session->xran_mplane, i, &pdsch_node); + success = fill_uplane_ch_tx_v2(&ru_session->xran_mplane, oai, i, &pdsch_node); VERIFY_SUCCESS(success, "[MPLANE] Failed to fill \"low-level-tx-endpoints\" node for %s.\n", ru_session->ru_mplane_config.tx_endpoints.name[i]); } @@ -333,9 +396,59 @@ static bool create_uplane_conf_v2(struct ly_ctx **ctx, const ru_session_t *ru_se return true; } + +static +bool create_pm_conf_v2(const ru_session_t *ru_session, const char *active, struct lyd_node **root) +{ + LY_ERR ret = LY_SUCCESS; + + ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-performance-management:performance-measurement-objects", NULL, 0, root); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"performance-measurement-objects\" node.\n"); + + ret = lyd_new_term(*root, NULL, "notification-interval", "10", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"notification-interval\" node.\n"); + + ret = lyd_new_term(*root, NULL, "rx-window-measurement-interval", "10", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-window-measurement-interval\" node.\n"); + + ret = lyd_new_term(*root, NULL, "tx-measurement-interval", "10", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-measurement-interval\" node.\n"); + + for (size_t i = 0; i < ru_session->pm_stats.rx_num; i++) { + struct lyd_node *rx_window_meas_objects = NULL; + ret = lyd_new_list(*root, NULL, "rx-window-measurement-objects", 0, &rx_window_meas_objects, ru_session->pm_stats.rx_window_meas[i]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-window-measurement-objects\" node.\n"); + + ret = lyd_new_term(rx_window_meas_objects, NULL, "active", active, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + + ret = lyd_new_term(rx_window_meas_objects, NULL, "object-unit", "RU", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"object-unit\" node.\n"); + + ret = lyd_new_term(rx_window_meas_objects, NULL, "report-info", "COUNT", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"report-info\" node.\n"); + } + + for (size_t i = 0; i < ru_session->pm_stats.tx_num; i++) { + struct lyd_node *tx_meas_objects = NULL; + ret = lyd_new_list(*root, NULL, "tx-measurement-objects", 0, &tx_meas_objects, ru_session->pm_stats.tx_meas[i]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-measurement-objects\" node.\n"); + + ret = lyd_new_term(tx_meas_objects, NULL, "active", active, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + + ret = lyd_new_term(tx_meas_objects, NULL, "object-unit", "RU", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"object-unit\" node.\n"); + + ret = lyd_new_term(tx_meas_objects, NULL, "report-info", "COUNT", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"report-info\" node.\n"); + } + + return true; +} #endif -bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result) +bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result) { bool success = false; @@ -357,12 +470,12 @@ bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, struct lyd_node *cu_interface = NULL; char int_name[12]; snprintf(int_name, sizeof(int_name), "INTERFACE_%ld", i); - success = create_cu_interface_v2(ctx, ru_session, i, int_name, &cu_interface); + success = create_cu_interface_v2(ru_session, i, int_name, &cu_interface); VERIFY_SUCCESS(success, "[MPLANE] Cannot create CU-plane interface.\n"); // struct lyd_node *proc_elem = NULL; - success = create_proc_elem_v2(ctx, ru_session, i, int_name, &proc_elem); + success = create_proc_elem_v2(ru_session, i, int_name, &proc_elem); VERIFY_SUCCESS(success, "[MPLANE] Cannot create CU-plane processing element.\n"); ret = lyd_merge_siblings(&all_merge, cu_interface, 0); @@ -376,17 +489,49 @@ bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, // struct lyd_node *uplane_conf = NULL; - success = create_uplane_conf_v2(ctx, ru_session, oai, num_rus, "PLANE_0", &uplane_conf); + success = create_uplane_conf_v2(ru_session, oai, num_rus, "PLANE_0", &uplane_conf); VERIFY_SUCCESS(success, "[MPLANE] Cannot create U-plane configuration.\n"); - - ret = lyd_merge_siblings(&uplane_conf, all_merge, 0); + + ret = lyd_merge_siblings(&all_merge, uplane_conf, 0); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element and U-plane configuration.\n"); - lyd_print_mem(result, uplane_conf, LYD_XML, LYD_PRINT_WITHSIBLINGS); + // + struct lyd_node *pm_conf = NULL; + if (ru_session->pm_stats.start_up_timing) { + success = create_pm_conf_v2(ru_session, "true", &pm_conf); + VERIFY_SUCCESS(success, "[MPLANE] Cannot create PM activation.\n"); + } else { + success = create_pm_conf_v2(ru_session, "false", &pm_conf); + VERIFY_SUCCESS(success, "[MPLANE] Cannot create PM deactivation.\n"); + } + + ret = lyd_merge_siblings(&all_merge, pm_conf, 0); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Cannot merge CU-plane interface, processing element, U-plane configuration and PM configuration.\n"); + + lyd_print_mem(result, all_merge, LYD_XML, LYD_PRINT_WITHSIBLINGS); lyd_free_siblings(all_merge); lyd_free_siblings(uplane_conf); + lyd_free_siblings(pm_conf); #endif return true; } + +char *get_pm_content(const ru_session_t *ru_session, const char *active) +{ + bool success = false; + char *content = NULL; + +#ifdef MPLANE_V1 + VERIFY_SUCCESS(success, "[MPLANE] To be implemented and tested.\n"); +#elif defined MPLANE_V2 + struct lyd_node *pm_conf = NULL; + success = create_pm_conf_v2(ru_session, active, &pm_conf); + AssertError(success, return false, "[MPLANE] Cannot create PM configuration.\n"); + lyd_print_mem(&content, pm_conf, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(pm_conf); +#endif + + return content; +} diff --git a/radio/fhi_72/mplane/yang/create-yang-config.h b/radio/fhi_72/mplane/yang/create-yang-config.h index 9e06bdc923..2f03a3f774 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.h +++ b/radio/fhi_72/mplane/yang/create-yang-config.h @@ -27,6 +27,8 @@ #include -bool configure_ru_from_yang(struct ly_ctx **ctx, const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result); +bool configure_ru_from_yang(const ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus, char **result); + +char *get_pm_content(const ru_session_t *ru_session, const char *active); #endif /* CREATE_MPLANE_YANG_CONFIG_H */ diff --git a/radio/fhi_72/mplane/yang/get-yang.c b/radio/fhi_72/mplane/yang/get-yang.c index c27454136f..60131b34cf 100644 --- a/radio/fhi_72/mplane/yang/get-yang.c +++ b/radio/fhi_72/mplane/yang/get-yang.c @@ -95,8 +95,10 @@ static bool load_from_operational_ds(xmlNode *node, ru_session_t *ru_session, st return false; } -bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx) +bool load_yang_models(ru_session_t *ru_session, const char *buffer) { + struct ly_ctx **ctx = (struct ly_ctx **)&ru_session->ctx; + // Initialize the xml file size_t len = strlen(buffer) + 1; xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0); @@ -114,7 +116,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ct 1) the yang models order is not good - the dependancy models have to be loaded first 2) earlier O-RAN yang versions (e.g. v4) is not properly defined (i.e. optional parameters should not be included by default) */ const char *yang_dir = YANG_MODELS; - const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "o-ran-processing-element", "o-ran-uplane-conf"}; + const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "o-ran-processing-element", "o-ran-uplane-conf", "ietf-netconf-acm", "ietf-crypto-types", "o-ran-file-management", "o-ran-performance-management"}; #ifdef MPLANE_V1 *ctx = ly_ctx_new(yang_dir, 0); diff --git a/radio/fhi_72/mplane/yang/get-yang.h b/radio/fhi_72/mplane/yang/get-yang.h index 5956bde203..7ca191d234 100644 --- a/radio/fhi_72/mplane/yang/get-yang.h +++ b/radio/fhi_72/mplane/yang/get-yang.h @@ -26,6 +26,6 @@ #include -bool load_yang_models(ru_session_t *ru_session, const char *buffer, struct ly_ctx **ctx); +bool load_yang_models(ru_session_t *ru_session, const char *buffer); #endif /* GET_MPLANE_YANG_MODELS_H */ diff --git a/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang b/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang new file mode 100644 index 0000000000..1b94b03176 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang @@ -0,0 +1,1783 @@ +module ietf-crypto-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-crypto-types"; + prefix ct; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + Author: Kent Watsen + Author: Wang Haiguang "; + + description + "This module defines common YANG types for cryptographic + applications. + + Copyright (c) 2019 IETF Trust and the persons identified + as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with + or without modification, is permitted pursuant to, and + subject to the license terms contained in, the Simplified + BSD License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC + itself for full legal notices.; + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', + 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', + 'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document + are to be interpreted as described in BCP 14 (RFC 2119) + (RFC 8174) when, and only when, they appear in all + capitals, as shown here."; + + revision 2019-04-29 { + description + "Initial version"; + reference + "RFC XXXX: Common YANG Data Types for Cryptography"; + } + + /**************************************/ + /* Identities for Hash Algorithms */ + /**************************************/ + + identity hash-algorithm { + description + "A base identity for hash algorithm verification."; + } + + identity sha-224 { + base hash-algorithm; + description + "The SHA-224 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + identity sha-256 { + base hash-algorithm; + description + "The SHA-256 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + identity sha-384 { + base hash-algorithm; + description + "The SHA-384 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + identity sha-512 { + base hash-algorithm; + description + "The SHA-512 algorithm."; + reference + "RFC 6234: US Secure Hash Algorithms."; + } + + /***********************************************/ + /* Identities for Asymmetric Key Algorithms */ + /***********************************************/ + + identity asymmetric-key-algorithm { + description + "Base identity from which all asymmetric key + encryption Algorithm."; + } + + identity rsa1024 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 1024-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa2048 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 2048-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa3072 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 3072-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa4096 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 4096-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa7680 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 7680-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa15360 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 15360-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity secp192r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + identity secp224r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp256r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp384r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp521r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + /*************************************/ + /* Identities for MAC Algorithms */ + /*************************************/ + + identity mac-algorithm { + description + "A base identity for mac generation."; + } + + identity hmac-sha1 { + base mac-algorithm; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 3174: US Secure Hash Algorithm 1 (SHA1)"; + } + + identity hmac-sha1-96 { + base mac-algorithm; + description + "Generating MAC using SHA1 hash function"; + reference + "RFC 2404: The Use of HMAC-SHA-1-96 within ESP and AH"; + } + + identity hmac-sha2-224 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-256 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-256-128 { + base mac-algorithm; + description + "Generating a 256 bits MAC using SHA2 hash function and + truncate it to 128 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 + with IPsec"; + } + + identity hmac-sha2-384 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-384-192 { + base mac-algorithm; + description + "Generating a 384 bits MAC using SHA2 hash function and + truncate it to 192 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with + IPsec"; + } + + identity hmac-sha2-512 { + base mac-algorithm; + description + "Generating MAC using SHA2 hash function"; + reference + "RFC 6234: + US Secure Hash Algorithms (SHA and SHA-based HMAC and + HKDF)"; + } + + identity hmac-sha2-512-256 { + base mac-algorithm; + description + "Generating a 512 bits MAC using SHA2 hash function and + truncating it to 256 bits"; + reference + "RFC 4868: + Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with + IPsec"; + } + + identity aes-128-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-192-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-256-gmac { + base mac-algorithm; + description + "Generating MAC using the Advanced Encryption Standard (AES) + Galois Message Authentication Code (GMAC) as a mechanism to + provide data origin authentication"; + reference + "RFC 4543: + The Use of Galois Message Authentication Code (GMAC) in + IPsec ESP and AH"; + } + + identity aes-cmac-96 { + base mac-algorithm; + description + "Generating MAC using Advanced Encryption Standard (AES) + Cipher-based Message Authentication Code (CMAC)"; + reference + "RFC 4494: The AES-CMAC-96 Algorithm and its Use with IPsec"; + } + + identity aes-cmac-128 { + base mac-algorithm; + description + "Generating MAC using Advanced Encryption Standard (AES) + Cipher-based Message Authentication Code (CMAC)"; + reference + "RFC 4493: The AES-CMAC Algorithm"; + } + + /********************************************/ + /* Identities for Encryption Algorithms */ + /********************************************/ + + identity encryption-algorithm { + description + "A base identity for encryption algorithm."; + } + + identity aes-128-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 128 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-192-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 192 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-256-cbc { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CBC mode with a key + length of 256 bits"; + reference + "RFC 3565: + Use of the Advanced Encryption Standard (AES) Encryption + Algorithm in Cryptographic Message Syntax (CMS)"; + } + + identity aes-128-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 128 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + identity aes-192-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 192 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-256-ctr { + base encryption-algorithm; + description + "Encrypt message with AES algorithm in CTR mode with a key + length of 256 bits"; + reference + "RFC 3686: + Using Advanced Encryption Standard (AES) Counter Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + /****************************************************/ + /* Identities for Encryption and MAC Algorithms */ + /****************************************************/ + + identity encryption-and-mac-algorithm { + description + "A base identity for encryption and MAC algorithm."; + } + + identity aes-128-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-192-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 192 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-256-ccm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in CCM mode with a key + length of 256 bits; it can also be used for generating MAC"; + reference + "RFC 4309: + Using Advanced Encryption Standard (AES) CCM Mode with + IPsec Encapsulating Security Payload (ESP)"; + } + + identity aes-128-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + + identity aes-192-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 192 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + + identity mac-aes-256-gcm { + base encryption-and-mac-algorithm; + description + "Encrypt message with AES algorithm in GCM mode with a key + length of 128 bits; it can also be used for generating MAC"; + reference + "RFC 4106: + The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating + Security Payload (ESP)"; + } + identity chacha20-poly1305 { + base encryption-and-mac-algorithm; + description + "Encrypt message with chacha20 algorithm and generate MAC with + POLY1305; it can also be used for generating MAC"; + reference + "RFC 8439: ChaCha20 and Poly1305 for IETF Protocols"; + } + + /******************************************/ + /* Identities for signature algorithm */ + /******************************************/ + + identity signature-algorithm { + description + "A base identity for asymmetric key encryption algorithm."; + } + + identity dsa-sha1 { + base signature-algorithm; + description + "The signature algorithm using DSA algorithm with SHA1 hash + algorithm"; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity rsassa-pkcs1-sha1 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the SHA1 + hash algorithm."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity rsassa-pkcs1-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA256 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell + (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + identity rsassa-pkcs1-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA384 hash algorithm."; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pkcs1-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PKCS1-v1_5 with the + SHA512 hash algorithm."; + reference + "RFC 8332: + Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell + (SSH) Protocol + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA384 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-rsae-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA512 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the rsaEncryption + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha256 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha384 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity rsassa-pss-pss-sha512 { + base signature-algorithm; + description + "The signature algorithm using RSASSA-PSS with mask generation + function 1 and SHA256 hash algorithm. If the public key is + carried in an X.509 certificate, it MUST use the RSASSA-PSS + OID"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp256r1-sha256 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp256r1 + and SHA256 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp384r1-sha384 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp384r1 + and SHA384 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdsa-secp521r1-sha512 { + base signature-algorithm; + description + "The signature algorithm using ECDSA with curve name secp521r1 + and SHA512 hash algorithm."; + reference + "RFC 5656: Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer + RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ed25519 { + base signature-algorithm; + description + "The signature algorithm using EdDSA as defined in RFC 8032 or + its successors."; + reference + "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + + identity ed448 { + base signature-algorithm; + description + "The signature algorithm using EdDSA as defined in RFC 8032 or + its successors."; + reference + "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; + } + + identity eccsi { + base signature-algorithm; + description + "The signature algorithm using ECCSI signature as defined in + RFC 6507."; + reference + "RFC 6507: + Elliptic Curve-Based Certificateless Signatures for + Identity-based Encryption (ECCSI)"; + } + + /**********************************************/ + /* Identities for key exchange algorithms */ + /**********************************************/ + + identity key-exchange-algorithm { + description + "A base identity for Diffie-Hellman based key exchange + algorithm."; + } + + identity psk-only { + base key-exchange-algorithm; + description + "Using Pre-shared key for authentication and key exchange"; + reference + "RFC 4279: + Pre-Shared Key cipher suites for Transport Layer Security + (TLS)"; + } + + identity dhe-ffdhe2048 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 2048 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe3072 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 3072 bit finite + field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe4096 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 4096 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe6144 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 6144 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity dhe-ffdhe8192 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with 8192 bit + finite field"; + reference + "RFC 7919: + Negotiated Finite Field Diffie-Hellman Ephemeral Parameters + for Transport Layer Security (TLS)"; + } + + identity psk-dhe-ffdhe2048 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE2048"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe3072 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE3072"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe4096 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE4096"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe6144 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE6144"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-dhe-ffdhe8192 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with Diffie-Hellman key + generation mechanism, where the DH group is FFDHE8192"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity ecdhe-secp256r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp256r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-secp384r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp384r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-secp521r1 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve secp521r1"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-x25519 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve x25519"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity ecdhe-x448 { + base key-exchange-algorithm; + description + "Ephemeral Diffie Hellman key exchange with elliptic group + over curve x448"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity psk-ecdhe-secp256r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp256r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-secp384r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp384r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-secp521r1 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve secp521r1"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-x25519 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve x25519"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity psk-ecdhe-x448 { + base key-exchange-algorithm; + description + "Key exchange using pre-shared key with elliptic group-based + Ephemeral Diffie Hellman key exchange over curve x448"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity diffie-hellman-group14-sha1 { + base key-exchange-algorithm; + description + "Using DH group14 and SHA1 for key exchange"; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity diffie-hellman-group14-sha256 { + base key-exchange-algorithm; + description + "Using DH group14 and SHA256 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group15-sha512 { + base key-exchange-algorithm; + description + "Using DH group15 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group16-sha512 { + base key-exchange-algorithm; + description + "Using DH group16 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group17-sha512 { + base key-exchange-algorithm; + description + "Using DH group17 and SHA512 for key exchange"; + + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity diffie-hellman-group18-sha512 { + base key-exchange-algorithm; + description + "Using DH group18 and SHA512 for key exchange"; + reference + "RFC 8268: + More Modular Exponentiation (MODP) Diffie-Hellman (DH) + Key Exchange (KEX) Groups for Secure Shell (SSH)"; + } + + identity ecdh-sha2-secp256r1 { + base key-exchange-algorithm; + description + "Elliptic curve-based Diffie Hellman key exchange over curve + secp256r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: Suite B Cryptographic Suites for Secure Shell + (SSH)"; + } + + identity ecdh-sha2-secp384r1 { + base key-exchange-algorithm; + description + "Elliptic curve-based Diffie Hellman key exchange over curve + secp384r1 and using SHA2 for MAC generation"; + reference + "RFC 6239: Suite B Cryptographic Suites for Secure Shell + (SSH)"; + } + + identity rsaes-oaep { + base key-exchange-algorithm; + description + "RSAES-OAEP combines the RSAEP and RSADP primitives with the + EME-OAEP encoding method"; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsaes-pkcs1-v1_5 { + base key-exchange-algorithm; + description + " RSAES-PKCS1-v1_5 combines the RSAEP and RSADP primitives + with the EME-PKCS1-v1_5 encoding method"; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + /**********************************************************/ + /* Typedefs for identityrefs to above base identities */ + /**********************************************************/ + + typedef hash-algorithm-ref { + type identityref { + base hash-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'hash-algorithm' base identity."; + } + + typedef signature-algorithm-ref { + type identityref { + base signature-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'signature-algorithm' base identity."; + } + + typedef mac-algorithm-ref { + type identityref { + base mac-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'mac-algorithm' base identity."; + } + + typedef encryption-algorithm-ref { + type identityref { + base encryption-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'encryption-algorithm' + base identity."; + } + + typedef encryption-and-mac-algorithm-ref { + type identityref { + base encryption-and-mac-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'encryption-and-mac-algorithm' + base identity."; + } + + typedef asymmetric-key-algorithm-ref { + type identityref { + base asymmetric-key-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'asymmetric-key-algorithm' + base identity."; + } + + typedef key-exchange-algorithm-ref { + type identityref { + base key-exchange-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'key-exchange-algorithm' base identity."; + } + + /***************************************************/ + /* Typedefs for ASN.1 structures from RFC 5280 */ + /***************************************************/ + + typedef x509 { + type binary; + description + "A Certificate structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef crl { + type binary; + description + "A CertificateList structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + /***********************************************/ + /* Typedefs for ASN.1 structures from 5652 */ + /***********************************************/ + + typedef cms { + type binary; + description + "A ContentInfo structure, as specified in RFC 5652, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5652: + Cryptographic Message Syntax (CMS) + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef data-content-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + data content type, as described by Section 4 in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef signed-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + signed-data content type, as described by Section 5 in + RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef enveloped-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + enveloped-data content type, as described by Section 6 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef digested-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + digested-data content type, as described by Section 7 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef encrypted-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + encrypted-data content type, as described by Section 8 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef authenticated-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + authenticated-data content type, as described by Section 9 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + /***************************************************/ + /* Typedefs for structures related to RFC 4253 */ + /***************************************************/ + + typedef ssh-host-key { + type binary; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5280 */ + /*********************************************************/ + + typedef trust-anchor-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a self-signed + root certificate."; + } + + typedef end-entity-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a certificate + that is neither self-signed nor having Basic constraint + CA true."; + } + + /*********************************************************/ + /* Typedefs for ASN.1 structures related to RFC 5652 */ + /*********************************************************/ + + typedef trust-anchor-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the chain of + X.509 certificates needed to authenticate the certificate + presented by a client or end-entity. + + The CMS MUST contain only a single chain of certificates. + The client or end-entity certificate MUST only authenticate + to last intermediate CA certificate listed in the chain. + + In all cases, the chain MUST include a self-signed root + certificate. In the case where the root certificate is + itself the issuer of the client or end-entity certificate, + only one certificate is present. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + typedef end-entity-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the end + entity certificate itself, and MAY contain any number + of intermediate certificates leading up to a trust + anchor certificate. The trust anchor certificate + MAY be included as well. + + The CMS MUST contain a single end entity certificate. + The CMS MUST NOT contain any spurious certificates. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure that is commonly used to disseminate X.509 + certificates and revocation objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile."; + } + + /**********************************************/ + /* Groupings for keys and/or certificates */ + /**********************************************/ + + grouping public-key-grouping { + description + "A public key. + + The 'algorithm' and 'public-key' nodes are not + mandatory because they MAY be defined in . + Implementations SHOULD assert that these values are + either configured or that they exist in ."; + leaf algorithm { + nacm:default-deny-write; + type asymmetric-key-algorithm-ref; + must '../public-key'; + description + "Identifies the key's algorithm. More specifically, + this leaf specifies how the 'public-key' binary leaf + is encoded."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key { + nacm:default-deny-write; + type binary; + must '../algorithm'; + description + "A binary that contains the value of the public key. The + interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPublicKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented using the 'publicKey' described in + RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + } + + grouping asymmetric-key-pair-grouping { + description + "A private/public key pair. + The 'algorithm', 'public-key', and 'private-key' nodes are + not mandatory because they MAY be defined in . + Implementations SHOULD assert that these values are either + configured or that they exist in ."; + uses public-key-grouping; + leaf private-key { + nacm:default-deny-all; + type union { + type binary; + type enumeration { + enum permanently-hidden { + description + "The private key is inaccessible due to being + protected by the system (e.g., a cryptographic + hardware module). + + How such keys are backed-up and restored, if + at all, is implementation specific. + + Servers MUST fail any attempt by a client to + configure this value directly. This value is + not set by clients, but rather is set by the + 'generate-hidden-key' and 'install-hidden-key' + actions."; + } + } + } + must '../public-key'; + description + "A binary that contains the value of the private key. The + interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPrivateKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented as ECPrivateKey as defined in RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } // private-key + + action generate-hidden-key { + nacm:default-deny-all; + description + "Requests the device to generate a hidden key using the + specified asymmetric key algorithm. This action is + used to request the system to generate a key that is + 'permanently-hidden', perhaps protected by a cryptographic + hardware module. The resulting asymmetric key values are + considered operational state and hence present only in + and bound to the lifetime of the parent + 'config true' node. Subsequent invocations of this or + the 'install-hidden-key' action are denied with error-tag + 'data-exists'."; + input { + leaf algorithm { + type asymmetric-key-algorithm-ref; + mandatory true; + description + "The algorithm to be used when generating the + asymmetric key."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + } + } // generate-hidden-key + + action install-hidden-key { + nacm:default-deny-all; + description + "Requests the device to load the specified values into + a hidden key. The resulting asymmetric key values are + considered operational state and hence present only in + and bound to the lifetime of the parent + 'config true' node. Subsequent invocations of this + or the 'generate-hidden-key' action are denied with + error-tag 'data-exists'."; + input { + leaf algorithm { + type asymmetric-key-algorithm-ref; + mandatory true; + description + "The algorithm to be used when generating the + asymmetric key."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key { + type binary; + description + "A binary that contains the value of the public key. + The interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an + RSA key is represented as RSAPublicKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented using the 'publicKey' described in + RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + leaf private-key { + type binary; + description + "A binary that contains the value of the private key. + The interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPrivateKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented as ECPrivateKey as defined in RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + } + } // install-hidden-key + } // asymmetric-key-pair-grouping + + + grouping trust-anchor-cert-grouping { + description + "A trust anchor certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping trust-anchor-certs-grouping { + description + "A list of trust anchor certificates, and a notification + for when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-cert-grouping { + description + "An end entity certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping end-entity-certs-grouping { + description + "A list of end entity certificates, and a notification for + when one is about to (or already has) expire."; + leaf-list cert { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + reference + "RFC YYYY: Common YANG Data Types for Cryptography"; + } + notification certificate-expiration { + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping asymmetric-key-pair-with-cert-grouping { + description + "A private/public key pair and an associated certificate."; + uses asymmetric-key-pair-grouping; + uses end-entity-cert-grouping; + + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-cert-grouping + + + grouping asymmetric-key-pair-with-certs-grouping { + description + "A private/public key pair and associated certificates."; + uses asymmetric-key-pair-grouping; + container certificates { + nacm:default-deny-write; + description + "Certificates associated with this asymmetric key. + More than one certificate supports, for instance, + a TPM-protected asymmetric key that has both IDevID + and LDevID certificates associated."; + list certificate { + key "name"; + description + "A certificate for this asymmetric key."; + leaf name { + type string; + description + "An arbitrary name for the certificate. If the name + matches the name of a certificate that exists + independently in (i.e., an IDevID), + then the 'cert' node MUST NOT be configured."; + } + uses end-entity-cert-grouping; + } + } // certificates + + action generate-certificate-signing-request { + nacm:default-deny-all; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. The specified assertions need + to be appropriate for the certificate's use. For + example, an entity certificate for a TLS server + SHOULD have values that enable clients to satisfy + RFC 6125 processing."; + input { + leaf subject { + type binary; + mandatory true; + description + "The 'subject' field per the CertificationRequestInfo + structure as specified by RFC 2986, Section 4.1 + encoded using the ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + leaf attributes { + type binary; + description + "The 'attributes' field from the structure + CertificationRequestInfo as specified by RFC 2986, + Section 4.1 encoded using the ASN.1 distinguished + encoding rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + output { + leaf certificate-signing-request { + type binary; + mandatory true; + description + "A CertificationRequest structure as specified by + RFC 2986, Section 4.2 encoded using the ASN.1 + distinguished encoding rules (DER), as specified + in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax + Specification Version 1.7. + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + } + } // generate-certificate-signing-request + } // asymmetric-key-pair-with-certs-grouping +} diff --git a/radio/fhi_72/mplane/yang/models/ietf-netconf-acm.yang b/radio/fhi_72/mplane/yang/models/ietf-netconf-acm.yang new file mode 100644 index 0000000000..ec9687a9d7 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/ietf-netconf-acm.yang @@ -0,0 +1,440 @@ +module ietf-netconf-acm { + + namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"; + + prefix nacm; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + Author: Andy Bierman + + Author: Martin Bjorklund + "; + + description + "Network Configuration Access Control Model. + Copyright (c) 2012 - 2018 IETF Trust and the persons + identified as authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 8341; see + the RFC itself for full legal notices."; + + revision "2018-02-14" { + description + "Added support for YANG 1.1 actions and notifications tied to + data nodes. Clarified how NACM extensions can be used by + other data models."; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + revision "2012-02-22" { + description + "Initial version."; + reference + "RFC 6536: Network Configuration Protocol (NETCONF) + Access Control Model"; + } + + /* + * Extension statements + */ + + extension default-deny-write { + description + "Used to indicate that the data model node + represents a sensitive security system parameter. + If present, the NETCONF server will only allow the designated + 'recovery session' to have write access to the node. An + explicit access control rule is required for all other users. + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + The 'default-deny-write' extension MAY appear within a data + definition statement. It is ignored otherwise."; + } + + extension default-deny-all { + description + "Used to indicate that the data model node + controls a very sensitive security system parameter. + If present, the NETCONF server will only allow the designated + 'recovery session' to have read, write, or execute access to + the node. An explicit access control rule is required for all + other users. + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + The 'default-deny-all' extension MAY appear within a data + definition statement, 'rpc' statement, or 'notification' + statement. It is ignored otherwise."; + } + + /* + * Derived types + */ + + typedef user-name-type { + type string { + length "1..max"; + } + description + "General-purpose username string."; + } + + typedef matchall-string-type { + type string { + pattern '\*'; + } + description + "The string containing a single asterisk '*' is used + to conceptually represent all possible values + for the particular leaf using this data type."; + } + + typedef access-operations-type { + type bits { + bit create { + description + "Any protocol operation that creates a + new data node."; + } + bit read { + description + "Any protocol operation or notification that + returns the value of a data node."; + } + bit update { + description + "Any protocol operation that alters an existing + data node."; + } + bit delete { + description + "Any protocol operation that removes a data node."; + } + bit exec { + description + "Execution access to the specified protocol operation."; + } + } + description + "Access operation."; + } + + typedef group-name-type { + type string { + length "1..max"; + pattern '[^\*].*'; + } + description + "Name of administrative group to which + users can be assigned."; + } + + typedef action-type { + type enumeration { + enum permit { + description + "Requested action is permitted."; + } + enum deny { + description + "Requested action is denied."; + } + } + description + "Action taken by the server when a particular + rule matches."; + } + + typedef node-instance-identifier { + type yang:xpath1.0; + description + "Path expression used to represent a special + data node, action, or notification instance-identifier + string. + A node-instance-identifier value is an + unrestricted YANG instance-identifier expression. + All the same rules as an instance-identifier apply, + except that predicates for keys are optional. If a key + predicate is missing, then the node-instance-identifier + represents all possible server instances for that key. + This XML Path Language (XPath) expression is evaluated in the + following context: + o The set of namespace declarations are those in scope on + the leaf element where this type is used. + o The set of variable bindings contains one variable, + 'USER', which contains the name of the user of the + current session. + o The function library is the core function library, but + note that due to the syntax restrictions of an + instance-identifier, no functions are allowed. + o The context node is the root node in the data tree. + The accessible tree includes actions and notifications tied + to data nodes."; + } + + /* + * Data definition statements + */ + + container nacm { + nacm:default-deny-all; + + description + "Parameters for NETCONF access control model."; + + leaf enable-nacm { + type boolean; + default "true"; + description + "Enables or disables all NETCONF access control + enforcement. If 'true', then enforcement + is enabled. If 'false', then enforcement + is disabled."; + } + + leaf read-default { + type action-type; + default "permit"; + description + "Controls whether read access is granted if + no appropriate rule is found for a + particular read request."; + } + + leaf write-default { + type action-type; + default "deny"; + description + "Controls whether create, update, or delete access + is granted if no appropriate rule is found for a + particular write request."; + } + + leaf exec-default { + type action-type; + default "permit"; + description + "Controls whether exec access is granted if no appropriate + rule is found for a particular protocol operation request."; + } + + leaf enable-external-groups { + type boolean; + default "true"; + description + "Controls whether the server uses the groups reported by the + NETCONF transport layer when it assigns the user to a set of + NACM groups. If this leaf has the value 'false', any group + names reported by the transport layer are ignored by the + server."; + } + + leaf denied-operations { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request was denied."; + } + + leaf denied-data-writes { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request to alter + a configuration datastore was denied."; + } + + leaf denied-notifications { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that + a notification was dropped for a subscription because + access to the event type was denied."; + } + + container groups { + description + "NETCONF access control groups."; + + list group { + key name; + + description + "One NACM group entry. This list will only contain + configured entries, not any entries learned from + any transport protocols."; + + leaf name { + type group-name-type; + description + "Group name associated with this entry."; + } + + leaf-list user-name { + type user-name-type; + description + "Each entry identifies the username of + a member of the group associated with + this entry."; + } + } + } + + list rule-list { + key name; + ordered-by user; + description + "An ordered collection of access control rules."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule-list."; + } + leaf-list group { + type union { + type matchall-string-type; + type group-name-type; + } + description + "List of administrative groups that will be + assigned the associated access rights + defined by the 'rule' list. + The string '*' indicates that all groups apply to the + entry."; + } + + list rule { + key name; + ordered-by user; + description + "One access control rule. + Rules are processed in user-defined order until a match is + found. A rule matches if 'module-name', 'rule-type', and + 'access-operations' match the request. If a rule + matches, the 'action' leaf determines whether or not + access is granted."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule."; + } + + leaf module-name { + type union { + type matchall-string-type; + type string; + } + default "*"; + description + "Name of the module associated with this rule. + This leaf matches if it has the value '*' or if the + object being accessed is defined in the module with the + specified module name."; + } + choice rule-type { + description + "This choice matches if all leafs present in the rule + match the request. If no leafs are present, the + choice matches all requests."; + case protocol-operation { + leaf rpc-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if + its value equals the requested protocol operation + name."; + } + } + case notification { + leaf notification-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if its + value equals the requested notification name."; + } + } + + case data-node { + leaf path { + type node-instance-identifier; + mandatory true; + description + "Data node instance-identifier associated with the + data node, action, or notification controlled by + this rule. + Configuration data or state data + instance-identifiers start with a top-level + data node. A complete instance-identifier is + required for this type of path value. + The special value '/' refers to all possible + datastore contents."; + } + } + } + + leaf access-operations { + type union { + type matchall-string-type; + type access-operations-type; + } + default "*"; + description + "Access operations associated with this rule. + This leaf matches if it has the value '*' or if the + bit corresponding to the requested operation is set."; + } + + leaf action { + type action-type; + mandatory true; + description + "The access control action associated with the + rule. If a rule has been determined to match a + particular request, then this object is used + to determine whether to permit or deny the + request."; + } + + leaf comment { + type string; + description + "A textual description of the access rule."; + } + } + } + } +} diff --git a/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang b/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang new file mode 100644 index 0000000000..ee07645a44 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang @@ -0,0 +1,213 @@ +module o-ran-file-management { + yang-version 1.1; + namespace "urn:o-ran:file-management:1.0"; + prefix "o-ran-file-mgmt"; + + import ietf-crypto-types { + prefix "ct"; + } + + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the configuration and operations for handling upload. + + Copyright 2019 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) backward compatible changes to correct sFTP Server Authentication . + 2) minor fixes according to lack of descriptions + 3) backward compatible changes to introduce groupings"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + grouping file-path-grouping { + description "Complete logical path of the file to upload/download + (no wildcard is allowed) ex : /o-RAN/log/syslog.1"; + + leaf local-logical-file-path { + type string; + mandatory true; + description "Local logical file path"; + } + + leaf remote-file-path { + type string; + mandatory true; + description "URI specifying the remote-file-path on O-DU/NMS. + Format:sftp://@[:port]/path"; + } + } + + grouping output-status-grouping { + description "Status grouping"; + + leaf status { + type enumeration { + enum SUCCESS { + description "";} + enum FAILURE { + description "";} + } + description "Operation status"; + } + + leaf reject-reason { + when "../status = 'FAILURE'"; + type string; + description ""; + } + } + + grouping credential-information { + description "Type of authentication to use for SFTP upload or download."; + choice credentials { + case password { + container password { + presence true; + leaf password { + type string; + mandatory true; + description + "password needed for O-RU authentication."; + } + description + "password for O-RU authentication method in use"; + } + container server { + list keys { + key algorithm; + ordered-by user; + uses ct:public-key-grouping; + description + "List of allowed algorithms with its keys"; + } + description + "Key for sFTP server authentication"; + } + } + case certificate { + container certificate { + presence true; + description + "certificate authentication method in use"; + } + } + description ""; + } + } + + grouping retrieve-input { + description "Grouping for information retrieval RPC input"; + leaf logical-path { + type string; + mandatory true; + description "O-RAN unit of which the files are to be listed. + ex : O-RAN/log, o-RAN/PM, O-RAN/transceiver"; + } + leaf file-name-filter { + type string; + description "Filter which are to be applied on the result list of file names (* is allowed as wild-card)."; + } + } + + grouping retrieve-output { + description "Grouping for information retrieval RPC output"; + uses output-status-grouping; + leaf-list file-list { + when "../status = 'SUCCESS'"; + type string; + description "List of files in the unit with the filter applied."; + } + } + +// RPCs + + rpc file-upload { + description "File upload over SFTP from equipment to NETCONF client"; + input { + uses file-path-grouping; + uses credential-information; + } + output { + uses output-status-grouping; + } + } + + rpc retrieve-file-list { + description "List all the files in the logical O-RAN unit (* is allowed as wild-card)."; + input { + uses retrieve-input; + + } + output { + uses retrieve-output; + } + } + + notification file-upload-notification { + uses file-path-grouping; + uses output-status-grouping; + description ""; + } + + rpc file-download { + description + "Management plane triggered to generate the download file of O-RU."; + input { + uses file-path-grouping; + uses credential-information; + } + output { + uses output-status-grouping; + } + } + + notification file-download-event { + uses file-path-grouping; + uses output-status-grouping; + description ""; + } +} diff --git a/radio/fhi_72/mplane/yang/models/o-ran-performance-management.yang b/radio/fhi_72/mplane/yang/models/o-ran-performance-management.yang new file mode 100644 index 0000000000..fb8298f663 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-performance-management.yang @@ -0,0 +1,1168 @@ +module o-ran-performance-management { + yang-version 1.1; + namespace "urn:o-ran:performance-management:1.0"; + prefix "o-ran-pm"; + + import ietf-yang-types { + prefix "yang-types"; + revision-date 2013-07-15; + } + + // import idetifier for O-RU + import ietf-hardware { + prefix "hw"; + } + + // import ietf-interface + import ietf-interfaces { + prefix "if"; + } + + // import ietf-inet-type + import ietf-inet-types { + prefix "inet"; + } + + // import port-number + import o-ran-interfaces { + prefix "o-ran-int"; + } + + // import ru-mac-address, o-du-mac-address and vlan-id + import o-ran-processing-element { + prefix "o-ran-elements"; + } + + import o-ran-file-management { + prefix "o-ran-fm"; + } + + import iana-hardware { + prefix ianahw; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the configuration for performance measurement for + transceiver and rx-window measurement objects. + + NOTE, whereas this YANG model may define support of schema nodes associated + with O-RU measurements as optional, the CU-Plane specification may further + specify whether, according to a particular version of the CU plane + specification, which specific measurements are mandatory to support + from an O-RU perspective. In such a situation, the definition of mandatory + performance counters in sub-section 7.1 of the CU-plane specification shall + take precedence. + + Copyright 2020 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) updated top level model description concerning optionality of measurements + 2) added new rx window counters + 3) added new TX stats measurements + 4) added new EPE measurements + 5) fixed typo in enumeration - TX_POPWER + 6) introduced config false data indicating which type of measurmeents are supported"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 2.0.0 + + 1) added new measurement objects for QSFP + 2) backward compatible changes to correct sFTP Server Authentication. + 3) simplifying file management and authentication to reuse from o-ran-file-management module + 4) minor fixes according to lack of descriptions and reference + 5) added to descriptions to indicate applicability of leafs and Containers + to separate O-RAN use cases + 6) backward compatible changes to introduce groupings."; + + reference "ORAN-WG4.M.0-v02.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + + feature GRANULARITY-TRANSPORT-MEASUREMENT { + description + "This feature indicates that the O-RU supports an optional object-unit TRANSPORT in rx-window-measurement."; + } + + feature GRANULARITY-EAXC-ID-MEASUREMENT { + description + "This feature indicates that the O-RU supports an optional object-unit EAXC_ID in rx-window-measurement."; + } + + grouping start-and-end-time { + description + "Definition for start and end time for an event"; + + leaf start-time { + type yang-types:date-and-time; + description + "Start time for measurement of object stats"; + } + leaf end-time { + type yang-types:date-and-time; + description + "End time for measurement of object stats"; + } + } + + grouping epe-measurement-result-grouping { + description + "energy, power and environmental measurement-result are listed for O-RU"; + + list epe-measurement-result { + key "object-unit-id"; + config false; + leaf object-unit-id { + type leafref { + path "/hw:hardware/hw:component/hw:class"; + } + + description + "the hardware component type is used for the object-unit-id for the + EPE measurements. For example, the object-unit-id will be set to + or-hw:O-RAN-RADIO if the measurement applies to the complete O-RU + self-contained sub-system. + + Other hardware-classes include: or-hw:O-RU-POWER-AMPLIFIER, + ianahw:power-supply, ianahw:fan, ianahw:cpu"; + } + leaf min { + type decimal64 { + fraction-digits 4; + } + + description + "minimum value for the measurment-object"; + } + leaf max { + type decimal64 { + fraction-digits 4; + } + description + "maximum value for the measurment-object"; + } + leaf average { + type decimal64 { + fraction-digits 4; + } + description + "average value of the measurement-object"; + } + } + } + + grouping transceiver-measurement-result-grouping { + description + "transceiver-measurement-result are listed per port-number"; + + list transceiver-measurement-result { + key "object-unit-id"; + config false; + leaf object-unit-id { + type leafref { + path "/if:interfaces/if:interface/o-ran-int:port-reference/o-ran-int:port-number"; + } + + description + "port-number is used for the object-unit-id for the + transceiver-measurement-result, for which object-unit is + PORT_NUMBER only"; + } + container min { + description + "minimum value with recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "minimum value for the measurment-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the minimum value"; + } + } + container max { + description + "maximum value with recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "maximum value for the measurment-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the maximum value"; + } + } + container first { + description + "first value with the recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "first value of the measurement-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the first value"; + } + } + container latest { + description + "latest value with the recorded time are included for the + measurement-object"; + + leaf value { + type decimal64 { + fraction-digits 4; + } + + description + "latest value of the measurement-object"; + } + leaf time { + type yang-types:date-and-time; + + description + "recorded time for the latest value"; + } + } + leaf-list frequeny-table { + type uint32; + + description + "frequency-table for the measurment-object are included per bin. + The configuration parameters for this frequency-table are defined + by bin-count, lower-bound and upper-bound"; + } + + description + "List of transceiver measurement results"; + } + } + + grouping rx-window-measurement-result-grouping{ + description + "Group of measurement reasults for rx window measurements"; + + choice object-unit-id { + config false; + case RU { + leaf name{ + type leafref { + path "/hw:hardware/hw:component/hw:name"; + } + + description + "the name of O-RU module or one of its child ports + in ietf-hardware/component is used when O-RU is selected as + object-unit for the reception window stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the reception + window stats per O-RU."; + } + } + + case TRANSPORT { + list tr-measured-result{ + leaf name{ + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements + when TRANSPORT is selected as object-unit for the reception + window stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the reception + window stats."; + } + + description + "the number of data packet are counted for the reception + window stats per TRANSPORT."; + } + } + + case EAXC_ID { + list eaxc-measured-result { + leaf eaxc-id{ + type uint16; + + description + "eaxc-id is used + when EAXC_ID is selected as object-unit for the reception + window stats. + EAXC_ID consists of DU-Port-Id, Band-Selector, CC-id and + RU-Port-Id to be used in header of C/U-plane data packet."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the reception + window stats."; + } + leaf transport-name { + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements for the + transport information corresponding to this eaxc-id"; + } + + description + "the number of data packet are counted for the reception + window stats per EAXC-ID."; + } + } + + description + "measurement-result for the reception window stats depends on the + configured object-unit, RU, TRANSPORT or EAXC_ID"; + } + } + + grouping tx-measurement-result-grouping{ + description + "Group of measurement reasults for tx stats"; + + choice object-unit-id { + config false; + case RU { + leaf name{ + type leafref { + path "/hw:hardware/hw:component/hw:name"; + } + + description + "the name of O-RU module or one of its child ports + in ietf-hardware/component is used when O-RU is selected as + object-unit for the reception window stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the tx stats per O-RU."; + } + } + + case TRANSPORT { + list tr-measured-result{ + leaf name{ + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements + when TRANSPORT is selected as object-unit for the tx stats."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the tx stats."; + } + + description + "the number of data packet are counted for the tx stats per TRANSPORT."; + } + } + + case EAXC_ID { + list eaxc-measured-result { + leaf eaxc-id{ + type uint16; + + description + "eaxc-id is used + when EAXC_ID is selected as object-unit for the tx stats. + EAXC_ID consists of DU-Port-Id, Band-Selector, CC-id and + RU-Port-Id to be used in header of C/U-plane data packet."; + } + leaf count { + type uint64; + mandatory true; + + description + "the number of data packet are counted for the tx stats."; + } + leaf transport-name { + type leafref{ + path "/o-ran-elements:processing-elements/o-ran-elements:ru-elements/o-ran-elements:name"; + } + + description + "the name of ru-elements in o-ran-processing-elements for the + transport information corresponding to this eaxc-id"; + } + + description + "the number of data packet are counted for the tx stats per EAXC-ID."; + } + } + + description + "measurement-result for the tx stats depends on the + configured object-unit, RU, TRANSPORT or EAXC_ID"; + } + } + + + grouping measurement-group { + description + "Group of measurement results"; + + uses measurement-capabilities; + leaf enable-SFTP-upload { + type boolean; + default false; + description + "Flag to enable upload of performance measurement result files."; + } + + leaf enable-random-file-upload { + type boolean; + default false; + description + "Flag to enable upload of performance measurement result files at + random within file-upload-interval."; + } + + list remote-SFTP-uploads { + key remote-SFTP-upload-path; + description + "SFTP upload can be done to one or more than one SFTP servers"; + + leaf remote-SFTP-upload-path { + type inet:uri; + description + "URI specifying the remote location where the files are to uploaded. + The following format is possible: + sftp://@[:]/path"; + } + + uses o-ran-fm:credential-information; + } + +// transceiver measurements applicable to all O-RAN HW functions + + leaf transceiver-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the performance of transceiver + measurement objects periodically."; + } + +// EPE measurements applicable to all O-RAN HW functions + + leaf epe-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the energy, power and environmental + measurement objects periodically."; + } + +// RX Window measurements applicable to O-RAN WG4 defined functions + + leaf rx-window-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the performance of reception + window measurement objects periodically."; + } + + leaf tx-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the tx (outbound) + window measurement objects periodically."; + } + + leaf notification-interval { + type uint16; + units seconds; + description + "notification interval for the measurement result to be notified + periodically."; + } + + leaf file-upload-interval { + type uint16; + units seconds; + description + "file upload interval for the measurement result file to be + uploaded periodically."; + } + + leaf max-bin-count{ + type uint16; + config false; + mandatory true; + description + "indicates the maximum value of configurable bin-count for frequency + table in transceiver-measurement-objects as one of module + capabilities."; + } + + list transceiver-measurement-objects { + key "measurement-object"; + description + "optional list used to report transceiver measurements + applicable to any O-RAN defined hardware function"; + leaf measurement-object { + type enumeration { + enum RX_POWER { + description + "Measured Rx input power in mW for SFP or lane 1 of QSFP"; + } + enum RX_POWER_LANE_2 { + description + "Measured Rx input power in mW for lane 2 of QSFP"; + } + enum RX_POWER_LANE_3 { + description + "Measured Rx input power in mW for lane 3 of QSFP"; + } + enum RX_POWER_LANE_4 { + description + "Measured Rx input power in mW for lane 4 of QSFP"; + } + enum TX_POPWER { + status deprecated; + description + "Measured Tx input power in mW."; + } + enum TX_POWER { + description + "Measured Tx input power in mW."; + } + enum TX_POWER_LANE_2 { + description + "Measured Tx input power in mW for lane 2 of QSFP"; + } + enum TX_POWER_LANE_3 { + description + "Measured Tx input power in mW for lane 3 of QSFP"; + } + enum TX_POWER_LANE_4 { + description + "Measured Tx input power in mW for lane 4 of QSFP"; + } + enum TX_BIAS_COUNT { + description + "Internally measured Tx Bias Current in mA for SFP or lane 1 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_2 { + description + "Internally measured Tx Bias Current in mA for lane 2 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_3 { + description + "Internally measured Tx Bias Current in mA for lane 3 of QSFP"; + } + enum TX_BIAS_COUNT_LANE_4 { + description + "Internally measured Tx Bias Current in mA for lane 4 of QSFP"; + } + enum VOLTAGE { + description + "Internally measured transceiver supply voltage in mV"; + } + enum TEMPERATURE { + description + "Internally measured optional laser temperature in degrees Celsius."; + } + } + description "Target metric to measure the performance"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per Object"; + } + + leaf-list report-info { + type enumeration { + enum MAXIMUM { + description + "to report maximum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum MINIMUM { + description + "to report minimum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum FIRST { + description + "to report first value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum LATEST { + description + "to report latest value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum FREQUENCY_TABLE { + description + "to report frequency bin table within the + measurement-interval for the measurement-object."; + } + } + description "The reporting info to the measurement object."; + } + + leaf object-unit { + type enumeration { + enum PORT_NUMBER { + description + "unit to measure the performance per object-id"; + } + } + mandatory true; + description "unit to measure the performance per object-id."; + } + + leaf function { + type enumeration { + enum RAW { + description + "the value is expressed by real value."; + } + enum LOG_10 { + description + "the value is expressed by logarithm with base 10."; + } + } + + description + "the value to be recorded for transceiver-measurement + by real value or log 10."; + } + + leaf bin-count { + type uint16; + + description + "the number of bin for the frequency table. + This value shall be less than max-bin-count"; + } + + leaf lower-bound { + type decimal64 { + fraction-digits 4; + } + + description + "the lower value of the first bin of frequency table."; + } + + leaf upper-bound { + type decimal64 { + fraction-digits 4; + } + + description + "the upper value of the last bin of frequency table."; + } + uses transceiver-measurement-result-grouping; +// configuration and measurement result for the transceiver-measurement + + } + + list rx-window-measurement-objects { + key "measurement-object"; + description + "optional list used to report RX Window measurements + applicable to O-RAN WG4 define O-RU functions"; + leaf measurement-object { + type enumeration { + enum RX_ON_TIME { + description + "the number of data packets, received on time within + the reception window."; + } + enum RX_EARLY { + description + "the number of data packets, received before + the reception window."; + } + enum RX_LATE { + description + "the number of data packets, received after + the reception window."; + } + enum RX_CORRUPT { + description + "the number of data packets, which are corrupt or whose header + is incorrect."; + } + enum RX_DUPL { + status deprecated; + description + "the number of data packets, which is duplicated with other packets, + received within the measurement period."; + } + enum RX_TOTAL { + description + "the total number of received packets (data and control) within the measurement period."; + } + enum RX_ON_TIME_C { + description + "the number of control packets, received on time within + the reception window."; + } + enum RX_EARLY_C { + description + "the number of control packets, received before + the reception window."; + } + enum RX_LATE_C { + description + "the number of control packets, received after + the reception window."; + } + enum RX_SEQID_ERR { + description + "the number of data packets, received with an erroneous sequence ID."; + } + enum RX_SEQID_ERR_C { + description + "the number of control packets, received with an erroneous sequence ID."; + } + enum RX_ERR_DROP { + description + "The total number of inbound messages which are discarded by the receiving + O-RAN entity for any reason."; + } + } + description + "target reception window metric to measure the performance."; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per reception window + measurement object."; + } + + leaf object-unit { + type enumeration { + enum RU { + description + "the reception window stats are counted per hardware component. + This may be the parent 'module' or child 'port' component."; + } + enum TRANSPORT { + if-feature GRANULARITY-TRANSPORT-MEASUREMENT; + description + "the reception window stats are counted per transport flow. + When there are multiple transport flows between O-DU and O-RU, + e.g. multiple sets of o-du mac address, ru mac address and + vlan-id, the reception window stats per transport flow + are counted in this case. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-TRANSPORT-MEASUREMENT."; + } + enum EAXC_ID { + if-feature GRANULARITY-EAXC-ID-MEASUREMENT; + + description + "the reception window stats are counted per eAxC ID, which is + used in the header of receivd data packet. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-EAXC-ID-MEASUREMENT."; + } + } + description + "unit to measure the performance per object-id."; + } + + leaf report-info { + type enumeration { + enum COUNT { + description + "the number of data packet are counted for the reception + window stats."; + } + } + description + "The reporting info to the measurement object."; + } + + uses rx-window-measurement-result-grouping; +// configuration and measurement result for the reception window stats + + } + + + list tx-measurement-objects { + key "measurement-object"; + description + "optional list used to report TX measurements + applicable to O-RAN WG4 define O-RU functions"; + leaf measurement-object { + type enumeration { + enum TX_TOTAL { + description + "the number of outbound packets (data and control), transmitted within + the measurement period"; + } + enum TX_TOTAL_C { + description + "the number of outbound control packets, transmitted within + the measurement period. + This counter is required only if RU supports LAA/LBT capabilities."; + } + } + description + "CU-plane transmission counters"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the measurement per measurement object."; + } + + leaf object-unit { + type enumeration { + enum RU { + description + "the transmission stats are counted per hardware component. + This may be the parent 'module' or child 'port' component."; + } + enum TRANSPORT { + if-feature GRANULARITY-TRANSPORT-MEASUREMENT; + description + "the transmission stats are counted per transport flow. + When there are multiple transport flows between O-DU and O-RU, + e.g. multiple sets of o-du mac address, ru mac address and + vlan-id, the transmission stats per transport flow + are counted in this case. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-TRANSPORT-MEASUREMENT."; + } + enum EAXC_ID { + if-feature GRANULARITY-EAXC-ID-MEASUREMENT; + + description + "the transmission stats are counted per eAxC ID, which is + used in the header of receivd data packet. + This configuration is allowed only when O-RU supports + a feature GRANULARITY-EAXC-ID-MEASUREMENT."; + } + } + description + "unit to measure the performance per object-id."; + } + + leaf report-info { + type enumeration { + enum COUNT { + description + "the number of data packet are counted for the reception + window stats."; + } + } + description + "The reporting info to the measurement object."; + } + + uses tx-measurement-result-grouping; + // configuration and measurement result for the tx stats + + } + + list epe-measurement-objects { + key "measurement-object"; + description + "optional list used to report energy, power and environmental + measurements applicable to any O-RAN defined hardware function"; + leaf measurement-object { + type enumeration { + enum TEMPERATURE { + description + "Measured temperature in degrees celcius"; + } + enum POWER { + description + "Measured power consumed, in watts (W)"; + } + } + description "Target metric to measure the performance"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per Object"; + } + + leaf-list report-info { + type enumeration { + enum MAXIMUM { + description + "to report maximum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum MINIMUM { + description + "to report minimum value and its recorded time within the + measurement-interval for the measurement-object."; + } + enum AVERAGE { + description + "to report average value within the + measurement-interval for the measurement-object."; + } + } + description "The reporting info to the measurement object."; + } + + + uses epe-measurement-result-grouping; + // configuration and measurement result for the epe-measurement + + } + + + } + + grouping measurement-capabilities { + container measurement-capabilitites { + config false; + description "the type of measurement objects supported by the O-RU"; + + list transceiver-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; + } + } + } + list rx-window-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; + } + } + } + list tx-stats-objects { + key measurement-object; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; + } + } + } + list epe-stats-objects { + key "measurement-object"; + description + "An optional list describing the energy, power and environmental measurements supported + by the O-RU. Measurements are defined per hardware component."; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/epe-measurement-objects/measurement-object"; + } + } + leaf-list component-class { + type identityref { + base ianahw:hardware-class; + } + description + "An indication of the general hardware type of the + component for which EPE measurements are supported."; + + } + } + } + } + + grouping measurement-notification { + list transceiver-stats { + key "measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; + } + + description + "measurement-object for the transceiver-measurement"; + } + + uses start-and-end-time; + uses transceiver-measurement-result-grouping; + + description + "measurement result of transceiver-measurement per measurement-object"; + } + + list rx-window-stats { + key "measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; + } + + description + "measurement-object for the reception window measurement"; + } + uses start-and-end-time; + uses rx-window-measurement-result-grouping; + + description + "measurement result for the reception window measurement per + measurement-object"; + + } + + list tx-stats { + key "measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; + } + + description + "measurement-object for the tx stats measurement"; + } + uses start-and-end-time; + uses tx-measurement-result-grouping; + + description + "measurement result for the tx stats measurement per + measurement-object"; + + } + + container epe-stats { + description + "container for the epe stats measurement"; + + uses start-and-end-time; + uses epe-measurement-result-grouping; + + + } + + description + "notification may contain measurement result for transceiver-stats + and/or rx-window-stats"; + } + + // Top level container + + container performance-measurement-objects { + description + "configuration for performance management and measurement-result are + included"; + uses measurement-group; + } + +// Notifications + + notification measurement-result-stats { + description + "Notification may contain measurement results for transceiver-stats + and/or rx-window-stats"; + uses measurement-notification; + } +} diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index 42aabd99bb..baeefbc68d 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -35,6 +35,7 @@ #define ORAN_CONFIG_DU_ADDR "du_addr" // only needed for M-plane #define ORAN_CONFIG_VLAN_TAG "vlan_tag" // only needed for M-plane #define ORAN_CONFIG_RU_ADDR "ru_addr" // not needed if M-plane used +#define ORAN_CONFIG_RU_USERNAME "ru_username" // only needed for M-plane #define ORAN_CONFIG_RU_IP_ADDR "ru_ip_addr" // only needed for M-plane #define ORAN_CONFIG_MTU "mtu" // not needed if M-plane used #define ORAN_CONFIG_FILE_PREFIX "file_prefix" @@ -56,6 +57,7 @@ {ORAN_CONFIG_DU_ADDR, "Ether addr of DU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ {ORAN_CONFIG_VLAN_TAG, "VLAN tag\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ {ORAN_CONFIG_RU_ADDR, "Ether addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ + {ORAN_CONFIG_RU_USERNAME, "Username of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ {ORAN_CONFIG_RU_IP_ADDR, "IP addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ {ORAN_CONFIG_MTU, "MTU of Eth interface\n", 0, .uptr=NULL, .defuintval=1500, TYPE_UINT, 0}, \ {ORAN_CONFIG_FILE_PREFIX, "DPDK file-prefix\n", 0, .strptr=NULL, .defstrval="wls_0", TYPE_STRING, 0}, \ @@ -82,6 +84,7 @@ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ { .s3a = { config_checkstr_assign_integer, \ {"PA", "VA"}, {0, 1}, 2} }, \ { .s5 = { NULL } }, \ diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 4a141275d7..3bdbe1df12 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -338,6 +338,11 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d if (!ru_ready[i] && ru_session->ru_notif.config_change && ru_session->ru_notif.rx_carrier_state && ru_session->ru_notif.tx_carrier_state) { MP_LOG_I("RU \"%s\" is now ready.\n", ru_session->ru_ip_add); ru_ready[i] = true; + if (!ru_session->pm_stats.start_up_timing) { + success = pm_conf(ru_session, "true"); + if (success) + MP_LOG_I("Sucessfully activated PM after start-up procedure for RU \"%s\".\n", ru_session->ru_ip_add); + } } else { all_rus_ready = false; break; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf index 72d174cfb3..3dd36be9c7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf @@ -205,7 +205,7 @@ RUs = ( local_rf = "no"; nb_tx = 8; nb_rx = 8; - att_tx = 0; + att_tx = 35; att_rx = 0; bands = [77]; max_pdschReferenceSignalPower = -27; @@ -240,6 +240,7 @@ fhi_72 = { du_key_pair = ("/home/eurecom/.ssh/id_rsa.pub", "/home/eurecom/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67", "00:11:22:33:44:68", "00:11:22:33:44:69"); vlan_tag = (5, 5, 6, 6); + ru_username = ("oranbenetel", "oranbenetel"); ru_ip_addr = ("192.168.80.5", "192.168.80.6"); fh_config = ( # RAN650 #1 diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf index be35562fd7..ed996cac27 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf @@ -208,7 +208,7 @@ RUs = ( local_rf = "no"; nb_tx = 4; nb_rx = 4; - att_tx = 0; + att_tx = 24; att_rx = 0; bands = [78]; max_pdschReferenceSignalPower = -27; @@ -260,6 +260,7 @@ fhi_72 = { du_key_pair = ("/home/eurecom/.ssh/id_rsa.pub", "/home/eurecom/.ssh/id_rsa"); du_addr = ("00:11:22:33:44:68","00:11:22:33:44:69"); vlan_tag = (11, 11); + ru_username = ("oranbenetel"); ru_ip_addr = ("192.168.80.10"); fh_config = ({ T1a_cp_dl = (419, 470);