Merge branch 'integration_2025_w35' into 'develop'

Integration: `2025.w35`

* !3604 Consider PDSCH EPRE to DMRS EPRE in NR UE
* !3606 Fix SRS TLV unpack
* !3602 Update RFsim CN
* !3516 [FHI72 M-plane] CM improvements and PM implementation
* !3538 add a new graphical T tracer to see gNB MAC scheduling decisions
* !3425 RFSim test for 10 UEs/process

Closes #950

See merge request oai/openairinterface5g!3610
This commit is contained in:
Robert Schmidt
2025-08-28 21:10:14 +00:00
104 changed files with 5805 additions and 582 deletions
+90
View File
@@ -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
@@ -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"
@@ -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}
@@ -0,0 +1,210 @@
<!--
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The OpenAirInterface Software Alliance licenses this file to You under
the OAI Public License, Version 1.1 (the "License"); you may not use this file
except in compliance with the License.
You may obtain a copy of the License at
http://www.openairinterface.org/?page_id=698
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
For more information about the OpenAirInterface (OAI) Software Alliance:
contact@openairinterface.org
-->
<testCaseList>
<htmlTabRef>rfsim-5gnr-tdd-multiue</htmlTabRef>
<htmlTabName>Monolithic SA TDD gNB multiue</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<TestCaseRequestedList>
111111
800813
000001
000002
000003
000008
020001
020002
020003
020004
020105
444445
030001
030002
444444
100001
222222
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="111111">
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<svr_id>0</svr_id>
<images>oai-gnb-asan oai-nr-ue</images>
</testCase>
<testCase id="800813">
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
</testCase>
<testCase id="000001">
<class>Deploy_Object</class>
<desc>Deploy OAI 5G CoreNetwork</desc>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_multiue</yaml_path>
<services>mysql oai-amf oai-smf oai-upf oai-ext-dn</services>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
</testCase>
<testCase id="000002">
<class>Deploy_Object</class>
<desc>Deploy OAI 5G gNB RF sim SA</desc>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_multiue</yaml_path>
<services>oai-gnb</services>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
</testCase>
<testCase id="000003">
<class>Deploy_Object</class>
<desc>Deploy OAI 5G NR-UE RF sim SA</desc>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_multiue</yaml_path>
<services>oai-nr-ue</services>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
</testCase>
<testCase id="000008">
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
<id>rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10</id>
<nodes>acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas</nodes>
</testCase>
<testCase id="020001">
<class>Ping</class>
<desc>Ping ext-dn from NR-UE</desc>
<id>rfsim5g_multiue1</id>
<nodes>acamas</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>acamas</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="020002">
<class>Ping</class>
<desc>Ping NR-UE from ext-dn</desc>
<id>rfsim5g_ext_dn</id>
<nodes>acamas</nodes>
<svr_id>rfsim5g_multiue1</svr_id>
<svr_node>acamas</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="020003">
<class>Ping</class>
<desc>Ping ext-dn from Second NR-UE</desc>
<id>rfsim5g_multiue2</id>
<nodes>acamas</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>acamas</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="020004">
<class>Ping</class>
<desc>Ping Second NR-UE from ext-dn</desc>
<id>rfsim5g_ext_dn</id>
<nodes>acamas</nodes>
<svr_id>rfsim5g_multiue2</svr_id>
<svr_node>acamas</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="020005">
<class>Ping</class>
<desc>Ping ext-dn from both UEs</desc>
<id>rfsim5g_multiue1 rfsim5g_multiue2</id>
<nodes>acamas acamas</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>acamas</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="020105">
<class>Ping</class>
<desc>Ping ext-dn from all UEs</desc>
<id>rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10</id>
<nodes>acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>acamas</svr_node>
<ping_args>-c 20 -i 0.25 -s 1016</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="030001">
<class>Iperf</class>
<desc>Iperf (DL/3Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 3M -t 20 -R</iperf_args>
<id>rfsim5g_multiue1</id>
<nodes>acamas</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>acamas</svr_node>
<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
<iperf_bitrate_threshold>90</iperf_bitrate_threshold>
</testCase>
<testCase id="030002">
<class>Iperf</class>
<desc>Iperf (UL/1Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 1M -t 20</iperf_args>
<id>rfsim5g_multiue1</id>
<nodes>acamas</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>acamas</svr_node>
<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
<iperf_bitrate_threshold>90</iperf_bitrate_threshold>
</testCase>
<testCase id="444444">
<class>Detach_UE</class>
<desc>Detach OAI UEs</desc>
<id>rfsim5g_multiue1</id>
<nodes>acamas</nodes>
</testCase>
<testCase id="100001">
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_multiue</yaml_path>
<d_retx_th>1,0,0,0</d_retx_th>
<u_retx_th>1,0,0,0</u_retx_th>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
</testCase>
<testCase id="222222">
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<svr_id>0</svr_id>
<images>oai-gnb-asan oai-nr-ue</images>
</testCase>
</testCaseList>
@@ -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
@@ -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
@@ -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 #
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"
@@ -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"
@@ -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
@@ -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:
@@ -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
+1
View File
@@ -3,6 +3,7 @@
genids
tracer/enb
tracer/gnb
tracer/gnb_mac
tracer/extract_config
tracer/record
tracer/replay
+22 -2
View File
@@ -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
+7 -3
View File
@@ -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()
+11 -6
View File
@@ -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
+8 -8
View File
@@ -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 */
+332
View File
@@ -0,0 +1,332 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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 <database file> this option is mandatory\n"
" -ip <host> connect to given IP address (default %s)\n"
" -p <port> 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 = &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;
}
+2
View File
@@ -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);
+16
View File
@@ -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)
{
+2 -2
View File
@@ -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);
+44 -33
View File
@@ -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;
}
+17 -17
View File
@@ -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;
+46 -15
View File
@@ -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);
+53 -14
View File
@@ -5,31 +5,36 @@
#include <pthread.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
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;
}
+4 -3
View File
@@ -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_ */
+2 -2
View File
@@ -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;
+5 -5
View File
@@ -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))
+1 -1
View File
@@ -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")
+224 -32
View File
@@ -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 = ("<path-to>/.ssh/id_rsa.pub", "<path-to>/.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" = <get-schema> for module "ietf-yang-metadata".
[HW] [MPLANE] RPC request to RU "192.168.80.9" = <get-schema> for module "yang".
[HW] [MPLANE] RPC request to RU "192.168.80.9" = <get-schema> for module "ietf-inet-types".
@@ -1636,6 +1649,59 @@ sequenceDiagram
<vlan-id xmlns="urn:o-ran:interfaces:1.0">9</vlan-id>
</interface>
</interfaces>
<performance-measurement-objects xmlns="urn:o-ran:performance-management:1.0">
<rx-window-measurement-interval>10</rx-window-measurement-interval>
<tx-measurement-interval>10</tx-measurement-interval>
<notification-interval>10</notification-interval>
<rx-window-measurement-objects>
<measurement-object>RX_ON_TIME</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_EARLY</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_LATE</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_TOTAL</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_ON_TIME_C</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_EARLY_C</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_LATE_C</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<tx-measurement-objects>
<measurement-object>TX_TOTAL</measurement-object>
<active>false</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</tx-measurement-objects>
</performance-measurement-objects>
<processing-elements xmlns="urn:o-ran:processing-element:1.0">
<transport-session-type>ETH-INTERFACE</transport-session-type>
<ru-elements>
@@ -1729,8 +1795,10 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
@@ -1746,8 +1814,10 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
@@ -1763,8 +1833,10 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
@@ -1780,8 +1852,10 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
@@ -1797,9 +1871,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1807,6 +1887,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>0</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<low-level-rx-endpoints>
<name>LowLevelRxPrachEndpoint0</name>
@@ -1814,9 +1895,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1824,6 +1911,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>4</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<low-level-rx-endpoints>
<name>LowLevelRxEndpoint1</name>
@@ -1831,9 +1919,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1841,6 +1935,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>1</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<low-level-rx-endpoints>
<name>LowLevelRxPrachEndpoint1</name>
@@ -1848,9 +1943,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1858,6 +1959,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>5</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<low-level-rx-endpoints>
<name>LowLevelRxEndpoint2</name>
@@ -1865,9 +1967,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1875,6 +1983,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>2</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<low-level-rx-endpoints>
<name>LowLevelRxPrachEndpoint2</name>
@@ -1882,9 +1991,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1892,6 +2007,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>6</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<low-level-rx-endpoints>
<name>LowLevelRxEndpoint3</name>
@@ -1899,9 +2015,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1909,6 +2031,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>3</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<low-level-rx-endpoints>
<name>LowLevelRxPrachEndpoint3</name>
@@ -1916,9 +2039,15 @@ sequenceDiagram
<iq-bitwidth>9</iq-bitwidth>
<compression-type>STATIC</compression-type>
</compression>
<cp-length>0</cp-length>
<cp-length-other>0</cp-length-other>
<frame-structure>193</frame-structure>
<cp-type>NORMAL</cp-type>
<cp-length>352</cp-length>
<cp-length-other>288</cp-length-other>
<offset-to-absolute-frequency-center>0</offset-to-absolute-frequency-center>
<ul-fft-sampling-offsets>
<scs>KHZ_30</scs>
<ul-fft-sampling-offset>0</ul-fft-sampling-offset>
</ul-fft-sampling-offsets>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3840</band-sector-bitmask>
@@ -1926,6 +2055,7 @@ sequenceDiagram
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>7</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>true</non-time-managed-delay-enabled>
</low-level-rx-endpoints>
<tx-array-carriers>
<name>TxArray0</name>
@@ -1933,7 +2063,7 @@ sequenceDiagram
<center-of-channel-bandwidth>3950400000</center-of-channel-bandwidth>
<channel-bandwidth>100000000</channel-bandwidth>
<active>ACTIVE</active>
<gain>0.0</gain>
<gain>24.0</gain>
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
<downlink-sfn-offset>0</downlink-sfn-offset>
</tx-array-carriers>
@@ -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" = <commit> 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" = <edit-config>:
<performance-measurement-objects xmlns="urn:o-ran:performance-management:1.0">
<rx-window-measurement-interval>10</rx-window-measurement-interval>
<tx-measurement-interval>10</tx-measurement-interval>
<notification-interval>10</notification-interval>
<rx-window-measurement-objects>
<measurement-object>RX_ON_TIME</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_EARLY</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_LATE</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_TOTAL</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_ON_TIME_C</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_EARLY_C</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<rx-window-measurement-objects>
<measurement-object>RX_LATE_C</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</rx-window-measurement-objects>
<tx-measurement-objects>
<measurement-object>TX_TOTAL</measurement-object>
<active>true</active>
<object-unit>RU</object-unit>
<report-info>COUNT</report-info>
</tx-measurement-objects>
</performance-measurement-objects>
[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" = <validate> 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" = <commit> 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".
```
</details>
+1 -1
View File
@@ -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
+2
View File
@@ -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) {
+13 -4
View File
@@ -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) {
-1
View File
@@ -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;
+24 -25
View File
@@ -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);
}
}
+46 -43
View File
@@ -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; card<MAX_CARDS; card++) {
openair0_config_t *cfg = &ue->openair0_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) {
+1
View File
@@ -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;
+1 -1
View File
@@ -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;
@@ -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,
+3 -1
View File
@@ -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);
+2 -1
View File
@@ -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);
@@ -19,6 +19,7 @@
* contact@openairinterface.org
*/
#include "nr_common.h"
#include <string.h>
#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};
@@ -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
@@ -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;
+1 -1
View File
@@ -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);
@@ -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;
@@ -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;
+19 -11
View File
@@ -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);
}
}
+1
View File
@@ -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
@@ -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,
@@ -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);
+1 -2
View File
@@ -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);
+1 -2
View File
@@ -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));
-8
View File
@@ -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)
+21 -6
View File
@@ -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_ */
+1
View File
@@ -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)
+25 -23
View File
@@ -38,7 +38,7 @@
#include "nr_rlc/nr_rlc_oai_api.h"
#include "RRC/NR_UE/rrc_proto.h"
#include <pthread.h>
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;
}
+7 -2
View File
@@ -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;
}
@@ -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;
@@ -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,
+3
View File
@@ -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;
+1
View File
@@ -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);
@@ -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;
}
@@ -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_ */
@@ -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;
}
@@ -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_ */
@@ -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;
}
@@ -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_ */
+19
View File
@@ -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;
+2
View File
@@ -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);
+1 -1
View File
@@ -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;
+18 -20
View File
@@ -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)
+1 -1
View File
@@ -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
+163 -124
View File
@@ -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;
}
+2
View File
@@ -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
+2
View File
@@ -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
+2 -4
View File
@@ -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;
+7
View File
@@ -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 */
+21 -23
View File
@@ -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 <libyang/libyang.h>
#include <nc_client.h>
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 <edit-config> RPC.\n");
MP_LOG_I("RPC request to RU \"%s\" = <edit-config>:\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] <edit-config> 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;
}
+1 -5
View File
@@ -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 */
+13 -4
View File
@@ -20,6 +20,7 @@
*/
#include "connect-mplane.h"
#include "init-mplane.h"
#include "common/utils/assertions.h"
#include <libyang/libyang.h>
@@ -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\" = <connect> with username \"%s\" and port ID \"%d\".\n", ru_session->ru_ip_add, user, port);
MP_LOG_I("RPC request to RU \"%s\" = <connect> 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();
+32 -7
View File
@@ -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 <libyang/libyang.h>
#include <nc_client.h>
@@ -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 <edit-config> 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;
}
+2
View File
@@ -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 */
+52 -5
View File
@@ -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;
}
+21
View File
@@ -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 */
+37 -1
View File
@@ -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
+2 -1
View File
@@ -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;
}
+178 -33
View File
@@ -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 <gain-correction-range>
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");
// <o-ran-processing-element>
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,
// <o-ran-uplane-conf>
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);
// <o-ran-pm>
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;
}
@@ -27,6 +27,8 @@
#include <libyang/libyang.h>
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 */
+4 -2
View File
@@ -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);
+1 -1
View File
@@ -26,6 +26,6 @@
#include <libyang/libyang.h>
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 */
File diff suppressed because it is too large Load Diff
@@ -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: <https://datatracker.ietf.org/wg/netconf/>
WG List: <mailto:netconf@ietf.org>
Author: Andy Bierman
<mailto:andy@yumaworks.com>
Author: Martin Bjorklund
<mailto:mbj@tail-f.com>";
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.";
}
}
}
}
}
@@ -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://<username>@<host>[: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 "";
}
}
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More