Commit 6d9c2c35 authored by Robert Schmidt's avatar Robert Schmidt

Merge branch 'integration_2025_w07' into 'develop'

Integration: `2025.w07`

Closes #812, #901, #904, #881, and #819

See merge request oai/openairinterface5g!3258

* !3055 Dynamic PDCCH aggregation level
* !3176 Refactor and extend NAS Registration Request
* !3256 Add check on force_local in custom_command CI handling
* !3257 Bugfix in gNB modulated DCI buffer size
* !3249 Improvements in TDD configuration
* !3194 fix NTN LEO scenarios
* !3200 FHI72: remove polling, fix memory leak
* !3127 Optimizations of PDSCH Resource Mapping in nr_dlsch.c/nr_modulation.c
* !3252 \[E2 agent\] Multi RC REPORT service styles support
parents ff58b5e1 87c83f72
......@@ -1366,6 +1366,7 @@ target_link_libraries(NR_L2_UE PRIVATE nr_nas)
add_library(MAC_NR_COMMON
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c
)
target_link_libraries(MAC_NR_COMMON PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
......@@ -1891,6 +1892,7 @@ add_executable(nr-uesoftmodem
${OPENAIR_DIR}/radio/COMMON/common_lib.c
${OPENAIR_DIR}/radio/COMMON/record_player.c
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c
${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
)
......
......@@ -18,7 +18,8 @@ gNBs =
sib1_tda = 5;
min_rxtxtime = 6;
disable_harq = 1;
num_dlharq = 32;
num_ulharq = 32;
servingCellConfigCommon = (
{
......@@ -28,11 +29,11 @@ gNBs =
# downlinkConfigCommon
#frequencyInfoDL
# this is 2150.43 MHz + 14 PRBs@15kHz SCS (same as initial BWP), points to Subcarrier 0 of RB#10 of SSB block
absoluteFrequencySSB = 430590;
dl_frequencyBand = 66;
# this is 2150.43 MHz
dl_absoluteFrequencyPointA = 430086;
# GSCN 6221
absoluteFrequencySSB = 497770;
dl_frequencyBand = 254;
# this is 2486.15 MHz
dl_absoluteFrequencyPointA = 497230;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
......@@ -52,9 +53,9 @@ gNBs =
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 66;
# this is 1750.43 MHz
ul_absoluteFrequencyPointA = 350086;
ul_frequencyBand = 254;
# this is 1612.65 MHz
ul_absoluteFrequencyPointA = 322530;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
......@@ -147,14 +148,15 @@ gNBs =
#ext2
#ntn_Config_r17
cellSpecificKoffset_r17 = 478;
ta-Common-r17 = 29314900;
cellSpecificKoffset_r17 = 40;
ta-Common-r17 = 4634000; # 18.87 ms
ta-CommonDrift-r17 = -230000; # -46 µs/s
positionX-r17 = 0;
positionY-r17 = 0;
positionZ-r17 = 32433846;
positionY-r17 = -2166908; # -2816980.4 m
positionZ-r17 = 4910784; # 6384019.2 m
velocityVX-r17 = 0;
velocityVY-r17 = 0;
velocityVZ-r17 = 0;
velocityVY-r17 = 115246; # 6914.76 m/s
velocityVZ-r17 = 50853; # 3051.18 m/s
}
);
......@@ -196,8 +198,11 @@ MACRLCs = (
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
# ulsch_max_frame_inactivity = 0;
pusch_TargetSNRx10 = 150;
pucch_TargetSNRx10 = 200;
dl_max_mcs = 9;
ul_max_mcs = 9;
}
);
......@@ -205,7 +210,7 @@ L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
prach_dtx_threshold = 150;
pucch0_dtx_threshold = 150;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
......@@ -243,11 +248,28 @@ rfsimulator :
{
serveraddr = "server";
serverport = 4043;
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
options = ("chanmod"); #("saviq"); or/and "chanmod"
prop_delay = 20;
IQfile = "/tmp/rfsimulator.iqs";
};
channelmod = {
max_chan=10;
modellist="modellist_rfsimu_1";
modellist_rfsimu_1 = (
{
model_name = "rfsimu_channel_enB0"
type = "SAT_LEO_TRANS";
noise_power_dB = -100;
},
{
model_name = "rfsimu_channel_ue0"
type = "SAT_LEO_TRANS";
noise_power_dB = -100;
}
);
};
security = {
# preferred ciphering algorithms
# the first one of the list that an UE supports in chosen
......@@ -277,4 +299,3 @@ log_config :
ngap_log_level ="debug";
f1ap_log_level ="debug";
};
......@@ -28,11 +28,11 @@ gNBs =
# downlinkConfigCommon
#frequencyInfoDL
# GSCN 6221 = 497770, (GSCN 6215 - 497290)
# GSCN 6221
absoluteFrequencySSB = 497770;
dl_frequencyBand = 254;
# this is 2486.9 MHz
dl_absoluteFrequencyPointA = 497380;
# this is 2486.15 MHz
dl_absoluteFrequencyPointA = 497230;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
......@@ -47,14 +47,14 @@ gNBs =
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 0;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 0;
initialDLBWPcontrolResourceSetZero = 2;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 254;
# this is 1613.4 MHz
ul_absoluteFrequencyPointA = 322680;
# this is 1612.65 MHz
ul_absoluteFrequencyPointA = 322530;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
......@@ -147,8 +147,8 @@ gNBs =
#ext2
#ntn_Config_r17
cellSpecificKoffset_r17 = 478; //GEO
ta-Common-r17 = 29319745;
cellSpecificKoffset_r17 = 478;
ta-Common-r17 = 58629666; # 238.74 ms
positionX-r17 = 0;
positionY-r17 = 0;
positionZ-r17 = 32433846;
......@@ -196,8 +196,11 @@ MACRLCs = (
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
# ulsch_max_frame_inactivity = 0;
pusch_TargetSNRx10 = 150;
pucch_TargetSNRx10 = 200;
dl_max_mcs = 9;
ul_max_mcs = 9;
}
);
......@@ -205,7 +208,7 @@ L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
prach_dtx_threshold = 150;
pucch0_dtx_threshold = 150;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
......@@ -244,7 +247,7 @@ rfsimulator :
serveraddr = "server";
serverport = 4043;
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
prop_delay = 238.74;
IQfile = "/tmp/rfsimulator.iqs";
};
......@@ -277,4 +280,3 @@ log_config :
ngap_log_level ="debug";
f1ap_log_level ="debug";
};
......@@ -406,6 +406,9 @@ def ExecuteActionWithParam(action):
elif action == 'Custom_Command':
node = test.findtext('node')
if force_local:
# Change all execution targets to localhost
node = 'localhost'
command = test.findtext('command')
command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes']
success = cls_oaicitest.Custom_Command(HTML, node, command, command_fail)
......
......@@ -86,7 +86,7 @@ services:
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.prop_delay 238.74 --log_config.global_log_options level,nocolor,time
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
ASAN_OPTIONS: detect_leaks=0
depends_on:
- oai-ext-dn
......@@ -94,7 +94,7 @@ services:
public_net:
ipv4_address: 192.168.71.140
volumes:
- ../../conf_files/gnb.sa.band66.ntn.25prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf
- ../../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf:/opt/oai-gnb/etc/gnb.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
......@@ -110,7 +110,7 @@ services:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS: --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --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 --log_config.global_log_options level,nocolor,time
depends_on:
- oai-gnb
networks:
......
......@@ -150,6 +150,15 @@ typedef enum ip_traffic_type_e {
TRAFFIC_PC5S_SESSION_INIT = 10
} ip_traffic_type_t;
typedef enum {
PDCCH_AGG_LEVEL1 = 0,
PDCCH_AGG_LEVEL2,
PDCCH_AGG_LEVEL4,
PDCCH_AGG_LEVEL8,
PDCCH_AGG_LEVEL16,
NUM_PDCCH_AGG_LEVELS
} Pdcch_Aggregation_Level_t;
typedef struct net_ip_address_s {
unsigned ipv4: 1;
unsigned ipv6: 1;
......
......@@ -551,6 +551,18 @@ void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) {
*n_rb = 6*count;
}
// According to 38.211 7.3.2.2
int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration)
{
int num_rbs;
int rb_offset;
get_coreset_rballoc(FreqDomainResource, &num_rbs, &rb_offset);
int total_resource_element_groups = num_rbs * duration;
int reg_per_cce = 6;
int total_cces = total_resource_element_groups / reg_per_cce;
return total_cces;
}
int get_nb_periods_per_frame(uint8_t tdd_period)
{
......
......@@ -142,7 +142,7 @@ typedef struct frame_structure_s {
int8_t numb_slots_frame;
int8_t numb_slots_period;
int8_t numb_period_frame;
bool is_tdd;
frame_type_t frame_type;
} frame_structure_t;
typedef struct {
......@@ -245,6 +245,7 @@ uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, ui
int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs);
int get_SLIV(uint8_t S, uint8_t L);
void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset);
int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration);
int get_nr_table_idx(int nr_bandP, uint8_t scs_index);
int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index);
frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index);
......
......@@ -23,6 +23,7 @@
#define NOTIFIED_FIFO_H
#include "pthread_utils.h"
#include <stdint.h>
#include <malloc.h>
#include <pthread.h>
#include "time_meas.h"
#include <memory.h>
......
......@@ -38,6 +38,33 @@ The actual scheduler implementation can be found in functions `pf_dl()` and
[`gNB_scheduler_ulsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c)
(for UL), respectively.
## PDDCH aggregation level
PDCCH aggregation level is selected using closed loop controller, where DL HARQ
feedback is the controller feedback signal. It is used to increment `pdcch_cl_adjust`
variable if no feedback is detected and decrement the variable when feedback is detected.
`pdcch_cl_adjust` is later mapped to the PDCCH aggregation level range.
The value of `pdcch_cl_adjust` is clamped to range <0,1>, the increment value is 0.05 while
the decrement value is 0.01. These values are selected to ensure PDCCH success rate is high.
See Examples below for futher explaination.
The possible values of aggregation level on UE SS can be configured via `uess_agg_levels` configuration
option. By default the gNB uses only aggregation level 2 which translates to `uess_agg_levels` set to
`[0, 1, 0, 0, 0]`. For example, to enable aggregation level 2 and 4 set `uess_agg_levels` to `[0, 1, 1, 0, 0]`.
### Examples:
#### Example 1:
Say we have 90% PDCCH success rate at aggregation level 1, `pdcch_cl_adjust` will stay at 0
for most of the time. 2 consecutive PDCCH failures will not result in increasing the aggregation
level (because (0.05 + 0.05) * 4 = 0.4 which is closer to 0 than to 1). If PDCCH fails 3 times
in a row the aggregation level will change to 2 and hopefully back to 1 once more PDDCH successes
happen.
### Example 2
Say we have 0% PDCCH success rate (radio link failure scenario) but `pdcch_cl_adjust` is 0 indicating
perfect PDCCH channel. it would take ~18 PDCCH failures to reach maximum aggregation level.
# Periodic output and interpretation
The scheduler periodically outputs statistics that can help you judge the radio
......
......@@ -475,6 +475,19 @@ cmake .. -GNinja -DOAI_FHI72=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
ninja nr-softmodem oran_fhlib_5g params_libconfig
```
Note that in tags 2025.w06 and prior, the FHI72 driver used polling to wait for
the next slot. This is inefficient as it burns CPU time, and has been replaced
with a more efficient mechanism. Nevertheless, if you experience problems that
did not occur previously, it is possible to re-enable polling, either with
`build_oai` like this
./build_oai --gNB --ninja -t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=$HOME/phy/fhi_lib/lib --cmake-opt -DOAI_FHI72_USE_POLLING=ON
or with `cmake` like so
cmake .. -GNinja -DOAI_FHI72=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib -DOAI_FHI72_USE_POLLING=ON
ninja oran_fhlib_5g
# Configuration
RU and DU configurations have a circular dependency: you have to configure DU MAC address in the RU configuration and the RU MAC address, VLAN and Timing advance parameters in the DU configuration.
......@@ -1040,6 +1053,8 @@ In this case, you should reverify that `ptp4l` and `phc2sys` are working, e.g.,
do not do any jumps (during the last hour). While an occasional jump is not
necessarily problematic for the gNB, many such messages mean that the system is
not working, and UEs might not be able to attach or reach good performance.
Also, you can try to compile with polling (see [the build
section](.#build-oai-gnb)) to see if it resolves the problem.
# Operation with multiple RUs
......
......@@ -221,15 +221,49 @@ Or by providing this the the command line parameters:
### gNB
The main parameter to cope with the large NTN propagation delay is the cellSpecificKoffset.
This parameter is the scheduling offset used for the timing relationships that are modified for NTN (see TS 38.213).
The main parameters to cope with the large NTN propagation delay are cellSpecificKoffset, ta-Common, ta-CommonDrift and the ephemeris data (satellite position and velocity vectors).
The parameter `cellSpecificKoffset_r17` is the scheduling offset used for the timing relationships that are modified for NTN (see TS 38.213).
The unit of the field Koffset is number of slots for a given subcarrier spacing of 15 kHz.
This parameter can be provided to the gNB in the conf file as `cellSpecificKoffset_r17` in the section `servingCellConfigCommon`.
The parameter `ta-Common-r17` is used to provide the propagation delay between the reference point (at the gNB) and the satellite.
The granularity of ta-Common is 4.072 × 10^(-3) µs. Values are given in unit of corresponding granularity.
The parameter `ta-CommonDrift-r17` indicates the drift rate of the common TA.
The granularity of ta-CommonDrift is 0.2 × 10^(-3) µs/s. Values are given in unit of corresponding granularity.
The satellite position and velocity vartors are provided using the following parameters:
`positionX-r17`, `positionY-r17`, `positionZ-r17`:
X, Y, Z coordinate of satellite position state vector in ECEF. Unit is meter.
Step of 1.3 m. Actual value = field value * 1.3.
`velocityVX-r17`, `velocityVY-r17`, `velocityVZ-r17`:
X, Y, Z coordinate of satellite velocity state vector in ECEF. Unit is meter/second.
Step of 0.06 m/s. Actual value = field value * 0.06.
These parameters can be provided to the gNB in the conf file in the section `servingCellConfigCommon`:
```
...
cellSpecificKoffset_r17 = 478; # GEO satellite
# cellSpecificKoffset_r17 = 40; # LEO satellite
# GEO satellite
cellSpecificKoffset_r17 = 478;
ta-Common-r17 = 58629666; # 238.74 ms
positionX-r17 = 0;
positionY-r17 = 0;
positionZ-r17 = 32433846;
velocityVX-r17 = 0;
velocityVY-r17 = 0;
velocityVZ-r17 = 0;
# LEO satellite
# cellSpecificKoffset_r17 = 40;
# ta-Common-r17 = 4634000; # 18.87 ms
# ta-CommonDrift-r17 = -230000; # -46 µs/s
# positionX-r17 = 0;
# positionY-r17 = -2166908; # -2816980.4 m
# positionZ-r17 = 4910784; # 6384019.2 m
# velocityVX-r17 = 0;
# velocityVY-r17 = 115246; # 6914.76 m/s
# velocityVZ-r17 = 50853; # 3051.18 m/s
...
```
......@@ -262,10 +296,11 @@ To enable this feature, the `disable_harq` flag has to be added to the gNB conf
...
```
So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this:
The settings for a transparent GEO satellite scenario are already provided in the file `ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf`.
Using this conf file, an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this:
```
cd cmake_targets
sudo ./ran_build/build/nr-softmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf --rfsim --rfsimulator.prop_delay 238.74
sudo ./ran_build/build/nr-softmodem -O ../ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf --rfsim
```
To configure NTN gNB with 32 HARQ processes in downlink and uplink, add these settings in conf files under section `gNBs.[0]`
......@@ -281,32 +316,43 @@ To simulate a LEO satellite channel model with rfsimulator in UL (DL is simulate
@include "channelmod_rfsimu_LEO_satellite.conf"
```
So with these modifications to the file `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf` an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, trasparent LEO satellite 5G NR NTN is this:
The settings for a transparent LEO satellite scenario are already provided in the file `ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf`.
Using this conf file, an example gNB command for FDD, 5 MHz BW, 15 kHz SCS, trasparent LEO satellite 5G NR NTN is this:
```
cd cmake_targets
sudo ./ran_build/build/nr-softmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf --rfsim --rfsimulator.prop_delay 20
sudo ./ran_build/build/nr-softmodem -O ../ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf --rfsim
```
### NR UE
At UE side, there are two main parameters to cope with the large NTN propagation delay, cellSpecificKoffset and ta-Common.
`cellSpecificKoffset` is the same as for gNB and can be provided to the UE via command line parameter `--ntn-koffset`.
`ta-Common` is a common timing advance and can be provided to the UE via command line parameter `--ntn-ta-common` in milliseconds.
At UE side, only few parameters have to be provided, as the UE receives most relevant parameters via SIB19 from the gNB.
But to calculate the UE specific TA, the UE position has to be provided in the `ue.conf` file.
Also the LEO channel model has to be configured, e.g. by using an `@include` statement, just like on the gNB side:
```
...
position0 = {
x = 0.0;
y = 0.0;
z = 6377900.0;
}
@include "channelmod_rfsimu_LEO_satellite.conf"
```
So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent GEO satellite 5G NR NTN is this:
```
cd cmake_targets
sudo ./ran_build/build/nr-uesoftmodem --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --rfsim --rfsimulator.prop_delay 238.74 --ntn-koffset 478 --ntn-ta-common 477.48
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 238.74
```
For LEO satellites a third parameter specifying the NTN propagation delay drift has ben added, ta-CommonDrift.
`ta-CommonDrift` provides the drift rate of the common timing advance and can be provided to the UE via command line parameter `--ntn-ta-commondrift` in microseconds per second.
For LEO satellite scenarios, the parameter `--ntn-initial-time-drift` must be provided via command line, as the UE needs this value to compensate for the time drift during initial sync, before SIB19 was received.
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.
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 --band 66 -C 2152680000 --CO -400000000 -r 25 --numerology 0 --ssb 48 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/channelmod_rfsimu_LEO_satellite.conf --time-sync-I 0.2 --ntn-koffset 40 --ntn-ta-common 37.74 --ntn-ta-commondrift -50 --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
```
# Specific OAI modes
......
......@@ -219,7 +219,6 @@ static void rx_func(processingData_L1_t *info)
gNB->if_inst->NR_UL_indication(&UL_INFO);
stop_meas(&gNB->ul_indication_stats);
#ifndef OAI_FHI72
notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->L1_rx_out, NULL);
processingData_L1_t *syncMsg = NotifiedFifoData(res);
syncMsg->gNB = gNB;
......@@ -228,7 +227,6 @@ static void rx_func(processingData_L1_t *info)
res->key = slot_rx;
LOG_D(NR_PHY, "Signaling completion for %d.%d (mod_slot %d) on L1_rx_out\n", frame_rx, slot_rx, slot_rx % RU_RX_SLOT_DEPTH);
pushNotifiedFIFO(&gNB->L1_rx_out, res);
#endif
}
}
......
......@@ -1084,6 +1084,48 @@ void ru_tx_func(void *param)
}//else emulate_rf
}
/* @brief wait for the next RX TTI to be free
*
* Certain radios, e.g., RFsim, can run faster than real-time. This might
* create problems, e.g., if RX and TX get too far from each other. This
* function ensures that a maximum of 4 RX slots are processed at a time (and
* not more than those four are started).
*
* Through the queue L1_rx_out, we are informed about completed RX jobs.
* rx_tti_busy keeps track of individual slots that have been started; this
* function blocks until the current frame/slot is completed, signaled through
* a message.
*
* @param L1_rx_out the queue from which to read completed RX jobs
* @param rx_tti_busy array to mark RX job completion
* @param frame_rx the frame to wait for
* @param slot_rx the slot to wait for
*/
static bool wait_free_rx_tti(notifiedFIFO_t *L1_rx_out, bool rx_tti_busy[RU_RX_SLOT_DEPTH], int frame_rx, int slot_rx)
{
int idx = slot_rx % RU_RX_SLOT_DEPTH;
if (rx_tti_busy[idx]) {
bool not_done = true;
LOG_D(NR_PHY, "%d.%d Waiting to access RX slot %d\n", frame_rx, slot_rx, idx);
// block and wait for frame_rx/slot_rx free from previous slot processing.
// as we can get other slots, we loop on the queue
while (not_done) {
notifiedFIFO_elt_t *res = pullNotifiedFIFO(L1_rx_out);
if (!res)
return false;
processingData_L1_t *info = NotifiedFifoData(res);
LOG_D(NR_PHY, "%d.%d Got access to RX slot %d.%d (%d)\n", frame_rx, slot_rx, info->frame_rx, info->slot_rx, idx);
rx_tti_busy[info->slot_rx % RU_RX_SLOT_DEPTH] = false;
if ((info->slot_rx % RU_RX_SLOT_DEPTH) == idx)
not_done = false;
delNotifiedFIFO_elt(res);
}
}
// set the tti to busy: the caller will process this slot now
rx_tti_busy[idx] = true;
return true;
}
void *ru_thread(void *param)
{
static int ru_thread_status;
......@@ -1097,9 +1139,7 @@ void *ru_thread(void *param)
char threadname[40];
int initial_wait = 0;
#ifndef OAI_FHI72
bool rx_tti_busy[RU_RX_SLOT_DEPTH] = {false};
#endif
// set default return value
ru_thread_status = 0;
// set default return value
......@@ -1245,39 +1285,12 @@ void *ru_thread(void *param)
if (ru->idx != 0)
proc->frame_tx = (proc->frame_tx + proc->frame_offset) & 1023;
#ifndef OAI_FHI72
// do RX front-end processing (frequency-shift, dft) if needed
int slot_type = nr_slot_select(&ru->config, proc->frame_rx, proc->tti_rx);
if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
if (!wait_free_rx_tti(&gNB->L1_rx_out, rx_tti_busy, proc->frame_rx, proc->tti_rx))
break; // nothing to wait for: we have to stop
if (ru->feprx) {
if (rx_tti_busy[proc->tti_rx % RU_RX_SLOT_DEPTH]) {
bool not_done = true;
LOG_D(NR_PHY, "%d.%d Waiting to access RX slot %d\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH);
// now we block and wait our slot memory zone is freed from previous slot processing
// as we can get other slots ending, we loop on the queue
notifiedFIFO_elt_t *res = NULL;
while (not_done) {
res = pullNotifiedFIFO(&gNB->L1_rx_out);
if (!res)
break;
processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res);
LOG_D(NR_PHY,
"%d.%d Got access to RX slot %d.%d (%d)\n",
proc->frame_rx,
proc->tti_rx,
info->frame_rx,
info->slot_rx,
proc->tti_rx % RU_RX_SLOT_DEPTH);
rx_tti_busy[info->slot_rx % RU_RX_SLOT_DEPTH] = false;
if ((info->slot_rx % RU_RX_SLOT_DEPTH) == (proc->tti_rx % RU_RX_SLOT_DEPTH))
not_done = false;
delNotifiedFIFO_elt(res);
}
if (!res)
break;
}
// set the tti that was generated to busy
rx_tti_busy[proc->tti_rx % RU_RX_SLOT_DEPTH] = true;
ru->feprx(ru,proc->tti_rx);
LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH);
//LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1);
......@@ -1315,7 +1328,6 @@ void *ru_thread(void *param)
} // end if (prach_id > 0)
} // end if (ru->feprx)
} // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
#endif
notifiedFIFO_elt_t *resTx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, NULL);
processingData_L1tx_t *syncMsgTx = NotifiedFifoData(resTx);
......
This diff is collapsed.
......@@ -12,6 +12,7 @@
#define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n"
#define CONFIG_HLP_TIME_SYNC_P "coefficient for Proportional part of time sync PI controller\n"
#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_AGC "Rx Gain control used for UE\n"
......@@ -62,6 +63,7 @@
{"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \
{"time-sync-P", CONFIG_HLP_TIME_SYNC_P, 0, .dblptr=&(nrUE_params.time_sync_P), .defdblval=0.5, TYPE_DOUBLE, 0}, \
{"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}, \
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \
}
......@@ -85,6 +87,7 @@ typedef struct {
int ssb_start_subcarrier;
double time_sync_P;
double time_sync_I;
double ntn_init_time_drift;
int autonomous_ta;
int agc;
char *usrp_args;
......
......@@ -556,9 +556,9 @@ typedef struct {
} fapi_nr_ta_command_pdu;
typedef struct {
// N_common_ta_adj represents common propagation delay received in SIB19 (ms)
// N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms)
double N_common_ta_adj;
// N_UE_TA_adj calculated propagation delay from UE and SAT (ms)
// N_UE_TA_adj calculated round-trip-time between UE and SAT (ms)
double N_UE_TA_adj;
// drift rate of common ta in µs/s
double ntn_ta_commondrift;
......@@ -655,21 +655,18 @@ typedef struct
typedef struct
{
uint8_t slot_config;//For each symbol in each slot a uint8_t value is provided indicating: 0: DL slot 1: UL slot 2: Guard slot
uint8_t slot_config; //For each symbol in each slot a uint8_t value is provided indicating: 0: DL slot 1: UL slot 2: Guard slot
} fapi_nr_max_num_of_symbol_per_slot_t;
typedef struct
{
fapi_nr_max_num_of_symbol_per_slot_t *max_num_of_symbol_per_slot_list;
} fapi_nr_max_tdd_periodicity_t;
typedef struct
{
uint8_t tdd_period_in_slots;
fapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list;
} fapi_nr_tdd_table_t;
typedef struct
......@@ -709,8 +706,7 @@ typedef struct {
fapi_nr_cell_config_t cell_config;
fapi_nr_ssb_config_t ssb_config;
fapi_nr_ssb_table_t ssb_table;
fapi_nr_tdd_table_t tdd_table_1;
fapi_nr_tdd_table_t *tdd_table_2;
fapi_nr_tdd_table_t tdd_table;
fapi_nr_prach_config_t prach_config;
} fapi_nr_config_request_t;
......
This diff is collapsed.
......@@ -60,8 +60,7 @@ void nr_layer_mapping(int nbCodes,
uint8_t n_layers,
int layerSz,
uint32_t n_symbs,
c16_t tx_layers[layerSz],
int l);
c16_t tx_layers[][layerSz]);
/*! \brief Perform NR layer mapping. TS 38.211 V15.4.0 subclause 7.3.1.3
@param[in] ulsch_ue, double Pointer to NR_UE_ULSCH_t struct
......@@ -136,12 +135,10 @@ void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms,
c16_t nr_layer_precoder(int sz, c16_t datatx_F_precoding[][sz], const char *prec_matrix, uint8_t n_layers, int32_t re_offset);
c16_t nr_layer_precoder_cm(int n_layers,
int n_symbols,
int symSz,
c16_t datatx_F_precoding[n_layers][n_symbols][symSz],
c16_t datatx_F_precoding[n_layers][symSz],
int ap,
nfapi_nr_pm_pdu_t *pmi_pdu,
int symbol,
int offset);
/*! \brief Precoding with SIMDe, txdataF_precoded[] = prec_matrix[] * txdataF_res_mapped[]
......@@ -151,13 +148,11 @@ c16_t nr_layer_precoder_cm(int n_layers,
@param[out] txdataF_precoded Precoded antenna data
*/
void nr_layer_precoder_simd(const int n_layers,
const int n_symbols,
const int symSz,
const c16_t txdataF_res_mapped[n_layers][n_symbols][symSz],
const int ant,
const nfapi_nr_pm_pdu_t *pmi_pdu,
const int symbol,
const int sc_offset,
const int re_cnt,
c16_t *txdataF_precoded);
const int symSz,
const c16_t txdataF_res_mapped[n_layers][symSz],
const int ant,
const nfapi_nr_pm_pdu_t *pmi_pdu,
const int sc_offset,
const int re_cnt,
c16_t *txdataF_precoded);
#endif
......@@ -99,7 +99,7 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
if (dci_pdu->RNTI != 0xFFFF)
LOG_D(NR_PHY_DCI,
"DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d, "
"reg_mapping %d), Scrambling_Id %d, ScramblingRNTI %x, PayloadSizeBits %d\n",
"reg_mapping %d), Scrambling_Id %d, ScramblingRNTI %x, PayloadSizeBits %d AggregationLevel %d\n",
rb_offset,
n_rb,
dmrs_length,
......@@ -108,7 +108,8 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
pdcch_pdu_rel15->CceRegMappingType,
dci_pdu->ScramblingId,
dci_pdu->ScramblingRNTI,
dci_pdu->PayloadSizeBits);
dci_pdu->PayloadSizeBits,
dci_pdu->AggregationLevel);
dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset
/// DMRS QPSK modulation
......@@ -162,7 +163,7 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] );
#endif
/// QPSK modulation
c16_t mod_dci[NR_MAX_DCI_SIZE >> 2] __attribute__((aligned(16)));
c16_t mod_dci[NR_MAX_DCI_SIZE / 2] __attribute__((aligned(16)));
nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, (int16_t *)mod_dci); // Qm = 2 as DMRS is QPSK modulated
#ifdef DEBUG_DCI
......@@ -248,9 +249,11 @@ void nr_generate_dci_top(processingData_L1tx_t *msgTx, int slot, int txdataF_off
{
PHY_VARS_gNB *gNB = msgTx->gNB;
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
start_meas(&gNB->dci_generation_stats);
for (int i = 0; i < msgTx->num_ul_pdcch; i++)
nr_generate_dci(msgTx->gNB, &msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, frame_parms, slot);
for (int i = 0; i < msgTx->num_dl_pdcch; i++)
nr_generate_dci(msgTx->gNB, &msgTx->pdcch_pdu[i].pdcch_pdu_rel15, txdataF_offset, frame_parms, slot);
stop_meas(&gNB->dci_generation_stats);
}
This diff is collapsed.
......@@ -520,6 +520,8 @@ typedef struct PHY_VARS_gNB_s {
time_stats_t dlsch_interleaving_stats;
time_stats_t dlsch_segmentation_stats;
time_stats_t dci_generation_stats;
time_stats_t phase_comp_stats;
time_stats_t rx_pusch_stats;
time_stats_t rx_pusch_init_stats;
time_stats_t rx_pusch_symbol_processing_stats;
......
......@@ -395,7 +395,7 @@ void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) {
void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu)
{
frame_structure_t fs = {.is_tdd = true};
frame_structure_t fs = {.frame_type = TDD};
fs.numb_slots_frame = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
fs.numb_period_frame = get_nb_periods_per_frame(gNB->gNB_config.tdd_table.tdd_period.value);
fs.numb_slots_period = fs.numb_slots_frame / fs.numb_period_frame;
......
......@@ -290,6 +290,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
//apply the OFDM symbol rotation here
if (gNB->phase_comp) {
start_meas(&gNB->phase_comp_stats);
for(int i = 0; i < gNB->common_vars.num_beams_period; ++i) {
for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) {
apply_nr_rotation_TX(fp,
......@@ -304,6 +305,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
T_INT(aa), T_BUFFER(&gNB->common_vars.txdataF[aa][txdataF_offset], fp->samples_per_slot_wCP*sizeof(int32_t)));
}
}
stop_meas(&gNB->phase_comp_stats);
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 0);
......
......@@ -44,14 +44,8 @@ int nr_ue_slot_select(const fapi_nr_config_request_t *cfg, int nr_slot)
if (cfg->cell_config.frame_duplex_type == FDD)
return NR_UPLINK_SLOT | NR_DOWNLINK_SLOT;
int period = cfg->tdd_table_1.tdd_period_in_slots +
(cfg->tdd_table_2 ? cfg->tdd_table_2->tdd_period_in_slots : 0);
int rel_slot = nr_slot % period;
const fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table_1;
if (cfg->tdd_table_2 && rel_slot >= tdd_table->tdd_period_in_slots) {
rel_slot -= tdd_table->tdd_period_in_slots;
tdd_table = cfg->tdd_table_2;
}
const fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table;
int rel_slot = nr_slot % tdd_table->tdd_period_in_slots;
if (tdd_table->max_tdd_periodicity_list == NULL) // this happens before receiving TDD configuration
return NR_DOWNLINK_SLOT;
......
......@@ -647,7 +647,11 @@ printf("%d\n", slot);
frame_structure_t frame_structure = {0};
frame_type_t frame_type = TDD;
config_frame_structure(mu, scc, get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon), frame_type, &frame_structure);
config_frame_structure(mu,
scc->tdd_UL_DL_ConfigurationCommon,
get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon),
frame_type,
&frame_structure);
AssertFatal(is_dl_slot(slot, &frame_structure), "The slot selected is not DL. Can't run DLSIM\n");
// TODO do a UECAP for phy-sim
......@@ -671,7 +675,8 @@ printf("%d\n", slot);
.timer_config.n310 = 10,
.timer_config.t311 = 3000,
.timer_config.n311 = 1,
.timer_config.t319 = 400};
.timer_config.t319 = 400,
.num_agg_level_candidates = {0, 0, 1, 1, 0}};
RC.nb_nr_macrlc_inst = 1;
RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
......@@ -858,7 +863,7 @@ printf("%d\n", slot);
nr_l2_init_ue(1);
UE_mac = get_mac_inst(0);
ue_init_config_request(UE_mac, mu);
ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu));
UE->if_inst = nr_ue_if_module_init(0);
UE->if_inst->scheduled_response = nr_ue_scheduled_response;
......@@ -960,10 +965,12 @@ printf("%d\n", slot);
reset_meas(&gNB->dlsch_segmentation_stats);
reset_meas(&gNB->dlsch_modulation_stats);
reset_meas(&gNB->dlsch_encoding_stats);
reset_meas(&gNB->dci_generation_stats);
reset_meas(&gNB->tinput);
reset_meas(&gNB->tprep);
reset_meas(&gNB->tparity);
reset_meas(&gNB->toutput);
reset_meas(&gNB->phase_comp_stats);
uint32_t errors_scrambling[16] = {0};
int n_errors[16] = {0};
......@@ -1259,6 +1266,7 @@ printf("%d\n", slot);
UE->dl_harq_processes[0][slot].C,
msgDataTx->dlsch[0][0].harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0] << 3);
printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
printStatIndent2(&gNB->dci_generation_stats, "DCI encoding time");
printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
printStatIndent3(&gNB->tinput,"DLSCH LDPC input processing time");
......@@ -1269,8 +1277,9 @@ printf("%d\n", slot);
printStatIndent3(&gNB->dlsch_interleaving_stats, "DLSCH Interleaving time");
printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time");
printStatIndent2(&gNB->dlsch_scrambling_stats, "DLSCH scrambling time");
printStatIndent2(&gNB->dlsch_resource_mapping_stats, "DLSCH Resource Mapping time");
printStatIndent2(&gNB->dlsch_precoding_stats,"DLSCH Layer Precoding time");
printStatIndent2(&gNB->dlsch_precoding_stats,"DLSCH Mapping/Precoding time");
if (gNB->phase_comp)
printStatIndent2(&gNB->phase_comp_stats, "Phase Compensation");
printf("\nUE function statistics (per %d us slot)\n", 1000 >> *scc->ssbSubcarrierSpacing);
for (int i = RX_PDSCH_STATS; i <= DLSCH_PROCEDURES_STATS; i++) {
......
......@@ -628,7 +628,11 @@ int main(int argc, char *argv[])
frame_structure_t frame_structure = {0};
frame_type_t frame_type = TDD;
config_frame_structure(mu, scc, get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon), frame_type, &frame_structure);
config_frame_structure(mu,
scc->tdd_UL_DL_ConfigurationCommon,
get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon),
frame_type,
&frame_structure);
AssertFatal(is_ul_slot(slot, &frame_structure), "The slot selected is not UL. Can't run ULSIM\n");
// TODO do a UECAP for phy-sim
......@@ -737,7 +741,7 @@ int main(int argc, char *argv[])
nr_l2_init_ue(1);
NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0);
ue_init_config_request(UE_mac, mu);
ue_init_config_request(UE_mac, get_slots_per_frame_from_scs(mu));
UE->if_inst = nr_ue_if_module_init(0);
UE->if_inst->scheduled_response = nr_ue_scheduled_response;
......
......@@ -477,9 +477,11 @@ typedef struct {
} nr_mac_rrc_config_mib_t;
typedef struct {
NR_SIB1_t *sib1;
bool can_start_ra;
} nr_mac_rrc_config_sib1_t;
typedef struct {
NR_SIB19_r17_t *sib19;
bool can_start_ra;
} nr_mac_rrc_config_other_sib_t;
#endif /* RRC_MESSAGES_TYPES_H_ */
......@@ -169,7 +169,7 @@ static void fill_rc_report(ran_func_def_report_t* report)
// Mandatory
// 9.3.8
// [1- 4294967295]
report_style->ran_param[0].id = RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID;
report_style->ran_param[0].id = E2SM_RC_RS4_RRC_STATE_CHANGED_TO;
// RAN Parameter Name
// Mandatory
......@@ -476,14 +476,11 @@ void read_rc_setup_sm(void* data)
DevAssert(ret == 0);
}
RB_PROTOTYPE(ric_id_2_param_id_trees, ric_req_id_s, entries, cmp_ric_req_id);
static seq_ran_param_t fill_rrc_state_change_seq_ran(const rc_sm_rrc_state_e rrc_state)
{
seq_ran_param_t seq_ran_param = {0};
seq_ran_param.ran_param_id = RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID;
seq_ran_param.ran_param_id = E2SM_RC_RS4_RRC_STATE_CHANGED_TO;
seq_ran_param.ran_param_val.type = ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE;
seq_ran_param.ran_param_val.flag_false = calloc(1, sizeof(ran_parameter_value_t));
assert(seq_ran_param.ran_param_val.flag_false != NULL && "Memory exhausted");
......@@ -528,23 +525,40 @@ static rc_ind_data_t* fill_ue_rrc_state_change(const gNB_RRC_UE_t *rrc_ue_contex
return rc_ind;
}
static void send_aper_ric_ind(const uint32_t ric_req_id, rc_ind_data_t* rc_ind_data)
{
async_event_agent_api(ric_req_id, rc_ind_data);
printf("[E2 AGENT] Event for RIC request ID %d generated\n", ric_req_id);
}
static void check_rrc_state(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state, const uint32_t ric_req_id, const e2sm_rc_ev_trg_frmt_4_t *frmt_4)
{
for (size_t i = 0; i < frmt_4->sz_ue_info_chng; i++) {
const rrc_state_lst_t *rrc_elem = &frmt_4->ue_info_chng[i].rrc_state;
for (size_t j = 0; j < rrc_elem->sz_rrc_state; j++) {
const rrc_state_e2sm_rc_e ev_tr_rrc_state = rrc_elem->state_chng_to[j].state_chngd_to;
if (ev_tr_rrc_state == (rrc_state_e2sm_rc_e)rrc_state || ev_tr_rrc_state == ANY_RRC_STATE_E2SM_RC) {
rc_ind_data_t* rc_ind_data = fill_ue_rrc_state_change(rrc_ue_context, rrc_state);
send_aper_ric_ind(ric_req_id, rc_ind_data);
}
}
}
}
void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state)
{
{
pthread_mutex_lock(&rc_mutex);
if (rc_subs_data.rb[RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID].rbh_root == NULL) {
if (rc_subs_data.rs4_param202.data == NULL) {
pthread_mutex_unlock(&rc_mutex);
return;
}
struct ric_req_id_s *node;
RB_FOREACH(node, ric_id_2_param_id_trees, &rc_subs_data.rb[RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID]) {
rc_ind_data_t* rc_ind_data = fill_ue_rrc_state_change(rrc_ue_context, rrc_state);
// Needs review: memory ownership of the type rc_ind_data_t is transferred to the E2 Agent. Bad
async_event_agent_api(node->ric_req_id, rc_ind_data);
printf( "Event for RIC Req ID %u generated\n", node->ric_req_id);
const size_t num_subs = seq_arr_size(&rc_subs_data.rs4_param202);
for (size_t sub_idx = 0; sub_idx < num_subs; sub_idx++) {
const ran_param_data_t data = *(const ran_param_data_t *)seq_arr_at(&rc_subs_data.rs4_param202, sub_idx);
check_rrc_state(rrc_ue_context, rrc_state, data.ric_req_id, &data.ev_tr.frmt_4);
}
pthread_mutex_unlock(&rc_mutex);
}
......@@ -553,38 +567,65 @@ static void free_aperiodic_subscription(uint32_t ric_req_id)
remove_rc_subs_data(&rc_subs_data, ric_req_id);
}
static seq_arr_t *get_sa(const e2sm_rc_event_trigger_t *ev_tr, const uint32_t ran_param_id)
{
seq_arr_t *sa = NULL;
switch (ev_tr->format) {
case FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT:
if (ran_param_id == E2SM_RC_RS4_RRC_STATE_CHANGED_TO) {
sa = &rc_subs_data.rs4_param202;
}
break;
default:
printf("[E2 AGENT] RC REPORT Style %d not yet implemented.\n", ev_tr->format + 1);
break;
}
return sa;
}
static void get_list_for_report_style(const uint32_t ric_req_id, const e2sm_rc_event_trigger_t *ev_tr, const size_t sz, const param_report_def_t *param_def)
{
for (size_t i = 0; i < sz; i++) {
seq_arr_t *sa = get_sa(ev_tr, param_def[i].ran_param_id);
if (!sa) {
printf("[E2 AGENT] Requested RAN Parameter ID %d not yet implemented", param_def[i].ran_param_id);
} else {
struct ran_param_data data = { .ric_req_id = ric_req_id, .ev_tr = cp_e2sm_rc_event_trigger(ev_tr) };
insert_rc_subs_data(sa, &data);
}
}
}
sm_ag_if_ans_t write_subs_rc_sm(void const* src)
{
assert(src != NULL); // && src->type == RAN_CTRL_SUBS_V1_03);
wr_rc_sub_data_t* wr_rc = (wr_rc_sub_data_t*)src;
assert(wr_rc->rc.ad != NULL && "Cannot be NULL");
sm_ag_if_ans_t ans = {0};
const uint32_t ric_req_id = wr_rc->ric_req_id;
const uint32_t report_style = wr_rc->rc.ad->ric_style_type;
// 9.2.1.2 RIC ACTION DEFINITION IE
switch (wr_rc->rc.ad->format) {
case FORMAT_1_E2SM_RC_ACT_DEF: {
case FORMAT_1_E2SM_RC_ACT_DEF: { // for all REPORT styles
// Parameters to be Reported List
// [1-65535]
const uint32_t ric_req_id = wr_rc->ric_req_id;
arr_ran_param_id_t* arr_ran_param_id = calloc(1, sizeof(arr_ran_param_id_t));
assert(arr_ran_param_id != NULL && "Memory exhausted");
arr_ran_param_id->len = wr_rc->rc.ad->frmt_1.sz_param_report_def;
arr_ran_param_id->ran_param_id = calloc(arr_ran_param_id->len, sizeof(ran_param_id_e));
const size_t sz = arr_ran_param_id->len;
for(size_t i = 0; i < sz; i++) {
arr_ran_param_id->ran_param_id[i] = wr_rc->rc.ad->frmt_1.param_report_def[i].ran_param_id;
if (wr_rc->rc.et.format + 1 != report_style) { // wr_rc->rc.et.format is an enum -> initialization starts from 0
AssertError(false, return ans, "[E2 AGENT] Event Trigger Definition Format %d doesn't correspond to REPORT style %d.\n", wr_rc->rc.et.format + 1, report_style);
}
insert_rc_subs_data(&rc_subs_data, ric_req_id, arr_ran_param_id);
get_list_for_report_style(ric_req_id, &wr_rc->rc.et, wr_rc->rc.ad->frmt_1.sz_param_report_def, wr_rc->rc.ad->frmt_1.param_report_def);
break;
}
default:
AssertFatal(wr_rc->rc.ad->format == FORMAT_1_E2SM_RC_ACT_DEF, "Action Definition Format %d not yet implemented", wr_rc->rc.ad->format);
AssertError(wr_rc->rc.ad->format == FORMAT_1_E2SM_RC_ACT_DEF, return ans, "[E2 AGENT] Action Definition Format %d not yet implemented", wr_rc->rc.ad->format + 1);
}
sm_ag_if_ans_t ans = {.type = SUBS_OUTCOME_SM_AG_IF_ANS_V0};
ans.type = SUBS_OUTCOME_SM_AG_IF_ANS_V0;
ans.subs_out.type = APERIODIC_SUBSCRIPTION_FLRC;
ans.subs_out.aper.free_aper_subs = free_aperiodic_subscription;
......
......@@ -21,6 +21,7 @@
#include "ran_func_rc_subs.h"
#include "common/utils/assertions.h"
#include "common/utils/alg/find.h"
#include <assert.h>
#include <pthread.h>
......@@ -29,86 +30,36 @@
static pthread_mutex_t rc_mutex = PTHREAD_MUTEX_INITIALIZER;
int cmp_ric_req_id(struct ric_req_id_s *c1, struct ric_req_id_s *c2)
static bool eq_int(const void* value, const void* it)
{
if (c1->ric_req_id < c2->ric_req_id)
return -1;
if (c1->ric_req_id > c2->ric_req_id)
return 1;
return 0;
const uint32_t ric_req_id = *(uint32_t *)value;
const ran_param_data_t *dit = (const ran_param_data_t *)it;
return ric_req_id == dit->ric_req_id;
}
RB_GENERATE(ric_id_2_param_id_trees, ric_req_id_s, entries, cmp_ric_req_id);
void init_rc_subs_data(rc_subs_data_t* rc_subs_data)
void init_rc_subs_data(rc_subs_data_t *rc_subs_data)
{
pthread_mutex_lock(&rc_mutex);
// Initialize hash table
DevAssert(rc_subs_data->htable == NULL);
// Initialize RB trees
// 1 RB tree = 1 ran_param_id => many ric_req_id(s)
for (size_t i = 0; i < END_E2SM_RC_RAN_PARAM_ID; i++) {
RB_INIT(&rc_subs_data->rb[i]);
}
rc_subs_data->htable = hashtable_create(MAX_NUM_RIC_REQ_ID, NULL, free);
assert(rc_subs_data->htable != NULL && "Memory exhausted");
// Initialize sequence array
seq_arr_init(&rc_subs_data->rs4_param202, sizeof(ran_param_data_t));
pthread_mutex_unlock(&rc_mutex);
}
void insert_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id, arr_ran_param_id_t* arr_ran_param_id)
void insert_rc_subs_data(seq_arr_t *seq_arr, ran_param_data_t *data)
{
pthread_mutex_lock(&rc_mutex);
// Insert in hash table
DevAssert(rc_subs_data->htable != NULL);
uint64_t key = ric_req_id;
// Check if the subscription already exists
AssertFatal(hashtable_is_key_exists(rc_subs_data->htable, key) == HASH_TABLE_KEY_NOT_EXISTS, "RIC req ID %d already subscribed", ric_req_id);
arr_ran_param_id_t* data = malloc(sizeof(*data));
assert(data != NULL);
*data = *arr_ran_param_id;
hashtable_rc_t ret = hashtable_insert(rc_subs_data->htable, key, data);
assert(ret == HASH_TABLE_OK && "Hash table not ok");
// Insert in RB trees
// 1 RB tree = 1 ran_param_id => many ric_req_id(s)
const size_t sz = arr_ran_param_id->len;
rb_ric_req_id_t *node = calloc(1, sizeof(*node));
assert(node != NULL);
node->ric_req_id = ric_req_id;
for (size_t i = 0; i < sz; i++) {
RB_INSERT(ric_id_2_param_id_trees, &rc_subs_data->rb[arr_ran_param_id->ran_param_id[i]], node);
}
// Insert (RIC request ID + Event Trigger Definition) in specific RAN Parameter ID sequence
seq_arr_push_back(seq_arr, data, sizeof(*data));
pthread_mutex_unlock(&rc_mutex);
}
void remove_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id)
void remove_rc_subs_data(rc_subs_data_t *rc_subs_data, uint32_t ric_req_id)
{
pthread_mutex_lock(&rc_mutex);
DevAssert(rc_subs_data->htable != NULL);
uint64_t key = ric_req_id;
// Get the array of ran_param_id(s)
void *data = NULL;
hashtable_rc_t ret = hashtable_get(rc_subs_data->htable, key, &data);
AssertFatal(ret == HASH_TABLE_OK && data != NULL, "element for ue_id %d not found\n", ric_req_id);
arr_ran_param_id_t arr_ran_param_id = *(arr_ran_param_id_t *)data;
// Remove ric_req_id with its ran_param_id(s) from hash table
ret = hashtable_remove(rc_subs_data->htable, key);
// Remove ric_req_id from each ran_param_id tree where subscribed
rb_ric_req_id_t *node = calloc(1, sizeof(*node));
assert(node != NULL);
node->ric_req_id = ric_req_id;
for (size_t i = 0; i < arr_ran_param_id.len; i++) {
RB_REMOVE(ric_id_2_param_id_trees, &rc_subs_data->rb[arr_ran_param_id.ran_param_id[i]], node);
}
/* find the sequence element that matches RIC request ID */
elm_arr_t elm = find_if(&rc_subs_data->rs4_param202, (void *)&ric_req_id, eq_int);
ran_param_data_t *data = elm.it;
free_e2sm_rc_event_trigger(&data->ev_tr);
seq_arr_erase(&rc_subs_data->rs4_param202, elm.it);
pthread_mutex_unlock(&rc_mutex);
}
......@@ -22,35 +22,74 @@
#ifndef RAN_FUNC_SM_RAN_CTRL_SUBSCRIPTION_AGENT_H
#define RAN_FUNC_SM_RAN_CTRL_SUBSCRIPTION_AGENT_H
#include "common/utils/hashtable/hashtable.h"
#include "common/utils/collection/tree.h"
#include "openair2/E2AP/flexric/src/sm/rc_sm/ie/rc_data_ie.h"
#include "common/utils/ds/seq_arr.h"
typedef enum {
RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID = 202, // 8.2.4 RAN Parameters for Report Service Style 4
typedef enum { // 8.2.1 RAN Parameters for Report Service Style 1
E2SM_RC_RS1_UE_EVENT_ID = 1,
E2SM_RC_RS1_NI_MESSAGE = 2,
E2SM_RC_RS1_RRC_MESSAGE = 3,
E2SM_RC_RS1_UE_ID = 4,
E2SM_RC_RS1_OLD_AMF_UE_NGAP_ID = 5,
E2SM_RC_RS1_CELL_GLOBAL_ID = 6,
END_E2SM_RC_RAN_PARAM_ID
} ran_param_id_e;
END_E2SM_RC_RS1_RAN_PARAM_ID
} report_style_1_ran_param_id_e;
typedef struct{
size_t len;
ran_param_id_e* ran_param_id;
} arr_ran_param_id_t;
typedef enum { // 8.2.2 RAN Parameters for Report Service Style 2
E2SM_RC_RS2_CURRENT_UE_ID = 1,
E2SM_RC_RS2_OLD_UE_ID = 2,
E2SM_RC_RS2_CURRENT_RRC_STATE = 3,
E2SM_RC_RS2_OLD_RRC_STATE = 4,
E2SM_RC_RS2_UE_CONTEXT_INFORMATION_CONTAINER = 5,
E2SM_RC_RS2_CELL_GLOBAL_ID = 6,
E2SM_RC_RS2_UE_INFORMATION = 7,
typedef struct ric_req_id_s {
RB_ENTRY(ric_req_id_s) entries;
END_E2SM_RC_RS2_RAN_PARAM_ID
} report_style_2_ran_param_id_e;
typedef enum { // 8.2.3 RAN Parameters for Report Service Style 3
E2SM_RC_RS3_CELL_CONTEXT_INFORMATION = 1,
E2SM_RC_RS3_CELL_DELETED = 2,
E2SM_RC_RS3_NEIGHBOUR_RELATION_TABLE = 3,
END_E2SM_RC_RS3_RAN_PARAM_ID
} report_style_3_ran_param_id_e;
typedef enum { // 8.2.4 RAN Parameters for Report Service Style 4
E2SM_RC_RS4_UL_MAC_CE = 100,
E2SM_RC_RS4_DL_MAC_CE = 101,
E2SM_RC_RS4_DL_BUFFER_OCCUPANCY = 102,
E2SM_RC_RS4_CURRENT_RRC_STATE = 201,
E2SM_RC_RS4_RRC_STATE_CHANGED_TO = 202,
E2SM_RC_RS4_RRC_MESSAGE = 203,
E2SM_RC_RS4_OLD_UE_ID = 300,
E2SM_RC_RS4_CURRENT_UE_ID = 301,
E2SM_RC_RS4_NI_MESSAGE = 302,
E2SM_RC_RS4_CELL_GLOBAL_ID = 400,
END_E2SM_RC_RS4_RAN_PARAM_ID
} report_style_4_ran_param_id_e;
typedef enum { // 8.2.5 RAN Parameters for Report Service Style 5
E2SM_RC_RS5_UE_CONTEXT_INFORMATION = 1,
E2SM_RC_RS5_CELL_CONTEXT_INFORMATION = 2,
E2SM_RC_RS5_NEIGHBOUR_RELATION_TABLE = 3,
END_E2SM_RC_RS5_RAN_PARAM_ID
} report_style_5_ran_param_id_e;
typedef struct ran_param_data {
uint32_t ric_req_id;
} rb_ric_req_id_t;
e2sm_rc_event_trigger_t ev_tr;
} ran_param_data_t;
typedef struct {
RB_HEAD(ric_id_2_param_id_trees, ric_req_id_s) rb[END_E2SM_RC_RAN_PARAM_ID]; // 1 RB tree = (1 RAN Parameter ID) : (n RIC Request ID) => m RB tree = (m RAN Parameter ID) : (n RIC Request ID)
hash_table_t* htable; // 1 Hash table = (n RIC Request ID) : (m RAN Parameter ID)
seq_arr_t rs4_param202; // E2SM_RC_RS4_RRC_STATE_CHANGED_TO
} rc_subs_data_t;
int cmp_ric_req_id(struct ric_req_id_s *c1, struct ric_req_id_s *c2);
void init_rc_subs_data(rc_subs_data_t* rc_subs_data);
void insert_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id, arr_ran_param_id_t* arr_ran_param_id);
void remove_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id);
void init_rc_subs_data(rc_subs_data_t *rc_subs_data);
void insert_rc_subs_data(seq_arr_t *seq_arr, ran_param_data_t *data);
void remove_rc_subs_data(rc_subs_data_t *rc_subs_data, uint32_t ric_req_id);
#endif
......@@ -132,6 +132,7 @@
#define GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VY "velocityVY-r17"
#define GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VZ "velocityVZ-r17"
#define GNB_CONFIG_STRING_TA_COMMON "ta-Common-r17"
#define GNB_CONFIG_STRING_TA_COMMONDRIFT "ta-CommonDrift-r17"
#define CARRIERBANDWIDTH_OKVALUES {11,18,24,25,31,32,38,51,52,65,66,78,79,93,106,107,121,132,133,135,160,162,189,216,217,245,264,270,273}
......@@ -257,6 +258,7 @@
{GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VY,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVY_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \
{GNB_CONFIG_STRING_EPHEMERIS_VELOCITY_VZ,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->velocityVZ_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \
{GNB_CONFIG_STRING_TA_COMMON,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17,.defint64val=-1,TYPE_INT64,0}, \
{GNB_CONFIG_STRING_TA_COMMONDRIFT,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17,.defint64val=0,TYPE_INT64,0}, \
{GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,.defintval=-1,TYPE_INT64,0}}
#define SCC_PATTERN2_STRING_CONFIG "pattern2"
......
......@@ -185,6 +185,7 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc)
scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17));
scc->ext2->ntn_Config_r17->ta_Info_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17));
scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17));
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_positionVelocity_r17;
scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 =
......@@ -528,7 +529,12 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap)
free(scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17);
scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = NULL;
}
if (*scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 == 0) {
free(scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17);
scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17 = NULL;
}
if (scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17 == -1) {
free(scc->ext2->ntn_Config_r17->ta_Info_r17->ta_CommonDrift_r17);
free(scc->ext2->ntn_Config_r17->ta_Info_r17);
scc->ext2->ntn_Config_r17->ta_Info_r17 = NULL;
}
......@@ -1129,11 +1135,25 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf
AssertFatal(pcc != NULL && pcc->commonSearchSpaceList == NULL, "memory leak\n");
pcc->commonSearchSpaceList = calloc_or_fail(1, sizeof(*pcc->commonSearchSpaceList));
NR_SearchSpace_t *ss1 = rrc_searchspace_config(true, 1, 0);
// TODO: Make CSS aggregation levels configurable
int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
css_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
if (get_softmodem_params()->usim_test) {
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_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_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
}
css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
NR_SearchSpace_t *ss1 = rrc_searchspace_config(true, 1, 0, css_num_agg_level_candidates);
asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss1);
NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, 2, 0);
NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, 2, 0, css_num_agg_level_candidates);
asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss2);
NR_SearchSpace_t *ss3 = rrc_searchspace_config(true, 3, 0);
NR_SearchSpace_t *ss3 = rrc_searchspace_config(true, 3, 0, css_num_agg_level_candidates);
asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss3);
asn1cCallocOne(pcc->searchSpaceSIB1, 0);
......@@ -1501,6 +1521,34 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
}
}
// Construct default aggragation level list or read from config
int uess_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
if (get_softmodem_params()->usim_test) {
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1;
} else {
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n2;
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n0;
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
}
uess_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
int* agg_level_list = uess_num_agg_level_candidates;
int num_agg_levels = 5;
if (GNBParamList.paramarray[0][GNB_UESS_AGG_LEVEL_LIST_IDX].numelt > 0) {
agg_level_list = GNBParamList.paramarray[0][GNB_UESS_AGG_LEVEL_LIST_IDX].iptr;
num_agg_levels = GNBParamList.paramarray[0][GNB_UESS_AGG_LEVEL_LIST_IDX].numelt;
}
memcpy(config.num_agg_level_candidates, agg_level_list, sizeof(int) * num_agg_levels);
LOG_I(NR_MAC,
"Candidates per PDCCH aggregation level on UESS: L1: %d, L2: %d, L4: %d, L8: %d, L16: %d\n",
config.num_agg_level_candidates[PDCCH_AGG_LEVEL1],
config.num_agg_level_candidates[PDCCH_AGG_LEVEL2],
config.num_agg_level_candidates[PDCCH_AGG_LEVEL4],
config.num_agg_level_candidates[PDCCH_AGG_LEVEL8],
config.num_agg_level_candidates[PDCCH_AGG_LEVEL16]);
NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME);
//xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc);
NR_ServingCellConfig_t *scd = get_scd_config(cfg);
......
......@@ -138,6 +138,7 @@ typedef enum {
#define GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES "num_dlharq"
#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_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n"
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
......@@ -148,6 +149,7 @@ typedef enum {
#define GNB_CONFIG_HLP_GNB_CU_UP_ID "defines the gNB-CU-UP ID (only applicable for CU-UP)"
#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"
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* cell configuration parameters */
......@@ -191,6 +193,8 @@ typedef enum {
{GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES, GNB_CONFIG_HLP_NUM_DL_HARQ, 0, .iptr=NULL, .defintval=16, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES, GNB_CONFIG_HLP_NUM_UL_HARQ, 0, .iptr=NULL, .defintval=16, TYPE_INT, 0}, \
{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}, \
}
// clang-format on
......@@ -231,6 +235,7 @@ typedef enum {
#define GNB_NUM_DL_HARQ_IDX 33
#define GNB_NUM_UL_HARQ_IDX 34
#define GNB_BEAMWEIGHTS_IDX 35
#define GNB_UESS_AGG_LEVEL_LIST_IDX 36
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32}
......@@ -273,6 +278,7 @@ typedef enum {
{ .s1 = { config_check_intval, NUM_DL_HARQ_OKVALUES,8 } }, \
{ .s1 = { config_check_intval, NUM_UL_HARQ_OKVALUES,2 } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
......
......@@ -76,8 +76,6 @@ static const uint16_t symbol_ssb_E[64] = {8, 12, 16, 20, 32, 36, 40, 44,
288, 292, 296, 300, 312, 316, 320, 324, 344, 348, 352, 356, 368, 372, 376, 380,
400, 404, 408, 412, 424, 428, 432, 436, 456, 460, 464, 468, 480, 484, 488, 492};
const uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160};
// Table 6.3.3.1-5 (38.211) NCS for preamble formats with delta_f_RA = 1.25 KHz
static const uint16_t NCS_unrestricted_delta_f_RA_125[16] = {0, 13, 15, 18, 22, 26, 32, 38, 46, 59, 76, 93, 119, 167, 279, 419};
static const uint16_t NCS_restricted_TypeA_delta_f_RA_125[15] =
......@@ -3555,73 +3553,6 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrec
}
}
static const int tdd_period_to_num[8] = {500, 625, 1000, 1250, 2000, 2500, 5000, 10000};
bool is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slot)
{
if (tdd_UL_DL_ConfigurationCommon == NULL)
return true;
int period1, period2 = 0;
if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)
period1 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period1 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity];
if (tdd_UL_DL_ConfigurationCommon->pattern2) {
if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)
period2 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity];
}
int period = period1+period2;
int scs = tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing;
int slots = period * (1 << scs) / 1000;
int slots1 = period1 * (1 << scs) / 1000;
int slot_in_period = slot % slots;
if (slot_in_period < slots1)
return slot_in_period <= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
else
return slot_in_period <= slots1 + tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots;
}
bool is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slot, frame_type_t frame_type)
{
// Note: condition on frame_type
// goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work
if (frame_type == FDD)
return true;
if (tdd_UL_DL_ConfigurationCommon == NULL)
// before receiving TDD information all slots should be considered to be DL
return false;
int period1, period2 = 0;
if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)
period1 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period1 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity];
if (tdd_UL_DL_ConfigurationCommon->pattern2) {
if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 &&
tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)
period2 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530;
else
period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity];
}
int period = period1+period2;
int scs = tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing;
int slots = period * (1 << scs) / 1000;
int slots1 = period1 * (1 << scs) / 1000;
int slot_in_period = slot % slots;
if (slot_in_period < slots1)
return slot_in_period >= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
else
return slot_in_period >= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots;
}
int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,
int dci_format,
int dmrs_TypeA_Position,
......@@ -4198,6 +4129,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
// 38.213 table 10.1-1
/// MUX PATTERN 1
int slots_per_frame = get_slots_per_frame_from_scs(scs_ssb);
if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR1){
big_o = table_38213_13_11_c1[index_4lsb];
big_m = table_38213_13_11_c3[index_4lsb];
......@@ -4214,7 +4146,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
// 38.213 chapter 13: over two consecutive slots
type0_PDCCH_CSS_config->search_space_duration = 2;
// two frames
type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1;
type0_PDCCH_CSS_config->search_space_frame_period = slots_per_frame << 1;
}
if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){
......@@ -4235,7 +4167,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
// 38.213 chapter 13: over two consecutive slots
type0_PDCCH_CSS_config->search_space_duration = 2;
// two frames
type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1;
type0_PDCCH_CSS_config->search_space_frame_period = slots_per_frame << 1;
}
/// MUX PATTERN 2
......@@ -4302,7 +4234,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
// 38.213 chapter 13: over one slot
type0_PDCCH_CSS_config->search_space_duration = 1;
// SSB periodicity in slots
type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb];
type0_PDCCH_CSS_config->search_space_frame_period = ssb_period * slots_per_frame;
}
/// MUX PATTERN 3
......@@ -4332,7 +4264,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD
// 38.213 chapter 13: over one slot
type0_PDCCH_CSS_config->search_space_duration = 1;
// SSB periodicity in slots
type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb];
type0_PDCCH_CSS_config->search_space_frame_period = ssb_period * slots_per_frame;
}
AssertFatal(type0_PDCCH_CSS_config->sfn_c >= 0, "");
......@@ -4392,9 +4324,7 @@ void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_conf
coreset0->pdcch_DMRS_ScramblingID = NULL;
}
void fill_searchSpaceZero(NR_SearchSpace_t *ss0,
int slots_per_frame,
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config)
void fill_searchSpaceZero(NR_SearchSpace_t *ss0, int slots_per_frame, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config)
{
AssertFatal(ss0, "SearchSpace0 should have been allocated outside of this function\n");
if(ss0->controlResourceSetId == NULL)
......
......@@ -63,10 +63,16 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,
int startSymbol,
mappingType_t mappingtype,
int length);
bool is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP);
bool is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP, frame_type_t frame_type);
int get_slots_per_frame_from_scs(int scs);
bool is_ul_slot(const slot_t slot, const frame_structure_t *fs);
bool is_dl_slot(const slot_t slot, const frame_structure_t *fs);
bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs);
int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd);
void config_frame_structure(int mu,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
uint8_t tdd_period,
uint8_t frame_type,
frame_structure_t *fs);
uint8_t compute_srs_resource_indicator(long *maxMIMO_Layers,
NR_PUSCH_Config_t *pusch_Config,
......
/*
* 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 "nr_mac_common.h"
#include "common/utils/nr/nr_common.h"
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h"
int get_slots_per_frame_from_scs(int scs)
{
const int nr_slots_per_frame[5] = {10, 20, 40, 80, 160};
return nr_slots_per_frame[scs];
}
const float tdd_ms_period_pattern[] = {0.5, 0.625, 1.0, 1.25, 2.0, 2.5, 5.0, 10.0};
const float tdd_ms_period_ext[] = {3.0, 4.0};
/**
* @brief Retrieves the periodicity in milliseconds for the given TDD pattern
* depending on the presence of the extension
* @param pattern Pointer to the NR_TDD_UL_DL_Pattern_t pattern structure
* @return Periodicity value in milliseconds.
*/
static float get_tdd_periodicity(NR_TDD_UL_DL_Pattern_t *pattern)
{
if (!pattern->ext1) {
LOG_D(NR_MAC, "Setting TDD configuration period to dl_UL_TransmissionPeriodicity %ld\n", pattern->dl_UL_TransmissionPeriodicity);
return tdd_ms_period_pattern[pattern->dl_UL_TransmissionPeriodicity];
} else {
DevAssert(pattern->ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL);
LOG_D(NR_MAC,
"Setting TDD configuration period to dl_UL_TransmissionPeriodicity_v1530 %ld\n",
*pattern->ext1->dl_UL_TransmissionPeriodicity_v1530);
return tdd_ms_period_ext[*pattern->ext1->dl_UL_TransmissionPeriodicity_v1530];
}
}
/**
* @brief Determines the TDD period index based on pattern periodicities
* @note Not applicabile to pattern extension
* @param tdd Pointer to the NR_TDD_UL_DL_ConfigCommon_t containing patterns
* @return Index of the TDD period in tdd_ms_period_pattern
*/
int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd)
{
int tdd_period_idx = 0;
float pattern1_ms = get_tdd_periodicity(&tdd->pattern1);
float pattern2_ms = tdd->pattern2 ? get_tdd_periodicity(tdd->pattern2) : 0.0;
bool found_match = false;
// Find matching TDD period in the predefined list of periodicities
for (int i = 0; i < NFAPI_MAX_NUM_PERIODS; i++) {
if ((pattern1_ms + pattern2_ms) == tdd_ms_period_pattern[i]) {
tdd_period_idx = i;
LOG_I(NR_MAC,
"TDD period index = %d, based on the sum of dl_UL_TransmissionPeriodicity "
"from Pattern1 (%f ms) and Pattern2 (%f ms): Total = %f ms\n",
tdd_period_idx,
pattern1_ms,
pattern2_ms,
pattern1_ms + pattern2_ms);
found_match = true;
break;
}
}
// Assert if no match was found
AssertFatal(found_match, "The sum of pattern1_ms and pattern2_ms does not match any value in tdd_ms_period_pattern");
return tdd_period_idx;
}
/**
* @brief Configures the TDD period, including bitmap, in the frame structure
*
* This function sets the TDD period configuration for DL, UL, and mixed slots in
* the specified frame structure instance, according to the given pattern, and
* updates the bitmap.
*
* @param pattern NR_TDD_UL_DL_Pattern_t configuration containing TDD slots and symbols configuration
* @param fs frame_structure_t pointer
* @param curr_total_slot current position in the slot bitmap to start from
*
* @return Number of slots in the configured TDD period
*/
static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot)
{
int8_t n_dl_slot = pattern->nrofDownlinkSlots;
int8_t n_ul_slot = pattern->nrofUplinkSlots;
int8_t n_dl_symbols = pattern->nrofDownlinkSymbols;
int8_t n_ul_symbols = pattern->nrofUplinkSymbols;
// Total slots in the period: if DL/UL symbols are present, is mixed slot
const bool has_mixed_slot = (n_ul_symbols + n_dl_symbols) > 0;
int8_t total_slot = has_mixed_slot ? n_dl_slot + n_ul_slot + 1 : n_dl_slot + n_ul_slot;
/** Update TDD period configuration:
* mixed slots with DL symbols are counted as DL slots
* mixed slots with UL symbols are counted as UL slots */
pc->num_dl_slots += (n_dl_slot + (n_dl_symbols > 0));
pc->num_ul_slots += (n_ul_slot + (n_ul_symbols > 0));
// Populate the slot bitmap for each slot in the TDD period
for (int i = 0; i < total_slot; i++) {
tdd_bitmap_t *bitmap = &pc->tdd_slot_bitmap[i + curr_total_slot];
if (i < n_dl_slot)
bitmap->slot_type = TDD_NR_DOWNLINK_SLOT;
else if ((i == n_dl_slot) && has_mixed_slot) {
bitmap->slot_type = TDD_NR_MIXED_SLOT;
bitmap->num_dl_symbols = n_dl_symbols;
bitmap->num_ul_symbols = n_ul_symbols;
} else if (n_ul_slot)
bitmap->slot_type = TDD_NR_UPLINK_SLOT;
}
LOG_I(NR_MAC,
"Set TDD configuration period to: %d DL slots, %d UL slots, %d slots per period (NR_TDD_UL_DL_Pattern is %d DL slots, %d "
"UL slots, %d DL symbols, %d UL symbols)\n",
pc->num_dl_slots,
pc->num_ul_slots,
total_slot,
n_dl_slot,
n_ul_slot,
n_dl_symbols,
n_ul_symbols);
return total_slot;
}
/**
* @brief Configures TDD patterns (1 or 2) in the frame structure
*
* This function sets up the TDD configuration in the frame structure by applying
* DL and UL patterns as defined in NR_TDD_UL_DL_ConfigCommon.
* It handles both TDD pattern1 and pattern2.
*
* @param tdd NR_TDD_UL_DL_ConfigCommon_t pointer containing pattern1 and pattern2
* @param fs Pointer to the frame structure to update with the configured TDD patterns.
*
* @return void
*/
static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs)
{
int num_of_patterns = 1;
uint8_t nb_slots_p2 = 0;
// Reset num dl/ul slots
tdd_period_config_t *pc = &fs->period_cfg;
pc->num_dl_slots = 0;
pc->num_ul_slots = 0;
// Pattern1
uint8_t nb_slots_p1 = set_tdd_bmap_period(&tdd->pattern1, pc, 0);
// Pattern2
if (tdd->pattern2) {
num_of_patterns++;
nb_slots_p2 = set_tdd_bmap_period(tdd->pattern2, pc, nb_slots_p1);
}
LOG_I(NR_MAC,
"Configured %d TDD patterns (total slots: pattern1 = %d, pattern2 = %d)\n",
num_of_patterns,
nb_slots_p1,
nb_slots_p2);
}
/**
* @brief Configures the frame structure and the NFAPI config request
* depending on the duplex mode. If TDD, does the TDD patterns
* and TDD periods configuration.
*
* @param mu numerology
* @param scc pointer to scc
* @param tdd_period TDD period
* @param frame_type type of frame structure (FDD or TDD)
* @param fs pointer to the frame structure to update
*/
void config_frame_structure(int mu,
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,
uint8_t tdd_period,
uint8_t frame_type,
frame_structure_t *fs)
{
fs->numb_slots_frame = get_slots_per_frame_from_scs(mu);
fs->frame_type = frame_type;
if (frame_type == TDD) {
fs->numb_period_frame = get_nb_periods_per_frame(tdd_period);
fs->numb_slots_period = fs->numb_slots_frame / fs->numb_period_frame;
config_tdd_patterns(tdd_UL_DL_ConfigurationCommon, fs);
} else { // FDD
fs->numb_period_frame = 1;
fs->numb_slots_period = fs->numb_slots_frame;
}
AssertFatal(fs->numb_period_frame > 0, "Frame configuration cannot be configured!\n");
}
/**
* @brief Returns true for:
* (1) FDD
* (2) Mixed slot with UL symbols
* (3) Full UL slot
*/
bool is_ul_slot(const slot_t slot, const frame_structure_t *fs)
{
if (fs->frame_type == FDD)
return true;
const tdd_period_config_t *pc = &fs->period_cfg;
slot_t s = get_slot_idx_in_period(slot, fs);
return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_ul_symbols)
|| (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_UPLINK_SLOT));
}
/**
* @brief Returns true for:
* (1) FDD
* (2) Mixed slot with DL symbols
* (3) Full DL slot
*/
bool is_dl_slot(const slot_t slot, const frame_structure_t *fs)
{
if (fs->frame_type == FDD)
return true;
const tdd_period_config_t *pc = &fs->period_cfg;
slot_t s = get_slot_idx_in_period(slot, fs);
return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_dl_symbols)
|| (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_DOWNLINK_SLOT));
}
/**
* @brief Returns true for:
* (1) Mixed slot with DL and/or UL symbols
*/
bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs)
{
if (fs->frame_type == FDD)
return false;
slot_t s = get_slot_idx_in_period(slot, fs);
const tdd_period_config_t *pc = &fs->period_cfg;
return pc->tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT;
}
......@@ -37,8 +37,6 @@
/*#include "PHY/defs_common.h"*/
extern const uint8_t nr_slots_per_frame[5];
/* Scheduler */
extern RAN_CONTEXT_t RC;
extern uint8_t nfapi_mode;
......
This diff is collapsed.
......@@ -165,7 +165,7 @@
// Define the UE L2 states with X-Macro
#define NR_UE_L2_STATES \
UE_STATE(UE_NOT_SYNC) \
UE_STATE(UE_SYNC) \
UE_STATE(UE_RECEIVING_SIB) \
UE_STATE(UE_PERFORMING_RA) \
UE_STATE(UE_CONNECTED) \
UE_STATE(UE_DETACHING)
......@@ -554,9 +554,9 @@ typedef struct {
} si_schedInfo_t;
typedef struct ntn_timing_advance_components {
// N_common_ta_adj represents common propagation delay received in SIB19 (ms)
// N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms)
double N_common_ta_adj;
// N_UE_TA_adj calculated propagation delay from UE and SAT (ms)
// N_UE_TA_adj calculated round-trip-time between UE and SAT (ms)
double N_UE_TA_adj;
// drift rate of common ta in µs/s
double ntn_ta_commondrift;
......@@ -599,7 +599,7 @@ typedef struct NR_UE_MAC_INST_s {
NR_UL_TIME_ALIGNMENT_t ul_time_alignment;
NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon;
frame_type_t frame_type;
frame_structure_t frame_structure;
/* Random Access */
/// CRNTI
......@@ -682,7 +682,7 @@ static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_
static inline double GET_COMPLETE_TIME_ADVANCE_MS(const ntn_timing_advance_componets_t *ntn_ta)
{
return (ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj) * 2;
return ntn_ta->N_common_ta_adj + ntn_ta->N_UE_TA_adj;
}
static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta)
......
......@@ -85,10 +85,10 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id,
NR_MIB_t *mibP,
int sched_sib1);
void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1);
void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra);
struct position; /* forward declaration */
void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17);
void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, bool can_start_ra);
void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause);
......@@ -367,7 +367,7 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac);
void ue_init_config_request(NR_UE_MAC_INST_t *mac, int scs);
void ue_init_config_request(NR_UE_MAC_INST_t *mac, int slots_per_frame);
fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot);
......@@ -376,7 +376,6 @@ void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu);
fapi_nr_ul_config_request_pdu_t *fapiLockIterator(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx);
void release_ul_config(fapi_nr_ul_config_request_pdu_t *pdu, bool clearIt);
void clear_ul_config_request(NR_UE_MAC_INST_t *mac, int scs);
int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm);
// PUSCH scheduler:
......
......@@ -94,7 +94,7 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
// sf80 default for retxBSR_Timer sf10 for periodicBSR_Timer
int mu = mac->current_UL_BWP ? mac->current_UL_BWP->scs : get_softmodem_params()->numerology;
int subframes_per_slot = nr_slots_per_frame[mu] / 10;
int subframes_per_slot = get_slots_per_frame_from_scs(mu) / 10;
nr_timer_setup(&mac->scheduling_info.retxBSR_Timer, 80 * subframes_per_slot, 1); // 1 slot update rate
nr_timer_setup(&mac->scheduling_info.periodicBSR_Timer, 10 * subframes_per_slot, 1); // 1 slot update rate
......@@ -139,7 +139,7 @@ NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst)
nr_ue_init_mac(mac);
nr_ue_mac_default_configs(mac);
if (IS_SA_MODE(get_softmodem_params()))
ue_init_config_request(mac, get_softmodem_params()->numerology);
ue_init_config_request(mac, get_slots_per_frame_from_scs(get_softmodem_params()->numerology));
}
int rc = rlc_module_init(0);
......
......@@ -84,7 +84,7 @@ void init_RA(NR_UE_MAC_INST_t *mac,
// PRACH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1)
prach_resources->RA_PCMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frame_type,
mac->frame_structure.frame_type,
mac->frequency_range,
mac->current_UL_BWP->channel_bandwidth,
2,
......@@ -617,8 +617,7 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s
RA_config_t *ra = &mac->ra;
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta);
const int mu = mac->current_UL_BWP->scs;
const int slots_per_ms = nr_slots_per_frame[mu] / 10;
const int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
// start contention resolution timer
const int RA_contention_resolution_timer_ms = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) << 3;
......@@ -914,14 +913,12 @@ int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon)
void nr_get_RA_window(NR_UE_MAC_INST_t *mac)
{
RA_config_t *ra = &mac->ra;
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__);
const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta);
const int mu = mac->current_DL_BWP->scs;
const int slots_per_ms = nr_slots_per_frame[mu] / 10;
const int ra_Offset_slots = ra->RA_offset * nr_slots_per_frame[mu];
int slots_per_frame = mac->frame_structure.numb_slots_frame;
const int slots_per_ms = slots_per_frame / 10;
const int ra_Offset_slots = ra->RA_offset * slots_per_frame;
const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms);
ra->RA_window_cnt = ra_Offset_slots + ta_Common_slots; // taking into account the 2 frames gap introduced by OAI gNB
......@@ -1041,7 +1038,7 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr
void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac)
{
LOG_W(NR_MAC, "Triggering new RA procedure for UE with RNTI %x\n", mac->crnti);
mac->state = UE_SYNC;
mac->state = UE_PERFORMING_RA;
reset_ra(mac, false);
mac->ra.msg3_C_RNTI = true;
}
......
......@@ -515,7 +515,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl
NR_BWP_Id_t dl_bwp_id = current_DL_BWP ? current_DL_BWP->bwp_id : 0;
NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[dl_bwp_id];
int scs = current_DL_BWP ? current_DL_BWP->scs : get_softmodem_params()->numerology;
const int slots_per_frame = nr_slots_per_frame[scs];
const int slots_per_frame = get_slots_per_frame_from_scs(scs);
if (mac->get_sib1) {
int ssb_sc_offset_norm;
if (mac->ssb_subcarrier_offset < 24 && mac->frequency_range == FR1)
......
......@@ -347,7 +347,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
// modulated CP-OFDM of equivalent RB allocation.
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frame_type,
mac->frame_structure.frame_type,
mac->frequency_range,
current_UL_BWP->channel_bandwidth,
2,
......@@ -529,7 +529,7 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
int M_pusch_component = 10 * log10((pow(2, mu)) * num_rb);
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frame_type,
mac->frame_structure.frame_type,
mac->frequency_range,
mac->current_UL_BWP->channel_bandwidth,
qm,
......@@ -619,7 +619,7 @@ int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac,
// allocation.
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frame_type,
mac->frame_structure.frame_type,
mac->frequency_range,
mac->current_UL_BWP->channel_bandwidth,
2,
......
......@@ -223,10 +223,14 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id)
if (mac->first_sync_frame == -1)
mac->first_sync_frame = frame;
if(get_softmodem_params()->phy_test)
if (get_softmodem_params()->phy_test)
mac->state = UE_CONNECTED;
else if(mac->state == UE_NOT_SYNC)
mac->state = UE_SYNC;
else if (mac->state == UE_NOT_SYNC) {
if (IS_SA_MODE(get_softmodem_params()) && mac->get_sib1)
mac->state = UE_RECEIVING_SIB;
else
mac->state = UE_PERFORMING_RA;
}
}
static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu,
......@@ -235,6 +239,7 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc
int frame,
int slot,
int mu,
int slots_per_frame,
NR_PDSCH_Config_t *pdsch_config)
{
// only for C-RNTI, MCS-C-RNTI, CS-RNTI (and only C-RNTI is supported for now)
......@@ -258,7 +263,7 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc
AssertFatal(zp_res->periodicityAndOffset, "periodicityAndOffset cannot be null for periodic ZP resource\n");
int period, offset;
csi_period_offset(NULL, zp_res->periodicityAndOffset, &period, &offset);
if((frame * nr_slots_per_frame[mu] + slot - offset) % period != 0)
if((frame * slots_per_frame + slot - offset) % period != 0)
continue;
AssertFatal(dlsch_pdu->numCsiRsForRateMatching < NFAPI_MAX_NUM_CSI_RATEMATCH, "csiRsForRateMatching out of bounds\n");
fapi_nr_dl_config_csirs_pdu_rel15_t *csi_pdu = &dlsch_pdu->csiRsForRateMatching[dlsch_pdu->numCsiRsForRateMatching];
......@@ -705,7 +710,8 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
}
dlsch_pdu->numCsiRsForRateMatching = 0;
configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, dlsch_pdu->SubcarrierSpacing, pdsch_config);
int slots_frame = mac->frame_structure.numb_slots_frame;
configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, dlsch_pdu->SubcarrierSpacing, slots_frame, pdsch_config);
/* IDENTIFIER_DCI_FORMATS */
......@@ -1034,7 +1040,8 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
nr_rnti_type_t rnti_type = get_rnti_type(mac, dci_ind->rnti);
dlsch_pdu->numCsiRsForRateMatching = 0;
configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, current_DL_BWP->scs, pdsch_Config);
int slots_frame = mac->frame_structure.numb_slots_frame;
configure_ratematching_csi(dlsch_pdu, dl_config, rnti_type, frame, slot, current_DL_BWP->scs, slots_frame, pdsch_Config);
/* IDENTIFIER_DCI_FORMATS */
/* CARRIER_IND */
......@@ -1468,8 +1475,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
current_harq->dai_cumul = 0;
current_harq->delta_pucch = delta_pucch;
// FIXME k0 != 0 currently not taken into consideration
int scs = mac->current_DL_BWP ? mac->current_DL_BWP->scs : get_softmodem_params()->numerology;
int slots_per_frame = nr_slots_per_frame[scs];
int slots_per_frame = mac->frame_structure.numb_slots_frame;
current_harq->ul_frame = frame;
current_harq->ul_slot = slot + data_toul_fb;
if (current_harq->ul_slot >= slots_per_frame) {
......@@ -1532,8 +1538,7 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
long *pusch_id = NULL;
long *id0 = NULL;
const int scs = current_UL_BWP->scs;
int subframe_number = slot / (nr_slots_per_frame[scs]/10);
int subframe_number = slot / (mac->frame_structure.numb_slots_frame / 10);
pucch_pdu->rnti = rnti;
LOG_D(NR_MAC, "initial_pucch_id %d, pucch_resource %p\n", pucch->initial_pucch_id, pucch->pucch_resource);
......@@ -2503,7 +2508,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p
int SR_period; int SR_offset;
find_period_offset_SR(sr_Config, &SR_period, &SR_offset);
const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs];
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
int sfn_sf = frame * n_slots_frame + slot;
if ((sfn_sf - SR_offset) % SR_period == 0) {
......@@ -2613,7 +2618,7 @@ int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCC
if(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic) {
int period, offset;
csi_period_offset(csirep, NULL, &period, &offset);
const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs];
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
if (((n_slots_frame*frame + slot - offset)%period) == 0 && pucch_Config) {
int csi_res_id = -1;
for (int i = 0; i < csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.count; i++) {
......@@ -3433,12 +3438,10 @@ static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, in
NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
ul_time_alignment->ta_command = ta;
ul_time_alignment->ta_apply = type;
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
const int n_slots_frame = nr_slots_per_frame[mac->current_UL_BWP->scs];
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
ul_time_alignment->frame = (frame + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER;
ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame;
// start or restart the timeAlignmentTimer associated with the indicated TAG
nr_timer_start(&mac->time_alignment_timer);
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -241,6 +241,8 @@ typedef struct NR_UE_RRC_INST_s {
bool reconfig_after_reestab;
//Sidelink params
NR_SL_PreconfigurationNR_r16_t *sl_preconfig;
// NTN params
bool is_NTN_UE;
} NR_UE_RRC_INST_t;
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment