Commit d8a6c5c9 authored by Robert Schmidt's avatar Robert Schmidt

Merge branch 'integration_2024_w40' into 'develop'

Integration: `2024.w40`

Closes #756 and #849

See merge request oai/openairinterface5g!3014

* !2886 (doc): Added a new doc on hardware requirements
* !2955 dockerized clang-format error detection tool
* !3005 Fix symbol size in nr_dlsch_mmse
* !2930 SRS tx power
* SA-B200-Module-SABOX pipeline: improve radio
* SA-AW2S-CN5G: accept 5% ping packet loss
* !3003 Resolve "SEGFAULT in L1_rx_thread" - CI
* !3016 fix tests for log2_approx and log2_approx64
* patch to move RFsim-4G to cacofonix
parents fc0cbc31 4c85eb4a
......@@ -43,6 +43,7 @@ Please see [NOTICE](NOTICE.md) file for third party software that is included in
* [General overview of documentation](./doc/README.md)
* [The implemented features](./doc/FEATURE_SET.md)
* [System Requirements for Using OAI Stack](./doc/system_requirements.md)
* [How to build](./doc/BUILD.md)
* [How to run the modems](./doc/RUNMODEM.md)
......
......@@ -22,8 +22,9 @@ gNBs =
////////// Physical parameters:
min_rxtxtime = 6;
min_rxtxtime = 2;
do_CSIRS = 1;
do_SRS = 1;
servingCellConfigCommon = (
{
......@@ -183,7 +184,7 @@ L1s = (
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 200;
pucch0_dtx_threshold = 100;
pucch0_dtx_threshold = 30;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
......@@ -193,8 +194,8 @@ RUs = (
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 0
att_rx = 0;
att_tx = 10;
att_rx = 10;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 114;
......
......@@ -184,7 +184,7 @@ L1s = (
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
pucch0_dtx_threshold = 100;
pucch0_dtx_threshold = 30;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
......@@ -194,8 +194,8 @@ RUs = (
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 14;
att_rx = 14;
att_tx = 10;
att_rx = 10;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 114;
......
......@@ -108,14 +108,14 @@
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
</testCase>
<testCase id="020011">
<class>Ping</class>
<desc>Ping Traffic-Gen from LTE-UE</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args> -c 20 192.168.61.11</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -125,7 +125,7 @@
<desc>Ping LTE-UE from Traffic-Gen</desc>
<id>rfsim4g_ext_dn</id>
<ping_args>-c 20 12.0.0.2</ping_args>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -137,8 +137,8 @@
<iperf_args>-u -t 30 -b 2M -R</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<nodes>obelix</nodes>
<svr_node>obelix</svr_node>
<nodes>cacofonix</nodes>
<svr_node>cacofonix</svr_node>
</testCase>
<testCase id="030011">
......@@ -149,8 +149,8 @@
<iperf_args>-u -t 30 -b 1M</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<nodes>obelix</nodes>
<svr_node>obelix</svr_node>
<nodes>cacofonix</nodes>
<svr_node>cacofonix</svr_node>
</testCase>
<testCase id="100011">
......
......@@ -86,7 +86,7 @@
<class>Ping</class>
<desc>Ping Traffic-Gen from LTE-UE</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args> -c 20 10.0.1.1</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -95,7 +95,7 @@
<class>Ping</class>
<desc>Ping LTE-UE from eNB</desc>
<id>rfsim4g_enb_nos1</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args> -c 20 10.0.1.2</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -104,9 +104,9 @@
<class>Iperf</class>
<desc>Iperf UDP DL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_enb_nos1</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 2M -R</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......@@ -116,9 +116,9 @@
<class>Iperf</class>
<desc>Iperf UDP UL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_enb_nos1</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 1M</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......
......@@ -108,14 +108,14 @@
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
</testCase>
<testCase id="020011">
<class>Ping</class>
<desc>Ping Traffic-Gen from LTE-UE</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args> -c 20 192.168.61.11</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -124,7 +124,7 @@
<class>Ping</class>
<desc>Ping LTE-UE from Traffic-Gen</desc>
<id>rfsim4g_ext_dn</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args>-c 20 12.0.0.2</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -133,9 +133,9 @@
<class>Iperf</class>
<desc>Iperf UDP DL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_ext_dn</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 2M -R</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......@@ -145,9 +145,9 @@
<class>Iperf</class>
<desc>Iperf UDP UL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_ext_dn</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 1M</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......
......@@ -108,14 +108,14 @@
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
</testCase>
<testCase id="020011">
<class>Ping</class>
<desc>Ping Traffic-Gen from LTE-UE</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args> -c 20 192.168.61.11</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -124,7 +124,7 @@
<class>Ping</class>
<desc>Ping LTE-UE from Traffic-Gen</desc>
<id>rfsim4g_ext_dn</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args>-c 20 12.0.0.2</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -133,9 +133,9 @@
<class>Iperf</class>
<desc>Iperf UDP DL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_ext_dn</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 2M -R</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......@@ -145,9 +145,9 @@
<class>Iperf</class>
<desc>Iperf UDP UL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_ext_dn</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 1M</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......
......@@ -83,9 +83,9 @@
<class>Iperf2_Unidir</class>
<desc>Iperf2 UDP DL</desc>
<id>rfsim4g_ue_fembms</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_enb_fembms</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 2M</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......
......@@ -83,9 +83,9 @@
<class>Iperf</class>
<desc>Iperf UDP DL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_enb_nos1</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 2M -R</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......
......@@ -108,7 +108,7 @@
<class>Ping</class>
<desc>Ping Traffic-Gen from LTE-UE</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args> -c 20 192.168.61.11</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -117,7 +117,7 @@
<class>Ping</class>
<desc>Ping LTE-UE from Traffic-Gen</desc>
<id>rfsim4g_ext_dn</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<ping_args>-c 20 12.0.0.2</ping_args>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
......@@ -126,9 +126,9 @@
<class>Iperf</class>
<desc>Iperf UDP DL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_ext_dn</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 2M -R</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......@@ -138,9 +138,9 @@
<class>Iperf</class>
<desc>Iperf UDP UL</desc>
<id>rfsim4g_ue</id>
<nodes>obelix</nodes>
<nodes>cacofonix</nodes>
<svr_id>rfsim4g_ext_dn</svr_id>
<svr_node>obelix</svr_node>
<svr_node>cacofonix</svr_node>
<iperf_args>-u -t 30 -b 1M</iperf_args>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
......
......@@ -222,7 +222,7 @@
<desc>Ping: 20pings in 20sec, multi-ue</desc>
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15</id>
<ping_args>-c 20 %cn_ip%</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_packetloss_threshold>5</ping_packetloss_threshold>
<ping_rttavg_threshold>25</ping_rttavg_threshold>
</testCase>
......
......@@ -67,8 +67,6 @@ services:
--RUs.[0].sdr_addrs serial=30C51D4
--continuous-tx -E
--telnetsrv --telnetsrv.listenport 9091 --telnetsrv.shrmod ci
--gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1
--RUs.[0].att_rx 14 --RUs.[0].att_tx 14
--log_config.global_log_options level,nocolor,time,line_num,function
devices:
- /dev/bus/usb/:/dev/bus/usb/
......
......@@ -36,6 +36,79 @@
#include "nr_common.h"
#include <complex.h>
#define C_SRS_NUMBER (64)
#define B_SRS_NUMBER (4)
/* TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration */
static const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2] = {
/* B_SRS = 0 B_SRS = 1 B_SRS = 2 B_SRS = 3 */
/* C SRS m_srs0 N_0 m_srs1 N_1 m_srs2 N_2 m_srs3 N_3 */
/* 0 */ {{4, 1}, {4, 1}, {4, 1}, {4, 1}},
/* 1 */ {{8, 1}, {4, 2}, {4, 1}, {4, 1}},
/* 2 */ {{12, 1}, {4, 3}, {4, 1}, {4, 1}},
/* 3 */ {{16, 1}, {4, 4}, {4, 1}, {4, 1}},
/* 4 */ {{16, 1}, {8, 2}, {4, 2}, {4, 1}},
/* 5 */ {{20, 1}, {4, 5}, {4, 1}, {4, 1}},
/* 6 */ {{24, 1}, {4, 6}, {4, 1}, {4, 1}},
/* 7 */ {{24, 1}, {12, 2}, {4, 3}, {4, 1}},
/* 8 */ {{28, 1}, {4, 7}, {4, 1}, {4, 1}},
/* 9 */ {{32, 1}, {16, 2}, {8, 2}, {4, 2}},
/* 10 */ {{36, 1}, {12, 3}, {4, 3}, {4, 1}},
/* 11 */ {{40, 1}, {20, 2}, {4, 5}, {4, 1}},
/* 12 */ {{48, 1}, {16, 3}, {8, 2}, {4, 2}},
/* 13 */ {{48, 1}, {24, 2}, {12, 2}, {4, 3}},
/* 14 */ {{52, 1}, {4, 13}, {4, 1}, {4, 1}},
/* 15 */ {{56, 1}, {28, 2}, {4, 7}, {4, 1}},
/* 16 */ {{60, 1}, {20, 3}, {4, 5}, {4, 1}},
/* 17 */ {{64, 1}, {32, 2}, {16, 2}, {4, 4}},
/* 18 */ {{72, 1}, {24, 3}, {12, 2}, {4, 3}},
/* 19 */ {{72, 1}, {36, 2}, {12, 3}, {4, 3}},
/* 20 */ {{76, 1}, {4, 19}, {4, 1}, {4, 1}},
/* 21 */ {{80, 1}, {40, 2}, {20, 2}, {4, 5}},
/* 22 */ {{88, 1}, {44, 2}, {4, 11}, {4, 1}},
/* 23 */ {{96, 1}, {32, 3}, {16, 2}, {4, 4}},
/* 24 */ {{96, 1}, {48, 2}, {24, 2}, {4, 6}},
/* 25 */ {{104, 1}, {52, 2}, {4, 13}, {4, 1}},
/* 26 */ {{112, 1}, {56, 2}, {28, 2}, {4, 7}},
/* 27 */ {{120, 1}, {60, 2}, {20, 3}, {4, 5}},
/* 28 */ {{120, 1}, {40, 3}, {8, 5}, {4, 2}},
/* 29 */ {{120, 1}, {24, 5}, {12, 2}, {4, 3}},
/* 30 */ {{128, 1}, {64, 2}, {32, 2}, {4, 8}},
/* 31 */ {{128, 1}, {64, 2}, {16, 4}, {4, 4}},
/* 32 */ {{128, 1}, {16, 8}, {8, 2}, {4, 2}},
/* 33 */ {{132, 1}, {44, 3}, {4, 11}, {4, 1}},
/* 34 */ {{136, 1}, {68, 2}, {4, 17}, {4, 1}},
/* 35 */ {{144, 1}, {72, 2}, {36, 2}, {4, 9}},
/* 36 */ {{144, 1}, {48, 3}, {24, 2}, {12, 2}},
/* 37 */ {{144, 1}, {48, 3}, {16, 3}, {4, 4}},
/* 38 */ {{144, 1}, {16, 9}, {8, 2}, {4, 2}},
/* 39 */ {{152, 1}, {76, 2}, {4, 19}, {4, 1}},
/* 40 */ {{160, 1}, {80, 2}, {40, 2}, {4, 10}},
/* 41 */ {{160, 1}, {80, 2}, {20, 4}, {4, 5}},
/* 42 */ {{160, 1}, {32, 5}, {16, 2}, {4, 4}},
/* 43 */ {{168, 1}, {84, 2}, {28, 3}, {4, 7}},
/* 44 */ {{176, 1}, {88, 2}, {44, 2}, {4, 11}},
/* 45 */ {{184, 1}, {92, 2}, {4, 23}, {4, 1}},
/* 46 */ {{192, 1}, {96, 2}, {48, 2}, {4, 12}},
/* 47 */ {{192, 1}, {96, 2}, {24, 4}, {4, 6}},
/* 48 */ {{192, 1}, {64, 3}, {16, 4}, {4, 4}},
/* 49 */ {{192, 1}, {24, 8}, {8, 3}, {4, 2}},
/* 50 */ {{208, 1}, {104, 2}, {52, 2}, {4, 13}},
/* 51 */ {{216, 1}, {108, 2}, {36, 3}, {4, 9}},
/* 52 */ {{224, 1}, {112, 2}, {56, 2}, {4, 14}},
/* 53 */ {{240, 1}, {120, 2}, {60, 2}, {4, 15}},
/* 54 */ {{240, 1}, {80, 3}, {20, 4}, {4, 5}},
/* 55 */ {{240, 1}, {48, 5}, {16, 3}, {8, 2}},
/* 56 */ {{240, 1}, {24, 10}, {12, 2}, {4, 3}},
/* 57 */ {{256, 1}, {128, 2}, {64, 2}, {4, 16}},
/* 58 */ {{256, 1}, {128, 2}, {32, 4}, {4, 8}},
/* 59 */ {{256, 1}, {16, 16}, {8, 2}, {4, 2}},
/* 60 */ {{264, 1}, {132, 2}, {44, 3}, {4, 11}},
/* 61 */ {{272, 1}, {136, 2}, {68, 2}, {4, 17}},
/* 62 */ {{272, 1}, {68, 4}, {4, 17}, {4, 1}},
/* 63 */ {{272, 1}, {16, 17}, {8, 2}, {4, 2}},
};
const char *duplex_mode[]={"FDD","TDD"};
static const uint8_t bit_reverse_table_256[] = {
......@@ -1212,3 +1285,11 @@ void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t ste
timer->step = step;
nr_timer_stop(timer);
}
unsigned short get_m_srs(int c_srs, int b_srs) {
return srs_bandwidth_config[c_srs][b_srs][0];
}
unsigned short get_N_b_srs(int c_srs, int b_srs) {
return srs_bandwidth_config[c_srs][b_srs][1];
}
......@@ -250,6 +250,8 @@ int get_scan_ssb_first_sc(const double fc,
void check_ssb_raster(uint64_t freq, int band, int scs);
int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_range, int n_rbs);
unsigned short get_m_srs(int c_srs, int b_srs);
unsigned short get_N_b_srs(int c_srs, int b_srs);
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
......
......@@ -26,7 +26,12 @@ The hardware on which we have tried this tutorial:
|Intel(R) Xeon(R) Gold 6354 36-Core, 128GB|Ubuntu 22.04.3 LTS (5.15.0-1033-realtime) |Intel X710, i40e, 9.00 0x8000cfeb 21.5.9 |
|AMD EPYC 9374F 32-Core Processor, 128GB |Ubuntu 22.04.2 LTS (5.15.0-1038-realtime) |Intel E810 ,ice, 4.00 0x8001184e 1.3236.0|
**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.
- If you are using Intel servers then use only Ice Lake or newer generations. In case of AMD use only 4th generation, Genoa or newer.
- If you try on any other server apart from the above listed, then choose a desktop/server with clock speed higher than 3.0 GHz and `avx512` capabilities.
NICs we have tested so far:
......
......@@ -64,3 +64,7 @@ When this is done, you are set up. How to use:
6) Commit. It won't work if code is not properly formatted due to the
pre-commit hook. Force committing with `git commit --no-verify`
# Checking errors introduced by a branch
Here is the script that can be used to detect any clang-format errors introduced by a branch [here](../tools/formatting/README.md)
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">System Requirements for Using OAI Stack</font></b>
</td>
</tr>
</table>
This document describes the minimal and performant system requirements for OpenAirInterface (OAI) 4G/5G software stack (UE and gNB stack). The information provided in this document is based on experimentation, if you have a feedback then open an issue or send an email on the mailing list.
**Table of Contents**
[[_TOC_]]
# Supported CPU Architecture
|Architecture |
|------------------------------------------ |
|x86_64 (Intel, AMD) |
|aarch64 (Neoverse-N1, N2 and Grace hopper) |
**Note**:
- On `x86_64` platform the CPU should support `avx2` instruction set (Minimum requirement).
# Supported Operating System
|Operating System |
|-----------------|
|Ubuntu 20/22/24 |
|RHEL 9 |
|Fedora 40 |
|Debian 11 |
|Rocky 9 |
# Minimum Hardware Requirement for x86_64 Platforms
The minimum hardware requirements depends on the radio unit you would like to use or the test case that you would like to execute.
## Simulated Radio
OAI offers an inbuilt simulated radio, [RFSimulator](../radio/rfsimulator/README.md). It can be used to familiarize oneself with OAI, for development and debugging, and offers the possibility to use basic channel models. It is not designed to do high performance testing. The below requirements are valid for both 4G and 5G RAN and UE Stack.
The following requirements are minimum requirements for all use cases:
### Minimum requirements for gNB Stack
- CPU: 2
- Minimum frequency > 2GHz
- Memory: 4Gi
- `avx2` instruction set
- `sctp` protocol should be enabled
**NOTE**: We have not tested on Intel Atom or Celeron processors, and they
likely won't work well.
### Minimum requirements for UE Stack
- CPU: 2
- Minimum frequency > 2GHz
- Memory: 3Gi
- `avx2` instruction set
**NOTE**: We have not tested on Intel Atom or Celeron processors
## USRP B2XX or Blade RF
USRP B2XX or Blade RF are USB based radios recommended to use with USB 3.0. You can choose a minimum hardware to do functional testing and performance hardware for performance testing. This hardware you can find in Mini-PCs or laptops.
The minimum requirements stated in [simulated radio](.##simulated-radio) apply.
### Minimum requirements for both gNB and UE Stack
- CPU: 3
- Memory: 5Gi
- Disable CPU sleep states
- USB 3.0
- Intel i5, AMD Ryzen 5
### Recommended for performance for gNB and UE Stack
- CPU: 4
- Boost Frequency > 3GHz
- Use only performance cores
- Disable hyper-threading
- Disable CPU sleep states
- DDR4 or DDR5 RAM, minimum 5Gi
- USB 3.0
Apart from this you should follow [tuning and security tips](./tuning_and_security.md) to
tune your system to get high performance.
## USRP N3XX/X3XX/X4XX/AW2S
USRP N3XX/X3XX/X4XX requires two dedicated 10G SFP+ connections. For these radios we only recommend having performance hardware. This hardware you can find in Desktop servers or rack/blade servers. For the gNB, the same applies in case of using AW2S radios.
The minimum requirements stated in [simulated radio](.##simulated-radio) apply.
Apart from this you should follow [tuning and security tips](./tuning_and_security.md) to
tune your system to get high performance.
**NOTE**: In case you are using Mellanox NIC cards then you have to download `mlnx-ofed` and configure your NIC for performance.
### Recommended for performance for gNB Stack
- CPU: 8-10
- Boost Frequency > 4GHz
- Use only performance cores
- Disable CPU sleep states
- DDR4 or DDR5 RAM, 5 Gi
- (Optional) Realtime kernel to have better Jitter statistics
- Intel x710/xx710/E-810 or Mellanox connect 5x or 6x
### Recommended for performance for UE Stack
- CPU: 4
- Boost Frequency > 4GHz
- DDR4 or DDR5 RAM, 5Gi
- Use only performance cores
- Disable CPU sleep states
- (Optional) Realtime kernel to have better Jitter statistics
- Intel x710/xx710/E-810 or Mellanox connect 5x or 6x
## O-RAN Radio Units
We have dedicated documentation for O-RAN Radio Units. [Refer to 7.2 FH documentation](./ORAN_FHI7.2_Tutorial.md) before purchasing a Desktop server or rack/blade server.
The minimum requirements stated in [simulated radio](.##simulated-radio) apply.
......@@ -391,6 +391,7 @@ typedef struct {
uint16_t t_srs; // SRS-Periodicity in slots [3GPP TS 38.211, Sec 6.4.1.4.4], Value: 1,2,3,4,5,8,10,16,20,32,40,64,80,160,320,640,1280,2560
uint16_t t_offset; // Slot offset value [3GPP TS 38.211, Sec 6.4.1.4.3], Value:0->2559
nfapi_nr_ue_ul_beamforming_t beamforming;
int16_t tx_power;
} fapi_nr_ul_config_srs_pdu;
typedef struct {
......
......@@ -631,7 +631,7 @@ int nr_srs_channel_estimation(
const uint8_t N_ap = 1<<srs_pdu->num_ant_ports;
const uint8_t K_TC = 2<<srs_pdu->comb_size;
const uint16_t m_SRS_b = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0];
const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);
const uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC;
uint8_t fd_cdm = N_ap;
if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) {
......
......@@ -80,7 +80,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
const uint8_t N_ap = 1<<srs_pdu->num_ant_ports;
const uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols;
const uint8_t K_TC = 2 << srs_pdu->comb_size;
const uint16_t M_sc_b_SRS = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0] * NR_NB_SC_PER_RB/K_TC;
const uint16_t M_sc_b_SRS = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index) * NR_NB_SC_PER_RB / K_TC;
int32_t *rx_signal;
bool no_srs_signal = true;
......
......@@ -110,17 +110,17 @@ uint16_t compute_F_b(frame_t frame_number,
uint16_t product_N_b = 1;
for (unsigned int b_prime = b_hop; b_prime < B_SRS; b_prime++) {
if (b_prime != b_hop) {
product_N_b *= srs_bandwidth_config[C_SRS][b_prime][1];
product_N_b *= get_N_b_srs(C_SRS, b_prime);
}
}
uint16_t F_b = 0;
uint8_t N_b = srs_bandwidth_config[C_SRS][b][1];
uint8_t N_b = get_N_b_srs(C_SRS, b);
if (N_b & 1) { // Nb odd
F_b = (N_b/2)*(n_SRS/product_N_b);
} else { // Nb even
uint16_t product_N_b_B_SRS = product_N_b;
product_N_b_B_SRS *= srs_bandwidth_config[C_SRS][B_SRS][1]; /* product for b_hop to b */
product_N_b_B_SRS *= get_N_b_srs(C_SRS, B_SRS); /* product for b_hop to b */
F_b = (N_b/2)*((n_SRS%product_N_b_B_SRS)/product_N_b) + ((n_SRS%product_N_b_B_SRS)/2*product_N_b);
}
......@@ -142,8 +142,8 @@ uint16_t compute_n_b(frame_t frame_number,
uint8_t l_line,
uint8_t b) {
uint8_t N_b = srs_bandwidth_config[C_SRS][b][1];
uint16_t m_SRS_b = srs_bandwidth_config[C_SRS][B_SRS][0];
uint8_t N_b = get_N_b_srs(C_SRS, b);
uint16_t m_SRS_b = get_m_srs(C_SRS, B_SRS);
uint16_t n_b = 0;
if (b_hop >= B_SRS) {
......@@ -211,7 +211,7 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
uint8_t N_symb_SRS = 1<<srs_config_pdu->num_symbols; // Number of consecutive OFDM symbols
uint8_t l0 = frame_parms->symbols_per_slot - 1 - l_offset; // Starting symbol position in the time domain
uint8_t n_SRS_cs_max = srs_max_number_cs[srs_config_pdu->comb_size];
uint16_t m_SRS_b = srs_bandwidth_config[C_SRS][B_SRS][0]; // Number of resource blocks
uint16_t m_SRS_b = get_m_srs(C_SRS, B_SRS); // Number of resource blocks
uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB/K_TC; // Length of the SRS sequence
#ifdef SRS_DEBUG
......@@ -273,7 +273,7 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
}
uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_config_pdu->bwp_start*NR_NB_SC_PER_RB;
double sqrt_N_ap = sqrt(N_ap);
uint16_t n_b[B_SRS_NUMBER];
uint16_t n_b[B_SRS + 1];
// Find index of table which is for this SRS length
uint16_t M_sc_b_SRS_index = 0;
......
......@@ -35,83 +35,6 @@
#include "PHY/defs_nr_UE.h"
/************** DEFINE ********************************************/
#define C_SRS_NUMBER (64)
#define B_SRS_NUMBER (4)
/************** VARIABLES *****************************************/
/* TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration */
static const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2] = {
/* B_SRS = 0 B_SRS = 1 B_SRS = 2 B_SRS = 3 */
/* C SRS m_srs0 N_0 m_srs1 N_1 m_srs2 N_2 m_srs3 N_3 */
/* 0 */ {{4, 1}, {4, 1}, {4, 1}, {4, 1}},
/* 1 */ {{8, 1}, {4, 2}, {4, 1}, {4, 1}},
/* 2 */ {{12, 1}, {4, 3}, {4, 1}, {4, 1}},
/* 3 */ {{16, 1}, {4, 4}, {4, 1}, {4, 1}},
/* 4 */ {{16, 1}, {8, 2}, {4, 2}, {4, 1}},
/* 5 */ {{20, 1}, {4, 5}, {4, 1}, {4, 1}},
/* 6 */ {{24, 1}, {4, 6}, {4, 1}, {4, 1}},
/* 7 */ {{24, 1}, {12, 2}, {4, 3}, {4, 1}},
/* 8 */ {{28, 1}, {4, 7}, {4, 1}, {4, 1}},
/* 9 */ {{32, 1}, {16, 2}, {8, 2}, {4, 2}},
/* 10 */ {{36, 1}, {12, 3}, {4, 3}, {4, 1}},
/* 11 */ {{40, 1}, {20, 2}, {4, 5}, {4, 1}},
/* 12 */ {{48, 1}, {16, 3}, {8, 2}, {4, 2}},
/* 13 */ {{48, 1}, {24, 2}, {12, 2}, {4, 3}},
/* 14 */ {{52, 1}, {4, 13}, {4, 1}, {4, 1}},
/* 15 */ {{56, 1}, {28, 2}, {4, 7}, {4, 1}},
/* 16 */ {{60, 1}, {20, 3}, {4, 5}, {4, 1}},
/* 17 */ {{64, 1}, {32, 2}, {16, 2}, {4, 4}},
/* 18 */ {{72, 1}, {24, 3}, {12, 2}, {4, 3}},
/* 19 */ {{72, 1}, {36, 2}, {12, 3}, {4, 3}},
/* 20 */ {{76, 1}, {4, 19}, {4, 1}, {4, 1}},
/* 21 */ {{80, 1}, {40, 2}, {20, 2}, {4, 5}},
/* 22 */ {{88, 1}, {44, 2}, {4, 11}, {4, 1}},
/* 23 */ {{96, 1}, {32, 3}, {16, 2}, {4, 4}},
/* 24 */ {{96, 1}, {48, 2}, {24, 2}, {4, 6}},
/* 25 */ {{104, 1}, {52, 2}, {4, 13}, {4, 1}},
/* 26 */ {{112, 1}, {56, 2}, {28, 2}, {4, 7}},
/* 27 */ {{120, 1}, {60, 2}, {20, 3}, {4, 5}},
/* 28 */ {{120, 1}, {40, 3}, {8, 5}, {4, 2}},
/* 29 */ {{120, 1}, {24, 5}, {12, 2}, {4, 3}},
/* 30 */ {{128, 1}, {64, 2}, {32, 2}, {4, 8}},
/* 31 */ {{128, 1}, {64, 2}, {16, 4}, {4, 4}},
/* 32 */ {{128, 1}, {16, 8}, {8, 2}, {4, 2}},
/* 33 */ {{132, 1}, {44, 3}, {4, 11}, {4, 1}},
/* 34 */ {{136, 1}, {68, 2}, {4, 17}, {4, 1}},
/* 35 */ {{144, 1}, {72, 2}, {36, 2}, {4, 9}},
/* 36 */ {{144, 1}, {48, 3}, {24, 2}, {12, 2}},
/* 37 */ {{144, 1}, {48, 3}, {16, 3}, {4, 4}},
/* 38 */ {{144, 1}, {16, 9}, {8, 2}, {4, 2}},
/* 39 */ {{152, 1}, {76, 2}, {4, 19}, {4, 1}},
/* 40 */ {{160, 1}, {80, 2}, {40, 2}, {4, 10}},
/* 41 */ {{160, 1}, {80, 2}, {20, 4}, {4, 5}},
/* 42 */ {{160, 1}, {32, 5}, {16, 2}, {4, 4}},
/* 43 */ {{168, 1}, {84, 2}, {28, 3}, {4, 7}},
/* 44 */ {{176, 1}, {88, 2}, {44, 2}, {4, 11}},
/* 45 */ {{184, 1}, {92, 2}, {4, 23}, {4, 1}},
/* 46 */ {{192, 1}, {96, 2}, {48, 2}, {4, 12}},
/* 47 */ {{192, 1}, {96, 2}, {24, 4}, {4, 6}},
/* 48 */ {{192, 1}, {64, 3}, {16, 4}, {4, 4}},
/* 49 */ {{192, 1}, {24, 8}, {8, 3}, {4, 2}},
/* 50 */ {{208, 1}, {104, 2}, {52, 2}, {4, 13}},
/* 51 */ {{216, 1}, {108, 2}, {36, 3}, {4, 9}},
/* 52 */ {{224, 1}, {112, 2}, {56, 2}, {4, 14}},
/* 53 */ {{240, 1}, {120, 2}, {60, 2}, {4, 15}},
/* 54 */ {{240, 1}, {80, 3}, {20, 4}, {4, 5}},
/* 55 */ {{240, 1}, {48, 5}, {16, 3}, {8, 2}},
/* 56 */ {{240, 1}, {24, 10}, {12, 2}, {4, 3}},
/* 57 */ {{256, 1}, {128, 2}, {64, 2}, {4, 16}},
/* 58 */ {{256, 1}, {128, 2}, {32, 4}, {4, 8}},
/* 59 */ {{256, 1}, {16, 16}, {8, 2}, {4, 2}},
/* 60 */ {{264, 1}, {132, 2}, {44, 3}, {4, 11}},
/* 61 */ {{272, 1}, {136, 2}, {68, 2}, {4, 17}},
/* 62 */ {{272, 1}, {68, 4}, {4, 17}, {4, 1}},
/* 63 */ {{272, 1}, {16, 17}, {8, 2}, {4, 2}},
};
#define SRS_PERIODICITY (17)
static const uint16_t srs_periodicity[SRS_PERIODICITY] = {1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560};
......
......@@ -14,4 +14,4 @@ add_executable(test_log2_approx test_log2_approx.cpp ../log2_approx.c)
target_link_libraries(test_log2_approx PRIVATE GTest::gtest LOG minimal_lib)
add_dependencies(tests test_log2_approx)
add_test(NAME test_log2_approx
COMMAND ./test_log2_approx)
COMMAND ./test_log2_approx --gtest_filter=-log2_approx.complete)
......@@ -10,25 +10,27 @@ uint8_t log2_approx_ref(uint32_t x)
return std::round(std::log2(x));
}
uint8_t log2_approx64_ref(unsigned long long int x)
{
return std::round(std::log2(static_cast<long double>(x)));
}
TEST(log2_approx, complete)
{
for (uint32_t i = 0; i < UINT32_MAX; i++)
EXPECT_EQ(log2_approx(i), log2_approx_ref(i));
}
TEST(log2_approx, boundaries)
{
for (int i = 0; i < 32; i++) {
uint32_t i2 = std::pow(2.0, i + 0.5);
EXPECT_EQ(log2_approx(i2), i) << "log2(" << i2 << ")";
EXPECT_EQ(log2_approx(i2 + 1), i + 1) << "log2(" << i2 + 1 << ")";
}
}
TEST(log2_approx64, boundaries)
{
for (long double i = 0; i < 64; i++) {
unsigned long long i2 = std::pow(2.0L, i + 0.5L);
for (unsigned long long j = -10; j <= 10; j++) {
unsigned long long x = i2 + j;
EXPECT_EQ(log2_approx64(x), log2_approx64_ref(x));
}
for (int i = 0; i < 64; i++) {
unsigned long long int i2 = std::pow(2.0L, i + 0.5L);
EXPECT_EQ(log2_approx64(i2), i) << "log2(" << i2 << ")";
EXPECT_EQ(log2_approx64(i2 + 1), i + 1) << "log2(" << i2 + 1 << ")";
}
}
......
......@@ -577,6 +577,9 @@ typedef struct NR_UE_UL_BWP {
int channel_bandwidth;
// Minimum transmission power according to 38.101 6.3.1
float P_CMIN;
// SRS power control adjustment state
int h_b_f_c;
bool srs_power_control_initialized;
} NR_UE_UL_BWP_t;
// non-BWP serving cell configuration
......
......@@ -1280,7 +1280,7 @@ static void handle_aperiodic_srs_type(struct NR_SRS_ResourceSet__resourceType__a
struct NR_SRS_ResourceSet__resourceType__aperiodic__ext1__aperiodicSRS_ResourceTriggerList);
}
static void setup_srsresourceset(NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSet_t *source)
static void setup_srsresourceset(NR_UE_UL_BWP_t *bwp, NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSet_t *source)
{
target->srs_ResourceSetId = source->srs_ResourceSetId;
if (source->srs_ResourceIdList)
......@@ -1311,15 +1311,20 @@ static void setup_srsresourceset(NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSe
}
}
target->usage = source->usage;
if (source->alpha) {
bwp->h_b_f_c = 0;
}
UPDATE_IE(target->alpha, source->alpha, NR_Alpha_t);
if (source->p0)
if (source->p0) {
bwp->h_b_f_c = 0;
UPDATE_IE(target->p0, source->p0, long);
}
if (source->pathlossReferenceRS)
UPDATE_IE(target->pathlossReferenceRS, source->pathlossReferenceRS, struct NR_PathlossReferenceRS_Config);
UPDATE_IE(target->srs_PowerControlAdjustmentStates, source->srs_PowerControlAdjustmentStates, long);
}
static void setup_srsconfig(NR_SRS_Config_t *source, NR_SRS_Config_t *target)
static void setup_srsconfig(NR_UE_UL_BWP_t *bwp, NR_SRS_Config_t *source, NR_SRS_Config_t *target)
{
UPDATE_IE(target->tpc_Accumulation, source->tpc_Accumulation, long);
// SRS-Resource
......@@ -1337,14 +1342,25 @@ static void setup_srsconfig(NR_SRS_Config_t *source, NR_SRS_Config_t *target)
srs_ResourceId);
}
// SRS-ResourceSet
if (source->srs_ResourceSetToAddModList) {
struct NR_SRS_Config__srs_ResourceSetToAddModList *source_srs_list = source->srs_ResourceSetToAddModList;
if (source_srs_list) {
if (!target->srs_ResourceSetToAddModList)
target->srs_ResourceSetToAddModList = calloc(1, sizeof(*target->srs_ResourceSetToAddModList));
ADDMOD_IE_FROMLIST_WFUNCTION(source->srs_ResourceSetToAddModList,
target->srs_ResourceSetToAddModList,
srs_ResourceSetId,
NR_SRS_ResourceSet_t,
setup_srsresourceset);
struct NR_SRS_Config__srs_ResourceSetToAddModList *target_srs_list = target->srs_ResourceSetToAddModList;
for (int i = 0; i < source_srs_list->list.count; i++) {
long srs_resource_id = source_srs_list->list.array[i]->srs_ResourceSetId;
int j;
for (j = 0; j < target_srs_list->list.count; j++) {
if (srs_resource_id == target_srs_list->list.array[j]->srs_ResourceSetId)
break;
}
if (j == target_srs_list->list.count) {
NR_SRS_ResourceSet_t *new = calloc(1, sizeof(*new));
ASN_SEQUENCE_ADD(&target_srs_list->list, new);
}
setup_srsresourceset(bwp, target_srs_list->list.array[j], source_srs_list->list.array[i]);
}
}
if (source->srs_ResourceSetToReleaseList) {
RELEASE_IE_FROMLIST(source->srs_ResourceSetToReleaseList,
......@@ -1459,7 +1475,7 @@ static void configure_dedicated_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP
if (ul_dedicated->srs_Config->present == NR_SetupRelease_SRS_Config_PR_setup) {
if (!bwp->srs_Config)
bwp->srs_Config = calloc(1, sizeof(*bwp->srs_Config));
setup_srsconfig(ul_dedicated->srs_Config->choice.setup, bwp->srs_Config);
setup_srsconfig(bwp, ul_dedicated->srs_Config->choice.setup, bwp->srs_Config);
}
}
AssertFatal(!ul_dedicated->configuredGrantConfig, "configuredGrantConfig not supported\n");
......@@ -1513,6 +1529,7 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up
bwp->channel_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index);
// Minumum transmission power depends on bandwidth, precalculate it here
bwp->P_CMIN = nr_get_Pcmin(bw_index);
bwp->srs_power_control_initialized = false;
if (bwp_id == 0) {
mac->sc_info.initial_ul_BWPSize = bwp->BWPSize;
mac->sc_info.initial_ul_BWPStart = bwp->BWPStart;
......
......@@ -609,6 +609,7 @@ typedef struct NR_UE_MAC_INST_s {
bool pucch_power_control_initialized;
int f_b_f_c;
bool pusch_power_control_initialized;
int delta_msg2;
} NR_UE_MAC_INST_t;
/*@}*/
......
......@@ -240,6 +240,12 @@ int get_pusch_tx_power_ue(
bool is_rar_tx_retx,
bool transform_precoding);
int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac,
NR_SRS_Resource_t *srs_resource,
NR_SRS_ResourceSet_t *srs_resource_set,
int delta_srs,
bool is_configured_for_pusch_on_current_bwp);
int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
int slot,
frame_t frame,
......
......@@ -578,6 +578,7 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
mac->f_b_f_c = DELTA_P_rampup + delta_pusch;
mac->pusch_power_control_initialized = true;
mac->delta_msg2 = delta_pusch;
} else {
if (!((pusch_power_without_f_b_f_c + mac->f_b_f_c >= P_CMAX && delta_pusch > 0) ||
(pusch_power_without_f_b_f_c + mac->f_b_f_c <= P_CMIN && delta_pusch < 0))) {
......@@ -595,3 +596,84 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
f_b_f_c);
return min(P_CMAX, P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF + f_b_f_c);
}
int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac,
NR_SRS_Resource_t *srs_resource,
NR_SRS_ResourceSet_t *srs_resource_set,
int delta_srs,
bool is_configured_for_pusch_on_current_bwp)
{
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
AssertFatal(current_UL_BWP, "Missing configuration: need UL_BWP to calculate SRS tx power\n");
AssertFatal(srs_resource_set->p0, "P0 mantatory present at configuration\n");
int P_0_SRS = *srs_resource_set->p0;
// alpha is optional, use same default as PUSCH
const float alpha_factor_table[8] = {0.0f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f};
float alpha = srs_resource_set->alpha ? alpha_factor_table[*srs_resource_set->alpha] : 1.0f;
int m_srs_component =
10 * log10(pow(2, current_UL_BWP->scs) * get_m_srs(srs_resource->freqHopping.c_SRS, srs_resource->freqHopping.b_SRS));
// The allowed MPR for SRS, PUCCH formats 0, 1, 3 and 4, and PRACH shall be as specified for QPSK modulated DFTs-OFDM of
// equivalent RB allocation. The allowed MPR for PUCCH format 2 shall be as specified for QPSK modulated CP-OFDM of equivalent RB
// allocation.
int P_CMAX = nr_get_Pcmax(mac->p_Max,
mac->nr_band,
mac->frame_type,
mac->frequency_range,
mac->current_UL_BWP->channel_bandwidth,
2,
false,
mac->current_UL_BWP->scs,
mac->current_UL_BWP->BWPSize,
true,
get_m_srs(srs_resource->freqHopping.c_SRS, srs_resource->freqHopping.b_SRS),
0); // TODO: Determine SRS start RB
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
int srs_power_without_h_b_f_c = P_0_SRS + alpha * pathloss + m_srs_component;
// Power adjustment state
int h_b_f_c = 0;
bool use_pusch_power_adjustment_state = srs_resource_set->srs_PowerControlAdjustmentStates == NULL;
if (is_configured_for_pusch_on_current_bwp && use_pusch_power_adjustment_state) {
// Case 1: Use PUSCH power control adjustment state
h_b_f_c = mac->f_b_f_c;
} else {
// Case 2: Separate power control adjustment state
AssertFatal(srs_resource_set->srs_PowerControlAdjustmentStates == NULL
|| *srs_resource_set->srs_PowerControlAdjustmentStates
!= NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_sameAsFci2,
"Two PUSCH power adjustment states not supported");
bool is_tpc_accumulation_provided = current_UL_BWP->srs_Config != NULL && current_UL_BWP->srs_Config->tpc_Accumulation != NULL;
bool separate_pc_adjustment_state = srs_resource_set->srs_PowerControlAdjustmentStates
&& *srs_resource_set->srs_PowerControlAdjustmentStates
== NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_separateClosedLoop;
if (!is_tpc_accumulation_provided && (!is_configured_for_pusch_on_current_bwp || separate_pc_adjustment_state)) {
if (!current_UL_BWP->srs_power_control_initialized) {
NR_PRACH_RESOURCES_t *prach_resources = &mac->ra.prach_resources;
float DELTA_P_rampup_requested =
(prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP;
float DELTA_P_rampup = P_CMAX - (P_0_SRS + m_srs_component + alpha * pathloss);
DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup));
current_UL_BWP->srs_power_control_initialized = true;
current_UL_BWP->h_b_f_c = DELTA_P_rampup + mac->delta_msg2;
} else {
int P_CMIN = mac->current_UL_BWP->P_CMIN;
if (!((srs_power_without_h_b_f_c + current_UL_BWP->h_b_f_c >= P_CMAX && delta_srs > 0)
|| (srs_power_without_h_b_f_c + current_UL_BWP->h_b_f_c <= P_CMIN && delta_srs < 0))) {
current_UL_BWP->h_b_f_c += delta_srs;
}
}
h_b_f_c = current_UL_BWP->h_b_f_c;
} else {
// Case 3: No accumulation
h_b_f_c = delta_srs;
}
}
return min(P_CMAX, srs_power_without_h_b_f_c + h_b_f_c);
}
......@@ -1058,7 +1058,8 @@ int configure_srs_pdu(NR_UE_MAC_INST_t *mac,
NR_SRS_Resource_t *srs_resource,
fapi_nr_ul_config_srs_pdu *srs_config_pdu,
int period,
int offset)
int offset,
NR_SRS_ResourceSet_t *srs_resource_set)
{
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
......@@ -1100,6 +1101,11 @@ int configure_srs_pdu(NR_UE_MAC_INST_t *mac,
srs_config_pdu->t_offset = offset;
}
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0; // DCI format 2_3 not implemented
srs_config_pdu->tx_power =
get_srs_tx_power_ue(mac, srs_resource, srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
#ifdef SRS_DEBUG
LOG_I(NR_MAC,"Frame = %i, slot = %i\n", frame, slot);
LOG_I(NR_MAC,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti);
......@@ -1142,10 +1148,11 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
int slot_offset = 0;
NR_SRS_Resource_t *srs_resource = NULL;
NR_SRS_ResourceSet_t *srs_resource_set = NULL;
for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
// Find aperiodic resource set
NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
if(srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_aperiodic)
continue;
// the resource trigger need to match the DCI one
......@@ -1186,7 +1193,7 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, sched_frame, sched_slot, FAPI_NR_UL_CONFIG_TYPE_SRS);
if (!pdu)
return;
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, 0, 0);
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, 0, 0, srs_resource_set);
if (ret != 0)
remove_ul_config_last_item(pdu);
release_ul_config(pdu, false);
......@@ -1204,9 +1211,10 @@ static bool nr_ue_periodic_srs_scheduling(NR_UE_MAC_INST_t *mac, frame_t frame,
}
bool srs_scheduled = false;
NR_SRS_ResourceSet_t *srs_resource_set = NULL;
for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
// Find periodic resource set
NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
if(srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_periodic) {
continue;
}
......@@ -1237,7 +1245,7 @@ static bool nr_ue_periodic_srs_scheduling(NR_UE_MAC_INST_t *mac, frame_t frame,
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame, slot, FAPI_NR_UL_CONFIG_TYPE_SRS);
if (!pdu)
return false;
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, period, offset);
int ret = configure_srs_pdu(mac, srs_resource, &pdu->srs_config_pdu, period, offset, srs_resource_set);
if (ret != 0)
remove_ul_config_last_item(pdu);
else
......
......@@ -594,6 +594,125 @@ TEST(test_pcmax, test_non_obvious_bwp_size)
nr_get_Pcmax(23, nr_band, frame_type, FR1, channel_bandwidth, 2, false, 1, N_RB_UL, false, 6, prb_start));
}
TEST(test_srs_power, use_pusch_power_adjustment_state)
{
NR_UE_MAC_INST_t mac = {0};
NR_UE_UL_BWP_t current_UL_BWP = {0};
current_UL_BWP.scs = 1;
current_UL_BWP.BWPSize = 106;
mac.current_UL_BWP = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
srs_resource_set.srs_PowerControlAdjustmentStates = NULL;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
long p0 = 0;
srs_resource_set.p0 = &p0;
int tx_power = get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
mac.f_b_f_c = 4;
int increased_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + mac.f_b_f_c, increased_tx_power);
}
TEST(test_srs_power, no_support_for_two_pusch_power_adjustment_states)
{
NR_UE_MAC_INST_t mac = {0};
NR_UE_UL_BWP_t current_UL_BWP = {0};
current_UL_BWP.scs = 1;
current_UL_BWP.BWPSize = 106;
mac.current_UL_BWP = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
long p0 = 0;
srs_resource_set.p0 = &p0;
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
long srs_PowerControlAdjustmentStates = NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_sameAsFci2;
srs_resource_set.srs_PowerControlAdjustmentStates = &srs_PowerControlAdjustmentStates;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
EXPECT_DEATH(get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp),
"Two PUSCH power adjustment states not supported");
}
TEST(test_srs_power, no_tpc_accumulation)
{
NR_UE_MAC_INST_t mac = {0};
NR_UE_UL_BWP_t current_UL_BWP = {0};
current_UL_BWP.scs = 1;
current_UL_BWP.BWPSize = 106;
mac.current_UL_BWP = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
long p0 = 0;
srs_resource_set.p0 = &p0;
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
long srs_PowerControlAdjustmentStates = NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_separateClosedLoop;
srs_resource_set.srs_PowerControlAdjustmentStates = &srs_PowerControlAdjustmentStates;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
NR_SRS_Config_t srs_Config = {0};
long tpc_Accumulation = 0;
srs_Config.tpc_Accumulation = &tpc_Accumulation;
current_UL_BWP.srs_Config = &srs_Config;
int tx_power = get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
delta_srs = 4;
int increased_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + delta_srs, increased_tx_power);
}
TEST(test_srs_power, tpc_accumulation)
{
NR_UE_MAC_INST_t mac = {0};
NR_UE_UL_BWP_t current_UL_BWP = {0};
current_UL_BWP.scs = 1;
current_UL_BWP.BWPSize = 106;
mac.current_UL_BWP = &current_UL_BWP;
NR_SRS_Resource_t srs_resource = {0};
NR_SRS_ResourceSet_t srs_resource_set = {0};
long p0 = 0;
srs_resource_set.p0 = &p0;
bool is_configured_for_pusch_on_current_bwp = true;
int delta_srs = 0;
long srs_PowerControlAdjustmentStates = NR_SRS_ResourceSet__srs_PowerControlAdjustmentStates_separateClosedLoop;
srs_resource_set.srs_PowerControlAdjustmentStates = &srs_PowerControlAdjustmentStates;
mac.nr_band = 78;
mac.f_b_f_c = 0;
mac.pusch_power_control_initialized = true;
current_UL_BWP.srs_power_control_initialized = true;
NR_SRS_Config_t srs_Config = {0};
current_UL_BWP.srs_Config = &srs_Config;
int tx_power = get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
delta_srs = 4;
int increased_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + delta_srs, increased_tx_power);
int more_tx_power =
get_srs_tx_power_ue(&mac, &srs_resource, &srs_resource_set, delta_srs, is_configured_for_pusch_on_current_bwp);
EXPECT_EQ(tx_power + delta_srs * 2, more_tx_power);
}
int main(int argc, char** argv)
{
logInit();
......
......@@ -3175,21 +3175,23 @@ void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_le
mac->mac_rrc.initial_ul_rrc_message_transfer(0, &ul_rrc_msg);
}
void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
{
NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
/* activate SRB0 */
if (!nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message))
return false;
/* create this UE's initial CellGroup */
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;
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;
/* activate SRB0 */
nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message);
/* the cellGroup sent to CU specifies there is SRB1, so create it */
DevAssert(cellGroupConfig->rlc_BearerToAddModList->list.count == 1);
const NR_RLC_BearerConfig_t *bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[0];
......@@ -3199,6 +3201,7 @@ void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
int priority = bearer->mac_LogicalChannelConfig->ul_SpecificParameters->priority;
nr_lc_config_t c = {.lcid = bearer->logicalChannelIdentity, .priority = priority};
nr_mac_add_lcid(&UE->UE_sched_ctrl, &c);
return true;
}
void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
......
......@@ -444,20 +444,23 @@ static int nr_process_mac_pdu(instance_t module_idP,
mac_len = 6;
}
LOG_D(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", mac_len, UE->rnti);
prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE);
mac_rlc_data_ind(module_idP,
UE->rnti,
module_idP,
frameP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
0,
(char *) (pduP + mac_subheader_len),
mac_len,
1,
NULL);
LOG_I(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", mac_len, UE->rnti);
if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) {
mac_rlc_data_ind(module_idP,
UE->rnti,
module_idP,
frameP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
0,
(char *) (pduP + mac_subheader_len),
mac_len,
1,
NULL);
} else {
LOG_E(NR_MAC, "prepare_initial_ul_rrc_message() returned false, cannot forward CCCH message\n");
}
break;
case UL_SCH_LCID_DTCH ... (UL_SCH_LCID_DTCH + 28):
......@@ -498,7 +501,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
break;
default:
LOG_E(NR_MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid);
LOG_E(NR_MAC, "RNTI %0x, received unknown MAC header (LCID = 0x%02x)\n", UE->rnti, rx_lcid);
return -1;
break;
}
......
......@@ -449,7 +449,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
long get_lcid_from_drbid(int drb_id);
long get_lcid_from_srbid(int srb_id);
void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE);
bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE);
void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
void finish_nr_dl_harq(NR_UE_sched_ctrl_t *sched_ctrl, int harq_pid);
......
......@@ -983,10 +983,17 @@ void deliver_sdu_srb0(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
s0->send_initial_ul_rrc_message(s0->ue_id, (unsigned char *)buf, size, s0->data);
}
void nr_rlc_activate_srb0(int ue_id,
bool nr_rlc_activate_srb0(int ue_id,
void *data,
void (*send_initial_ul_rrc_message)(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data))
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id);
if (ue->srb0 != NULL) {
LOG_W(RLC, "SRB0 already exists for UE %x, do nothing\n", ue_id);
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return false;
}
struct srb0_data *srb0_data = calloc(1, sizeof(struct srb0_data));
AssertFatal(srb0_data, "out of memory\n");
......@@ -994,21 +1001,13 @@ void nr_rlc_activate_srb0(int ue_id,
srb0_data->data = data;
srb0_data->send_initial_ul_rrc_message = send_initial_ul_rrc_message;
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id);
if (ue->srb0 != NULL) {
LOG_W(RLC, "SRB0 already exists for UE %d, do nothing\n", ue_id);
free(srb0_data);
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return;
}
nr_rlc_entity_t *nr_rlc_tm = new_nr_rlc_entity_tm(10000,
deliver_sdu_srb0, srb0_data);
deliver_sdu_srb0, srb0_data);
nr_rlc_ue_add_srb_rlc_entity(ue, 0, nr_rlc_tm);
LOG_I(RLC, "Activated srb0 for UE %d\n", ue_id);
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return true;
}
rlc_op_status_t rrc_rlc_config_req(const protocol_ctxt_t* const ctxt_pP,
......
......@@ -62,7 +62,7 @@ void nr_rlc_activate_avg_time_to_tx(const int ue_id, const logical_chan_id_t cha
void nr_rlc_srb_recv_sdu(const int ue_id, const logical_chan_id_t channel_id, unsigned char *buf, int size);
void nr_rlc_activate_srb0(int ue_id,
bool nr_rlc_activate_srb0(int ue_id,
void *data,
void (*send_initial_ul_rrc_message)(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data));
......
# Overview
Dockerized tool to list clang-format errors introduced in a branch.
# Usage
Checkout the branch you want to compare. This is necessary because if there are files added by the branch
they need to be present for clang-format to analyze them.
Then:
```
./tools/formatting/detect_clang_format_errors.sh
```
Or
```
docker compose up
```
Or (to avoid docker related lines in stdout)
```
docker compose run clang-formatter | tee output
```
#!/bin/bash
set -eo pipefail
BASE_COMMIT=$(git merge-base HEAD origin/develop)
git diff -U0 --no-color $BASE_COMMIT...HEAD | clang-format-diff -p1
services:
clang-formatter:
image: clang-formatter
build:
dockerfile_inline: |
FROM ubuntu:22.04
RUN DEBIAN_FRONTEND=noninteractive apt update && apt install -y git clang-format
volumes:
- ../../:/code/
command:
bash -c "git config --global --add safe.directory /code && cd /code/ && \
git config --global clangFormat.style file && \
./tools/formatting/detect_clang_format_errors.sh"
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