Merge branch 'integration_2025_w15' into 'develop'

Integration: `2025.w15`

Closes #901, #943, #944, #942, and #939

See merge request oai/openairinterface5g!3374

* !3358 RedCap InitialBWP
* !3364 NR UE: fix PRACH generation with frequency resource id not 0 when msg1-FDM > 1 in SIB1
* !3365 nr pdcp: 'count' is 32 bits, use explicit type instead of generic 'int'
* !3366 Fix typo in gNB_scheduler_uci.c
* !3370 Doc: add information on how to avoid a common asan bug
* !3275 NAS service reject
* !3312 NR UE: enable concurrent UL slot processing
* !3368 Encapsulate cmake asn1c call, suppress useless output
* !3336 Fix logging in nr_dlsim
* !3281 Add support for 'dl_min_mcs' and 'ul_min_mcs' configuration parameters
* !3355 NR UE: add support for continuous frequency offset compensation (in particular NTN LEO Doppler)
* !3375 CI CoreNetwork fixes
* !3184 NR SIB2
* !3348 CI: Replacing Devkit server with a Grace Hopper in Aerial pipeline
This commit is contained in:
Robert Schmidt
2025-04-15 05:54:26 +00:00
137 changed files with 4075 additions and 1522 deletions
+1
View File
@@ -823,6 +823,7 @@ set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c
${OPENAIR1_DIR}/PHY/TOOLS/lut.c
${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c
${OPENAIR1_DIR}/PHY/TOOLS/get_sin_cos.c
)
set(PHY_SRC
+2 -2
View File
@@ -77,8 +77,8 @@ oc-cn5g-20897:
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72"
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72 %%log_dir%%"
oc-cn5g-20897-aerial2:
Host: aerial2
oc-cn5g-20897-aerial:
Host: gracehopper1-oai
NetworkScript: echo "inet 172.21.6.105"
RunIperf3Server: False
Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-nvidia-aerial"
+5 -2
View File
@@ -49,7 +49,7 @@ class CoreNetwork:
self._host = c.get('Host').strip()
if self._host == "%%current_host%%":
if node is None:
raise Exception(f"core network {self} requires node, but none provided (cannot replace %%current_host%%)")
raise Exception(f"core network {cn_name} requires node, but none provided (cannot replace %%current_host%%)")
self._host = node
if d is not None:
raise Exception("directory handling not implemented")
@@ -66,7 +66,7 @@ class CoreNetwork:
logging.info(f'initialized core {self} from {filename}')
def __str__(self):
return f"{self._cn_name}@{self._host} [IP: {self.getIP()}]"
return f"{self._cn_name}@{self._host}"
def __repr__(self):
return self.__str__()
@@ -162,6 +162,9 @@ class CoreNetwork:
def getCmdPrefix(self):
return self._cmd_prefix or ""
def getName(self):
return self._cn_name
def getHost(self):
return self._host
+2 -2
View File
@@ -464,7 +464,7 @@ class OaiCiTest():
return (False, f"UE {ue.getName()} has no IP address")
svrIP = cn.getIP()
if not svrIP:
return (False, f"Iperf server {ue.getName()} has no IP address")
return (False, f"Iperf server {cn.getName()} has no IP address")
iperf_opt = self.iperf_args
jsonReport = "--json"
@@ -862,7 +862,7 @@ class OaiCiTest():
success, output = cn.deploy()
logging.info(f"deployment core network {core_name} success {success}, output:\n{output}")
if success:
msg = f"Started {cn}"
msg = f"Started {cn} [{cn.getIP()}]"
HTML.CreateHtmlTestRowQueue(core_name, 'OK', [msg])
else:
msg = f"deployment of core network {core_name} FAILED"
@@ -186,8 +186,8 @@ gNBs =
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.131";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.131";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.202";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.202";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
@@ -20,6 +20,8 @@ gNBs =
min_rxtxtime = 6;
num_dlharq = 32;
num_ulharq = 32;
cu_sibs = [2];
du_sibs = [19];
servingCellConfigCommon = (
{
@@ -235,15 +237,6 @@ RUs = (
}
);
THREAD_STRUCT = (
{
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
worker_config = "WORKER_DISABLE";
}
);
rfsimulator :
{
serveraddr = "server";
@@ -296,6 +289,4 @@ log_config :
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="debug";
f1ap_log_level ="debug";
};
@@ -19,6 +19,8 @@ gNBs =
sib1_tda = 5;
min_rxtxtime = 6;
disable_harq = 1;
cu_sibs = [2];
du_sibs = [19];
servingCellConfigCommon = (
{
@@ -48,7 +50,7 @@ gNBs =
initialDLBWPsubcarrierSpacing = 0;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 2;
initialDLBWPsearchSpaceZero = 0;
initialDLBWPsearchSpaceZero = 2;
#uplinkConfigCommon
#frequencyInfoUL
@@ -0,0 +1,35 @@
uicc0 = {
imsi = "208990100001100";
key = "fec86ba6eb707ed08905757b1bb44b8f";
opc= "C42449363BBAD02B66D16BC975D77CC1";
dnn= "oai";
nssai_sst=1;
}
position0 = {
x = 0.0;
y = 0.0;
z = 6377900.0;
}
thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
#/* configuration for channel modelisation */
#/* To be included in main config file when */
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */
channelmod = {
max_chan = 10;
modellist = "modellist_rfsimu_1";
modellist_rfsimu_1 = (
{ # DL, modify on UE side
model_name = "rfsimu_channel_enB0"
type = "SAT_LEO_TRANS";
noise_power_dB = -100;
},
{ # UL, modify on gNB side
model_name = "rfsimu_channel_ue0"
type = "SAT_LEO_TRANS";
noise_power_dB = -100;
}
);
};
@@ -0,0 +1,118 @@
<!--
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-ntn-Leo</htmlTabRef>
<htmlTabName>Monolithic SA NTN LEO gNB</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<TestCaseRequestedList>
111111
100001
800813
000001
000002
000003
020001
020002
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-asan</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_ntn_leo</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+nrUE RF sim SA</desc>
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_ntn_leo</yaml_path>
<services>oai-gnb oai-nr-ue</services>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
</testCase>
<testCase id="000003">
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
<id>rfsim5g_ue</id>
<nodes>cacofonix</nodes>
</testCase>
<testCase id="020001">
<class>Ping</class>
<desc>Ping ext-dn from NR-UE</desc>
<id>rfsim5g_ue</id>
<nodes>cacofonix</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>cacofonix</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>cacofonix</nodes>
<svr_id>rfsim5g_ue</svr_id>
<svr_node>cacofonix</svr_node>
<ping_args>-c 20 -i 0.25</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</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_ntn_leo</yaml_path>
<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-asan</images>
</testCase>
</testCaseList>
@@ -44,7 +44,7 @@
<testCase id="555000">
<class>DeployCoreNetwork</class>
<desc>Initialize 5G Core</desc>
<cn_id>oc-cn5g-20897-aerial2</cn_id>
<cn_id>oc-cn5g-20897-aerial</cn_id>
</testCase>
<testCase id="111111">
@@ -52,6 +52,7 @@
<desc>Pull Images from Local Registry</desc>
<svr_id>0</svr_id>
<images>oai-gnb-aerial</images>
<tag_prefix>arm_</tag_prefix>
</testCase>
<testCase id="800813">
@@ -89,16 +90,16 @@
<class>Ping</class>
<desc>Ping: 100pings in 20sec</desc>
<id>up2-aerial</id>
<svr_id>oc-cn5g-20897-aerial2</svr_id>
<svr_id>oc-cn5g-20897-aerial</svr_id>
<ping_args>-c 100 -i 0.2</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="000022">
<class>Iperf</class>
<desc>iperf (DL/UDP/600M)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 600M -t 30 -R</iperf_args>
<svr_id>oc-cn5g-20897-aerial2</svr_id>
<desc>iperf (DL/UDP/500M)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 500M -t 30 -R</iperf_args>
<svr_id>oc-cn5g-20897-aerial</svr_id>
<id>up2-aerial</id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
@@ -106,9 +107,9 @@
<testCase id="000033">
<class>Iperf</class>
<desc>iperf (UL/UDP/50M)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 50M -t 30</iperf_args>
<svr_id>oc-cn5g-20897-aerial2</svr_id>
<desc>iperf (UL/UDP/40M)(30 sec)(single-ue profile)</desc>
<iperf_args>-u -b 40M -t 30</iperf_args>
<svr_id>oc-cn5g-20897-aerial</svr_id>
<id>up2-aerial</id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
@@ -144,7 +145,7 @@
<class>UndeployCoreNetwork</class>
<always_exec>true</always_exec>
<desc>Terminate 5G Core</desc>
<cn_id>oc-cn5g-20897-aerial2</cn_id>
<cn_id>oc-cn5g-20897-aerial</cn_id>
</testCase>
</testCaseList>
@@ -1,49 +0,0 @@
<!--
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>TEST-GH-AERIAL-SA</htmlTabRef>
<htmlTabName>Gracehopper AERIAL 100 MHz TDD SA</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<TestCaseRequestedList>
111111
333333
</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-aerial</images>
<tag_prefix>arm_</tag_prefix>
</testCase>
<testCase id="333333">
<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-aerial</images>
</testCase>
</testCaseList>
@@ -110,7 +110,7 @@ services:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --num-ul-actors 1 --log_config.global_log_options level,nocolor,time
depends_on:
- oai-gnb
networks:
@@ -0,0 +1,151 @@
services:
mysql:
container_name: "rfsim5g-mysql"
image: mysql:8.0
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
environment:
- TZ=Europe/Paris
- MYSQL_DATABASE=oai_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=linux
healthcheck:
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 30
networks:
public_net:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oaisoftwarealliance/oai-amf:v2.0.0
environment:
- TZ=Europe/paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml
depends_on:
- mysql
networks:
public_net:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oaisoftwarealliance/oai-smf:v2.0.0
environment:
- TZ=Europe/Paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
depends_on:
- oai-amf
networks:
public_net:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.0.0
environment:
- TZ=Europe/Paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml
depends_on:
- oai-smf
cap_add:
- NET_ADMIN
- SYS_ADMIN
cap_drop:
- ALL
privileged: true
networks:
public_net:
ipv4_address: 192.168.71.134
traffic_net:
ipv4_address: 192.168.72.134
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
image: oaisoftwarealliance/trf-gen-cn5g:focal
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
depends_on:
- oai-upf
networks:
traffic_net:
ipv4_address: 192.168.72.135
healthcheck:
test: /bin/bash -c "ping -c 2 192.168.72.134"
interval: 10s
timeout: 5s
retries: 5
oai-gnb:
image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop}
container_name: rfsim5g-oai-gnb
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
ASAN_OPTIONS: detect_leaks=0
depends_on:
- oai-ext-dn
networks:
public_net:
ipv4_address: 192.168.71.140
volumes:
- ../../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf:/opt/oai-gnb/etc/gnb.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
timeout: 5s
retries: 5
oai-nr-ue:
image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
container_name: rfsim5g-oai-nr-ue
cap_drop:
- ALL
cap_add:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS:
--band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60
--rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod
--rfsimulator.serveraddr 192.168.71.140
--time-sync-I 0.1 --ntn-initial-time-drift -46
--autonomous-ta --initial-fo 57340 --cont-fo-comp 2
--log_config.global_log_options level,nocolor,time
depends_on:
- oai-gnb
networks:
public_net:
ipv4_address: 192.168.71.150
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- ../../conf_files/nrue.uicc.ntn-leo.conf:/opt/oai-nr-ue/etc/nr-ue.conf
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
driver: bridge
name: rfsim5g-oai-public-net
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-public"
traffic_net:
driver: bridge
name: rfsim5g-oai-traffic-net
ipam:
config:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-traffic"
@@ -24,7 +24,7 @@ sudo -E echo start_server -uid 0 | sudo -E nvidia-cuda-mps-control
# Check if an argument is provided
if [ $# -eq 0 ]; then
# No argument provided, use default value
argument="P5G_FXN"
argument="P5G_FXN_GH"
else
# Argument provided, use it
argument="$1"
@@ -23,7 +23,7 @@ services:
- ../../../cmake_targets/share:/opt/cuBB/share
userns_mode: host
ipc: "shareable"
image: cubb-build:24-1
image: cubb-build:24-3
environment:
- cuBB_SDK=/opt/nvidia/cuBB
command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh"
+15
View File
@@ -107,3 +107,18 @@ or directly with
")
endif()
endfunction()
function(run_asn1c ASN1C_GRAMMAR ASN1C_PREFIX)
set(options "")
set(oneValueArgs COMMENT)
set(multiValueArgs OUTPUT OPTIONS)
cmake_parse_arguments(ASN1C "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
get_filename_component(GRAMMAR_FILE ${ASN1C_GRAMMAR} NAME)
set(LOGFILE "${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_FILE}.log")
add_custom_command(OUTPUT ${ASN1C_OUTPUT}
COMMAND ASN1C_PREFIX=${ASN1C_PREFIX} ${ASN1C_EXEC} ${ASN1C_OPTIONS} -D ${CMAKE_CURRENT_BINARY_DIR} ${ASN1C_GRAMMAR} > ${LOGFILE} 2>&1 || cat ${LOGFILE}
DEPENDS ${ASN1C_GRAMMAR}
COMMENT "Generating ${ASN1C_COMMENT} from ${GRAMMAR_FILE}"
)
endfunction()
+8 -3
View File
@@ -157,14 +157,19 @@ int write_file_matlab(const char *fname, const char *vname, void *data, int leng
//printf("Writing %d elements of type %d to %s\n",length,format,fname);
const int fname_len = strlen(fname);
char write_file_name[fname_len + 10];
const char *fn_format = (format & MATLAB_RAW) ? "%s.bin" : "%s";
snprintf(write_file_name, sizeof(write_file_name), fn_format, fname);
if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) {
fp = fopen(fname,"a+");
fp = fopen(write_file_name, "a+");
} else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) {
fp = fopen(fname,"w+");
fp = fopen(write_file_name, "w+");
}
if (fp== NULL) {
printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n",fname);
printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n", write_file_name);
return(-1);
}
+7
View File
@@ -38,6 +38,7 @@
#include "assertions.h"
#include "common/utils/utils.h"
#define MAX_SI_GROUPS 3
#define NR_MAX_PDSCH_TBS 3824
#define MAX_NUM_BEAM_PERIODS 4
#define MAX_BWP_SIZE 275
@@ -93,6 +94,12 @@ static inline const char *rnti_types(nr_rnti_type_t rr)
// the total shift is 2 * 15, in dB scale thats 10log10(2^(15*2))
#define SQ15_SQUARED_NORM_FACTOR_DB 90.3089986992
typedef struct {
uint8_t *SIB_buffer;
int SIB_size;
int SIB_type;
} nr_SIBs_t;
typedef struct nr_bandentry_s {
int16_t band;
uint64_t ul_min;
+48 -53
View File
@@ -24,8 +24,11 @@ The hardware on which we have tried this tutorial:
|----------------------------------------------------------------------------|----------------------------------|--------------------------------------------------|
| Gigabyte Edge E251-U70 (Intel Xeon Gold 6240R, 2.4GHz, 24C48T, 96GB DDR4) |Ubuntu 22.04.3 LTS (5.15.0-72-lowlatency)| NVIDIA ConnectX®-6 Dx 22.38.1002 |
| Dell PowerEdge R750 (Dual Intel Xeon Gold 6336Y CPU @ 2.4G, 24C/48T (185W), 512GB RDIMM, 3200MT/s) |Ubuntu 22.04.3 LTS (5.15.0-72-lowlatency)| NVIDIA Converged Accelerator A100X (24.39.2048) |
| Supermicro Grace Hopper MGX ARS-111GL-NHR (Neoverse-V2, 3.4GHz, 72C/72T, 576GB LPDDR5) | Ubuntu 22.04.5 LTS (6.5.0-1019-nvidia-64k) |NVIDIA BlueField3 (32.41.1000)|
**NOTE**: These are not minimum hardware requirements. This is the configuration of our servers. The NIC card should support hardware PTP time stamping.
**NOTE**:
- These are not minimum hardware requirements. This is the configuration of our servers. The NIC card should support hardware PTP time stamping.
- Starting from tag [2025.w13](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/2025.w13?ref_type=tags) of OAI, we are only testing with the Grace Hopper server.
PTP enabled switches and grandmaster clock we have tested with:
@@ -42,6 +45,7 @@ These are the radio units we've used for testing:
|-------------|------------------|
| Foxconn RPQN-7801E RU | 2.6.9r254 |
| Foxconn RPQN-7801E RU | 3.1.15_0p4 |
| Foxconn RPQN-7801E RU | v3.2.0q.551.12.E.rc2.srs-AIO |
The UEs that have been tested and confirmed working with Aerial are the following:
@@ -54,35 +58,30 @@ The UEs that have been tested and confirmed working with Aerial are the followin
| Apaltec | Tributo 5G-Dongle |
| OnePlus | Nord (AC2003) |
| Apple iPhone | 14 Pro (MQ0G3RX/A) (iOS 17.3) |
| Samsung | S23 Ultra |
## Configure your server
The first step is to obtain the NVIDIA Aerial SDK, you'll need to request access [here](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/aerial-sdk).
After obtaining access to the SDK, you can refer to [this instructions page](https://docs.nvidia.com/aerial/aerial-ran-colab-ota/current/index.html) to setup the L1 components using NVIDIAs' SDK manager, or to [this instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html) in order to setup and install the components manually.
The currently used Aerial Version is 24-1, which is also the one currently used by the SDK Manager.
To set up the L1 and install the components manually refer to this [instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html).
**Note**:
- To configure the Gigabyte server please refer to these [instructions](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/2025.w13/doc/Aerial_FAPI_Split_Tutorial.md)
- The last release to support the Gigabyte server is **Aerial CUDA-Accelerated RAN 24-1**.
### CPU allocation
Currently, the CPU isolation is setup the following:
| Server brand | Model | Nº of CPU Cores | Isolated CPUs |
|------------------|---------------|:---------------:|:--------------:|
| Grace Hopper MGX | ARS-111GL-NHR | 72 | 4-64 |
| Server brand | Model | Nº of CPU Cores | Isolated CPUs |
|--------------|-----------|:---------------:|:--------------:|
| Gigabyte | Edge E251-U70 | 24 | 2-10 |
**Gigabyte Edge E251-U70**
**Grace Hopper MGX ARS-111GL-NHR**
| Applicative Threads | Allocated CPUs |
|------------------------|----------------|
| Aerial L1 | 2,3,4,5,6,7,8 |
| PTP & PHC2SYS Services | 9 |
| PTP & PHC2SYS Services | 41 |
| OAI `nr-softmodem` | 13-20 |
## PTP configuration
1. You need to install the `linuxptp` debian package. It will install both ptp4l and phc2sys.
@@ -99,14 +98,10 @@ Once installed you can use this configuration file for ptp4l (`/etc/ptp4l.conf`)
domainNumber 24
slaveOnly 1
time_stamping hardware
tx_timestamp_timeout 1
logging_level 6
summary_interval 0
#priority1 127
tx_timestamp_timeout 30
[your_PTP_ENABLED_NIC]
network_transport L2
hybrid_e2e 0
```
@@ -120,7 +115,7 @@ Documentation=man:ptp4l
Restart=always
RestartSec=5s
Type=simple
ExecStart=taskset -c 9 /usr/sbin/ptp4l -f /etc/ptp.conf
ExecStart=taskset -c 41 /usr/sbin/ptp4l -f /etc/ptp.conf
[Install]
WantedBy=multi-user.target
@@ -149,17 +144,16 @@ WantedBy=multi-user.target
# Build OAI gNB
If installing with the Aerial SDK, you should already have the repository cloned in `~/openairinterface5g`, if
Clone OAI code base in a suitable repository, here we are cloning in `~/openairinterface5g` directory,
If it's not already cloned, the first step is to clone OAI repository
```bash
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
cd ~/openairinterface5g/
```
## Get nvIPC sources from the L1 container
The library used for communication between L1 and L2 components is called nvIPC, and was developed by NVIDIA, as such, it is not open-source and can't be freely distributed.
In order to be able to use this library to achieve communication, we need to obtain the nvIPC source files from the L1 container (cuBB) and place it in out gNB project directory `~/openairinterface5g`.
The library used for communication between L1 and L2 components is called nvIPC, and is developed by NVIDIA. It is not open-source and can't be freely distributed.
In order to achieve this communication, we need to obtain the nvIPC source files from the L1 container (cuBB) and place it in the gNB project directory `~/openairinterface5g`.
This allows us to build and install this library when building the L2 docker container.
Check whether your L1 container is running:
@@ -177,7 +171,7 @@ cuBB
aerial@c_aerial_aerial:/opt/nvidia/cuBB#
```
After logging into the container, we need to pack the nvIPC sources and copy them to the host ( the command creates a tar.gz file with the following name format: nvipc_src.YYYY.MM.DD.tar.gz)
After logging into the container, you need to pack the nvIPC sources and copy them to the host ( the command creates a `tar.gz` file with the following name format: `nvipc_src.YYYY.MM.DD.tar.gz`)
```bash
~$ docker exec -it cuBB bash
aerial@c_aerial_aerial:/opt/nvidia/cuBB# cd cuPHY-CP/gt_common_libs
@@ -216,7 +210,7 @@ With the nvIPC sources in the project directory, the docker image can be built.
## Building OAI gNB docker image
In order to build the final image, there is an intermediary image to be built (ran-base)
In order to build the target image (`oai-gnb-aerial`), first you should build a common shared image (`ran-base`)
```bash
~$ cd ~/openairinterface5g/
~/openairinterface5g$ docker build . -f docker/Dockerfile.base.ubuntu22 --tag ran-base:latest
@@ -224,21 +218,23 @@ In order to build the final image, there is an intermediary image to be built (r
```
## Running the setup
In order to use Docker compose to automatically start and stop the setup, we need to first create a ready-made image of the L1, after compiling the L1 software and making the necessary adjustments to its configuration files.
The process of preparing the L1 is covered on NVIDIAs' documentation, and falls outside the scope of this document.
# Running the setup
### Prepare the L1 image
After preparing the L1 software, the container needs to be committed in order for an image in which the L1 is ready to be executed, and that can be referenced by a docker-compose.yaml file later:
*Note:* In preparing the L1 image, the default L1 configuration file is cuphycontroller_P5G_FXN.yaml, located in `/opt/nvidia/cuBB/cuPHY-CP/cuphycontroller/config/`.
This is the file where the RU MAC address needs to be applied before commiting the image
In order to use Docker Compose to automatically start and stop the setup, we first need to create a pre-built image of L1 after compiling the L1 software and making the necessary adjustments to its configuration files.
The process of preparing L1 is covered in NVIDIA's documentation and falls outside the scope of this document.
## Prepare the L1 image
After preparing the L1 software, the container needs to be committed to create an image where L1 is ready for execution, which can later be referenced by a `docker-compose.yaml` file.
*Note:* The default L1 configuration file is `cuphycontroller_P5G_FXN_GH.yaml`, located in `/opt/nvidia/cuBB/cuPHY-CP/cuphycontroller/config/`.
In this file the RU MAC address needs to be specified before commiting the image.
```bash
~$ docker commit nv-cubb cubb-build:24-1
~$ docker commit nv-cubb cubb-build:24-3
~$ docker image ls
..
cubb-build 24-1 824156e0334c 2 weeks ago 40.1GB
..
cubb-build 24-3 824156e0334c 2 weeks ago 23.9GB
-..
```
## Adapt the OAI-gNB configuration file to your system/workspace
@@ -255,14 +251,12 @@ The default amf_ip_address:ipv4 value is 192.168.70.132, when installing the CN5
Both 'GNB_IPV4_ADDRESS_FOR_NG_AMF' and 'GNB_IPV4_ADDRESS_FOR_NGU' need to be set to the IP address of the NIC referenced previously.
### Running docker compose
#### Aerial L1 entrypoint script
Before running docker-compose, we can check which L1 configuration file is to be used by cuphycontroller_scf.
This is set in the script [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh), which is used by the L1 container in order to start the L1 software.
The script begins by setting up some environment variables, restarting NVIDIA MPS, and finally running cuphycontroller_scf.
The L1 software is run with an argument that indicates which configuration file is to be used.
This argument may be changed by providing an argument to the [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh) call in [`docker-compose.yaml`](../ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml).
When no argument is provided (this is the default behaviour), it uses "P5G_FXN" as the cuphycontroller_scf argument.
## Running docker compose
### Aerial L1 entrypoint script
The `aerial_l1_entrypoint` script is used by the L1 container to start the L1 software and is called in the Docker Compose file.
It begins by setting up environment variables, restarting NVIDIA MPS, and finally running `cuphycontroller_scf`.
The L1 software is executed with an argument that specifies which configuration file to use. If not modified, the default argument is set to `P5G_FXN_GH`.
After building the gNB image, and preparing the configuration file, the setup can be run with the following command:
@@ -271,17 +265,18 @@ cd ci-scripts/yaml_files/sa_gnb_aerial/
docker compose up -d
```
This will start both containers, beginning with 'nv-cubb' and only after it being ready it starts 'oai-gnb-aerial'.
This will start both containers, beginning with `nv-cubb`, and `oai-gnb-aerial` will start only after it is ready.
The gNB logs can be followed with:
The logs can be followed using these commands:
```bash
docker logs -f oai-gnb-aerial
docker logs -f nv-cubb
```
#### Running with multiple L2s
### Running with multiple L2s
One L1 instance can support multiple L2 instances. See also the [aerial documentation](https://developer.nvidia.com/docs/gputelecom/aerial-sdk/text/cubb_quickstart/running_cubb-end-to-end.html#run-multiple-l2-instances-with-single-l1-instance) for more details.
In OAI the share memory prefix must be configured in the configuration file.
In OAI the shared memory prefix must be configured in the configuration file.
```bash
tr_s_preference = "aerial";
@@ -289,9 +284,9 @@ In OAI the share memory prefix must be configured in the configuration file.
```
### Stopping the setup
## Stopping the setup
Running the following command, will stop both containers, leaving the system ready to be run later:
Run the following command to stop and remove both containers, leaving the system ready to be restarted later:
```bash
cd ci-scripts/yaml_files/sa_gnb_aerial/
docker compose down
+3 -2
View File
@@ -105,7 +105,7 @@ These modes of operation are supported:
- MAC -> PHY configuration using NR FAPI P5 interface
- MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU
- Scheduler procedures for SIB1
- Generation of and scheduler procedures for MIB/SIB1
- Scheduler procedures for RA
- 4-Step RA
- Contention Free RA procedure
@@ -140,6 +140,7 @@ These modes of operation are supported:
- MAC scheduling of SR reception
- Intra-frequency handover
- Initial support for RedCap
- Scheduling of SIBs (2, 19)
## gNB RLC
@@ -174,7 +175,7 @@ These modes of operation are supported:
- NR RRC (38.331) Rel 17 messages using new [asn1c](https://github.com/mouse07410/asn1c)
- LTE RRC (36.331) also updated to Rel 15
- Generation of MIB/SIB1 (received from DU)
- Generation of system information (SIB2)
- RRC can configure PDCP, RLC, MAC
- Interface with GTP-U (tunnel creation/handling for S1-U (NSA), N3 (SA), F1 interfaces)
- Integration of RRC messages and procedures supporting UE 5G SA connection
+5 -1
View File
@@ -232,7 +232,9 @@ In the `MACRLCs` section of the gNB/DU configuration file:
In the `gNBs` section of the gNB/DU configuration file: some of the parameters
affect RRC configuration (CellGroupConfig) of a UE, and are therefore listed
here, *also they pertain to the DU*, i.e., the scheduler.
here, *also they pertain to the DU*, i.e., the scheduler. Note also that some
SIBs are configured at the DU and some at the CU; please consult the [RRC
configuration](../RRC/rrc-usage.md) as well for SIB configuration.
* `pdsch_AntennaPorts_XP` (default 1): number of XP logical antenna
ports in PDSCH (see also [`RUNMODEM.md`](../RUNMODEM.md))
@@ -267,6 +269,8 @@ here, *also they pertain to the DU*, i.e., the scheduler.
options are 2, 4, 6, 8, 10, 12, 32; **32 is a Rel-17 features**)
* `num_ulharq` (default 16): as `num_dlharq` for UL (other valid option is 32;
**32 is i Rel-17 feature**)
- `du_sibs` (default `[]`): list of SIBs to transmit in the cell. Currently,
SIB19 (for NTN) is supported.
## ServingCellConfigCommon parameters
+5
View File
@@ -67,6 +67,9 @@ RRC-specific configuration
### cell-specific options
Note that some SIBS are configured at the CU and some at the DU; please consult
the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration.
- `gNB_ID` and `gNB_name`: ID and name of the gNB
- `tracking_area_code`: the current tracking area code in the range `[0x0001,
0xfffd]`
@@ -84,6 +87,8 @@ RRC-specific configuration
- `enable_sdap` (default: false): enable the use of the SDAP layer. If
deactivated, a transparent SDAP header is prepended to packets, but no
further processing is being done.
- `cu_sibs` (default: `[]`) list of SIBs to give to the DU for transmission.
Currently, SIB2 is supported.
### UE-specific configuration
+16 -2
View File
@@ -136,7 +136,15 @@ Here are some useful command line options for the NR UE:
| Parameter | Description |
|--------------------------|---------------------------------------------------------------------------------------------------------------|
| `--ue-scan-carrier` | Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. |
| `--ue-fo-compensation` | Enables the frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. |
| `--ue-fo-compensation` | Enables the initial frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. |
| `--cont-fo-comp` | Enables the continuous frequency offset (FO) estimation and compensation. Parameter value `1` specifies that the main FO contribution comes from the local oscillator's (LO) accuracy. Parameter value `2` specifies that the main FO contribution comes from Doppler shift. |
| `--initial-fo` | Sets the known initial frequency offset. Useful especially with large Doppler frequency, e.g. LEO satellite. |
| `--freq-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the continuous frequency offset compensation. Default value 0.01. |
| `--freq-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the continuous frequency offset compensation. Default value 0.001. |
| `--ntn-initial-time-drift` | Sets the initial NTN DL time drift (feeder link and service link), given in µs/s. |
| `--autonomous-ta` | Enables the autonomous TA update, based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite). |
| `--time-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the time synchronization. Default value 0.5. |
| `--time-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the time synchronization. Default value 0.0. |
| `--usrp-args` | Equivalent to the `sdr_addrs` field in the gNB config file. Used to identify the USRP and set some basic parameters (like the clock source). |
| `--clock-source` | Sets the clock source (internal or external). |
| `--time-source` | Sets the time source (internal or external). |
@@ -349,10 +357,16 @@ For LEO satellite scenarios, the parameter `--ntn-initial-time-drift` must be pr
This parameter provides the drift rate of the complete DL timing (incl. feeder link and service link) in µs/s.
Also, to perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` should be added in case of a LEO satellite scenario.
For LEO satellite scenario we assume the LO to be very accurate and the main FO contribution comes from Doppler shift.
Therefore, we use the command line parameter `--cont-fo-comp 2` to continuously compensate the DL Doppler and pre-compensate the UL Doppler.
The initial Doppler frequency offset must be provided via command line with the parameter `--initial-fo`.
For other information on optional NR UE command line options, please refer [here](#optional-nr-ue-command-line-options).
So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent LEO satellite 5G NR NTN is this:
```
cd cmake_targets
sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta
sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta --initial-fo 57340 --cont-fo-comp 2
```
# Specific OAI modes
+4 -4
View File
@@ -19,10 +19,10 @@
| starsky | Starsky | eNB (B40) | b200mini (30A3E3C) |
| carabe | Carabe | UE (B7UE) | B200mini (30AE8C9) |
| avra | Avra | gNB (n78) | AW2S Jaguar (192.168.80.239) |
| aerial2 | Aerial2 | gNB (PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial SDK integrated_ |
| cacofonix | Cacofonix | gNB (n78, FHI7.2) | -- |
| matix | Matix | gNB (n77) | N310 |
| gracehopper1-oai | Gracehopper1 | build, gNB/Aerial | _Nvidia Aerial SDK integrated_ |
| gracehopper1-oai | Gracehopper1 | gNB (n78, PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial integration_ |
| gracehopper3-oai | Gracehopper3 | build | -- |
Note: The available resources, and their current usage, is indicated here:
- [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/):
@@ -127,7 +127,7 @@ information on how the images are built.
- build unit tests from `ci-scripts/docker/Dockerfile.unittest.ubuntu22`, and run them
- [RAN-Ubuntu-ARM-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-ARM-Image-Builder/)
~BUILD-ONLY ~4G-LTE ~5G-NR
- gracehopper1-oai: ARM Ubuntu 22 image build using docker
- gracehopper3-oai: ARM Ubuntu 22 image build using docker
- base image from `Dockerfile.base.ubuntu22`
- build image from `Dockerfile.build.ubuntu22`, followed by
- target image from `Dockerfile.gNB.ubuntu22`
@@ -199,7 +199,7 @@ information on how the images are built.
- OpenShift cluster for CN deployment and container images for gNB and UE deployment
- [RAN-SA-AERIAL-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AERIAL-CN5G/)
~5G-NR
- 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on Aerial2 + Foxconn RU, up2 + COTS UE (Quectel RM520N), OAI CN5G
- 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on gracehopper1-oai + Foxconn RU, up2 + COTS UE (Quectel RM520N), OAI CN5G
- container images for gNB deployment
- [RAN-SA-2x2-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-2x2-Module-CN5G/)
~5G-NR
+19
View File
@@ -29,6 +29,25 @@ cd cmake_targets/ran_build/build
sudo LD_LIBRARY_PATH=. ./nr-softmodem ...
```
### Possible problems
On some systems with specific ASan versions, executing a program compiled with
ASan might fail with an error `DEADLYSIGNAL`, or simply a segmentation fault.
Note that since OAI compiles and runs some programs _during compilation_ (for
code generation), typically already the build is impacted.
The issue is related to Address Space Layout Randomization (ASLR) settings
in Linux, a security feature designed to make it more difficult for attackers
to predict the locations of processes in memory. In this case, it is possible
to avoid the bug by running
```
sudo sysctl vm.mmap_rnd_bits=30
```
which reduces the number of bits for memory mappings used to randomize mmap
base addresses. _This reduces the security of the system._
## Undefined Behavior Sanitizer (UBSAN)
[Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) (UBSAN) is a runtime undefined behavior checker. It uses compile-time instrumentation to catch undefined behavior by inserting code that performs specific checks before operations that may cause it. UBSAN can be activated with the `--sanitize-undefined` option or `-fsanitize=undefined`.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 80 KiB

+30 -22
View File
@@ -13,15 +13,15 @@
duplexer/.style={draw,fill=white},
]
\node[label=above:porcepix] (porcepix)
\node[label=above:cluster] (cluster)
{\includegraphics[width=1.2cm]{server}};
\node[above right=-0.8cm and 2cm of porcepix, label=above:aerial2] (aerial2)
\node[above right=-0.6cm and 2cm of cluster, label=above:gracehopper1-oai] (gracehopper1-oai)
{\includegraphics[width=1.2cm]{server}}
edge (porcepix);
\node[right=0.3cm of aerial2, label=above:Foxconn, draw,
edge (cluster);
\node[right=0.3cm of gracehopper1-oai, label=above:Foxconn, draw,
minimum width=1.7cm, minimum height=0.8cm] (foxconn)
{O-RU} edge (aerial2);
{O-RU} edge (gracehopper1-oai);
\node[below right=+0.45cm and 0.35cm of foxconn.east] (antf1)
{\includegraphics[width=0.3cm]{antenna}} edge (foxconn.east);
\node[below right=-0.1cm and 0.35cm of foxconn.east] (antf2)
@@ -31,7 +31,7 @@
\node[above right=+0.45cm and 0.35cm of foxconn.east] (antf4)
{\includegraphics[width=0.3cm]{antenna}} edge (foxconn.east);
\node[above right=+1.3cm and 2cm of porcepix, label=above:matix] (matix)
\node[above right=+1.5cm and 2cm of cluster, label=above:matix] (matix)
{\includegraphics[width=1.2cm]{server}};
\node[right=0.3cm of matix, label=above:N310] (n310a)
{\includegraphics[width=1.5cm]{n310}} edge (matix);
@@ -41,22 +41,9 @@
\node[above right=-0.1cm and 0.35cm of b77o.east] (anto2)
{\includegraphics[width=0.3cm]{antenna}} edge (b77o);
\node[below right=-0.6cm and 2cm of porcepix, label=above:obelix] (obelix)
\node[below right=-0.4cm and 2cm of cluster, label=above:cacofonix] (cacofonix)
{\includegraphics[width=1.2cm]{server}}
edge (porcepix);
\node[right=0.3cm of obelix, label=above:N310] (n310o)
{\includegraphics[width=1.5cm]{n310}} edge (obelix);
\node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o);
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[below=2cm of porcepix, label=above:Cluster] (cluster)
{\includegraphics[width=1.2cm]{server}};
\node[right=2cm of cluster, label=above:cacofonix] (cacofonix)
{\includegraphics[width=1.2cm]{server}}
edge (cluster);
edge (cluster);
\node[right=0.3cm of cacofonix, label=above:VVDN, draw,
minimum width=1.7cm, minimum height=0.8cm] (vvdn)
{O-RU} edge (cacofonix);
@@ -69,7 +56,28 @@
\node[above right=+0.45cm and 0.35cm of vvdn.east] (antv4)
{\includegraphics[width=0.3cm]{antenna}} edge (vvdn.east);
\node[above right=+0.0cm and 5.0cm of n310o.east, label=above:RM520N-GL] (quectel)
\node[below=2cm of cluster, label=above:porcepix] (porcepix)
{\includegraphics[width=1.2cm]{server}};
\node[right=2cm of porcepix, label=above:obelix] (obelix)
{\includegraphics[width=1.2cm]{server}}
edge (porcepix);
\node[right=0.3cm of obelix, label=above:N310] (n310o)
{\includegraphics[width=1.5cm]{n310}} edge (obelix);
\node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o);
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
%\node[right=0.3cm of cacofonix, label=above:N310] (n310o)
% {\includegraphics[width=1.5cm]{n310}} edge (cacofonix);
\node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o);
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
\node[above right=+0.0cm and 5.0cm of vvdn.east, label=above:RM520N-GL] (quectel)
{\includegraphics[height=1.2cm]{quectel}};
\node[above left=-0.1cm and 0.8cm of quectel.west] (aq2)
{\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+2 -11
View File
@@ -464,23 +464,14 @@ int start_L1L2(module_id_t gnb_id)
NR_BCCH_BCH_Message_t *mib = mac->common_channels[0].mib;
const NR_BCCH_DL_SCH_Message_t *sib1 = mac->common_channels[0].sib1;
/* update existing config in F1 Setup request structures */
f1ap_setup_req_t *sr = mac->f1_config.setup_req;
DevAssert(sr->num_cells_available == 1);
f1ap_served_cell_info_t *info = &sr->cell[0].info;
DevAssert(info->mode == F1AP_MODE_TDD);
/* update existing config in F1 Setup request structures */
DevAssert(scc->tdd_UL_DL_ConfigurationCommon != NULL);
info->tdd = read_tdd_config(scc); /* updates radio config */
/* send gNB-DU configuration update to RRC */
f1ap_gnb_du_configuration_update_t update = {
.transaction_id = 1,
.num_cells_to_modify = 1,
};
update.cell_to_modify[0].old_nr_cellid = info->nr_cellid;
update.cell_to_modify[0].info = *info;
update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1);
mac->mac_rrc.gnb_du_configuration_update(&update);
prepare_du_configuration_update(mac, info, mib, sib1);
init_NR_RU(config_get_if(), NULL);
+33 -23
View File
@@ -41,6 +41,7 @@
#include "instrumentation.h"
#include "common/utils/threadPool/notified_fifo.h"
#include "position_interface.h"
#include "nr_phy_common.h"
/*
* NR SLOT PROCESSING SEQUENCE
@@ -104,7 +105,9 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
static void start_process_slot_tx(void* arg) {
notifiedFIFO_elt_t *newTx = arg;
nr_rxtx_thread_data_t *curMsgTx = NotifiedFifoData(newTx);
pushNotifiedFIFO(&curMsgTx->UE->ul_actor.fifo, newTx);
int num_ul_actors_to_use =
get_nrUE_params()->num_ul_actors == 0 ? NUM_UL_ACTORS : min(get_nrUE_params()->num_ul_actors, NUM_UL_ACTORS);
pushNotifiedFIFO(&curMsgTx->UE->ul_actors[curMsgTx->proc.nr_slot_tx % num_ul_actors_to_use].fifo, newTx);
}
static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len)
@@ -436,9 +439,13 @@ static void UE_synch(void *arg) {
((ret.rx_offset << 1) / fp->samples_per_subframe * fp->slots_per_subframe)
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
// rerun with new cell parameters and frequency-offset
// todo: the freq_offset computed on DL shall be scaled before being applied to UL
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
if (get_nrUE_params()->cont_fo_comp) {
UE->freq_offset = freq_offset;
} else {
// rerun with new cell parameters and frequency-offset
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
}
if (get_nrUE_params()->agc) {
nr_ue_adjust_rx_gain(UE, cfg0, UE->adjust_rxgain);
@@ -452,7 +459,6 @@ static void UE_synch(void *arg) {
cfg0->rx_freq[0],
cfg0->tx_freq[0]);
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
UE->is_synchronized = 1;
} else {
int gain_change = 0;
@@ -551,6 +557,15 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action)
writeBlockSize -= dummyBlockSize;
}
// pre-compensate UL frequency offset
if (flags != TX_BURST_INVALID && get_nrUE_params()->cont_fo_comp) {
double ul_freq_offset = -UE->freq_offset * ((double)fp->ul_CarrierFreq / (double)fp->dl_CarrierFreq);
if (get_nrUE_params()->cont_fo_comp == 2) // different from LO frequency error compensation, Doppler UL pre-compensation has to be negative
ul_freq_offset = -ul_freq_offset;
for (int i = 0; i < fp->nb_antennas_tx; i++)
nr_fo_compensation(ul_freq_offset, fp->samples_per_subframe, writeTimestamp, txp[i], writeBlockSize);
}
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, txp, writeBlockSize, fp->nb_antennas_tx, flags);
AssertFatal(tmp == writeBlockSize, "");
}
@@ -585,6 +600,7 @@ void processSlotTX(void *arg)
UE->if_inst->sl_indication(&sl_indication);
stop_meas(&UE->ue_ul_indication_stats);
}
dynamic_barrier_join(rxtxD->next_barrier);
if (phy_data.sl_tx_action) {
@@ -611,12 +627,14 @@ void processSlotTX(void *arg)
UE->if_inst->ul_indication(&ul_indication);
stop_meas(&UE->ue_ul_indication_stats);
}
dynamic_barrier_join(rxtxD->next_barrier);
phy_procedures_nrUE_TX(UE, proc, &phy_data);
}
} else {
dynamic_barrier_join(rxtxD->next_barrier);
}
RU_write(rxtxD, sl_tx_action);
dynamic_barrier_join(rxtxD->next_barrier);
TracyCZoneEnd(ctx);
}
@@ -656,7 +674,9 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
for (int i = 0; i < NUM_DL_ACTORS; i++) {
flush_actor(UE->dl_actors + i);
}
flush_actor(&UE->ul_actor);
for (int i = 0; i < NUM_UL_ACTORS; i++) {
flush_actor(UE->ul_actors + i);
}
clean_UE_harq(UE);
UE->is_synchronized = 0;
@@ -861,13 +881,12 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
NR_DL_FRAME_PARMS *fp,
int slot_nr,
bool *update_ntn_system_information,
int *duration_rx_to_tx,
int *timing_advance,
int *ntn_koffset)
{
if (*update_ntn_system_information) {
*update_ntn_system_information = false;
if (UE->ntn_config_message->update) {
UE->ntn_config_message->update = false;
double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms;
UE->timing_advance = fp->samples_per_subframe * total_ta_ms;
@@ -913,6 +932,8 @@ void *UE_thread(void *arg)
if (usrp_tx_thread == 1)
UE->rfdevice.trx_write_init(&UE->rfdevice);
InitSinLUT();
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
@@ -947,13 +968,9 @@ void *UE_thread(void *arg)
double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
int ntn_koffset = 0;
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
int nr_slot_tx_offset = 0;
bool update_ntn_system_information = false;
while (!oai_exit) {
nr_slot_tx_offset = 0;
if (syncRunning) {
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
@@ -1078,12 +1095,6 @@ void *UE_thread(void *arg)
absolute_slot++;
TracyCFrameMark;
if (UE->ntn_config_message->update) {
UE->ntn_config_message->update = false;
update_ntn_system_information = true;
nr_slot_tx_offset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset << fp->numerology_index;
}
int slot_nr = absolute_slot % nb_slot_frame;
nr_rxtx_thread_data_t curMsg = {0};
curMsg.UE=UE;
@@ -1173,8 +1184,8 @@ void *UE_thread(void *arg)
shiftForNextFrame = ret;
pushNotifiedFIFO(&UE->dl_actors[curMsg.proc.nr_slot_rx % NUM_DL_ACTORS].fifo, newRx);
// apply new duration next run to avoid thread dead lock
apply_ntn_config(UE, fp, slot_nr, &update_ntn_system_information, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
// apply new NTN timing information
apply_ntn_config(UE, fp, slot_nr, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
// Start TX slot processing here. It runs in parallel with RX slot processing
// in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot
@@ -1185,7 +1196,6 @@ void *UE_thread(void *arg)
curMsgTx->writeBlockSize = writeBlockSize;
curMsgTx->proc.timestamp_tx = writeTimestamp;
curMsgTx->UE = UE;
curMsgTx->proc.nr_slot_tx_offset = nr_slot_tx_offset;
int slot = curMsgTx->proc.nr_slot_tx;
int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame;
+8 -2
View File
@@ -224,6 +224,8 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
UE->chest_freq = nrUE_params.chest_freq;
UE->chest_time = nrUE_params.chest_time;
UE->no_timing_correction = nrUE_params.no_timing_correction;
UE->initial_fo = nrUE_params.initial_fo;
UE->cont_fo_comp = nrUE_params.cont_fo_comp;
LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time);
@@ -508,7 +510,9 @@ int main(int argc, char **argv)
for (int i = 0; i < NUM_DL_ACTORS; i++) {
init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1);
}
init_actor(&UE[CC_id]->ul_actor, "UL_", -1);
for (int i = 0; i < NUM_UL_ACTORS; i++) {
init_actor(&UE[CC_id]->ul_actors[i], "UL_", -1);
}
init_nr_ue_vars(UE[CC_id], inst);
if (UE[CC_id]->sl_mode) {
@@ -578,7 +582,9 @@ int main(int argc, char **argv)
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id];
if (phy_vars) {
shutdown_actor(&phy_vars->ul_actor);
for (int i = 0; i < NUM_UL_ACTORS; i++) {
shutdown_actor(&phy_vars->ul_actors[i]);
}
for (int i = 0; i < NUM_DL_ACTORS; i++) {
shutdown_actor(&phy_vars->dl_actors[i]);
}
+15
View File
@@ -14,7 +14,12 @@
#define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n"
#define CONFIG_HLP_NTN_INIT_TIME_DRIFT "Initial NTN DL time drift (feeder link and service link), given in µs/s\n"
#define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n"
#define CONFIG_HLP_INITIAL_FO "Initially compensated DL frequency offset (e.g. known Doppler shift in NTN LEO scenario)\n"
#define CONFIG_HLP_FREQ_SYNC_P "coefficient for Proportional part of continuous frequency offset compensation PI controller\n"
#define CONFIG_HLP_FREQ_SYNC_I "coefficient for Integrating part of continuous frequency offset compensation PI controller\n"
#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift)\n"
#define CONFIG_HLP_AGC "Rx Gain control used for UE\n"
#define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to use the default value\n"
/***************************************************************************************************************************************/
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
@@ -65,7 +70,12 @@
{"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"ntn-initial-time-drift", CONFIG_HLP_NTN_INIT_TIME_DRIFT, 0, .dblptr=&(nrUE_params.ntn_init_time_drift), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \
{"initial-fo", CONFIG_HLP_INITIAL_FO, 0, .dblptr=&(nrUE_params.initial_fo), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"freq-sync-P", CONFIG_HLP_FREQ_SYNC_P, 0, .dblptr=&(nrUE_params.freq_sync_P), .defdblval=0.01, TYPE_DOUBLE, 0}, \
{"freq-sync-I", CONFIG_HLP_FREQ_SYNC_I, 0, .dblptr=&(nrUE_params.freq_sync_I), .defdblval=0.001, TYPE_DOUBLE, 0}, \
{"cont-fo-comp", CONFIG_HLP_CONT_FO_COMP, 0, .iptr=&(nrUE_params.cont_fo_comp), .defintval=0, TYPE_INT, 0}, \
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \
{"num-ul-actors", CONFIG_HLP_NUM_UL_ACTORS, 0, .iptr=&nrUE_params.num_ul_actors, .defintval=0, TYPE_INT, 0}, \
}
// clang-format on
@@ -89,6 +99,10 @@ typedef struct {
double time_sync_I;
double ntn_init_time_drift;
int autonomous_ta;
double initial_fo;
double freq_sync_P;
double freq_sync_I;
int cont_fo_comp;
int agc;
char *usrp_args;
char *tx_subdev;
@@ -101,6 +115,7 @@ typedef struct {
double rx_gain_off;
int vcdflag;
int tx_max_power;
int num_ul_actors;
} nrUE_params_t;
extern uint64_t get_nrUE_optmask(void);
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
-6
View File
@@ -171,7 +171,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
NR_DL_FRAME_PARMS *const fp = &ue->frame_parms;
NR_UE_COMMON *const common_vars = &ue->common_vars;
NR_UE_PRACH **const prach_vars = ue->prach_vars;
NR_UE_SRS **const srs_vars = ue->srs_vars;
LOG_I(PHY, "Initializing UE vars for gNB TXant %u, UE RXant %u\n", fp->nb_antennas_tx, fp->nb_antennas_rx);
@@ -257,8 +256,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
// DLSCH
for (int gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
prach_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_PRACH));
srs_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_SRS));
srs_vars[gNB_id]->active = false;
// ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32)
ue->nr_csi_info = malloc16_clear(sizeof(nr_csi_info_t));
@@ -318,8 +315,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
free_and_zero(ue->nr_srs_info);
free_and_zero(ue->srs_vars[gNB_id]);
free_and_zero(ue->prach_vars[gNB_id]);
}
@@ -487,7 +482,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE)
for (int harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) {
NR_UL_UE_HARQ_t *ul_harq_process = &UE->ul_harq_processes[harq_pid];
ul_harq_process->tx_status = NEW_TRANSMISSION_HARQ;
ul_harq_process->ULstatus = SCH_IDLE;
ul_harq_process->round = 0;
}
}
+7
View File
@@ -25,6 +25,7 @@
#include "nr_modulation.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
#include <common/utils/LOG/log.h>
//#define DEBUG_FEP
@@ -108,6 +109,12 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
rxdata_ptr = (int16_t *)tmp_dft_in;
}
if (ue && ue->cont_fo_comp) {
start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
nr_fo_compensation(ue->freq_offset, frame_parms->samples_per_subframe, rx_offset, (c16_t *)rxdata_ptr, frame_parms->ofdm_symbol_size);
stop_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
}
if (ue)
start_meas_nr_ue_phy(ue, RX_DFT_STATS);
+1 -1
View File
@@ -730,7 +730,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
#endif
}
uint32_t dmrs_idx = rel15->rbStart;
if (rel15->rnti != SI_RNTI)
if (rel15->refPoint == 0)
dmrs_idx += rel15->BWPStart;
dmrs_idx *= dmrs_Type == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
c16_t txdataF_precoding[rel15->nrOfLayers][symbol_sz] __attribute__((aligned(64)));
@@ -47,7 +47,7 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN);
// search for maximum position within the cyclic prefix
for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) {
for (int i = -frame_parms->nb_prefix_samples; i < frame_parms->nb_prefix_samples; i++) {
int temp = 0;
int j = (i < 0) ? (i + frame_parms->ofdm_symbol_size) : i;
+4 -1
View File
@@ -640,6 +640,9 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
{
int e_rx_cand_idx = 0;
*dci_ind = (fapi_nr_dci_indication_t){.SFN = proc->frame_rx, .slot = proc->nr_slot_rx};
// if DCI for SIB we don't break after finding 1st DCI with that RNTI
// there might be SIB1 and otherSIB in the same slot with the same length
bool is_SI = rel15->rnti == SI_RNTI;
for (int j = 0; j < rel15->number_of_candidates; j++) {
int CCEind = rel15->CCE[j];
@@ -653,7 +656,7 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
int dci_length = rel15->dci_length_options[k];
int ind;
for (ind = 0; ind < dci_ind->number_of_dcis; ind++) {
if (rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) {
if (!is_SI && rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) {
break;
}
}
@@ -766,10 +766,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
for (int a = 0; a < nbRx; a++) {
int offset = (void *)rxdataF_comp[0][a] - (void *)rxdataF_comp[0] + symbol * rx_size_symbol * sizeof(c16_t);
memcpy(ue->phy_sim_pdsch_rxdataF_comp + offset, rxdataF_comp[0][a] + symbol * rx_size_symbol, sizeof(c16_t) * rx_size_symbol);
memcpy(ue->phy_sim_pdsch_dl_ch_estimates + offset, dl_ch_estimates, pdsch_est_size * sizeof(c16_t));
memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates + pdsch_est_size * a, dl_ch_estimates, pdsch_est_size * sizeof(c16_t));
}
if (ue->phy_sim_pdsch_dl_ch_estimates_ext)
memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol, dl_ch_estimates_ext, sizeof(dl_ch_estimates_ext));
memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol,
dl_ch_estimates_ext,
sizeof(dl_ch_estimates_ext));
return (0);
}
@@ -199,6 +199,9 @@ void nr_scan_ssb(void *arg)
// initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame
// only one frame is used for simulation tools
for (int frame_id = 0; frame_id < ssbInfo->nFrames && !ssbInfo->syncRes.cell_detected; frame_id++) {
if (ssbInfo->freqOffset)
compensate_freq_offset(rxdata, fp, ssbInfo->freqOffset, frame_id);
/* process pss search on received buffer */
ssbInfo->syncRes.frame_id = frame_id;
int nid2;
@@ -268,7 +271,7 @@ void nr_scan_ssb(void *arg)
phase_tdd_ncp,
ssbInfo->syncRes.rx_offset);
#endif
ssbInfo->freqOffset = freq_offset_pss + freq_offset_sss;
ssbInfo->freqOffset += freq_offset_pss + freq_offset_sss;
if (ssbInfo->syncRes.cell_detected) { // we got sss channel
ssbInfo->syncRes.cell_detected = nr_pbch_detection(ssbInfo->proc,
@@ -319,6 +322,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
.syncRes.cell_detected = false,
.nFrames = n_frames,
.foFlag = ue->UE_fo_compensation,
.freqOffset = ue->initial_fo,
.targetNidCell = ue->target_Nid_cell};
ssbInfo->rxdata = malloc16_clear(fp->nb_antennas_rx * sizeof(c16_t *));
for (int ant = 0; ant < fp->nb_antennas_rx; ant++) {
+18
View File
@@ -525,3 +525,21 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
TracyCZoneEnd(ctx);
return 0;
}
double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms,
int estimateSz,
const c16_t dl_ch_estimates[][estimateSz])
{
const int i_ssb = frame_parms->ssb_index;
const int symbol_offset = nr_get_ssb_start_symbol(frame_parms, i_ssb) % frame_parms->symbols_per_slot;
const c16_t *dl_ch_est_symb1 = &dl_ch_estimates[0][(symbol_offset + 1) * frame_parms->ofdm_symbol_size];
const c16_t *dl_ch_est_symb3 = &dl_ch_estimates[0][(symbol_offset + 3) * frame_parms->ofdm_symbol_size];
const int nb_re = 240;
const c32_t dot_prod_res = dot_product(dl_ch_est_symb1, dl_ch_est_symb3, nb_re, 8);
const double res_phase = atan2(dot_prod_res.i, dot_prod_res.r);
const int samples_per_symbol = frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples;
const double t_ofdm = samples_per_symbol / (frame_parms->samples_per_subframe * 1000.0); // symbol duration in sec
const double freq_offset = res_phase / (2 * M_PI * (3 - 1) * t_ofdm);
return freq_offset;
}
+1 -1
View File
@@ -68,7 +68,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
int Ncp = 0;
int prach_start, prach_sequence_length, prach_len, dftlen, mu, n_ra_prb, k, prachStartSymbol, sample_offset_slot;
fd_occasion = 0;
fd_occasion = prach_pdu->num_ra;
prach_len = 0;
dftlen = 0;
first_nonzero_root_idx = 0;
@@ -204,6 +204,10 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
int rxdataFSize,
const struct complex16 rxdataF[][rxdataFSize]);
double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms,
int estimateSz,
const c16_t dl_ch_estimates[][estimateSz]);
#ifndef modOrder
#define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS
#endif
@@ -46,8 +46,6 @@ typedef enum {
typedef struct {
/// HARQ tx status
harq_result_t tx_status;
/// Status Flag indicating for this ULSCH (idle,active,disabled)
SCH_status_t ULstatus;
/// Last TPC command
uint8_t TPC;
/// Length of ACK information (bits)
@@ -87,6 +85,7 @@ typedef struct {
} NR_UL_UE_HARQ_t;
typedef struct {
SCH_status_t status;
/// NDAPI struct for UE
nfapi_nr_ue_pusch_pdu_t pusch_pdu;
// UL number of harq processes
+1 -8
View File
@@ -471,7 +471,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
if (UE->ul_harq_processes[harq_pid].ULstatus != ACTIVE)
if (phy_data->ulsch.status != ACTIVE)
return;
start_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
@@ -542,8 +542,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
/////////////////////////ULSCH coding/////////////////////////
if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) {
NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
harq_process_ulsch->ULstatus = SCH_IDLE;
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
return;
}
@@ -820,12 +818,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
} // symbol loop
} // port loop
NR_UL_UE_HARQ_t *harq_process_ulsch = NULL;
harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
harq_process_ulsch->ULstatus = SCH_IDLE;
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
}
uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
@@ -426,14 +426,15 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t **txdataF,
nr_phy_data_tx_t *phy_data,
bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT])
{
if(!ue->srs_vars[0]->active) {
if(phy_data->srs_vars.active == false) {
return -1;
}
ue->srs_vars[0]->active = false;
nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t*)&ue->srs_vars[0]->srs_config_pdu;
// TODO: This is wrong: casting from UE fapi to gNB NFAPI srs pdu
nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t *)&phy_data->srs_vars.srs_config_pdu;
int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position;
// Num consecutive SRS symbols according to 38.211 6.4.1.4.1
@@ -78,7 +78,10 @@ int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource,
@param rxtx context
@param current gNB_id identifier
@returns 0 if srs is transmitted -1 otherwise */
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF, bool was_symbol_used[14]);
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t **txdataF,
nr_phy_data_tx_t *phy_data,
bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]);
#endif /* SRS_MODULATION_NR_H */
+70
View File
@@ -0,0 +1,70 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <stdint.h>
#include <math.h>
#include "tools_defs.h"
#define LUT_SIN_RESOL 128
// look-up table for the sine (cosine) function
static uint16_t LUTSin[LUT_SIN_RESOL + 1];
void InitSinLUT(void)
{
for (int i = 0; i < (LUT_SIN_RESOL + 1); i++) {
LUTSin[i] = round(sin((M_PI * i) / (2 * LUT_SIN_RESOL)) * (1 << 14)); // Format: Q14
}
}
// fast calculation of e^{i*2*pi*phase}
// ret.r == cosinus << 14
// ret.i == sinus << 14
c16_t get_sin_cos(double phase)
{
int index;
if (phase < 0) {
index = (int)(-phase * 4 * LUT_SIN_RESOL + 0.5) % (4 * LUT_SIN_RESOL);
index = 4 * LUT_SIN_RESOL - index;
} else {
index = (int)(phase * 4 * LUT_SIN_RESOL + 0.5) % (4 * LUT_SIN_RESOL);
}
c16_t ret;
if (index < 2 * LUT_SIN_RESOL) { // check for 1st and 2nd Quadrant
if (index < LUT_SIN_RESOL) { // 1st Quadrant
ret.r = LUTSin[LUT_SIN_RESOL - index];
ret.i = LUTSin[index];
} else { // 2nd Quadrant
ret.r = -LUTSin[index - LUT_SIN_RESOL];
ret.i = LUTSin[2 * LUT_SIN_RESOL - index];
}
} else { // 3rd and 4th Quadrant
if (index < 3 * LUT_SIN_RESOL) { // 3rd Quadrant
ret.r = -LUTSin[3 * LUT_SIN_RESOL - index];
ret.i = -LUTSin[index - 2 * LUT_SIN_RESOL];
} else { // 4th Quadrant
ret.r = LUTSin[index - 3 * LUT_SIN_RESOL];
ret.i = -LUTSin[4 * LUT_SIN_RESOL - index];
}
}
return ret;
}
+7
View File
@@ -792,6 +792,13 @@ double interp(double x, double *xs, double *ys, int count);
void simde_mm128_separate_real_imag_parts(simde__m128i *out_re, simde__m128i *out_im, simde__m128i in0, simde__m128i in1);
void simde_mm256_separate_real_imag_parts(simde__m256i *out_re, simde__m256i *out_im, simde__m256i in0, simde__m256i in1);
void InitSinLUT(void);
// fast calculation of e^{i*2*pi*phase}
// ret.r == cosinus << 14
// ret.i == sinus << 14
c16_t get_sin_cos(double phase);
#ifdef __cplusplus
}
#endif
+9 -7
View File
@@ -82,6 +82,7 @@
/// suppress compiler warning for unused arguments
#define UNUSED(x) (void)x;
#define NUM_DL_ACTORS 4
#define NUM_UL_ACTORS 2
// Set the number of barriers for processSlotTX to 512. This value has to be at least 483 for NTN where
// DL-to-UL offset is up to 483. The selected value is also half of the frame range so that
@@ -401,7 +402,6 @@ typedef struct PHY_VARS_NR_UE_s {
nr_synch_request_t synch_request;
NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_SRS *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE];
uint8_t prs_active_gNBs;
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
@@ -460,6 +460,11 @@ typedef struct PHY_VARS_NR_UE_s {
int64_t max_pos_iir; /// Timing offset IIR filter
int max_pos_acc; /// Timing offset accumuluated error for PI filter
double initial_fo; /// initial frequency offset provided by the user
int cont_fo_comp; /// flag enabling the continuous frequency offset estimation and compensation
double freq_offset; /// currently compensated frequency offset
double freq_off_acc; /// accumulated frequency error (for PI controller)
/// Timing Advance updates variables
/// Timing advance update computed from the TA command signalled from gNB
int timing_advance;
@@ -514,7 +519,7 @@ typedef struct PHY_VARS_NR_UE_s {
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
Actor_t sync_actor;
Actor_t dl_actors[NUM_DL_ACTORS];
Actor_t ul_actor;
Actor_t ul_actors[NUM_UL_ACTORS];
ntn_config_message_t* ntn_config_message;
pthread_t main_thread;
pthread_t stat_thread;
@@ -525,10 +530,6 @@ typedef struct {
int gNB_id;
/// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_tx;
/// NR slot index tx offset to resume
/// in case of NTN, tx_offset can be changed dynamically via SIB19
/// we need to notify the right tx thread slot based on TX offset change
int nr_slot_tx_offset;
int rx_slot_type;
/// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission
int nr_slot_rx;
@@ -571,6 +572,7 @@ typedef struct {
typedef struct nr_phy_data_tx_s {
NR_UE_ULSCH_t ulsch;
NR_UE_PUCCH pucch_vars;
NR_UE_SRS srs_vars;
// Sidelink Rx action decided by MAC
sl_nr_tx_config_type_enum_t sl_tx_action;
@@ -597,7 +599,7 @@ typedef struct nr_rxtx_thread_data_s {
PHY_VARS_NR_UE *UE;
int writeBlockSize;
nr_phy_data_t phy_data;
dynamic_barrier_t *next_barrier;
dynamic_barrier_t* next_barrier;
} nr_rxtx_thread_data_t;
typedef struct LDPCDecode_ue_s {
@@ -80,4 +80,6 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int
void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal);
void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay);
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb);
void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size);
#endif
@@ -28,6 +28,7 @@
#define FOREACH_NR_PHY_CPU_MEAS(FN) \
FN(RX_PDSCH_STATS),\
FN(DLSCH_RX_PDCCH_STATS),\
FN(RX_FO_COMPENSATION_STATS),\
FN(RX_DFT_STATS),\
FN(DLSCH_CHANNEL_ESTIMATION_STATS),\
FN(DLSCH_DECODING_STATS),\
@@ -453,3 +453,40 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, in
}
return (0);
}
void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size)
{
const double phase_inc = -fo_Hz / (samples_per_ms * 1000);
double phase = sample_offset * phase_inc;
phase -= (int)phase;
#if 1
// The bottleneck is the calculation of the complex rotation values using get_sin_cos().
// This code path does not compute these values for the complete OFDM symbol, but only for a smaller CHUNK size.
// After applying the rotation to a CHUNK size of the output, these rotation values are efficiently rotated further by `rot_vec`.
// Unfortunately, this propagates small errors from one chunk to the next.
// Therefore, there is a tradeoff between speed (better with small CHUNK sizes) and accuracy (better with large CHUNK sizes).
#define CHUNK 128
c16_t rot[CHUNK] __attribute__((aligned(32)));
for (int i = 0; i < CHUNK; i++) {
rot[i] = get_sin_cos(phase);
phase += phase_inc;
}
const c16_t rot_vec = get_sin_cos(CHUNK * phase_inc);
while (size > CHUNK) {
mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, CHUNK, 14);
rxdata_ptr += CHUNK;
rotate_cpx_vector(rot, &rot_vec, rot, CHUNK, 14);
size -= CHUNK;
}
mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, size, 14);
#else
// This code path computes the complex rotation values for the complete OFDM symbol using get_sin_cos().
// This is more accurate, but also slower than the code path above.
c16_t rot[size] __attribute__((aligned(32)));
for (int i = 0; i < size; i++) {
rot[i] = get_sin_cos(phase);
phase += phase_inc;
}
mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, size, 14);
#endif
}
+3 -3
View File
@@ -518,7 +518,7 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r
pdu->pusch_config_pdu.tx_request_body.pdu_length);
}
harq_process_ul_ue->ULstatus = ACTIVE;
phy_data->ulsch.status = ACTIVE;
pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
} break;
@@ -549,8 +549,8 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r
case FAPI_NR_UL_CONFIG_TYPE_SRS:
// srs config pdu
phy->srs_vars[0]->srs_config_pdu = pdu->srs_config_pdu;
phy->srs_vars[0]->active = true;
phy_data->srs_vars.srs_config_pdu = pdu->srs_config_pdu;
phy_data->srs_vars.active = true;
pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
break;
+12 -1
View File
@@ -290,7 +290,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used);
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, was_symbol_used);
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, phy_data, was_symbol_used);
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used);
@@ -929,6 +929,17 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_
sampleShift =
nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384);
}
if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) {
double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates);
LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz, accumulated frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset, ue->freq_off_acc);
// PI controller
const double PID_P = get_nrUE_params()->freq_sync_P;
const double PID_I = get_nrUE_params()->freq_sync_I;
ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I;
ue->freq_off_acc += freq_offset;
}
}
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
nr_ue_rrc_measurements(ue, proc, rxdataF);
+46 -19
View File
@@ -958,6 +958,13 @@ printf("%d\n", slot);
fprintf(csv_file,"avg_round,eff_rate,eff_throughput,TBS\n");
}
//---------------
Sched_INFO = malloc(sizeof(*Sched_INFO));
if (Sched_INFO == NULL) {
LOG_E(PHY, "out of memory\n");
exit(1);
}
for (SNR = snr0; SNR < snr1 && !stop; SNR += .2) {
varArray_t *table_tx=initVarArray(1000,sizeof(double));
@@ -988,6 +995,9 @@ printf("%d\n", slot);
n_false_positive = 0;
if (n_trials== 1) num_rounds = 1;
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
for (trial = 0; trial < n_trials && !stop; trial++) {
errors_bit = 0;
@@ -1003,19 +1013,11 @@ printf("%d\n", slot);
int harq_pid = slot;
NR_DL_UE_HARQ_t *UE_harq_process = &UE->dl_harq_processes[0][harq_pid];
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
UE_harq_process->decodeResult = false;
round = 0;
UE_harq_process->DLround = round;
UE_harq_process->first_rx = 1;
Sched_INFO = malloc(sizeof(*Sched_INFO));
if (Sched_INFO == NULL) {
LOG_E(PHY, "out of memory\n");
exit(1);
}
memset(Sched_INFO, 0, sizeof(*Sched_INFO));
Sched_INFO->sched_response_id = -1;
@@ -1109,10 +1111,10 @@ printf("%d\n", slot);
sprintf(filename,"txsig%d.m", aa);//LOG_M
LOG_M(filename,"txs", &txdata[aa][slot_offset +frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1);
}
}
if (output_fd) {
printf("writing txdata to binary file\n");
fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
if (output_fd) {
printf("writing txdata to binary file\n");
fwrite(txdata[0], sizeof(int32_t), frame_length_complex_samples, output_fd);
}
}
int txlev[n_tx];
@@ -1296,15 +1298,38 @@ printf("%d\n", slot);
}
if (n_trials == 1) {
unsigned int op_format = 1;
unsigned int dec = 1;
if (output_fd) { // Write in bin format
op_format |= MATLAB_RAW;
}
LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1);
LOG_M("rxsig0.m", "rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, dec, op_format);
if (UE->frame_parms.nb_antennas_rx>1)
LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1);
LOG_M("rxF0.m","rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, 1, 1);
LOG_M("rxF_ext.m","rxFe",UE->phy_sim_pdsch_rxdataF_ext,g_rbSize*12*14,1,1);
LOG_M("chestF0.m","chF0",UE->phy_sim_pdsch_dl_ch_estimates_ext,g_rbSize*12*14,1,1);
write_output("rxF_comp.m","rxFc",UE->phy_sim_pdsch_rxdataF_comp,N_RB_DL*12*14,1,1);
LOG_M("rxF_llr.m","rxFllr",UE->phy_sim_pdsch_llr,available_bits,1,0);
LOG_M("rxsig1.m", "rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, dec, op_format);
LOG_M("rxF0.m", "rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, dec, op_format);
LOG_M("rxF_ext.m", "rxFe", UE->phy_sim_pdsch_rxdataF_ext, g_rbSize * 12 * 14, dec, op_format);
const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15);
const uint32_t numValidReSym = g_rbSize * 12;
{
const int s = rel15->StartSymbolIndex;
const int n = rel15->NrOfSymbols;
for (int i = s; i < s + n; i++) {
char fName[50];
snprintf(fName, sizeof(fName), "chestF0_ext_s%d.m", i);
LOG_M(fName,
"chF0_ext",
((c16_t *)UE->phy_sim_pdsch_dl_ch_estimates_ext) + (i * numReSym),
numValidReSym,
dec,
op_format);
snprintf(fName, sizeof(fName), "rxF_comp_s%d.m", i);
LOG_M(fName, "rxFc", ((c16_t *)UE->phy_sim_pdsch_rxdataF_comp) + (i * numReSym), numValidReSym, dec, op_format);
}
}
LOG_M("chestF0.m", "chF0", UE->phy_sim_pdsch_dl_ch_estimates, frame_parms->ofdm_symbol_size * 14, dec, op_format);
op_format = (op_format & (~1));
LOG_M("rxF_llr.m", "rxFllr", UE->phy_sim_pdsch_llr, available_bits, dec, op_format);
break;
}
@@ -1316,6 +1341,8 @@ printf("%d\n", slot);
n_errs = n_errors[0];
} // NSR
free(Sched_INFO);
free_channel_desc_scm(gNB2UE);
for (i = 0; i < n_tx; i++) {
+30 -27
View File
@@ -239,6 +239,7 @@ int main(int argc, char *argv[])
int threadCnt=0;
int max_ldpc_iterations = 5;
int num_antennas_per_thread = 1;
uint32_t log_format = 0;
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
exit_fun("[NR_ULSIM] Error, configuration module init failed\n");
}
@@ -250,8 +251,7 @@ int main(int argc, char *argv[])
InitSinLUT();
int c;
while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:k:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) {
while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:jk:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) {
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
if (c == 1 || c == '-' || c == 'O')
@@ -345,7 +345,11 @@ int main(int argc, char *argv[])
i+=2;
} while (optarg[i-1] == ',');
break;
case 'j':
log_format |= MATLAB_RAW;
break;
case 'k':
printf("Setting threequarter_fs_flag\n");
openair0_cfg[0].threequarter_fs= 1;
@@ -523,6 +527,7 @@ int main(int argc, char *argv[])
printf("-g Channel model configuration. Arguments list: Number of arguments = 3, {Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300}, {Correlation: [l] Low, [m] Medium, [h] High}, {Maximum Doppler shift} e.g. -g A,l,10\n");
printf("-h This message\n");
printf("-i Change channel estimation technique. Arguments list: Number of arguments=2, Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}. e.g. -i 1,0\n");
printf("-j Save signal buffers in binary format.");
printf("-k 3/4 sampling\n");
printf("-m MCS value\n");
printf("-n Number of trials to simulate\n");
@@ -559,7 +564,7 @@ int main(int argc, char *argv[])
}
}
logInit();
set_glog(loglvl);
@@ -1214,12 +1219,12 @@ int main(int argc, char *argv[])
phy_procedures_nrUE_TX(UE, &UE_proc, &phy_data);
if (n_trials == 1) {
LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1);
LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1 | log_format);
if (precod_nbr_layers > 1) {
LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1);
if (precod_nbr_layers == 4) {
LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1);
LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1);
LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1 | log_format);
if (precod_nbr_layers == 4) {
LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1 | log_format);
LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1 | log_format);
}
}
}
@@ -1293,16 +1298,16 @@ int main(int argc, char *argv[])
ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot, &UL_INFO);
if (n_trials == 1 && round == 0) {
LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1);
LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1);
LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1 | log_format);
LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
if (precod_nbr_layers > 1) {
LOG_M("rxsig1.m", "rx1", &rxdata[1][slot_offset], slot_length, 1, 1);
LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1);
LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
if (precod_nbr_layers == 4) {
LOG_M("rxsig2.m", "rx2", &rxdata[2][slot_offset], slot_length, 1, 1);
LOG_M("rxsig3.m", "rx3", &rxdata[3][slot_offset], slot_length, 1, 1);
LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1);
LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1);
LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
}
}
}
@@ -1316,71 +1321,69 @@ int main(int argc, char *argv[])
&pusch_vars->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size],
frame_parms->ofdm_symbol_size,
1,
1);
1 | log_format);
LOG_M("rxsigF0_comp.m",
"rxsF0_comp",
&pusch_vars->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
1 | log_format);
if (precod_nbr_layers == 2) {
LOG_M("chestF3.m",
"chF3",
&pusch_vars->ul_ch_estimates[3][start_symbol * frame_parms->ofdm_symbol_size],
frame_parms->ofdm_symbol_size,
1,
1);
1 | log_format);
LOG_M("rxsigF2_comp.m",
"rxsF2_comp",
&pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
1 | log_format);
}
if (precod_nbr_layers == 4) {
LOG_M("chestF5.m",
"chF5",
&pusch_vars->ul_ch_estimates[5][start_symbol * frame_parms->ofdm_symbol_size],
frame_parms->ofdm_symbol_size,
1,
1);
1 | log_format);
LOG_M("chestF10.m",
"chF10",
&pusch_vars->ul_ch_estimates[10][start_symbol * frame_parms->ofdm_symbol_size],
frame_parms->ofdm_symbol_size,
1,
1);
1 | log_format);
LOG_M("chestF15.m",
"chF15",
&pusch_vars->ul_ch_estimates[15][start_symbol * frame_parms->ofdm_symbol_size],
frame_parms->ofdm_symbol_size,
1,
1);
1 | log_format);
LOG_M("rxsigF4_comp.m",
"rxsF4_comp",
&pusch_vars->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
1 | log_format);
LOG_M("rxsigF8_comp.m",
"rxsF8_comp",
&pusch_vars->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
1 | log_format);
LOG_M("rxsigF12_comp.m",
"rxsF12_comp",
&pusch_vars->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
1,
1);
1 | log_format);
}
LOG_M("rxsigF0_llr.m",
@@ -1388,7 +1391,7 @@ int main(int argc, char *argv[])
&pusch_vars->llr[0],
precod_nbr_layers * (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order,
1,
0);
0 | log_format);
}
if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) {
@@ -143,31 +143,6 @@ void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *des
#else
void add_noise(c16_t **rxdata,
const double **r_re,
const double **r_im,
const double sigma,
const int length,
const int slot_offset,
const double ts,
const int delay,
const uint16_t pdu_bit_map,
const uint16_t ptrs_bit_map,
const uint8_t nb_antennas_rx)
{
for (int i = 0; i < length; i++) {
for (int ap = 0; ap < nb_antennas_rx; ap++) {
c16_t *rxd = &rxdata[ap][slot_offset + i + delay];
rxd->r = r_re[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); // convert to fixed point
rxd->i = r_im[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0);
/* Add phase noise if enabled */
if (pdu_bit_map & ptrs_bit_map) {
phase_noise(ts, &rxdata[ap][slot_offset + i + delay].r, &rxdata[ap][slot_offset + i + delay].i);
}
}
}
}
void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *desc,
double *tx_sig_re[NB_ANTENNAS_TX],
double *tx_sig_im[NB_ANTENNAS_TX],
+30 -36
View File
@@ -23,47 +23,41 @@
#include "sim.h"
static uint16_t LUTSin[ResolSinCos+1];
/* linear phase noise model */
void phase_noise(double ts, int16_t * InRe, int16_t * InIm)
void phase_noise(double ts, int16_t *InRe, int16_t *InIm)
{
static uint64_t i=0;
int32_t x=0 ,y=0;
double fd = 300;//0.01*30000
int16_t SinValue = 0, CosValue= 0;
double IdxDouble = (double)(i*fd * ts * ResolSinCos * 4);
int16_t IdxModulo = ((int32_t)(IdxDouble>0 ? IdxDouble+0.5 : IdxDouble-0.5)) % (ResolSinCos*4);
IdxModulo = IdxModulo<0 ? IdxModulo+ResolSinCos*4 : IdxModulo;
if(IdxModulo<2*ResolSinCos) {//< 2 check for 1st and 2nd
if(IdxModulo < ResolSinCos) {// 1st Quadrant
SinValue = LUTSin[IdxModulo];
CosValue = LUTSin[ResolSinCos-IdxModulo];
}
else {// 2nd Quadrant
SinValue = LUTSin[2*ResolSinCos-IdxModulo];
CosValue = -LUTSin[IdxModulo-ResolSinCos];
}
}
else {// 3rd and 4th Quadrant
if(IdxModulo < 3*ResolSinCos) {// 3rd Quadrant
SinValue = -LUTSin[IdxModulo-2*ResolSinCos];
CosValue = -LUTSin[3*ResolSinCos-IdxModulo];
}
else {//4th Quadrant
SinValue = -LUTSin[4*ResolSinCos-IdxModulo];
CosValue = LUTSin[IdxModulo-3*ResolSinCos];
}
}
x = ( ((int32_t)InRe[0] * CosValue) - ((int32_t)InIm[0] * SinValue ));
y = ( ((int32_t)InIm[0] * CosValue) + ((int32_t)InRe[0] * SinValue ));
InRe[0]= (int16_t)(x>>14);
InIm[0]= (int16_t)(y>>14);
double phase = (double)(i * fd * ts);
c16_t rot = get_sin_cos(phase);
c16_t val = {.r = *InRe, .i = *InIm};
val = c16mulShift(val, rot, 14);
*InRe = val.r;
*InIm = val.i;
i++;
}
/* Initialisation function for SIN table values */
void InitSinLUT( void ) {
for ( int i=0; i<(ResolSinCos+1); i++ ) {
LUTSin[i] = sin((double)(M_PI*i)/(2*ResolSinCos)) * (1<<14); //Format: Q14
void add_noise(c16_t **rxdata,
const double **r_re,
const double **r_im,
const double sigma,
const int length,
const int slot_offset,
const double ts,
const int delay,
const uint16_t pdu_bit_map,
const uint16_t ptrs_bit_map,
const uint8_t nb_antennas_rx)
{
for (int i = 0; i < length; i++) {
for (int ap = 0; ap < nb_antennas_rx; ap++) {
c16_t *rxd = &rxdata[ap][slot_offset + i + delay];
rxd->r = r_re[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); // convert to fixed point
rxd->i = r_im[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0);
/* Add phase noise if enabled */
if (pdu_bit_map & ptrs_bit_map) {
phase_noise(ts, &rxdata[ap][slot_offset + i + delay].r, &rxdata[ap][slot_offset + i + delay].i);
}
}
}
}
+6 -1
View File
@@ -1663,7 +1663,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
maxDoppler = 0;
chan_desc->sat_height = 600e3;
chan_desc->enable_dynamic_delay = true;
chan_desc->enable_dynamic_Doppler = false; // TODO: requires UE to support continuous Doppler estimation, compensation and pre-compensation
chan_desc->enable_dynamic_Doppler = true;
fill_channel_desc(chan_desc,nb_tx,
nb_rx,
nb_taps,
@@ -1762,6 +1762,11 @@ void set_channeldesc_name(channel_desc_t *cdesc,char *modelname) {
cdesc->model_name=strdup(modelname);
}
void set_channeldesc_direction(channel_desc_t *cdesc, bool is_uplink)
{
cdesc->is_uplink = is_uplink;
}
#ifdef DEBUG_CH_POWER
double accumulated_ch_power = 0;
int ch_power_count = 0;
+38 -32
View File
@@ -139,6 +139,8 @@ typedef struct {
float Doppler_phase_inc;
/// current Doppler phase of each RX antenna (for continuous phase from one block to the next)
float *Doppler_phase_cur;
/// flag indicating if channel direction is UL or DL
bool is_uplink;
} channel_desc_t;
typedef struct {
@@ -358,6 +360,7 @@ void free_channel_desc_scm(channel_desc_t *ch);
\param module_id identifies the channel model. should be define as a macro in simu.h
*/
void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id);
/**
\brief This function set a model name to a model descriptor, can be later used to identify a allocated channel model
\param cdesc points to the model descriptor
@@ -365,6 +368,13 @@ void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_i
*/
void set_channeldesc_name(channel_desc_t *cdesc,char *modelname);
/**
\brief This function set a channel model direction to either uplink or downlink
\param cdesc points to the model descriptor
\param is_uplink indicates if this channel is applied in uplink (not downlink) direction
*/
void set_channeldesc_direction(channel_desc_t *cdesc, bool is_uplink);
/** \fn void get_cexp_doppler(struct complexd *cexp_doppler, channel_desc_t *chan_desc, const uint32_t length)
\brief This routine generates the complex exponential to apply the Doppler shift
\param cexp_doppler Output with the complex exponential of Doppler shift
@@ -379,32 +389,6 @@ void get_cexp_doppler(struct complexd *cexp_doppler, channel_desc_t *chan_desc,
*/
int random_channel(channel_desc_t *desc, uint8_t abstraction_flag);
/**
\brief Add AWGN noise and phase noise if enabled
\param rxdata output data with noise
\param r_re real part of input data without noise
\param r_im imaginary part of input data without noise
\param sigma noise power
\param length number of samples to apply the noise
\param slot_offset slot offset to start applying the noise
\param ts sampling time
\param delay introduce delay in terms of number of samples
\param pdu_bit_map bitmap indicating presence of optional PDUs
\param ptrs_bit_map
\param nb_antennas_rx number of receive antennas
*/
void add_noise(c16_t **rxdata,
const double **r_re,
const double **r_im,
const double sigma,
const int length,
const int slot_offset,
const double ts,
const int delay,
const uint16_t pdu_bit_map,
const uint16_t ptrs_bit_map,
const uint8_t nb_antennas_rx);
/**\fn void multipath_channel(channel_desc_t *desc,
double tx_sig_re[NB_ANTENNAS_TX],
double tx_sig_im[NB_ANTENANS_TX],
@@ -570,16 +554,38 @@ double N_RB2sampling_rate(uint16_t N_RB);
double N_RB2channel_bandwidth(uint16_t N_RB);
/* Linear phase noise model */
/*!
/**
\brief This function produce phase noise and add to input signal
\param ts Sampling time
\param ts Sampling time
\param *Re *Im Real and Imag part of the signal
*/
//look-up table for the sine (cosine) function
#define ResolSinCos 100
void InitSinLUT( void );
void phase_noise(double ts, int16_t * InRe, int16_t * InIm);
void phase_noise(double ts, int16_t *InRe, int16_t *InIm);
/**
\brief Add AWGN noise and phase noise if enabled
\param rxdata output data with noise
\param r_re real part of input data without noise
\param r_im imaginary part of input data without noise
\param sigma noise power
\param length number of samples to apply the noise
\param slot_offset slot offset to start applying the noise
\param ts sampling time
\param delay introduce delay in terms of number of samples
\param pdu_bit_map bitmap indicating presence of optional PDUs
\param ptrs_bit_map
\param nb_antennas_rx number of receive antennas
*/
void add_noise(c16_t **rxdata,
const double **r_re,
const double **r_im,
const double sigma,
const int length,
const int slot_offset,
const double ts,
const int delay,
const uint16_t pdu_bit_map,
const uint16_t ptrs_bit_map,
const uint8_t nb_antennas_rx);
void do_DL_sig(sim_t *sim,
uint16_t subframe,
+5 -4
View File
@@ -9,10 +9,11 @@ else()
message(FATAL_ERROR "unknown E1AP_RELEASE ${E1AP_RELEASE}")
endif()
add_custom_command(OUTPUT ${e1ap_source} ${e1ap_headers}
COMMAND ASN1C_PREFIX=E1AP_ ${ASN1C_EXEC} -gen-APER -gen-UPER -no-gen-JER -no-gen-BER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}
COMMENT "Generating E1AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}"
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}
"E1AP_"
OUTPUT ${e1ap_source} ${e1ap_headers}
OPTIONS -gen-APER -gen-UPER -no-gen-JER -no-gen-BER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps
COMMENT "E1AP source files"
)
add_library(asn1_e1ap ${e1ap_source})
+5 -4
View File
@@ -8,10 +8,11 @@ else()
message(FATAL_ERROR "unknown F1AP_RELEASE ${F1AP_RELEASE}")
endif()
add_custom_command(OUTPUT ${f1ap_source} ${f1ap_headers}
COMMAND ASN1C_PREFIX=F1AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}
COMMENT "Generating F1AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}"
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}
"F1AP_"
OUTPUT ${f1ap_source} ${f1ap_headers}
OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps
COMMENT "F1AP source files"
)
add_library(asn1_f1ap ${f1ap_source})
+10 -8
View File
@@ -653,11 +653,9 @@ static void encode_cells_to_activate(const served_cells_to_activate_t *cell, F1A
&cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation;
const f1ap_sib_msg_t *SI_msg = &cell->SI_msg[n];
if (SI_msg->SI_container != NULL) {
if (SI_msg->SI_type > 6 && SI_msg->SI_type != 9) {
asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item);
sib_item->sIBtype = SI_msg->SI_type;
OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length);
}
asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item);
sib_item->sIBtype = SI_msg->SI_type;
OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length);
}
}
}
@@ -1221,7 +1219,7 @@ f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg)
const f1ap_sib_msg_t *b_SI_msg = &msg_cell->SI_msg[j];
cp_SI_msg->SI_container_length = b_SI_msg->SI_container_length;
cp_SI_msg->SI_container = malloc_or_fail(cp_SI_msg->SI_container_length);
*cp_SI_msg->SI_container = *b_SI_msg->SI_container;
memcpy(cp_SI_msg->SI_container, b_SI_msg->SI_container, b_SI_msg->SI_container_length);
cp_SI_msg->SI_type = b_SI_msg->SI_type;
}
}
@@ -2109,8 +2107,12 @@ f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_a
for (int i = 0; i < cp.num_cells_to_activate; i++) {
cp.cells_to_activate[i] = msg->cells_to_activate[i];
for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) {
cp.cells_to_activate[i].SI_msg[s].SI_container = calloc_or_fail(1, sizeof(*cp.cells_to_activate[i].SI_msg[s].SI_container));
*cp.cells_to_activate[i].SI_msg[s].SI_container = *msg->cells_to_activate[i].SI_msg[s].SI_container;
f1ap_sib_msg_t *cp_sib = &cp.cells_to_activate[i].SI_msg[s];
const f1ap_sib_msg_t *msg_sib = &msg->cells_to_activate[i].SI_msg[s];
cp_sib->SI_type = msg_sib->SI_type;
cp_sib->SI_container_length = msg_sib->SI_container_length;
cp_sib->SI_container = calloc_or_fail(cp_sib->SI_container_length, sizeof(*cp_sib->SI_container));
memcpy(cp_sib->SI_container, msg_sib->SI_container, cp_sib->SI_container_length);
}
}
return cp;
+28 -23
View File
@@ -63,14 +63,15 @@
#define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres"
#define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper"
#define CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER "dl_bler_target_lower"
#define CONFIG_STRING_MACRLC_DL_MIN_MCS "dl_min_mcs"
#define CONFIG_STRING_MACRLC_DL_MAX_MCS "dl_max_mcs"
#define CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER "ul_bler_target_upper"
#define CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER "ul_bler_target_lower"
#define CONFIG_STRING_MACRLC_UL_MIN_MCS "ul_min_mcs"
#define CONFIG_STRING_MACRLC_UL_MAX_MCS "ul_max_mcs"
#define CONFIG_STRING_MACRLC_DL_HARQ_ROUND_MAX "dl_harq_round_max"
#define CONFIG_STRING_MACRLC_UL_HARQ_ROUND_MAX "ul_harq_round_max"
#define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb"
#define CONFIG_STRING_MACRLC_MIN_GRANT_MCS "min_grant_mcs"
#define CONFIG_STRING_MACRLC_IDENTITY_PM "identity_precoding_matrix"
#define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming"
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
@@ -81,14 +82,15 @@
#define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not"
#define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS"
#define HLP_MACRLC_DL_BLER_LO "Lower threshold of BLER to increase DL MCS"
#define HLP_MACRLC_DL_MIN_MCS "Minimum DL MCS that should be used"
#define HLP_MACRLC_DL_MAX_MCS "Maximum DL MCS that should be used"
#define HLP_MACRLC_UL_BLER_UP "Upper threshold of BLER to decrease UL MCS"
#define HLP_MACRLC_UL_BLER_LO "Lower threshold of BLER to increase UL MCS"
#define HLP_MACRLC_UL_MIN_MCS "Minimum UL MCS that should be used"
#define HLP_MACRLC_UL_MAX_MCS "Maximum UL MCS that should be used"
#define HLP_MACRLC_DL_HARQ_MAX "Maximum number of DL HARQ rounds"
#define HLP_MACRLC_UL_HARQ_MAX "Maximum number of UL HARQ rounds"
#define HLP_MACRLC_MIN_GRANT_PRB "Minimal Periodic ULSCH Grant PRBs"
#define HLP_MACRLC_MIN_GRANT_MCS "Minimal Periodic ULSCH Grant MCS"
#define HLP_MACRLC_IDENTITY_PM "Flag to use only identity matrix in DL precoding"
#define HLP_MACRLC_AB "Flag to enable analog beamforming"
#define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams"
@@ -125,14 +127,15 @@
{CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, .iptr=NULL, .defintval=10, TYPE_INT, 0}, \
{CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, HLP_MACRLC_DL_BLER_UP, 0, .dblptr=NULL, .defdblval=0.15, TYPE_DOUBLE, 0}, \
{CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER, HLP_MACRLC_DL_BLER_LO, 0, .dblptr=NULL, .defdblval=0.05, TYPE_DOUBLE, 0}, \
{CONFIG_STRING_MACRLC_DL_MIN_MCS, HLP_MACRLC_DL_MIN_MCS, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_DL_MAX_MCS, HLP_MACRLC_DL_MAX_MCS, 0, .u8ptr=NULL, .defintval=28, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER, HLP_MACRLC_UL_BLER_UP, 0, .dblptr=NULL, .defdblval=0.15, TYPE_DOUBLE, 0}, \
{CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER, HLP_MACRLC_UL_BLER_LO, 0, .dblptr=NULL, .defdblval=0.05, TYPE_DOUBLE, 0}, \
{CONFIG_STRING_MACRLC_UL_MIN_MCS, HLP_MACRLC_UL_MIN_MCS, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_UL_MAX_MCS, HLP_MACRLC_UL_MAX_MCS, 0, .u8ptr=NULL, .defintval=28, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_DL_HARQ_ROUND_MAX, HLP_MACRLC_DL_HARQ_MAX, 0, .u8ptr=NULL, .defintval=4, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_UL_HARQ_ROUND_MAX, HLP_MACRLC_UL_HARQ_MAX, 0, .u8ptr=NULL, .defintval=4, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_MIN_GRANT_PRB, HLP_MACRLC_MIN_GRANT_PRB, 0, .u8ptr=NULL, .defintval=5, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_MIN_GRANT_MCS, HLP_MACRLC_MIN_GRANT_MCS, 0, .u8ptr=NULL, .defintval=9, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_IDENTITY_PM, HLP_MACRLC_IDENTITY_PM, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
{CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
{CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \
@@ -170,23 +173,24 @@
#define MACRLC_PUSCHFAILURETHRES_IDX 20
#define MACRLC_DL_BLER_TARGET_UPPER_IDX 21
#define MACRLC_DL_BLER_TARGET_LOWER_IDX 22
#define MACRLC_DL_MAX_MCS_IDX 23
#define MACRLC_UL_BLER_TARGET_UPPER_IDX 24
#define MACRLC_UL_BLER_TARGET_LOWER_IDX 25
#define MACRLC_UL_MAX_MCS_IDX 26
#define MACRLC_DL_HARQ_ROUND_MAX_IDX 27
#define MACRLC_UL_HARQ_ROUND_MAX_IDX 28
#define MACRLC_MIN_GRANT_PRB_IDX 29
#define MACRLC_MIN_GRANT_MCS_IDX 30
#define MACRLC_IDENTITY_PM_IDX 31
#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 32
#define MACRLC_TRANSPORT_S_SHM_PREFIX 33
#define MACRLC_TRANSPORT_S_POLL_CORE 34
#define MACRLC_ANALOG_BEAMFORMING_IDX 35
#define MACRLC_ANALOG_BEAM_DURATION_IDX 36
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 37
#define MACRLC_PUSCH_RSSI_THRES_IDX 38
#define MACRLC_PUCCH_RSSI_THRES_IDX 39
#define MACRLC_DL_MIN_MCS_IDX 23
#define MACRLC_DL_MAX_MCS_IDX 24
#define MACRLC_UL_BLER_TARGET_UPPER_IDX 25
#define MACRLC_UL_BLER_TARGET_LOWER_IDX 26
#define MACRLC_UL_MIN_MCS_IDX 27
#define MACRLC_UL_MAX_MCS_IDX 28
#define MACRLC_DL_HARQ_ROUND_MAX_IDX 29
#define MACRLC_UL_HARQ_ROUND_MAX_IDX 30
#define MACRLC_MIN_GRANT_PRB_IDX 31
#define MACRLC_IDENTITY_PM_IDX 32
#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 33
#define MACRLC_TRANSPORT_S_SHM_PREFIX 34
#define MACRLC_TRANSPORT_S_POLL_CORE 35
#define MACRLC_ANALOG_BEAMFORMING_IDX 36
#define MACRLC_ANALOG_BEAM_DURATION_IDX 37
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 38
#define MACRLC_PUSCH_RSSI_THRES_IDX 39
#define MACRLC_PUCCH_RSSI_THRES_IDX 40
#define MACRLCPARAMS_CHECK { \
{ .s5 = { NULL } }, \
@@ -212,14 +216,15 @@
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s2 = { config_check_intrange, {0, 31} } }, /* DL min MCS */ \
{ .s2 = { config_check_intrange, {0, 31} } }, /* DL max MCS */ \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s2 = { config_check_intrange, {0, 31} } }, /* UL min MCS */ \
{ .s2 = { config_check_intrange, {0, 31} } }, /* UL max MCS */ \
{ .s2 = { config_check_intrange, {1, 8} } }, /* DL max HARQ rounds */ \
{ .s2 = { config_check_intrange, {1, 8} } }, /* UL max HARQ rounds */ \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s2 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
+74 -11
View File
@@ -1141,7 +1141,7 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf
css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1;
} else {
css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2;
css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
}
css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
@@ -1312,7 +1312,7 @@ static f1ap_fdd_info_t read_fdd_config(const NR_ServingCellConfigCommon_t *scc)
return fdd;
}
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1)
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1, seq_arr_t *du_SIBs)
{
int buf_len = 3;
f1ap_gnb_du_system_info_t *sys_info = calloc_or_fail(1, sizeof(*sys_info));
@@ -1329,15 +1329,24 @@ f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCC
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
if (du_SIBs) {
for (int i = 0; i < du_SIBs->size; i++) {
nr_SIBs_t *si = (nr_SIBs_t *)seq_arr_at(du_SIBs, i);
// other SIB in gNB-DU System Information not implemented yet
// only DU SIB not included in this message is SIB19
AssertFatal(si->SIB_type == 19, "Cannot handle SIB%d in gNB-DU System Information\n", si->SIB_type);
}
}
return sys_info;
}
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
const char *name,
const f1ap_served_cell_info_t *info,
const NR_ServingCellConfigCommon_t *scc,
NR_BCCH_BCH_Message_t *mib,
const NR_BCCH_DL_SCH_Message_t *sib1)
const NR_BCCH_DL_SCH_Message_t *sib1,
seq_arr_t *du_SIBs)
{
f1ap_setup_req_t *req = calloc(1, sizeof(*req));
AssertFatal(req != NULL, "out of memory\n");
@@ -1381,7 +1390,7 @@ f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
if (IS_SA_MODE(get_softmodem_params())) {
// in NSA we don't transmit SIB1, so cannot fill DU system information
// so cannot send MIB either
req->cell[0].sys_info = get_sys_info(mib, sib1);
req->cell[0].sys_info = get_sys_info(mib, sib1, du_SIBs);
}
int num = read_version(TO_STRING(NR_RRC_VERSION), &req->rrc_ver[0], &req->rrc_ver[1], &req->rrc_ver[2]);
@@ -1421,6 +1430,31 @@ static nr_redcap_config_t *get_redcap_config(int gnb_idx)
return rc;
}
static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray)
{
if (NODE_IS_DU(get_node_type()))
AssertFatal(GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0, "This is DU, do not input CU SIBs\n");
if (!config_isparamset(GNBparamarray, GNB_DU_SIBS_IDX))
return NULL;
seq_arr_t *du_SIBs = malloc(sizeof(seq_arr_t));
seq_arr_init(du_SIBs, sizeof(nr_SIBs_t));
for (int i = 0; i < GNBparamarray[GNB_DU_SIBS_IDX].numelt; i++) {
int sib_value = GNBparamarray[GNB_DU_SIBS_IDX].iptr[i];
// SIB10, SIB12, SIB13, SIB14, SIB15, SIB17, SIB18, SIB19 and SIB20 are generated by the DU
// all the rest in the DU
AssertFatal((sib_value > 9 && sib_value < 21) && sib_value != 11 && sib_value != 16,
"SIB%d is not a DU SIB, to be configured in DU section\n",
sib_value);
nr_SIBs_t *du_sib = calloc_or_fail(1, sizeof(nr_SIBs_t));
du_sib->SIB_type = sib_value;
LOG_I(GNB_APP, "activate SIB%d at DU\n", sib_value);
seq_arr_push_back(du_SIBs, du_sib, sizeof(nr_SIBs_t));
}
return du_SIBs;
}
void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
{
int j = 0;
@@ -1650,6 +1684,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler;
dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr);
dl_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr);
dl_bler_options->min_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MIN_MCS_IDX].u8ptr);
dl_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr);
if (config.disable_harq)
dl_bler_options->harq_round_max = 1;
@@ -1658,13 +1693,13 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
NR_bler_options_t *ul_bler_options = &RC.nrmac[j]->ul_bler;
ul_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_UPPER_IDX].dblptr);
ul_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_LOWER_IDX].dblptr);
ul_bler_options->min_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MIN_MCS_IDX].u8ptr);
ul_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MAX_MCS_IDX].u8ptr);
if (config.disable_harq)
ul_bler_options->harq_round_max = 1;
else
ul_bler_options->harq_round_max = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_HARQ_ROUND_MAX_IDX].u8ptr);
RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr);
RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr);
RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr);
// PRB Blacklist
uint16_t prbbl[MAX_BWP_SIZE] = {0};
@@ -1692,17 +1727,18 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
f1ap_served_cell_info_t info;
read_du_cell_info(cfg, NODE_IS_DU(node_type), &gnb_id, &gnb_du_id, &name, &info, 1);
if (IS_SA_MODE(get_softmodem_params())) {
NR_COMMON_channels_t *cc = &RC.nrmac[0]->common_channels[0];
cc->du_SIBs = fill_du_sibs(GNBParamList.paramarray[0]);
if (IS_SA_MODE(get_softmodem_params()))
nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac);
if (scc->ext2 && scc->ext2->ntn_Config_r17)
nr_mac_configure_sib19(RC.nrmac[0]);
}
// read F1 Setup information from config and generated MIB/SIB1
// and store it at MAC for sending later
NR_BCCH_BCH_Message_t *mib = RC.nrmac[0]->common_channels[0].mib;
const NR_BCCH_DL_SCH_Message_t *sib1 = RC.nrmac[0]->common_channels[0].sib1;
f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1);
seq_arr_t *du_SIBs = RC.nrmac[0]->common_channels[0].du_SIBs;
f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1, du_SIBs);
AssertFatal(req != NULL, "could not read F1 Setup information\n");
RC.nrmac[0]->f1_config.setup_req = req;
RC.nrmac[0]->f1_config.gnb_id = gnb_id;
@@ -1846,6 +1882,31 @@ static int sort_neighbour_cell_config_by_cell_id(const void *a, const void *b)
return 0;
}
static seq_arr_t *fill_cu_sibs(paramdef_t *GNBparamarray)
{
if (NODE_IS_CU(get_node_type()))
AssertFatal(GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0, "This is CU, do not input DU SIBs\n");
if (!config_isparamset(GNBparamarray, GNB_CU_SIBS_IDX))
return NULL;
seq_arr_t *SIBs = malloc(sizeof(seq_arr_t));
seq_arr_init(SIBs, sizeof(nr_SIBs_t));
for (int i = 0; i < GNBparamarray[GNB_CU_SIBS_IDX].numelt; i++) {
int sib_value = GNBparamarray[GNB_CU_SIBS_IDX].iptr[i];
// SIB10, SIB12, SIB13, SIB14, SIB15, SIB17, SIB18, SIB19 and SIB20 are generated by the DU
// all the rest in the CU
AssertFatal((sib_value > 1 && sib_value < 10) || sib_value == 11 || sib_value == 16,
"SIB%d is not a CU SIB, to be configured in DU section\n",
sib_value);
nr_SIBs_t *cu_sib = calloc_or_fail(1, sizeof(*cu_sib));
cu_sib->SIB_type = sib_value;
LOG_I(GNB_APP, "activate SIB%d at CU\n", sib_value);
seq_arr_push_back(SIBs, cu_sib, sizeof(nr_SIBs_t));
}
return SIBs;
}
static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
{
char gnbpath[MAX_OPTNAME_SIZE + 8];
@@ -2085,6 +2146,8 @@ gNB_RRC_INST *RCconfig_NRRRC()
fill_measurement_configuration(k, rrc);
rrc->SIBs = fill_cu_sibs(GNBParamList.paramarray[i]);
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
+1 -7
View File
@@ -95,14 +95,8 @@ gNB_RRC_INST *RCconfig_NRRRC();
int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
void wait_f1_setup_response(void);
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
const char *name,
const f1ap_served_cell_info_t *info,
const NR_ServingCellConfigCommon_t *scc,
NR_BCCH_BCH_Message_t *mib,
const NR_BCCH_DL_SCH_Message_t *sib1);
f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc);
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1);
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1, seq_arr_t *du_SIBs);
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update);
MessageDef *RCconfig_NR_CU_E1(const E1_t *entity);
ngran_node_t get_node_type(void);
+10
View File
@@ -139,6 +139,8 @@ typedef enum {
#define GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES "num_ulharq"
#define GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST "beam_weights"
#define GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST "uess_agg_levels"
#define GNB_CONFIG_STRING_CU_SIB_LIST "cu_sibs"
#define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs"
#define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n"
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
@@ -150,6 +152,8 @@ typedef enum {
#define GNB_CONFIG_HLP_NUM_DL_HARQ "Set Num DL harq processes. Valid values 2,4,6,8,10,12,16,32. Default 16"
#define GNB_CONFIG_HLP_NUM_UL_HARQ "Set Num UL harq processes. Valid values 16,32. Default 16"
#define GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST "List of aggregation levels with number of candidates per level. Element 0 - aggregation level 1"
#define GNB_CONFIG_HLP_CU_SIBS "List of CU generated SIBs to be transmitted"
#define GNB_CONFIG_HLP_DU_SIBS "List of DU generated SIBs to be transmitted"
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* cell configuration parameters */
@@ -195,6 +199,8 @@ typedef enum {
{GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
{GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST, \
GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST, 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \
{GNB_CONFIG_STRING_CU_SIB_LIST, GNB_CONFIG_HLP_CU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
{GNB_CONFIG_STRING_DU_SIB_LIST, GNB_CONFIG_HLP_DU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
}
// clang-format on
@@ -236,6 +242,8 @@ typedef enum {
#define GNB_NUM_UL_HARQ_IDX 34
#define GNB_BEAMWEIGHTS_IDX 35
#define GNB_UESS_AGG_LEVEL_LIST_IDX 36
#define GNB_CU_SIBS_IDX 37
#define GNB_DU_SIBS_IDX 38
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32}
@@ -279,6 +287,8 @@ typedef enum {
{ .s1 = { config_check_intval, NUM_UL_HARQ_OKVALUES,2 } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -1505,6 +1505,74 @@ void find_aggregation_candidates(uint8_t *aggregation_level,
}
}
void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset)
{
switch(ss->monitoringSlotPeriodicityAndOffset->present) {
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
*period = 1;
*offset = 0;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
*period = 2;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
*period = 4;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
*period = 5;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
*period = 8;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
*period = 10;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
*period = 16;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
*period = 20;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
*period = 40;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
*period = 80;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
*period = 160;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
*period = 320;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
*period = 640;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
*period = 1280;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
*period = 2560;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
break;
default:
AssertFatal(1==0,"Invalid monitoring slot periodicity value\n");
break;
}
}
void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss,
uint16_t period,
@@ -213,6 +213,7 @@ uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx);
uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx);
uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset);
void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset);
uint32_t nr_compute_tbslbrm(uint16_t table,
uint16_t nb_rb,
+3 -6
View File
@@ -936,10 +936,7 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source)
target->intraFreqReselection = source->intraFreqReselection;
}
void nr_rrc_mac_config_req_mib(module_id_t module_id,
int cc_idP,
NR_MIB_t *mib,
int sched_sib)
void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
int ret = pthread_mutex_lock(&mac->if_mutex);
@@ -952,8 +949,8 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id,
mac->phy_config.CC_id = cc_idP;
if (sched_sib == 1)
mac->get_sib1 = true;
else if (sched_sib == 2)
mac->get_otherSI = true;
else if (sched_sib > 1)
mac->get_otherSI[sched_sib - 2] = true;
nr_ue_decode_mib(mac, cc_idP);
ret = pthread_mutex_unlock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret);
+1 -1
View File
@@ -539,7 +539,7 @@ typedef struct NR_UE_MAC_INST_s {
int servCellIndex;
long physCellId;
bool get_sib1;
bool get_otherSI;
bool get_otherSI[MAX_SI_GROUPS];
NR_MIB_t *mib;
si_schedInfo_t si_SchedInfo;
+6 -6
View File
@@ -68,12 +68,12 @@ void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch);
\param sibs_mask sibs mask
\param pduP pointer to pdu
\param pdu_length length of pdu */
int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
int cc_id,
unsigned int gNB_index,
uint8_t ack_nack,
uint8_t *pduP,
uint32_t pdu_len);
void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
int cc_id,
unsigned int gNB_index,
uint8_t ack_nack,
uint8_t *pduP,
uint32_t pdu_len);
void release_dl_BWP(NR_UE_MAC_INST_t *mac, int index);
void release_ul_BWP(NR_UE_MAC_INST_t *mac, int index);
+2 -1
View File
@@ -56,7 +56,8 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id);
nr_ue_reset_sync_state(mac);
mac->get_sib1 = false;
mac->get_otherSI = false;
for (int i = 0; i < MAX_SI_GROUPS; i++)
mac->get_otherSI[i] = false;
memset(&mac->phy_config, 0, sizeof(mac->phy_config));
mac->si_SchedInfo.si_window_start = -1;
mac->servCellIndex = 0;
@@ -343,76 +343,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac,
dl_config->number_pdus += 1;
}
void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset)
{
switch(ss->monitoringSlotPeriodicityAndOffset->present) {
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
*period = 1;
*offset = 0;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
*period = 2;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
*period = 4;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
*period = 5;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
*period = 8;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
*period = 10;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
*period = 16;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
*period = 20;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
*period = 40;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
*period = 80;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
*period = 160;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
*period = 320;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
*period = 640;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
*period = 1280;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
*period = 2560;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
break;
default:
AssertFatal(1==0,"Invalid monitoring slot periodicity value\n");
break;
}
}
bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss)
{
if (!ss)
@@ -445,7 +375,6 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac,
if (((frame * slots_per_frame + slot - offset - i) % period) == 0) {
int N = mac->ssb_list.nb_tx_ssb;
int K = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb];
// numbering current frame and slot in terms of monitoring occasions in window
int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start;
int current_monitor_occasion = (rel_slot % period) + (duration * rel_slot / period);
@@ -469,44 +398,41 @@ bool is_window_valid(NR_UE_MAC_INST_t *mac, int window_slots, int abs_slot)
return true;
}
bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
const NR_SearchSpace_t *ss,
const int slots_per_frame,
const int frame,
const int slot)
static bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
const NR_SearchSpace_t *ss,
const int si_idx,
const int slots_per_frame,
const int frame,
const int slot)
{
// according to 5.2.2.3.2 in 331
const int abs_slot = frame * slots_per_frame + slot;
for (int i = 0; i < mac->si_SchedInfo.si_SchedInfo_list.count; i++) {
si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[i];
int window_slots = 5 << mac->si_SchedInfo.si_WindowLength;
int x = (config->si_WindowPosition - 1) * window_slots;
int T = 8 << config->si_Periodicity; // radio frame periodicity
bool check_valid;
switch (config->type) {
case NR_SI_INFO :
if (mac->si_SchedInfo.si_window_start == -1) {
if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0))
mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number
}
check_valid = is_window_valid(mac, window_slots, abs_slot);
if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame))
return true;
break;
case NR_SI_INFO_v1700 :
if (mac->si_SchedInfo.si_window_start == -1) {
if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame))
mac->si_SchedInfo.si_window_start = abs_slot;
}
window_slots = 10; // TODO window length hardcoded to 10 at gNB for NTN
check_valid = is_window_valid(mac, window_slots, abs_slot);
if (check_valid && (config->si_WindowPosition - 1) == slot)
return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame);
break;
default :
AssertFatal(false, "Invalid SI-SchedulingInfo case\n");
}
si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[si_idx];
int window_slots = 5 << mac->si_SchedInfo.si_WindowLength;
int x = (config->si_WindowPosition - 1) * window_slots;
int T = 8 << config->si_Periodicity; // radio frame periodicity
bool check_valid;
switch (config->type) {
case NR_SI_INFO :
if (mac->si_SchedInfo.si_window_start == -1) {
if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0))
mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number
}
check_valid = is_window_valid(mac, window_slots, abs_slot);
if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame))
return true;
break;
case NR_SI_INFO_v1700 :
if (mac->si_SchedInfo.si_window_start == -1) {
if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame))
mac->si_SchedInfo.si_window_start = abs_slot;
}
if (is_window_valid(mac, window_slots, abs_slot))
return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame);
break;
default :
AssertFatal(false, "Invalid SI-SchedulingInfo case\n");
}
return false;
}
@@ -549,13 +475,15 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, mac->search_space_zero);
}
}
if (mac->get_otherSI) {
for (int i = 0; i < MAX_SI_GROUPS; i++) {
if (!mac->get_otherSI[i])
continue;
// If searchSpaceOtherSystemInformation is set to zero,
// PDCCH monitoring occasions for SI message reception in SI-window
// are same as PDCCH monitoring occasions for SIB1
const NR_SearchSpace_t *ss = pdcch_config->otherSI_SS ? pdcch_config->otherSI_SS : mac->search_space_zero;
// TODO configure SI-window
if (monitor_dci_for_other_SI(mac, ss, slots_per_frame, frame, slot)) {
if (monitor_dci_for_other_SI(mac, ss, i, slots_per_frame, frame, slot)) {
LOG_D(NR_MAC_DCI, "Monitoring DCI for other SIs in frame %d slot %d\n", frame, slot);
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss);
}
+24 -13
View File
@@ -300,18 +300,22 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc
}
}
int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
int cc_id,
unsigned int gNB_index,
uint8_t ack_nack,
uint8_t *pduP,
uint32_t pdu_len)
void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
int cc_id,
unsigned int gNB_index,
uint8_t ack_nack,
uint8_t *pduP,
uint32_t pdu_len)
{
if(ack_nack) {
LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
mac->get_sib1 = false;
mac->get_otherSI = false;
if (mac->get_sib1)
mac->get_sib1 = false;
for (int i = 0; i < MAX_SI_GROUPS; i++) {
if (mac->get_otherSI[i])
mac->get_otherSI[i] = false;
}
T(T_NRUE_MAC_DL_PDU_WITH_DATA,
T_INT(SI_RNTI),
T_INT(-1 /* frame, unavailable here */),
@@ -319,9 +323,10 @@ int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
T_INT(0 /* harq_pid */),
T_BUFFER(pduP, pdu_len));
}
else
else {
LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI");
return 0;
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0);
}
}
/*
@@ -742,8 +747,10 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
return -1;
}
dlsch_pdu->rb_offset = dlsch_pdu->start_rb + dlsch_pdu->BWPStart;
if (mac->get_sib1 || mac->get_otherSI)
if (mac->get_sib1)
dlsch_pdu->rb_offset -= dlsch_pdu->BWPStart;
/* TIME_DOM_RESOURCE_ASSIGNMENT */
@@ -2993,7 +3000,7 @@ static void extract_10_ra_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc
EXTRACT_DCI_ITEM(dci_pdu_rel15->tb_scaling, 2);
}
static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB)
static uint8_t extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB)
{
LOG_D(NR_MAC_DCI, "Received dci 1_0 SI rnti\n");
@@ -3009,6 +3016,7 @@ static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc
EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2);
// System information indicator 1 bit
EXTRACT_DCI_ITEM(dci_pdu_rel15->system_info_indicator, 1);
return dci_pdu_rel15->system_info_indicator;
}
static bool extract_10_c_rnti(NR_UE_MAC_INST_t *mac,
@@ -3312,7 +3320,10 @@ static nr_dci_format_t nr_extract_dci_00_10(NR_UE_MAC_INST_t *mac,
n_RB = get_nrb_for_dci(mac, format, ss_type);
if (n_RB == 0)
return NR_DCI_NONE;
extract_10_si_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB);
uint8_t sys_info = extract_10_si_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB);
// sys info = 0 for SIB1 and 1 for other SIB
if (mac->get_sib1 == 0 && sys_info == 0)
return NR_DCI_NONE;
break;
case TYPE_C_RNTI_ :
// Identifier for DCI formats
+84 -26
View File
@@ -38,6 +38,7 @@
#include "BIT_STRING.h"
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "GNB_APP/gnb_config.h"
#include "NR_MIB.h"
#include "NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_BCCH-BCH-Message.h"
@@ -863,30 +864,98 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
NR_RA_t *ra = &cc->ra[n];
nr_clear_ra_proc(ra);
}
nr_fill_sched_osi(nrmac, scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
if (IS_SA_MODE(get_softmodem_params()))
config_sched_ctrlCommon(nrmac);
}
void nr_fill_sched_osi(gNB_MAC_INST *nrmac, const struct NR_SetupRelease_PDCCH_ConfigCommon *pdcch_ConfigCommon)
bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib])
{
NR_SearchSpaceId_t *osi_SearchSpace = pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation;
if (osi_SearchSpace) {
nrmac->sched_osi = CALLOC(1, sizeof(*nrmac->sched_osi));
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
seq_arr_t *du_SIBs = nrmac->common_channels[0].du_SIBs;
int num_du_sib = 0;
if (du_SIBs)
num_du_sib = du_SIBs->size;
if (num_cu_sib + num_du_sib == 0)
return false; /* no updates */
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList =
pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n");
for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
NR_SearchSpace_t *ss = commonSearchSpaceList->list.array[i];
if (ss->searchSpaceId == *osi_SearchSpace)
nrmac->sched_osi->search_space = ss;
int config_sibs[num_cu_sib + num_du_sib];
NR_SystemInformation_IEs_t *sysInfo = calloc(1, sizeof(*sysInfo)); //for SIB up to 14 included
NR_SystemInformation_IEs_t *sysInfov17 = calloc(1, sizeof(*sysInfov17)); // for othersibs
for (int i = 0; i < num_cu_sib; i++) {
config_sibs[i] = cu_sib[i].SI_type;
switch (config_sibs[i]) {
case 2: {
struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type = calloc(1, sizeof(*type));
type->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2;
// SIB2 coming from CU need to decode it
NR_SIB2_t *sib2 = NULL;
asn_dec_rval_t dec_rval = uper_decode(NULL,
&asn_DEF_NR_SIB2,
(void **)&sib2,
cu_sib[i].SI_container,
cu_sib[i].SI_container_length,
0,
0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_MAC, "cannot decode SIB%d from CU\n", config_sibs[i]);
ASN_STRUCT_FREE(asn_DEF_NR_SIB2, cu_sib[i].SI_container);
}
type->choice.sib2 = sib2;
add_sib_to_systeminformation(sysInfo, type);
break;
}
default :
AssertFatal(false, "Invalid or not supported SIB%d\n", config_sibs[i]);
}
AssertFatal(nrmac->sched_osi->search_space != NULL, "SearchSpace cannot be null for OSI\n");
}
for (int i = 0; i < num_du_sib; i++) {
nr_SIBs_t *si = (nr_SIBs_t *)seq_arr_at(du_SIBs, i);
int sib_idx = i + num_cu_sib;
config_sibs[sib_idx] = si->SIB_type;
switch (config_sibs[sib_idx]) {
case 19: {
struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type_du = calloc(1, sizeof(*type_du));
type_du->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700;
NR_SIB19_r17_t *sib19 = get_SIB19_NR(cc->ServingCellConfigCommon);
type_du->choice.sib19_v1700 = sib19;
add_sib_to_systeminformation(sysInfov17, type_du);
break;
}
default :
AssertFatal(false, "Invalid or not supported SIB%d\n", sib_idx);
}
}
update_SIB1_NR_SI(cc->sib1, num_cu_sib + num_du_sib, config_sibs);
cc->sib1_bcch_length = encode_SIB_NR(cc->sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu));
AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n");
// generate otherSIB payloads
cc->other_sib_bcch_length[0] = encode_sysinfo_ie(sysInfo, cc->other_sib_bcch_pdu[0], sizeof(cc->other_sib_bcch_pdu[0]));
cc->other_sib_bcch_length[1] = encode_sysinfo_ie(sysInfov17, cc->other_sib_bcch_pdu[1], sizeof(cc->other_sib_bcch_pdu[1]));
ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfo);
ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfov17);
return true;
}
void prepare_du_configuration_update(gNB_MAC_INST *mac,
f1ap_served_cell_info_t *info,
NR_BCCH_BCH_Message_t *mib,
const NR_BCCH_DL_SCH_Message_t *sib1)
{
/* send gNB-DU configuration update to RRC */
f1ap_gnb_du_configuration_update_t update = {
.transaction_id = 1,
.num_cells_to_modify = 1,
};
update.cell_to_modify[0].old_nr_cellid = info->nr_cellid;
update.cell_to_modify[0].info = *info;
update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1, NULL);
mac->mac_rrc.gnb_du_configuration_update(&update);
}
void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_t cellID, int tac)
@@ -897,21 +966,10 @@ void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, plmn, cellID, tac, &nrmac->radio_config);
cc->sib1 = sib1;
cc->sib1_bcch_length = encode_SIB1_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu));
cc->sib1_bcch_length = encode_SIB_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu));
AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n");
}
void nr_mac_configure_sib19(gNB_MAC_INST *nrmac)
{
AssertFatal(IS_SA_MODE(get_softmodem_params()), "error: SIB19 only applicable for SA\n");
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_BCCH_DL_SCH_Message_t *sib19 = get_SIB19_NR(scc);
cc->sib19 = sib19;
cc->sib19_bcch_length = encode_SIB19_NR(sib19, cc->sib19_bcch_pdu, sizeof(cc->sib19_bcch_pdu));
AssertFatal(cc->sib19_bcch_length > 0, "could not encode SIB19\n");
}
bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup)
{
/* ideally, instead of this function, "users" of this function should call
+1 -2
View File
@@ -219,8 +219,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
// SIB19 will be scheduled if ntn_Config_r17 is initialized
if (IS_SA_MODE(get_softmodem_params())) {
schedule_nr_sib1(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req);
if (cc->sib19)
schedule_nr_sib19(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req, cc->sib19_bcch_length, cc->sib19_bcch_pdu);
schedule_nr_other_sib(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req);
}
// This schedule PRACH if we are not in phy_test mode
+4 -74
View File
@@ -878,7 +878,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
ul_dci_req->numPdus += 1;
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch, false);
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch);
nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15;
}
@@ -1250,81 +1250,11 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_
nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu);
}
static void find_monitoring_periodicity_offset_common(const NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset)
{
switch (ss->monitoringSlotPeriodicityAndOffset->present) {
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
*slot_period = 1;
*offset = 0;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
*slot_period = 2;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
*slot_period = 4;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
*slot_period = 5;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
*slot_period = 8;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
*slot_period = 10;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
*slot_period = 16;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
*slot_period = 20;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
*slot_period = 40;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
*slot_period = 80;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
*slot_period = 160;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
*slot_period = 320;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
*slot_period = 640;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
*slot_period = 1280;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
break;
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
*slot_period = 2560;
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
break;
default:
AssertFatal(1 == 0, "Invalid monitoring slot periodicity and offset value\n");
break;
}
}
static bool check_msg2_monitoring(const NR_RA_t *ra, int slots_per_frame, int current_frame, int current_slot)
{
// check if the slot is not among the PDCCH monitored ones (38.213 10.1)
uint16_t monitoring_slot_period, monitoring_offset;
find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset);
int monitoring_slot_period, monitoring_offset;
get_monitoring_period_offset(ra->ra_ss, &monitoring_slot_period, &monitoring_offset);
if ((current_frame * slots_per_frame + current_slot - monitoring_offset) % monitoring_slot_period != 0)
return false;
return true;
@@ -1432,7 +1362,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu));
dl_req->nPDUs += 1;
pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch, false);
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch);
nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15;
}
+298 -271
View File
@@ -274,76 +274,75 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
}
}
uint32_t get_tbs(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
NR_sched_pdsch_t *pdsch,
uint32_t num_total_bytes,
uint16_t *vrb_map)
static uint32_t get_tbs_bch(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
NR_sched_pdsch_t *pdsch,
uint32_t num_total_bytes,
uint16_t *vrb_map)
{
NR_tda_info_t *tda_info = &pdsch->tda_info;
const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs;
int rbStart = type0_PDCCH_CSS_config->cset_start_rb;
// Calculate number of PRB_DMRS
uint8_t N_PRB_DMRS = pdsch->dmrs_parms.N_PRB_DMRS;
uint16_t dmrs_length = pdsch->dmrs_parms.N_DMRS_SLOT;
LOG_D(MAC, "dlDmrsSymbPos %x\n", pdsch->dmrs_parms.dl_dmrs_symb_pos);
int mcsTableIdx = 0;
int rbSize = 0;
uint32_t TBS = 0;
do {
if (rbSize < bwpSize && !(vrb_map[rbStart + rbSize] & SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols)))
rbSize++;
const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
int bwpSize = type0_PDCCH_CSS_config->num_rbs;
int bwpStart = type0_PDCCH_CSS_config->cset_start_rb;
int rbStop = bwpSize - 1;
int rbStart = 0;
uint16_t rbSize = 0;
while (rbStart < rbStop) {
if (vrb_map[rbStart + bwpStart] & slbitmap)
rbStart++;
else {
if (pdsch->mcs < 10)
pdsch->mcs++;
else
break;
}
TBS = nr_compute_tbs(nr_get_Qm_dl(pdsch->mcs, mcsTableIdx),
nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx),
rbSize,
tda_info->nrOfSymbols,
N_PRB_DMRS * dmrs_length,
0,
0,
1)
>> 3;
} while (TBS < num_total_bytes);
int max_rbSize = 0;
while (rbStart + max_rbSize <= rbStop && !(vrb_map[rbStart + max_rbSize + bwpStart] & slbitmap))
max_rbSize++;
if (TBS < num_total_bytes) {
for (int rb = 0; rb < bwpSize; rb++)
LOG_I(NR_MAC, "vrb_map[%d] %x\n", rbStart + rb, vrb_map[rbStart + rb]);
bool res = false;
while (res == false && pdsch->mcs < 10) {
res = nr_find_nb_rb(nr_get_Qm_dl(pdsch->mcs, mcsTableIdx),
nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx),
1, // no transform precoding for DL
1, // single layer
tda_info->nrOfSymbols,
pdsch->dmrs_parms.N_PRB_DMRS * pdsch->dmrs_parms.N_DMRS_SLOT,
num_total_bytes,
1, // min_rbSize
max_rbSize,
&TBS,
&rbSize);
if (!res)
pdsch->mcs++;
}
break;
}
}
AssertFatal(
TBS >= num_total_bytes,
"Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d SLmask %x - [%d,%d])\n",
num_total_bytes,
rbStart,
rbSize,
bwpSize,
SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols),
tda_info->startSymbolIndex,
tda_info->nrOfSymbols);
AssertFatal(TBS >= num_total_bytes,
"Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d)\n",
num_total_bytes,
rbStart,
rbSize,
bwpSize);
pdsch->rbSize = rbSize;
pdsch->rbStart = 0;
pdsch->rbStart = rbStart;
LOG_D(
NR_MAC,
"mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n",
pdsch->mcs,
tda_info->startSymbolIndex,
tda_info->nrOfSymbols,
pdsch->rbSize,
TBS,
dmrs_length,
N_PRB_DMRS,
tda_info->mapping_type);
LOG_D(NR_MAC,
"mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n",
pdsch->mcs,
tda_info->startSymbolIndex,
tda_info->nrOfSymbols,
rbSize,
TBS,
pdsch->dmrs_parms.N_DMRS_SLOT,
N_PRB_DMRS,
tda_info->mapping_type);
return TBS;
}
static uint32_t schedule_control_sib1(module_id_t module_id,
static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac,
int CC_id,
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
int time_domain_allocation,
@@ -353,7 +352,6 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
int beam,
uint16_t num_total_bytes)
{
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n");
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
uint16_t *vrb_map = cc->vrb_map[beam];
@@ -382,7 +380,10 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n");
uint32_t TBS = get_tbs(type0_PDCCH_CSS_config, &gNB_mac->sched_ctrlCommon->sched_pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map);
uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config,
&gNB_mac->sched_ctrlCommon->sched_pdsch,
gNB_mac->sched_ctrlCommon->num_total_bytes,
vrb_map);
// Mark the corresponding RBs as used
fill_pdcch_vrb_map(gNB_mac,
@@ -397,92 +398,22 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
return TBS;
}
static uint32_t schedule_control_other_si(module_id_t module_id,
int CC_id,
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
int time_domain_allocation,
NR_pdsch_dmrs_t *dmrs_parms,
NR_tda_info_t *tda_info,
uint8_t candidate_idx,
int beam,
uint16_t num_total_bytes)
static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac,
NR_sched_pdsch_t *pdsch,
NR_sched_pdcch_t *pdcch,
NR_SearchSpace_t *search_space,
NR_ControlResourceSet_t *coreset,
int aggregation_level,
int cce_index,
nfapi_nr_dl_tti_request_body_t *dl_req,
int pdu_index,
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
uint32_t TBS,
int StartSymbolIndex,
int NrOfSymbols,
bool is_sib1,
int beam_index)
{
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
uint16_t *vrb_map = cc->vrb_map[beam];
if (!gNB_mac->sched_osi->coreset) {
gNB_mac->sched_osi->coreset =
get_coreset(gNB_mac, scc, NULL, gNB_mac->sched_osi->search_space, NR_SearchSpace__searchSpaceType_PR_common);
gNB_mac->sched_osi->sched_pdcch =
set_pdcch_structure(NULL, gNB_mac->sched_osi->search_space, gNB_mac->sched_osi->coreset, scc, NULL, type0_PDCCH_CSS_config);
}
NR_sched_pdsch_t *pdsch = &gNB_mac->sched_osi->sched_pdsch;
pdsch->time_domain_allocation = time_domain_allocation;
pdsch->dmrs_parms = *dmrs_parms;
pdsch->tda_info = *tda_info;
pdsch->mcs = 0; // starting from mcs 0
gNB_mac->sched_osi->num_total_bytes = num_total_bytes;
uint8_t nr_of_candidates;
for (int i = 0; i < 3; i++) {
find_aggregation_candidates(&gNB_mac->sched_osi->aggregation_level,
&nr_of_candidates,
gNB_mac->sched_ctrlCommon->search_space,
4 << i);
if (nr_of_candidates > 0)
break; // choosing the lower value of aggregation level available
}
AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n");
gNB_mac->sched_osi->cce_index = find_pdcch_candidate(gNB_mac,
CC_id,
gNB_mac->sched_osi->aggregation_level,
nr_of_candidates,
beam,
&gNB_mac->sched_osi->sched_pdcch,
gNB_mac->sched_osi->coreset,
0);
AssertFatal(gNB_mac->sched_osi->cce_index >= 0, "Could not find CCE for coreset0\n");
// Calculate number of PRB_DMRS
uint32_t TBS = get_tbs(type0_PDCCH_CSS_config, &gNB_mac->sched_osi->sched_pdsch, gNB_mac->sched_osi->num_total_bytes, vrb_map);
// Mark the corresponding RBs as used
fill_pdcch_vrb_map(gNB_mac,
CC_id,
&gNB_mac->sched_osi->sched_pdcch,
gNB_mac->sched_osi->cce_index,
gNB_mac->sched_osi->aggregation_level,
beam);
for (int rb = 0; rb < pdsch->rbSize; rb++) {
vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
}
return TBS;
}
static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
NR_UE_sched_osi_ctrl_t *sched_osi,
NR_UE_sched_ctrl_t *sched_ctrlCommon,
nfapi_nr_dl_tti_request_body_t *dl_req,
int pdu_index,
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
uint32_t TBS,
int StartSymbolIndex,
int NrOfSymbols,
int beam_index)
{
// will set data according to SIB type (SIB1/OtherSI)
NR_sched_pdsch_t *pdsch = (sched_ctrlCommon ? &sched_ctrlCommon->sched_pdsch : &sched_osi->sched_pdsch);
NR_sched_pdcch_t *pdcch = (sched_ctrlCommon ? &sched_ctrlCommon->sched_pdcch : &sched_osi->sched_pdcch);
NR_SearchSpace_t *search_space = (sched_ctrlCommon ? sched_ctrlCommon->search_space : sched_osi->search_space);
NR_ControlResourceSet_t *coreset = (sched_ctrlCommon ? sched_ctrlCommon->coreset : sched_osi->coreset);
uint8_t aggregation_level = (sched_ctrlCommon ? sched_ctrlCommon->aggregation_level : sched_osi->aggregation_level);
int cce_index = (sched_ctrlCommon ? sched_ctrlCommon->cce_index : sched_osi->cce_index);
gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP];
NR_COMMON_channels_t *cc = gNB_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
int mcsTableIdx = 0;
@@ -493,10 +424,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
dl_tti_pdcch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
dl_req->nPDUs += 1;
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
nr_configure_pdcch(pdcch_pdu_rel15,
coreset,
pdcch,
sched_ctrlCommon ? false : true);
nr_configure_pdcch(pdcch_pdu_rel15, coreset, pdcch);
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset(dl_tti_pdsch_pdu, 0, sizeof(*dl_tti_pdcch_pdu));
@@ -532,7 +460,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
pdsch_pdu_rel15->nrOfLayers = 1;
pdsch_pdu_rel15->transmissionScheme = 0;
pdsch_pdu_rel15->refPoint = 1;
pdsch_pdu_rel15->refPoint = is_sib1;
pdsch_pdu_rel15->dmrsConfigType = 0;
pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
pdsch_pdu_rel15->SCID = 0;
@@ -598,7 +526,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0;
dci_payload.antenna_ports.val = 0;
dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
dci_payload.system_info_indicator = sched_ctrlCommon ? 0 : 1;
dci_payload.system_info_indicator = is_sib1 ? 0 : 1;
int dci_format = NR_DL_DCI_FORMAT_1_0;
int rnti_type = TYPE_SI_RNTI_;
@@ -696,7 +624,8 @@ void schedule_nr_sib1(module_id_t module_idP,
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
// Configure sched_ctrlCommon for SIB1
uint32_t TBS = schedule_control_sib1(module_idP, CC_id,
uint32_t TBS = schedule_control_sib1(gNB_mac,
CC_id,
type0_PDCCH_CSS_config,
time_domain_allocation,
&dmrs_parms,
@@ -707,17 +636,21 @@ void schedule_nr_sib1(module_id_t module_idP,
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
int pdu_index = gNB_mac->pdu_index[0]++;
LOG_D(NR_MAC, "%s() %4d.%2d\n", __func__, frameP, slotP);
nr_fill_nfapi_dl_SIB_pdu(module_idP,
NULL,
gNB_mac->sched_ctrlCommon,
dl_req,
pdu_index,
type0_PDCCH_CSS_config,
TBS,
tda_info.startSymbolIndex,
tda_info.nrOfSymbols,
beam_index);
nr_fill_nfapi_dl_SIB_pdu(gNB_mac,
&gNB_mac->sched_ctrlCommon->sched_pdsch,
&gNB_mac->sched_ctrlCommon->sched_pdcch,
gNB_mac->sched_ctrlCommon->search_space,
gNB_mac->sched_ctrlCommon->coreset,
gNB_mac->sched_ctrlCommon->aggregation_level,
gNB_mac->sched_ctrlCommon->cce_index,
dl_req,
pdu_index,
type0_PDCCH_CSS_config,
TBS,
tda_info.startSymbolIndex,
tda_info.nrOfSymbols,
true,
beam_index);
const int ntx_req = TX_req->Number_of_PDUs;
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
@@ -762,133 +695,227 @@ struct NR_SchedulingInfo2_r17 *find_sib19_sched_info(const struct NR_SI_Scheduli
return NULL;
}
void schedule_nr_sib19(module_id_t module_idP,
frame_t frameP,
slot_t slotP,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req,
int sib19_bcch_length,
uint8_t *sib19_bcch_pdu)
static void other_sib_sched_control(module_id_t module_idP,
frame_t frame,
slot_t slot,
int beam_index,
NR_SearchSpace_t *ss,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req,
int payload_idx)
{
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
const int CC_id = 0;
uint8_t candidate_idx = 0;
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon;
int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate otherSIB corresponding for SSB number %d in any available beam\n", beam_index);
LOG_D(NR_MAC, "(%d.%d) otherSIB payload %d transmission for ssb number %d\n", frame, slot, payload_idx, beam_index);
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[cc->ssb_index[beam_index]];
AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n");
NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup;
int time_domain_allocation = 1;
NR_tda_info_t tda_info = set_tda_info_from_list(pdsch_ConfigCommon->pdsch_TimeDomainAllocationList, time_domain_allocation);
LOG_D(NR_MAC,"tda_info.startSymbolIndex: %d, tda_info.nrOfSymbols: %d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols);
// there is no reason to execute further if sched_osi not initialized
if (!gNB_mac->sched_osi)
return;
NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1);
// get sib19 scheduling info from sib1
struct NR_SI_SchedulingInfo_v1700 *si_schedulinginfo2_r17 = cc->sib1->message.choice.c1->choice.systemInformationBlockType1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->si_SchedulingInfo_v1700;
if (!si_schedulinginfo2_r17) {
LOG_E(GNB_APP, "SIB1 does not contain si_SchedulingInfo_v1700\n");
return;
uint8_t aggregation_level = 0;
uint8_t nr_of_candidates = 0;
for (int i = 0; i < 5; i++) {
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 16 >> i);
if (nr_of_candidates > 0)
break; // choosing the higher value of aggregation level available
}
struct NR_SchedulingInfo2_r17 *sib19_sched_info = find_sib19_sched_info(si_schedulinginfo2_r17);
if (!sib19_sched_info) {
LOG_D(GNB_APP, "SIB1 does not contain scheduling info for SIB19\n");
AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n");
NR_ControlResourceSet_t *coreset = get_coreset(gNB_mac, scc, NULL, ss, NR_SearchSpace__searchSpaceType_PR_common);
if (!gNB_mac->sched_pdcch_otherSI) {
gNB_mac->sched_pdcch_otherSI = calloc(1, sizeof(*gNB_mac->sched_pdcch_otherSI));
*gNB_mac->sched_pdcch_otherSI = set_pdcch_structure(gNB_mac, ss, coreset, scc, NULL, type0_PDCCH_CSS_config);
}
int cce_index = find_pdcch_candidate(gNB_mac,
0,
aggregation_level,
nr_of_candidates,
beam.idx,
gNB_mac->sched_pdcch_otherSI,
coreset,
0);
AssertFatal(cce_index >= 0, "Could not find CCE for otherSIB DCI\n");
// Mark the corresponding RBs as used
fill_pdcch_vrb_map(gNB_mac, 0, gNB_mac->sched_pdcch_otherSI, cce_index, aggregation_level, beam.idx);
NR_sched_pdsch_t sched_pdsch_otherSI = {0};
sched_pdsch_otherSI.time_domain_allocation = time_domain_allocation;
sched_pdsch_otherSI.dmrs_parms = dmrs_parms;
sched_pdsch_otherSI.tda_info = tda_info;
sched_pdsch_otherSI.mcs = 0; // starting from mcs 0
uint16_t *vrb_map = cc->vrb_map[beam.idx];
uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx];
int num_total_bytes = cc->other_sib_bcch_length[payload_idx];
uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config, &sched_pdsch_otherSI, num_total_bytes, vrb_map);
for (int rb = 0; rb < sched_pdsch_otherSI.rbSize; rb++) {
vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
}
int pdu_index = gNB_mac->pdu_index[0]++;
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
nr_fill_nfapi_dl_SIB_pdu(gNB_mac,
&sched_pdsch_otherSI,
gNB_mac->sched_pdcch_otherSI,
ss,
coreset,
aggregation_level,
cce_index,
dl_req,
pdu_index,
type0_PDCCH_CSS_config,
TBS,
tda_info.startSymbolIndex,
tda_info.nrOfSymbols,
false,
beam_index);
const int ntx_req = TX_req->Number_of_PDUs;
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
// Data to be transmitted
memcpy(tx_req->TLVs[0].value.direct, sib_bcch_pdu, TBS);
tx_req->PDU_length = TBS;
tx_req->PDU_index = pdu_index;
tx_req->num_TLV = 1;
tx_req->TLVs[0].length = TBS + 2;
TX_req->Number_of_PDUs++;
TX_req->SFN = frame;
TX_req->Slot = slot;
T(T_GNB_MAC_DL_PDU_WITH_DATA,
T_INT(module_idP),
T_INT(0),
T_INT(SI_RNTI),
T_INT(frame),
T_INT(slot),
T_INT(0), // harq_pid
T_BUFFER(sib_bcch_pdu, num_total_bytes));
}
// This function verifies if we need to schedule otherSIB in frame and slot
static bool test_other_sib_sched_occasion(int window_pos,
int window_len,
int period,
int n_slots_frame,
int frame,
int slot,
int rel_frame,
int rel_slot)
{
int x = window_pos * window_len;
int T = 8 << period;
int test_frame = (frame - rel_frame) % MAX_FRAME_NUMBER;
int si_slot = (x % n_slots_frame) + rel_slot;
bool res = ((test_frame % T) != (x / n_slots_frame)) || (si_slot != slot);
return res;
}
void schedule_nr_other_sib(module_id_t module_idP,
frame_t frame,
slot_t slot,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req)
{
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
NR_SIB1_t *sib1 = cc->sib1->message.choice.c1->choice.systemInformationBlockType1;
NR_SI_SchedulingInfo_t *schedInfo = sib1->si_SchedulingInfo;
if (!schedInfo)
return;
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon;
NR_PDCCH_ConfigCommon_t *pdcch_common = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
NR_SearchSpaceId_t *ss_id = pdcch_common->searchSpaceOtherSystemInformation;
AssertFatal(ss_id, "searchSpaceOtherSystemInformation not present\n");
NR_SearchSpace_t *ss = NULL;
for (int i = 0; i < pdcch_common->commonSearchSpaceList->list.count; i++) {
if (pdcch_common->commonSearchSpaceList->list.array[i]->searchSpaceId == *ss_id)
ss = pdcch_common->commonSearchSpaceList->list.array[i];
}
AssertFatal(ss, "searchSpaceOtherSystemInformation not found\n");
NR_SI_SchedulingInfo_v1700_t *schedInfo17 = NULL;
if (sib1->nonCriticalExtension) {
NR_SIB1_v1610_IEs_t *sib1_v1610 = sib1->nonCriticalExtension;
if (sib1_v1610 && sib1_v1610->nonCriticalExtension && sib1_v1610->nonCriticalExtension->nonCriticalExtension) {
NR_SIB1_v1700_IEs_t *sib1_v17 = sib1_v1610->nonCriticalExtension->nonCriticalExtension;
schedInfo17 = sib1_v17->si_SchedulingInfo_v1700;
}
}
// convert periodicity enum type into actual frames number
int frame = 8 << sib19_sched_info->si_Periodicity_r17;
int time_domain_allocation = 1; // row 0 of pdsch tda common table
int L_max;
switch (scc->ssb_PositionsInBurst->present) {
case 1:
L_max = 4;
break;
case 2:
L_max = 8;
break;
case 3:
L_max = 64;
break;
default:
AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
scc->ssb_PositionsInBurst->present);
int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
int window_length_sl = 5 << schedInfo->si_WindowLength;
int window_length_f = (window_length_sl / n_slots_frame) + ((window_length_sl % n_slots_frame) > 0);
int num_ssb = cc->num_active_ssb;
// number of PDCCH monitoring occasions in SI-window
int period, offset;
get_monitoring_period_offset(ss, &period, &offset);
// The UE assumes that, in the SI window, PDCCH for an SI message is transmitted
// in at least one PDCCH monitoring occasion corresponding to each transmitted SSB
// frame and slot relative to start of window
// The [x×N+K]th PDCCH monitoring occasion(s) for SI message in SI-window corresponds to the Kth transmitted SSB
// in our implmentation we transmit only once per SSB per window so N = 1
// Section 5.2.2.3.2 of 38.331
int temp_slot = offset % n_slots_frame;
int temp_frame = offset / n_slots_frame;
int rel_slot[num_ssb];
int rel_frame[num_ssb];
int ssb = 0;
while (ssb < num_ssb) {
AssertFatal(temp_frame < window_length_f, "Couldn't fit %d SSB in window length of %d slots\n", num_ssb, window_length_sl);
if (is_dl_slot(temp_slot, &gNB_mac->frame_structure)) {
rel_slot[ssb] = temp_slot;
rel_frame[ssb] = temp_frame;
ssb++;
}
temp_frame += (temp_slot + period) / n_slots_frame;
temp_slot = (temp_slot + period) % n_slots_frame;
}
const int window_length = 10;
for (int i = 0; i < L_max; i++) {
for (int ssb = 0; ssb < num_ssb; ssb++) {
for (int i = 0; i < schedInfo->schedulingInfoList.list.count; i++) {
NR_SchedulingInfo_t *schedulingInfo = schedInfo->schedulingInfoList.list.array[i];
if (test_other_sib_sched_occasion(i,
window_length_sl,
schedulingInfo->si_Periodicity,
n_slots_frame,
frame,
slot,
rel_frame[ssb],
rel_slot[ssb]))
continue;
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i];
if(((frameP - 1) % frame == 0) &&
(slotP == ((sib19_sched_info->si_WindowPosition_r17 % window_length) - 1)) &&
(type0_PDCCH_CSS_config->num_rbs > 0)) {
other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 0);
}
if (!schedInfo17)
continue;
for (int i = 0; i < schedInfo17->schedulingInfoList2_r17.list.count; i++) {
NR_SchedulingInfo2_r17_t *schedulingInfo2_r17 = schedInfo17->schedulingInfoList2_r17.list.array[i];
if (test_other_sib_sched_occasion(schedulingInfo2_r17->si_WindowPosition_r17,
window_length_sl,
schedulingInfo2_r17->si_Periodicity_r17,
n_slots_frame,
frame,
slot,
rel_frame[ssb],
rel_slot[ssb]))
continue;
const int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
int beam_index = get_fapi_beamforming_index(gNB_mac, i);
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SIB19 corresponding to SSB %d in any available beam\n", i);
LOG_D(NR_MAC,"(%d.%d) SIB19 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index);
NR_tda_info_t tda_info = set_tda_info_from_list(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList, time_domain_allocation);
LOG_D(NR_MAC,"tda_info.startSymbolIndex: %d, tda_info.nrOfSymbols: %d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols);
AssertFatal((tda_info.startSymbolIndex + tda_info.nrOfSymbols) < 14, "SIB19 TDA %d would cause overlap with CSI-RS. Please select a different SIB1 TDA.\n", time_domain_allocation);
NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc,
NULL,
&tda_info,
1);
// Configure sched_osi for SIB19
uint32_t TBS = schedule_control_other_si(module_idP,
CC_id,
type0_PDCCH_CSS_config,
time_domain_allocation,
&dmrs_parms,
&tda_info,
candidate_idx,
beam.idx,
sib19_bcch_length);
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
int pdu_index = gNB_mac->pdu_index[0]++;
nr_fill_nfapi_dl_SIB_pdu(module_idP,
gNB_mac->sched_osi,
NULL,
dl_req,
pdu_index,
type0_PDCCH_CSS_config,
TBS,
tda_info.startSymbolIndex,
tda_info.nrOfSymbols,
beam_index);
const int ntx_req = TX_req->Number_of_PDUs;
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
// Data to be transmitted
memcpy(tx_req->TLVs[0].value.direct, sib19_bcch_pdu, TBS);
tx_req->PDU_length = TBS;
tx_req->PDU_index = pdu_index;
tx_req->num_TLV = 1;
tx_req->TLVs[0].length = TBS + 2;
TX_req->Number_of_PDUs++;
TX_req->SFN = frameP;
TX_req->Slot = slotP;
type0_PDCCH_CSS_config->active = false;
T(T_GNB_MAC_DL_PDU_WITH_DATA,
T_INT(module_idP),
T_INT(CC_id),
T_INT(SI_RNTI),
T_INT(frameP),
T_INT(slotP),
T_INT(0 /* harq_pid */),
T_BUFFER(sib19_bcch_pdu, sib19_bcch_length));
other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 1);
}
}
}
@@ -1045,7 +1045,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %04x, bwp %d, cs %d\n", UE->rnti, bwp_id, coresetid);
NR_ControlResourceSet_t *coreset = sched_ctrl->coreset;
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch, false);
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch);
gNB_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu;
}
@@ -281,8 +281,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx)
NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
const NR_UE_DL_BWP_t *dl_bwp,
const NR_tda_info_t *tda_info,
const int Layers) {
const int Layers)
{
NR_pdsch_dmrs_t dmrs = {0};
int frontloaded_symb = 1; // default value
nr_dci_format_t dci_format = dl_bwp ? dl_bwp->dci_format : NR_DL_DCI_FORMAT_1_0;
@@ -732,12 +732,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
int max_mcs,
frame_t frame)
{
/* first call: everything is zero. Initialize to sensible default */
if (bler_stats->last_frame == 0 && bler_stats->mcs == 0) {
bler_stats->last_frame = frame;
bler_stats->mcs = 9;
bler_stats->bler = (bler_options->lower + bler_options->upper) / 2.0f;
}
int diff = frame - bler_stats->last_frame;
if (diff < 0) // wrap around
diff += 1024;
@@ -756,11 +750,11 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
int new_mcs = old_mcs;
if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && num_dl_sched > 3)
new_mcs += 1;
else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold
|| (num_dl_sched <= 3 && old_mcs > 9)) // no activity
else if (bler_stats->bler > bler_options->upper || num_dl_sched <= 3) // above threshold or no activity
new_mcs -= 1;
// else we are within threshold boundaries
new_mcs = max(new_mcs, bler_options->min_mcs);
bler_stats->last_frame = frame;
bler_stats->mcs = new_mcs;
memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds));
@@ -865,12 +859,8 @@ int nr_get_default_pucch_res(int pucch_ResourceCommon) {
return(default_pucch_csset[pucch_ResourceCommon]);
}
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
NR_ControlResourceSet_t *coreset,
NR_sched_pdcch_t *pdcch,
bool otherSI) {
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *pdcch)
{
pdcch_pdu->BWPSize = pdcch->BWPSize;
pdcch_pdu->BWPStart = pdcch->BWPStart;
pdcch_pdu->SubcarrierSpacing = pdcch->SubcarrierSpacing;
@@ -879,19 +869,23 @@ void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
pdcch_pdu->DurationSymbols = coreset->duration;
for (int i=0;i<6;i++)
for (int i = 0; i < 6; i++)
pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i];
LOG_D(MAC,"Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %d\n",
pdcch_pdu->BWPStart,pdcch_pdu->BWPSize,(int)pdcch_pdu->SubcarrierSpacing,(int)coreset->frequencyDomainResources.buf[0],(int)coreset->duration);
LOG_D(NR_MAC,
"Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %ld\n",
pdcch_pdu->BWPStart,
pdcch_pdu->BWPSize,
pdcch_pdu->SubcarrierSpacing,
coreset->frequencyDomainResources.buf[0],
coreset->duration);
pdcch_pdu->CceRegMappingType = pdcch->CceRegMappingType;
pdcch_pdu->RegBundleSize = pdcch->RegBundleSize;
pdcch_pdu->InterleaverSize = pdcch->InterleaverSize;
pdcch_pdu->ShiftIndex = pdcch->ShiftIndex;
pdcch_pdu->CoreSetType =
(otherSI || coreset->controlResourceSetId != 0) ? NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG : NFAPI_NR_CSET_CONFIG_MIB_SIB1;
pdcch_pdu->CoreSetType = coreset->controlResourceSetId != 0 ? NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG : NFAPI_NR_CSET_CONFIG_MIB_SIB1;
//precoderGranularity
pdcch_pdu->precoderGranularity = coreset->precoderGranularity;
@@ -2492,6 +2486,13 @@ void reset_srs_stats(NR_UE_info_t *UE) {
}
}
static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats_t *bler_stats, frame_t frame)
{
bler_stats->last_frame = frame;
bler_stats->mcs = bler_options->min_mcs;
bler_stats->bler = (float)(bler_options->lower + bler_options->upper) / 2.0f;
}
//------------------------------------------------------------------------------
NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup)
{
@@ -2522,6 +2523,10 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
sched_ctrl->sched_srs.slot = -1;
sched_ctrl->pdcch_cl_adjust = 0;
// Initialize bler_stats
init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame);
init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame);
// initialize LCID structure
seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t));
@@ -3322,7 +3327,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
int CC_id = 0;
int srb_id = 1;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig;
const NR_ServingCellConfig_t *sccd = UE->is_redcap ? NULL : mac->common_channels[CC_id].pre_ServingCellConfig;
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = cellGroupConfig;
@@ -100,7 +100,7 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot,
#define MIN_RSRP_VALUE -141
#define MAX_RSRP_VALUE -43
//Measured RSRP Values Table 10.1.16.1-1 from 36.133
//Measured RSRP Values Table 10.1.16.1-1 from 38.133
//Stored all the upper limits[Max RSRP Value of corresponding index]
//stored -1 for invalid values
static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = {
@@ -119,7 +119,7 @@ static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = {
-1, -1, -1, -1, -1, -1, -1, -1 // 120 - 127
};
//Differential RSRP values Table 10.1.6.1-2 from 36.133
//Differential RSRP values Table 10.1.6.1-2 from 38.133
//Stored the upper limits[MAX RSRP Value]
static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = {
0,
@@ -350,6 +350,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
if (lcid == UL_SCH_LCID_CCCH_48_BITS_REDCAP) {
LOG_I(MAC, "UE with RNTI %04x is RedCap\n", UE->rnti);
UE->is_redcap = true;
}
if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) {
@@ -2050,7 +2051,6 @@ static void pf_ul(module_id_t module_id,
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx);
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
sched_pusch->mcs = max(nrmac->min_grant_mcs, sched_pusch->mcs);
update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm);
sched_pusch->rbStart = rbStart;
sched_pusch->rbSize = min_rb;
@@ -2680,7 +2680,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_
ul_dci_request_pdu->PDUSize = (uint8_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
ul_dci_req->numPdus += 1;
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch, false);
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch);
pdcch_pdu_coreset[coresetid] = pdcch_pdu;
}
+11 -14
View File
@@ -54,10 +54,8 @@ void mac_top_init_gNB(ngran_node_t node_type,
void nr_mac_send_f1_setup_req(void);
void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *mac_config);
void nr_fill_sched_osi(gNB_MAC_INST *nrmac, const struct NR_SetupRelease_PDCCH_ConfigCommon *pdcch_ConfigCommon);
void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_t cellID, int tac);
void nr_mac_configure_sib19(gNB_MAC_INST *nrmac);
bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]);
bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
@@ -97,13 +95,11 @@ void schedule_nr_sib1(module_id_t module_idP,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req);
void schedule_nr_sib19(module_id_t module_idP,
frame_t frameP,
slot_t slotP,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req,
int sib19_bcch_length,
uint8_t *sib19_bcch_pdu);
void schedule_nr_other_sib(module_id_t module_idP,
frame_t frame,
slot_t slot,
nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req);
struct NR_SchedulingInfo2_r17* find_sib19_sched_info(const struct NR_SI_SchedulingInfo_v1700*);
@@ -215,10 +211,7 @@ void find_search_space(int ss_type,
NR_BWP_Downlink_t *bwp,
NR_SearchSpace_t *ss);
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
NR_ControlResourceSet_t *coreset,
NR_sched_pdcch_t *pdcch,
bool otherSI);
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *pdcch);
NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac,
NR_SearchSpace_t *ss,
@@ -474,4 +467,8 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid);
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti);
void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected);
void prepare_du_configuration_update(gNB_MAC_INST *mac,
f1ap_served_cell_info_t *info,
NR_BCCH_BCH_Message_t *mib,
const NR_BCCH_DL_SCH_Message_t *sib1);
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
@@ -165,7 +165,15 @@ void f1_setup_response(const f1ap_setup_resp_t *resp)
AssertFatal(check_plmn_identity(&du_cell->plmn, &cu_cell->plmn), "PLMN mismatch\n");
AssertFatal(du_cell->nr_pci == cu_cell->nrpci, "PCI mismatch: DU %d vs CU %d\n", du_cell->nr_pci, cu_cell->nrpci);
AssertFatal(cu_cell->num_SI == 0, "handling of CU-provided SIBs: not implemented\n");
// we can configure other SIB only after having received the ones generated by CU
bool update = nr_mac_configure_other_sib(mac, cu_cell->num_SI, cu_cell->SI_msg);
if (update) {
f1ap_setup_req_t *sr = mac->f1_config.setup_req;
DevAssert(sr->num_cells_available == 1);
f1ap_served_cell_info_t *info = &sr->cell[0].info;
NR_COMMON_channels_t *cc = &mac->common_channels[0];
prepare_du_configuration_update(mac, info, cc->mib, cc->sib1);
}
mac->f1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp));
AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n");
+7 -20
View File
@@ -276,7 +276,7 @@ typedef struct {
frame_type_t frame_type;
NR_BCCH_BCH_Message_t *mib;
NR_BCCH_DL_SCH_Message_t *sib1;
NR_BCCH_DL_SCH_Message_t *sib19;
seq_arr_t *du_SIBs;
NR_ServingCellConfigCommon_t *ServingCellConfigCommon;
/// pre-configured ServingCellConfig that is default for every UE
NR_ServingCellConfig_t *pre_ServingCellConfig;
@@ -285,9 +285,9 @@ typedef struct {
/// Outgoing BCCH pdu for PHY
uint8_t sib1_bcch_pdu[NR_MAX_SIB_LENGTH / 8];
int sib1_bcch_length;
/// used for sib19 data
uint8_t sib19_bcch_pdu[NR_MAX_SIB_LENGTH / 8];
int sib19_bcch_length;
/// used for otherSIB data
uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8];
int other_sib_bcch_length[2];
/// Template for RA computations
NR_RA_t ra[NR_NB_RA_PROC_MAX];
/// VRB map for common channels
@@ -691,19 +691,6 @@ typedef struct {
float pdcch_cl_adjust;
} NR_UE_sched_ctrl_t;
typedef struct {
NR_SearchSpace_t *search_space;
NR_ControlResourceSet_t *coreset;
NR_sched_pdcch_t sched_pdcch;
NR_sched_pdsch_t sched_pdsch;
uint32_t num_total_bytes;
int cce_index;
uint8_t aggregation_level;
} NR_UE_sched_osi_ctrl_t;
typedef struct {
uicc_t *uicc;
} NRUEcontext_t;
@@ -738,6 +725,7 @@ typedef struct NR_mac_stats {
typedef struct NR_bler_options {
double upper;
double lower;
uint8_t min_mcs;
uint8_t max_mcs;
uint8_t harq_round_max;
} NR_bler_options_t;
@@ -783,6 +771,7 @@ typedef struct {
float ul_thr_ue;
float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook;
bool is_redcap;
} NR_UE_info_t;
typedef struct {
@@ -927,9 +916,8 @@ typedef struct gNB_MAC_INST_s {
nr_mac_config_t radio_config;
NR_UE_sched_osi_ctrl_t *sched_osi;
NR_UE_sched_ctrl_t *sched_ctrlCommon;
NR_sched_pdcch_t *sched_pdcch_otherSI;
uint16_t cset0_bwp_start;
uint16_t cset0_bwp_size;
NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config[64];
@@ -938,7 +926,6 @@ typedef struct gNB_MAC_INST_s {
NR_bler_options_t dl_bler;
NR_bler_options_t ul_bler;
uint8_t min_grant_prb;
uint8_t min_grant_mcs;
bool identity_pm;
int precoding_matrix_size[NR_MAX_NB_LAYERS];
int fapi_beam_index[MAX_NUM_OF_SSB];
+2 -2
View File
@@ -155,13 +155,13 @@ typedef struct nr_pdcp_entity_t {
stream_security_context_t *security_context;
void (*cipher)(stream_security_context_t *security_context,
unsigned char *buffer, int length,
int bearer, int count, int direction);
int bearer, uint32_t count, int direction);
void (*free_security)(stream_security_context_t *security_context);
stream_security_context_t *integrity_context;
void (*integrity)(stream_security_context_t *integrity_context,
unsigned char *out,
unsigned char *buffer, int length,
int bearer, int count, int direction);
int bearer, uint32_t count, int direction);
void (*free_integrity)(stream_security_context_t *integrity_context);
/* security/integrity algorithms need to know uplink/downlink information
* which is reverse for gnb and ue, so we need to know if this
@@ -42,7 +42,7 @@ stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_
void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context,
unsigned char *out,
unsigned char *buffer, int length,
int bearer, int count, int direction)
int bearer, uint32_t count, int direction)
{
nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)integrity_context;
@@ -29,7 +29,7 @@ stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_
void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context,
unsigned char *out,
unsigned char *buffer, int length,
int bearer, int count, int direction);
int bearer, uint32_t count, int direction);
void nr_pdcp_integrity_nia1_free_integrity(stream_security_context_t *integrity_context);
@@ -39,14 +39,13 @@ stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]
return (stream_security_context_t *)ctx;
}
void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction)
void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, uint32_t count, int direction)
{
DevAssert(integrity_context != NULL);
DevAssert(out != NULL);
DevAssert(buffer != NULL);
DevAssert(length > -1);
DevAssert(bearer > 0 && bearer < 33);
DevAssert(count > -1);
cbc_cmac_ctx_t *ctx = (cbc_cmac_ctx_t *)integrity_context;
@@ -31,7 +31,7 @@ stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]
void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context,
unsigned char *out,
unsigned char *buffer, int length,
int bearer, int count, int direction);
int bearer, uint32_t count, int direction);
void nr_pdcp_integrity_nia2_free_integrity(stream_security_context_t *integrity_context);
@@ -43,7 +43,7 @@ void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context,
unsigned char *buffer,
int length,
int bearer,
int count,
uint32_t count,
int direction)
{
nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)security_context;
@@ -30,7 +30,7 @@ void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context,
unsigned char *buffer,
int length,
int bearer,
int count,
uint32_t count,
int direction);
void nr_pdcp_security_nea1_free_security(stream_security_context_t *security_context);
@@ -36,14 +36,13 @@ stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_k
return (stream_security_context_t *)ciphering_key;
}
void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, int count, int direction)
void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, uint32_t count, int direction)
{
DevAssert(security_context != NULL);
DevAssert(buffer != NULL);
DevAssert(length > 0);
DevAssert(bearer > -1 && bearer < 32);
DevAssert(direction > -1 && direction < 2);
DevAssert(count > -1);
aes_128_t p = {0};
const uint8_t *ciphering_key = (uint8_t const *)security_context;
@@ -28,7 +28,7 @@ stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_k
void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context,
unsigned char *buffer, int length,
int bearer, int count, int direction);
int bearer, uint32_t count, int direction);
void nr_pdcp_security_nea2_free_security(stream_security_context_t *security_context);
+5 -4
View File
@@ -18,10 +18,11 @@ else()
message(FATAL_ERROR "unknown M2AP_RELEASE ${M2AP_RELEASE}")
endif()
add_custom_command(OUTPUT ${m2ap_source} ${m2ap_headers}
COMMAND ASN1C_PREFIX=M2AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}
COMMENT "Generating M2AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}"
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}
"M2AP_"
OUTPUT ${m2ap_source} ${m2ap_headers}
OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps
COMMENT "M2AP source files"
)
add_library(asn1_m2ap ${m2ap_source})
+2 -1
View File
@@ -1108,7 +1108,8 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac,
uint8_t *pduP,
uint32_t pdu_len)
{
return nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len);
nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len);
return 0;
}
// L2 Abstraction Layer
+5 -4
View File
@@ -10,10 +10,11 @@ else()
message(FATAL_ERROR "unknown LTE_RRC_RELEASE ${LTE_RRC_RELEASE}")
endif()
add_custom_command(OUTPUT ${lte_rrc_source} ${lte_rrc_headers}
COMMAND ASN1C_PREFIX=LTE_ ${ASN1C_EXEC} -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}
COMMENT "Generating LTE RRC source file from ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}"
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}
"LTE_"
OUTPUT ${lte_rrc_source} ${lte_rrc_headers}
OPTIONS -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example
COMMENT "LTE RRC source files"
)
# Many other targets include LTE RRC ASN.1 headers, without actually needing
+5 -4
View File
@@ -10,10 +10,11 @@ else()
message(FATAL_ERROR "unknown NR_RRC_RELEASE ${NR_RRC_RELEASE}")
endif()
add_custom_command(OUTPUT ${nr_rrc_source} ${nr_rrc_headers}
COMMAND ASN1C_PREFIX=NR_ ${ASN1C_EXEC} -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -findirect-choice -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}
COMMENT "Generating NR RRC source file from ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}"
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}
"NR_"
OUTPUT ${nr_rrc_source} ${nr_rrc_headers}
OPTIONS -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -findirect-choice
COMMENT "NR RRC source files"
)
# Many other targets include NR RRC ASN.1 headers, without actually needing the
+29 -43
View File
@@ -197,51 +197,37 @@ int xer_nr_sprint(char *string, size_t string_size, asn_TYPE_descriptor_t *td, v
//------------------------------------------------------------------------------
int do_SIB23_NR(rrc_gNB_carrier_data_t *carrier)
int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc)
{
asn_enc_rval_t enc_rval;
SystemInformation_IEs__sib_TypeAndInfo__Member *sib2 = NULL;
SystemInformation_IEs__sib_TypeAndInfo__Member *sib3 = NULL;
NR_SIB2_t *sib2 = calloc(1, sizeof(*sib2));
sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB0;
struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars *speed = calloc(1, sizeof(*speed));
NR_MobilityStateParameters_t mobilityStateParameters = {0};
mobilityStateParameters.t_Evaluation = NR_MobilityStateParameters__t_Evaluation_s30;
mobilityStateParameters.t_HystNormal = NR_MobilityStateParameters__t_HystNormal_s30;
mobilityStateParameters.n_CellChangeMedium = 1;
mobilityStateParameters.n_CellChangeHigh = 2;
speed->mobilityStateParameters = mobilityStateParameters;
struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF qhyst = {0};
qhyst.sf_Medium = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_Medium_dB_4;
qhyst.sf_High = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_High_dB_6;
speed->q_HystSF = qhyst;
sib2->cellReselectionInfoCommon.speedStateReselectionPars = speed;
sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 0; // INTEGER (0..7)
sib2->cellReselectionServingFreqInfo.threshServingLowP = 0;
NR_ReselectionThresholdQ_t *threshServingLowQ = calloc(1, sizeof(*threshServingLowQ));
*threshServingLowQ = 0;
sib2->cellReselectionServingFreqInfo.threshServingLowQ = threshServingLowQ;
sib2->intraFreqCellReselectionInfo.q_RxLevMin = -56; // INTEGER (-70..-22)
sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 22; // INTEGER (0..31)
sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 1; // INTEGER (0..7)
sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true;
sib2->intraFreqCellReselectionInfo.smtc = ssbmtc;
NR_BCCH_DL_SCH_Message_t *sib_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t));
sib_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1;
sib_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1));
sib_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation;
sib_message->message.choice.c1->choice.systemInformation = CALLOC(1,sizeof(struct NR_SystemInformation));
struct NR_SystemInformation *sib = sib_message->message.choice.c1->choice.systemInformation;
sib->criticalExtensions.present = NR_SystemInformation__criticalExtensions_PR_systemInformation;
sib->criticalExtensions.choice.systemInformation = CALLOC(1, sizeof(struct NR_SystemInformation_IEs));
struct NR_SystemInformation_IEs *ies = sib->criticalExtensions.choice.systemInformation;
sib2 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member));
sib2->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2;
sib2->choice.sib2 = CALLOC(1, sizeof(struct NR_SIB2));
sib2->choice.sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB1;
sib2->choice.sib2->cellReselectionServingFreqInfo.threshServingLowP = 2; // INTEGER (0..31)
sib2->choice.sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 2; // INTEGER (0..7)
sib2->choice.sib2->intraFreqCellReselectionInfo.q_RxLevMin = -50; // INTEGER (-70..-22)
sib2->choice.sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 2; // INTEGER (0..31)
sib2->choice.sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 2; // INTEGER (0..7)
sib2->choice.sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true;
asn1cSeqAdd(&ies->sib_TypeAndInfo.list, sib2);
sib3 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member));
sib3->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3;
sib3->choice.sib3 = CALLOC(1, sizeof(struct NR_SIB3));
asn1cSeqAdd(&ies->sib_TypeAndInfo.list, sib3);
//encode SIB to data
// carrier->SIB23 = (uint8_t *) malloc16(128);
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message,
NULL,
(void *)sib_message,
carrier->SIB23,
100);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_DL_SCH_Message, sib_message);
return((enc_rval.encoded+7)/8);
ssize_t size = uper_encode_to_new_buffer(&asn_DEF_NR_SIB2, NULL, (void *)sib2, (void **)msg_SIB2);
AssertFatal (size > 0, "ASN1 message encoding failed (encoded %lu bytes)!\n", size);
ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2);
return size;
}
int do_RRCReject(uint8_t *const buffer)

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