diff --git a/CMakeLists.txt b/CMakeLists.txt index e9455ec2e9..edd9c18657 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1374,7 +1374,6 @@ set (MAC_NR_SRC_UE ${NR_UE_MAC_DIR}/nr_ue_scheduler.c ${NR_UE_MAC_DIR}/nr_ue_scheduler_sl.c ${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c - ${NR_UE_MAC_DIR}/nr_ra_procedures.c ) set (ENB_APP_SRC @@ -1423,7 +1422,7 @@ endif() add_library(MAC_UE_NR ${MAC_NR_SRC_UE}) -target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs PUBLIC nr_ue_power_procedures) +target_link_libraries(MAC_UE_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs PUBLIC nr_ue_power_procedures nr_ue_ra_procedures) add_library(L2_LTE ${L2_LTE_SRC}) target_link_libraries(L2_LTE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) @@ -1478,7 +1477,7 @@ target_link_libraries(L2_UE PRIVATE asn1_lte_rrc_hdrs) add_library( NR_L2_UE ${NR_L2_SRC_UE} ${MAC_NR_SRC_UE} ) target_link_libraries(NR_L2_UE PRIVATE f1ap nr_rlc) -target_link_libraries(NR_L2_UE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_common nr_ue_power_procedures) +target_link_libraries(NR_L2_UE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_common nr_ue_power_procedures nr_ue_ra_procedures) add_library(MAC_NR_COMMON ${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c diff --git a/ci-scripts/conf_files/nrue.uicc.conf b/ci-scripts/conf_files/nrue.uicc.conf index afd2c0142e..d97a271ff6 100644 --- a/ci-scripts/conf_files/nrue.uicc.conf +++ b/ci-scripts/conf_files/nrue.uicc.conf @@ -6,6 +6,8 @@ uicc0 = { nssai_sst=1; } +thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + #/* configuration for channel modelisation */ #/* To be included in main config file when */ #/* channel modelisation is used (rfsimulator with chanmod options enabled) */ diff --git a/ci-scripts/conf_files/nrue.uicc.yaml b/ci-scripts/conf_files/nrue.uicc.yaml index f2af872ba7..da3b7e7e19 100644 --- a/ci-scripts/conf_files/nrue.uicc.yaml +++ b/ci-scripts/conf_files/nrue.uicc.yaml @@ -5,6 +5,8 @@ uicc0: dnn: oai nssai_sst: 1 +thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + #/* configuration for channel modelisation */ #/* To be included in main config file when */ #/* channel modelisation is used (rfsimulator with chanmod options enabled) */ diff --git a/ci-scripts/conf_files/ue.sa.conf b/ci-scripts/conf_files/ue.sa.conf index 3e6f78f709..9101c7e8e9 100644 --- a/ci-scripts/conf_files/ue.sa.conf +++ b/ci-scripts/conf_files/ue.sa.conf @@ -6,3 +6,5 @@ uicc0 = { nssai_sst=1; nssai_sd=66051; } + +thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 16c02050d2..8c925cbc5f 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -34,6 +34,11 @@ 030020 030021 030022 + 040001 + 020022 + 040002 + 030021 + 030022 100021 222222 @@ -117,11 +122,36 @@ 90 + + Custom_Command + Trigger Reestablishment + cacofonix + echo ci force_reestab | nc 192.168.71.171 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' + yes + + + + Ping + Ping ext-dn from all NR-UEs + rfsim5g_ue + cacofonix + -c 20 192.168.72.135 -i0.5 -w25 + 80 + + + + Custom_Command + Verify Reestablishment + cacofonix + echo ci get_reestab_count | nc 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' + yes + + Custom_Command Simulate a disruption of DL radio channel (ploss 55)(5 sec) cacofonix - echo channelmod modify 0 ploss 55 | nc -N 192.168.71.181 8091 && sleep 5 + echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 && sleep 5 yes @@ -129,7 +159,7 @@ Custom_Command Get UE sync state (UE ID 0) cacofonix - echo ciUE sync_state 0 | nc -N 192.168.71.181 8091 | grep -E UE_NOT_SYNC + echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_NOT_SYNC yes @@ -137,7 +167,7 @@ Custom_Command Restoration of the original DL channel conditions (ploss 0)(5 sec) cacofonix - echo channelmod modify 0 ploss 0 | nc -N 192.168.71.181 8091 && sleep 5 + echo channelmod modify 0 ploss 0 | nc 192.168.71.181 8091 && sleep 5 yes @@ -145,7 +175,7 @@ Custom_Command Get UE sync state (UE ID 0) cacofonix - echo ciUE sync_state 0 | nc -N 192.168.71.181 8091 | grep -E UE_CONNECTED && sleep 10 + echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED && sleep 10 yes diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml index 5d43c89c3c..514672df66 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml @@ -192,7 +192,7 @@ iperf (DL/TCP)(30 sec)(multi-ue profile) -t 30 -R 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 - 4 + 3.9 oc-cn5g diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index c925af1adb..df0a9f4b07 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -87,9 +87,12 @@ services: container_name: rfsim5g-oai-cu cap_drop: - ALL - environment: + environment: USE_ADDITIONAL_OPTIONS: --log_config.global_log_options level,nocolor,time - ASAN_OPTIONS: detect_leaks=0 + --rfsimulator.options chanmod + --telnetsrv --telnetsrv.listenaddr 192.168.71.150 + --telnetsrv.shrmod ci + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-ext-dn networks: @@ -113,6 +116,7 @@ services: --log_config.global_log_options level,nocolor,time --rfsimulator.options chanmod --telnetsrv --telnetsrv.listenaddr 192.168.71.171 + --telnetsrv.shrmod ci ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-cu diff --git a/common/utils/T/tracer/event.c b/common/utils/T/tracer/event.c index f75af1e398..61fb12dd2a 100644 --- a/common/utils/T/tracer/event.c +++ b/common/utils/T/tracer/event.c @@ -94,6 +94,10 @@ event new_event(int type, int length, char *buffer, void *database) e.e[i].type = EVENT_ULONG; e.e[i].ul = *(unsigned long *)(&buffer[offset]); offset += sizeof(unsigned long); + } else if (!strcmp(f.type[i], "float")) { + e.e[i].type = EVENT_FLOAT; + e.e[i].f = *(float *)(&buffer[offset]); + offset += sizeof(float); } else if (!strcmp(f.type[i], "string")) { e.e[i].type = EVENT_STRING; e.e[i].s = &buffer[offset]; diff --git a/common/utils/T/tracer/event.h b/common/utils/T/tracer/event.h index 4e631fbb49..e3d7637bf4 100644 --- a/common/utils/T/tracer/event.h +++ b/common/utils/T/tracer/event.h @@ -13,6 +13,7 @@ enum event_arg_type { EVENT_INT, EVENT_ULONG, + EVENT_FLOAT, EVENT_STRING, EVENT_BUFFER }; @@ -23,6 +24,7 @@ typedef struct { union { int i; unsigned long ul; + float f; char *s; struct { int bsize; diff --git a/common/utils/T/tracer/logger/textlog.c b/common/utils/T/tracer/logger/textlog.c index 8217c2b981..2003ff4233 100644 --- a/common/utils/T/tracer/logger/textlog.c +++ b/common/utils/T/tracer/logger/textlog.c @@ -11,7 +11,7 @@ enum format_item_type { INSTRING, - INT, ULONG, STRING, BUFFER }; + INT, ULONG, FLOAT, STRING, BUFFER }; struct format_item { enum format_item_type type; @@ -67,6 +67,7 @@ static void _event(void *p, event e) case INSTRING: PUTS(&l->o, l->f[i].s); break; case INT: PUTI(&l->o, e.e[l->f[i].event_arg].i); break; case ULONG: PUTUL(&l->o, e.e[l->f[i].event_arg].ul); break; + case FLOAT: PUTF(&l->o, e.e[l->f[i].event_arg].f); break; case STRING: PUTS_CLEAN(&l->o, e.e[l->f[i].event_arg].s); break; case BUFFER: PUTS(&l->o, "{buffer size:"); @@ -106,6 +107,7 @@ static int find_argument(char *name, database_event_format f, *event_arg = i; if (!strcmp(f.type[i], "int")) *it = INT; else if (!strcmp(f.type[i], "ulong")) *it = ULONG; + else if (!strcmp(f.type[i], "float")) *it = FLOAT; else if (!strcmp(f.type[i], "string")) *it = STRING; else if (!strcmp(f.type[i], "buffer")) *it = BUFFER; else return 0; diff --git a/common/utils/T/tracer/utils.c b/common/utils/T/tracer/utils.c index 39e04fb973..78b01a2516 100644 --- a/common/utils/T/tracer/utils.c +++ b/common/utils/T/tracer/utils.c @@ -276,3 +276,9 @@ void PUTUL(OBUF *o, unsigned long l) { sprintf(s, "%lu", l); PUTS(o, s); } + +void PUTF(OBUF *o, float f) { + char s[256]; + sprintf(s, "%g", f); + PUTS(o, s); +} diff --git a/common/utils/T/tracer/utils.h b/common/utils/T/tracer/utils.h index 6784117fa6..e1055d4efa 100644 --- a/common/utils/T/tracer/utils.h +++ b/common/utils/T/tracer/utils.h @@ -50,5 +50,6 @@ void PUTS_CLEAN(OBUF *o, char *s); void PUTI(OBUF *o, int i); void PUTX2(OBUF *o, int i); void PUTUL(OBUF *o, unsigned long i); +void PUTF(OBUF *o, float f); #endif /* _UTILS_H_ */ diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 09dd5e7d94..516c94cb46 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -194,76 +194,80 @@ int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_ // - N_OFFs for bands from 80 to 89 and band 95 is referred to UL // - Frequencies are expressed in KHz // - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster -const nr_bandentry_t nr_bandtable[] = { - {1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, - {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, - {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, - {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, - {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, - {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, - {12, 699000, 716000, 729000, 746000, 20, 145800, 100}, - {13, 777000, 787000, 746000, 756000, 20, 149200, 100}, - {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, - {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, - {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, - {24, 1627500, 1656500, 1526000, 1536000, 20, 305000, 100}, - {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, - {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, - {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, - {29, 000, 000, 717000, 728000, 20, 143400, 100}, - {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, - {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, - {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, - {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, - {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, - {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, - {48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, - {48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, - {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, - {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, - {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, - {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, - {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, - {67, 000, 000, 738000, 758000, 20, 147600, 100}, - {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, - {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, - {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, - {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, - {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, - {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, - {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, - {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, - {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, - {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, - {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, - {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {81, 880000, 915000, 000, 000, 20, 176000, 100}, - {82, 832000, 862000, 000, 000, 20, 166400, 100}, - {83, 703000, 748000, 000, 000, 20, 140600, 100}, - {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, - {85, 698000, 716000, 728000, 746000, 20, 145600, 100}, - {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {89, 824000, 849000, 000, 000, 20, 342000, 100}, - {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, - {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, - {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, - {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, - {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, - {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, - {96, 5925000, 7125000, 5925000, 7125000, 1, 795000, 15}, - {257,26500020,29500000,26500020,29500000, 1,2054166, 60}, - {257,26500080,29500000,26500080,29500000, 2,2054167, 120}, - {258,24250080,27500000,24250080,27500000, 1,2016667, 60}, - {258,24250080,27500000,24250080,27500000, 2,2016667, 120}, - {260,37000020,40000000,37000020,40000000, 1,2229166, 60}, - {260,37000080,40000000,37000080,40000000, 2,2229167, 120}, - {261,27500040,28350000,27500040,28350000, 1,2070833, 60}, - {261,27500040,28350000,27500040,28350000, 2,2070833, 120} -}; +const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, + {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, + {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, + {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, + {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, + {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, + {12, 699000, 716000, 729000, 746000, 20, 145800, 100}, + {13, 777000, 787000, 746000, 756000, 20, 149200, 100}, + {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, + {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, + {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, + {24, 1627500, 1656500, 1526000, 1536000, 20, 305000, 100}, + {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, + {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, + {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, + {29, 000, 000, 717000, 728000, 20, 143400, 100}, + {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, + {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, + {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, + {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, + {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, + {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, + {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, + {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, + {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, + {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, + {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, + {67, 000, 000, 738000, 758000, 20, 147600, 100}, + {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, + {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, + {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, + {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, + {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, + {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, + {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, + {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, + {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, + {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, + {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, + {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {81, 880000, 915000, 000, 000, 20, 176000, 100}, + {82, 832000, 862000, 000, 000, 20, 166400, 100}, + {83, 703000, 748000, 000, 000, 20, 140600, 100}, + {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, + {85, 698000, 716000, 728000, 746000, 20, 145600, 100}, + {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {89, 824000, 849000, 000, 000, 20, 342000, 100}, + {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, + {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, + {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, + {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, + {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, + {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, + {96, 5925000, 7125000, 5925000, 7125000, 1, 795000, 15}, + {254, 1610000, 1626500, 2483500, 2500000, 20, 496700, 100}, + {254, 1610000, 1626500, 2483500, 2500000, 2, 496700, 10}, + {255, 1626500, 1660500, 1525000, 1559000, 20, 305000, 100}, + {255, 1626500, 1660500, 1525000, 1559000, 2, 305000, 10}, + {256, 1980000, 2010000, 2170000, 2200000, 20, 434000, 100}, + {256, 1980000, 2010000, 2170000, 2200000, 2, 434000, 10}, + {257, 26500020, 29500000, 26500020, 29500000, 1, 2054166, 60}, + {257, 26500080, 29500000, 26500080, 29500000, 2, 2054167, 120}, + {258, 24250080, 27500000, 24250080, 27500000, 1, 2016667, 60}, + {258, 24250080, 27500000, 24250080, 27500000, 2, 2016667, 120}, + {260, 37000020, 40000000, 37000020, 40000000, 1, 2229166, 60}, + {260, 37000080, 40000000, 37000080, 40000000, 2, 2229167, 120}, + {261, 27500040, 28350000, 27500040, 28350000, 1, 2070833, 60}, + {261, 27500040, 28350000, 27500040, 28350000, 2, 2070833, 120}}; // synchronization raster per band tables (Rel.15) // (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1) @@ -321,6 +325,11 @@ const sync_raster_t sync_raster[] = { {92, 0, 3584, 1, 3787}, {93, 0, 3572, 1, 3574}, {94, 0, 3584, 1, 3587}, + {254, 0, 6215, 1, 6244}, + {254, 1, 6218, 1, 6241}, + {255, 0, 3818, 1, 3892}, + {255, 1, 3824, 1, 3886}, + {256, 0, 5429, 1, 5494}, {257, 3, 22388, 1, 22558}, {257, 4, 22390, 2, 22556}, {258, 3, 22257, 1, 22443}, diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 43208748d0..9e708efc38 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -67,6 +67,12 @@ static telnetsrv_params_t telnetparams; #define TELNETSRV_OPTNAME_STATICMOD "staticmod" #define TELNETSRV_OPTNAME_SHRMOD "shrmod" +#define TELNET_LOG(fmt, ...) \ + do { \ + printf("[TELNETSRV] " fmt __VA_OPT__(, ) __VA_ARGS__); \ + fflush(stdout); \ + } while (0) + // clang-format off paramdef_t telnetoptions[] = { /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ @@ -653,10 +659,10 @@ void run_telnetsrv(void) { using_history(); int plen=sprintf(prompt,"%s_%s> ",TELNET_PROMPT_PREFIX,get_softmodem_function(NULL)); - printf("\nInitializing telnet server...\n"); + TELNET_LOG("\nInitializing telnet server...\n"); while( (telnetparams.new_socket = accept(sock, &cli_addr, &cli_len)) ) { - printf("[TELNETSRV] Telnet client connected....\n"); + TELNET_LOG("Telnet client connected....\n"); read_history(telnetparams.histfile); stifle_history(telnetparams.histsize); @@ -682,12 +688,12 @@ void run_telnetsrv(void) { } if(!readc) { - printf ("[TELNETSRV] Telnet Client disconnected.\n"); + TELNET_LOG("Telnet Client disconnected.\n"); break; } if (telnetparams.telnetdbg > 0) - printf("[TELNETSRV] Command received: readc %i filled %i \"%s\"\n", readc, filled,buf); + TELNET_LOG("Command received: readc %i filled %i \"%s\"\n", readc, filled, buf); if (buf[0] == '!') { if (buf[1] == '!') { @@ -720,7 +726,7 @@ void run_telnetsrv(void) { send(telnetparams.new_socket, prompt, strlen(prompt), MSG_NOSIGNAL); } else { - printf ("[TELNETSRV] Closing telnet connection...\n"); + TELNET_LOG("Closing telnet connection...\n"); break; } } @@ -728,7 +734,7 @@ void run_telnetsrv(void) { write_history(telnetparams.histfile); clear_history(); close(telnetparams.new_socket); - printf ("[TELNETSRV] Telnet server waitting for connection...\n"); + TELNET_LOG("Telnet server waiting for connection...\n"); } close(sock); @@ -927,7 +933,7 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde cmd[j].qptr = afifo; } } - printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n", i, telnetparams.CmdParsers[i].module); + TELNET_LOG("Telnet server: module %i = %s added to shell\n", i, telnetparams.CmdParsers[i].module); break; } } diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 700ff73135..ba3062178f 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -37,6 +37,7 @@ #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -115,10 +116,8 @@ int get_reestab_count(char *buf, int debug, telnet_printfunc_t prnt) return 0; } -int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt) +int fetch_rnti(char *buf, telnet_printfunc_t prnt) { - if (!RC.nrmac) - ERROR_MSG_RET("no MAC/RLC present, cannot trigger reestablishment\n"); int rnti = -1; if (!buf) { rnti = get_single_ue_rnti_mac(); @@ -129,9 +128,15 @@ int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt) if (rnti < 1 || rnti >= 0xfffe) ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n"); } + return rnti; +} +int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt) +{ + if (!RC.nrmac) + ERROR_MSG_RET("no MAC/RLC present, cannot trigger reestablishment\n"); + int rnti = fetch_rnti(buf, prnt); nr_rlc_test_trigger_reestablishment(rnti); - prnt("Reset RLC counters of UE RNTI %04x to trigger reestablishment\n", rnti); return 0; } @@ -163,7 +168,27 @@ int rrc_gNB_trigger_f1_ho(char *buf, int debug, telnet_printfunc_t prnt) gNB_RRC_UE_t *UE = &ue->ue_context; nr_HO_F1_trigger_telnet(RC.nrrrc[0], UE->rrc_ue_id); prnt("RRC F1 handover triggered for UE %u\n", UE->rrc_ue_id); + return 0; +} +int force_ul_failure(char *buf, int debug, telnet_printfunc_t prnt) +{ + if (!RC.nrmac) + ERROR_MSG_RET("no MAC/RLC present, force_ul_failure failed\n"); + int rnti = fetch_rnti(buf, prnt); + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti); + nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); + return 0; +} + +int force_ue_release(char *buf, int debug, telnet_printfunc_t prnt) +{ + force_ul_failure(buf, debug, prnt); + int rnti = fetch_rnti(buf, prnt); + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti); + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + sched_ctrl->ul_failure_timer = 2; + nr_mac_check_ul_failure(RC.nrmac[0], UE->rnti, sched_ctrl); return 0; } @@ -171,6 +196,8 @@ static telnetshell_cmddef_t cicmds[] = { {"get_single_rnti", "", get_single_rnti}, {"force_reestab", "[rnti(hex,opt)]", trigger_reestab}, {"get_reestab_count", "[rnti(hex,opt)]", get_reestab_count}, + {"force_ue_release", "[rnti(hex,opt)]", force_ue_release}, + {"force_ul_failure", "[rnti(hex,opt)]", force_ul_failure}, {"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho}, {"", "", NULL}, }; diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c index 673d904969..dd95f8009c 100644 --- a/common/utils/telnetsrv/telnetsrv_ciUE.c +++ b/common/utils/telnetsrv/telnetsrv_ciUE.c @@ -36,6 +36,7 @@ #include #include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" +#include "openair2/RRC/NR_UE/rrc_proto.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -73,9 +74,31 @@ int get_sync_state(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +/** + * Force RLF on UE + */ +int force_rlf(char *buf, int debug, telnet_printfunc_t prnt) +{ + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(0); + handle_rlf_detection(rrc); + return 0; +} + +/** + * Send UE to RRC_IDLE + */ +int force_RRC_IDLE(char *buf, int debug, telnet_printfunc_t prnt) +{ + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(0); + nr_rrc_going_to_IDLE(rrc, OTHER, NULL); + return 0; +} + /* Telnet shell command definitions */ static telnetshell_cmddef_t cicmds[] = { {"sync_state", "[UE_ID(int,opt)]", get_sync_state}, + {"force_rlf", "", force_rlf}, + {"force_RRC_IDLE", "", force_RRC_IDLE}, {"", "", NULL}, }; diff --git a/executables/nr-ue.c b/executables/nr-ue.c index bd64a9d361..d6c3086317 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -607,7 +607,13 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc if (UE->synch_request.received_synch_request == 1) { fapi_nr_synch_request_t *synch_req = &UE->synch_request.synch_req; UE->is_synchronized = 0; - UE->UE_scan_carrier = synch_req->ssb_bw_scan; + // if upper layers signal BW scan we do as instructed by command line parameter + // if upper layers disable BW scan we set it to false + if (UE->synch_request.synch_req.ssb_bw_scan) + UE->UE_scan_carrier = get_nrUE_params()->UE_scan_carrier; + else + UE->UE_scan_carrier = false; + UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell; UE->target_Nid_cell = synch_req->target_Nid_cell; uint64_t dl_bw = (12 * fp->N_RB_DL) * (15000 << fp->numerology_index); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index ac5235b108..fbd10c5c04 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -334,7 +334,7 @@ static void trigger_stop(int sig) } static void trigger_deregistration(int sig) { - if (!stop_immediately) { + if (!stop_immediately && IS_SA_MODE(get_softmodem_params())) { MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_DEREGISTRATION_REQ); NAS_DEREGISTRATION_REQ(msg).cause = AS_DETACH; itti_send_msg_to_task(TASK_NAS_NRUE, 0, msg); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index dc2f8eef83..2476833d7c 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -979,6 +979,7 @@ typedef struct uint16_t scramb_id; // ScramblingID of the CSI-RS [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->1023 uint8_t power_control_offset; // Ratio of PDSCH EPRE to NZP CSI-RSEPRE [3GPP TS 38.214, sec 5.2.2.3.1], Value: 0->23 representing -8 to 15 dB in 1dB steps; 255: L1 is configured with ProfileSSS uint8_t power_control_offset_ss; // Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE [3GPP TS 38.214, sec 5.2.2.3.1], Values: 0: -3dB; 1: 0dB; 2: 3dB; 3: 6dB; 255: L1 is configured with ProfileSSS + nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming; } nfapi_nr_dl_tti_csi_rs_pdu_rel15_t; diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 939478f35c..1f5c22c71e 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -30,7 +30,7 @@ static const uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, static const uint16_t nr_slots_per_subframe[MAX_NUM_SUBCARRIER_SPACING] = {1, 2, 4, 8, 16}; // Table 5.4.3.3-1 38-101 -static const int nr_ssb_table[54][3] = { +static const int nr_ssb_table[][3] = { {1, 15, nr_ssb_type_A}, {2, 15, nr_ssb_type_A}, {3, 15, nr_ssb_type_A}, @@ -84,7 +84,12 @@ static const int nr_ssb_table[54][3] = { {92, 15, nr_ssb_type_A}, {93, 15, nr_ssb_type_A}, {94, 15, nr_ssb_type_A}, - {96, 30, nr_ssb_type_C}}; + {96, 30, nr_ssb_type_C}, + {254, 15, nr_ssb_type_A}, + {254, 30, nr_ssb_type_C}, + {255, 15, nr_ssb_type_A}, + {255, 30, nr_ssb_type_B}, + {256, 15, nr_ssb_type_A}}; void set_Lmax(NR_DL_FRAME_PARMS *fp) { // definition of Lmax according to ts 38.213 section 4.1 diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 6cae31d465..54ca8665c3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -80,12 +80,12 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, uint32_t cset_nsymb = pdcch_pdu_rel15->DurationSymbols; int dci_idx = 0; // multi-beam number (for concurrent beams) + int bitmap = SL_to_bitmap(cset_start_symb, pdcch_pdu_rel15->DurationSymbols); int beam_nb = beam_index_allocation(dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx, &gNB->common_vars, slot, frame_parms->symbols_per_slot, - cset_start_symb, - pdcch_pdu_rel15->DurationSymbols); + bitmap); LOG_D(NR_PHY_DCI, "pdcch: Coreset rb_offset %d, nb_rb %d BWP Start %d\n", rb_offset, n_rb, pdcch_pdu_rel15->BWPStart); LOG_D(NR_PHY_DCI, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 321ff3028b..e69e6b2f89 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -471,12 +471,12 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) start_meas(&gNB->dlsch_precoding_stats); nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; // beam number in multi-beam scenario (concurrent beams) + int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols); int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, &gNB->common_vars, slot, frame_parms->symbols_per_slot, - rel15->StartSymbolIndex, - rel15->NrOfSymbols); + bitmap); c16_t **txdataF = gNB->common_vars.txdataF[beam_nb]; diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index a043d93500..3f41712f2c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -85,12 +85,8 @@ void nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *p int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; // TODO no idea how to compute final prach symbol here so for now we go til the end of the slot int temp_nb_symbols = NR_NUMBER_OF_SYMBOLS_PER_SLOT - prach_pdu->prach_start_symbol; - prach->beam_nb = beam_index_allocation(fapi_beam_idx, - &gNB->common_vars, - Slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, - prach_pdu->prach_start_symbol, - temp_nb_symbols); + int bitmap = SL_to_bitmap(prach_pdu->prach_start_symbol, temp_nb_symbols); + prach->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, Slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap); } LOG_D(NR_PHY,"Copying prach pdu %d bytes to index %d\n", (int)sizeof(*prach_pdu), prach_id); memcpy(&prach->pdu, prach_pdu, sizeof(*prach_pdu)); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 47a0afc625..982b236b70 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -75,12 +75,8 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t ulsch->beam_nb = 0; if (gNB->common_vars.beam_id) { int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; - ulsch->beam_nb = beam_index_allocation(fapi_beam_idx, - &gNB->common_vars, - slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, - ulsch_pdu->start_symbol_index, - ulsch_pdu->nr_of_symbols); + int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols); + ulsch->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap); } ulsch->frame = frame; ulsch->slot = slot; diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 084046cc38..72cb374470 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -75,12 +75,8 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, pucch->beam_nb = 0; if (gNB->common_vars.beam_id) { int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; - pucch->beam_nb = beam_index_allocation(fapi_beam_idx, - &gNB->common_vars, - slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, - pucch_pdu->start_symbol_index, - pucch_pdu->nr_of_symbols); + int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols); + pucch->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap); } memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); LOG_D(PHY, diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index 931bfe21e7..49ae659a06 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -57,13 +57,9 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu srs->active = true; srs->beam_nb = 0; if (gNB->common_vars.beam_id) { + int bitmap = SL_to_bitmap(srs_pdu->time_start_position, 1 << srs_pdu->num_symbols); int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; - srs->beam_nb = beam_index_allocation(fapi_beam_idx, - &gNB->common_vars, - slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, - srs_pdu->time_start_position, - 1 << srs_pdu->num_symbols); + srs->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap); } memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t)); break; diff --git a/openair1/PHY/TOOLS/tests/test_vector_op.cpp b/openair1/PHY/TOOLS/tests/test_vector_op.cpp index 6173c40e7e..02d5df5fcd 100644 --- a/openair1/PHY/TOOLS/tests/test_vector_op.cpp +++ b/openair1/PHY/TOOLS/tests/test_vector_op.cpp @@ -46,6 +46,30 @@ int main() for (int vector_size = 1237; vector_size < 1237 + 8; vector_size++) { auto input1 = generate_random_c16(vector_size); auto input2 = generate_random_c16(vector_size); + + // Clip the input for -32768 because this will make different result + // C version promote the int16 to int before doing the conjugate (so negate imaginary part) + // simd version do it on the int16, so the result overflows to -32768 + // other overflows exist, but they make the same + // in C we do with int promotion, for real part: + // (int)x.r*(int)y.r - (int)x.i*(int)y.i + // that can overflow because each multiplication result is full int range + // so when we sum, it overflows + // _mm256_madd_epi16() overflows also, as do regular addition instruction + // so the result will be the same (the same wrong value) + + for(auto it = input1.begin(); it != input1.end(); it++ ) { + if (it->r == -32768) + it->r=-32767; + if (it->i == -32768) + it->i=-32767; + } + for(auto it = input2.begin(); it != input2.end(); it++ ) { + if (it->r == -32768) + it->r=-32767; + if (it->i == -32768) + it->i=-32767; + } AlignedVector512 output; output.resize(vector_size); mult_complex_vectors(input1.data(), input2.data(), output.data(), vector_size, shift); diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h index 7f9dfad719..16d5854604 100644 --- a/openair1/PHY/impl_defs_nr.h +++ b/openair1/PHY/impl_defs_nr.h @@ -487,16 +487,6 @@ typedef enum { reserved = 7 } PUCCH_MaxCodeRate_t; -typedef struct { - pucch_format_nr_t format; - uint8_t startingSymbolIndex; - uint8_t nrofSymbols; - uint16_t PRB_offset; - uint8_t nb_CS_indexes; - uint8_t initial_CS_indexes[MAX_NB_CYCLIC_SHIFT]; -} initial_pucch_resource_t; - - /*********************************************************************** * * FUNCTIONALITY : Scheduling Request Configuration (SR) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index a56c01ce99..73eda60dcd 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -43,19 +43,16 @@ //#define DEBUG_RXDATA //#define SRS_IND_DEBUG -int beam_index_allocation(int fapi_beam_index, - NR_gNB_COMMON *common_vars, - int slot, - int symbols_per_slot, - int start_symbol, - int nb_symbols) +int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, int bitmap_symbols) { if (!common_vars->beam_id) return 0; int idx = -1; for (int j = 0; j < common_vars->num_beams_period; j++) { - for (int i = start_symbol; i < start_symbol + nb_symbols; i++) { + for (int i = 0; i < symbols_per_slot; i++) { + if (((bitmap_symbols >> i) & 0x01) == 0) + continue; int current_beam = common_vars->beam_id[j][slot * symbols_per_slot + i]; if (current_beam == -1 || current_beam == fapi_beam_index) idx = j; @@ -68,8 +65,10 @@ int beam_index_allocation(int fapi_beam_index, break; } AssertFatal(idx >= 0, "Couldn't allocate beam ID %d\n", fapi_beam_index); - for (int j = start_symbol; j < start_symbol + nb_symbols; j++) - common_vars->beam_id[idx][slot * symbols_per_slot + j] = fapi_beam_index; + for (int j = 0; j < symbols_per_slot; j++) { + if (((bitmap_symbols >> j) & 0x01)) + common_vars->beam_id[idx][slot * symbols_per_slot + j] = fapi_beam_index; + } LOG_D(PHY, "Allocating beam %d in slot %d\n", idx, slot); return idx; } @@ -129,12 +128,12 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n c16_t ***txdataF = gNB->common_vars.txdataF; int txdataF_offset = slot * fp->samples_per_slot_wCP; // beam number in a scenario with multiple concurrent beams + int bitmap = SL_to_bitmap(ssb_start_symbol, 4); // 4 ssb symbols int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, &gNB->common_vars, slot, fp->symbols_per_slot, - ssb_start_symbol, - 4); // 4 ssb symbols + bitmap); nr_generate_pss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp); nr_generate_sss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp); @@ -253,7 +252,6 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, for (int i = 0; i < NR_SYMBOLS_PER_SLOT; i++){ NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[i]; if (csirs->active == 1) { - AssertFatal(gNB->common_vars.beam_id == NULL, "Cannot handle CSI in the framework of beamforming yet\n"); LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot); nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csirs->csirs_pdu.csi_rs_pdu_rel15; if (csi_params->csi_type == 2) { // ZP-CSI @@ -264,8 +262,19 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, csi_params->freq_domain, csi_params->symb_l0, csi_params->symb_l1); + nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming; + int csi_bitmap = 0; + int lprime_num = mapping_parms.lprime + 1; + for (int j = 0; j < mapping_parms.size; j++) + csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j]; + int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, + &gNB->common_vars, + slot, + fp->symbols_per_slot, + csi_bitmap); + nr_generate_csi_rs(&gNB->frame_parms, - (int32_t **)gNB->common_vars.txdataF[0], + (int32_t **)gNB->common_vars.txdataF[beam_nb], gNB->TX_AMP, csi_params, slot, diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 6cde0e8614..20028cea9f 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -47,10 +47,5 @@ void feptx_prec(RU_t *ru,int frame_tx,int tti_tx); int nr_phy_init_RU(RU_t *ru); void nr_phy_free_RU(RU_t *ru); void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot); -int beam_index_allocation(int fapi_beam_index, - NR_gNB_COMMON *common_vars, - int slot, - int symbols_per_slot, - int start_symbol, - int nb_symbols); +int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, int bitmap_symbols); #endif diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 085317b0df..2be6faeb9c 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -409,13 +409,13 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, if (ret==0) { #ifdef DEBUG_PHY_PROC - uint16_t frame_tx; - LOG_D(PHY,"[UE %d] frame %d, nr_slot_rx %d, Received PBCH (MIB): frame_tx %d. N_RB_DL %d\n", - ue->Mod_id, - frame_rx, - nr_slot_rx, - frame_tx, - ue->frame_parms.N_RB_DL); + LOG_D(PHY, + "[UE %d] frame %d, nr_slot_rx %d, Received PBCH (MIB): ssb idx: %d, N_RB_DL %d\n", + ue->Mod_id, + frame_rx, + nr_slot_rx, + ssb_index, + ue->frame_parms.N_RB_DL); #endif } else { @@ -882,12 +882,21 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, return dec; } +static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index) +{ + if (ue->received_config_request) { + const fapi_nr_config_request_t *cfg = &ue->nrUE_config; + const uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[index / 32].ssb_mask; + return ((curr_mask >> (31 - (index % 32))) & 0x01); + } else + return ue->frame_parms.ssb_index == index; +} + int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) { int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; int gNB_id = proc->gNB_id; - fapi_nr_config_request_t *cfg = &ue->nrUE_config; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; int sampleShift = INT_MAX; @@ -901,16 +910,18 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; __attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; // checking if current frame is compatible with SSB periodicity - if (cfg->ssb_table.ssb_period == 0 || !(frame_rx % (1 << (cfg->ssb_table.ssb_period - 1)))) { + + const int default_ssb_period = 2; + const int ssb_period = ue->received_config_request ? ue->nrUE_config.ssb_table.ssb_period : default_ssb_period; + if (ssb_period == 0 || !(frame_rx % (1 << (ssb_period - 1)))) { const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size; // loop over SSB blocks - for(int ssb_index=0; ssb_indexLmax; ssb_index++) { - uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[ssb_index/32].ssb_mask; - // check if if current SSB is transmitted - if ((curr_mask >> (31-(ssb_index%32))) &0x01) { + for (int ssb_index = 0; ssb_index < fp->Lmax; ssb_index++) { + // check if current SSB is transmitted + if (is_ssb_index_transmitted(ue, ssb_index)) { int ssb_start_symbol = nr_get_ssb_start_symbol(fp, ssb_index); int ssb_slot = ssb_start_symbol/fp->symbols_per_slot; - int ssb_slot_2 = (cfg->ssb_table.ssb_period == 0) ? ssb_slot+(fp->slots_per_frame>>1) : -1; + int ssb_slot_2 = (ssb_period == 0) ? ssb_slot + (fp->slots_per_frame >> 1) : -1; if (ssb_slot == nr_slot_rx || ssb_slot_2 == nr_slot_rx) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_IN); diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index ef09d98284..fb94aeb29e 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -85,3 +85,6 @@ MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFramePr // eNB: RLC -> RRC messages MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) MESSAGE_DEF(NAS_PDU_SESSION_REQ, MESSAGE_PRIORITY_MED, nas_pdu_session_req_t, nas_pdu_session_req) + +// UE: RLC -> RRC messages +MESSAGE_DEF(NR_RRC_RLC_MAXRTX, MESSAGE_PRIORITY_MED, RlcMaxRtxIndication, nr_rlc_maxrtx_indication) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 15509b1807..0e57120ee4 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -97,6 +97,8 @@ #define NAS_OAI_TUN_NSA(mSGpTR) (mSGpTR)->ittiMsg.nas_oai_tun_nsa #define NAS_PDU_SESSION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdu_session_req +#define NR_RRC_RLC_MAXRTX(mSGpTR) (mSGpTR)->ittiMsg.nr_rlc_maxrtx_indication + //-------------------------------------------------------------------------------------------// typedef struct RrcStateInd_s { Rrc_State_t state; @@ -453,4 +455,8 @@ typedef struct rlc_sdu_indication_s { int message_id; } RlcSduIndication; +typedef struct { + int ue_id; +} RlcMaxRtxIndication; + #endif /* RRC_MESSAGES_TYPES_H_ */ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index b7e2da6f10..04304f8b9a 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -122,6 +122,11 @@ static inline int get_mac_len(uint8_t *pdu, uint32_t pdu_len, uint16_t *mac_ce_l *mac_subheader_len = sizeof(*s); *mac_ce_len = s->L; } + if (*mac_ce_len > pdu_len) { + LOG_E(NR_MAC, "MAC sdu len impossible (%d)\n", *mac_ce_len); + return false; + } + return true; } @@ -133,8 +138,6 @@ typedef struct { uint8_t LcgID: 3; // octet 1 MSB } __attribute__ ((__packed__)) NR_BSR_SHORT; -typedef NR_BSR_SHORT NR_BSR_SHORT_TRUNCATED; - // Long BSR for all logical channel group ID typedef struct { uint8_t LcgID0: 1; // octet 1 [0] @@ -144,19 +147,9 @@ typedef struct { uint8_t LcgID4: 1; // octet 1 [4] uint8_t LcgID5: 1; // octet 1 [5] uint8_t LcgID6: 1; // octet 1 [6] - uint8_t LcgID7: 1; // octet 1 [7] - uint8_t Buffer_size0: 8; // octet 2 [7:0] - uint8_t Buffer_size1: 8; // octet 3 [7:0] - uint8_t Buffer_size2: 8; // octet 4 [7:0] - uint8_t Buffer_size3: 8; // octet 5 [7:0] - uint8_t Buffer_size4: 8; // octet 6 [7:0] - uint8_t Buffer_size5: 8; // octet 7 [7:0] - uint8_t Buffer_size6: 8; // octet 8 [7:0] - uint8_t Buffer_size7: 8; // octet 9 [7:0] + uint8_t LcgID7: 1; // octet 1 [7] } __attribute__ ((__packed__)) NR_BSR_LONG; -typedef NR_BSR_LONG NR_BSR_LONG_TRUNCATED; - // 38.321 ch. 6.1.3.4 typedef struct { uint8_t TA_COMMAND: 6; // octet 1 [5:0] diff --git a/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt b/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt index 6589a2fda5..aa583c8598 100644 --- a/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt +++ b/openair2/LAYER2/NR_MAC_UE/CMakeLists.txt @@ -1,5 +1,7 @@ add_library(nr_ue_power_procedures nr_ue_power_procedures.c) target_link_libraries(nr_ue_power_procedures PUBLIC asn1_nr_rrc ${T_LIB} MAC_NR_COMMON nr_common) +add_library(nr_ue_ra_procedures nr_ra_procedures.c) +target_link_libraries(nr_ue_ra_procedures PUBLIC asn1_nr_rrc asn1_lte_rrc_hdrs ${T_LIB} MAC_NR_COMMON nr_common) if (ENABLE_TESTS) add_subdirectory(tests) endif() diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 3c66515eef..80e2255aa5 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1611,8 +1611,7 @@ static void configure_timeAlignmentTimer(NR_timer_t *time_alignment_timer, NR_Ti nr_timer_start(time_alignment_timer); } -void nr_rrc_mac_config_req_reset(module_id_t module_id, - NR_UE_MAC_reset_cause_t cause) +void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -1621,8 +1620,8 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, switch (cause) { case GO_TO_IDLE: reset_ra(mac, true); - release_mac_configuration(mac, cause); nr_ue_init_mac(mac); + release_mac_configuration(mac, cause); nr_ue_mac_default_configs(mac); // new sync but no target cell id -> -1 nr_ue_send_synch_request(mac, module_id, 0, &sync_req); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 426d8f88d1..1530846d6b 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -70,8 +70,7 @@ #define NR_BSR_TRIGGER_NONE (0) /* No BSR Trigger */ #define NR_BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */ -#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */ -#define NR_BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */ +#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */ #define NR_INVALID_LCGID (NR_MAX_NUM_LCGID) @@ -184,6 +183,15 @@ typedef enum { #undef UE_STATE } NR_UE_L2_STATE_t; +typedef struct { + pucch_format_nr_t format; + uint8_t startingSymbolIndex; + uint8_t nrofSymbols; + uint16_t PRB_offset; + uint8_t nb_CS_indexes; + uint8_t initial_CS_indexes[MAX_NB_CYCLIC_SHIFT]; +} initial_pucch_resource_t; + typedef enum { GO_TO_IDLE, DETACH, @@ -194,8 +202,6 @@ typedef enum { typedef struct { // after multiplexing buffer remain for each lcid int32_t LCID_buffer_remain; - // buffer status for each lcid - bool LCID_buffer_with_data; // logical channel group id of this LCID long LCGID; // Bj bucket usage per lcid @@ -203,13 +209,6 @@ typedef struct { NR_timer_t Bj_timer; } NR_LC_SCHEDULING_INFO; -typedef struct { - // buffer status for each lcgid - uint8_t BSR; // should be more for mesh topology - // keep the number of bytes in rlc buffer for each lcgid - int32_t BSR_bytes; -} NR_LCG_SCHEDULING_INFO; - typedef struct { bool active_SR_ID; /// SR pending as defined in 38.321 @@ -244,8 +243,6 @@ typedef struct { typedef struct { // lcs scheduling info NR_LC_SCHEDULING_INFO lc_sched_info[NR_MAX_NUM_LCID]; - // lcg scheduling info - NR_LCG_SCHEDULING_INFO lcg_sched_info[NR_MAX_NUM_LCGID]; // SR INFO nr_sr_info_t sr_info[NR_MAX_SR_ID]; /// BSR report flag management diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 6feca8756e..094d1e5965 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -172,13 +172,22 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac,nr_downlink_indication_t *dl_info, int pdu_id); +typedef struct { + union { + NR_BSR_SHORT s; + NR_BSR_LONG l; + uint8_t lcg_bsr[8]; + } bsr; + enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr; +} type_bsr_t; + +int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end); + int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom, - uint16_t *crnti, - NR_BSR_SHORT *truncated_bsr, - NR_BSR_SHORT *short_bsr, - NR_BSR_LONG *long_bsr); + const type_bsr_t *bsr, + uint8_t *mac_ce_end); void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, @@ -188,16 +197,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot); -uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, - int cc_id, - frame_t frameP, - sub_frame_t subframe, - uint8_t gNB_index, - uint8_t *ulsch_buffer, - uint32_t buflen, - int16_t tx_power, - int16_t P_CMAX); - void set_harq_status(NR_UE_MAC_INST_t *mac, uint8_t pucch_id, uint8_t harq_id, @@ -210,7 +209,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, int slot); bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); - +initial_pucch_resource_t get_initial_pucch_resource(const int idx); void multiplex_pucch_resource(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, int num_res); int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index f535d7f3b8..68dd57efd1 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -192,7 +192,6 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) for (int i = 0; i < NR_MAX_NUM_LCID; i++) { LOG_D(NR_MAC, "Applying default logical channel config for LCID %d\n", i); nr_mac->scheduling_info.lc_sched_info[i].Bj = 0; - nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false; nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0; } @@ -326,27 +325,3 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca for (int i = mac->TAG_list.count; i > 0 ; i--) asn_sequence_del(&mac->TAG_list, i - 1, 1); } - -void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id) -{ - for (int j = 0; j < MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD; j++) - for (int k = 0; k < MAX_NB_FRAME_IN_PRACH_CONF_PERIOD; k++) - for (int l = 0; l < MAX_NB_SLOT_IN_FRAME; l++) - free(nr_mac->prach_assoc_pattern[bwp_id].prach_conf_period_list[j].prach_occasion_slot_map[k][l].prach_occasion); - - free(nr_mac->ssb_list[bwp_id].tx_ssb); -} - -void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach) -{ - RA_config_t *ra = &nr_mac->ra; - if(ra->rach_ConfigDedicated) - asn1cFreeStruc(asn_DEF_NR_RACH_ConfigDedicated, ra->rach_ConfigDedicated); - memset(ra, 0, sizeof(RA_config_t)); - - if (!free_prach) - return; - - for (int i = 0; i < MAX_NUM_BWP_UE; i++) - free_rach_structures(nr_mac, i); -} diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 493d90eaf6..53f29ff056 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -785,7 +785,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB } else if (!IS_SA_MODE(get_softmodem_params())) { uint8_t temp_pdu[16] = {0}; - size_sdu = nr_write_ce_ulsch_pdu(temp_pdu, mac, 0, &(mac->crnti), NULL, NULL, NULL); + size_sdu = nr_write_ce_msg3_pdu(temp_pdu, mac, mac->crnti, temp_pdu + sizeof(temp_pdu)); ra->Msg3_size = size_sdu; } } else if (ra->RA_window_cnt != -1) { // RACH is active @@ -1076,3 +1076,27 @@ void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) remove_ul_config_last_item(pdu); release_ul_config(pdu, false); } + +void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id) +{ + for (int j = 0; j < MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD; j++) + for (int k = 0; k < MAX_NB_FRAME_IN_PRACH_CONF_PERIOD; k++) + for (int l = 0; l < MAX_NB_SLOT_IN_FRAME; l++) + free(nr_mac->prach_assoc_pattern[bwp_id].prach_conf_period_list[j].prach_occasion_slot_map[k][l].prach_occasion); + + free(nr_mac->ssb_list[bwp_id].tx_ssb); +} + +void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach) +{ + RA_config_t *ra = &nr_mac->ra; + if (ra->rach_ConfigDedicated) + asn1cFreeStruc(asn_DEF_NR_RACH_ConfigDedicated, ra->rach_ConfigDedicated); + memset(ra, 0, sizeof(RA_config_t)); + + if (!free_prach) + return; + + for (int i = 0; i < MAX_NUM_BWP_UE; i++) + free_rach_structures(nr_mac, i); +} diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index bd233f2163..c871a696da 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1514,6 +1514,11 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, current_harq->dai_cumul); } +initial_pucch_resource_t get_initial_pucch_resource(const int idx) +{ + return initial_pucch_resource[idx]; +} + int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame, @@ -1534,10 +1539,9 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, LOG_D(NR_MAC, "initial_pucch_id %d, pucch_resource %p\n", pucch->initial_pucch_id, pucch->pucch_resource); // configure pucch from Table 9.2.1-1 // only for ack/nack - if (pucch->initial_pucch_id > -1 && - pucch->pucch_resource == NULL) { + if (pucch->initial_pucch_id > -1 && pucch->pucch_resource == NULL) { const int idx = *current_UL_BWP->pucch_ConfigCommon->pucch_ResourceCommon; - const initial_pucch_resource_t pucch_resourcecommon = initial_pucch_resource[idx]; + const initial_pucch_resource_t pucch_resourcecommon = get_initial_pucch_resource(idx); pucch_pdu->format_type = pucch_resourcecommon.format; pucch_pdu->start_symbol_index = pucch_resourcecommon.startingSymbolIndex; pucch_pdu->nr_of_symbols = pucch_resourcecommon.nrofSymbols; @@ -2524,7 +2528,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n"); } } - return sr_count > 0 ? true : false; + return sr_count > 0; } int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id) @@ -2537,12 +2541,14 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_Schedu return 0; } - LOG_D(NR_MAC, "[UE %d] Frame %d slot %d SR %s for ID %ld\n", + LOG_D(NR_MAC, + "[UE %d] Frame %d slot %d SR %s for ID %ld, timer %d\n", mac->ue_id, frame, slot, sr_info->pending ? "pending" : "not pending", - sr_id); // todo + sr_id, // todo + nr_timer_is_active(&sr_info->prohibitTimer)); // TODO check if the PUCCH resource for the SR transmission occasion does not overlap with a UL-SCH resource if (!sr_info->pending || nr_timer_is_active(&sr_info->prohibitTimer)) @@ -3772,9 +3778,23 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i } } +int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end) +{ + uint8_t *pdu = mac_ce; + if (IS_SA_MODE(get_softmodem_params()) && mac->ra.ra_state != nrRA_SUCCEEDED) { + LOG_D(NR_MAC, "Generating C-RNTI MAC CE with C-RNTI %x\n", crnti); + *(NR_MAC_SUBHEADER_FIXED *)mac_ce = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_C_RNTI}; + mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED); + // C-RNTI MAC CE (2 octets) + memcpy(mac_ce, &crnti, sizeof(crnti)); + // update pointer and length + mac_ce += sizeof(crnti); + } + return mac_ce - pdu; +} + /** * Function: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU - * Notes: TODO: PHR and BSR reporting * Parameters: * @mac_ce pointer to the MAC sub-PDUs including the MAC CEs * @mac pointer to the MAC instance @@ -3783,158 +3803,98 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom, - uint16_t *crnti, - NR_BSR_SHORT *truncated_bsr, - NR_BSR_SHORT *short_bsr, - NR_BSR_LONG *long_bsr) + const type_bsr_t *bsr, + uint8_t *mac_ce_end) { - int mac_ce_len = 0; uint8_t *pdu = mac_ce; if (power_headroom) { // MAC CE fixed subheader - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR; - mac_ce++; - - // PHR MAC CE (1 octet) - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PH = power_headroom->PH; - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R1 = 0; - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PCMAX = power_headroom->PCMAX; - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R2 = 0; - - // update pointer and length - int mac_ce_size = sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE); - mac_ce += mac_ce_size; - mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); + *(NR_MAC_SUBHEADER_FIXED *)mac_ce = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR}; + mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED); + *(NR_SINGLE_ENTRY_PHR_MAC_CE *)mac_ce = *power_headroom; + mac_ce += sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE); LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : power_headroom pdu %p mac_ce %p b\n", pdu, mac_ce); } - if (crnti && (!IS_SA_MODE(get_softmodem_params()) && get_softmodem_params()->do_ra && mac->ra.ra_state != nrRA_SUCCEEDED)) { - LOG_D(NR_MAC, "In %s: generating C-RNTI MAC CE with C-RNTI %x\n", __FUNCTION__, (*crnti)); - - // MAC CE fixed subheader - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_C_RNTI; - mac_ce++; - - // C-RNTI MAC CE (2 octets) - memcpy(mac_ce, crnti, sizeof(*crnti)); - - // update pointer and length - int mac_ce_size = sizeof(uint16_t); - mac_ce += mac_ce_size; - mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); + switch (bsr->type_bsr) { + case b_short: + case b_short_trunc: { + *(NR_MAC_SUBHEADER_FIXED *)mac_ce = + (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = bsr->type_bsr == b_short ? UL_SCH_LCID_S_BSR : UL_SCH_LCID_S_TRUNCATED_BSR}; + mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED); + *(NR_BSR_SHORT *)mac_ce = bsr->bsr.s; + mac_ce += sizeof(NR_BSR_SHORT); + LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : bsr Buffer_size %d LcgID %d \n", bsr->bsr.s.Buffer_size, bsr->bsr.s.LcgID); + } break; + case b_long: + case b_long_trunc: { + // ch 6.1.3.1. TS 38.321 + NR_MAC_SUBHEADER_SHORT *mac_pdu_subheader_ptr = (NR_MAC_SUBHEADER_SHORT *)mac_ce; + mac_ce += sizeof(NR_MAC_SUBHEADER_SHORT); + uint8_t *mark = mac_ce; + // Could move to nr_get_sdu() + NR_BSR_LONG *ceLong = (NR_BSR_LONG *)mac_ce; + *ceLong = (NR_BSR_LONG){0}; + mac_ce += sizeof(NR_BSR_LONG); + // int NR_BSR_LONG_SIZE = 1; + if (bsr->bsr.lcg_bsr[0] && mac_ce < mac_ce_end) { + ceLong->LcgID0 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[0]; + } + if (bsr->bsr.lcg_bsr[1] && mac_ce < mac_ce_end) { + ceLong->LcgID1 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[1]; + } + if (bsr->bsr.lcg_bsr[2] && mac_ce < mac_ce_end) { + ceLong->LcgID2 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[2]; + } + if (bsr->bsr.lcg_bsr[3] && mac_ce < mac_ce_end) { + ceLong->LcgID3 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[3]; + } + if (bsr->bsr.lcg_bsr[4] && mac_ce < mac_ce_end) { + ceLong->LcgID4 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[4]; + } + if (bsr->bsr.lcg_bsr[5] && mac_ce < mac_ce_end) { + ceLong->LcgID5 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[5]; + } + if (bsr->bsr.lcg_bsr[6] && mac_ce < mac_ce_end) { + ceLong->LcgID6 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[6]; + } + if (bsr->bsr.lcg_bsr[7] && mac_ce < mac_ce_end) { + ceLong->LcgID7 = 1; + *mac_ce++ = bsr->bsr.lcg_bsr[7]; + } + *mac_pdu_subheader_ptr = + (NR_MAC_SUBHEADER_SHORT){.LCID = bsr->type_bsr == b_long ? UL_SCH_LCID_L_BSR : UL_SCH_LCID_L_TRUNCATED_BSR, + .L = mac_ce - mark}; + LOG_D(NR_MAC, + "[UE] Generating ULSCH PDU : long_bsr size %d Lcgbit 0x%02x Buffer_size %d %d %d %d %d %d %d %d\n", + ((NR_MAC_SUBHEADER_SHORT *)mac_pdu_subheader_ptr)->L, + *mac_ce, + bsr->bsr.lcg_bsr[0], + bsr->bsr.lcg_bsr[1], + bsr->bsr.lcg_bsr[2], + bsr->bsr.lcg_bsr[3], + bsr->bsr.lcg_bsr[4], + bsr->bsr.lcg_bsr[5], + bsr->bsr.lcg_bsr[6], + bsr->bsr.lcg_bsr[7]); + } break; + case b_none: + break; + default: + DevAssert(false); } - if (truncated_bsr) { - - // MAC CE fixed subheader - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_TRUNCATED_BSR; - mac_ce++; - - // Short truncated BSR MAC CE (1 octet) - ((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> Buffer_size = truncated_bsr->Buffer_size; - ((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> LcgID = truncated_bsr->LcgID;; - - // update pointer and length - int mac_ce_size = sizeof(NR_BSR_SHORT_TRUNCATED); - mac_ce += mac_ce_size; - mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); - LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : truncated_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n", - truncated_bsr->Buffer_size, truncated_bsr->LcgID, pdu, mac_ce); - - } else if (short_bsr) { - - // MAC CE fixed subheader - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_BSR; - mac_ce++; - - // Short truncated BSR MAC CE (1 octet) - ((NR_BSR_SHORT *) mac_ce)->Buffer_size = short_bsr->Buffer_size; - ((NR_BSR_SHORT *) mac_ce)->LcgID = short_bsr->LcgID; - - // update pointer and length - int mac_ce_size = sizeof(NR_BSR_SHORT); - mac_ce += mac_ce_size; - mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); - LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : short_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n", - short_bsr->Buffer_size, short_bsr->LcgID, pdu, mac_ce); - } else if (long_bsr) { - - // MAC CE variable subheader - // ch 6.1.3.1. TS 38.321 - ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->R = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->F = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->LCID = UL_SCH_LCID_L_BSR; - - NR_MAC_SUBHEADER_SHORT *mac_pdu_subheader_ptr = (NR_MAC_SUBHEADER_SHORT *) mac_ce; - mac_ce += 2; - - // Could move to nr_get_sdu() - uint8_t *Buffer_size_ptr= (uint8_t*) mac_ce + 1; - //int NR_BSR_LONG_SIZE = 1; - if (long_bsr->Buffer_size0 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID0 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID0 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size0; - } - if (long_bsr->Buffer_size1 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID1 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID1 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size1; - } - if (long_bsr->Buffer_size2 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID2 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID2 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size2; - } - if (long_bsr->Buffer_size3 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID3 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID3 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size3; - } - if (long_bsr->Buffer_size4 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID4 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID4 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size4; - } - if (long_bsr->Buffer_size5 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID5 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID5 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size5; - } - if (long_bsr->Buffer_size6 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID6 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID6 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size6; - } - if (long_bsr->Buffer_size7 == 0) { - ((NR_BSR_LONG *) mac_ce)->LcgID7 = 0; - } else { - ((NR_BSR_LONG *) mac_ce)->LcgID7 = 1; - *Buffer_size_ptr++ = long_bsr->Buffer_size7; - } - int mac_ce_size = ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_subheader_ptr)->L = (uint8_t*) Buffer_size_ptr - (uint8_t*) mac_ce; - LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : long_bsr size %d Lcgbit 0x%02x Buffer_size %d %d %d %d %d %d %d %d\n", mac_ce_size, *((uint8_t*) mac_ce), - ((NR_BSR_LONG *) mac_ce)->Buffer_size0, ((NR_BSR_LONG *) mac_ce)->Buffer_size1, ((NR_BSR_LONG *) mac_ce)->Buffer_size2, ((NR_BSR_LONG *) mac_ce)->Buffer_size3, - ((NR_BSR_LONG *) mac_ce)->Buffer_size4, ((NR_BSR_LONG *) mac_ce)->Buffer_size5, ((NR_BSR_LONG *) mac_ce)->Buffer_size6, ((NR_BSR_LONG *) mac_ce)->Buffer_size7); - mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_SHORT); - } - - return mac_ce_len; + return mac_ce - pdu; } - ///////////////////////////////////// // Random Access Response PDU // // TS 38.213 ch 8.2 // diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 26b2f35e0f..ff44c21541 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -68,6 +68,16 @@ static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac, float tx_power, frame_t frameP, sub_frame_t subframe); +static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, + int cc_id, + frame_t frameP, + sub_frame_t subframe, + uint8_t gNB_index, + uint8_t *ulsch_buffer, + const uint32_t buflen, + int tx_power, + int P_MAX, + bool *BSRsent); void clear_ul_config_request(NR_UE_MAC_INST_t *mac, int scs) { @@ -865,8 +875,8 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, if (pusch_config_pdu->scid == 0 && NR_DMRS_ulconfig && NR_DMRS_ulconfig->transformPrecodingDisabled && NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID0) pusch_config_pdu->ul_dmrs_scrambling_id = *NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID0; - if (pusch_config_pdu->scid == 1 && NR_DMRS_ulconfig && - NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID1) + if (pusch_config_pdu->scid == 1 && NR_DMRS_ulconfig && NR_DMRS_ulconfig->transformPrecodingDisabled + && NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID1) pusch_config_pdu->ul_dmrs_scrambling_id = *NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID1; } @@ -1386,20 +1396,28 @@ void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac) // TODO we don't have semi-persistent CSI reporting } -static void nr_update_sr(NR_UE_MAC_INST_t *mac) +static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent) { NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info; // if no pending data available for transmission // All pending SR(s) shall be cancelled and each respective sr-ProhibitTimer shall be stopped - bool data_avail = false; - for (int i = 0; i < NR_MAX_NUM_LCID; i++) { - if (sched_info->lc_sched_info[i].LCID_buffer_remain > 0) { - data_avail = true; - break; - } + // in TS 38.321: + // The SR configuration of the logical channel that triggered the BSR + // (subclause 5.4.5) (if such a configuration exists) is considered as corresponding SR configuration for the triggered SR + // in the hereafter code, we compute actual state at the time we compute the SR + // So, it might be more accurate than the logical channel that triggered the BSR some slots ago if new data came in the UE for + // ULSCH + + nr_lcordered_info_t *lc_info = NULL; + for (int idx = 0; idx < mac->lc_ordered_list.count && lc_info == NULL; idx++) { + nr_lcordered_info_t *lc_info_loop = mac->lc_ordered_list.array[idx]; + NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lc_info_loop->lcid); + if (lc_sched_info->LCID_buffer_remain) + lc_info = lc_info_loop; } - if (!data_avail) { + + if (lc_info == NULL) { // all queues are empty for (int i = 0; i < NR_MAX_SR_ID; i++) { nr_sr_info_t *sr = &sched_info->sr_info[i]; if (sr->active_SR_ID) { @@ -1409,39 +1427,38 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac) nr_timer_stop(&sr->prohibitTimer); } } + return; } // if a Regular BSR has been triggered and logicalChannelSR-DelayTimer is not running - if (((sched_info->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0) - || nr_timer_is_active(&sched_info->sr_DelayTimer)) + if (BSRsent || nr_timer_is_active(&sched_info->sr_DelayTimer)) return; - nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, sched_info->regularBSR_trigger_lcid); - AssertFatal(lc_info, "Couldn't find logical channel with LCID %ld\n", sched_info->regularBSR_trigger_lcid); - // if there is no UL-SCH resource available for a new transmission (ie we are at this point) - // if the MAC entity is configured with configured uplink grant(s) and the Regular BSR was triggered for a // logical channel for which logicalChannelSR-Mask is set to false or if (mac->current_UL_BWP->configuredGrantConfig && lc_info->lc_SRMask) return; + // if the UL-SCH resources available for a new transmission do not meet the LCP mapping restrictions // TODO not implemented + NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; + NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL; + if (!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList) + return; // cannot schedule SR if there is no schedulingRequestResource configured + if (lc_info->sr_id < 0 || lc_info->sr_id >= NR_MAX_SR_ID) LOG_E(NR_MAC, "No SR corresponding to this LCID\n"); // TODO not sure what to do here else { nr_sr_info_t *sr = &sched_info->sr_info[lc_info->sr_id]; if (!sr->pending) { - NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; - NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL; if (check_pucchres_for_pending_SR(pucch_Config, lc_info->sr_id)) { // trigger SR LOG_D(NR_MAC, "Triggering SR for ID %d\n", lc_info->sr_id); sr->pending = true; sr->counter = 0; - } - else { + } else { // initiate a Random Access procedure on the SpCell and cancel the pending SR // if the MAC entity has no valid PUCCH resource configured for the pending SR sr->pending = false; @@ -1453,68 +1470,66 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac) } } -static void nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index) +static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index) { - // Reset All BSR Infos - for (int id = 0; id < NR_MAX_NUM_LCID; id++) { - // Reset transmission status - mac->scheduling_info.lc_sched_info[id].LCID_buffer_with_data = false; - } + for (int i = 0; i < mac->lc_ordered_list.count; i++) { + nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; + int lcid = lc_info->lcid; + NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); + mac_rlc_status_resp_t rlc_status = + mac_rlc_status_ind(mac->ue_id, mac->ue_id, gNB_index, frameP, slotP, ENB_FLAG_NO, MBMS_FLAG_NO, lcid, 0, 0); - for (int lcgid = 0; lcgid < NR_MAX_NUM_LCGID; lcgid++) { - // Reset Buffer Info - mac->scheduling_info.lcg_sched_info[lcgid].BSR = 0; - mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes = 0; + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(NR_MAC, + "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", + mac->ue_id, + lcid, + rlc_status.bytes_in_buffer, + frameP, + slotP); + lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer; + } } +} +/*TS 38.321 +A BSR shall be triggered if any of the following events occur: +- UL data, for a logical channel which belongs to an LCG, becomes available to the MAC entity; and either + => here we don't implement exactly the same, there is no direct relation with new data came in the UE since last BSR + +- this UL data belongs to a logical channel with higher priority than the priority of any logical channel + containing available UL data which belong to any LCG; or + => same, we don't know the last BSR content + +- none of the logical channels which belong to an LCG contains any available UL data. + in which case the BSR is referred below to as 'Regular BSR'; + +- UL resources are allocated and number of padding bits is equal to or larger than the size of the Buffer Status +Report MAC CE plus its subheader, in which case the BSR is referred below to as 'Padding BSR'; + +- retxBSR-Timer expires, and at least one of the logical channels which belong to an LCG contains UL data, in +which case the BSR is referred below to as 'Regular BSR'; + +- periodicBSR-Timer expires, in which case the BSR is referred below to as 'Periodic BSR'. + +*/ + +static void nr_update_bsr(NR_UE_MAC_INST_t *mac, uint32_t *LCG_bytes) +{ bool bsr_regular_triggered = mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_REGULAR; for (int i = 0; i < mac->lc_ordered_list.count; i++) { nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; int lcid = lc_info->lcid; NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); int lcgid = lc_sched_info->LCGID; - // check if UL data for a logical channel which belongs to a LCG becomes available for transmission if (lcgid != NR_INVALID_LCGID) { - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mac->ue_id, - mac->ue_id, - gNB_index, - frameP, - slotP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - lcid, - 0, - 0); - - lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer; - - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(NR_MAC, - "[UE %d] LCID %d LCGID %d has %d bytes to transmit at frame %d slot %d\n", - mac->ue_id, - lcid, - lcgid, - rlc_status.bytes_in_buffer, - frameP, - slotP); - - lc_sched_info->LCID_buffer_with_data = true; - - //Update BSR_bytes - mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes += rlc_status.bytes_in_buffer; - - if (!bsr_regular_triggered) { - bsr_regular_triggered = true; - trigger_regular_bsr(mac, lcid, lc_info->sr_DelayTimerApplied); - LOG_D(NR_MAC, - "[UE %d] MAC BSR Triggered LCID %d LCGID %d data become available at %d.%d\n", - mac->ue_id, - lcid, - lcgid, - frameP, - slotP); - } + // Update waiting bytes for this LCG + LCG_bytes[lcgid] += lc_sched_info->LCID_buffer_remain; + if (!bsr_regular_triggered) { + bsr_regular_triggered = true; + trigger_regular_bsr(mac, lcid, lc_info->sr_DelayTimerApplied); + LOG_D(NR_MAC, "[UE %d] MAC BSR Triggered\n", mac->ue_id); } } } @@ -1533,14 +1548,11 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) nr_ue_prach_scheduler(mac, frame_tx, slot_tx); } - // Periodic SRS scheduling - if(mac->state == UE_CONNECTED) + bool BSRsent = false; + if (mac->state == UE_CONNECTED) { nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx); - - // Call BSR procedure as described in Section 5.4.5 in 38.321 - // Check whether BSR is triggered before scheduling ULSCH - if(mac->state == UE_CONNECTED) - nr_update_bsr(mac, frame_tx, slot_tx, gNB_index); + nr_update_rlc_buffers_status(mac, frame_tx, slot_tx, gNB_index); + } // Schedule ULSCH only if the current frame and slot match those in ul_config_req // AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus) @@ -1555,21 +1567,22 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) while (ulcfg_pdu->pdu_type != FAPI_NR_END) { uint8_t *ulsch_input_buffer = ulsch_input_buffer_array[number_of_pdus]; if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { - uint32_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size; + nfapi_nr_ue_pusch_pdu_t *pdu = &ulcfg_pdu->pusch_config_pdu; + uint32_t TBS_bytes = pdu->pusch_data.tb_size; LOG_D(NR_MAC, "harq_id %d, new_data_indicator %d, TBS_bytes %d (ra_state %d)\n", - ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id, - ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator, + pdu->pusch_data.harq_process_id, + pdu->pusch_data.new_data_indicator, TBS_bytes, ra->ra_state); - ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = NULL; + pdu->tx_request_body.fapiTxPdu = NULL; if ((ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_MSGB) && !ra->cfra) { nr_get_Msg3_MsgA_PUSCH_payload(mac, ulsch_input_buffer, TBS_bytes); for (int k = 0; k < TBS_bytes; k++) { LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]); } - ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = ulsch_input_buffer; - ulcfg_pdu->pusch_config_pdu.tx_request_body.pdu_length = TBS_bytes; + pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer; + pdu->tx_request_body.pdu_length = TBS_bytes; number_of_pdus++; } else { if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator @@ -1580,23 +1593,23 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) return; } // Getting IP traffic to be transmitted - int tx_power = ulcfg_pdu->pusch_config_pdu.tx_power; + int tx_power = pdu->tx_power; int P_CMAX = nr_get_Pcmax(mac->p_Max, mac->nr_band, mac->frame_type, mac->frequency_range, mac->current_UL_BWP->channel_bandwidth, - ulcfg_pdu->pusch_config_pdu.qam_mod_order, + pdu->qam_mod_order, false, mac->current_UL_BWP->scs, mac->current_UL_BWP->BWPSize, - ulcfg_pdu->pusch_config_pdu.transform_precoding, - ulcfg_pdu->pusch_config_pdu.rb_size, - ulcfg_pdu->pusch_config_pdu.rb_start); + pdu->transform_precoding, + pdu->rb_size, + pdu->rb_start); - nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes, tx_power, P_CMAX); - ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = ulsch_input_buffer; - ulcfg_pdu->pusch_config_pdu.tx_request_body.pdu_length = TBS_bytes; + nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes, tx_power, P_CMAX, &BSRsent); + pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer; + pdu->tx_request_body.pdu_length = TBS_bytes; number_of_pdus++; // start or restart dataInactivityTimer if any MAC entity transmits a MAC SDU for DTCH logical channel, // or DCCH logical channel @@ -1637,7 +1650,10 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) } if(mac->state == UE_CONNECTED) - nr_update_sr(mac); + nr_update_sr(mac, BSRsent); + // Global variables implicit logic + // far away, BSR_reporting_active is set + mac->scheduling_info.BSR_reporting_active = NR_BSR_TRIGGER_NONE; // update Bj for all active lcids before LCP procedure if (mac->current_UL_BWP) { @@ -1668,22 +1684,15 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) static uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value) { - uint8_t ju, jm, jl; - int ascend; - //DevAssert(size > 0); - //DevAssert(size <= 256); - if (value == 0) { return 0; //elseif (value > 150000) return 63; } - jl = 0; // lower bound - ju = size - 1; // upper bound - ascend = (table[ju] >= table[jl]) ? 1 : 0; // determine the order of the the table: 1 if ascending order of table, 0 otherwise - + int jl = 0; // lower bound + int ju = size - 1; // upper bound + bool ascend = table[ju] >= table[jl] ? 1 : 0; // determine the order of the the table: 1 if ascending order of table, 0 otherwise while (ju - jl > 1) { //If we are not yet done, - jm = (ju + jl) >> 1; //compute a midpoint, - + int jm = (ju + jl) / 2; // compute a midpoint, if ((value >= table[jm]) == ascend) { jl = jm; // replace the lower limit } else { @@ -2319,7 +2328,11 @@ void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) LOG_D(NR_MAC,"Map SSB to RO done\n"); } -static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int slot_tx, const PUCCH_sched_t *pucch) +static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, + frame_t frame_tx, + int slot_tx, + const PUCCH_sched_t *pucch, + NR_UE_UL_BWP_t *current_UL_BWP) { fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = lockGet_ul_iterator(mac, frame_tx, slot_tx); if (!ulcfg_pdu) @@ -2334,29 +2347,37 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int s NR_PUCCH_Resource_t *pucchres = pucch->pucch_resource; int nr_of_symbols = 0; int start_symbol_index = 0; - switch(pucchres->format.present) { - case NR_PUCCH_Resource__format_PR_format0 : - nr_of_symbols = pucchres->format.choice.format0->nrofSymbols; - start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format1 : - nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; - start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format2 : - nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; - start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format3 : - nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; - start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; - break; - case NR_PUCCH_Resource__format_PR_format4 : - nr_of_symbols = pucchres->format.choice.format4->nrofSymbols; - start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex; - break; - default : - AssertFatal(false, "Undefined PUCCH format \n"); + if (pucch->initial_pucch_id > -1 && pucch->pucch_resource == NULL) { + const int idx = *current_UL_BWP->pucch_ConfigCommon->pucch_ResourceCommon; + const initial_pucch_resource_t pucch_resourcecommon = get_initial_pucch_resource(idx); + start_symbol_index = pucch_resourcecommon.startingSymbolIndex; + nr_of_symbols = pucch_resourcecommon.nrofSymbols; + } + else { + switch(pucchres->format.present) { + case NR_PUCCH_Resource__format_PR_format0 : + nr_of_symbols = pucchres->format.choice.format0->nrofSymbols; + start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format1 : + nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; + start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format2 : + nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; + start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format3 : + nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; + start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format4 : + nr_of_symbols = pucchres->format.choice.format4->nrofSymbols; + start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex; + break; + default : + AssertFatal(false, "Undefined PUCCH format \n"); + } } int final_symbol = nr_of_symbols + start_symbol_index; // PUCCH overlapping in time with PUSCH @@ -2387,22 +2408,25 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int s // and does not transmit the PUCCH if the UE does not multiplex aperiodic or semi-persistent CSI reports in the PUSCH bool mux_done = false; if (pucch->n_harq > 0) { - pusch_pdu->pusch_uci.harq_ack_bit_length = pucch->n_harq; - pusch_pdu->pusch_uci.harq_payload = pucch->ack_payload; NR_PUSCH_Config_t *pusch_Config = mac->current_UL_BWP->pusch_Config; - AssertFatal(pusch_Config && pusch_Config->uci_OnPUSCH, "UCI on PUSCH need to be configured\n"); - NR_UCI_OnPUSCH_t *onPusch = pusch_Config->uci_OnPUSCH->choice.setup; - AssertFatal(onPusch && - onPusch->betaOffsets && - onPusch->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_semiStatic, - "Only semistatic beta offset is supported\n"); - NR_BetaOffsets_t *beta_offsets = onPusch->betaOffsets->choice.semiStatic; - pusch_pdu->pusch_uci.beta_offset_harq_ack = pucch->n_harq > 2 ? - (pucch->n_harq < 12 ? *beta_offsets->betaOffsetACK_Index2 : - *beta_offsets->betaOffsetACK_Index3) : - *beta_offsets->betaOffsetACK_Index1; - pusch_pdu->pusch_uci.alpha_scaling = onPusch->scaling; - mux_done = true; + if (pusch_Config && pusch_Config->uci_OnPUSCH) { + NR_UCI_OnPUSCH_t *onPusch = pusch_Config->uci_OnPUSCH->choice.setup; + AssertFatal(onPusch && + onPusch->betaOffsets && + onPusch->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_semiStatic, + "Only semistatic beta offset is supported\n"); + NR_BetaOffsets_t *beta_offsets = onPusch->betaOffsets->choice.semiStatic; + pusch_pdu->pusch_uci.harq_ack_bit_length = pucch->n_harq; + pusch_pdu->pusch_uci.harq_payload = pucch->ack_payload; + pusch_pdu->pusch_uci.beta_offset_harq_ack = pucch->n_harq > 2 ? + (pucch->n_harq < 12 ? *beta_offsets->betaOffsetACK_Index2 : + *beta_offsets->betaOffsetACK_Index3) : + *beta_offsets->betaOffsetACK_Index1; + pusch_pdu->pusch_uci.alpha_scaling = onPusch->scaling; + mux_done = true; + } else { + LOG_E(NR_MAC, "UCI on PUSCH need to be configured to schedule UCI on PUSCH\n"); + } } if (pusch_pdu->pusch_uci.csi_part1_bit_length == 0 && pusch_pdu->pusch_uci.csi_part2_bit_length == 0) { // To support this we would need to shift some bits into CSI part2 -> need to change the logic @@ -2465,7 +2489,7 @@ void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) mac->nr_ue_emul_l1.num_csi_reports = pucch[j].n_csi; // checking if we need to schedule pucch[j] on PUSCH - if (schedule_uci_on_pusch(mac, frameP, slotP, &pucch[j])) + if (schedule_uci_on_pusch(mac, frameP, slotP, &pucch[j], mac->current_UL_BWP)) continue; fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PUCCH); @@ -2979,95 +3003,68 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_fra } typedef struct { - uint8_t bsr_len; - uint8_t bsr_ce_len; - uint8_t bsr_header_len; uint8_t phr_len; - uint8_t phr_ce_len; - uint8_t phr_header_len; - uint16_t sdu_length_total; - NR_BSR_SHORT *bsr_s; - NR_BSR_LONG *bsr_l; - NR_BSR_SHORT *bsr_t; - NR_SINGLE_ENTRY_PHR_MAC_CE* phr; - //NR_POWER_HEADROOM_CMD *phr_pr; - int tot_mac_ce_len; - uint8_t total_mac_pdu_header_len; + uint sdu_length_total; + NR_SINGLE_ENTRY_PHR_MAC_CE phr; + type_bsr_t bsr; + uint8_t *pdu_end; + uint8_t *end_for_tailer; + uint8_t *cur_ptr; + uint num_sdus; + // int highest_priority = 16; + // variable used to store the lcid data status during lcp + bool lcids_data_status[NR_MAX_NUM_LCID]; + uint32_t lcp_allocation_counter; } NR_UE_MAC_CE_INFO; -/* - nr_ue_get_sdu_mac_ce_pre finds length in various mac_ce field - Need nothing from mac_ce_p: - Update the following in mac_ce_p: - bsr_len; - bsr_ce_len; - bsr_header_len; - phr_len; TBD - phr_ce_len; TBD - phr_header_len; TBD -*/ -static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac, - int CC_id, - frame_t frameP, - sub_frame_t subframe, - uint8_t gNB_index, - uint8_t *ulsch_buffer, - uint32_t buflen, - int16_t tx_power, - int16_t P_CMAX, - NR_UE_MAC_CE_INFO *mac_ce_p) +static void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac, + int CC_id, + frame_t frameP, + sub_frame_t subframe, + uint8_t gNB_index, + uint8_t *ulsch_buffer, + uint32_t buflen, + uint32_t *LCG_bytes, + NR_UE_MAC_CE_INFO *mac_ce_p, + int tx_power, + int P_CMAX) { - int num_lcg_id_with_data = 0; // Preparing the MAC CEs sub-PDUs and get the total size - mac_ce_p->bsr_header_len = 0; - int lcg_id = 0; - while (lcg_id != NR_INVALID_LCGID) { - if (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes) { - num_lcg_id_with_data++; - } - lcg_id++; - } + *mac_ce_p = (NR_UE_MAC_CE_INFO){.pdu_end = ulsch_buffer + buflen, .cur_ptr = ulsch_buffer}; + memset(mac_ce_p->lcids_data_status, 1, NR_MAX_NUM_LCID); // Compute BSR Length if Regular or Periodic BSR is triggered - // WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing + // If we decide here to send BSR long, we may decide later to use BSR short // if there remains less than 1 LCGROUP with data after Tx + int bsr_len = 0; if (mac->scheduling_info.BSR_reporting_active) { - AssertFatal((mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_PADDING) == 0, - "Inconsistent BSR Trigger=%d !\n", - mac->scheduling_info.BSR_reporting_active); - + // count the active channels + int num_lcg_id_with_data = 0; + for (int i = 0; i < NR_MAX_NUM_LCGID; i++) { + if (LCG_bytes[i]) + num_lcg_id_with_data++; + } // A Regular or Periodic BSR can only be sent if TBS is sufficient // as transmitting only a BSR is not allowed if UE has data to transmit - if (num_lcg_id_with_data <= 1) { - if (buflen >= (sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED) + 1)) { - mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); // 1 byte - mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); // 1 byte - } - } else { - if (buflen >= (num_lcg_id_with_data + 1 + sizeof(NR_MAC_SUBHEADER_SHORT) + 1)) { - mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; // variable size - mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); // 2 bytes - } - } + int size_for_long = num_lcg_id_with_data + sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT); + int size_for_short = sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED); + if (num_lcg_id_with_data > 1 && buflen >= size_for_long) + bsr_len = size_for_long; + else if ((num_lcg_id_with_data > 0 && buflen >= size_for_short) + || mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_PERIODIC) + bsr_len = size_for_short; } - mac_ce_p->bsr_len = mac_ce_p->bsr_ce_len + mac_ce_p->bsr_header_len; - - nr_phr_info_t *phr_info = &mac->scheduling_info.phr_info; - mac_ce_p->phr_header_len = 0; - mac_ce_p->phr_ce_len = 0; if (phr_info->is_configured && phr_info->phr_reporting > 0) { - if (buflen >= (mac_ce_p->bsr_len + sizeof(NR_MAC_SUBHEADER_FIXED) + sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE))) { + int needed = sizeof(NR_MAC_SUBHEADER_FIXED) + sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE); + if (buflen >= bsr_len + needed) { if (mac->scheduling_info.phr_info.phr_reporting) { - mac_ce_p->phr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); - mac_ce_p->phr_ce_len = sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE); - nr_ue_fill_phr(mac, mac_ce_p->phr, P_CMAX, tx_power, frameP, subframe); + mac_ce_p->phr_len = needed; + nr_ue_fill_phr(mac, &mac_ce_p->phr, P_CMAX, tx_power, frameP, subframe); } } } - mac_ce_p->phr_len = mac_ce_p->phr_header_len + mac_ce_p->phr_ce_len; - - return (mac_ce_p->bsr_len + mac_ce_p->phr_len); + mac_ce_p->end_for_tailer = mac_ce_p->pdu_end - bsr_len - mac_ce_p->phr_len; } /* @@ -3075,14 +3072,11 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac, Need the following from mac_ce_p: bsr_ce_len bsr_len - sdu_length_total - total_mac_pdu_header_len Update the following in mac_ce_p: bsr_ce_len bsr_header_len bsr_len tot_mac_ce_len - total_mac_pdu_header_len bsr_s bsr_l bsr_t @@ -3090,30 +3084,21 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac, static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, - uint8_t *ulsch_buffer, - uint32_t buflen, - NR_UE_MAC_CE_INFO *mac_ce_p) + NR_UE_MAC_CE_INFO *mac_ce_p, + uint32_t *LCG_bytes, + bool *BSRsent) { // Compute BSR Values and update Nb LCGID with data after multiplexing - uint32_t padding_len = 0; - int num_lcg_id_with_data = 0; - int lcg_id_bsr_trunc = 0; + int lcg_id_bsr_max = 0; NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info; - for (int lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) { - if (mac_ce_p->bsr_ce_len == sizeof(NR_BSR_SHORT)) { - sched_info->lcg_sched_info[lcg_id].BSR = - nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, - NR_SHORT_BSR_TABLE_SIZE, - sched_info->lcg_sched_info[lcg_id].BSR_bytes); - } else { - sched_info->lcg_sched_info[lcg_id].BSR = - nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, - NR_LONG_BSR_TABLE_SIZE, - sched_info->lcg_sched_info[lcg_id].BSR_bytes); - } - if (sched_info->lcg_sched_info[lcg_id].BSR_bytes) { - num_lcg_id_with_data++; - lcg_id_bsr_trunc = lcg_id; + // Search the LCGID within waiting data for the highest priority LC + for (int i = 0; i < mac->lc_ordered_list.count; i++) { + int lcid = mac->lc_ordered_list.array[i]->lcid; + NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid); + if (sched_info->LCID_buffer_remain) { + // this is the highest priority LC with data to transmit + lcg_id_bsr_max = sched_info->LCGID; + break; } } @@ -3128,119 +3113,79 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, - else report Short BSR. - else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR. */ - if (mac_ce_p->sdu_length_total) { - padding_len = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total); - } - - if ((padding_len) && (mac_ce_p->bsr_len == 0)) { - /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR */ - if (padding_len >= (num_lcg_id_with_data + 1 + sizeof(NR_MAC_SUBHEADER_SHORT))) { - mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; //variable size - mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); //2 bytes - // Trigger BSR Padding - sched_info->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING; - } else if (padding_len >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED))) { - mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); //1 byte - mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); //1 byte - - if (num_lcg_id_with_data > 1) { - // REPORT SHORT TRUNCATED BSR - // Get LCGID of highest priority LCID with data (todo) - for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) { - NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid); - if ((sched_info->LCGID != NR_INVALID_LCGID) && (mac->scheduling_info.lcg_sched_info[sched_info->LCGID].BSR_bytes)) { - lcg_id_bsr_trunc = sched_info->LCGID; - } - } - } else { - // Report SHORT BSR, clear bsr_t - mac_ce_p->bsr_t = NULL; - } - - // Trigger BSR Padding - sched_info->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING; - } - - mac_ce_p->bsr_len = mac_ce_p->bsr_header_len + mac_ce_p->bsr_ce_len; - mac_ce_p->tot_mac_ce_len += mac_ce_p->bsr_len; - mac_ce_p->total_mac_pdu_header_len += mac_ce_p->bsr_len; - } - - //Fill BSR Infos - if (mac_ce_p->bsr_ce_len == 0) { - mac_ce_p->bsr_s = NULL; - mac_ce_p->bsr_l = NULL; - mac_ce_p->bsr_t = NULL; - } else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_SHORT)) { - mac_ce_p->bsr_s = NULL; - mac_ce_p->bsr_t = NULL; - mac_ce_p->bsr_l->Buffer_size0 = sched_info->lcg_sched_info[0].BSR; - mac_ce_p->bsr_l->Buffer_size1 = sched_info->lcg_sched_info[1].BSR; - mac_ce_p->bsr_l->Buffer_size2 = sched_info->lcg_sched_info[2].BSR; - mac_ce_p->bsr_l->Buffer_size3 = sched_info->lcg_sched_info[3].BSR; - mac_ce_p->bsr_l->Buffer_size4 = sched_info->lcg_sched_info[4].BSR; - mac_ce_p->bsr_l->Buffer_size5 = sched_info->lcg_sched_info[5].BSR; - mac_ce_p->bsr_l->Buffer_size6 = sched_info->lcg_sched_info[6].BSR; - mac_ce_p->bsr_l->Buffer_size7 = sched_info->lcg_sched_info[7].BSR; + uint32_t padding_len = mac_ce_p->pdu_end - mac_ce_p->cur_ptr - mac_ce_p->phr_len; + AssertFatal(padding_len >= 0, "Error in buffer size compute"); + mac_ce_p->bsr.type_bsr = b_none; + int short_bsr_sz = sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED); + int num_lcg_id_with_data = 0; + for (int lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) + num_lcg_id_with_data += LCG_bytes > 0; + int long_bsr_sz = num_lcg_id_with_data + sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT); + if (num_lcg_id_with_data < 2 && padding_len >= short_bsr_sz) { + mac_ce_p->bsr.type_bsr = b_short; + mac_ce_p->bsr.bsr.s.LcgID = lcg_id_bsr_max; + mac_ce_p->bsr.bsr.s.Buffer_size = + nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, NR_SHORT_BSR_TABLE_SIZE, LCG_bytes[lcg_id_bsr_max]); LOG_D(NR_MAC, - "[UE %d] Frame %d subframe %d BSR Trig=%d report LONG BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 " - "%d level LCGID4 %d,level LCGID5 %d,level LCGID6 %d,level LCGID7 %d)\n", + "[UE %d] sfn %d.%d BSR Trigger=0x%x report SHORT BSR with level %d for LCGID %d\n", mac->ue_id, frame, slot, sched_info->BSR_reporting_active, - sched_info->lcg_sched_info[0].BSR, - sched_info->lcg_sched_info[1].BSR, - sched_info->lcg_sched_info[2].BSR, - sched_info->lcg_sched_info[3].BSR, - sched_info->lcg_sched_info[4].BSR, - sched_info->lcg_sched_info[5].BSR, - sched_info->lcg_sched_info[6].BSR, - sched_info->lcg_sched_info[7].BSR); - } else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_FIXED)) { - mac_ce_p->bsr_l = NULL; - - if ((mac_ce_p->bsr_t != NULL) && (sched_info->BSR_reporting_active & NR_BSR_TRIGGER_PADDING)) { - //Truncated BSR - mac_ce_p->bsr_s = NULL; - mac_ce_p->bsr_t->LcgID = lcg_id_bsr_trunc; - mac_ce_p->bsr_t->Buffer_size = sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR; - LOG_D(NR_MAC, - "[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n", - mac->ue_id, - frame, - slot, - sched_info->BSR_reporting_active, - sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR, - lcg_id_bsr_trunc); - } else { - mac_ce_p->bsr_t = NULL; - mac_ce_p->bsr_s->LcgID = lcg_id_bsr_trunc; - mac_ce_p->bsr_s->Buffer_size = sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR; - LOG_D(NR_MAC, - "[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n", - mac->ue_id, - frame, - slot, - sched_info->BSR_reporting_active, - sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR, - lcg_id_bsr_trunc); + mac_ce_p->bsr.bsr.s.Buffer_size, + lcg_id_bsr_max); + } else if (padding_len >= long_bsr_sz) { + /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, + report Long BSR whatever periodic or regular BSR*/ + mac_ce_p->bsr.type_bsr = b_long; + uint8_t *tmp = mac_ce_p->bsr.bsr.lcg_bsr; + for (int lcg_id = 0; lcg_id < 8; lcg_id++) { + tmp[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, NR_LONG_BSR_TABLE_SIZE, LCG_bytes[lcg_id]); } - } + LOG_D(NR_MAC, + "[UE %d] sfn %d.%d BSR Trig=0x%x report LONG BSR (level LCGID %d %d %d %d %d %d %d %d)\n", + mac->ue_id, + frame, + slot, + sched_info->BSR_reporting_active, + tmp[0], + tmp[1], + tmp[2], + tmp[3], + tmp[4], + tmp[5], + tmp[6], + tmp[7]); + } else if (padding_len == short_bsr_sz) { + mac_ce_p->bsr.type_bsr = b_short_trunc; + mac_ce_p->bsr.bsr.s.LcgID = lcg_id_bsr_max; + mac_ce_p->bsr.bsr.s.Buffer_size = + nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, NR_SHORT_BSR_TABLE_SIZE, LCG_bytes[lcg_id_bsr_max]); + } else if (padding_len >= sizeof(NR_BSR_LONG) + sizeof(NR_MAC_SUBHEADER_SHORT)) { + mac_ce_p->bsr.type_bsr = b_long_trunc; + // Fixme: this should be sorted by (TS 38.321, 5.4.5) + // the logical channels having data available for + // transmission following a decreasing order of the highest priority logical channel (with or without data + // available for transmission) in each of these LCG(s), and in case of equal priority, in increasing order of LCGID + uint8_t *tmp = mac_ce_p->bsr.bsr.lcg_bsr; + for (int lcg_id = 0; lcg_id < 8; lcg_id++) { + tmp[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, NR_LONG_BSR_TABLE_SIZE, LCG_bytes[lcg_id]); + } + } else + LOG_D(NR_MAC, "Can't add any BSR, not enough padding\n"); /* Actions when a BSR is sent */ - if (mac_ce_p->bsr_ce_len) { + if (mac_ce_p->bsr.type_bsr != b_none) { LOG_D(NR_MAC, - "[UE %d] MAC BSR Sent! ce %d, hdr %d buff_len %d triggering LCID %ld\n", + "[UE %d] MAC BSR Sent! buff_len %ld triggering LCID %ld\n", mac->ue_id, - mac_ce_p->bsr_ce_len, - mac_ce_p->bsr_header_len, - buflen, + mac_ce_p->pdu_end - mac_ce_p->cur_ptr, sched_info->regularBSR_trigger_lcid); + *BSRsent = true; // Reset ReTx BSR Timer nr_timer_start(&sched_info->retxBSR_Timer); // Reset Periodic Timer except when BSR is truncated - if (mac_ce_p->bsr_t == NULL) { + if (mac_ce_p->bsr.type_bsr != b_long_trunc && mac_ce_p->bsr.type_bsr != b_short_trunc) { nr_timer_start(&sched_info->periodicBSR_Timer); LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset\n", mac->ue_id); } @@ -3256,10 +3201,12 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, nr_timer_stop(&sr->prohibitTimer); } } - // Reset BSR Trigger flags - sched_info->BSR_reporting_active = NR_BSR_TRIGGER_NONE; - sched_info->regularBSR_trigger_lcid = 0; } + + int size = + nr_write_ce_ulsch_pdu(mac_ce_p->cur_ptr, mac, mac_ce_p->phr_len ? &mac_ce_p->phr : NULL, &mac_ce_p->bsr, mac_ce_p->pdu_end); + LOG_D(NR_MAC, "Added %d bytes of BSR\n", size); + mac_ce_p->cur_ptr += size; } uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array) @@ -3276,19 +3223,19 @@ uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids return same_priority_count; } -long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac, - uint8_t same_priority_count, - uint8_t lc_num, - uint32_t buflen_remain_ep, - int32_t buflen_remain, - uint8_t round_id, - uint32_t *bytes_read_fromlc, - long *target) +static long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac, + uint8_t same_priority_count, + uint8_t lc_num, + uint32_t buflen_remain_ep, + int32_t buflen_remain, + uint8_t round_id, + uint32_t *bytes_read_fromlc, + long *target) { /* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/ nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, lc_num); AssertFatal(lc_info, "Couldn't find logical channel with LCID %d\n", lc_num); - uint32_t pbr = lc_info->pbr; + const uint32_t pbr = lc_info->pbr; NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lc_num); int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain; *target = (same_priority_count > 1) ? min(buflen_remain_ep, pbr) : pbr; @@ -3309,7 +3256,8 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac, num_bytes_requested = min(buflen_remain, lcid_remain_buffer); } } - AssertFatal(num_remaining_bytes >= 0, "the total number of bytes allocated until target length is greater than expected\n"); + AssertFatal(num_remaining_bytes >= 0 && num_bytes_requested <= buflen_remain, + "the total number of bytes allocated until target length is greater than expected\n"); LOG_D(NR_MAC, "number of bytes requested for lcid %d is %li\n", lc_num, num_bytes_requested); return num_bytes_requested; @@ -3327,64 +3275,69 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_ return false; } -static void select_logical_channels(NR_UE_MAC_INST_t *mac, int *num_active_lcids, nr_lcordered_info_t *active_lcids) +static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *active_lcids) { // (TODO: selection of logical channels for logical channel prioritization procedure as per 5.4.3.1.2 Selection of logical // channels, TS38.321) - + int nb = 0; // selection of logical channels with Bj > 0 for (int i = 0; i < mac->lc_ordered_list.count; i++) { int lcid = mac->lc_ordered_list.array[i]->lcid; NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid); if (sched_info->Bj > 0) { - active_lcids[*num_active_lcids] = *mac->lc_ordered_list.array[i]; - (*num_active_lcids)++; - LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, *num_active_lcids); + active_lcids[nb++] = *mac->lc_ordered_list.array[i]; + LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, nb); } } + return nb; } static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, uint8_t gNB_index, - uint32_t buflen, - int32_t *buflen_remain, int lcid, - uint8_t **pdu, - uint32_t *counter, - uint8_t count_same_priority_lcids, + uint count_same_priority_lcids, uint32_t buflen_ep, uint32_t *lcids_bytes_tot, - uint16_t *num_sdus, NR_UE_MAC_CE_INFO *mac_ce_p, - bool *lcids_data_status, - uint8_t *num_lcids_same_priority) + uint *num_lcids_same_priority, + uint32_t *LCG_bytes) { - const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG); - /* prepare the MAC sdu */ NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid); int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain; + uint usable = mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr; LOG_D(NR_MAC, - "[UE %d] [%d.%d] lcp round = %d, remaining mac pdu length = %d, lcid buffer remaining = %d, lcid = %d \n", + "[UE %d] [%d.%d] lcp round = %d, remaining mac pdu length before BSR = %d, lcid buffer remaining = %d, lcid = %d \n", mac->ue_id, frame, slot, - *counter, - *buflen_remain, + mac_ce_p->lcp_allocation_counter, + usable, lcid_remain_buffer, lcid); - // Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU - NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *)(*pdu); + if (mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr < sizeof(NR_MAC_SUBHEADER_LONG)) + // We can't add one byte after the header + return false; - *pdu += sh_size; + // Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *)mac_ce_p->cur_ptr; // number of bytes requested from RLC for each LCID long target = 0; - long bytes_requested = - get_num_bytes_to_reqlc(mac, count_same_priority_lcids, lcid, buflen_ep, *buflen_remain, *counter, lcids_bytes_tot, &target); + // NR_MAC_SUBHEADER_SHORT can handle up to 256 bytes message + int header_sz = usable < 256 ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG); + long bytes_requested = get_num_bytes_to_reqlc(mac, + count_same_priority_lcids, + lcid, + buflen_ep, + usable - header_sz, + mac_ce_p->lcp_allocation_counter, + lcids_bytes_tot, + &target); + header_sz = bytes_requested < 256 ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG); uint16_t sdu_length = mac_rlc_data_req(mac->ue_id, mac->ue_id, @@ -3394,7 +3347,7 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, MBMS_FLAG_NO, lcid, bytes_requested, - (char *)(*pdu), + (char *)mac_ce_p->cur_ptr + header_sz, 0, 0); @@ -3418,62 +3371,49 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, int lc_idx = lcid_buffer_index(lcid); if (sdu_length > 0) { + mac_ce_p->num_sdus++; LOG_D(NR_MAC, "[UE %d] [%d.%d] UL-DXCH -> ULSCH, Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID " - "0x%02x (buflen (TBS) %d bytes)\n", + "0x%02x (buflen (TBS) %ld bytes)\n", mac->ue_id, frame, slot, - (*num_sdus) + 1, + mac_ce_p->num_sdus, sdu_length, lcid, - buflen); - - header->R = 0; - header->F = 1; - header->LCID = lcid; - header->L = htons(sdu_length); - + mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr); + if (header_sz == sizeof(NR_MAC_SUBHEADER_SHORT)) { + *(NR_MAC_SUBHEADER_SHORT *)header = (NR_MAC_SUBHEADER_SHORT){.R = 0, .F = 0, .LCID = lcid, .L = sdu_length}; + } else { + *header = (NR_MAC_SUBHEADER_LONG){.R = 0, .F = 1, .LCID = lcid, .L = htons(sdu_length)}; #ifdef ENABLE_MAC_PAYLOAD_DEBUG - LOG_I(NR_MAC, "dumping MAC sub-header with length %d: \n", sh_size); - log_dump(NR_MAC, header, sh_size, LOG_DUMP_CHAR, "\n"); - LOG_I(NR_MAC, "dumping MAC SDU with length %d \n", sdu_length); - log_dump(NR_MAC, *pdu, sdu_length, LOG_DUMP_CHAR, "\n"); + LOG_I(NR_MAC, "dumping MAC SDU with length %d: \n", sduL); + log_dump(NR_MAC, header, sduL, LOG_DUMP_CHAR, "\n"); #endif - - *pdu += sdu_length; - mac_ce_p->sdu_length_total += sdu_length; - mac_ce_p->total_mac_pdu_header_len += sh_size; - - (*num_sdus)++; + } + mac_ce_p->cur_ptr += header_sz + sdu_length; } else { - *pdu -= sh_size; - lcids_data_status[lc_idx] = false; + mac_ce_p->lcids_data_status[lc_idx] = false; (*num_lcids_same_priority)--; - LOG_D(NR_MAC, "No data to transmit for RB with LCID 0x%02x and hence set to false\n", lcid); - return 0; + LOG_D(NR_MAC, "No data to transmit for RB with LCID 0x%02x\n and hence set to false", lcid); + return false; } - *buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size); - // Update Buffer remain and BSR bytes after transmission - NR_LCG_SCHEDULING_INFO *lcg_info = &mac->scheduling_info.lcg_sched_info[0]; sched_info->LCID_buffer_remain -= sdu_length; - (lcg_info + sched_info->LCGID)->BSR_bytes -= sdu_length; + LCG_bytes[sched_info->LCGID] -= sdu_length; LOG_D(NR_MAC, - "[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%ld = %d\n", + "[UE %d] Update BSR [%d.%d] LCG_bytes for LCG%ld = %d\n", mac->ue_id, frame, slot, sched_info->LCGID, - (lcg_info + sched_info->LCGID)->BSR_bytes); - if ((lcg_info + sched_info->LCGID)->BSR_bytes < 0) - (lcg_info + sched_info->LCGID)->BSR_bytes = 0; + LCG_bytes[sched_info->LCGID]); // update number of bytes served from the current lcid - lcids_bytes_tot[lc_idx] += (sdu_length + (count_same_priority_lcids > 1 ? 1 : 0) * sh_size); + lcids_bytes_tot[lc_idx] += (sdu_length + (count_same_priority_lcids > 1 ? 1 : 0) * sizeof(NR_MAC_SUBHEADER_LONG)); - if ((*counter == 0 && lcids_bytes_tot[lc_idx] >= target) + if ((mac_ce_p->lcp_allocation_counter == 0 && lcids_bytes_tot[lc_idx] >= target) || (count_same_priority_lcids > 1 && lcids_bytes_tot[lc_idx] >= buflen_ep)) { // only prioritized bit rate should be taken from logical channel in // the first lcp run except when infinity @@ -3482,9 +3422,9 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, lcid, lcids_bytes_tot[lc_idx]); (*num_lcids_same_priority)--; - return 0; + return false; } - return 1; + return true; } /** @@ -3499,77 +3439,55 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, * @ulsch_buffer Pointer to ULSCH PDU * @buflen TBS */ -uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, - int CC_id, - frame_t frame, - slot_t slot, - uint8_t gNB_index, - uint8_t *ulsch_buffer, - uint32_t buflen, - int16_t tx_power, - int16_t P_CMAX) +static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, + int CC_id, + frame_t frame, + slot_t slot, + uint8_t gNB_index, + uint8_t *ulsch_buffer, + const uint32_t buflen, + int tx_power, + int P_CMAX, + bool *BSRsent) { NR_UE_MAC_CE_INFO mac_ce_info; - NR_UE_MAC_CE_INFO *mac_ce_p=&mac_ce_info; - int32_t buflen_remain = 0; - mac_ce_p->bsr_len = 0; - mac_ce_p->bsr_ce_len = 0; - mac_ce_p->bsr_header_len = 0; - mac_ce_p->phr_len = 0; - //mac_ce_p->phr_ce_len = 0; - //mac_ce_p->phr_header_len = 0; - - uint16_t num_sdus = 0; - mac_ce_p->sdu_length_total = 0; - NR_BSR_SHORT bsr_short, bsr_truncated; - NR_BSR_LONG bsr_long; - mac_ce_p->bsr_s = &bsr_short; - mac_ce_p->bsr_l = &bsr_long; - mac_ce_p->bsr_t = &bsr_truncated; - - NR_SINGLE_ENTRY_PHR_MAC_CE phr; - mac_ce_p->phr = &phr; - - //int highest_priority = 16; - const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG); - - // Pointer used to build the MAC PDU by placing the RLC SDUs in the ULSCH buffer - uint8_t *pdu = ulsch_buffer; - - // variable used to store the lcid data status during lcp - bool lcids_data_status[NR_MAX_NUM_LCID] = {0}; - memset(lcids_data_status, 1, NR_MAX_NUM_LCID); // in the first run all the lc are allocated as per bj and prioritized bit rate but in subsequent runs, no need to consider - uint32_t lcp_allocation_counter = 0; // bj and prioritized bit rate but just consider priority uint32_t buflen_ep = 0; // this variable holds the length in bytes in mac pdu when multiple equal priority channels are present // because as per standard(TS38.321), all equal priority channels should be served equally - // nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length - mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(mac, CC_id, frame, slot, gNB_index, ulsch_buffer, buflen, tx_power, P_CMAX, mac_ce_p); - mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len; + // Call BSR procedure as described in Section 5.4.5 in 38.321 + // Check whether BSR is triggered before scheduling ULSCH + uint32_t LCG_bytes[NR_MAX_NUM_LCGID] = {0}; + nr_update_bsr(mac, LCG_bytes); - LOG_D(NR_MAC, "[UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", mac->ue_id, frame, slot, buflen); + nr_ue_get_sdu_mac_ce_pre(mac, CC_id, frame, slot, gNB_index, ulsch_buffer, buflen, LCG_bytes, &mac_ce_info, tx_power, P_CMAX); + + LOG_D(NR_MAC, + "[UE %d] [%d.%d] process UL transport block with size TBS = %d bytes, number of existing LCids %d \n", + mac->ue_id, + frame, + slot, + buflen, + mac->lc_ordered_list.count); - // selection of logical channels - int avail_lcids_count = 0; // variable used to build the lcids with positive Bj nr_lcordered_info_t lcids_bj_pos[mac->lc_ordered_list.count]; - select_logical_channels(mac, &avail_lcids_count, lcids_bj_pos); + int avail_lcids_count = select_logical_channels(mac, lcids_bj_pos); // multiplex in the order of highest priority do { /* go until there is space availabile in the MAC PDU and there is data available in RLC buffers of active logical channels */ - uint8_t num_lcids_same_priority = 0; - uint8_t count_same_priority_lcids = 0; + uint num_lcids_same_priority = 0; + uint count_same_priority_lcids = 0; // variable used to store the total bytes read from rlc for each lcid uint32_t lcids_bytes_tot[NR_MAX_NUM_LCID] = {0}; - for (uint8_t id = 0; id < avail_lcids_count; id++) { + for (uint id = 0; id < avail_lcids_count; id++) { /* loop over all logical channels in the order of priority. As stated in TS138.321 Section 5.4.3.1, in the first run, only prioritized number of bytes are taken out from the corresponding RLC buffers of all active logical channels and if there is @@ -3577,45 +3495,36 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, is placed in the MAC PDU before going on to next high priority logical channel */ int lcid = lcids_bj_pos[id].lcid; - NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); int idx = lcid_buffer_index(lcid); // skip the logical channel if no data in the buffer initially or the data in the buffer was zero because it was written in to // MAC PDU - if (!lc_sched_info->LCID_buffer_with_data || !lcids_data_status[idx]) { - lcids_data_status[idx] = false; + if (!mac_ce_info.lcids_data_status[idx]) { continue; } // count number of lc with same priority as lcid if (!num_lcids_same_priority) { - num_lcids_same_priority = count_same_priority_lcids = - get_count_lcids_same_priority(id, avail_lcids_count, lcids_bj_pos); + num_lcids_same_priority = count_same_priority_lcids = get_count_lcids_same_priority(id, avail_lcids_count, lcids_bj_pos); } - buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size); - + int remain = mac_ce_info.end_for_tailer - mac_ce_info.cur_ptr; LOG_D(NR_MAC, - "[UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header " - "len %d bytes," - "buflen_remain %d bytes)\n", + "[UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x buflen_remain %d bytes)\n", mac->ue_id, frame, slot, lcid, - buflen, - mac_ce_p->sdu_length_total, - mac_ce_p->tot_mac_ce_len, - buflen_remain); + remain); if (num_lcids_same_priority == count_same_priority_lcids) { - const int32_t buflen_ep_tmp = (buflen_remain - (count_same_priority_lcids * sh_size)) / count_same_priority_lcids; + buflen_ep = (remain - (count_same_priority_lcids * sizeof(NR_MAC_SUBHEADER_LONG))) / count_same_priority_lcids; /* after serving equal priority LCIDs in the first round, buflen_remain could be > 0 and < (count_same_priority_lcids * sh_size) if above division yeilds a remainder. hence the following sets buflen_ep to 0 if there is not enough buffer left for subsequent rounds */ - buflen_ep = buflen_ep_tmp < 0 ? 0 : buflen_ep_tmp; + buflen_ep = buflen_ep < 0 ? 0 : buflen_ep; } - while (buflen_remain > 0) { + while (mac_ce_info.end_for_tailer - mac_ce_info.cur_ptr > 0) { /* loops until the requested number of bytes from MAC to RLC are placed in the MAC PDU. The number of requested bytes depends on whether it is the first run or otherwise because in the first run only prioritited number of bytes of all @@ -3626,80 +3535,38 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, frame, slot, gNB_index, - buflen, - &buflen_remain, lcid, - &pdu, - &lcp_allocation_counter, count_same_priority_lcids, buflen_ep, lcids_bytes_tot, - &num_sdus, - mac_ce_p, - lcids_data_status, - &num_lcids_same_priority)) { + &mac_ce_info, + &num_lcids_same_priority, + LCG_bytes)) { break; } } } - lcp_allocation_counter++; - } while (buflen_remain > 0 && get_dataavailability_buffers(avail_lcids_count, lcids_bj_pos, lcids_data_status)); + mac_ce_info.lcp_allocation_counter++; + } while (mac_ce_info.end_for_tailer - mac_ce_info.cur_ptr > sizeof(NR_MAC_SUBHEADER_LONG) + && get_dataavailability_buffers(avail_lcids_count, lcids_bj_pos, mac_ce_info.lcids_data_status)); - //nr_ue_get_sdu_mac_ce_post recalculates all mac_ce related header fields since buffer has been changed after mac_rlc_data_req. - //Also, BSR padding is handled here after knowing mac_ce_p->sdu_length_total. - nr_ue_get_sdu_mac_ce_post(mac, frame, slot, ulsch_buffer, buflen, mac_ce_p); - - if (mac_ce_p->tot_mac_ce_len > 0) { - LOG_D(NR_MAC, "In %s copying %d bytes of MAC CEs to the UL PDU \n", __FUNCTION__, mac_ce_p->tot_mac_ce_len); - int size = nr_write_ce_ulsch_pdu(pdu, mac, mac_ce_p->phr_ce_len ? mac_ce_p->phr : NULL, 0, mac_ce_p->bsr_t, mac_ce_p->bsr_s, mac_ce_p->bsr_l); - if (size != mac_ce_p->tot_mac_ce_len) - LOG_E(NR_MAC, "MAC CE size computed by nr_write_ce_ulsch_pdu is %d while the one assumed before is %d\n", size, mac_ce_p->tot_mac_ce_len); - pdu += (unsigned char) mac_ce_p->tot_mac_ce_len; - -#ifdef ENABLE_MAC_PAYLOAD_DEBUG - LOG_I(NR_MAC, "In %s: dumping MAC CE with length tot_mac_ce_len %d: \n", __FUNCTION__, mac_ce_p->tot_mac_ce_len); - log_dump(NR_MAC, mac_header_control_elements, mac_ce_p->tot_mac_ce_len, LOG_DUMP_CHAR, "\n"); -#endif - } - - buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total); + nr_ue_get_sdu_mac_ce_post(mac, frame, slot, &mac_ce_info, LCG_bytes, BSRsent); // Compute final offset for padding and fill remainder of ULSCH with 0 - if (buflen_remain > 0) { - - LOG_D(NR_MAC, "Filling remainder %d bytes to the UL PDU \n", buflen_remain); - ((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = UL_SCH_LCID_PADDING; - -#ifdef ENABLE_MAC_PAYLOAD_DEBUG - LOG_I(NR_MAC, "Padding MAC sub-header with length %ld bytes \n", sizeof(NR_MAC_SUBHEADER_FIXED)); - log_dump(NR_MAC, pdu, sizeof(NR_MAC_SUBHEADER_FIXED), LOG_DUMP_CHAR, "\n"); -#endif - - pdu++; - buflen_remain--; - - if (IS_SOFTMODEM_RFSIM) { - for (int j = 0; j < buflen_remain; j++) { - pdu[j] = (unsigned char)rand(); - } - } else { - memset(pdu, 0, buflen_remain); - } - -#ifdef ENABLE_MAC_PAYLOAD_DEBUG - LOG_I(NR_MAC, "MAC padding sub-PDU with length %d bytes \n", buflen_remain); - log_dump(NR_MAC, pdu, buflen_remain, LOG_DUMP_CHAR, "\n"); -#endif + int remain = mac_ce_info.pdu_end - mac_ce_info.cur_ptr; + if (remain) { + LOG_D(NR_MAC, "Filling remainder %d bytes to the UL PDU \n", remain); + *(NR_MAC_SUBHEADER_FIXED *)mac_ce_info.cur_ptr = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_PADDING}; + mac_ce_info.cur_ptr++; + memset(mac_ce_info.cur_ptr, 0, mac_ce_info.pdu_end - mac_ce_info.cur_ptr); } - #ifdef ENABLE_MAC_PAYLOAD_DEBUG - LOG_I(NR_MAC, "Dumping MAC PDU with length %d: \n", buflen); + LOG_I(NR_MAC, "MAC PDU %d bytes \n", mac_ce_p->cur_ptr - ulsch_buffer); log_dump(NR_MAC, ulsch_buffer, buflen, LOG_DUMP_CHAR, "\n"); #endif - return num_sdus > 0 ? 1 : 0; + return mac_ce_info.num_sdus > 0; // success if we got at least one sdu } static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac) @@ -3726,7 +3593,7 @@ static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac, nr_phr_info_t *phr_info = &mac->scheduling_info.phr_info; // Value mapping according to 38.133 10.1.18.1 const int PC_MAX_00 = -29; - phr->PCMAX = max(0, (int)P_CMAX - PC_MAX_00) & 0x3f; + *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE){.PCMAX = max(0, (int)P_CMAX - PC_MAX_00) & 0x3f}; // Value mapping according to 38.133 10.1.17.1.1 const int POWER_HEADROOM_55 = 22; int headroom = P_CMAX - tx_power; diff --git a/openair2/LAYER2/NR_MAC_UE/tests/CMakeLists.txt b/openair2/LAYER2/NR_MAC_UE/tests/CMakeLists.txt index 40c8c5372b..6bb9d1b480 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/CMakeLists.txt +++ b/openair2/LAYER2/NR_MAC_UE/tests/CMakeLists.txt @@ -4,3 +4,9 @@ target_link_libraries(test_nr_ue_power_procedures PRIVATE nr_ue_power_procedures add_dependencies(tests test_nr_ue_power_procedures) add_test(NAME test_nr_ue_power_procedures COMMAND ./test_nr_ue_power_procedures) + +add_executable(test_nr_ue_ra_procedures test_nr_ue_ra_procedures.cpp) +target_link_libraries(test_nr_ue_ra_procedures PRIVATE nr_ue_ra_procedures nr_ue_power_procedures GTest::gtest minimal_lib) +add_dependencies(tests test_nr_ue_ra_procedures) +add_test(NAME test_nr_ue_ra_procedures + COMMAND ./test_nr_ue_ra_procedures) diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp new file mode 100644 index 0000000000..12502b9065 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -0,0 +1,150 @@ +/* + * 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 "gtest/gtest.h" +extern "C" { +#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" +#include "executables/softmodem-common.h" +uint64_t get_softmodem_optmask(void) +{ + return 0; +} +static softmodem_params_t softmodem_params; +softmodem_params_t *get_softmodem_params(void) +{ + return &softmodem_params; +} +void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) +{ +} +int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, + NR_UE_MAC_INST_t *mac, + NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom, + const type_bsr_t *bsr, + uint8_t *mac_ce_end) +{ + return 0; +} +int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end) +{ + return 0; +} +tbs_size_t mac_rlc_data_req(const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP, + char *buffer_pP, + const uint32_t sourceL2Id, + const uint32_t destinationL2Id) +{ + return 0; +} +fapi_nr_ul_config_request_pdu_t *lockGet_ul_config(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int slot_tx, uint8_t pdu_type) +{ + return nullptr; +} +void release_ul_config(fapi_nr_ul_config_request_pdu_t *configPerSlot, bool clearIt) +{ +} +void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu) +{ +} +int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, + int slot, + frame_t frame, + uint16_t rnti, + PUCCH_sched_t *pucch, + fapi_nr_ul_config_pucch_pdu *pucch_pdu) +{ + return 0; +} +} +#include +#include "common/utils/LOG/log.h" + +TEST(test_init_ra, four_step_cbra) +{ + NR_UE_MAC_INST_t mac = {0}; + NR_PRACH_RESOURCES_t prach_resources = {0}; + NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; + NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0}; + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = nullptr; + NR_UE_UL_BWP_t current_bwp; + mac.current_UL_BWP = ¤t_bwp; + long scs = 1; + current_bwp.scs = scs; + current_bwp.channel_bandwidth = 40; + nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs; + mac.p_Max = 23; + mac.nr_band = 78; + mac.frame_type = TDD; + mac.frequency_range = FR1; + + init_RA(&mac, &prach_resources, &nr_rach_ConfigCommon, &rach_ConfigGeneric, rach_ConfigDedicated); + + EXPECT_EQ(mac.ra.ra_type, RA_4_STEP); + EXPECT_EQ(mac.state, UE_PERFORMING_RA); + EXPECT_EQ(mac.ra.RA_active, true); + EXPECT_EQ(mac.ra.cfra, 0); +} + +TEST(test_init_ra, four_step_cfra) +{ + NR_UE_MAC_INST_t mac = {0}; + NR_PRACH_RESOURCES_t prach_resources = {0}; + NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; + NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0}; + NR_UE_UL_BWP_t current_bwp; + mac.current_UL_BWP = ¤t_bwp; + long scs = 1; + current_bwp.scs = scs; + current_bwp.channel_bandwidth = 40; + nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs; + mac.p_Max = 23; + mac.nr_band = 78; + mac.frame_type = TDD; + mac.frequency_range = FR1; + + NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0}; + struct NR_CFRA cfra; + rach_ConfigDedicated.cfra = &cfra; + + init_RA(&mac, &prach_resources, &nr_rach_ConfigCommon, &rach_ConfigGeneric, &rach_ConfigDedicated); + + EXPECT_EQ(mac.ra.ra_type, RA_4_STEP); + EXPECT_EQ(mac.state, UE_PERFORMING_RA); + EXPECT_EQ(mac.ra.RA_active, true); + EXPECT_EQ(mac.ra.cfra, 1); +} + +int main(int argc, char **argv) +{ + logInit(); + uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY); + g_log->log_component[MAC].level = OAILOG_DEBUG; + g_log->log_component[NR_MAC].level = OAILOG_DEBUG; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index bed7f2c961..9ded767395 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -345,9 +345,6 @@ static void config_common(gNB_MAC_INST *nrmac, } } - uint32_t band = *frequencyInfoDL->frequencyBandList.list.array[0]; - frequency_range = band < 100 ? FR1 : FR2; - frame_type_t frame_type = get_frame_type(*frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); nrmac->common_channels[0].frame_type = frame_type; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 0a51c9c803..4e591b6a7a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -778,11 +778,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) { const int n_slots_frame = nr_slots_per_frame[mu]; - NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, - sched_frame, - sched_slot, - ra->beam_id, - n_slots_frame); + NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, n_slots_frame); if (beam_ul.idx < 0) return; NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, ra->beam_id, n_slots_frame); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 82106d0ef2..4022476ac6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -613,7 +613,7 @@ static void pf_dl(module_id_t module_id, gNB_MAC_INST *mac = RC.nrmac[module_id]; NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon; // UEs that could be scheduled - UEsched_t UE_sched[MAX_MOBILES_PER_GNB] = {0}; + UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0}; int remainUEs = max_num_ue; int curUE = 0; int CC_id = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index dc442bedd0..e0cc7a8fe0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2729,10 +2729,6 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo NR_SCHED_ENSURE_LOCKED(&gNB_mac->sched_lock); - // TODO implement beam procedures - int beam = 0; - uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map[beam]; - UE_info->sched_csirs = 0; UE_iterator(UE_info->list, UE) { @@ -2764,8 +2760,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo } } - if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList != NULL && - nzp != NULL) { + if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList != NULL && nzp != NULL) { NR_NZP_CSI_RS_Resource_t *nzpcsi; int period, offset; @@ -2779,12 +2774,14 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo continue; NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping; - csi_period_offset(NULL,nzpcsi->periodicityAndOffset,&period,&offset); + csi_period_offset(NULL, nzpcsi->periodicityAndOffset, &period, &offset); - if((frame*n_slots_frame+slot-offset)%period == 0) { + if((frame * n_slots_frame + slot - offset) % period == 0) { - LOG_D(NR_MAC,"Scheduling CSI-RS in frame %d slot %d Resource ID %ld\n", - frame, slot, nzpcsi->nzp_CSI_RS_ResourceId); + LOG_D(NR_MAC,"Scheduling CSI-RS in frame %d slot %d Resource ID %ld\n", frame, slot, nzpcsi->nzp_CSI_RS_ResourceId); + NR_beam_alloc_t beam_csi = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, UE->UE_beam_index, n_slots_frame); + AssertFatal(beam_csi.idx >= 0, "Cannot allocate CSI-RS in any available beam\n"); + uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map[beam_csi.idx]; UE_info->sched_csirs |= (1 << dl_bwp->bwp_id); nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; @@ -2793,6 +2790,11 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo dl_tti_csirs_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_csi_rs_pdu)); nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csirs_pdu_rel15 = &dl_tti_csirs_pdu->csi_rs_pdu.csi_rs_pdu_rel15; + csirs_pdu_rel15->precodingAndBeamforming.num_prgs = 1; + csirs_pdu_rel15->precodingAndBeamforming.prg_size = resourceMapping.freqBand.nrofRBs; //1 PRG of max size + csirs_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces = 1; + csirs_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0; + csirs_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; csirs_pdu_rel15->bwp_size = dl_bwp->BWPSize; csirs_pdu_rel15->bwp_start = dl_bwp->BWPStart; csirs_pdu_rel15->subcarrier_spacing = dl_bwp->scs; @@ -2962,8 +2964,9 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo static void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) { + DevAssert(cell_group != NULL); /* remove a reconfigurationWithSync, we don't need it anymore */ - if (cell_group->spCellConfig->reconfigurationWithSync != NULL) { + if (cell_group->spCellConfig && cell_group->spCellConfig->reconfigurationWithSync != NULL) { ASN_STRUCT_FREE(asn_DEF_NR_ReconfigurationWithSync, cell_group->spCellConfig->reconfigurationWithSync); cell_group->spCellConfig->reconfigurationWithSync = NULL; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 4c0d40d24f..8a38c6e66d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1790,7 +1790,7 @@ static void pf_ul(module_id_t module_id, const int min_rb = nrmac->min_grant_prb; // UEs that could be scheduled - UEsched_t UE_sched[MAX_MOBILES_PER_GNB] = {0}; + UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0}; int remainUEs = max_num_ue; int curUE = 0; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index b8fd148876..2ebd18f5e7 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -114,14 +114,19 @@ logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id) for (logical_chan_id_t id = 1; id <= 32; id++) { nr_rlc_rb_t *rb = &ue->lcid2rb[id - 1]; if (is_srb) { - if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id) + if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id) { + nr_rlc_manager_unlock(nr_rlc_ue_manager); return id; + } } else { - if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id) + if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id) { + nr_rlc_manager_unlock(nr_rlc_ue_manager); return id; + } } } LOG_E(RLC, "Couldn't find LCID corresponding to %s %d\n", is_srb ? "SRB" : "DRB", rb_id); + nr_rlc_manager_unlock(nr_rlc_ue_manager); return 0; } @@ -614,10 +619,6 @@ static void max_retx_reached(void *_ue, nr_rlc_entity_t *entity) int i; int is_srb; int rb_id; -#if 0 - MessageDef *msg; -#endif - int is_enb; /* is it SRB? */ for (i = 0; i < 2; i++) { @@ -645,23 +646,18 @@ rb_found: is_srb ? "SRB" : "DRB", rb_id); - /* TODO: do something for DRBs? */ - if (is_srb == 0) - return; + if (ue->rlf_handler) + ue->rlf_handler(ue->ue_id); + else + LOG_W(RLC, "UE %04x: RLF detected, but no callable RLF handler registered\n", ue->ue_id); +} - is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager); - if (!is_enb) - return; - -#if 0 - msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION); - RLC_SDU_INDICATION(msg).rnti = ue->rnti; - RLC_SDU_INDICATION(msg).is_successful = 0; - RLC_SDU_INDICATION(msg).srb_id = rb_id; - RLC_SDU_INDICATION(msg).message_id = -1; - /* TODO: accept more than 1 instance? here we send to instance id 0 */ - itti_send_msg_to_task(TASK_RRC_ENB, 0, msg); -#endif +void nr_rlc_set_rlf_handler(int ue_id, rlf_handler_t rlf_h) +{ + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + ue->rlf_handler = rlf_h; + nr_rlc_manager_unlock(nr_rlc_ue_manager); } void nr_rlc_reestablish_entity(int ue_id, int lc_id) @@ -671,6 +667,7 @@ void nr_rlc_reestablish_entity(int ue_id, int lc_id) if (ue == NULL) { LOG_E(RLC, "RLC instance for the given UE was not found \n"); + nr_rlc_manager_unlock(nr_rlc_ue_manager); return; } nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, lc_id); @@ -1099,8 +1096,14 @@ bool nr_rlc_update_id(int from_id, int to_id) return true; } -/* This function is for testing purposes. At least on a COTS UE, it will - * trigger a reestablishment. */ +/** + * @brief This function is for testing purposes. + * Re-establishment is triggered by resetting RLC counters of the bearer, + * which leads to UE reaching maximum RLC retransmissions, RLF detection + * and RRC triggering re-sync. It is assumed that there is ongoing traffic on the bearer. + * - With COTS UEs, triggers re-establishment on SRB 1, where periodical measurement reports are sent. + * - With OAI UE, triggers re-establishment on DRB 1, assuming there is ongoing data traffic. + */ void nr_rlc_test_trigger_reestablishment(int ue_id) { nr_rlc_manager_lock(nr_rlc_ue_manager); @@ -1114,6 +1117,9 @@ void nr_rlc_test_trigger_reestablishment(int ue_id) * as the UE context is created. */ nr_rlc_entity_t *ent = ue->srb[0]; ent->reestablishment(ent); + /* Trigger re-establishment on OAI UE */ + nr_rlc_entity_t *drb = ue->drb[0]; + drb->reestablishment(drb); nr_rlc_manager_unlock(nr_rlc_ue_manager); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index 736c42a0b7..10182f3793 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -44,6 +44,8 @@ struct NR_LogicalChannelConfig; void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); +void nr_rlc_set_rlf_handler(int ue_id, rlf_handler_t rlf_h); + logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id); void nr_rlc_reestablish_entity(int ue_id, int lc_id); void nr_rlc_remove_ue(int ue_id); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h index e37d7929d8..13f5c55a2f 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h @@ -37,12 +37,15 @@ typedef struct nr_rlc_rb_t { } choice; } nr_rlc_rb_t; +typedef void (*rlf_handler_t)(int rnti); + typedef struct nr_rlc_ue_t { int ue_id; nr_rlc_entity_t *srb0; nr_rlc_entity_t *srb[3]; nr_rlc_entity_t *drb[MAX_DRBS_PER_UE]; nr_rlc_rb_t lcid2rb[32]; + rlf_handler_t rlf_handler; } nr_rlc_ue_t; /***********************************************************************/ diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 6966394667..f955528167 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -542,7 +542,7 @@ void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig, NR_SCS_SpecificCarrier_t *scs_carrier = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]; int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - const frequency_range_t freq_range = band < 100 ? FR1 : FR2; + const frequency_range_t freq_range = band < 257 ? FR1 : FR2; const int scs = scs_carrier->subcarrierSpacing; const int bw_size = scs_carrier->carrierBandwidth; @@ -2302,7 +2302,7 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, } const NR_FreqBandIndicatorNR_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - frequency_range_t frequency_range = band < 100 ? FR1 : FR2; + frequency_range_t frequency_range = band > 256 ? FR2 : FR1; sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = get_ssb_offset_to_pointA(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index c018b8030a..881a6d7fee 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -915,7 +915,7 @@ static void rrc_gNB_process_RRCReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RR * reestablishment, instead of re-requesting the CellGroupConfig from the DU. * Hence, add below hack; the solution would be to request the * CellGroupConfig from the DU when doing reestablishment. */ - if (cellGroupConfig->spCellConfig->reconfigurationWithSync != NULL) { + if (cellGroupConfig->spCellConfig && cellGroupConfig->spCellConfig->reconfigurationWithSync) { ASN_STRUCT_FREE(asn_DEF_NR_ReconfigurationWithSync, cellGroupConfig->spCellConfig->reconfigurationWithSync); cellGroupConfig->spCellConfig->reconfigurationWithSync = NULL; } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 53364b0768..13e5965d75 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -151,6 +151,11 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers); +NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance) +{ + return &NR_UE_rrc_inst[instance]; +} + static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id) { AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id); @@ -873,6 +878,13 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, return 0; } +static void nr_rrc_signal_maxrtxindication(int ue_id) +{ + MessageDef *msg = itti_alloc_new_message(TASK_RLC_UE, ue_id, NR_RRC_RLC_MAXRTX); + NR_RRC_RLC_MAXRTX(msg).ue_id = ue_id; + itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, msg); +} + static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupConfig_t *cellGroupConfig) { @@ -901,9 +913,11 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; nr_rlc_add_srb(rrc->ue_id, srb_id, rlc_bearer); + nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); } else { // DRB NR_DRB_Identity_t drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity; nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer); + nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); } } } @@ -1843,6 +1857,15 @@ void *rrc_nrue(void *notUsed) nr_rrc_going_to_IDLE(rrc, release_cause, NULL); break; + case NR_RRC_RLC_MAXRTX: + // detection of RLF upon indication from RLC that the maximum number of retransmissions has been reached + LOG_W(NR_RRC, + "[UE %ld ID %d] Received indication that RLC reached max retransmissions\n", + instance, + NR_RRC_RLC_MAXRTX(msg_p).ue_id); + handle_rlf_detection(rrc); + break; + case NR_RRC_MAC_MSG3_IND: nr_rrc_handle_msg3_indication(rrc, NR_RRC_MAC_MSG3_IND(msg_p).rnti); break; @@ -2285,6 +2308,26 @@ void handle_RRCRelease(NR_UE_RRC_INST_t *rrc) asn1cFreeStruc(asn_DEF_NR_RRCRelease, rrc->RRCRelease); } +void handle_rlf_detection(NR_UE_RRC_INST_t *rrc) +{ + // 5.3.10.3 in 38.331 + bool srb2 = rrc->Srb[2] != RB_NOT_PRESENT; + bool any_drb = false; + for (int i = 0; i < MAX_DRBS_PER_UE; i++) { + if (rrc->status_DRBs[i] != RB_NOT_PRESENT) { + any_drb = true; + break; + } + } + + if (rrc->as_security_activated && srb2 && any_drb) // initiate the connection re-establishment procedure + nr_rrc_initiate_rrcReestablishment(rrc, NR_ReestablishmentCause_otherFailure, 0); + else { + NR_Release_Cause_t cause = rrc->as_security_activated ? RRC_CONNECTION_FAILURE : OTHER; + nr_rrc_going_to_IDLE(rrc, cause, NULL); + } +} + void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, NR_Release_Cause_t release_cause, NR_RRCRelease_t *RRCRelease) diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 95685c8e2f..d1f1d3228f 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -42,7 +42,7 @@ #include "common/utils/ocp_itti/intertask_interface.h" NR_UE_RRC_INST_t *nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx); - +NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance); void init_nsa_message (NR_UE_RRC_INST_t *rrc, char* reconfig_file, char* rbconfig_file); void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message, int msg_len); @@ -63,6 +63,7 @@ void *rrc_nrue_task(void *args_p); void *rrc_nrue(void *args_p); void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc); +void handle_rlf_detection(NR_UE_RRC_INST_t *rrc); /**\brief RRC NSA UE task. \param void *args_p Pointer on arguments to start the task. */ diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index f0635b16b2..7e0c040731 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -157,10 +157,9 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) bool t310_expired = nr_timer_tick(&timers->T310); if(t310_expired) { LOG_W(NR_RRC, "Timer T310 expired\n"); - // TODO // handle detection of radio link failure // as described in 5.3.10.3 of 38.331 - AssertFatal(false, "Radio link failure! Not handled yet!\n"); + handle_rlf_detection(rrc); } bool t311_expired = nr_timer_tick(&timers->T311); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu0.25prb.rfsim.conf new file mode 100644 index 0000000000..274f31db46 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu0.25prb.rfsim.conf @@ -0,0 +1,280 @@ +Active_gNBs = ( "5G-GOA-gNB"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "5G-GOA-gNB"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + + sib1_tda = 5; + min_rxtxtime = 6; + disable_harq = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN 6221 = 497770, (GSCN 6215 - 497290) + absoluteFrequencySSB = 497770; + dl_frequencyBand = 254; + # this is 2486.9 MHz + dl_absoluteFrequencyPointA = 497380; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 0; + dl_carrierBandwidth = 25; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=25 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 0; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 254; + # this is 1613.4 MHz + ul_absoluteFrequencyPointA = 322680; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 0; + ul_carrierBandwidth = 25; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 0; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 0; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 0; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 0; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; //GEO + ta-Common-r17 = 29319745; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + sdr_addrs = "type=x300"; + clock_src = "internal"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf new file mode 100644 index 0000000000..a84bf9c88f --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf @@ -0,0 +1,280 @@ +Active_gNBs = ( "5G-GOA-gNB"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "5G-GOA-gNB"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + + sib1_tda = 5; + min_rxtxtime = 6; + disable_harq = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN 6221 = 497770, (GSCN 6215 - 497290) + absoluteFrequencySSB = 497770; + dl_frequencyBand = 254; + # this is 2483.90 Mhz + dl_absoluteFrequencyPointA = 496780; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=25 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 254; + # this is 1610.4 MHz + ul_absoluteFrequencyPointA = 322080; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; //GEO + ta-Common-r17 = 29319745; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + sdr_addrs = "type=x300"; + clock_src = "internal"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf new file mode 100644 index 0000000000..98cd0fb66b --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf @@ -0,0 +1,279 @@ +Active_gNBs = ( "5G-GOA-gNB"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "5G-GOA-gNB"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + + sib1_tda = 5; + min_rxtxtime = 6; + disable_harq = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN 3855 - 308430 + absoluteFrequencySSB = 308430; + dl_frequencyBand = 255; + # this is 1540.35 MHz + dl_absoluteFrequencyPointA = 308070; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 0; + dl_carrierBandwidth = 25; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=25 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 0; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 255; + ul_absoluteFrequencyPointA = 328370; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 0; + ul_carrierBandwidth = 25; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 0; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 0; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 0; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 0; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; //GEO + ta-Common-r17 = 29319745; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + sdr_addrs = "type=x300"; + clock_src = "internal"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf new file mode 100644 index 0000000000..221b6b0c89 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf @@ -0,0 +1,279 @@ +Active_gNBs = ( "5G-GOA-gNB"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "5G-GOA-gNB"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + + sib1_tda = 5; + min_rxtxtime = 6; + disable_harq = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN 5459 - 436810 + absoluteFrequencySSB = 436810; + dl_frequencyBand = 256; + # this is 2181.95 MHz + dl_absoluteFrequencyPointA = 436390; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 0; + dl_carrierBandwidth = 25; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=25 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 0; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 256; + ul_absoluteFrequencyPointA = 398390; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 0; + ul_carrierBandwidth = 25; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6600; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 0; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 0; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 0; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 0; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; //GEO + ta-Common-r17 = 29319745; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + sdr_addrs = "type=x300"; + clock_src = "internal"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; +