From 0d0e1111354877464a213663c60dfb45872e399e Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Sun, 14 Jan 2024 10:17:50 +0100 Subject: [PATCH 01/41] remove asserts on min RX/TX, set the RX/TX shift as 2 in the UE --- openair1/PHY/impl_defs_top.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 10 ---------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 18 ------------------ 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index c06cd13ff7..e43100d32a 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -272,7 +272,7 @@ /* - between reception of pdsch and tarnsmission of its acknowlegment */ /* - between reception of un uplink grant and its related transmission */ // should be 2 as per NR standard, but current UE is not able to perform this value -#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3) +#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (2) #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 5f0bc51e9a..0b4b33c6e8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -767,10 +767,6 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, } if (dci_ind->rnti != mac->ra.ra_rnti && dci_ind->rnti != SI_RNTI) - AssertFatal(1 + dci->pdsch_to_harq_feedback_timing_indicator.val > DURATION_RX_TO_TX, - "PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%d).\n", - 1 + dci->pdsch_to_harq_feedback_timing_indicator.val, - DURATION_RX_TO_TX); // set the harq status at MAC for feedback set_harq_status(mac, @@ -1098,12 +1094,6 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac, // according to TS 38.213 Table 9.2.3-1 uint8_t feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; - AssertFatal(feedback_ti > DURATION_RX_TO_TX, - "PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%d). Min feedback time set in config " - "file (min_rxtxtime).\n", - feedback_ti, - DURATION_RX_TO_TX); - // set the harq status at MAC for feedback set_harq_status(mac, dci->pucch_resource_indicator, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 8c9062d8ec..adf4e11125 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -996,9 +996,6 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger return; } - AssertFatal(slot_offset > DURATION_RX_TO_TX, - "Slot offset between DCI and aperiodic SRS (%d) needs to be higher than DURATION_RX_TO_TX (%d)\n", - slot_offset, DURATION_RX_TO_TX); int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; int sched_slot = (slot + slot_offset) % n_slots_frame; NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->tdd_UL_DL_ConfigurationCommon; @@ -1434,13 +1431,6 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, AssertFatal(1 == 0, "Invalid numerology %i\n", mu); } - AssertFatal((k2 + delta) > DURATION_RX_TO_TX, - "Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%d). Please set min_rxtxtime at least to %d in gNB config file or gNBs.[0].min_rxtxtime=%d via command line.\n", - k2, - DURATION_RX_TO_TX, - DURATION_RX_TO_TX, - DURATION_RX_TO_TX); - *slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; if (current_slot + k2 + delta >= nr_slots_per_frame[mu]){ *frame_tx = (current_frame + 1) % 1024; @@ -1449,14 +1439,6 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, } } else { - - AssertFatal(k2 > DURATION_RX_TO_TX, - "Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%d). Please set min_rxtxtime at least to %d in gNB config file or gNBs.[0].min_rxtxtime=%d via command line.\n", - k2, - DURATION_RX_TO_TX, - DURATION_RX_TO_TX, - DURATION_RX_TO_TX); - if (k2 < 0) { // This can happen when a false DCI is received LOG_W(PHY, "%d.%d. Received k2 %ld\n", current_frame, current_slot, k2); return -1; From 90f82d19da89892c447fb27e7725a887fe68b74d Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 29 Apr 2024 12:39:44 +0200 Subject: [PATCH 02/41] remove false DCI reception indication --- .../CODING/nrPolar_tools/nr_polar_encoder.c | 12 +-- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 76 +++++-------------- 2 files changed, 23 insertions(+), 65 deletions(-) diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c index f411e0c6be..1668631029 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c @@ -488,12 +488,12 @@ void build_polar_tables(t_nrPolar_params *polarParams) { void polar_encoder_fast(uint64_t *A, void *out, - int32_t crcmask, - uint8_t ones_flag, - int8_t messageType, - uint16_t messageLength, - uint8_t aggregation_level) { - + int32_t crcmask, + uint8_t ones_flag, + int8_t messageType, + uint16_t messageLength, + uint8_t aggregation_level) +{ t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, false); #ifdef POLAR_CODING_DEBUG diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 8392988aaa..e6d5baf753 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -680,36 +680,6 @@ static void nr_pdcch_unscrambling(c16_t *e_rx, } } - -/* This function compares the received DCI bits with - * re-encoded DCI bits and returns the number of mismatched bits - */ -static uint16_t nr_dci_false_detection(uint64_t *dci, - int16_t *soft_in, - int encoded_length, - int rnti, - int8_t messageType, - uint16_t messageLength, - uint8_t aggregation_level) -{ - uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD]; - polar_encoder_fast(dci, (void *)encoder_output, rnti, 1, messageType, messageLength, aggregation_level); - uint8_t *enout_p = (uint8_t*)encoder_output; - uint16_t x = 0; - - for (int i=0; i> 15) & 1); - x += ((enout_p[i] >> 1) & 1) ^ ((soft_in[i * 8 + 1] >> 15) & 1); - x += ((enout_p[i] >> 2) & 1) ^ ((soft_in[i * 8 + 2] >> 15) & 1); - x += ((enout_p[i] >> 3) & 1) ^ ((soft_in[i * 8 + 3] >> 15) & 1); - x += ((enout_p[i] >> 4) & 1) ^ ((soft_in[i * 8 + 4] >> 15) & 1); - x += ((enout_p[i] >> 5) & 1) ^ ((soft_in[i * 8 + 5] >> 15) & 1); - x += ((enout_p[i] >> 6) & 1) ^ ((soft_in[i * 8 + 6] >> 15) & 1); - x += ((enout_p[i] >> 7) & 1) ^ ((soft_in[i * 8 + 7] >> 15) & 1); - } - return x; -} - void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t *pdcch_e_rx, @@ -771,35 +741,23 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, CCEind, dci_length, *(unsigned long long *)dci_estimation); - uint16_t mb = nr_dci_false_detection(dci_estimation, tmp_e, L * 108, n_rnti, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L); - ue->dci_thres = (ue->dci_thres + mb) / 2; - if (mb > (ue->dci_thres + 30)) { - LOG_W(NR_PHY_DCI, - "DCI false positive. Dropping DCI index %d. Mismatched bits: %d/%d. Current DCI threshold: %d\n", - j, - mb, - L * 108, - ue->dci_thres); - continue; - } else { - AssertFatal(dci_ind->number_of_dcis < sizeofArray(dci_ind->dci_list), "Fix allocation\n"); - fapi_nr_dci_indication_pdu_t *dci = dci_ind->dci_list + dci_ind->number_of_dcis; - *dci = (fapi_nr_dci_indication_pdu_t){ - .rnti = n_rnti, - .n_CCE = CCEind, - .N_CCE = L, - .dci_format = rel15->dci_format_options[k], - .ss_type = rel15->ss_type_options[k], - .coreset_type = rel15->coreset.CoreSetType, - }; - int n_rb, rb_offset; - get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset); - dci->cset_start = rel15->BWPStart + rb_offset; - dci->payloadSize = dci_length; - memcpy(dci->payloadBits, dci_estimation, (dci_length + 7) / 8); - dci_ind->number_of_dcis++; - break; // If DCI is found, no need to check for remaining DCI lengths - } + AssertFatal(dci_ind->number_of_dcis < sizeofArray(dci_ind->dci_list), "Fix allocation\n"); + fapi_nr_dci_indication_pdu_t *dci = dci_ind->dci_list + dci_ind->number_of_dcis; + *dci = (fapi_nr_dci_indication_pdu_t){ + .rnti = n_rnti, + .n_CCE = CCEind, + .N_CCE = L, + .dci_format = rel15->dci_format_options[k], + .ss_type = rel15->ss_type_options[k], + .coreset_type = rel15->coreset.CoreSetType, + }; + int n_rb, rb_offset; + get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset); + dci->cset_start = rel15->BWPStart + rb_offset; + dci->payloadSize = dci_length; + memcpy(dci->payloadBits, dci_estimation, (dci_length + 7) / 8); + dci_ind->number_of_dcis++; + break; // If DCI is found, no need to check for remaining DCI lengths } else { LOG_D(NR_PHY_DCI, "(%i.%i) Decoded crc %x does not match rnti %x for DCI format %d\n", From 114fb5dbca855585be0ba7581728751fbdd7eab4 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 29 Apr 2024 14:30:50 +0200 Subject: [PATCH 03/41] bugfix in dci reception, CRC is 24 bits but uint16 was used --- .../CODING/nrPolar_tools/nr_polar_decoder.c | 27 ++++++++++++++----- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c index 61525c6905..4d4970774e 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c @@ -621,7 +621,7 @@ uint32_t polar_decoder_int16(int16_t *input, uint8_t ones_flag, int8_t messageType, uint16_t messageLength, - uint8_t aggregation_level ) + uint8_t aggregation_level) { t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true); @@ -638,7 +638,13 @@ uint32_t polar_decoder_int16(int16_t *input, #endif int16_t d_tilde[polarParams->N]; - nr_polar_rate_matching_int16(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength, polarParams->i_bil); + nr_polar_rate_matching_int16(input, + d_tilde, + polarParams->rate_matching_pattern, + polarParams->K, + polarParams->N, + polarParams->encoderLength, + polarParams->i_bil); for (int i=0; iN; i++) { if (d_tilde[i]<-128) d_tilde[i]=-128; @@ -792,13 +798,20 @@ uint32_t polar_decoder_int16(int16_t *input, printf("\n\n"); #endif -#if 0 - printf("A %llx B %llx|%llx Cprime %llx|%llx (crc %x,rxcrc %llx %d)\n", +#ifdef POLAR_CODING_DEBUG + printf("A %lx B %lx|%lx Cprime %lx|%lx (crc %x,rxcrc %lx, XOR %lx, bits%d)\n", Ar, - B[1],B[0],Cprime[1],Cprime[0],crc, - rxcrc,polarParams->payloadBits); + B[1], + B[0], + Cprime[1], + Cprime[0], + crc, + rxcrc, + crc^rxcrc, + polarParams->payloadBits); #endif - out[0]=Ar; + + out[0] = Ar; polarReturn crc^rxcrc; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index e6d5baf753..47be51813f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -728,7 +728,7 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e); - uint16_t crc = polar_decoder_int16(tmp_e, dci_estimation, 1, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L); + const uint32_t crc = polar_decoder_int16(tmp_e, dci_estimation, 1, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L); rnti_t n_rnti = rel15->rnti; if (crc == n_rnti) { From c719b3f05761d6f6b3b58d97952a5a01b674ddbe Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 1 May 2024 16:13:04 +0200 Subject: [PATCH 04/41] adding new nr bands to the tables --- common/utils/nr/nr_common.c | 6 +++- openair1/PHY/INIT/nr_parms.c | 66 +++++++++++++++++++++++++++++------ openair2/GNB_APP/gnb_config.c | 21 +++++++++++ 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 64aabab0a4..6bc9eff5ff 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -118,10 +118,12 @@ const nr_bandentry_t nr_bandtable[] = { {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, 698000, 716000, 729000, 746000, 20, 145800, 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}, @@ -141,6 +143,7 @@ const nr_bandentry_t nr_bandtable[] = { {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}, @@ -157,6 +160,7 @@ const nr_bandentry_t nr_bandtable[] = { {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}, diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index c96754fe74..2e292e4705 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -29,17 +29,61 @@ 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[48][3] = { - {1, 15, nr_ssb_type_A}, {2, 15, nr_ssb_type_A}, {3, 15, nr_ssb_type_A}, {5, 15, nr_ssb_type_A}, {5, 30, nr_ssb_type_B}, - {7, 15, nr_ssb_type_A}, {8, 15, nr_ssb_type_A}, {12, 15, nr_ssb_type_A}, {14, 15, nr_ssb_type_A}, {18, 15, nr_ssb_type_A}, - {20, 15, nr_ssb_type_A}, {25, 15, nr_ssb_type_A}, {26, 15, nr_ssb_type_A}, {28, 15, nr_ssb_type_A}, {29, 15, nr_ssb_type_A}, - {30, 15, nr_ssb_type_A}, {34, 15, nr_ssb_type_A}, {34, 30, nr_ssb_type_C}, {38, 15, nr_ssb_type_A}, {38, 30, nr_ssb_type_C}, - {39, 15, nr_ssb_type_A}, {39, 30, nr_ssb_type_C}, {40, 30, nr_ssb_type_C}, {41, 15, nr_ssb_type_A}, {41, 30, nr_ssb_type_C}, - {46, 30, nr_ssb_type_C}, {48, 30, nr_ssb_type_C}, {50, 30, nr_ssb_type_C}, {51, 15, nr_ssb_type_A}, {53, 15, nr_ssb_type_A}, - {65, 15, nr_ssb_type_A}, {66, 15, nr_ssb_type_A}, {66, 30, nr_ssb_type_B}, {70, 15, nr_ssb_type_A}, {71, 15, nr_ssb_type_A}, - {74, 15, nr_ssb_type_A}, {75, 15, nr_ssb_type_A}, {76, 15, nr_ssb_type_A}, {77, 30, nr_ssb_type_C}, {78, 30, nr_ssb_type_C}, - {79, 30, nr_ssb_type_C}, {90, 15, nr_ssb_type_A}, {90, 30, nr_ssb_type_C}, {91, 15, nr_ssb_type_A}, {92, 15, nr_ssb_type_A}, - {93, 15, nr_ssb_type_A}, {94, 15, nr_ssb_type_A}, {96, 30, nr_ssb_type_C}}; +static const int nr_ssb_table[54][3] = { + {1, 15, nr_ssb_type_A}, + {2, 15, nr_ssb_type_A}, + {3, 15, nr_ssb_type_A}, + {5, 15, nr_ssb_type_A}, + {5, 30, nr_ssb_type_B}, + {7, 15, nr_ssb_type_A}, + {8, 15, nr_ssb_type_A}, + {12, 15, nr_ssb_type_A}, + {13, 15, nr_ssb_type_A}, + {14, 15, nr_ssb_type_A}, + {18, 15, nr_ssb_type_A}, + {20, 15, nr_ssb_type_A}, + {24, 15, nr_ssb_type_A}, + {24, 30, nr_ssb_type_B}, + {25, 15, nr_ssb_type_A}, + {26, 15, nr_ssb_type_A}, + {28, 15, nr_ssb_type_A}, + {29, 15, nr_ssb_type_A}, + {30, 15, nr_ssb_type_A}, + {34, 15, nr_ssb_type_A}, + {34, 30, nr_ssb_type_C}, + {38, 15, nr_ssb_type_A}, + {38, 30, nr_ssb_type_C}, + {39, 15, nr_ssb_type_A}, + {39, 30, nr_ssb_type_C}, + {40, 30, nr_ssb_type_C}, + {41, 15, nr_ssb_type_A}, + {41, 30, nr_ssb_type_C}, + {46, 30, nr_ssb_type_C}, + {48, 30, nr_ssb_type_C}, + {50, 30, nr_ssb_type_C}, + {51, 15, nr_ssb_type_A}, + {53, 15, nr_ssb_type_A}, + {53, 30, nr_ssb_type_C}, + {65, 15, nr_ssb_type_A}, + {66, 15, nr_ssb_type_A}, + {66, 30, nr_ssb_type_B}, + {67, 15, nr_ssb_type_A}, + {70, 15, nr_ssb_type_A}, + {71, 15, nr_ssb_type_A}, + {74, 15, nr_ssb_type_A}, + {75, 15, nr_ssb_type_A}, + {76, 15, nr_ssb_type_A}, + {77, 30, nr_ssb_type_C}, + {78, 30, nr_ssb_type_C}, + {79, 30, nr_ssb_type_C}, + {85, 15, nr_ssb_type_A}, + {90, 15, nr_ssb_type_A}, + {90, 30, nr_ssb_type_C}, + {91, 15, nr_ssb_type_A}, + {92, 15, nr_ssb_type_A}, + {93, 15, nr_ssb_type_A}, + {94, 15, nr_ssb_type_A}, + {96, 30, nr_ssb_type_C}}; void set_Lmax(NR_DL_FRAME_PARMS *fp) { if (get_softmodem_params()->sl_mode == 2) { diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 7e2d9c5b07..79f4c293dd 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -108,20 +108,35 @@ const sync_raster_t sync_raster[] = { {7, 0, 6554, 1, 6718}, {8, 0, 2318, 1, 2395}, {12, 0, 1828, 1, 1858}, + {13, 0, 1871, 1, 1885}, + {14, 0, 1901, 1, 1915}, + {18, 0, 2156, 1, 2182}, {20, 0, 1982, 1, 2047}, + {24, 0, 3818, 1, 3892}, + {24, 1, 3824, 1, 3886}, {25, 0, 4829, 1, 4981}, + {26, 0, 2153, 1, 2230}, {28, 0, 1901, 1, 2002}, + {29, 0, 1798, 1, 1813}, + {30, 0, 5879, 1, 5893}, {34, 0, 5030, 1, 5056}, + {34, 1, 5036, 1, 5050}, {38, 0, 6431, 1, 6544}, + {38, 1, 6437, 1, 6538}, {39, 0, 4706, 1, 4795}, + {39, 1, 4712, 1, 4789}, {40, 1, 5762, 1, 5989}, {41, 0, 6246, 3, 6717}, {41, 1, 6252, 3, 6714}, {48, 1, 7884, 1, 7982}, {50, 0, 3584, 1, 3787}, {51, 0, 3572, 1, 3574}, + {53, 0, 6215, 1, 6232}, + {53, 1, 6221, 1, 6226}, + {65, 0, 5279, 1, 5494}, {66, 0, 5279, 1, 5494}, {66, 1, 5285, 1, 5488}, + {67, 0, 1850, 1, 1888}, {70, 0, 4993, 1, 5044}, {71, 0, 1547, 1, 1624}, {74, 0, 3692, 1, 3790}, @@ -130,6 +145,12 @@ const sync_raster_t sync_raster[] = { {77, 1, 7711, 1, 8329}, {78, 1, 7711, 1, 8051}, {79, 1, 8480, 16, 8880}, + {85, 0, 1826, 1, 1858}, + {90, 1, 6252, 1, 6714}, + {91, 0, 3572, 1, 3574}, + {92, 0, 3584, 1, 3787}, + {93, 0, 3572, 1, 3574}, + {94, 0, 3584, 1, 3587}, {257, 3, 22388, 1, 22558}, {257, 4, 22390, 2, 22556}, {258, 3, 22257, 1, 22443}, From 1056e53acbc5325c51a1e3977f75cdbe8bc52c1b Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 1 May 2024 16:51:40 +0200 Subject: [PATCH 05/41] mostly formatting --- openair1/PHY/NR_TRANSPORT/nr_prach.c | 4 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 4 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 63 ++++++++++--------- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index d103505357..4bf70acaa8 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -73,8 +73,8 @@ int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) { void nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, - nfapi_nr_prach_pdu_t *prach_pdu) { - + nfapi_nr_prach_pdu_t *prach_pdu) +{ int prach_id = find_nr_prach(gNB,SFN,Slot,SEARCH_EXIST_OR_FREE); AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)), "illegal or no prach_id found!!! prach_id %d\n", prach_id); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 886482bc5d..cd024fbd86 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -81,7 +81,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_ fp->print_ue_help_cmdline_log = false; if (fp->dl_CarrierFreq != fp->ul_CarrierFreq) LOG_A(PHY, - "Command line parameters for the UE: -C %lu --CO %lu -r %d --numerology %d --ssb %d\n", + "Command line parameters for the UE: -C %lu --CO %ld -r %d --numerology %d --ssb %d\n", fp->dl_CarrierFreq, fp->dl_CarrierFreq - fp->ul_CarrierFreq, fp->N_RB_DL, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 1ef7a9e2ce..af6336e12c 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -702,8 +702,8 @@ static const int16_t N_RA_RB[16] = {6, 3, 2, 24, 12, 6, 12, 6, 3, 24, 12, 6, 12, /* Function to get number of RBs required for prach occasion based on * 38.211 Table 6.3.3.2-1 */ -int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH) { - +int16_t get_N_RA_RB (int delta_f_RA_PRACH, int delta_f_PUSCH) +{ int8_t index = 0; switch(delta_f_RA_PRACH) { case 0 : diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 1cca125300..2f6e75e1f6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -266,9 +266,10 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; int mu; - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) - mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + if (rach_ConfigCommon->msg1_SubcarrierSpacing) + mu = *rach_ConfigCommon->msg1_SubcarrierSpacing; else mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; int index = ul_buffer_index(frameP, slotP, mu, gNB->UL_tti_req_ahead_size); @@ -276,8 +277,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; if (is_nr_UL_slot(scc->tdd_UL_DL_ConfigurationCommon, slotP, cc->frame_type)) { - - uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; + const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric; + uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex; uint8_t N_dur, N_t_slot, start_symbol = 0, N_RA_slot; uint16_t RA_sfn_index = -1; uint8_t config_period = 1; @@ -289,22 +290,22 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 - if ( get_nr_prach_info_from_index(config_index, - (int)frameP, - (int)slotP, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - mu, - cc->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period) ) { + if (get_nr_prach_info_from_index(config_index, + (int)frameP, + (int)slotP, + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, + mu, + cc->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period)) { - uint16_t format0 = format&0xff; // first column of format from table - uint16_t format1 = (format>>8)&0xff; // second column of format from table + uint16_t format0 = format & 0xff; // first column of format from table + uint16_t format1 = (format >> 8) & 0xff; // second column of format from table if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe if (slotP%2 == 1) @@ -339,15 +340,19 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP prach_pdu->num_prach_ocas = N_t_slot; prach_pdu->prach_start_symbol = start_symbol; prach_pdu->num_ra = fdm_index; - prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig, + prach_pdu->num_cs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig); + rach_ConfigCommon->restrictedSetConfig); - LOG_D(NR_MAC, "Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n", - frameP, slotP, - prach_occasion_id, prach_pdu->num_ra, + LOG_D(NR_MAC, + "Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n", + frameP, + slotP, + prach_occasion_id, + prach_pdu->num_ra, prach_pdu->prach_start_symbol, - slot_index, RA_sfn_index); + slot_index, + RA_sfn_index); // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities // We added 9 = A1/B1 10 = A2/B2 11 A3/B3 if (format1!=0xff) { @@ -409,15 +414,13 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP } // block resources in vrb_map_UL - const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = - &scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric; const uint8_t mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - const int16_t N_RA_RB = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); + const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); index = ul_buffer_index(frameP, slotP, mu, gNB->vrb_map_UL_size); uint16_t *vrb_map_UL = &cc->vrb_map_UL[index * MAX_BWP_SIZE]; - for (int i = 0; i < N_RA_RB * fdm; ++i) - vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] |= SL_to_bitmap(start_symbol, N_t_slot*N_dur); + for (int i = 0; i < n_ra_rb * fdm; ++i) + vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] |= SL_to_bitmap(start_symbol, N_t_slot * N_dur); } } } From 31b4f48e29170e25e5375e781860cf14eaebee43 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 2 May 2024 20:06:10 +0200 Subject: [PATCH 06/41] ci: set min_rxtxtime = 2 in OAIUE pipeline --- ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index d43d2ed8e9..294d6dba37 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -19,7 +19,7 @@ gNBs = ////////// Physical parameters: - min_rxtxtime = 5; + min_rxtxtime = 2; do_SRS = 0; force_256qam_off = 1; pdsch_AntennaPorts_N1 = 1; From f5dccc2a59c7e1b26fc29d6df7d063814ecc8002 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 29 Jun 2023 14:01:57 +0100 Subject: [PATCH 07/41] Improvements in nr_dlsch_channel_compensation() function --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 371 +++++++----------- 1 file changed, 149 insertions(+), 222 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 6f58ba97a2..6f9eb98594 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -738,6 +738,20 @@ void nr_dlsch_deinterleaving(uint8_t symbol, // Pre-processing for LLR computation //============================================================================================== +simde__m128i nr_dlsch_a_mult_conjb(simde__m128i a, simde__m128i b, unsigned char output_shift) +{ + simde__m128i mmtmpD0 = simde_mm_madd_epi16(b, a); + simde__m128i mmtmpD1 = simde_mm_shufflelo_epi16(b, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); + mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); + mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i *)&conjugate[0]); + mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, a); + mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); + simde__m128i mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); + simde__m128i mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); + return simde_mm_packs_epi32(mmtmpD2, mmtmpD3); +} + static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, int nbRx, c16_t rxdataF_ext[][rx_size_symbol], @@ -757,21 +771,18 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, unsigned char output_shift, PHY_NR_MEASUREMENTS *measurements) { - - - unsigned short rb; - unsigned char aarx,atx; - simde__m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*dl_ch_mag128r,*rxdataF128,*rxdataF_comp128,*rho128; - simde__m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0},QAM_amp128r={0}; + simde__m128i *dl_ch128, *dl_ch128_2, *dl_ch_mag128, *dl_ch_mag128b, *dl_ch_mag128r, *rxdataF128, *rxdataF_comp128, *rho128; + simde__m128i mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3, QAM_amp128 = {0}, QAM_amp128b = {0}, QAM_amp128r = {0}; uint32_t nb_rb_0 = length / 12 + ((length % 12) ? 1 : 0); + for (int l = 0; l < n_layers; l++) { if (mod_order == 4) { - QAM_amp128 = simde_mm_set1_epi16(QAM16_n1); // 2/sqrt(10) + QAM_amp128 = simde_mm_set1_epi16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = simde_mm_setzero_si128(); QAM_amp128r = simde_mm_setzero_si128(); } else if (mod_order == 6) { - QAM_amp128 = simde_mm_set1_epi16(QAM64_n1); // + QAM_amp128 = simde_mm_set1_epi16(QAM64_n1); // QAM_amp128b = simde_mm_set1_epi16(QAM64_n2); QAM_amp128r = simde_mm_setzero_si128(); } else if (mod_order == 8) { @@ -782,257 +793,173 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); - for (aarx=0; aarxnb_antennas_rx; aarx++) { - - dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(l * frame_parms->nb_antennas_rx) + aarx]; dl_ch_mag128 = (simde__m128i *)dl_ch_mag[l][aarx]; dl_ch_mag128b = (simde__m128i *)dl_ch_magb[l][aarx]; dl_ch_mag128r = (simde__m128i *)dl_ch_magr[l][aarx]; - rxdataF128 = (simde__m128i *)rxdataF_ext[aarx]; + rxdataF128 = (simde__m128i *)rxdataF_ext[aarx]; rxdataF_comp128 = (simde__m128i *)(rxdataF_comp[l][aarx] + symbol * nb_rb * 12); - for (rb=0; rb2) { + for (int rb = 0; rb < nb_rb_0; rb++) { + if (mod_order > 2) { // get channel amplitude if not QPSK - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0],dl_ch128[0]); - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_madd_epi16(dl_ch128[1],dl_ch128[1]); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD0 = simde_mm_packs_epi32(mmtmpD0,mmtmpD1); //|H[0]|^2 |H[1]|^2 |H[2]|^2 |H[3]|^2 |H[4]|^2 |H[5]|^2 |H[6]|^2 |H[7]|^2 + mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0], dl_ch128[0]); + mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); + + mmtmpD1 = simde_mm_madd_epi16(dl_ch128[1], dl_ch128[1]); + mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); + + mmtmpD0 = simde_mm_packs_epi32(mmtmpD0, mmtmpD1); //|H[0]|^2 |H[1]|^2 |H[2]|^2 |H[3]|^2 |H[4]|^2 |H[5]|^2 |H[6]|^2 |H[7]|^2 // store channel magnitude here in a new field of dlsch - dl_ch_mag128[0] = simde_mm_unpacklo_epi16(mmtmpD0,mmtmpD0); + dl_ch_mag128[0] = simde_mm_unpacklo_epi16(mmtmpD0, mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; dl_ch_mag128r[0] = dl_ch_mag128[0]; - dl_ch_mag128[0] = simde_mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); - dl_ch_mag128[0] = simde_mm_slli_epi16(dl_ch_mag128[0],1); + dl_ch_mag128[0] = simde_mm_mulhrs_epi16(dl_ch_mag128[0], QAM_amp128); + dl_ch_mag128b[0] = simde_mm_mulhrs_epi16(dl_ch_mag128b[0], QAM_amp128b); + dl_ch_mag128r[0] = simde_mm_mulhrs_epi16(dl_ch_mag128r[0], QAM_amp128r); - dl_ch_mag128b[0] = simde_mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); - dl_ch_mag128b[0] = simde_mm_slli_epi16(dl_ch_mag128b[0],1); - - dl_ch_mag128r[0] = simde_mm_mulhi_epi16(dl_ch_mag128r[0],QAM_amp128r); - dl_ch_mag128r[0] = simde_mm_slli_epi16(dl_ch_mag128r[0],1); - - //print_ints("Re(ch):",(int16_t*)&mmtmpD0); - //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128); - //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]); - dl_ch_mag128[1] = simde_mm_unpackhi_epi16(mmtmpD0,mmtmpD0); + dl_ch_mag128[1] = simde_mm_unpackhi_epi16(mmtmpD0, mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; dl_ch_mag128r[1] = dl_ch_mag128[1]; - dl_ch_mag128[1] = simde_mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); - dl_ch_mag128[1] = simde_mm_slli_epi16(dl_ch_mag128[1],1); + dl_ch_mag128[1] = simde_mm_mulhrs_epi16(dl_ch_mag128[1], QAM_amp128); + dl_ch_mag128b[1] = simde_mm_mulhrs_epi16(dl_ch_mag128b[1], QAM_amp128b); + dl_ch_mag128r[1] = simde_mm_mulhrs_epi16(dl_ch_mag128r[1], QAM_amp128r); - dl_ch_mag128b[1] = simde_mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); - dl_ch_mag128b[1] = simde_mm_slli_epi16(dl_ch_mag128b[1],1); + mmtmpD0 = simde_mm_madd_epi16(dl_ch128[2], dl_ch128[2]); + mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); + mmtmpD1 = simde_mm_packs_epi32(mmtmpD0, mmtmpD0); - dl_ch_mag128r[1] = simde_mm_mulhi_epi16(dl_ch_mag128r[1],QAM_amp128r); - dl_ch_mag128r[1] = simde_mm_slli_epi16(dl_ch_mag128r[1],1); - - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[2],dl_ch128[2]);//[H_I(0)^2+H_Q(0)^2 H_I(1)^2+H_Q(1)^2 H_I(2)^2+H_Q(2)^2 H_I(3)^2+H_Q(3)^2] - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_packs_epi32(mmtmpD0,mmtmpD0);//[|H(0)|^2 |H(1)|^2 |H(2)|^2 |H(3)|^2 |H(0)|^2 |H(1)|^2 |H(2)|^2 |H(3)|^2] - - dl_ch_mag128[2] = simde_mm_unpacklo_epi16(mmtmpD1,mmtmpD1);//[|H(0)|^2 |H(0)|^2 |H(1)|^2 |H(1)|^2 |H(2)|^2 |H(2)|^2 |H(3)|^2 |H(3)|^2] + dl_ch_mag128[2] = simde_mm_unpacklo_epi16(mmtmpD1, mmtmpD1); dl_ch_mag128b[2] = dl_ch_mag128[2]; dl_ch_mag128r[2] = dl_ch_mag128[2]; - dl_ch_mag128[2] = simde_mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); - dl_ch_mag128[2] = simde_mm_slli_epi16(dl_ch_mag128[2],1); - - dl_ch_mag128b[2] = simde_mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); - dl_ch_mag128b[2] = simde_mm_slli_epi16(dl_ch_mag128b[2],1); - - dl_ch_mag128r[2] = simde_mm_mulhi_epi16(dl_ch_mag128r[2],QAM_amp128r); - dl_ch_mag128r[2] = simde_mm_slli_epi16(dl_ch_mag128r[2],1); + dl_ch_mag128[2] = simde_mm_mulhrs_epi16(dl_ch_mag128[2], QAM_amp128); + dl_ch_mag128b[2] = simde_mm_mulhrs_epi16(dl_ch_mag128b[2], QAM_amp128b); + dl_ch_mag128r[2] = simde_mm_mulhrs_epi16(dl_ch_mag128r[2], QAM_amp128r); } - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0],rxdataF128[0]); - // print_ints("re",&mmtmpD0); + // Multiply received data by conjugated channel + rxdataF_comp128[0] = nr_dlsch_a_mult_conjb(rxdataF128[0], dl_ch128[0], output_shift); + rxdataF_comp128[1] = nr_dlsch_a_mult_conjb(rxdataF128[1], dl_ch128[1], output_shift); + rxdataF_comp128[2] = nr_dlsch_a_mult_conjb(rxdataF128[2], dl_ch128[2], output_shift); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(dl_ch128[0],SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1,SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)&conjugate[0]); - // print_ints("im",&mmtmpD1); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,rxdataF128[0]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - // print_ints("re(shift)",&mmtmpD0); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - // print_ints("im(shift)",&mmtmpD1); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - // print_ints("c0",&mmtmpD2); - // print_ints("c1",&mmtmpD3); - rxdataF_comp128[0] = simde_mm_packs_epi32(mmtmpD2,mmtmpD3); - -#ifdef DEBUG_DLSCH_DEMOD - printf("%%arx%d atx%d rb_index %d symbol %d shift %d\n",aarx,l,rb,symbol,output_shift); - printf("rx_%d(%d,:)",aarx+1,rb+1); - print_shorts(" ",(int16_t *)&rxdataF128[0]); - printf("ch_%d%d(%d,:)",aarx+1,l+1,rb+1); - print_shorts(" ",(int16_t *)&dl_ch128[0]); - printf("rx_comp_%d%d(%d,:)",aarx+1,l+1,rb+1); - print_shorts(" ",(int16_t *)&rxdataF_comp128[0]); -#endif - - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[1],rxdataF128[1]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(dl_ch128[1],SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1,SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)conjugate); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,rxdataF128[1]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - - rxdataF_comp128[1] = simde_mm_packs_epi32(mmtmpD2,mmtmpD3); -#ifdef DEBUG_DLSCH_DEMOD - print_shorts("rx:",(int16_t*)&rxdataF128[1]); - print_shorts("ch:",(int16_t*)&dl_ch128[1]); - print_shorts("pack:",(int16_t*)&rxdataF_comp128[1]); -#endif - - // multiply by conjugated channel - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[2],rxdataF128[2]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = simde_mm_shufflelo_epi16(dl_ch128[2],SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1,SIMDE_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = simde_mm_sign_epi16(mmtmpD1,*(simde__m128i*)conjugate); - mmtmpD1 = simde_mm_madd_epi16(mmtmpD1,rxdataF128[2]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = simde_mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = simde_mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - - rxdataF_comp128[2] = simde_mm_packs_epi32(mmtmpD2,mmtmpD3); -#ifdef DEBUG_DLSCH_DEMOD - print_shorts("rx:",(int16_t*)&rxdataF128[2]); - print_shorts("ch:",(int16_t*)&dl_ch128[2]); - print_shorts("pack:",(int16_t*)&rxdataF_comp128[2]); -#endif - - dl_ch128+=3; - dl_ch_mag128+=3; - dl_ch_mag128b+=3; - dl_ch_mag128r+=3; - rxdataF128+=3; - rxdataF_comp128+=3; + dl_ch128 += 3; + dl_ch_mag128 += 3; + dl_ch_mag128b += 3; + dl_ch_mag128r += 3; + rxdataF128 += 3; + rxdataF_comp128 += 3; } } } + if (rho) { - //we compute the Tx correlation matrix for each Rx antenna - //As an example the 2x2 MIMO case requires - //rho[aarx][nl*nl] = [cov(H_aarx_0,H_aarx_0) cov(H_aarx_0,H_aarx_1) - // cov(H_aarx_1,H_aarx_0) cov(H_aarx_1,H_aarx_1)], aarx=0,...,nb_antennas_rx-1 + // we compute the Tx correlation matrix for each Rx antenna + // As an example the 2x2 MIMO case requires + // rho[aarx][nl*nl] = [cov(H_aarx_0,H_aarx_0) cov(H_aarx_0,H_aarx_1) + // cov(H_aarx_1,H_aarx_0) cov(H_aarx_1,H_aarx_1)], aarx=0,...,nb_antennas_rx-1 - //int avg_rho_re[frame_parms->nb_antennas_rx][nl*nl]; - //int avg_rho_im[frame_parms->nb_antennas_rx][nl*nl]; - - for (aarx=0; aarxnb_antennas_rx; aarx++) { + // int avg_rho_re[frame_parms->nb_antennas_rx][nl*nl]; + // int avg_rho_im[frame_parms->nb_antennas_rx][nl*nl]; + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { for (int l = 0; l < n_layers; l++) { + for (int atx = 0; atx < n_layers; atx++) { + // avg_rho_re[aarx][l*n_layers+atx] = 0; + // avg_rho_im[aarx][l*n_layers+atx] = 0; + rho128 = (simde__m128i *)&rho[aarx][l * n_layers + atx][symbol * nb_rb * 12]; + dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[l * frame_parms->nb_antennas_rx + aarx]; + dl_ch128_2 = (simde__m128i *)dl_ch_estimates_ext[atx * frame_parms->nb_antennas_rx + aarx]; - for (atx = 0; atx < n_layers; atx++) { - //avg_rho_re[aarx][l*n_layers+atx] = 0; - //avg_rho_im[aarx][l*n_layers+atx] = 0; - rho128 = (simde__m128i *)&rho[aarx][l * n_layers + atx][symbol * nb_rb * 12]; - dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[l * frame_parms->nb_antennas_rx + aarx]; - dl_ch128_2 = (simde__m128i *)dl_ch_estimates_ext[atx * frame_parms->nb_antennas_rx + aarx]; + for (int rb = 0; rb < nb_rb_0; rb++) { + // multiply by conjugated channel + mmtmpD0 = simde_mm_madd_epi16(dl_ch128[0], dl_ch128_2[0]); + // print_ints("re",&mmtmpD0); + // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) + mmtmpD1 = simde_mm_shufflelo_epi16(dl_ch128[0], SIMDE_MM_SHUFFLE(2, 3, 0, 1)); + mmtmpD1 = simde_mm_shufflehi_epi16(mmtmpD1, SIMDE_MM_SHUFFLE(2, 3, 0, 1)); + mmtmpD1 = simde_mm_sign_epi16(mmtmpD1, *(simde__m128i *)&conjugate[0]); + // print_ints("im",&mmtmpD1); + mmtmpD1 = simde_mm_madd_epi16(mmtmpD1, dl_ch128_2[0]); + // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) + mmtmpD0 = simde_mm_srai_epi32(mmtmpD0, output_shift); + // print_ints("re(shift)",&mmtmpD0); + mmtmpD1 = simde_mm_srai_epi32(mmtmpD1, output_shift); + // print_ints("im(shift)",&mmtmpD1); + mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); + mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); + // print_ints("c0",&mmtmpD2); + // print_ints("c1",&mmtmpD3); + rho128[0] = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); + // print_shorts("rx:",dl_ch128_2); + // print_shorts("ch:",dl_ch128); + // print_shorts("pack:",rho128); - for (rb=0; rb Date: Fri, 30 Jun 2023 17:33:33 +0100 Subject: [PATCH 08/41] Noise power estimation and MMSE computation for DL at UE side --- .../nr_dl_channel_estimation.c | 33 +++++- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 3 +- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 111 ++++++++++-------- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 5 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 13 +- 5 files changed, 106 insertions(+), 59 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 7e44335225..012d5c2121 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1087,7 +1087,8 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch, int8_t delta, - delay_t *delay) + delay_t *delay, + uint32_t *nvar) { c16_t *dl_ch0 = dl_ch; int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size; @@ -1095,6 +1096,9 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); + int nest_count = 0; + uint64_t noise_amp2 = 0; + for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) { if (pilot_cnt % 2 == 0) { c16_t ch = c16mulShift(*pil, rxF[re_offset], 15); @@ -1150,6 +1154,12 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t *dl_inv_delay_table = frame_parms->delay_table[inv_delay_idx]; for (int k = 0; k < 12 * nb_rb_pdsch; k++) { dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8); + noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k])); + nest_count++; + } + + if (nvar && nest_count > 0) { + *nvar = (uint32_t)(noise_amp2 / (nest_count * frame_parms->nb_antennas_rx)); } } @@ -1245,7 +1255,8 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, unsigned short nb_rb_pdsch, int8_t delta, unsigned short p, - delay_t *delay) + delay_t *delay, + uint32_t *nvar) { int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size; c16_t *dl_ch0 = dl_ch; @@ -1253,6 +1264,9 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); memset(dl_ls_est, 0, sizeof(dl_ls_est)); + int nest_count = 0; + uint64_t noise_amp2 = 0; + for (int pilot_cnt = 0; pilot_cnt < 4 * nb_rb_pdsch; pilot_cnt += 2) { c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15); #ifdef DEBUG_PDSCH @@ -1301,6 +1315,12 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms, c16_t *dl_inv_delay_table = frame_parms->delay_table[inv_delay_idx]; for (int k = 0; k < 12 * nb_rb_pdsch; k++) { dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8); + noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k])); + nest_count++; + } + + if (nvar && nest_count > 0) { + *nvar = (uint32_t)(noise_amp2 / (nest_count * frame_parms->nb_antennas_rx)); } } @@ -1402,7 +1422,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size], int rxdataFsize, - c16_t rxdataF[][rxdataFsize]) + c16_t rxdataF[][rxdataFsize], + uint32_t *nvar) { int gNB_id = proc->gNB_id; int Ns = proc->nr_slot_rx; @@ -1456,7 +1477,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, bwp_start_subcarrier, nb_rb_pdsch, delta, - &delay); + &delay, + nvar); } else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->chest_freq == 0) { NFAPI_NR_DMRS_TYPE2_linear_interp(&ue->frame_parms, @@ -1467,7 +1489,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, nb_rb_pdsch, delta, p, - &delay); + &delay, + nvar); } else if (config_type == NFAPI_NR_DMRS_TYPE1) { NFAPI_NR_DMRS_TYPE1_average_prb(&ue->frame_parms, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 157250a413..701967a235 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -93,7 +93,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, uint32_t pdsch_est_size, int32_t dl_ch_estimates[][pdsch_est_size], int rxdataFsize, - c16_t rxdataF[][rxdataFsize]); + c16_t rxdataF[][rxdataFsize], + uint32_t *nvar); int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, PHY_VARS_NR_UE *ue, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 6f9eb98594..78eaa220e2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -82,20 +82,21 @@ unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{ #define print_ints(s,x) printf("%s = %d %d %d %d\n",s,(x)[0],(x)[1],(x)[2],(x)[3]) #define print_shorts(s,x) printf("%s = [%d+j*%d, %d+j*%d, %d+j*%d, %d+j*%d]\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7]) -/* compute H_h_H matrix inversion up to 4x4 matrices */ -uint8_t nr_zero_forcing_rx(uint32_t rx_size_symbol, - unsigned char n_rx, - unsigned char n_tx,//number of layer - int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], - int32_t dl_ch_estimates_ext[][rx_size_symbol], - unsigned short nb_rb, - unsigned char mod_order, - int shift, - unsigned char symbol, - int length); +/* compute the MMSE up to 4x4 matrices */ +static void nr_dlsch_mmse(uint32_t rx_size_symbol, + unsigned char n_rx, + unsigned char n_tx, // number of layer + int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], + int32_t dl_ch_mag[][n_rx][rx_size_symbol], + int32_t dl_ch_magb[][n_rx][rx_size_symbol], + int32_t dl_ch_magr[][n_rx][rx_size_symbol], + int32_t dl_ch_estimates_ext[][rx_size_symbol], + unsigned short nb_rb, + unsigned char mod_order, + int shift, + unsigned char symbol, + int length, + uint32_t noise_var); /* Apply layer demapping */ static void nr_dlsch_layer_demapping(int16_t *llr_cw[2], @@ -259,7 +260,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT], int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT], - int G) + int G, + uint32_t nvar) { const int nl = dlsch[0].Nl; const int matrixSz = ue->frame_parms.nb_antennas_rx * nl; @@ -529,26 +531,27 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, symbol, nb_rb_pdsch, nb_re_pdsch); - if (nl >= 2) // Apply zero forcing for 2, 3, and 4 Tx layers - nr_zero_forcing_rx(rx_size_symbol, - n_rx, - nl, - rxdataF_comp, - dl_ch_mag, - dl_ch_magb, - dl_ch_magr, - dl_ch_estimates_ext, - nb_rb_pdsch, - dlsch_config->qamModOrder, - *log2_maxh, - symbol, - nb_re_pdsch); + if (nl >= 2) // Apply MMSE for 2, 3, and 4 Tx layers + nr_dlsch_mmse(rx_size_symbol, + n_rx, + nl, + rxdataF_comp, + dl_ch_mag, + dl_ch_magb, + dl_ch_magr, + dl_ch_estimates_ext, + nb_rb_pdsch, + dlsch_config->qamModOrder, + *log2_maxh, + symbol, + nb_re_pdsch, + nvar); } if (meas_enabled) { stop_meas(&meas); LOG_D(PHY, - "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine and zero forcing %5.2f \n", + "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine and MMSE %5.2f \n", frame, nr_slot_rx, slot, @@ -1650,23 +1653,23 @@ void nr_conjch0_mult_ch1(int *ch0, simde_m_empty(); } -/* Zero Forcing Rx function: up to 4 layers - * - * - * */ -uint8_t nr_zero_forcing_rx(uint32_t rx_size_symbol, - unsigned char n_rx, - unsigned char n_tx,//number of layer - int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], - int32_t dl_ch_mag[][n_rx][rx_size_symbol], - int32_t dl_ch_magb[][n_rx][rx_size_symbol], - int32_t dl_ch_magr[][n_rx][rx_size_symbol], - int32_t dl_ch_estimates_ext[][rx_size_symbol], - unsigned short nb_rb, - unsigned char mod_order, - int shift, - unsigned char symbol, - int length) +/* + * MMSE Rx function: up to 4 layers + */ +static void nr_dlsch_mmse(uint32_t rx_size_symbol, + unsigned char n_rx, + unsigned char n_tx, // number of layer + int32_t rxdataF_comp[][n_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], + int32_t dl_ch_mag[][n_rx][rx_size_symbol], + int32_t dl_ch_magb[][n_rx][rx_size_symbol], + int32_t dl_ch_magr[][n_rx][rx_size_symbol], + int32_t dl_ch_estimates_ext[][rx_size_symbol], + unsigned short nb_rb, + unsigned char mod_order, + int shift, + unsigned char symbol, + int length, + uint32_t noise_var) { int *ch0r, *ch0c; uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); @@ -1698,6 +1701,18 @@ uint8_t nr_zero_forcing_rx(uint32_t rx_size_symbol, } } + // Add noise_var such that: H^h * H + noise_var * I + if (noise_var != 0) { + simde__m128i nvar_128i = simde_mm_set1_epi32(noise_var >> 3); + for (int p = 0; p < n_tx; p++) { + simde__m128i *conjH_H_128i = (simde__m128i *)conjH_H_elements[0][p][p]; + for (int k = 0; k < 3 * nb_rb_0; k++) { + conjH_H_128i[0] = simde_mm_add_epi32(conjH_H_128i[0], nvar_128i); + conjH_H_128i++; + } + } + } + //Compute the inverse and determinant of the H^*H matrix //Allocate the inverse matrix c16_t *inv_H_h_H[n_tx][n_tx]; @@ -1795,8 +1810,6 @@ uint8_t nr_zero_forcing_rx(uint32_t rx_size_symbol, dl_ch_mag128r_0 += 1; } } - - return 0; } static void nr_dlsch_layer_demapping(int16_t *llr_cw[2], diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index deafd7a9ee..111e457c05 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -406,13 +406,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], uint32_t llr_offset[NR_SYMBOLS_PER_SLOT], - int32_t *log2_maxhrx_size_symbol, + int32_t *log2_maxh, int rx_size_symbol, int nbRx, int32_t rxdataF_comp[][nbRx][rx_size_symbol * NR_SYMBOLS_PER_SLOT], c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT], int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT], - int G); + int G, + uint32_t nvar); int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t slot); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index eb84c1e470..935563c35f 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -528,10 +528,13 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) int32_t rxdataF_comp[dlsch[0].Nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT]; memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); + uint32_t nvar = 0; + for (int m = dlschCfg->start_symbol; m < (dlschCfg->start_symbol + dlschCfg->number_symbols); m++) { if (dlschCfg->dlDmrsSymbPos & (1 << m)) { for (int nl = 0; nl < dlsch0->Nl; nl++) { //for MIMO Config: it shall loop over no_layers LOG_D(PHY,"PDSCH Channel estimation layer %d, slot %d, symbol %d\n", nl, nr_slot_rx, m); + uint32_t nvar_tmp = 0; nr_pdsch_channel_estimation(ue, proc, nl, @@ -547,7 +550,9 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, pdsch_est_size, pdsch_dl_ch_estimates, ue->frame_parms.samples_per_slot_wCP, - rxdataF); + rxdataF, + &nvar_tmp); + nvar += nvar_tmp; #if 0 ///LOG_M: the channel estimation int nr_frame_rx = proc->frame_rx; @@ -561,6 +566,9 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, } } } + + nvar /= (dlschCfg->number_symbols * dlsch0->Nl * ue->frame_parms.nb_antennas_rx); + nr_ue_measurement_procedures(2, ue, proc, &dlsch[0], pdsch_est_size, pdsch_dl_ch_estimates); if (ue->chest_time == 1) { // averaging time domain channel estimates @@ -618,7 +626,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, rxdataF_comp, ptrs_phase_per_slot, ptrs_re_per_slot, - G) + G, + nvar) < 0) return -1; From a5055cacf04a0e387c6cd284cb1ee6bf086d962d Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 1 May 2024 09:09:48 +0100 Subject: [PATCH 09/41] Remove commented code --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 35 +------------------ 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 78eaa220e2..67527b295f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -866,14 +866,9 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, // rho[aarx][nl*nl] = [cov(H_aarx_0,H_aarx_0) cov(H_aarx_0,H_aarx_1) // cov(H_aarx_1,H_aarx_0) cov(H_aarx_1,H_aarx_1)], aarx=0,...,nb_antennas_rx-1 - // int avg_rho_re[frame_parms->nb_antennas_rx][nl*nl]; - // int avg_rho_im[frame_parms->nb_antennas_rx][nl*nl]; - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { for (int l = 0; l < n_layers; l++) { for (int atx = 0; atx < n_layers; atx++) { - // avg_rho_re[aarx][l*n_layers+atx] = 0; - // avg_rho_im[aarx][l*n_layers+atx] = 0; rho128 = (simde__m128i *)&rho[aarx][l * n_layers + atx][symbol * nb_rb * 12]; dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[l * frame_parms->nb_antennas_rx + aarx]; dl_ch128_2 = (simde__m128i *)dl_ch_estimates_ext[atx * frame_parms->nb_antennas_rx + aarx]; @@ -895,22 +890,13 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = simde_mm_unpacklo_epi32(mmtmpD0, mmtmpD1); mmtmpD3 = simde_mm_unpackhi_epi32(mmtmpD0, mmtmpD1); - // print_ints("c0",&mmtmpD2); + // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rho128[0] = simde_mm_packs_epi32(mmtmpD2, mmtmpD3); // print_shorts("rx:",dl_ch128_2); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rho128); - /*avg_rho_re[aarx][l*n_layers+atx] +=(((int16_t*)&rho128[0])[0]+ - ((int16_t*)&rho128[0])[2] + - ((int16_t*)&rho128[0])[4] + - ((int16_t*)&rho128[0])[6])/16;*/ - /*avg_rho_im[aarx][l*n_layers+atx] +=(((int16_t*)&rho128[0])[1]+ - ((int16_t*)&rho128[0])[3] + - ((int16_t*)&rho128[0])[5] + - ((int16_t*)&rho128[0])[7])/16;*/ - // multiply by conjugated channel mmtmpD0 = simde_mm_madd_epi16(dl_ch128[1], dl_ch128_2[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) @@ -928,16 +914,6 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rho128+1); - // multiply by conjugated channel - /*avg_rho_re[aarx][l*n_layers+atx] +=(((int16_t*)&rho128[1])[0]+ - ((int16_t*)&rho128[1])[2] + - ((int16_t*)&rho128[1])[4] + - ((int16_t*)&rho128[1])[6])/16;*/ - /*avg_rho_im[aarx][l*n_layers+atx] +=(((int16_t*)&rho128[1])[1]+ - ((int16_t*)&rho128[1])[3] + - ((int16_t*)&rho128[1])[5] + - ((int16_t*)&rho128[1])[7])/16;*/ - mmtmpD0 = simde_mm_madd_epi16(dl_ch128[2], dl_ch128_2[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = simde_mm_shufflelo_epi16(dl_ch128[2], SIMDE_MM_SHUFFLE(2, 3, 0, 1)); @@ -955,15 +931,6 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, // print_shorts("ch:",dl_ch128+2); // print_shorts("pack:",rho128+2); - /*avg_rho_re[aarx][l*n_layers+atx] +=(((int16_t*)&rho128[2])[0]+ - ((int16_t*)&rho128[2])[2] + - ((int16_t*)&rho128[2])[4] + - ((int16_t*)&rho128[2])[6])/16;*/ - /*avg_rho_im[aarx][l*n_layers+atx] +=(((int16_t*)&rho128[2])[1]+ - ((int16_t*)&rho128[2])[3] + - ((int16_t*)&rho128[2])[5] + - ((int16_t*)&rho128[2])[7])/16;*/ - dl_ch128+=3; dl_ch128_2+=3; rho128+=3; From bb66056b75e8ddb220fe7dda1aee2ab1b4f6f2da Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 25 Apr 2024 14:33:46 +0200 Subject: [PATCH 10/41] fix nr-ru.c external declarations in .c file The external declarations were incorrect, leading to mismatching prototypes of config_ru and config_rru (true bug in OAI lte!). --- executables/lte-ru.c | 8 ----- executables/lte-softmodem.h | 2 -- executables/nr-ru.c | 59 +++++++------------------------ executables/nr-softmodem-common.h | 2 +- executables/ru_control.c | 12 +++---- executables/softmodem-common.h | 4 +++ openair2/GNB_APP/gnb_config.h | 1 - radio/COMMON/common_lib.h | 5 ++- 8 files changed, 25 insertions(+), 68 deletions(-) diff --git a/executables/lte-ru.c b/executables/lte-ru.c index 2cee48ffbc..54747a9578 100644 --- a/executables/lte-ru.c +++ b/executables/lte-ru.c @@ -93,12 +93,6 @@ void stop_RU(RU_t **rup,int nb_ru); static void do_ru_synch(RU_t *ru); -void configure_ru(int idx, - void *arg); - -void configure_rru(int idx, - void *arg); - void reset_proc(RU_t *ru); int connect_rau(RU_t *ru); @@ -2183,8 +2177,6 @@ int stop_rf(RU_t *ru) { return 0; } - -extern void configure_ru(int idx, void *arg); extern void fep_full(RU_t *ru, int subframe); extern void feptx_ofdm(RU_t *ru, int frame_tx, int tti_tx); extern void feptx_ofdm_2thread(RU_t *ru, int frame_tx, int tti_tx); diff --git a/executables/lte-softmodem.h b/executables/lte-softmodem.h index 058018001b..643c8c6572 100644 --- a/executables/lte-softmodem.h +++ b/executables/lte-softmodem.h @@ -189,8 +189,6 @@ void kill_feptx_thread(RU_t *ru); void init_fep_thread(RU_t *ru, pthread_attr_t *attr_fep); void init_feptx_thread(RU_t *ru, pthread_attr_t *attr_feptx); void fep_full(RU_t *ru, int subframe); -void configure_ru(int, void *arg); -void configure_rru(int, void *arg); void ru_fep_full_2thread(RU_t *ru,int subframe); void feptx_ofdm(RU_t*ru, int frame_tx, int tti_tx); void feptx_prec(struct RU_t_s *ru, int frame_tx, int tti_tx); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 41adc59bf6..9777c956f6 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -53,14 +53,6 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include - -#ifdef SMBV -#include "PHY/TOOLS/smbv.h" -unsigned short config_frames[4] = {2,9,11,13}; -#endif - - - /* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */ static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; @@ -81,35 +73,14 @@ static int DEFRUTPCORES[] = {-1,-1,-1,-1}; #include "T.h" #include "nfapi_interface.h" #include - -extern int oai_exit; +#include "executables/nr-softmodem-common.h" uint16_t sl_ahead; - -extern struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); -extern struct timespec timespec_add(struct timespec lhs, struct timespec rhs); -extern void nr_phy_free_RU(RU_t *); -extern void nr_phy_config_request(NR_PHY_Config_t *gNB); -#include "executables/thread-common.h" -//extern PARALLEL_CONF_t get_thread_parallel_conf(void); -//extern WORKER_CONF_t get_thread_worker_conf(void); - -void stop_RU(int nb_ru); - -void configure_ru(int idx, void *arg); -void configure_rru(int idx, void *arg); -int attach_rru(RU_t *ru); -int connect_rau(RU_t *ru); static void NRRCconfig_RU(configmodule_interface_t *cfg); -extern int emulate_rf; -extern int numerology; - /*************************************************************/ /* Functions to attach and configure RRU */ -extern void wait_gNBs(void); - int attach_rru(RU_t *ru) { ssize_t msg_len,len; RRU_CONFIG_msg_t rru_config_msg; @@ -146,8 +117,7 @@ int attach_rru(RU_t *ru) { } } - configure_ru(ru->idx, - (RRU_capabilities_t *)&rru_config_msg.msg[0]); + configure_ru(ru, (RRU_capabilities_t *)&rru_config_msg.msg[0]); rru_config_msg.type = RRU_config; rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx, @@ -263,8 +233,7 @@ int connect_rau(RU_t *ru) { ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0], ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); - configure_rru(ru->idx, - (void *)&rru_config_msg.msg[0]); + configure_rru(ru, (void *)&rru_config_msg.msg[0]); configuration_received = 1; } } @@ -1486,10 +1455,8 @@ void init_RU_proc(RU_t *ru) { if(emulate_rf) threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - if (opp_enabled == 1) - threadCreate( &ru->ru_stats_thread, ru_stats_thread, (void *)ru,"ru_stats", -1, OAI_PRIORITY_RT ); - if (get_thread_worker_conf() == WORKER_ENABLE) { - } + if (opp_enabled == 1) + threadCreate(&ru->ru_stats_thread, ru_stats_thread, (void *)ru, "ru_stats", -1, OAI_PRIORITY_RT); LOG_I(PHY, "Initialized RU proc %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]); } @@ -1585,19 +1552,19 @@ const char rru_format_options[4][20] = {"OAI_IF5_only", "OAI_IF4p5_only", "OAI_I const char rru_formats[3][20] = {"OAI_IF5", "MBP_IF5", "OAI_IF4p5"}; const char ru_if_formats[4][20] = {"LOCAL_RF", "REMOTE_OAI_IF5", "REMOTE_MBP_IF5", "REMOTE_OAI_IF4p5"}; -void configure_ru(int idx, - void *arg) { - RU_t *ru = RC.ru[idx]; +void configure_ru(void *ruu, void *arg) +{ + RU_t *ru = (RU_t *)ruu; RRU_config_t *config = (RRU_config_t *)arg; RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg; nfapi_nr_config_request_scf_t *cfg = &ru->config; int ret; - LOG_I(PHY, "Received capabilities from RRU %d\n",idx); + LOG_I(PHY, "Received capabilities from RRU %d\n", ru->idx); if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]); ret = check_capabilities(ru,capabilities); - AssertFatal(ret == 0, "Cannot configure RRU %d, check_capabilities returned %d\n", idx, ret); + AssertFatal(ret == 0, "Cannot configure RRU %d, check_capabilities returned %d\n", ru->idx, ret); // take antenna capabilities of RRU ru->nb_tx = capabilities->nb_tx[0]; ru->nb_rx = capabilities->nb_rx[0]; @@ -1625,10 +1592,10 @@ void configure_ru(int idx, nr_phy_init_RU(ru); } -void configure_rru(int idx, - void *arg) { +void configure_rru(void *ruu, void *arg) +{ RRU_config_t *config = (RRU_config_t *)arg; - RU_t *ru = RC.ru[idx]; + RU_t *ru = (RU_t *)ruu; nfapi_nr_config_request_scf_t *cfg = &ru->config; ru->nr_frame_parms->nr_band = config->band_list[0]; ru->nr_frame_parms->dl_CarrierFreq = config->tx_freq[0]; diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 46763d6995..5ff6a0b323 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -151,5 +151,5 @@ extern double cpuf; extern int emulate_rf; extern int numerology; extern int usrp_tx_thread; - +void wait_gNBs(void); #endif diff --git a/executables/ru_control.c b/executables/ru_control.c index b7d71be89f..2136e5ff53 100644 --- a/executables/ru_control.c +++ b/executables/ru_control.c @@ -62,13 +62,11 @@ #include "SCHED/sched_eNB.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/INIT/phy_init.h" +#include "executables/softmodem-common.h" #include "common/utils/LOG/log.h" - int attach_rru(RU_t *ru); -void configure_ru(RU_t *ru, void *arg); -void configure_rru(RU_t *ru, void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); void* ru_thread_control( void* param ); @@ -372,9 +370,9 @@ int check_capabilities(RU_t *ru, return(-1); } -void configure_ru(RU_t *ru, - void *arg) +void configure_ru(void *ruu, void *arg) { + RU_t *ru = (RU_t *)ruu; RRU_config_t *config = (RRU_config_t *)arg; RRU_capabilities_t *capabilities = (RRU_capabilities_t*)arg; int ret; @@ -423,9 +421,9 @@ void configure_ru(RU_t *ru, phy_init_RU(ru); } -void configure_rru(RU_t *ru, - void *arg) +void configure_rru(void *ruu, void *arg) { + RU_t *ru = (RU_t *)ruu; RRU_config_t *config = (RRU_config_t *)arg; ru->frame_parms->eutra_band = config->band_list[0]; diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 43c8b4625e..d49c56d11b 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -374,6 +374,10 @@ extern int oai_exit; void rx_func(void *param); void ru_tx_func(void *param); +void configure_ru(void *, void *arg); +void configure_rru(void *, void *arg); +struct timespec timespec_add(struct timespec lhs, struct timespec rhs); +struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); extern uint8_t nfapi_mode; extern int16_t vnf_pnf_sfnslot_delta; #ifdef __cplusplus diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index 235a7582d5..e406a1ad7f 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -93,7 +93,6 @@ typedef struct ru_config_s { */ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type); -extern void NRRCconfig_RU(void); extern void RCconfig_nr_prs(void); extern void RCconfig_NR_L1(void); extern void RCconfig_nr_macrlc(configmodule_interface_t *cfg); diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index ee7a9543f6..074007dd10 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -567,12 +567,11 @@ struct openair0_device_t { * \param idx RU index * \param arg pointer to capabilities or configuration */ - void (*configure_rru)(int idx, void *arg); + void (*configure_rru)(void *, void *arg); -/*! \brief Pointer to generic RRU private information + /*! \brief Pointer to generic RRU private information */ - void *thirdparty_priv; /*! \brief Callback for Third-party RRU Initialization routine From c02908453a1c69592e550aac26b40cc97a164c96 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 26 Apr 2024 10:22:23 +0200 Subject: [PATCH 11/41] fix order error in ru.common.rxdataF filling lock, use consistently #define for buffer size --- executables/nr-ru.c | 11 +++++------ openair1/PHY/INIT/nr_init_ru.c | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 9777c956f6..71c9c5fd73 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1258,13 +1258,12 @@ void *ru_thread( void *param ) { // We should make a VNF main loop with proper tasks calls in case of VNF slot_start = timespec_add(slot_start,slot_duration); struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); - + clock_gettime(CLOCK_MONOTONIC, &curr_time); struct timespec sleep_time; - if((slot_start.tv_sec > curr_time.tv_sec) || (slot_start.tv_sec == curr_time.tv_sec && slot_start.tv_nsec > curr_time.tv_nsec)){ + if((slot_start.tv_sec > curr_time.tv_sec) || + (slot_start.tv_sec == curr_time.tv_sec && slot_start.tv_nsec > curr_time.tv_nsec)){ sleep_time = timespec_sub(slot_start,curr_time); - usleep(sleep_time.tv_nsec * 1e-3); } } @@ -1346,10 +1345,10 @@ void *ru_thread( void *param ) { if (!res) break; } - ru->feprx(ru,proc->tti_rx); // set the tti that was generated to busy - LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH); rx_tti_busy[proc->tti_rx % RU_RX_SLOT_DEPTH] = true; + ru->feprx(ru,proc->tti_rx); + LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH); clock_gettime(CLOCK_MONOTONIC,&ru->rt_ru_profiling.return_RU_feprx[rt_prof_idx]); //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 0a1a0322c5..a9f630198d 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -98,7 +98,7 @@ int nr_phy_init_RU(RU_t *ru) { ru->common.rxdataF = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) ); for (i=0; inb_rx; i++) { // allocate 4 slots of I/Q signal data (frequency) - ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(4*fp->symbols_per_slot*fp->ofdm_symbol_size) ); + ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(**ru->common.rxdataF)*(RU_RX_SLOT_DEPTH*fp->symbols_per_slot*fp->ofdm_symbol_size) ); LOG_I(PHY,"rxdataF[%d] %p for RU %d\n",i,ru->common.rxdataF[i],ru->idx); } From 00d78f048ab079f890e15f05f3e9a97d8d1f69fb Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 26 Apr 2024 18:04:43 +0200 Subject: [PATCH 12/41] remove a unused global storage of slot number This has no meaning at a global level, we run several slots: one tx, several rx at same time. Some minor cleaning of C style --- executables/nr-gnb.c | 11 ++++------- executables/nr-ru.c | 6 ++++-- executables/softmodem-common.h | 1 - openair1/SCHED_NR/fapi_nr_l1.c | 3 +-- openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c | 3 ++- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 2 -- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 -- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 4 +--- 9 files changed, 13 insertions(+), 21 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 9df218fe1b..38315bd578 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -106,11 +106,10 @@ time_stats_t softmodem_stats_rx_sf; // total rx time //#define TICK_TO_US(ts) (ts.diff) #define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials) #define L1STATSSTRLEN 16384 +static void rx_func(processingData_L1_t *param); -static void tx_func(void *param) +static void tx_func(processingData_L1tx_t *info) { - processingData_L1tx_t *info = (processingData_L1tx_t *) param; - int frame_tx = info->frame; int slot_tx = info->slot; int frame_rx = info->frame_rx; @@ -176,7 +175,6 @@ static void tx_func(void *param) deref_sched_response(info->sched_response_id); } - void *L1_rx_thread(void *arg) { PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg; @@ -206,9 +204,8 @@ void *L1_tx_thread(void *arg) { return NULL; } -void rx_func(void *param) +static void rx_func(processingData_L1_t *info) { - processingData_L1_t *info = (processingData_L1_t *) param; PHY_VARS_gNB *gNB = info->gNB; int frame_rx = info->frame_rx; int slot_rx = info->slot_rx; @@ -387,7 +384,7 @@ void init_gNB_Tpool(int inst) { // create the TX thread responsible for TX processing start event (L1_tx_out msg queue), then launch tx_func() threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread", gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX); - notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func); + notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, NULL); processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); memset(msgDataTx, 0, sizeof(processingData_L1tx_t)); init_DLSCH_struct(gNB, msgDataTx); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 71c9c5fd73..dbb0c30a95 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1089,9 +1089,11 @@ void ru_tx_func(void *param) { if(!emulate_rf) { // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,slot_tx,info->timestamp_tx); + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) + ru->fh_south_out(ru, frame_tx, slot_tx, info->timestamp_tx); - if (ru->fh_north_out) ru->fh_north_out(ru); + if (ru->fh_north_out) + ru->fh_north_out(ru); } else { if(frame_tx == print_frame) { for (int i=0; inb_tx; i++) { diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index d49c56d11b..40a94e1ec1 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -372,7 +372,6 @@ extern uint16_t sl_ahead; extern uint16_t sf_ahead; extern int oai_exit; -void rx_func(void *param); void ru_tx_func(void *param); void configure_ru(void *, void *arg); void configure_rru(void *, void *arg); diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 504c5fabe0..f990d6c157 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -159,8 +159,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) if (NFAPI_MODE == NFAPI_MONOLITHIC){ if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) { - processingData_L1tx_t *msgTx=NULL; - msgTx = gNB->msgDataTx; + processingData_L1tx_t *msgTx = gNB->msgDataTx; msgTx->num_pdsch_slot = 0; msgTx->num_dl_pdcch = 0; msgTx->num_ul_pdcch = number_ul_dci_pdu; diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c index f6a152627c..56633f53e0 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -54,7 +54,8 @@ bool read_mac_sm(void* data) mac_ue_stats_impl_t* rd = &mac->msg.ue_stats[i]; rd->frame = RC.nrmac[mod_id]->frame; - rd->slot = RC.nrmac[mod_id]->slot; + rd->slot = 0; // previously had slot info, but the gNB runs multiple slots + // in parallel, so this has no real meaning rd->dl_aggr_tbs = UE->mac_stats.dl.total_bytes; rd->ul_aggr_tbs = UE->mac_stats.ul.total_bytes; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 2c3ca94393..34a372247c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -210,8 +210,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ } gNB->frame = frame; - gNB->slot = slot; - start_meas(&gNB->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 9a1be26024..06429b61d3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2997,7 +2997,7 @@ int nr_mac_enable_ue_rrc_processing_timer(gNB_MAC_INST *mac, NR_UE_info_t *UE, b // frames, after RRC processing timer. UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024; - LOG_D(NR_MAC, "%4d.%2d UE %04x: Activate RRC processing timer (%d ms)\n", mac->frame, mac->slot, UE->rnti, delay); + LOG_D(NR_MAC, "UE %04x: Activate RRC processing timer (%d ms)\n", UE->rnti, delay); return 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 02b5f54a56..64aff46937 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -836,9 +836,7 @@ typedef struct gNB_MAC_INST_s { nr_mac_rrc_ul_if_t mac_rrc; f1_config_t f1_config; - int16_t frame; - int16_t slot; pthread_mutex_t sched_lock; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 6f3cd0a744..a2d508531c 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -388,11 +388,9 @@ static void match_crc_rx_pdu(nfapi_nr_rx_data_indication_t *rx_ind, nfapi_nr_crc static void run_scheduler(module_id_t module_id, int CC_id, int frame, int slot) { NR_IF_Module_t *ifi = nr_if_inst[module_id]; - // gNB_MAC_INST *mac = RC.nrmac[module_id]; - NR_Sched_Rsp_t *sched_info; LOG_D(NR_MAC, "Calling scheduler for %d.%d\n", frame, slot); - sched_info = allocate_sched_response(); + NR_Sched_Rsp_t *sched_info = allocate_sched_response(); // clear UL DCI prior to handling ULSCH sched_info->UL_dci_req.numPdus = 0; From 590afc811fc1eebfc9cfbb4f4dd9ed76ebda74e0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 15:09:40 +0100 Subject: [PATCH 13/41] Correct F1 criticality --- openair2/F1AP/f1ap_cu_ue_context_management.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 6fe48ed611..923278ab64 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -285,7 +285,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu for (int i=0; i<1; i++) { asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list,F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies); candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91 - candidate_spCell_item_ies->criticality = F1AP_Criticality_reject; + candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore; candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item; /* 7.1 Candidate_SpCell_Item */ F1AP_Candidate_SpCell_Item_t *candidate_spCell_item= @@ -375,7 +375,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu for (int i=0; isrbs_to_be_setup_length; i++) { asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetup_List.list, F1AP_SRBs_ToBeSetup_ItemIEs_t, srbs_toBeSetup_item_ies); srbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; // 73 - srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore; + srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject; srbs_toBeSetup_item_ies->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item; /* 11.1 SRBs_ToBeSetup_Item */ F1AP_SRBs_ToBeSetup_Item_t *srbs_toBeSetup_item=&srbs_toBeSetup_item_ies->value.choice.SRBs_ToBeSetup_Item; @@ -539,7 +539,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu if(f1ap_ue_context_setup_req->rrc_container_length > 0) { asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie14); ie14->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie14->criticality = F1AP_Criticality_reject; + ie14->criticality = F1AP_Criticality_ignore; ie14->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; OCTET_STRING_fromBuf(&ie14->value.choice.RRCContainer, (const char *)f1ap_ue_context_setup_req->rrc_container, f1ap_ue_context_setup_req->rrc_container_length); From c8539aeef51fa99eaeada5ebaeb62de33568b6bc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 15:09:56 +0100 Subject: [PATCH 14/41] Remove misleading comment --- openair2/RRC/NR/rrc_gNB_du.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index b83a3f268e..5fc9adf3bc 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -111,7 +111,6 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) } } - // if there is no system info or no SIB1 and we run in SA mode, we cannot handle it const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info; NR_BCCH_BCH_Message_t *mib = NULL; NR_SIB1_t *sib1 = NULL; From 00f85d54c58421c07f580bc300d3d8bf0e859fd3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 15:51:53 +0100 Subject: [PATCH 15/41] Remove dead code --- openair2/RRC/NR/rrc_gNB_du.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 5fc9adf3bc..f7a3315e03 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -178,28 +178,6 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (rrc->node_name != NULL) resp.gNB_CU_name = strdup(rrc->node_name); rrc->mac_rrc.f1_setup_response(assoc_id, &resp); - - /* - MessageDef *msg_p2 = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE); - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).gNB_CU_name = rrc->node_name; - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mcc = rrc->configuration.mcc[0]; - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mnc = rrc->configuration.mnc[0]; - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0]; - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].nr_cellid = rrc->nr_cellid; - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].nrpci = req->cell[0].info.nr_pci; - int num_SI = 0; - - if (rrc->carrier.SIB23) { - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].SI_container[2] = rrc->carrier.SIB23; - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].SI_container_length[2] = rrc->carrier.sizeof_SIB23; - num_SI++; - } - - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].num_SI = num_SI; - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).num_cells_to_activate = 1; - // send - itti_send_msg_to_task(TASK_CU_F1, 0, msg_p2); - */ } static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) From 9518e00923df50de2128d699f97aa29b905cdc19 Mon Sep 17 00:00:00 2001 From: Giulio Carota Date: Fri, 29 Mar 2024 12:05:16 +0100 Subject: [PATCH 16/41] fix(f1ap): Do not send optional hardcoded fields in UE context setup request --- openair2/F1AP/f1ap_cu_ue_context_management.c | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 923278ab64..8451fb7062 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -273,27 +273,27 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig_length); } } - - /* mandatory */ - /* c7. Candidate_SpCell_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_List; //90 - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List; + /* optional */ + if (0) { + /* c7. Candidate_SpCell_List */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie7); + ie7->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_List; // 90 + ie7->criticality = F1AP_Criticality_ignore; + ie7->value.present = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List; - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list,F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies); - candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91 - candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore; - candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item; - /* 7.1 Candidate_SpCell_Item */ - F1AP_Candidate_SpCell_Item_t *candidate_spCell_item= - &candidate_spCell_item_ies->value.choice.Candidate_SpCell_Item; - /* - candidate_SpCell_ID */ - //FixMe: first cell ??? - addnRCGI(candidate_spCell_item->candidate_SpCell_ID,f1ap_ue_context_setup_req); - /* TODO add correct mcc/mnc */ + for (int i = 0; i < 1; i++) { + asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list, F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies); + candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91 + candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore; + candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item; + /* 7.1 Candidate_SpCell_Item */ + F1AP_Candidate_SpCell_Item_t *candidate_spCell_item = &candidate_spCell_item_ies->value.choice.Candidate_SpCell_Item; + /* - candidate_SpCell_ID */ + // FixMe: first cell ??? + addnRCGI(candidate_spCell_item->candidate_SpCell_ID, f1ap_ue_context_setup_req); + /* TODO add correct mcc/mnc */ + } } /* optional */ @@ -335,32 +335,33 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu strlen("asdsa1d32sa1d31asd31as")); } - /* mandatory */ - /* c10. SCell_ToBeSetup_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List; + /* optional */ + if (0) { + /* c10. SCell_ToBeSetup_List */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie10); + ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_List; + ie10->criticality = F1AP_Criticality_ignore; + ie10->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List; - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie10->value.choice.SCell_ToBeSetup_List.list, F1AP_SCell_ToBeSetup_ItemIEs_t, scell_toBeSetup_item_ies); - scell_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_Item; //53 - scell_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeSetup_item_ies->value.present = F1AP_SCell_ToBeSetup_ItemIEs__value_PR_SCell_ToBeSetup_Item; - /* 10.1 SCell_ToBeSetup_Item */ - F1AP_SCell_ToBeSetup_Item_t *scell_toBeSetup_item=&scell_toBeSetup_item_ies->value.choice.SCell_ToBeSetup_Item; - /* 10.1.1 sCell_ID */ - addnRCGI(scell_toBeSetup_item->sCell_ID, f1ap_ue_context_setup_req); - /* TODO correct MCC/MNC */ - /* 10.1.2 sCellIndex */ - scell_toBeSetup_item->sCellIndex = 3; // issue here + for (int i = 0; i < 1; i++) { + asn1cSequenceAdd(ie10->value.choice.SCell_ToBeSetup_List.list, F1AP_SCell_ToBeSetup_ItemIEs_t, scell_toBeSetup_item_ies); + scell_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_Item; // 53 + scell_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore; + scell_toBeSetup_item_ies->value.present = F1AP_SCell_ToBeSetup_ItemIEs__value_PR_SCell_ToBeSetup_Item; + /* 10.1 SCell_ToBeSetup_Item */ + F1AP_SCell_ToBeSetup_Item_t *scell_toBeSetup_item = &scell_toBeSetup_item_ies->value.choice.SCell_ToBeSetup_Item; + /* 10.1.1 sCell_ID */ + addnRCGI(scell_toBeSetup_item->sCell_ID, f1ap_ue_context_setup_req); + /* TODO correct MCC/MNC */ + /* 10.1.2 sCellIndex */ + scell_toBeSetup_item->sCellIndex = 3; // issue here - /* OPTIONAL */ - /* 10.1.3 sCellULConfigured*/ - if (0) { - asn1cCallocOne(scell_toBeSetup_item->sCellULConfigured, - F1AP_CellULConfigured_ul_and_sul); // enum + /* OPTIONAL */ + /* 10.1.3 sCellULConfigured*/ + if (0) { + asn1cCallocOne(scell_toBeSetup_item->sCellULConfigured, + F1AP_CellULConfigured_ul_and_sul); // enum + } } } From 1bd6018f917418fef250f1bb00b84cf989d46598 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 16:06:52 +0100 Subject: [PATCH 17/41] Add extract_sys_info(): refactor DU cell sys_info handling in own function --- openair2/RRC/NR/rrc_gNB_du.c | 54 +++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index f7a3315e03..0e0bdd6239 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -49,6 +49,39 @@ static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell && conf->mnc[0] == info->plmn.mnc; } +static bool extract_sys_info(const f1ap_gnb_du_system_info_t *sys_info, NR_BCCH_BCH_Message_t **mib, NR_SIB1_t **sib1) +{ + DevAssert(sys_info != NULL); + DevAssert(mib != NULL); + DevAssert(sib1 != NULL); + + asn_dec_rval_t dec_rval = + uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)mib, sys_info->mib, sys_info->mib_length); + if (dec_rval.code != RC_OK || (*mib)->message.present != NR_BCCH_BCH_MessageType_PR_mib + || (*mib)->message.choice.messageClassExtension == NULL) { + LOG_E(RRC, "Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits) of DU\n", dec_rval.consumed); + ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib); + return false; + } + + if (sys_info->sib1) { + dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_SIB1, (void **)sib1, sys_info->sib1, sys_info->sib1_length); + if (dec_rval.code != RC_OK) { + ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib); + ASN_STRUCT_FREE(asn_DEF_NR_SIB1, *sib1); + LOG_E(RRC, "Failed to decode NR_SIB1 (%zu bits), rejecting DU\n", dec_rval.consumed); + return false; + } + } + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_BCCH_BCH_Message, *mib); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_SIB1, *sib1); + + return true; +} + void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) { AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n"); @@ -116,29 +149,12 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) NR_SIB1_t *sib1 = NULL; if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) { - asn_dec_rval_t dec_rval = - uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)&mib, sys_info->mib, sys_info->mib_length); - if (dec_rval.code != RC_OK || mib->message.present != NR_BCCH_BCH_MessageType_PR_mib - || mib->message.choice.messageClassExtension == NULL) { - LOG_E(RRC, "Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits) of DU, rejecting DU\n", dec_rval.consumed); + if (!extract_sys_info(sys_info, &mib, &sib1)) { + LOG_W(RRC, "rejecting DU ID %ld\n", req->gNB_DU_id); f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error}; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, mib); return; } - - if (sys_info->sib1) { - dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_SIB1, (void **)&sib1, sys_info->sib1, sys_info->sib1_length); - if (dec_rval.code != RC_OK) { - LOG_E(RRC, "Failed to decode NR_SIB1 (%zu bits) of DU, rejecting DU\n", dec_rval.consumed); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error}; - rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); - ASN_STRUCT_FREE(asn_DEF_NR_SIB1, sib1); - return; - } - if (LOG_DEBUGFLAG(DEBUG_ASN1)) - xer_fprint(stdout, &asn_DEF_NR_SIB1, sib1); - } } LOG_I(RRC, "Accepting DU %ld (%s), sending F1 Setup Response\n", req->gNB_DU_id, req->gNB_DU_name); LOG_I(RRC, "DU uses RRC version %u.%u.%u\n", req->rrc_ver[0], req->rrc_ver[1], req->rrc_ver[2]); From 1c747e8223a6ae3fe3d9126da48352575d714a9b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 16:51:18 +0100 Subject: [PATCH 18/41] RRC stats: show DU info --- openair2/RRC/NR/rrc_gNB_du.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 0e0bdd6239..bbf9942ddc 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -274,5 +274,18 @@ void dump_du_info(const gNB_RRC_INST *rrc, FILE *f) } const f1ap_served_cell_info_t *info = &sr->cell[0].info; fprintf(f, ": nrCellID %ld, PCI %d\n", info->nr_cellid, info->nr_pci); + + if (info->mode == F1AP_MODE_TDD) { + const f1ap_nr_frequency_info_t *fi = &info->tdd.freqinfo; + const f1ap_transmission_bandwidth_t *tb = &info->tdd.tbw; + fprintf(f, " TDD: band %d ARFCN %d SCS %d (kHz) PRB %d\n", fi->band, fi->arfcn, 15 * (1 << tb->scs), tb->nrb); + } else { + const f1ap_nr_frequency_info_t *dfi = &info->fdd.dl_freqinfo; + const f1ap_transmission_bandwidth_t *dtb = &info->fdd.dl_tbw; + fprintf(f, " FDD: DL band %d ARFCN %d SCS %d (kHz) PRB %d\n", dfi->band, dfi->arfcn, 15 * (1 << dtb->scs), dtb->nrb); + const f1ap_nr_frequency_info_t *ufi = &info->fdd.ul_freqinfo; + const f1ap_transmission_bandwidth_t *utb = &info->fdd.ul_tbw; + fprintf(f, " UL band %d ARFCN %d SCS %d (kHz) PRB %d\n", ufi->band, ufi->arfcn, 15 * (1 << utb->scs), utb->nrb); + } } } From f247373474898a38fcb57f588ebcf334b181d936 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 17:59:24 +0100 Subject: [PATCH 19/41] Refactor TDD/FDD config reading into functions --- openair2/GNB_APP/gnb_config.c | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 7e2d9c5b07..dfbe4c3672 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1104,6 +1104,35 @@ static int read_du_cell_info(configmodule_interface_t *cfg, return 1; } +static f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc) +{ + const NR_FrequencyInfoDL_t *dl = scc->downlinkConfigCommon->frequencyInfoDL; + f1ap_tdd_info_t tdd = { + .freqinfo.arfcn = dl->absoluteFrequencyPointA, + .freqinfo.band = *dl->frequencyBandList.list.array[0], + .tbw.scs = dl->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + .tbw.nrb = dl->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + }; + return tdd; +} + +static f1ap_fdd_info_t read_fdd_config(const NR_ServingCellConfigCommon_t *scc) +{ + const NR_FrequencyInfoDL_t *dl = scc->downlinkConfigCommon->frequencyInfoDL; + const NR_FrequencyInfoUL_t *ul = scc->uplinkConfigCommon->frequencyInfoUL; + f1ap_fdd_info_t fdd = { + .dl_freqinfo.arfcn = dl->absoluteFrequencyPointA, + .ul_freqinfo.arfcn = *ul->absoluteFrequencyPointA, + .dl_tbw.scs = dl->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + .ul_tbw.scs = ul->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + .dl_tbw.nrb = dl->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + .ul_tbw.nrb = ul->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + .dl_freqinfo.band = *dl->frequencyBandList.list.array[0], + .ul_freqinfo.band = *ul->frequencyBandList->list.array[0], + }; + return fdd; +} + static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, const char *name, const f1ap_served_cell_info_t *info, @@ -1129,27 +1158,14 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, req->cell[0].info.nr_cellid); req->cell[0].info.nr_pci = *scc->physCellId; - struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; if (scc->tdd_UL_DL_ConfigurationCommon) { LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for TDD\n", 0); req->cell[0].info.mode = F1AP_MODE_TDD; - f1ap_tdd_info_t *tdd = &req->cell[0].info.tdd; - tdd->freqinfo.arfcn = frequencyInfoDL->absoluteFrequencyPointA; - tdd->tbw.scs = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - tdd->tbw.nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - tdd->freqinfo.band = *frequencyInfoDL->frequencyBandList.list.array[0]; + req->cell[0].info.tdd = read_tdd_config(scc); } else { LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for FDD\n", 0); req->cell[0].info.mode = F1AP_MODE_FDD; - f1ap_fdd_info_t *fdd = &req->cell[0].info.fdd; - fdd->dl_freqinfo.arfcn = frequencyInfoDL->absoluteFrequencyPointA; - fdd->ul_freqinfo.arfcn = *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA; - fdd->dl_tbw.scs = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - fdd->ul_tbw.scs = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - fdd->dl_tbw.nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - fdd->ul_tbw.nrb = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - fdd->dl_freqinfo.band = *frequencyInfoDL->frequencyBandList.list.array[0]; - fdd->ul_freqinfo.band = *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]; + req->cell[0].info.fdd = read_fdd_config(scc); } req->cell[0].info.measurement_timing_information = "0"; From aa18edb8ac1b895731453309ad8c5e4772ca6b87 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 14:55:17 +0100 Subject: [PATCH 20/41] gNB-DU config update msg def and handle in CU --- openair2/COMMON/f1ap_messages_def.h | 3 + openair2/COMMON/f1ap_messages_types.h | 55 ++++++++++++++++ openair2/RRC/NR/mac_rrc_dl.h | 2 + openair2/RRC/NR/mac_rrc_dl_direct.c | 7 ++ openair2/RRC/NR/mac_rrc_dl_f1ap.c | 6 ++ openair2/RRC/NR/nr_rrc_defs.h | 1 + openair2/RRC/NR/rrc_gNB.c | 5 ++ openair2/RRC/NR/rrc_gNB_du.c | 93 +++++++++++++++++++++++++++ openair2/RRC/NR/rrc_gNB_du.h | 2 + 9 files changed, 174 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index a5e10b01f9..9177ed9001 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -27,11 +27,14 @@ MESSAGE_DEF(F1AP_DU_REGISTER_REQ, MESSAGE_PRIORITY_MED, f1ap_du_register_req_t, MESSAGE_DEF(F1AP_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_setup_req_t , f1ap_setup_req) MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_acknowledge_t , f1ap_gnb_cu_configuration_update_acknowledge) MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_failure_t , f1ap_gnb_cu_configuration_update_failure) +MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE, MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_t, f1ap_gnb_du_configuration_update) /* F1AP -> eNB_DU or eNB_CU_RRC -> F1AP application layer messages */ MESSAGE_DEF(F1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, f1ap_setup_resp_t , f1ap_setup_resp) MESSAGE_DEF(F1AP_SETUP_FAILURE , MESSAGE_PRIORITY_MED, f1ap_setup_failure_t , f1ap_setup_failure) MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_t , f1ap_gnb_cu_configuration_update) +MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_acknowledge_t, f1ap_gnb_du_configuration_update_acknowledge) +MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_failure_t, f1ap_gnb_du_configuration_update_failure) /* F1AP -> RRC to inform about lost connection */ MESSAGE_DEF(F1AP_LOST_CONNECTION, MESSAGE_PRIORITY_MED, f1ap_lost_connection_t, f1ap_lost_connection) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index f99f4ce250..8ce2c2a8ca 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -39,6 +39,10 @@ #define F1AP_GNB_CU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update #define F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_acknowledge #define F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_failure +#define F1AP_GNB_DU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update +#define F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update_acknowledge +#define F1AP_GNB_DU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update_failure + #define F1AP_SETUP_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_failure #define F1AP_LOST_CONNECTION(mSGpTR) (mSGpTR)->ittiMsg.f1ap_lost_connection @@ -247,6 +251,57 @@ typedef struct f1ap_gnb_cu_configuration_update_failure_s { uint16_t criticality_diagnostics; } f1ap_gnb_cu_configuration_update_failure_t; +/*DU configuration messages*/ +typedef struct f1ap_gnb_du_configuration_update_s { + /*TODO UPDATE TO SUPPORT DU CONFIG*/ + + /* Transaction ID */ + uint64_t transaction_id; + /// int cells_to_add + uint16_t num_cells_to_add; + struct { + f1ap_served_cell_info_t info; + f1ap_gnb_du_system_info_t *sys_info; + } cell_to_add[F1AP_MAX_NB_CELLS]; + + /// int cells_to_modify + uint16_t num_cells_to_modify; + struct { + f1ap_plmn_t old_plmn; + uint64_t old_nr_cellid; // NR Global Cell Id + f1ap_served_cell_info_t info; + f1ap_gnb_du_system_info_t *sys_info; + } cell_to_modify[F1AP_MAX_NB_CELLS]; + + /// int cells_to_delete + uint16_t num_cells_to_delete; + struct { + // NR CGI + f1ap_plmn_t plmn; + uint64_t nr_cellid; // NR Global Cell Id + } cell_to_delete[F1AP_MAX_NB_CELLS]; + + /// string holding gNB_CU_name + uint64_t *gNB_DU_ID; +} f1ap_gnb_du_configuration_update_t; + +typedef struct f1ap_gnb_du_configuration_update_acknowledge_s { + /// ulong transaction id + uint64_t transaction_id; + /// string holding gNB_CU_name + char *gNB_CU_name; + /// number of DU cells to activate + uint16_t num_cells_to_activate; // 0< num_cells_to_activate <= 512; + served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; +} f1ap_gnb_du_configuration_update_acknowledge_t; + +typedef struct f1ap_gnb_du_configuration_update_failure_s { + /*TODO UPDATE TO SUPPORT DU CONFIG*/ + uint16_t cause; + uint16_t time_to_wait; + uint16_t criticality_diagnostics; +} f1ap_gnb_du_configuration_update_failure_t; + typedef struct f1ap_dl_rrc_message_s { uint32_t gNB_CU_ue_id; diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index 0899bca06a..49eb03512a 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -27,6 +27,8 @@ typedef void (*f1_setup_response_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_resp_t *resp); typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *fail); +typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id, + const f1ap_gnb_du_configuration_update_acknowledge_t *ack); typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req); typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req); diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 55d1bf0236..2373b548eb 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -36,6 +36,12 @@ static void f1_setup_failure_direct(sctp_assoc_t assoc_id, const f1ap_setup_fail f1_setup_failure(fail); } +static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack) +{ + AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); + AssertFatal(false, "%s() not implemented\n", __func__); +} + static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); @@ -76,6 +82,7 @@ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc) { mac_rrc->f1_setup_response = f1_setup_response_direct; mac_rrc->f1_setup_failure = f1_setup_failure_direct; + mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_direct; mac_rrc->ue_context_setup_request = ue_context_setup_request_direct; mac_rrc->ue_context_modification_request = ue_context_modification_request_direct; mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm_direct; diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index b440f1818a..e3bdca518f 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -44,6 +44,11 @@ static void f1_setup_failure_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_failur itti_send_msg_to_task(TASK_CU_F1, 0, msg); } +static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack) +{ + AssertFatal(false, "%s() not implemented\n", __func__); +} + static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); @@ -208,6 +213,7 @@ void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc) { mac_rrc->f1_setup_response = f1_setup_response_f1ap; mac_rrc->f1_setup_failure = f1_setup_failure_f1ap; + mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_f1ap; mac_rrc->ue_context_setup_request = ue_context_setup_request_f1ap; mac_rrc->ue_context_modification_request = ue_context_modification_request_f1ap; mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm_f1ap; diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 6a5c9f691f..fda89f6f8a 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -359,6 +359,7 @@ typedef struct { typedef struct nr_mac_rrc_dl_if_s { f1_setup_response_func_t f1_setup_response; f1_setup_failure_func_t f1_setup_failure; + gnb_du_configuration_update_ack_func_t gnb_du_configuration_update_acknowledge; ue_context_setup_request_func_t ue_context_setup_request; ue_context_modification_request_func_t ue_context_modification_request; ue_context_modification_confirm_func_t ue_context_modification_confirm; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index d0d9735426..24df6141e9 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2477,6 +2477,11 @@ void *rrc_gnb_task(void *args_p) { rrc_CU_process_f1_lost_connection(RC.nrrrc[0], &F1AP_LOST_CONNECTION(msg_p), msg_p->ittiMsgHeader.originInstance); break; + case F1AP_GNB_DU_CONFIGURATION_UPDATE: + AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST in DU!\n"); + rrc_gNB_process_f1_du_configuration_update(&F1AP_GNB_DU_CONFIGURATION_UPDATE(msg_p), msg_p->ittiMsgHeader.originInstance); + break; + /* Messages from X2AP */ case X2AP_ENDC_SGNB_ADDITION_REQ: LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n"); diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index bbf9942ddc..fdbe1a4551 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -219,6 +219,99 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) return count; } +static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_info_t *new_ci) +{ + DevAssert(du != NULL); + DevAssert(new_ci != NULL); + + AssertFatal(du->setup_req->num_cells_available == 1, "expected 1 cell for DU, but has %d\n", du->setup_req->num_cells_available); + f1ap_served_cell_info_t *ci = &du->setup_req->cell[0].info; + + ci->nr_cellid = new_ci->nr_cellid; + ci->nr_pci = new_ci->nr_pci; + if (new_ci->tac != NULL) + *ci->tac = *new_ci->tac; + ci->num_ssi = new_ci->num_ssi; + ci->sst = new_ci->sst; + ci->sd = new_ci->sd; + ci->mode = new_ci->mode; + if (ci->mode == F1AP_MODE_TDD) + ci->tdd = new_ci->tdd; + else + ci->fdd = new_ci->fdd; +} + +void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update_t *conf_up, sctp_assoc_t assoc_id) +{ + AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n"); + gNB_RRC_INST *rrc = RC.nrrrc[0]; + DevAssert(rrc); + + // check: + // - it is one cell + // - PLMN and Cell ID matches + // - no previous DU with the same ID + // else reject + + nr_rrc_du_container_t *du = get_du_by_assoc_id(rrc, assoc_id); + AssertError(du != NULL, return, "no DU found for assoc_id %d\n", assoc_id); + + const f1ap_served_cell_info_t *info = &du->setup_req->cell[0].info; + if (conf_up->num_cells_to_add > 0) { + // Here we check if the number of cell limit is respectet, otherwise send failure + LOG_W(RRC, "du_configuration_update->cells_to_add_list is not supported yet"); + } + + if (conf_up->num_cells_to_modify > 0) { + // here the old nrcgi is used to find the cell information, if it exist then we modify consequently otherwise we fail + AssertFatal(conf_up->num_cells_to_modify == 1, "cannot handle more than one cell!\n"); + + if (info->nr_cellid != conf_up->cell_to_modify[0].old_nr_cellid) { + LOG_W(RRC, "no cell with ID %ld found, ignoring gNB-DU configuration update\n", conf_up->cell_to_modify[0].old_nr_cellid); + return; + } + + // verify the new plmn of the cell + if (!rrc_gNB_plmn_matches(rrc, &conf_up->cell_to_modify[0].info)) { + LOG_W(RRC, "PLMN does not match, ignoring gNB-DU configuration update\n"); + return; + } + + update_cell_info(du, &conf_up->cell_to_modify[0].info); + + const f1ap_gnb_du_system_info_t *sys_info = conf_up->cell_to_modify[0].sys_info; + + if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) { + // MIB is mandatory, so will be overwritten. SIB1 is optional, so will + // only be overwritten if present in sys_info + ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib); + if (sys_info->sib1 != NULL) + ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1); + + NR_BCCH_BCH_Message_t *mib = NULL; + if (!extract_sys_info(sys_info, &mib, &du->sib1)) { + LOG_W(RRC, "cannot update sys_info for DU %ld\n", du->setup_req->gNB_DU_id); + } else { + DevAssert(mib != NULL); + du->mib = mib->message.choice.mib; + mib->message.choice.mib = NULL; + ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib); + LOG_I(RRC, "update system information of DU %ld\n", du->setup_req->gNB_DU_id); + } + } + } + + if (conf_up->num_cells_to_delete > 0) { + // delete the cell and send cell to desactive IE in the response. + LOG_W(RRC, "du_configuration_update->cells_to_delete_list is not supported yet"); + } + + /* Send DU Configuration Acknowledgement */ + f1ap_gnb_du_configuration_update_acknowledge_t ack = {.transaction_id = conf_up->transaction_id}; + + rrc->mac_rrc.gnb_du_configuration_update_acknowledge(assoc_id, &ack); +} + void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id) { AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n"); diff --git a/openair2/RRC/NR/rrc_gNB_du.h b/openair2/RRC/NR/rrc_gNB_du.h index c57faf3802..618450f774 100644 --- a/openair2/RRC/NR/rrc_gNB_du.h +++ b/openair2/RRC/NR/rrc_gNB_du.h @@ -31,9 +31,11 @@ struct f1ap_setup_req_s; struct f1ap_lost_connection_t; struct gNB_RRC_INST_s; struct nr_rrc_du_container_t; +struct f1ap_gnb_du_configuration_update_s; void rrc_gNB_process_f1_setup_req(struct f1ap_setup_req_s *req, sctp_assoc_t assoc_id); void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id); +void rrc_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration_update_s *conf_up, sctp_assoc_t assoc_id); struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id); struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id); From cdd629de894e92faacbf892ada9c6c9c185834aa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 17:29:23 +0100 Subject: [PATCH 21/41] gNB-DU config update in DU --- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 6 +++ .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 1 + openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 1 + .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 47 +++++++++++++++++++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 6 +++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + openair2/RRC/NR/mac_rrc_dl_direct.c | 2 +- 7 files changed, 63 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 5b99631d73..977bbc0403 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -144,6 +144,12 @@ void f1_setup_failure(const f1ap_setup_failure_t *failure) exit(1); } +void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack) +{ + (void)ack; + LOG_I(MAC, "received gNB-DU configuration update acknowledge\n"); +} + static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb) { long priority = srb->srb_id; // high priority for SRB diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index 799285713e..7a284f2d8b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -28,6 +28,7 @@ void f1_setup_response(const f1ap_setup_resp_t *resp); void f1_setup_failure(const f1ap_setup_failure_t *failure); +void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack); NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig); void ue_context_setup_request(const f1ap_ue_context_setup_t *req); void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 7519691334..0d902a77c6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -26,6 +26,7 @@ #include "f1ap_messages_types.h" typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req); +typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd); typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp); typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index d3320c9ac2..9cb6613d87 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -66,6 +66,52 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req) itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } +static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_update_t *upd) +{ + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); + msg->ittiMsgHeader.originInstance = -1; // means monolithic + f1ap_gnb_du_configuration_update_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg); + DevAssert(upd->gNB_DU_ID == NULL); + f1ap_msg->transaction_id = upd->transaction_id; + DevAssert(upd->num_cells_to_add == 0); + DevAssert(upd->num_cells_to_delete == 0); + + f1ap_msg->num_cells_to_modify = upd->num_cells_to_modify; + for (int n = 0; n < upd->num_cells_to_modify; ++n) { + f1ap_msg->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid; + f1ap_msg->cell_to_modify[n].info = upd->cell_to_modify[n].info; // copy most fields + if (upd->cell_to_modify[n].info.tac) { + f1ap_msg->cell_to_modify[n].info.tac = malloc(sizeof(*f1ap_msg->cell_to_modify[n].info.tac)); + AssertFatal(f1ap_msg->cell_to_modify[n].info.tac != NULL, "out of memory\n"); + *f1ap_msg->cell_to_modify[n].info.tac = *upd->cell_to_modify[n].info.tac; + } + if (upd->cell_to_modify[n].info.measurement_timing_information) + f1ap_msg->cell_to_modify[n].info.measurement_timing_information = + strdup(upd->cell_to_modify[n].info.measurement_timing_information); + + if (upd->cell_to_modify[n].sys_info) { + f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info; + f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); + AssertFatal(copy_sys_info != NULL, "out of memory\n"); + f1ap_msg->cell_to_modify[n].sys_info = copy_sys_info; + + copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); + AssertFatal(copy_sys_info->mib != NULL, "out of memory\n"); + memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); + copy_sys_info->mib_length = orig_sys_info->mib_length; + + if (orig_sys_info->sib1_length > 0) { + copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); + AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n"); + memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); + copy_sys_info->sib1_length = orig_sys_info->sib1_length; + } + } + } + + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); +} + static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) { DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); @@ -227,6 +273,7 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { mac_rrc->f1_setup_request = f1_setup_request_direct; + mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_direct; mac_rrc->ue_context_setup_response = ue_context_setup_response_direct; mac_rrc->ue_context_modification_response = ue_context_modification_response_direct; mac_rrc->ue_context_modification_required = ue_context_modification_required_direct; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index e4fb8b8f0f..6318934328 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -98,6 +98,11 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) itti_send_msg_to_task(TASK_DU_F1, 0, msg); } +static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_update_t *upd) +{ + AssertFatal(false, "%s() not implemented\n", __func__); +} + static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) { DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); @@ -237,6 +242,7 @@ static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1 void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { mac_rrc->f1_setup_request = f1_setup_request_f1ap; + mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_f1ap; mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap; mac_rrc->ue_context_modification_response = ue_context_modification_response_f1ap; mac_rrc->ue_context_modification_required = ue_context_modification_required_f1ap; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 02b5f54a56..341f972a76 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -660,6 +660,7 @@ typedef struct NR_bler_options { typedef struct nr_mac_rrc_ul_if_s { f1_setup_request_func_t f1_setup_request; + gnb_du_configuration_update_t gnb_du_configuration_update; ue_context_setup_response_func_t ue_context_setup_response; ue_context_modification_response_func_t ue_context_modification_response; ue_context_modification_required_func_t ue_context_modification_required; diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 2373b548eb..4b0afbc0e1 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -39,7 +39,7 @@ static void f1_setup_failure_direct(sctp_assoc_t assoc_id, const f1ap_setup_fail static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); - AssertFatal(false, "%s() not implemented\n", __func__); + gnb_du_configuration_update_acknowledge(ack); } static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) From 1cefbdb87f0247b6193808bec81a2b407031e34c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 11 Feb 2024 17:45:04 +0100 Subject: [PATCH 22/41] F1AP for gNB-DU config update & ack in CU --- openair2/F1AP/f1ap_cu_interface_management.c | 345 ++++++++++++++++++- openair2/F1AP/f1ap_cu_interface_management.h | 7 +- openair2/F1AP/f1ap_cu_task.c | 3 + openair2/F1AP/f1ap_handlers.c | 2 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 6 +- 5 files changed, 353 insertions(+), 10 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 41c783a2db..c44ab89018 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -431,17 +431,352 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t * int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); + LOG_D(F1AP, "CU_handle_gNB_DU_CONFIGURATION_UPDATE\n"); + F1AP_GNBDUConfigurationUpdate_t *container; + F1AP_GNBDUConfigurationUpdateIEs_t *ie; + int i = 0; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate; + + /* gNB DU Configuration Update == Non UE-related procedure -> stream 0 */ + if (stream != 0) { + LOG_W(F1AP, "[SCTP %d] Received f1 setup request on stream != 0 (%d)\n", assoc_id, stream); + } + + MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); + message_p->ittiMsgHeader.originInstance = assoc_id; + f1ap_gnb_du_configuration_update_t *req = &F1AP_GNB_DU_CONFIGURATION_UPDATE(message_p); + + /* 3GPP TS 38.473 Transaction ID*/ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); + req->transaction_id = ie->value.choice.TransactionID; + LOG_D(F1AP, "req->transaction_id %lu \n", req->transaction_id); + + /* 3GPP TS 38.473 Served Cells To Add List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List, + false); + + if (ie != NULL) { + req->num_cells_to_add = ie->value.choice.Served_Cells_To_Add_List.list.count; + LOG_D(F1AP, "req->num_cells_to_add %d \n", req->num_cells_to_add); + + for (i = 0; i < req->num_cells_to_add; i++) { + F1AP_Served_Cells_To_Add_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Add_ItemIEs_t *)ie->value.choice.Served_Cells_To_Add_List.list.array[i]) + ->value.choice.Served_Cells_To_Add_Item; + F1AP_Served_Cell_Information_t *servedCellInformation = &served_cells_item->served_Cell_Information; + /* tac */ + if (servedCellInformation->fiveGS_TAC) { + req->cell_to_add[i].info.tac = malloc(sizeof(*req->cell_to_add[i].info.tac)); + AssertFatal(req->cell_to_add[i].info.tac != NULL, "out of memory\n"); + OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell_to_add[i].info.tac); + LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_add[i].info.tac); + } + + /* - nRCGI */ + TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), + req->cell_to_add[i].info.plmn.mcc, + req->cell_to_add[i].info.plmn.mnc, + req->cell_to_add[i].info.plmn.mnc_digit_length); + // NR cellID + BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, req->cell_to_add[i].info.nr_cellid); + LOG_D(F1AP, + "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", + assoc_id, + req->cell_to_add[i].info.plmn.mcc, + req->cell_to_add[i].info.plmn.mnc, + (long long unsigned int)req->cell_to_add[i].info.nr_cellid); + + /* - nRPCI */ + req->cell_to_add[i].info.nr_pci = servedCellInformation->nRPCI; + LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_add[i].info.nr_pci); + + // FDD Cells + if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { + req->cell_to_add[i].info.mode = F1AP_MODE_FDD; + f1ap_fdd_info_t *FDDs = &req->cell_to_add[i].info.fdd; + F1AP_FDD_Info_t *fDD_Info = servedCellInformation->nR_Mode_Info.choice.fDD; + FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; + AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); + for (int f = 0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; + FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); + } + FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; + int dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; + AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n"); + for (int dlB = 0; dlB < dlBands; dlB++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; + FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; + int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; + AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); + } + FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; + FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; + FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; + FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; + } else if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { + req->cell_to_add[i].info.mode = F1AP_MODE_TDD; + f1ap_tdd_info_t *TDDs = &req->cell_to_add[i].info.tdd; + F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; + TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; + AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); + for (int f = 0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { + struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; + TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; + int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; + AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); + } + TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; + TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; + } else { + AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); + } + + struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; + // System Information + req->cell_to_add[i].sys_info = calloc(1, sizeof(*req->cell_to_add[i].sys_info)); + AssertFatal(req->cell_to_add[i].sys_info != NULL, "out of memory\n"); + f1ap_gnb_du_system_info_t *sys_info = req->cell_to_add[i].sys_info; + /* mib */ + sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); + memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); + sys_info->mib_length = DUsi->mIB_message.size; + /* sib1 */ + sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); + memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); + sys_info->sib1_length = DUsi->sIB1_message.size; + } + } else { + req->num_cells_to_add = 0; + } + /* 3GPP TS 38.473 Served Cells To Modify List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List, + false); + + if (ie) { + req->num_cells_to_modify = ie->value.choice.Served_Cells_To_Modify_List.list.count; + LOG_D(F1AP, "req->num_cells_to_modify %d \n", req->num_cells_to_modify); + + for (i = 0; i < req->num_cells_to_modify; i++) { + F1AP_Served_Cells_To_Modify_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Modify_ItemIEs_t *)ie->value.choice.Served_Cells_To_Modify_List.list.array[i]) + ->value.choice.Served_Cells_To_Modify_Item; + + /* OLD NRCGI */ + TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity), + req->cell_to_modify[i].old_plmn.mcc, + req->cell_to_modify[i].old_plmn.mnc, + req->cell_to_modify[i].old_plmn.mnc_digit_length); + + BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity, req->cell_to_modify[i].old_nr_cellid); + + F1AP_Served_Cell_Information_t *servedCellInformation = &served_cells_item->served_Cell_Information; + /* SERVED CELL INFORMATION*/ + /* tac */ + if (servedCellInformation->fiveGS_TAC) { + req->cell_to_modify[i].info.tac = malloc(sizeof(*req->cell_to_modify[i].info.tac)); + AssertFatal(req->cell_to_modify[i].info.tac != NULL, "out of memory\n"); + OCTET_STRING_TO_INT16(servedCellInformation->fiveGS_TAC, *req->cell_to_modify[i].info.tac); + LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_modify[i].info.tac); + } + + /* - nRCGI */ + TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), + req->cell_to_modify[i].info.plmn.mcc, + req->cell_to_modify[i].info.plmn.mnc, + req->cell_to_modify[i].info.plmn.mnc_digit_length); + // NR cellID + BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, req->cell_to_modify[i].info.nr_cellid); + LOG_D(F1AP, + "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", + assoc_id, + req->cell_to_modify[i].info.plmn.mcc, + req->cell_to_modify[i].info.plmn.mnc, + (long long unsigned int)req->cell_to_modify[i].info.nr_cellid); + + /* - nRPCI */ + req->cell_to_modify[i].info.nr_pci = servedCellInformation->nRPCI; + LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_modify[i].info.nr_pci); + + // FDD Cells + if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { + req->cell_to_modify[i].info.mode = F1AP_MODE_FDD; + f1ap_fdd_info_t *FDDs = &req->cell_to_modify[i].info.fdd; + F1AP_FDD_Info_t *fDD_Info = servedCellInformation->nR_Mode_Info.choice.fDD; + FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; + AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); + for (int f = 0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; + FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); + } + FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; + int dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; + AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n"); + for (int dlB = 0; dlB < dlBands; dlB++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; + FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; + int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; + AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); + } + FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; + FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; + FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; + FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; + } else if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { + req->cell_to_modify[i].info.mode = F1AP_MODE_TDD; + f1ap_tdd_info_t *TDDs = &req->cell_to_modify[i].info.tdd; + F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; + TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; + AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); + for (int f = 0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { + struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; + TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; + int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; + AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); + } + TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; + TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; + } else { + AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); + } + // TODO: Measurement Config + + /*gNB DU SYSTEM INFORMATION */ + struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; + if (DUsi != NULL) { + // System Information + req->cell_to_modify[i].sys_info = calloc(1, sizeof(*req->cell_to_modify[i].sys_info)); + AssertFatal(req->cell_to_modify[i].sys_info != NULL, "out of memory\n"); + f1ap_gnb_du_system_info_t *sys_info = req->cell_to_modify[i].sys_info; + /* mib */ + sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); + AssertFatal(req->cell_to_modify[i].sys_info->mib != NULL, "out of memory\n"); + memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); + sys_info->mib_length = DUsi->mIB_message.size; + + /* sib1 */ + sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); + AssertFatal(req->cell_to_modify[i].sys_info->sib1 != NULL, "out of memory\n"); + memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); + sys_info->sib1_length = DUsi->sIB1_message.size; + } + } + } else { + req->num_cells_to_modify = 0; + } + + /* 3GPP TS 38.473 Served Cells To Delete List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List, + false); + if (ie) { + req->num_cells_to_delete = ie->value.choice.Served_Cells_To_Delete_List.list.count; + LOG_D(F1AP, "req->num_cells_to_delete %d \n", req->num_cells_to_delete); + + for (i = 0; i < req->num_cells_to_delete; i++) { + F1AP_Served_Cells_To_Delete_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Delete_ItemIEs_t *)ie->value.choice.Served_Cells_To_Delete_List.list.array[i]) + ->value.choice.Served_Cells_To_Delete_Item; + /* - Old nRCGI */ + TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity), + req->cell_to_delete[i].plmn.mcc, + req->cell_to_delete[i].plmn.mnc, + req->cell_to_delete[i].plmn.mnc_digit_length); + // NR cellID + BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity, req->cell_to_delete[i].nr_cellid); + LOG_D(F1AP, + "[SCTP %d] Received nRCGI to delete: MCC %d, MNC %d, CELL_ID %llu\n", + assoc_id, + req->cell_to_delete[i].plmn.mcc, + req->cell_to_delete[i].plmn.mnc, + (long long unsigned int)req->cell_to_delete[i].nr_cellid); + } + } else { + req->num_cells_to_delete = 0; + } + + /* 3GPP TS 38.473 Cells Status List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cells_Status_List, false); + + /* 3GPP TS 38.473 Dedicated SI Delivery Needed UE List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List, + false); + + /* 3GPP TS 38.473 gNB-DU ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_ID, false); + if (ie != NULL) + asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, req->gNB_DU_ID); + + /* 3GPP TS 38.473 gNB-DU TNL Association To Remove List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, + ie, + container, + F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List, + false); + + LOG_D(F1AP, "Sending F1AP_GNB_DU_CONFIGURATION_UPDATE ITTI message \n"); + itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); + return 0; } int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id, - F1AP_GNBDUConfigurationUpdateFailure_t *GNBDUConfigurationUpdateFailure) { + f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure) +{ AssertFatal(1==0,"Not implemented yet\n"); } -int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, - F1AP_GNBDUConfigurationUpdateAcknowledge_t *GNBDUConfigurationUpdateAcknowledge) { - AssertFatal(1==0,"Not implemented yet\n"); +int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( + sctp_assoc_t assoc_id, + f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge) +{ + F1AP_F1AP_PDU_t pdu = {}; + uint8_t *buffer; + uint32_t len; + + /* Create */ + /* 0. Message */ + + pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, succOut); + succOut->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; + succOut->criticality = F1AP_Criticality_reject; + succOut->value.present = F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge; + F1AP_GNBDUConfigurationUpdateAcknowledge_t *ack = &succOut->value.choice.GNBDUConfigurationUpdateAcknowledge; + + /* Mandatory */ + /* Transaction Id */ + asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = GNBDUConfigurationUpdateAcknowledge->transaction_id; + + /* Todo add optional fields */ + /* encode */ + + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); + return -1; + } + + LOG_DUMPMSG(F1AP, LOG_DUMP_CHAR, buffer, len, "F1AP gNB-DU CONFIGURATION UPDATE : "); + ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + return 0; } /* diff --git a/openair2/F1AP/f1ap_cu_interface_management.h b/openair2/F1AP/f1ap_cu_interface_management.h index 4d3f562128..f506b83152 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.h +++ b/openair2/F1AP/f1ap_cu_interface_management.h @@ -62,10 +62,11 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t * int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id, - F1AP_GNBDUConfigurationUpdateFailure_t *GNBDUConfigurationUpdateFailure); + f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure); -int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, - F1AP_GNBDUConfigurationUpdateAcknowledge_t *GNBDUConfigurationUpdateAcknowledge); +int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( + sctp_assoc_t assoc_id, + f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge); /* * gNB-CU Configuration Update diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 2731fa8e0b..3d8061b961 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -174,6 +174,9 @@ void *F1AP_CU_task(void *arg) { &F1AP_GNB_CU_CONFIGURATION_UPDATE(received_msg)); break; + case F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE: + CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(assoc_id, &F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(received_msg)); + break; case F1AP_DL_RRC_MESSAGE: // from rrc CU_send_DL_RRC_MESSAGE_TRANSFER(assoc_id, &F1AP_DL_RRC_MESSAGE(received_msg)); diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c index 458299e626..ecdda72000 100644 --- a/openair2/F1AP/f1ap_handlers.c +++ b/openair2/F1AP/f1ap_handlers.c @@ -45,7 +45,7 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = { {0, 0, 0}, /* Reset */ {CU_handle_F1_SETUP_REQUEST, DU_handle_F1_SETUP_RESPONSE, DU_handle_F1_SETUP_FAILURE}, /* F1Setup */ {0, 0, 0}, /* ErrorIndication */ - {0, 0, 0}, /* gNBDUConfigurationUpdate */ + {CU_handle_gNB_DU_CONFIGURATION_UPDATE, 0, 0}, /* gNBDUConfigurationUpdate */ {DU_handle_gNB_CU_CONFIGURATION_UPDATE, CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE, CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE}, /* gNBCUConfigurationUpdate */ diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index e3bdca518f..9a934cc675 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -46,7 +46,11 @@ static void f1_setup_failure_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_failur static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack) { - AssertFatal(false, "%s() not implemented\n", __func__); + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE); + msg->ittiMsgHeader.originInstance = assoc_id; + f1ap_gnb_du_configuration_update_acknowledge_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg); + *f1ap_msg = *ack; + itti_send_msg_to_task(TASK_CU_F1, 0, msg); } static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) From ae66ba7a7b629381b99086e5190e936a8cdabc78 Mon Sep 17 00:00:00 2001 From: Giulio Carota Date: Sun, 11 Feb 2024 16:35:00 +0100 Subject: [PATCH 23/41] fix(du/cu/rrc): use the correct MIB data structure Use the correct MIB data structure, MIB_t. This is required by 38.473, and the LiteOn DU sends only that. So our CU needs to handle it, so align the OAI DU as well. --- openair2/GNB_APP/gnb_config.c | 3 ++- openair2/RRC/NR/nr_rrc_config.c | 12 ++++++++++ openair2/RRC/NR/nr_rrc_config.h | 1 + openair2/RRC/NR/rrc_gNB_du.c | 39 ++++++++++++++------------------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index dfbe4c3672..a0db5ad338 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1181,7 +1181,8 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, sys_info->mib = calloc(buf_len, sizeof(*sys_info->mib)); DevAssert(sys_info->mib != NULL); DevAssert(mib != NULL); - sys_info->mib_length = encode_MIB_NR(mib, 0, sys_info->mib, buf_len); + // encode only the mib message itself + sys_info->mib_length = encode_MIB_NR_setup(mib->message.choice.mib, 0, sys_info->mib, buf_len); DevAssert(sys_info->mib_length == buf_len); DevAssert(sib1 != NULL); diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index b6a5d45ff9..be1aaeec82 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -1875,6 +1875,18 @@ int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_s return (enc_rval.encoded + 7) / 8; } +int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size) +{ + DevAssert(mib != NULL); + uint8_t sfn_msb = (uint8_t)((frame >> 4) & 0x3f); + *mib->systemFrameNumber.buf = sfn_msb << 2; + + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MIB, NULL, mib, buf, buf_size); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC, "Encoded MIB for frame %d sfn_msb %d, bits %lu\n", frame, sfn_msb, enc_rval.encoded); + return (enc_rval.encoded + 7) / 8; +} + NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, int tac) { AssertFatal(cellID < (1l << 36), "cellID must fit within 36 bits, but is %lu\n", cellID); diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index 1db2d4a2f1..b18be2ff61 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -55,6 +55,7 @@ void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, NR_BCCH_BCH_Message_t *get_new_MIB_NR(const NR_ServingCellConfigCommon_t *scc); void free_MIB_NR(NR_BCCH_BCH_Message_t *mib); int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_size); +int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size); #define NR_MAX_SIB_LENGTH 2976 // 3GPP TS 38.331 section 5.2.1 diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index fdbe1a4551..c67263a67e 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -49,35 +49,33 @@ static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell && conf->mnc[0] == info->plmn.mnc; } -static bool extract_sys_info(const f1ap_gnb_du_system_info_t *sys_info, NR_BCCH_BCH_Message_t **mib, NR_SIB1_t **sib1) +static bool extract_sys_info(const f1ap_gnb_du_system_info_t *sys_info, NR_MIB_t **mib, NR_SIB1_t **sib1) { DevAssert(sys_info != NULL); DevAssert(mib != NULL); DevAssert(sib1 != NULL); - asn_dec_rval_t dec_rval = - uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)mib, sys_info->mib, sys_info->mib_length); - if (dec_rval.code != RC_OK || (*mib)->message.present != NR_BCCH_BCH_MessageType_PR_mib - || (*mib)->message.choice.messageClassExtension == NULL) { - LOG_E(RRC, "Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits) of DU\n", dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib); + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_MIB, (void **)mib, sys_info->mib, sys_info->mib_length); + if (dec_rval.code != RC_OK) { + LOG_E(RRC, "Failed to decode NR_MIB (%zu bits) of DU\n", dec_rval.consumed); + ASN_STRUCT_FREE(asn_DEF_NR_MIB, *mib); return false; } if (sys_info->sib1) { dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_SIB1, (void **)sib1, sys_info->sib1, sys_info->sib1_length); if (dec_rval.code != RC_OK) { - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib); + ASN_STRUCT_FREE(asn_DEF_NR_MIB, *mib); ASN_STRUCT_FREE(asn_DEF_NR_SIB1, *sib1); LOG_E(RRC, "Failed to decode NR_SIB1 (%zu bits), rejecting DU\n", dec_rval.consumed); return false; } } - if (LOG_DEBUGFLAG(DEBUG_ASN1)) - xer_fprint(stdout, &asn_DEF_NR_BCCH_BCH_Message, *mib); - if (LOG_DEBUGFLAG(DEBUG_ASN1)) + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NR_MIB, *mib); xer_fprint(stdout, &asn_DEF_NR_SIB1, *sib1); + } return true; } @@ -145,7 +143,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) } const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info; - NR_BCCH_BCH_Message_t *mib = NULL; + NR_MIB_t *mib = NULL; NR_SIB1_t *sib1 = NULL; if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) { @@ -170,12 +168,9 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) du->setup_req = calloc(1,sizeof(*du->setup_req)); AssertFatal(du->setup_req, "out of memory\n"); *du->setup_req = *req; - if (mib != NULL && sib1 != NULL) { - du->mib = mib->message.choice.mib; - mib->message.choice.mib = NULL; - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib); - du->sib1 = sib1; - } + // MIB can be null and configured later via DU Configuration Update + du->mib = mib; + du->sib1 = sib1; RB_INSERT(rrc_du_tree, &rrc->dus, du); rrc->num_dus++; @@ -184,7 +179,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) .nr_cellid = cell_info->nr_cellid, .nrpci = cell_info->nr_pci, .num_SI = 0, - }; + }; f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id, .num_cells_to_activate = 1, @@ -288,14 +283,12 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update if (sys_info->sib1 != NULL) ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1); - NR_BCCH_BCH_Message_t *mib = NULL; + NR_MIB_t *mib = NULL; if (!extract_sys_info(sys_info, &mib, &du->sib1)) { LOG_W(RRC, "cannot update sys_info for DU %ld\n", du->setup_req->gNB_DU_id); } else { DevAssert(mib != NULL); - du->mib = mib->message.choice.mib; - mib->message.choice.mib = NULL; - ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib); + du->mib = mib; LOG_I(RRC, "update system information of DU %ld\n", du->setup_req->gNB_DU_id); } } From aaaa00378aee74ae0fe8e808bf003d5500459a8a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 26 Mar 2024 18:53:18 +0100 Subject: [PATCH 24/41] Do not send UE Context modif only with successful reconfig The OAI DU does not use this message, and could not roll-back. The LiteOn DU does not seem to like it. It is useless (as of now), so remove it --- openair2/RRC/NR/rrc_gNB.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 24df6141e9..52cb041aee 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1561,7 +1561,6 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ UE->ue_reconfiguration_counter++; LOG_I(NR_RRC, "UE %d: Receive RRC Reconfiguration Complete message (xid %d)\n", UE->rrc_ue_id, xid); - bool successful_reconfig = true; switch (UE->xids[xid]) { case RRC_PDUSESSION_RELEASE: { gtpv1u_gnb_delete_tunnel_req_t req = {0}; @@ -1585,11 +1584,9 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ break; case RRC_ACTION_NONE: LOG_E(RRC, "UE %d: Received RRC Reconfiguration Complete with xid %d while no transaction is ongoing\n", UE->rrc_ue_id, xid); - successful_reconfig = false; break; default: LOG_E(RRC, "UE %d: Received unexpected transaction type %d for xid %d\n", UE->rrc_ue_id, UE->xids[xid], xid); - successful_reconfig = false; break; } UE->xids[xid] = RRC_ACTION_NONE; @@ -1599,21 +1596,6 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ } } - gNB_RRC_INST *rrc = RC.nrrrc[0]; - f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); - f1ap_ue_context_modif_req_t ue_context_modif_req = { - .gNB_CU_ue_id = UE->rrc_ue_id, - .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn.mcc = rrc->configuration.mcc[0], - .plmn.mnc = rrc->configuration.mnc[0], - .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], - .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .ReconfigComplOutcome = successful_reconfig ? RRCreconf_success : RRCreconf_failure, - }; - rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); - /* if we did not receive any UE Capabilities, let's do that now. It should * only happen on the first time a reconfiguration arrives. Afterwards, we * should have them. If the UE does not give us anything, we will re-request From 67e55479573b592db04f10e87f241a0d2be78dde Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 14 Feb 2024 08:02:48 +0100 Subject: [PATCH 25/41] Refactor F1 setup req reading Refactor parts into a separate function, which will be reused within the gNB-DU configuration update function in the next commit. --- openair2/F1AP/f1ap_du_interface_management.c | 287 +++++++++---------- openair2/F1AP/f1ap_du_interface_management.h | 2 +- 2 files changed, 144 insertions(+), 145 deletions(-) diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 3fa2c1b65d..a8e7bfb499 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -83,12 +83,146 @@ int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint3 AssertFatal(1==0,"Not implemented yet\n"); } -/* - F1 Setup -*/ +static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_cell_info_t *c) +{ + /* 4.1.1 served cell Information */ + F1AP_Served_Cell_Information_t scell_info = {0}; + addnRCGI(scell_info.nRCGI, c); + + /* - nRPCI */ + scell_info.nRPCI = c->nr_pci; // int 0..1007 + + /* - fiveGS_TAC */ + if (c->tac != NULL) { + uint32_t tac = htonl(*c->tac); + asn1cCalloc(scell_info.fiveGS_TAC, netOrder); + OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3); + } + + /* - Configured_EPS_TAC */ + if (0) { + scell_info.configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t)); + OCTET_STRING_fromBuf(scell_info.configured_EPS_TAC, "2", 2); + } + + /* servedPLMN information */ + asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); + MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); + + F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info; + if (c->num_ssi > 0) { + F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p)); + servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t, served_plmns_itemExtIEs); + served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore; + served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList; + served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList; + F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList; + + AssertFatal(c->num_ssi == 1, "can only encode one slice\n"); + for (int s = 0; s < c->num_ssi; s++) { + asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); + INT8_TO_OCTET_STRING(c->sst, &slice->sNSSAI.sST); + if (c->sd != 0xffffff) { + asn1cCalloc(slice->sNSSAI.sD, tmp); + INT24_TO_OCTET_STRING(c->sd, tmp); + } + } + } + + if (c->mode == F1AP_MODE_FDD) { // FDD + const f1ap_fdd_info_t *fdd = &c->fdd; + nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; + asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); + /* FDD.1.1 UL NRFreqInfo ARFCN */ + fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer + + /* FDD.1.2 F1AP_SUL_Information */ + + /* FDD.1.3 freqBandListNr */ + int ul_band = 1; + for (int j = 0; j < ul_band; j++) { + asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* FDD.1.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band; + + /* FDD.1.3.2 supportedSULBandList*/ + } + + /* FDD.2.1 DL NRFreqInfo ARFCN */ + fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer + + /* FDD.2.2 F1AP_SUL_Information */ + + /* FDD.2.3 freqBandListNr */ + int dl_bands = 1; + for (int j = 0; j < dl_bands; j++) { + asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* FDD.2.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band; + + /* FDD.2.3.2 supportedSULBandList*/ + } // for FDD : DL freq_Bands + + /* FDD.3 UL Transmission Bandwidth */ + fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs; + fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb); + /* FDD.4 DL Transmission Bandwidth */ + fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs; + fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb); + } else if (c->mode == F1AP_MODE_TDD) { + const f1ap_tdd_info_t *tdd = &c->tdd; + nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; + asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); + /* TDD.1.1 nRFreqInfo ARFCN */ + tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; + + /* TDD.1.2 F1AP_SUL_Information */ + + /* TDD.1.3 freqBandListNr */ + int bands = 1; + for (int j = 0; j < bands; j++) { + asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* TDD.1.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band; + /* TDD.1.3.2 supportedSULBandList*/ + } + + /* TDD.2 transmission_Bandwidth */ + tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs; + tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb); + } else { + AssertFatal(false, "unknown mode %d\n", c->mode); + } + + /* - measurementTimingConfiguration */ + char *measurementTimingConfiguration = c->measurement_timing_information; + OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration, + measurementTimingConfiguration, + strlen(measurementTimingConfiguration)); + + return scell_info; +} + +static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_system_info_t *sys_info) +{ + if (sys_info == NULL) + return NULL; /* optional: can be NULL */ + + F1AP_GNB_DU_System_Information_t *enc_sys_info = calloc(1, sizeof(*enc_sys_info)); + AssertFatal(enc_sys_info != NULL, "out of memory\n"); + + AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n"); + OCTET_STRING_fromBuf(&enc_sys_info->mIB_message, (const char *)sys_info->mib, sys_info->mib_length); + + AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n"); + OCTET_STRING_fromBuf(&enc_sys_info->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length); + + return enc_sys_info; +} // SETUP REQUEST -int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req) +int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req) { F1AP_F1AP_PDU_t pdu= {0}; uint8_t *buffer; @@ -139,151 +273,16 @@ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req) for (int i=0; icell[i].info; + const f1ap_served_cell_info_t *cell = &setup_req->cell[i].info; + const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info; asn1cSequenceAdd(ieCells->value.choice.GNB_DU_Served_Cells_List.list, F1AP_GNB_DU_Served_Cells_ItemIEs_t, duServedCell); duServedCell->id = F1AP_ProtocolIE_ID_id_GNB_DU_Served_Cells_Item; duServedCell->criticality = F1AP_Criticality_reject; duServedCell->value.present = F1AP_GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item; - F1AP_GNB_DU_Served_Cells_Item_t *gnb_du_served_cells_item=&duServedCell->value.choice.GNB_DU_Served_Cells_Item; - /* 4.1.1 served cell Information */ - F1AP_Served_Cell_Information_t *served_cell_information= &gnb_du_served_cells_item->served_Cell_Information; - addnRCGI(served_cell_information->nRCGI, cell); - /* - nRPCI */ - served_cell_information->nRPCI = cell->nr_pci; // int 0..1007 - /* - fiveGS_TAC */ - if (cell->tac != NULL) { - uint32_t tac=htonl(*cell->tac); - asn1cCalloc(served_cell_information->fiveGS_TAC, netOrder); - OCTET_STRING_fromBuf(netOrder, ((char *)&tac)+1, 3); - } - - /* - Configured_EPS_TAC */ - if(0) { - served_cell_information->configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t)); - OCTET_STRING_fromBuf(served_cell_information->configured_EPS_TAC, "2", 2); - } - - /* servedPLMN information */ - asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t,servedPLMN_item); - MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); - // // /* - CHOICE NR-MODE-Info */ - F1AP_NR_Mode_Info_t *nR_Mode_Info= &served_cell_information->nR_Mode_Info; - F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p)); - servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *) p; - asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t , served_plmns_itemExtIEs); - served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore; - served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList; - served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList; - F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList; - - /* get list of sst/sd from configuration file */ - paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC; - paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0}; - char sstr[100]; - /* TODO: be sure that %d in the line below is at the right place */ - sprintf(sstr, "%s.[%d].%s.[0]", GNB_CONFIG_STRING_GNB_LIST, i, GNB_CONFIG_STRING_PLMN_LIST); - config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeofArray(SNSSAIParams), sstr); - AssertFatal(SNSSAIParamList.numelt > 0, "no slice configuration found (snssaiList in the configuration file)\n"); - AssertFatal(SNSSAIParamList.numelt <= 1024, "maximum size for slice support list is 1024, see F1AP 38.473 9.3.1.37\n"); - for (int s = 0; s < SNSSAIParamList.numelt; s++) { - uint32_t sst; - uint32_t sd; - bool has_sd; - sst = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr; - has_sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr != 0xffffff; - asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); - INT8_TO_OCTET_STRING(sst, &slice->sNSSAI.sST); - if (has_sd) { - sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr; - asn1cCalloc(slice->sNSSAI.sD, tmp); - INT24_TO_OCTET_STRING(sd, tmp); - } - } - - if (setup_req->cell[i].info.mode == F1AP_MODE_FDD) { // FDD - const f1ap_fdd_info_t *fdd = &setup_req->cell[i].info.fdd; - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; - asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); - /* FDD.1 UL NRFreqInfo */ - /* FDD.1.1 UL NRFreqInfo ARFCN */ - fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer - - /* FDD.1.2 F1AP_SUL_Information */ - - /* FDD.1.3 freqBandListNr */ - int fdd_ul_num_available_freq_Bands = 1; - for (int fdd_ul_j=0; fdd_ul_juL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band; - - /* FDD.1.3.2 supportedSULBandList*/ - } // for FDD : UL freq_Bands - - /* FDD.2 DL NRFreqInfo */ - /* FDD.2.1 DL NRFreqInfo ARFCN */ - fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer - - /* FDD.2.2 F1AP_SUL_Information */ - - /* FDD.2.3 freqBandListNr */ - int fdd_dl_num_available_freq_Bands = 1; - for (int fdd_dl_j=0; fdd_dl_jdL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.2.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band; - - /* FDD.2.3.2 supportedSULBandList*/ - } // for FDD : DL freq_Bands - - /* FDD.3 UL Transmission Bandwidth */ - fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs; - fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb); - /* FDD.4 DL Transmission Bandwidth */ - fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs; - fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb); - } else if (setup_req->cell[i].info.mode == F1AP_MODE_TDD) { // TDD - const f1ap_tdd_info_t *tdd = &setup_req->cell[i].info.tdd; - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; - asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); - /* TDD.1 nRFreqInfo */ - /* TDD.1.1 nRFreqInfo ARFCN */ - tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; // Integer - - /* TDD.1.2 F1AP_SUL_Information */ - - /* TDD.1.3 freqBandListNr */ - int tdd_num_available_freq_Bands = 1; - for (int j=0; jnRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* TDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band; - /* TDD.1.3.2 supportedSULBandList*/ - } // for TDD : freq_Bands - - /* TDD.2 transmission_Bandwidth */ - tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs; - tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb); - } else { - AssertFatal(false, "unknown mode %d\n", setup_req->cell[i].info.mode); - } - - /* - measurementTimingConfiguration */ - char *measurementTimingConfiguration = cell->measurement_timing_information; // sept. 2018 - OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration, - measurementTimingConfiguration, - strlen(measurementTimingConfiguration)); - - /* 4.1.2 gNB-DU System Information */ - if (setup_req->cell[i].sys_info != NULL) { - asn1cCalloc(gnb_du_served_cells_item->gNB_DU_System_Information, gNB_DU_System_Information); - const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info; - AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n"); - OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, (const char *)sys_info->mib, sys_info->mib_length); - AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n"); - OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length); - } + F1AP_GNB_DU_Served_Cells_Item_t *scell_item = &duServedCell->value.choice.GNB_DU_Served_Cells_Item; + scell_item->served_Cell_Information = encode_served_cell_info(cell); + scell_item->gNB_DU_System_Information = encode_system_info(sys_info); } /* mandatory */ diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index 8fa166d0bc..d7e9a8294a 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -50,7 +50,7 @@ int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint3 /* * F1 Setup */ -int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req); +int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req); int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); From a771d58472045fab590c14d4bda7be99c1deca4b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 14 Feb 2024 09:20:06 +0100 Subject: [PATCH 26/41] Implement F1AP code for gNB-DU configuration update --- openair2/F1AP/f1ap_du_interface_management.c | 261 +++++-------------- openair2/F1AP/f1ap_du_interface_management.h | 3 +- openair2/F1AP/f1ap_du_task.c | 4 + openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 30 ++- 4 files changed, 101 insertions(+), 197 deletions(-) diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index a8e7bfb499..5e7c892301 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -533,7 +533,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3 gNB-DU Configuration Update */ -int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_setup_req_t *f1ap_setup_req) +int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd) { F1AP_F1AP_PDU_t pdu= {0}; uint8_t *buffer=NULL; @@ -545,227 +545,100 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_setup_req_t initMsg->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; initMsg->criticality = F1AP_Criticality_reject; initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate; - F1AP_GNBDUConfigurationUpdate_t *out = &pdu.choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate; + F1AP_GNBDUConfigurationUpdate_t *out = &initMsg->value.choice.GNBDUConfigurationUpdate; + /* mandatory */ /* c1. Transaction ID (integer value) */ - asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie1); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie1); ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; ie1->criticality = F1AP_Criticality_reject; ie1->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); + ie1->value.choice.TransactionID = upd->transaction_id; + /* mandatory */ /* c2. Served_Cells_To_Add */ - asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List; + if (upd->num_cells_to_add > 0) { + AssertFatal(false, "code for adding cells not tested\n"); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List; - for (int j=0; j<1; j++) { - // - asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, F1AP_Served_Cells_To_Add_ItemIEs_t, served_cells_to_add_item_ies); - served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item; - served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item; - F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item= &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item; - F1AP_Served_Cell_Information_t *served_cell_information=&served_cells_to_add_item->served_Cell_Information; - /* - nRCGI */ - addnRCGI(served_cell_information->nRCGI, &f1ap_setup_req->cell[j].info); - /* - nRPCI */ - /* 2.1.1 serverd cell Information */ - f1ap_served_cell_info_t *cell = &f1ap_setup_req->cell[j].info; - served_cell_information->nRPCI = cell->nr_pci; // int 0..1007 - /* - fiveGS_TAC */ - if (cell->tac != NULL) { - uint32_t tac = htonl(*cell->tac); - served_cell_information->fiveGS_TAC = calloc(1, sizeof(*served_cell_information->fiveGS_TAC)); - OCTET_STRING_fromBuf(served_cell_information->fiveGS_TAC, ((char *)&tac)+1, 3); + for (int j = 0; j < upd->num_cells_to_add; j++) { + const f1ap_served_cell_info_t *cell = &upd->cell_to_add[j].info; + const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_add[j].sys_info; + asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, + F1AP_Served_Cells_To_Add_ItemIEs_t, + served_cells_to_add_item_ies); + served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item; + served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item; + F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item = + &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item; + served_cells_to_add_item->served_Cell_Information = encode_served_cell_info(cell); + served_cells_to_add_item->gNB_DU_System_Information = encode_system_info(sys_info); } - - /* - Configured_EPS_TAC */ - if(1) { - served_cell_information->configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t)); - OCTET_STRING_fromBuf(served_cell_information->configured_EPS_TAC,"2", 2); - } - - asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); - MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); - // // /* - CHOICE NR-MODE-Info */ - F1AP_NR_Mode_Info_t *nR_Mode_Info=&served_cell_information->nR_Mode_Info; - LOG_E(F1AP,"Here hardcoded values instead of values from configuration file\n"); - - if (cell->mode == F1AP_MODE_FDD) { - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; - /* > FDD >> FDD Info */ - asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); - /* >>> UL NRFreqInfo */ - fDD_Info->uL_NRFreqInfo.nRARFCN = 999L; - asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, ul_freqBandNrItem); - ul_freqBandNrItem->freqBandIndicatorNr = 888L; - asn1cSequenceAdd(ul_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, ul_supportedSULFreqBandItem); - ul_supportedSULFreqBandItem->freqBandIndicatorNr = 777L; - /* >>> DL NRFreqInfo */ - fDD_Info->dL_NRFreqInfo.nRARFCN = 666L; - asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, dl_freqBandNrItem); - dl_freqBandNrItem->freqBandIndicatorNr = 555L; - asn1cSequenceAdd(dl_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, dl_supportedSULFreqBandItem); - dl_supportedSULFreqBandItem->freqBandIndicatorNr = 444L; - /* >>> UL Transmission Bandwidth */ - fDD_Info->uL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15; - fDD_Info->uL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11; - /* >>> DL Transmission Bandwidth */ - fDD_Info->dL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15; - fDD_Info->dL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11; - } else if (cell->mode == F1AP_MODE_TDD) { // TDD - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; - /* > TDD >> TDD Info */ - asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); - /* >>> ARFCN */ - tDD_Info->nRFreqInfo.nRARFCN = 999L; // Integer - asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - nr_freqBandNrItem->freqBandIndicatorNr = 555L; - asn1cSequenceAdd(nr_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, nr_supportedSULFreqBandItem); - nr_supportedSULFreqBandItem->freqBandIndicatorNr = 444L; - tDD_Info->transmission_Bandwidth.nRSCS= F1AP_NRSCS_scs15; - tDD_Info->transmission_Bandwidth.nRNRB= F1AP_NRNRB_nrb11; - } else { - AssertFatal(false, "illegal mode %d\n", cell->mode); - } - - /* - measurementTimingConfiguration */ - char *measurementTimingConfiguration = "0"; // sept. 2018 - OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration, - measurementTimingConfiguration, - strlen(measurementTimingConfiguration)); - /* 2.1.2 gNB-DU System Information */ - asn1cCalloc(served_cells_to_add_item->gNB_DU_System_Information, gNB_DU_System_Information); - OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, // sept. 2018 - "1", - sizeof("1")); - OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, // sept. 2018 - "1", - sizeof("1")); } /* mandatory */ /* c3. Served_Cells_To_Modify */ - asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List; + if (upd->num_cells_to_modify > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List; + for (int i = 0; i < upd->num_cells_to_modify; i++) { + const f1ap_served_cell_info_t *cell = &upd->cell_to_modify[i].info; + const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_modify[i].sys_info; + asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, + F1AP_Served_Cells_To_Modify_ItemIEs_t, + served_cells_to_modify_item_ies); + served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item; + served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item; + F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item = + &served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item; - for (int i=0; i<1; i++) { - // - f1ap_served_cell_info_t *cell = &f1ap_setup_req->cell[i].info; - asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, F1AP_Served_Cells_To_Modify_ItemIEs_t, served_cells_to_modify_item_ies); - served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item; - served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item; - F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item=&served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item; - /* 3.1 oldNRCGI */ - //addnRGCI(served_cells_to_modify_item->oldNRCGI, f1ap_setup_req->cell[i]); - /* 3.2.1 serverd cell Information */ - F1AP_Served_Cell_Information_t *served_cell_information= &served_cells_to_modify_item->served_Cell_Information; - /* - nRCGI */ - //addnRGCI(served_cell_information->nRCGI,f1ap_setup_req->cell[i]); - /* - nRPCI */ - served_cell_information->nRPCI = cell->nr_pci; // int 0..1007 - /* - fiveGS_TAC */ - asn1cCalloc(served_cell_information->fiveGS_TAC, tac ); - OCTET_STRING_fromBuf(tac, - (const char *) &cell->tac, - 3); + F1AP_NRCGI_t *oldNRCGI = &served_cells_to_modify_item->oldNRCGI; + const f1ap_plmn_t *old_plmn = &upd->cell_to_modify[i].old_plmn; + MCC_MNC_TO_PLMNID(old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length, &oldNRCGI->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(upd->cell_to_modify[i].old_nr_cellid, &oldNRCGI->nRCellIdentity); - /* - Configured_EPS_TAC */ - if(1) { - asn1cCalloc(served_cell_information->configured_EPS_TAC, tmp2); - OCTET_STRING_fromBuf(tmp2, - "2", - 2); + served_cells_to_modify_item->served_Cell_Information = encode_served_cell_info(cell); + served_cells_to_modify_item->gNB_DU_System_Information = encode_system_info(sys_info); } - - asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); - MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); - // // /* - CHOICE NR-MODE-Info */ - F1AP_NR_Mode_Info_t *nR_Mode_Info= &served_cell_information->nR_Mode_Info; - - if (cell->mode == F1AP_MODE_FDD) { - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; - /* > FDD >> FDD Info */ - asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); - /* >>> UL NRFreqInfo */ - fDD_Info->uL_NRFreqInfo.nRARFCN = 999L; - asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, ul_freqBandNrItem); - ul_freqBandNrItem->freqBandIndicatorNr = 888L; - asn1cSequenceAdd(ul_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, ul_supportedSULFreqBandItem); - ul_supportedSULFreqBandItem->freqBandIndicatorNr = 777L; - /* >>> DL NRFreqInfo */ - fDD_Info->dL_NRFreqInfo.nRARFCN = 666L; - asn1cSequenceAdd(dl_freqBandNrItem->supportedSULBandList.list, F1AP_FreqBandNrItem_t, dl_freqBandNrItem); - dl_freqBandNrItem->freqBandIndicatorNr = 555L; - F1AP_SupportedSULFreqBandItem_t dl_supportedSULFreqBandItem; - memset((void *)&dl_supportedSULFreqBandItem, 0, sizeof(F1AP_SupportedSULFreqBandItem_t)); - dl_supportedSULFreqBandItem.freqBandIndicatorNr = 444L; - /* >>> UL Transmission Bandwidth */ - fDD_Info->uL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15; - fDD_Info->uL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11; - /* >>> DL Transmission Bandwidth */ - fDD_Info->dL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15; - fDD_Info->dL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11; - } else if (cell->mode == F1AP_MODE_TDD) { // TDD - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; - /* > TDD >> TDD Info */ - asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); - /* >>> ARFCN */ - tDD_Info->nRFreqInfo.nRARFCN = 999L; // Integer - asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - nr_freqBandNrItem->freqBandIndicatorNr = 555L; - asn1cSequenceAdd(nr_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, nr_supportedSULFreqBandItem); - nr_supportedSULFreqBandItem->freqBandIndicatorNr = 444L; - tDD_Info->transmission_Bandwidth.nRSCS= F1AP_NRSCS_scs15; - tDD_Info->transmission_Bandwidth.nRNRB= F1AP_NRNRB_nrb11; - } else { - AssertFatal(false, "unknown mode %d\n", cell->mode); - } - - /* - measurementTimingConfiguration */ - char *measurementTimingConfiguration = "0"; // sept. 2018 - OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration, - measurementTimingConfiguration, - strlen(measurementTimingConfiguration)); - /* 3.2.2 gNB-DU System Information */ - asn1cCalloc( served_cells_to_modify_item->gNB_DU_System_Information, gNB_DU_System_Information); - OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, // sept. 2018 - "1", - sizeof("1")); - OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, // sept. 2018 - "1", - sizeof("1")); } /* mandatory */ /* c4. Served_Cells_To_Delete */ - asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, F1AP_Served_Cells_To_Delete_ItemIEs_t, served_cells_to_delete_item_ies); - served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item; - served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item; - F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item=&served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item; - /* 3.1 oldNRCGI */ - addnRCGI(served_cells_to_delete_item->oldNRCGI, &f1ap_setup_req->cell[i].info); + if (upd->num_cells_to_delete > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List; + AssertFatal(upd->num_cells_to_delete == 0, "code for deleting cells not tested\n"); + for (int i = 0; i < upd->num_cells_to_delete; i++) { + asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, + F1AP_Served_Cells_To_Delete_ItemIEs_t, + served_cells_to_delete_item_ies); + served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item; + served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item; + F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item = + &served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item; + addnRCGI(served_cells_to_delete_item->oldNRCGI, &upd->cell_to_delete[i]); + } } + AssertFatal(upd->gNB_DU_ID == 0, "encoding of gNB-DU Id not handled yet\n"); + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); return -1; } ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index d7e9a8294a..c48754010f 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -59,8 +59,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3 /* * gNB-DU Configuration Update */ -int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, - f1ap_setup_req_t *f1ap_du_data); +int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd); int DU_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index 1783e9d909..7959f734fe 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -186,6 +186,10 @@ void *F1AP_DU_task(void *arg) { DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(assoc_id, &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg)); break; + case F1AP_GNB_DU_CONFIGURATION_UPDATE: + DU_send_gNB_DU_CONFIGURATION_UPDATE(assoc_id, &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg)); + break; + case TERMINATE_MESSAGE: LOG_W(F1AP, " *** Exiting F1AP thread\n"); itti_exit_task(); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 6318934328..8cd58e696a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -100,7 +100,35 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_update_t *upd) { - AssertFatal(false, "%s() not implemented\n", __func__); + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); + f1ap_gnb_du_configuration_update_t *f1_upd = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg); + f1_upd->transaction_id = upd->transaction_id; + AssertFatal(upd->num_cells_to_add == 0, "gNB-DU config update: cells to add not supported\n"); + f1_upd->num_cells_to_modify = upd->num_cells_to_modify; + for (int n = 0; n < upd->num_cells_to_modify; ++n) { + f1_upd->cell_to_modify[n].old_plmn = upd->cell_to_modify[n].old_plmn; + f1_upd->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid; + f1_upd->cell_to_modify[n].info = upd->cell_to_modify[n].info; + if (upd->cell_to_modify[n].sys_info) { + f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info; + f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); + f1_upd->cell_to_modify[n].sys_info = copy_sys_info; + + copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); + AssertFatal(copy_sys_info->mib != NULL, "out of memory\n"); + memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); + copy_sys_info->mib_length = orig_sys_info->mib_length; + + if (orig_sys_info->sib1_length > 0) { + copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); + AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n"); + memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); + copy_sys_info->sib1_length = orig_sys_info->sib1_length; + } + } + } + AssertFatal(upd->num_cells_to_delete == 0, "gNB-DU config update: cells to add not supported\n"); + itti_send_msg_to_task(TASK_DU_F1, 0, msg); } static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) From 2f81f190d1094207fc08097fb41fff515f0f18cd Mon Sep 17 00:00:00 2001 From: Giulio Carota Date: Mon, 11 Mar 2024 10:59:40 +0100 Subject: [PATCH 27/41] Generate TimingMeasurementConfig at DU, store at CU --- openair2/COMMON/f1ap_messages_types.h | 3 +- openair2/F1AP/f1ap_cu_interface_management.c | 26 +++++- openair2/F1AP/f1ap_du_interface_management.c | 5 +- openair2/GNB_APP/gnb_config.c | 12 ++- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 22 ++++-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 10 ++- openair2/RRC/NR/nr_rrc_config.c | 79 +++++++++++++++++++ openair2/RRC/NR/nr_rrc_config.h | 4 + openair2/RRC/NR/nr_rrc_defs.h | 2 + openair2/RRC/NR/rrc_gNB_du.c | 46 +++++++++++ 10 files changed, 196 insertions(+), 13 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 8ce2c2a8ca..26399fae85 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -140,7 +140,8 @@ typedef struct f1ap_served_cell_info_t { f1ap_tdd_info_t tdd; }; - char *measurement_timing_information; + uint8_t *measurement_timing_config; + int measurement_timing_config_len; } f1ap_served_cell_info_t; typedef struct f1ap_gnb_du_system_info_t { diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index c44ab89018..ed8403c492 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -67,6 +67,14 @@ int CU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_ErrorIndication_t *Erro AssertFatal(1==0,"Not implemented yet\n"); } +static uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) +{ + uint8_t *buf = calloc(os->size, sizeof(*buf)); + AssertFatal(buf != NULL, "out of memory\n"); + memcpy(buf, os->buf, os->size); + *len = os->size; + return buf; +} /* F1 Setup @@ -187,6 +195,11 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint3 AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); } + /* MeasurementConfig */ + if (servedCellInformation->measurementTimingConfiguration.size > 0) + req->cell[i].info.measurement_timing_config = + cp_octet_string(&servedCellInformation->measurementTimingConfiguration, &req->cell[i].info.measurement_timing_config_len); + struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information; if (DUsi != NULL) { // System Information @@ -537,6 +550,12 @@ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); } + /* MeasurementConfig */ + if (servedCellInformation->measurementTimingConfiguration.size > 0) + req->cell_to_add[i].info.measurement_timing_config = + cp_octet_string(&servedCellInformation->measurementTimingConfiguration, + &req->cell_to_add[i].info.measurement_timing_config_len); + struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; // System Information req->cell_to_add[i].sys_info = calloc(1, sizeof(*req->cell_to_add[i].sys_info)); @@ -648,7 +667,12 @@ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso } else { AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); } - // TODO: Measurement Config + + /* MeasurementConfig */ + if (servedCellInformation->measurementTimingConfiguration.size > 0) + req->cell_to_modify[i].info.measurement_timing_config = + cp_octet_string(&servedCellInformation->measurementTimingConfiguration, + &req->cell_to_modify[i].info.measurement_timing_config_len); /*gNB DU SYSTEM INFORMATION */ struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 5e7c892301..23af0ea3e6 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -196,10 +196,9 @@ static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_ } /* - measurementTimingConfiguration */ - char *measurementTimingConfiguration = c->measurement_timing_information; OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration, - measurementTimingConfiguration, - strlen(measurementTimingConfiguration)); + (const char *)c->measurement_timing_config, + c->measurement_timing_config_len); return scell_info; } diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index a0db5ad338..64a40e4a83 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -82,6 +82,7 @@ #include "NR_RateMatchPatternLTE-CRS.h" #include "NR_SearchSpace.h" #include "NR_ControlResourceSet.h" +#include "NR_MeasurementTimingConfiguration.h" #include "NR_EUTRA-MBSFN-SubframeConfig.h" #include "uper_decoder.h" #include "uper_encoder.h" @@ -1168,7 +1169,16 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id, req->cell[0].info.fdd = read_fdd_config(scc); } - req->cell[0].info.measurement_timing_information = "0"; + NR_MeasurementTimingConfiguration_t *mtc = get_new_MeasurementTimingConfiguration(scc); + uint8_t buf[1024]; + int len = encode_MeasurementTimingConfiguration(mtc, buf, sizeof(buf)); + DevAssert(len <= sizeof(buf)); + free_MeasurementTimingConfiguration(mtc); + uint8_t *mtc_buf = calloc(len, sizeof(*mtc_buf)); + AssertFatal(mtc_buf != NULL, "out of memory\n"); + memcpy(mtc_buf, buf, len); + req->cell[0].info.measurement_timing_config = mtc_buf; + req->cell[0].info.measurement_timing_config_len = len; if (get_softmodem_params()->sa) { // in NSA we don't transmit SIB1, so cannot fill DU system information diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 9cb6613d87..acef49ef5b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -39,8 +39,14 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req) AssertFatal(f1ap_msg->cell[n].info.tac != NULL, "out of memory\n"); *f1ap_msg->cell[n].info.tac = *req->cell[n].info.tac; } - if (req->cell[n].info.measurement_timing_information) - f1ap_msg->cell[n].info.measurement_timing_information = strdup(req->cell[n].info.measurement_timing_information); + if (req->cell[n].info.measurement_timing_config_len > 0) { + f1ap_msg->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t)); + AssertFatal(f1ap_msg->cell[n].info.measurement_timing_config != NULL, "out of memory\n"); + memcpy(f1ap_msg->cell[n].info.measurement_timing_config, + req->cell[n].info.measurement_timing_config, + req->cell[n].info.measurement_timing_config_len); + f1ap_msg->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len; + } if (req->cell[n].sys_info) { f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info; @@ -85,9 +91,15 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u AssertFatal(f1ap_msg->cell_to_modify[n].info.tac != NULL, "out of memory\n"); *f1ap_msg->cell_to_modify[n].info.tac = *upd->cell_to_modify[n].info.tac; } - if (upd->cell_to_modify[n].info.measurement_timing_information) - f1ap_msg->cell_to_modify[n].info.measurement_timing_information = - strdup(upd->cell_to_modify[n].info.measurement_timing_information); + if (upd->cell_to_modify[n].info.measurement_timing_config_len > 0) { + f1ap_msg->cell_to_modify[n].info.measurement_timing_config = + calloc(upd->cell_to_modify[n].info.measurement_timing_config_len, sizeof(uint8_t)); + AssertFatal(f1ap_msg->cell_to_modify[n].info.measurement_timing_config != NULL, "out of memory\n"); + memcpy(f1ap_msg->cell_to_modify[n].info.measurement_timing_config, + upd->cell_to_modify[n].info.measurement_timing_config, + upd->cell_to_modify[n].info.measurement_timing_config_len); + f1ap_msg->cell_to_modify[n].info.measurement_timing_config_len = upd->cell_to_modify[n].info.measurement_timing_config_len; + } if (upd->cell_to_modify[n].sys_info) { f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 8cd58e696a..19beddad7a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -69,8 +69,14 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) AssertFatal(f1ap_setup->cell[n].info.tac != NULL, "out of memory\n"); *f1ap_setup->cell[n].info.tac = *req->cell[n].info.tac; } - if (req->cell[n].info.measurement_timing_information) - f1ap_setup->cell[n].info.measurement_timing_information = strdup(req->cell[n].info.measurement_timing_information); + if (req->cell[n].info.measurement_timing_config_len > 0) { + f1ap_setup->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t)); + AssertFatal(f1ap_setup->cell[n].info.measurement_timing_config != NULL, "out of memory\n"); + memcpy(f1ap_setup->cell[n].info.measurement_timing_config, + req->cell[n].info.measurement_timing_config, + req->cell[n].info.measurement_timing_config_len); + f1ap_setup->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len; + } if (req->cell[n].sys_info) { f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index be1aaeec82..20953a20ca 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -36,6 +36,8 @@ #include "oai_asn1.h" #include "SIMULATION/TOOLS/sim.h" // for taus(); +#include "NR_MeasurementTimingConfiguration.h" + #include "uper_decoder.h" #include "uper_encoder.h" @@ -1887,6 +1889,83 @@ int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size) return (enc_rval.encoded + 7) / 8; } +static struct NR_SSB_MTC__periodicityAndOffset get_SSB_MTC_periodicityAndOffset(long ssb_periodicityServingCell) +{ + struct NR_SSB_MTC__periodicityAndOffset po = {0}; + switch (ssb_periodicityServingCell) { + case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms5: + po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf5; + po.choice.sf5 = 0; + break; + case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms10: + po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf10; + po.choice.sf10 = 0; + break; + case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms20: + po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf20; + po.choice.sf20 = 0; + break; + case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms40: + po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf40; + po.choice.sf40 = 0; + break; + case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms80: + po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf80; + po.choice.sf80 = 0; + break; + case NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms160: + po.present = NR_SSB_MTC__periodicityAndOffset_PR_sf160; + po.choice.sf160 = 0; + break; + default: + AssertFatal(false, "illegal ssb_periodicityServingCell %ld\n", ssb_periodicityServingCell); + break; + } + return po; +} + +NR_MeasurementTimingConfiguration_t *get_new_MeasurementTimingConfiguration(const NR_ServingCellConfigCommon_t *scc) +{ + NR_MeasurementTimingConfiguration_t *mtc = calloc(1, sizeof(*mtc)); + AssertFatal(mtc != NULL, "out of memory\n"); + mtc->criticalExtensions.present = NR_MeasurementTimingConfiguration__criticalExtensions_PR_c1; + mtc->criticalExtensions.choice.c1 = calloc(1, sizeof(*mtc->criticalExtensions.choice.c1)); + AssertFatal(mtc->criticalExtensions.choice.c1 != NULL, "out of memory\n"); + mtc->criticalExtensions.choice.c1->present = NR_MeasurementTimingConfiguration__criticalExtensions__c1_PR_measTimingConf; + NR_MeasurementTimingConfiguration_IEs_t *mtc_ie = calloc(1, sizeof(*mtc_ie)); + AssertFatal(mtc_ie != NULL, "out of memory\n"); + mtc->criticalExtensions.choice.c1->choice.measTimingConf = mtc_ie; + mtc_ie->measTiming = calloc(1, sizeof(*mtc_ie->measTiming)); + AssertFatal(mtc_ie->measTiming != NULL, "out of memory\n"); + + asn1cSequenceAdd(mtc_ie->measTiming->list, NR_MeasTiming_t, mt); + AssertFatal(mt != NULL, "out of memory\n"); + mt->frequencyAndTiming = calloc(1, sizeof(*mt->frequencyAndTiming)); + AssertFatal(mt->frequencyAndTiming != NULL, "out of memory\n"); + mt->frequencyAndTiming->carrierFreq = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB; + mt->frequencyAndTiming->ssbSubcarrierSpacing = *scc->ssbSubcarrierSpacing; + + NR_SSB_MTC_t *ssb_mtc = &mt->frequencyAndTiming->ssb_MeasurementTimingConfiguration; + ssb_mtc->duration = NR_SSB_MTC__duration_sf1; + ssb_mtc->periodicityAndOffset = get_SSB_MTC_periodicityAndOffset(*scc->ssb_periodicityServingCell); + + return mtc; +} + +int encode_MeasurementTimingConfiguration(const struct NR_MeasurementTimingConfiguration *mtc, uint8_t *buf, int buf_len) +{ + DevAssert(mtc != NULL); + xer_fprint(stdout, &asn_DEF_NR_MeasurementTimingConfiguration, mtc); + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MeasurementTimingConfiguration, NULL, mtc, buf, buf_len); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + return (enc_rval.encoded + 7) / 8; +} + +void free_MeasurementTimingConfiguration(NR_MeasurementTimingConfiguration_t *mtc) +{ + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); +} + NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, int tac) { AssertFatal(cellID < (1l << 36), "cellID must fit within 36 bits, but is %lu\n", cellID); diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index b18be2ff61..d469638fcf 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -57,6 +57,10 @@ void free_MIB_NR(NR_BCCH_BCH_Message_t *mib); int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_size); int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size); +struct NR_MeasurementTimingConfiguration; +struct NR_MeasurementTimingConfiguration *get_new_MeasurementTimingConfiguration(const NR_ServingCellConfigCommon_t *scc); +int encode_MeasurementTimingConfiguration(const struct NR_MeasurementTimingConfiguration *mtc, uint8_t *buf, int buf_len); +void free_MeasurementTimingConfiguration(struct NR_MeasurementTimingConfiguration *mtc); #define NR_MAX_SIB_LENGTH 2976 // 3GPP TS 38.331 section 5.2.1 NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const f1ap_plmn_t *plmn, uint64_t cellID, int tac); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index fda89f6f8a..728640c149 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -62,6 +62,7 @@ #include "NR_CellGroupConfig.h" #include "NR_ServingCellConfigCommon.h" #include "NR_EstablishmentCause.h" +#include "NR_MeasurementTimingConfiguration.h" //------------------- @@ -382,6 +383,7 @@ typedef struct nr_rrc_du_container_t { f1ap_setup_req_t *setup_req; NR_MIB_t *mib; NR_SIB1_t *sib1; + NR_MeasurementTimingConfiguration_t *mtc; } nr_rrc_du_container_t; typedef struct nr_rrc_cuup_container_t { diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index c67263a67e..a0d92a445a 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -80,6 +80,30 @@ static bool extract_sys_info(const f1ap_gnb_du_system_info_t *sys_info, NR_MIB_t return true; } +static NR_MeasurementTimingConfiguration_t *extract_mtc(uint8_t *buf, int buf_len) +{ + NR_MeasurementTimingConfiguration_t *mtc = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_MeasurementTimingConfiguration, (void **)&mtc, buf, buf_len); + if (dec_rval.code != RC_OK) { + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); + return NULL; + } + /* verify that it has the format we need */ + if (mtc->criticalExtensions.present != NR_MeasurementTimingConfiguration__criticalExtensions_PR_c1 + || mtc->criticalExtensions.choice.c1 == NULL + || mtc->criticalExtensions.choice.c1->present != NR_MeasurementTimingConfiguration__criticalExtensions__c1_PR_measTimingConf + || mtc->criticalExtensions.choice.c1->choice.measTimingConf == NULL + || mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming == NULL + || mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming->list.count == 0) { + LOG_E(RRC, "error: measurementTimingConfiguration does not have expected format (at least one measTiming entry\n"); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_MeasurementTimingConfiguration, mtc); + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); + return NULL; + } + return mtc; +} + void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) { AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n"); @@ -142,6 +166,15 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) } } + NR_MeasurementTimingConfiguration_t *mtc = + extract_mtc(cell_info->measurement_timing_config, cell_info->measurement_timing_config_len); + if (!mtc) { + LOG_W(RRC, "cannot decode MeasurementTimingConfiguration of DU ID %ld, rejecting\n", req->gNB_DU_id); + f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error}; + rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); + return; + } + const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info; NR_MIB_t *mib = NULL; NR_SIB1_t *sib1 = NULL; @@ -151,6 +184,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) LOG_W(RRC, "rejecting DU ID %ld\n", req->gNB_DU_id); f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error}; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); return; } } @@ -171,6 +205,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) // MIB can be null and configured later via DU Configuration Update du->mib = mib; du->sib1 = sib1; + du->mtc = mtc; RB_INSERT(rrc_du_tree, &rrc->dus, du); rrc->num_dus++; @@ -234,6 +269,16 @@ static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_i ci->tdd = new_ci->tdd; else ci->fdd = new_ci->fdd; + + NR_MeasurementTimingConfiguration_t *new_mtc = + extract_mtc(new_ci->measurement_timing_config, new_ci->measurement_timing_config_len); + if (new_mtc != NULL) { + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, du->mtc); + du->mtc = new_mtc; + } else { + LOG_E(RRC, "error decoding MeasurementTimingConfiguration during cell update, ignoring new config\n"); + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, new_mtc); + } } void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update_t *conf_up, sctp_assoc_t assoc_id) @@ -321,6 +366,7 @@ void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t LOG_I(RRC, "releasing DU ID %ld (%s) on assoc_id %d\n", req->gNB_DU_id, req->gNB_DU_name, assoc_id); ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib); ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1); + ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, du->mtc); /* TODO: free setup request */ nr_rrc_du_container_t *removed = RB_REMOVE(rrc_du_tree, &rrc->dus, du); DevAssert(removed != NULL); From 00cb7efa2a120e9bea559ff3ee881f540c41fe15 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Apr 2024 17:54:52 +0200 Subject: [PATCH 28/41] Use MeasurementTimingConfiguration to look up SSB ARFCN when needed MeasTimingConfig may not come with F1 Setup Request: some DUs send it with the DU configuration update. Handle this gracefully by checking for MTC before using it. --- openair2/RRC/NR/rrc_gNB.c | 96 ++++++------------------------------ openair2/RRC/NR/rrc_gNB_du.c | 8 +-- 2 files changed, 18 insertions(+), 86 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 52cb041aee..ca848e749b 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -186,79 +186,12 @@ static int get_ssb_scs(const f1ap_served_cell_info_t *cell_info) return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs; } -static int get_dl_arfcn(const f1ap_served_cell_info_t *cell_info) +static int get_ssb_arfcn(const nr_rrc_du_container_t *du) { - return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.freqinfo.arfcn : cell_info->fdd.dl_freqinfo.arfcn; -} - -static int get_dl_bw(const f1ap_served_cell_info_t *cell_info) -{ - return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.nrb : cell_info->fdd.dl_tbw.nrb; -} - -static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_t *mib, const NR_SIB1_t *sib1) -{ - DevAssert(cell_info != NULL && sib1 != NULL && mib != NULL); - const NR_FrequencyInfoDL_SIB_t *freq_info = &sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL; - AssertFatal(freq_info->scs_SpecificCarrierList.list.count == 1, - "cannot handle more than one carrier, but has %d\n", - freq_info->scs_SpecificCarrierList.list.count); - AssertFatal(freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier == 0, - "cannot handle offsetToCarrier != 0, but is %ld\n", - freq_info->scs_SpecificCarrierList.list.array[0]->offsetToCarrier); - - long offsetToPointA = freq_info->offsetToPointA; - long kssb = mib->ssb_SubcarrierOffset; - uint32_t dl_arfcn = get_dl_arfcn(cell_info); - int scs = get_ssb_scs(cell_info); - int band = get_dl_band(cell_info); - uint64_t freqpointa = from_nrarfcn(band, scs, dl_arfcn); - uint64_t freqssb = 0; - // 3GPP TS 38.211 sections 7.4.3.1 and 4.4.4.2 - // for FR1 offsetToPointA and k_SSB are expressed in terms of 15 kHz SCS - // for FR2 offsetToPointA is expressed in terms of 60 kHz SCS and k_SSB expressed in terms of the subcarrier spacing provided - // by the higher-layer parameter subCarrierSpacingCommon - // FR1 includes frequency bands from 410 MHz (ARFCN 82000) to 7125 MHz (ARFCN 875000) - // FR2 includes frequency bands from 24.25 GHz (ARFCN 2016667) to 71.0 GHz (ARFCN 2795832) - if (dl_arfcn >= 82000 && dl_arfcn < 875000) - freqssb = freqpointa + 15000 * (offsetToPointA * 12 + kssb) + 10ll * 12 * (1 << scs) * 15000; - else if (dl_arfcn >= 2016667 && dl_arfcn < 2795832) - freqssb = freqpointa + 60000 * offsetToPointA * 12 + (1 << scs) * 15000 * (kssb + 10ll * 12); - else - AssertFatal(false, "Invalid absoluteFrequencyPointA: %u\n", dl_arfcn); - - int band_size_hz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, scs, get_dl_bw(cell_info)) * 1000 * 1000; - uint32_t ssb_arfcn = to_nrarfcn(band, freqssb, scs, band_size_hz); - - LOG_D(NR_RRC, - "freqpointa %ld Hz/%d offsetToPointA %ld kssb %ld scs %d band %d band_size_hz %d freqssb %ld Hz/%d\n", - freqpointa, - dl_arfcn, - offsetToPointA, - kssb, - scs, - band, - band_size_hz, - freqssb, - ssb_arfcn); - - if (RC.nrmac) { - // debugging: let's test this is the correct ARFCN - // in the CU, we have no access to the SSB ARFCN and therefore need to - // compute it ourselves. If we are running in monolithic, though, we have - // access to the MAC structures and hence can read and compare to the - // original SSB ARFCN. If the below creates problems, it can safely be - // taken out (but the reestablishment will likely not work). - const NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; - uint32_t scc_ssb_arfcn = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB; - AssertFatal(ssb_arfcn == scc_ssb_arfcn, - "mismatch of SCC SSB ARFCN original %u vs. computed %u! Note: you can remove this Assert, the gNB might run but UE " - "connection instable\n", - scc_ssb_arfcn, - ssb_arfcn); - } - - return ssb_arfcn; + DevAssert(du != NULL && du->mtc != NULL); + /* format has been verified when accepting MeasurementTimingConfiguration */ + NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; + return mtlist->list.array[0]->frequencyAndTiming->carrierFreq; } ///---------------------------------------------------------------------------------------------------------------/// @@ -582,13 +515,8 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; int scs = get_ssb_scs(cell_info); int band = get_dl_band(cell_info); - NR_MeasConfig_t *measconfig = NULL; - if (du->mib != NULL && du->sib1 != NULL) { - /* we cannot calculate the default measurement config without MIB&SIB1, as - * we don't know the DU's SSB ARFCN */ - uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1); - measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs); - } + uint32_t ssb_arfcn = get_ssb_arfcn(du); + NR_MeasConfig_t *measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs); NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); @@ -996,7 +924,7 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id); ue_p->xids[xid] = RRC_REESTABLISH; const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; - uint32_t ssb_arfcn = get_ssb_arfcn(cell_info, du->mib, du->sib1); + uint32_t ssb_arfcn = get_ssb_arfcn(du); int size = do_RRCReestablishment(ue_context_pP, buffer, RRC_BUF_SIZE, xid, cell_info->nr_pci, ssb_arfcn); LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size); @@ -1286,6 +1214,14 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, goto fallback_rrc_setup; } + if (du->mtc == NULL) { + // some UEs don't send MeasurementTimingConfiguration, so we don't know the + // SSB ARFCN and can't do reestablishment. handle it gracefully by doing + // RRC setup procedure instead + LOG_E(NR_RRC, "no MeasurementTimingConfiguration for this cell, cannot perform reestablishment\n"); + goto fallback_rrc_setup; + } + /* TODO: start timer in ITTI and drop UE if it does not come back */ // update with new RNTI, and update secondary UE association diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index a0d92a445a..58b5dc6e7d 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -166,14 +166,10 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) } } + // MTC is mandatory, but some DUs don't send it in the F1 Setup Request, so + // "tolerate" this behavior, despite it being mandatory NR_MeasurementTimingConfiguration_t *mtc = extract_mtc(cell_info->measurement_timing_config, cell_info->measurement_timing_config_len); - if (!mtc) { - LOG_W(RRC, "cannot decode MeasurementTimingConfiguration of DU ID %ld, rejecting\n", req->gNB_DU_id); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error}; - rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); - return; - } const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info; NR_MIB_t *mib = NULL; From 177ddaa07928c229022b8e26202259b70d334261 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 25 Apr 2024 17:18:55 +0200 Subject: [PATCH 29/41] Fill RRC MeasConfig with correct SSB values from DU --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 15 +++++++++------ openair2/RRC/NR/MESSAGES/asn1_msg.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 12 ++++++++---- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 07c48c88d7..f1d2086086 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1093,8 +1093,12 @@ int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t r return((enc_rval.encoded+7)/8); } -NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs) +NR_MeasConfig_t *get_defaultMeasConfig(const NR_MeasTiming_t *mt, int band, int scs) { + DevAssert(mt != NULL && mt->frequencyAndTiming != NULL); + const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming; + const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration; + NR_MeasConfig_t *mc = calloc(1, sizeof(*mc)); mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList)); mc->reportConfigToAddModList = calloc(1, sizeof(*mc->reportConfigToAddModList)); @@ -1105,17 +1109,16 @@ NR_MeasConfig_t *get_defaultMeasConfig(uint32_t ssb_arfcn, int band, int scs) mo1->measObjectId = 1; mo1->measObject.present = NR_MeasObjectToAddMod__measObject_PR_measObjectNR; NR_MeasObjectNR_t *monr1 = calloc(1, sizeof(*monr1)); - asn1cCallocOne(monr1->ssbFrequency, ssb_arfcn); - asn1cCallocOne(monr1->ssbSubcarrierSpacing, scs); + asn1cCallocOne(monr1->ssbFrequency, ft->carrierFreq); + asn1cCallocOne(monr1->ssbSubcarrierSpacing, ft->ssbSubcarrierSpacing); monr1->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*monr1->referenceSignalConfig.ssb_ConfigMobility)); monr1->referenceSignalConfig.ssb_ConfigMobility->deriveSSB_IndexFromCell = true; monr1->absThreshSS_BlocksConsolidation = calloc(1, sizeof(*monr1->absThreshSS_BlocksConsolidation)); asn1cCallocOne(monr1->absThreshSS_BlocksConsolidation->thresholdRSRP, 36); asn1cCallocOne(monr1->nrofSS_BlocksToAverage, 8); monr1->smtc1 = calloc(1, sizeof(*monr1->smtc1)); - monr1->smtc1->periodicityAndOffset.present = NR_SSB_MTC__periodicityAndOffset_PR_sf20; - monr1->smtc1->periodicityAndOffset.choice.sf20 = 2; - monr1->smtc1->duration = NR_SSB_MTC__duration_sf2; + monr1->smtc1->periodicityAndOffset = ssb_mtc->periodicityAndOffset; + monr1->smtc1->duration = ssb_mtc->duration; monr1->quantityConfigIndex = 1; monr1->ext1 = calloc(1, sizeof(*monr1->ext1)); asn1cCallocOne(monr1->ext1->freqBandIndicatorNR, band); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 99fb0efda4..797c7e26be 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -143,7 +143,7 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP, int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier); -NR_MeasConfig_t *get_defaultMeasConfig(uint32_t absFreqSSB, int band, int scs); +NR_MeasConfig_t *get_defaultMeasConfig(const NR_MeasTiming_t *mt, int band, int scs); void free_defaultMeasConfig(NR_MeasConfig_t *mc); uint8_t do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index ca848e749b..a0ba85cb43 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -513,10 +513,14 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co const nr_rrc_du_container_t *du = get_du_for_ue(rrc, ue_p->rrc_ue_id); DevAssert(du != NULL); f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; - int scs = get_ssb_scs(cell_info); - int band = get_dl_band(cell_info); - uint32_t ssb_arfcn = get_ssb_arfcn(du); - NR_MeasConfig_t *measconfig = get_defaultMeasConfig(ssb_arfcn, band, scs); + NR_MeasConfig_t *measconfig = NULL; + if (du->mtc != NULL) { + int scs = get_ssb_scs(cell_info); + int band = get_dl_band(cell_info); + const NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; + const NR_MeasTiming_t *mt = mtlist->list.array[0]; + measconfig = get_defaultMeasConfig(mt, band, scs); + } NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); From 740189c625b4fae4beedb62173d553cb323e9d18 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Apr 2024 18:06:30 +0200 Subject: [PATCH 30/41] Revert "kssb < 16 or we cannot do reestablishment: add assert in DU" This reverts commit eaf28414ca138660a0375d1c0763f2beaeb7a2b1. This assertion was introduced as we (wrongfully) thought we needed to calculate the SSB ARFCN at the CU. Since PBCH might carry one bit, which is not available at the CU, only certain SSB ARFCNs would have been possible. With the availability of the SSB ARFCN through the MeasurementTimingConfiguration, this is not necessary anymore. --- ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf | 2 +- openair2/LAYER2/NR_MAC_gNB/config.c | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf index d42f6a36ab..c39f38d55e 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.usrpb200.conf @@ -30,7 +30,7 @@ gNBs = absoluteFrequencySSB = 620736; dl_frequencyBand = 78; # this is 3300.30 MHz - dl_absoluteFrequencyPointA = 620052; + dl_absoluteFrequencyPointA = 620020; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 5d3985b2d3..29c1f2ce83 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -540,13 +540,6 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant get_ssb_subcarrier_offset(*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, *scc->ssbSubcarrierSpacing); - - AssertFatal(cfg->ssb_table.ssb_subcarrier_offset.value < 16, - "cannot handle ssb_subcarrier_offset %d resulting from Point A %ld SSB %ld: please increase dl_absoluteFrequencyPointA " - "in the config by 16\n", - cfg->ssb_table.ssb_subcarrier_offset.value, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB); cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG; cfg->num_tlv++; From 956df365debb33012780db53fa5ac533e2c2f977 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 May 2024 08:07:38 +0200 Subject: [PATCH 31/41] Refactor F1 Setup Req/DU config update: transport slices via F1 and read config In the DU, read slice information from the DU config file. Handle multiple slices within the F1 Setup Request structure representation, and forward it via F1 to CU. The DU slice information is stored in the setup request structure. --- openair2/COMMON/f1ap_messages_types.h | 5 ++- openair2/F1AP/f1ap_cu_interface_management.c | 33 ++++++++++++++++++++ openair2/F1AP/f1ap_du_interface_management.c | 8 ++--- openair2/GNB_APP/gnb_config.c | 18 +++++++++-- openair2/RRC/NR/rrc_gNB_du.c | 4 +-- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 26399fae85..8ec4613327 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -129,10 +129,9 @@ typedef struct f1ap_served_cell_info_t { /* Tracking area code */ uint32_t *tac; - // Number of slide support items (max 16, could be increased to as much as 1024) + // Number of slice support items (max 16, could be increased to as much as 1024) uint16_t num_ssi; - uint8_t sst; - uint8_t sd; + nssai_t nssai[16]; f1ap_mode_t mode; union { diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index ed8403c492..92c1840350 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -76,6 +76,32 @@ static uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) return buf; } +static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, int max_nssai) +{ + if (plmn->iE_Extensions == NULL) + return 0; + + const F1AP_ProtocolExtensionContainer_10696P34_t *p = (F1AP_ProtocolExtensionContainer_10696P34_t *)plmn->iE_Extensions; + if (p->list.count == 0) + return 0; + + const F1AP_ServedPLMNs_ItemExtIEs_t *splmn = p->list.array[0]; + DevAssert(splmn->id == F1AP_ProtocolIE_ID_id_TAISliceSupportList); + DevAssert(splmn->extensionValue.present == F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList); + const F1AP_SliceSupportList_t *ssl = &splmn->extensionValue.choice.SliceSupportList; + AssertFatal(ssl->list.count <= max_nssai, "cannot handle more than 16 slices\n"); + for (int s = 0; s < ssl->list.count; ++s) { + const F1AP_SliceSupportItem_t *sl = ssl->list.array[s]; + nssai_t *n = &nssai[s]; + OCTET_STRING_TO_INT8(&sl->sNSSAI.sST, n->sst); + n->sd = 0xffffff; + if (sl->sNSSAI.sD != NULL) + OCTET_STRING_TO_INT24(sl->sNSSAI.sD, n->sd); + } + + return ssl->list.count; +} + /* F1 Setup */ @@ -152,6 +178,9 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint3 req->cell[i].info.nr_pci = servedCellInformation->nRPCI; LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell[i].info.nr_pci); + AssertFatal(servedCellInformation->servedPLMNs.list.count == 1, "only one PLMN handled\n"); + req->cell[i].info.num_ssi = read_slice_info(servedCellInformation->servedPLMNs.list.array[0], req->cell[i].info.nssai, 16); + // FDD Cells if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_fDD) { req->cell[i].info.mode = F1AP_MODE_FDD; @@ -507,6 +536,10 @@ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso req->cell_to_add[i].info.nr_pci = servedCellInformation->nRPCI; LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_add[i].info.nr_pci); + AssertFatal(servedCellInformation->servedPLMNs.list.count == 1, "only one PLMN handled\n"); + req->cell_to_add[i].info.num_ssi = + read_slice_info(servedCellInformation->servedPLMNs.list.array[0], req->cell_to_add[i].info.nssai, 16); + // FDD Cells if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { req->cell_to_add[i].info.mode = F1AP_MODE_FDD; diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 23af0ea3e6..7ea710a0b4 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -119,13 +119,13 @@ static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_ served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList; F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList; - AssertFatal(c->num_ssi == 1, "can only encode one slice\n"); for (int s = 0; s < c->num_ssi; s++) { asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); - INT8_TO_OCTET_STRING(c->sst, &slice->sNSSAI.sST); - if (c->sd != 0xffffff) { + const nssai_t *nssai = &c->nssai[s]; + INT8_TO_OCTET_STRING(nssai->sst, &slice->sNSSAI.sST); + if (nssai->sd != 0xffffff) { asn1cCalloc(slice->sNSSAI.sD, tmp); - INT24_TO_OCTET_STRING(c->sd, tmp); + INT24_TO_OCTET_STRING(nssai->sd, tmp); } } } diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 64a40e4a83..2b9e6ce56c 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1075,6 +1075,8 @@ static int read_du_cell_info(configmodule_interface_t *cfg, PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]); paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0}; config_getlist(cfg, &PLMNParamList, PLMNParams, sizeof(PLMNParams) / sizeof(paramdef_t), aprefix); + AssertFatal(PLMNParamList.numelt > 0, "need to have a PLMN in PLMN section\n"); + AssertFatal(PLMNParamList.numelt == 1, "cannot have more than one PLMN\n"); // if fronthaul is F1, require gNB_DU_ID, else use gNB_ID if (separate_du) { @@ -1099,8 +1101,20 @@ static int read_du_cell_info(configmodule_interface_t *cfg, info->plmn.mnc_digit_length); info->nr_cellid = (uint64_t) * (GNBParamList.paramarray[0][GNB_NRCELLID_IDX].u64ptr); - LOG_W(GNB_APP, "no slices transported via F1 Setup Request!\n"); - info->num_ssi = 0; + paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC; + paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0}; + checkedparam_t config_check_SNSSAIParams[] = SNSSAIPARAMS_CHECK; + for (int J = 0; J < sizeofArray(SNSSAIParams); ++J) + SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]); + char snssaistr[MAX_OPTNAME_SIZE * 2 + 8]; + sprintf(snssaistr, "%s.[0].%s.[0]", GNB_CONFIG_STRING_GNB_LIST, GNB_CONFIG_STRING_PLMN_LIST); + config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeofArray(SNSSAIParams), snssaistr); + info->num_ssi = SNSSAIParamList.numelt; + for (int s = 0; s < info->num_ssi; ++s) { + info->nssai[s].sst = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr; + info->nssai[s].sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr; + AssertFatal(info->nssai[s].sd <= 0xffffff, "SD cannot be bigger than 0xffffff, but is %d\n", info->nssai[s].sd); + } return 1; } diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 58b5dc6e7d..3bce7964b0 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -258,8 +258,8 @@ static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_i if (new_ci->tac != NULL) *ci->tac = *new_ci->tac; ci->num_ssi = new_ci->num_ssi; - ci->sst = new_ci->sst; - ci->sd = new_ci->sd; + for (int s = 0; s < new_ci->num_ssi; ++s) + ci->nssai[s] = new_ci->nssai[s]; ci->mode = new_ci->mode; if (ci->mode == F1AP_MODE_TDD) ci->tdd = new_ci->tdd; From 46e27ba4455d5a5a3b3215133e80424fd692a206 Mon Sep 17 00:00:00 2001 From: Giulio Carota Date: Fri, 1 Mar 2024 13:30:21 +0100 Subject: [PATCH 32/41] Add UE Context Setup/Modification functions in RRC --- openair2/RRC/NR/nr_rrc_defs.h | 1 + openair2/RRC/NR/nr_rrc_proto.h | 15 ++++++ openair2/RRC/NR/rrc_gNB.c | 91 ++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 728640c149..668af177cb 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -261,6 +261,7 @@ typedef struct gNB_RRC_UE_s { NR_MeasResults_t *measResults; bool as_security_active; + bool f1_ue_context_active; byte_array_t ue_cap_buffer; NR_UE_NR_Capability_t* UE_Capability_nr; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 310a955ba9..990c714bda 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -169,4 +169,19 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint3 void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue_p, uint8_t srb_id, const uint8_t* buffer, int size); /** @}*/ + +/* UE Management Procedures */ + +void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, + rrc_gNB_ue_context_t *const ue_context_pP, + int n_drbs, + const f1ap_drb_to_be_setup_t *drbs); + +void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, + rrc_gNB_ue_context_t *const ue_context_pP, + int n_drbs, + const f1ap_drb_to_be_setup_t *drbs, + int n_rel_drbs, + const f1ap_drb_to_be_released_t *rel_drbs); + #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a0ba85cb43..ae49f9000b 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2707,3 +2707,94 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint return 0; } + +/* F1AP UE Context Management Procedures */ + +//----------------------------------------------------------------------------- +void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, + rrc_gNB_ue_context_t *const ue_context_pP, + int n_drbs, + const f1ap_drb_to_be_setup_t *drbs) +//----------------------------------------------------------------------------- +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + AssertFatal(!ue_p->f1_ue_context_active, "logic error: ue context already active\n"); + + AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); + + cu_to_du_rrc_information_t cu2du = {0}; + cu_to_du_rrc_information_t *cu2du_p = NULL; + if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { + cu2du_p = &cu2du; + cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; + cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + } + + int nb_srb = 1; + f1ap_srb_to_be_setup_t srbs[1] = {{.srb_id = 2, .lcid = 2}}; + activate_srb(ue_p, 2); + + /* the callback will fill the UE context setup request and forward it */ + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data); + f1ap_ue_context_setup_t ue_context_setup_req = { + .gNB_CU_ue_id = ue_p->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .plmn.mcc = rrc->configuration.mcc[0], + .plmn.mnc = rrc->configuration.mnc[0], + .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, /* TODO: correct value? */ + .srbs_to_be_setup_length = nb_srb, + .srbs_to_be_setup = srbs, + .drbs_to_be_setup_length = n_drbs, + .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, + .cu_to_du_rrc_information = cu2du_p, + }; + + rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req); + LOG_I(RRC, "UE %d trigger UE context setup request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); +} + +//----------------------------------------------------------------------------- +void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, + rrc_gNB_ue_context_t *const ue_context_pP, + int n_drbs, + const f1ap_drb_to_be_setup_t *drbs, + int n_rel_drbs, + const f1ap_drb_to_be_released_t *rel_drbs) +//----------------------------------------------------------------------------- +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + AssertFatal(ue_p->f1_ue_context_active, "logic error: calling ue context modification when context not established\n"); + AssertFatal(ue_p->Srb[1].Active && ue_p->Srb[2].Active, "SRBs should already be active\n"); + + AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); + + cu_to_du_rrc_information_t cu2du = {0}; + cu_to_du_rrc_information_t *cu2du_p = NULL; + if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { + cu2du_p = &cu2du; + cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; + cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + } + + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data); + f1ap_ue_context_modif_req_t ue_context_modif_req = { + .gNB_CU_ue_id = ue_p->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .plmn.mcc = rrc->configuration.mcc[0], + .plmn.mnc = rrc->configuration.mnc[0], + .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, /* TODO: correct value? */ + .drbs_to_be_setup_length = n_drbs, + .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, + .drbs_to_be_released_length = n_rel_drbs, + .drbs_to_be_released = (f1ap_drb_to_be_released_t *)rel_drbs, + .cu_to_du_rrc_information = cu2du_p, + }; + rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + LOG_I(RRC, "UE %d trigger UE context modification request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); +} From 7340abc6f4e6649ff0de7b1a720cd0f724301dde Mon Sep 17 00:00:00 2001 From: Giulio Carota Date: Fri, 1 Mar 2024 14:39:10 +0100 Subject: [PATCH 33/41] Refactor Security Mode Command procedure: send in RRC DL transfer Previously, the CU sent the Security Mode Command as part of a UE context setup request. This was done "because it was possible", not because there was an inherent need to do this. However the LiteOn DU does not like this, as it expects to also have a DRB in the UE context setup request procedure, which is not always the case. Hence, send the Security Mode Command in a normal DL RRC msg transfer over F1. As of this commit, there is not UE context Setup Request (so it might not work with all DUs), but the OAI DU is cool and does not care, so RFsim still works. This also aligns the CU's behavior with O-RAN.WG5.C.1-v11. Finally, as of this commit, we do not trigger a UE context setup request, so we cannot handle PDU sessions inside the initial UE context setup request at the same time as the security mode command (which was done previously before reaching this point). This will be fixed in a later commit. --- openair2/RRC/NR/nr_rrc_proto.h | 8 +--- openair2/RRC/NR/rrc_gNB.c | 86 +++++++--------------------------- openair2/RRC/NR/rrc_gNB_NGAP.c | 9 ++-- 3 files changed, 23 insertions(+), 80 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 990c714bda..0bb66d314e 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -80,13 +80,7 @@ int generate_CG_Config(gNB_RRC_INST *rrc, int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m); -void -rrc_gNB_generate_SecurityModeCommand( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_be_setup_t *drbs -); +void rrc_gNB_generate_SecurityModeCommand(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *const ue_context_pP); unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index ae49f9000b..18d4fb6db5 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2105,11 +2105,9 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } if (!UE->as_security_active) { - /* no AS security active, need to send UE context setup req with security - * command (and the bearers) */ + /* no AS security active, need to activate security before data*/ protocol_ctxt_t ctxt = {.rntiMaybeUEid = UE->rrc_ue_id}; - rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p, nb_drb, drbs); - return; + rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p); } /* Gather UE capability if present */ @@ -2470,81 +2468,31 @@ void *rrc_gnb_task(void *args_p) { } } -typedef struct deliver_ue_ctxt_setup_data_t { - gNB_RRC_INST *rrc; - f1ap_ue_context_setup_t *setup_req; - sctp_assoc_t assoc_id; -} deliver_ue_ctxt_setup_data_t; -static void rrc_deliver_ue_ctxt_setup_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) -{ - DevAssert(deliver_pdu_data != NULL); - deliver_ue_ctxt_setup_data_t *data = deliver_pdu_data; - data->setup_req->rrc_container = (uint8_t*)buf; - data->setup_req->rrc_container_length = size; - data->rrc->mac_rrc.ue_context_setup_request(data->assoc_id, data->setup_req); -} - //----------------------------------------------------------------------------- -void -rrc_gNB_generate_SecurityModeCommand( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_be_setup_t *drbs -) +void rrc_gNB_generate_SecurityModeCommand(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *const ue_context_pP) //----------------------------------------------------------------------------- { - uint8_t buffer[100]; - uint8_t size; + uint8_t buffer[100]; + uint8_t size; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; AssertFatal(!ue_p->as_security_active, "logic error: security already active\n"); - T(T_ENB_RRC_SECURITY_MODE_COMMAND, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rntiMaybeUEid)); + T(T_ENB_RRC_SECURITY_MODE_COMMAND, + T_INT(ctxt_pP->module_id), + T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), + T_INT(ctxt_pP->rntiMaybeUEid)); NR_IntegrityProtAlgorithm_t integrity_algorithm = (NR_IntegrityProtAlgorithm_t)ue_p->integrity_algorithm; - size = do_NR_SecurityModeCommand(ctxt_pP, buffer, rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id), ue_p->ciphering_algorithm, integrity_algorithm); - LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Security Mode Command\n"); + size = do_NR_SecurityModeCommand(ctxt_pP, + buffer, + rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id), + ue_p->ciphering_algorithm, + integrity_algorithm); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Security Mode Command\n"); LOG_I(NR_RRC, "UE %u Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes %d)\n", ue_p->rrc_ue_id, size); gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; - AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; - if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; - } - - int nb_srb = 0; - f1ap_srb_to_be_setup_t srb_buf[1] = {0}; - f1ap_srb_to_be_setup_t *srbs = 0; - if (n_drbs > 0) { - nb_srb = 1; - srb_buf[0].srb_id = 2; - srb_buf[0].lcid = 2; - srbs = srb_buf; - } - - /* the callback will fill the UE context setup request and forward it */ - f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); - f1ap_ue_context_setup_t ue_context_setup_req = { - .gNB_CU_ue_id = ue_p->rrc_ue_id, - .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn.mcc = rrc->configuration.mcc[0], - .plmn.mnc = rrc->configuration.mnc[0], - .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], - .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .srbs_to_be_setup_length = nb_srb, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = n_drbs, - .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *) drbs, - .cu_to_du_rrc_information = cu2du_p, - }; - deliver_ue_ctxt_setup_data_t data = {.rrc = rrc, .setup_req = &ue_context_setup_req, .assoc_id = ue_data.du_assoc_id }; - nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_setup_req, &data); + nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size); } void diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index e198ab0748..7c44bd90f6 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -494,9 +494,10 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t nr_rrc_pdcp_config_security(&ctxt, ue_context_p, 0); uint8_t nb_pdusessions_tosetup = req->nb_of_pdusessions; - /* if there are PDU sessions to setup, first send them to the CU-UP, then - * send the UE Context setup with Security commend. Else go to the security - * command directly. */ + /* if there are PDU sessions to setup, first send them to the CU-UP. + * Once the E1 bearer are activated, the CUCP will trigger the context + * setup. */ + AssertFatal(nb_pdusessions_tosetup == 0, "no UE context setup request, so can't setup PDU sessions\n"); if (nb_pdusessions_tosetup > 0) { trigger_bearer_setup(RC.nrrrc[instance], UE, @@ -504,7 +505,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t req->pdusession_param, /*req->ueAggMaxBitRateDownlink*/ 0); } else { - rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p, 0, NULL); + rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p); } return 0; From 388942b5d38c5f3bec0e9cc31af939fd27356148 Mon Sep 17 00:00:00 2001 From: Giulio Carota Date: Thu, 2 May 2024 13:16:59 +0200 Subject: [PATCH 34/41] Revert "Send RRC UECapabilityEnquiry after reconfig, trigger UE update if necessary" This reverts commit 4a7d7975cee687131e7e413c91bd264a1da8d870. Trigger the UE capability right after security mode complete, as specified in O-RAN WG5.C.1-v11. Also, there is no "need" for the "default" RRC Reconfiguration (it will come once PDU sessions are requested), so remove this as well. --- openair2/RRC/NR/rrc_gNB.c | 56 +++------------------------------------ 1 file changed, 4 insertions(+), 52 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 18d4fb6db5..baa700b6f8 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -567,20 +567,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - /* hack: in many cases, we want to send a PDU session resource setup response - * after this dedicated RRC Reconfiguration (e.g., new PDU session). However, - * this is not always the case, e.g., when the PDU sessions came through the - * NG initial UE context setup, in which case all PDU sessions are - * established, and we end up here after a UE Capability Enquiry. So below, - * check if we are currently setting up any PDU sessions, and only then, set - * the xid to trigger a PDU session setup response. */ - ue_p->xids[xid] = RRC_DEDICATED_RECONF; - for (int i = 0; i < ue_p->nb_of_pdusessions; ++i) { - if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) { - ue_p->xids[xid] = RRC_PDUSESSION_ESTABLISH; - break; - } - } + ue_p->xids[xid] = RRC_PDUSESSION_ESTABLISH; struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList)); for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { @@ -1389,35 +1376,6 @@ static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ue_cap_info); - /* if we already have DRBs setup (SRB2 exists if there is at least one DRB), - * there might not be a further reconfiguration on which we can rely, so send - * the UE capabilities to the DU to have it trigger a reconfiguration. */ - if (UE->Srb[2].Active && UE->ue_cap_buffer.len > 0 && UE->ue_cap_buffer.buf != NULL) { - cu_to_du_rrc_information_t cu2du = {0}; - if (UE->ue_cap_buffer.len > 0 && UE->ue_cap_buffer.buf != NULL) { - cu2du.uE_CapabilityRAT_ContainerList = UE->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = UE->ue_cap_buffer.len; - } - - f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); - if (ue_data.du_assoc_id == 0) { - LOG_E(NR_RRC, "cannot send data: invalid assoc_id 0, DU offline\n"); - return -1; - } - gNB_RRC_INST *rrc = RC.nrrrc[0]; - f1ap_ue_context_modif_req_t ue_context_modif_req = { - .gNB_CU_ue_id = UE->rrc_ue_id, - .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn.mcc = rrc->configuration.mcc[0], - .plmn.mnc = rrc->configuration.mnc[0], - .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], - .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .cu_to_du_rrc_information = &cu2du, - }; - rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); - } - return 0; } @@ -1535,14 +1493,6 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ LOG_I(RRC, "UE %d: transaction %d still ongoing for action %d\n", UE->rrc_ue_id, i, UE->xids[i]); } } - - /* if we did not receive any UE Capabilities, let's do that now. It should - * only happen on the first time a reconfiguration arrives. Afterwards, we - * should have them. If the UE does not give us anything, we will re-request - * the capabilities after each reconfiguration, which is a finite number */ - if (UE->ue_cap_buffer.len == 0) { - rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); - } } //----------------------------------------------------------------------------- int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP, @@ -1650,7 +1600,9 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP, nr_rrc_pdcp_config_security(ctxt_pP, ue_context_p, 1); ue_context_p->ue_context.as_security_active = true; - rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); + /* trigger UE capability enquiry if we don't have them yet */ + if (ue_context_p->ue_context.ue_cap_buffer.len == 0) + rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); break; case NR_UL_DCCH_MessageType__c1_PR_securityModeFailure: From c7a2471542623074707e8cd5bab655fb73833e5e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 May 2024 13:20:10 +0200 Subject: [PATCH 35/41] Remove unused function for "default" RRC reconfiguration The default RRC reconfiguration was previously sent after the security mode command as a "first" RRC reconfiguration. However, it is simply not needed, as it will be triggered through a subsequent reconfiguration that also sets up DRBs. Move the Measurement Config to the "other/dedicated" RRC reconfiguration. This reconfiguration would have forwarded a NAS PDU (typically a registration accept). This is now done by a dedicated forwarding of NAS. --- openair2/RRC/NR/rrc_gNB.c | 124 ++++++++++++-------------------------- 1 file changed, 37 insertions(+), 87 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index baa700b6f8..0f446dcfcd 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -475,90 +475,6 @@ static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_p #endif } -//----------------------------------------------------------------------------- -static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP) -//----------------------------------------------------------------------------- -{ - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - ue_p->xids[xid] = RRC_DEFAULT_RECONF; - - struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList)); - - /* Add all NAS PDUs to the list */ - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { - asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, msg); - OCTET_STRING_fromBuf(msg, (char *)ue_p->pduSession[i].param.nas_pdu.buffer, ue_p->pduSession[i].param.nas_pdu.length); - - } - if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) { - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; - LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_p->pduSession[i].status, "PDU_SESSION_STATUS_DONE"); - } - } - - if (ue_p->nas_pdu.length) { - asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, msg); - OCTET_STRING_fromBuf(msg, (char *)ue_p->nas_pdu.buffer, ue_p->nas_pdu.length); - } - - /* If list is empty free the list and reset the address */ - if (dedicatedNAS_MessageList->list.count == 0) { - free(dedicatedNAS_MessageList); - dedicatedNAS_MessageList = NULL; - } - - const nr_rrc_du_container_t *du = get_du_for_ue(rrc, ue_p->rrc_ue_id); - DevAssert(du != NULL); - f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; - NR_MeasConfig_t *measconfig = NULL; - if (du->mtc != NULL) { - int scs = get_ssb_scs(cell_info); - int band = get_dl_band(cell_info); - const NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; - const NR_MeasTiming_t *mt = mtlist->list.array[0]; - measconfig = get_defaultMeasConfig(mt, band, scs); - } - NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); - NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); - - uint8_t buffer[RRC_BUF_SIZE] = {0}; - int size = do_RRCReconfiguration(ue_p, - buffer, - RRC_BUF_SIZE, - xid, - SRBs, - DRBs, - NULL, - NULL, - measconfig, - dedicatedNAS_MessageList, - ue_p->masterCellGroup); - AssertFatal(size > 0, "cannot encode RRCReconfiguration in %s()\n", __func__); - free_defaultMeasConfig(measconfig); - freeSRBlist(SRBs); - freeDRBlist(DRBs); - - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, ue_p->masterCellGroup); - } - - clear_nas_pdu(&ue_p->nas_pdu); - - LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Reconfiguration\n"); - - /* Free all NAS PDUs */ - for (int i = 0; i < ue_p->nb_of_pdusessions; i++) - clear_nas_pdu(&ue_p->pduSession[i].param.nas_pdu); - - LOG_I(NR_RRC, "UE %d: Generate RRCReconfiguration (bytes %d, xid %d)\n", ue_p->rrc_ue_id, size, xid); - AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DCCH, buffer, size); -} - //----------------------------------------------------------------------------- void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP) //----------------------------------------------------------------------------- @@ -602,6 +518,18 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup; + const nr_rrc_du_container_t *du = get_du_for_ue(rrc, ue_p->rrc_ue_id); + DevAssert(du != NULL); + f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info; + NR_MeasConfig_t *measconfig = NULL; + if (du->mtc != NULL) { + int scs = get_ssb_scs(cell_info); + int band = get_dl_band(cell_info); + const NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming; + const NR_MeasTiming_t *mt = mtlist->list.array[0]; + measconfig = get_defaultMeasConfig(mt, band, scs); + } + uint8_t buffer[RRC_BUF_SIZE] = {0}; NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false); NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false); @@ -614,10 +542,11 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c DRBs, ue_p->DRB_ReleaseList, NULL, - NULL, + measconfig, dedicatedNAS_MessageList, cellGroupConfig); LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); + free_defaultMeasConfig(measconfig); freeSRBlist(SRBs); freeDRBlist(DRBs); ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList); @@ -1272,6 +1201,22 @@ static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_p return 0; } +static void rrc_forward_ue_nas_message(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) +{ + if (UE->nas_pdu.buffer == NULL || UE->nas_pdu.length == 0) + return; // no problem: the UE will re-request a NAS PDU + + uint8_t buffer[4096]; + unsigned int xid = rrc_gNB_get_next_transaction_identifier(0); + uint32_t length = do_NR_DLInformationTransfer(buffer, sizeof(buffer), xid, UE->nas_pdu.length, UE->nas_pdu.buffer); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, buffer, length, "[MSG] RRC DL Information Transfer\n"); + rb_id_t srb_id = UE->Srb[2].Active ? DCCH1 : DCCH; + nr_rrc_transfer_protected_rrc_message(rrc, UE, srb_id, buffer, length); + // no need to free UE->nas_pdu.buffer, do_NR_DLInformationTransfer() did that + UE->nas_pdu.buffer = NULL; + UE->nas_pdu.length = 0; +} + static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_p, const NR_UECapabilityInformation_t *ue_cap_info) @@ -1376,6 +1321,8 @@ static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ue_cap_info); + rrc_forward_ue_nas_message(RC.nrrrc[ctxt_pP->instance], UE); + return 0; } @@ -1601,8 +1548,12 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP, ue_context_p->ue_context.as_security_active = true; /* trigger UE capability enquiry if we don't have them yet */ - if (ue_context_p->ue_context.ue_cap_buffer.len == 0) + if (ue_context_p->ue_context.ue_cap_buffer.len == 0) { rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); + /* else block is executed after receiving UE capability info */ + } else { + rrc_forward_ue_nas_message(RC.nrrrc[0], &ue_context_p->ue_context); + } break; case NR_UL_DCCH_MessageType__c1_PR_securityModeFailure: @@ -1943,7 +1894,6 @@ static void rrc_CU_process_ue_modification_required(MessageDef *msg_p) /* trigger reconfiguration */ nr_rrc_reconfiguration_req(ue_context_p, &ctxt, 0, 0); //rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p); - //rrc_gNB_generate_defaultRRCReconfiguration(&ctxt, ue_context_p); return; } LOG_W(RRC, From 179ecb8e84c57500b374e564395babda2fe7ab4f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 May 2024 14:34:30 +0200 Subject: [PATCH 36/41] Revert "Delay PDU session resource setup request if necessary" This reverts commit 0f100a6e9429d7d587d41f2ad3bf34797e401924, which introduced a hack to possibly wait with a PDU session setup at the RRC in case a RRC UE capability transaction (requesting UE capabilities from a UE) was ongoing. This happened, as we delayed the UE capabilities to after the first RRC reconfiguration; in that case, certain UEs were requesting the next PDU session, and if RRC did not delay the new PDU session (as requested from the core), this procedure might occur while UE capability enquiry was ongoing, leading to failures in these transactions. --- openair2/RRC/NR/nr_rrc_defs.h | 3 --- openair2/RRC/NR/rrc_gNB.c | 7 +++-- openair2/RRC/NR/rrc_gNB_NGAP.c | 40 ---------------------------- openair2/RRC/NR/rrc_gNB_UE_context.c | 1 - 4 files changed, 3 insertions(+), 48 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 668af177cb..c880604616 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -323,9 +323,6 @@ typedef struct gNB_RRC_UE_s { /* Nas Pdu */ ngap_pdu_t nas_pdu; - /* hack, see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() for more info */ - int max_delays_pdu_session; - } gNB_RRC_UE_t; typedef struct rrc_gNB_ue_context_s { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 0f446dcfcd..1531dd817a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2218,10 +2218,9 @@ void *rrc_gnb_task(void *args_p) { break; case TIMER_HAS_EXPIRED: - if (TIMER_HAS_EXPIRED(msg_p).timer_id == stats_timer_id) - write_rrc_stats(RC.nrrrc[0]); - else - itti_send_msg_to_task(TASK_RRC_GNB, 0, TIMER_HAS_EXPIRED(msg_p).arg); /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */ + /* only this one handled for now */ + DevAssert(TIMER_HAS_EXPIRED(msg_p).timer_id == stats_timer_id); + write_rrc_stats(RC.nrrrc[0]); break; case F1AP_INITIAL_UL_RRC_MESSAGE: diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 7c44bd90f6..4e20ab671e 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -815,28 +815,6 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP( return; } -/* \brief checks if any transaction is ongoing for any xid of this UE */ -static bool transaction_ongoing(const gNB_RRC_UE_t *UE) -{ - for (int xid = 0; xid < 4; ++xid) - if (UE->xids[xid] != RRC_ACTION_NONE) - return true; - return false; -} - -/* \brief delays the ongoing transaction (in msg_p) by setting a timer to wait - * 10ms; upon expiry, delivers to RRC, which sends the message to itself */ -static void delay_transaction(MessageDef *msg_p, int wait_us) -{ - MessageDef *new = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQ); - ngap_pdusession_setup_req_t *n = &NGAP_PDUSESSION_SETUP_REQ(new); - *n = NGAP_PDUSESSION_SETUP_REQ(msg_p); - - int instance = msg_p->ittiMsgHeader.originInstance; - long timer_id; - timer_setup(0, wait_us, TASK_RRC_GNB, instance, TIMER_ONE_SHOT, new, &timer_id); -} - //------------------------------------------------------------------------------ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t instance) //------------------------------------------------------------------------------ @@ -862,24 +840,6 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins AssertFatal(UE->rrc_ue_id == msg->gNB_ue_ngap_id, "logic bug\n"); UE->amf_ue_ngap_id = msg->amf_ue_ngap_id; - - /* This is a hack. We observed that with some UEs, PDU session requests might - * come in quick succession, faster than the RRC reconfiguration for the PDU - * session requests can be carried out (UE is doing reconfig, and second PDU - * session request arrives). We don't have currently the means to "queue up" - * these transactions, which would probably involve some rework of the RRC. - * To still allow these requests to come in and succeed, we below check and delay transactions - * for 10ms. However, to not accidentally end up in infinite loops, the - * maximum number is capped on a per-UE basis as indicated in variable - * max_delays_pdu_session. */ - if (UE->max_delays_pdu_session > 0 && transaction_ongoing(UE)) { - int wait_us = 10000; - LOG_D(RRC, "UE %d: delay PDU session setup by %d us, pending %d retries\n", UE->rrc_ue_id, wait_us, UE->max_delays_pdu_session); - delay_transaction(msg_p, wait_us); - UE->max_delays_pdu_session--; - return; - } - trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, msg->pdusession_setup_params, msg->ueAggMaxBitRateDownlink); return; } diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index 18edf9e856..82c5d29116 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -202,7 +202,6 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, "UE F1 Context for ID %d already exists, logic bug\n", ue->rrc_ue_id); cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data); - ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */ RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p); LOG_I(NR_RRC, From cbf446e2679d79a20089b9a50c24948c929fb0f1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Apr 2024 17:57:16 +0200 Subject: [PATCH 37/41] Trigger UE context setup req after E1 bearer setup resp As of this commit, since we now send the UE security command as a DL NAS message, there is no F1 UE Context setup request. Hence, instead of sending a UE context modif request, send the UE context setup request after the E1 bearer setup response (which logically also makes more sense, as the E1 setup procedure comes before the F1 setup procedure). --- openair2/RRC/NR/rrc_gNB.c | 56 ++++++++------------------------------- 1 file changed, 11 insertions(+), 45 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1531dd817a..7eef263629 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1725,6 +1725,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance return; } gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + UE->f1_ue_context_active = true; NR_CellGroupConfig_t *cellGroupConfig = NULL; asn_dec_rval_t dec_rval = uper_decode_complete(NULL, @@ -1743,13 +1744,14 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); if (resp->drbs_to_be_setup_length > 0) { - AssertFatal(resp->srbs_to_be_setup_length > 0 && resp->srbs_to_be_setup[0].srb_id == 2, "logic bug: we set up DRBs, so need to have both SRB1&SRB2\n"); + /* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU + * seems buggy and does not ack, so simply check that locally we activated */ + AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment"); e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); } - /* at this point, we don't have to do anything: the UE context setup request - * includes the Security Command, whose response will trigger the following - * messages (UE capability, to be specific) */ + protocol_ctxt_t ctxt = {.rntiMaybeUEid = resp->gNB_CU_ue_id, .module_id = instance}; + rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p); } static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p) @@ -1996,48 +1998,12 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } } - /* Instruction towards the DU for SRB2 configuration */ - int nb_srb = 0; - f1ap_srb_to_be_setup_t srbs[1] = {0}; - if (UE->Srb[2].Active == 0) { - activate_srb(UE, 2); - nb_srb = 1; - srbs[0].srb_id = 2; - srbs[0].lcid = 2; - } + AssertFatal(UE->as_security_active, "logic bug: security should be active when activating DRBs\n"); - if (!UE->as_security_active) { - /* no AS security active, need to activate security before data*/ - protocol_ctxt_t ctxt = {.rntiMaybeUEid = UE->rrc_ue_id}; - rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p); - } - - /* Gather UE capability if present */ - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; - if (UE->ue_cap_buffer.len > 0 && UE->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = UE->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = UE->ue_cap_buffer.len; - } - - f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); - RETURN_IF_INVALID_ASSOC_ID(ue_data); - f1ap_ue_context_modif_req_t ue_context_modif_req = { - .gNB_CU_ue_id = UE->rrc_ue_id, - .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn.mcc = rrc->configuration.mcc[0], - .plmn.mnc = rrc->configuration.mnc[0], - .plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0], - .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .srbs_to_be_setup_length = nb_srb, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = nb_drb, - .drbs_to_be_setup = drbs, - .cu_to_du_rrc_information = cu2du_p, - }; - rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + if (!UE->f1_ue_context_active) + rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, nb_drb, drbs); + else + rrc_gNB_generate_UeContextModificationRequest(rrc, ue_context_p, nb_drb, drbs, 0, NULL); } /** From 1fc16077ffe2859ab38a5523a635b2e0b0705f8f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 May 2024 15:14:33 +0200 Subject: [PATCH 38/41] Correctly trigger NGAP UE Context Setup Response Trigger UE ctxt setup response for the case of "registration request" (no PDU sessions in UE Context setup response), as mandated by O-RAN.WG5.C.1-v11. --- openair2/RRC/NR/nr_rrc_defs.h | 1 - openair2/RRC/NR/rrc_gNB.c | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index c880604616..62402827fc 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -241,7 +241,6 @@ typedef enum { RRC_SETUP_FOR_REESTABLISHMENT, RRC_REESTABLISH, RRC_REESTABLISH_COMPLETE, - RRC_DEFAULT_RECONF, RRC_DEDICATED_RECONF, RRC_PDUSESSION_ESTABLISH, RRC_PDUSESSION_MODIFY, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 7eef263629..cd8c56cfac 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1321,6 +1321,7 @@ static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ue_cap_info); + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); rrc_forward_ue_nas_message(RC.nrrrc[ctxt_pP->instance], UE); return 0; @@ -1420,9 +1421,6 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ case RRC_PDUSESSION_MODIFY: rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(ctxt_pP, ue_context_p, xid); break; - case RRC_DEFAULT_RECONF: - rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); - break; case RRC_REESTABLISH_COMPLETE: case RRC_DEDICATED_RECONF: /* do nothing */ @@ -1552,6 +1550,9 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); /* else block is executed after receiving UE capability info */ } else { + /* we already have capabilities, and no PDU sessions to setup, ack + * this UE */ + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); rrc_forward_ue_nas_message(RC.nrrrc[0], &ue_context_p->ue_context); } break; From 3e2d5f88208baddb1660d2ca0603394102b7d8c0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 May 2024 13:43:01 +0200 Subject: [PATCH 39/41] Handle PDU sessions in NG UE context setup request In the case of PDU sessions in the NG UE context setup request, we first have to set up security. Hence, in this commit, implement the "delayed" set up of theses PDU sessions, and acknowledge the setup request after reconfiguration, as requested by O-RAN.WG5.C.1-v11. --- openair2/RRC/NR/nr_rrc_defs.h | 5 +++++ openair2/RRC/NR/nr_rrc_proto.h | 2 ++ openair2/RRC/NR/rrc_gNB.c | 30 ++++++++++++++++++++++++++---- openair2/RRC/NR/rrc_gNB_NGAP.c | 24 ++++++++++-------------- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 62402827fc..1c6121db69 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -319,6 +319,11 @@ typedef struct gNB_RRC_UE_s { uint32_t ue_reconfiguration_counter; struct NR_SpCellConfig *spCellConfig; + /* NGUEContextSetup might come with PDU sessions, but setup needs to be + * delayed after security (and capability); PDU sessions are stored here */ + int n_initial_pdu; + pdusession_t *initial_pdus; + /* Nas Pdu */ ngap_pdu_t nas_pdu; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 0bb66d314e..9ae787bd7e 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -159,6 +159,8 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag, uint8_t *const kUPenc, uint8_t *const kUPint); +void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink); + int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint32_t tmsi, uint8_t paging_drx); void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue_p, uint8_t srb_id, const uint8_t* buffer, int size); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index cd8c56cfac..0bb2d27e9a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1321,8 +1321,17 @@ static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ue_cap_info); - rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); - rrc_forward_ue_nas_message(RC.nrrrc[ctxt_pP->instance], UE); + if (UE->n_initial_pdu > 0) { + /* there were PDU sessions with the NG UE Context setup, but we had to set + * up security and request capabilities, so trigger PDU sessions now. The + * UE NAS message will be forwarded in the corresponding reconfiguration, + * the Initial context setup response after reconfiguration complete. */ + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, 0); + } else { + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + rrc_forward_ue_nas_message(RC.nrrrc[ctxt_pP->instance], UE); + } return 0; } @@ -1415,7 +1424,13 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_ rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid); } break; case RRC_PDUSESSION_ESTABLISH: - if (UE->nb_of_pdusessions > 0) + if (UE->n_initial_pdu > 0) { + /* PDU sessions through initial UE context setup */ + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + UE->n_initial_pdu = 0; + free(UE->initial_pdus); + UE->initial_pdus = NULL; + } else if (UE->nb_of_pdusessions > 0) rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP, ue_context_p, xid); break; case RRC_PDUSESSION_MODIFY: @@ -1548,7 +1563,14 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP, /* trigger UE capability enquiry if we don't have them yet */ if (ue_context_p->ue_context.ue_cap_buffer.len == 0) { rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); - /* else block is executed after receiving UE capability info */ + /* else blocks are executed after receiving UE capability info */ + } else if (ue_context_p->ue_context.n_initial_pdu > 0) { + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + /* there were PDU sessions with the NG UE Context setup, but we had + * to set up security, so trigger PDU sessions now. The UE NAS + * message will be forwarded in the corresponding reconfiguration, + * the Initial context setup response after reconfiguration complete. */ + trigger_bearer_setup(gnb_rrc_inst, UE, UE->n_initial_pdu, UE->initial_pdus, 0); } else { /* we already have capabilities, and no PDU sessions to setup, ack * this UE */ diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 4e20ab671e..ec6922b598 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -362,7 +362,7 @@ static int decodePDUSessionResourceSetup(pdusession_t *session) return 0; } -static void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink) +void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink) { e1ap_bearer_setup_req_t bearer_req = {0}; @@ -493,19 +493,15 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t /* configure only integrity, ciphering comes after receiving SecurityModeComplete */ nr_rrc_pdcp_config_security(&ctxt, ue_context_p, 0); - uint8_t nb_pdusessions_tosetup = req->nb_of_pdusessions; - /* if there are PDU sessions to setup, first send them to the CU-UP. - * Once the E1 bearer are activated, the CUCP will trigger the context - * setup. */ - AssertFatal(nb_pdusessions_tosetup == 0, "no UE context setup request, so can't setup PDU sessions\n"); - if (nb_pdusessions_tosetup > 0) { - trigger_bearer_setup(RC.nrrrc[instance], - UE, - req->nb_of_pdusessions, - req->pdusession_param, - /*req->ueAggMaxBitRateDownlink*/ 0); - } else { - rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p); + rrc_gNB_generate_SecurityModeCommand(&ctxt, ue_context_p); + if (req->nb_of_pdusessions > 0) { + /* if there are PDU sessions to setup, store them to be created once + * security (and UE capabilities) are received */ + UE->n_initial_pdu = req->nb_of_pdusessions; + UE->initial_pdus = calloc(UE->n_initial_pdu, sizeof(*UE->initial_pdus)); + AssertFatal(UE->initial_pdus != NULL, "out of memory\n"); + for (int i = 0; i < UE->n_initial_pdu; ++i) + UE->initial_pdus[i] = req->pdusession_param[i]; } return 0; From 8d225a7e1064757fac77d3c12c8ce7c09f2f1c56 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 May 2024 18:43:12 +0200 Subject: [PATCH 40/41] NGAP Release Cplt: indicate release PDU sessions We can optionally indicate the PDU session IDs. At least with OAI 5GC, that should help it clean up. --- openair2/COMMON/ngap_messages_types.h | 2 ++ openair2/RRC/NR/rrc_gNB.c | 5 ++++- openair2/RRC/NR/rrc_gNB_NGAP.c | 17 ++++++++++------- openair2/RRC/NR/rrc_gNB_NGAP.h | 5 ++++- .../ngap_gNB_context_management_procedures.c | 16 +++++++++++++++- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 0c9be504ca..29ea48294a 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -583,6 +583,8 @@ typedef struct ngap_ue_ctxt_modification_resp_s { typedef struct ngap_ue_release_complete_s { uint32_t gNB_ue_ngap_id; + int num_pdu_sessions; + uint32_t pdu_session_id[256]; } ngap_ue_release_complete_t; //-------------------------------------------------------------------------------------------// diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 0bb2d27e9a..1e6915624b 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1810,7 +1810,10 @@ void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) * are in E1, we also need to free the UE in the CU-CP, so call it twice to * cover all cases */ nr_pdcp_remove_UE(UE->rrc_ue_id); - rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id); + uint32_t pdu_sessions[256]; + for (int i = 0; i < UE->nb_of_pdusessions && i < 256; ++i) + pdu_sessions[i] = UE->pduSession[i].param.pdusession_id; + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(0, UE->rrc_ue_id, UE->nb_of_pdusessions, pdu_sessions); LOG_I(NR_RRC, "removed UE CU UE ID %u/RNTI %04x \n", UE->rrc_ue_id, UE->rnti); rrc_delete_ue_data(UE); rrc_gNB_remove_ue_context(rrc, ue_context_p); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index ec6922b598..a6d5c86449 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1164,13 +1164,10 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ if (ue_context_p == NULL) { /* Can not associate this message to an UE index */ - MessageDef *msg_complete_p = NULL; LOG_W(NR_RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from gNB_ue_ngap_id (%u)\n", instance, gNB_ue_ngap_id); - msg_complete_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE); - NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).gNB_ue_ngap_id = gNB_ue_ngap_id; - itti_send_msg_to_task(TASK_NGAP, instance, msg_complete_p); + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, gNB_ue_ngap_id, 0, NULL); return -1; } @@ -1206,11 +1203,17 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ return 0; } -void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE( - instance_t instance, - uint32_t gNB_ue_ngap_id) { +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, + uint32_t gNB_ue_ngap_id, + int num_pdu, + uint32_t pdu_session_id[256]) +{ MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE); NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).gNB_ue_ngap_id = gNB_ue_ngap_id; + NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).num_pdu_sessions = num_pdu; + for (int i = 0; i < num_pdu; ++i) + NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).pdu_session_id[i] = pdu_session_id[i]; + LOG_W(RRC, "trigger release with %d pdu\n", num_pdu); itti_send_msg_to_task(TASK_NGAP, instance, msg); } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 25e7974632..533aa8d15d 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -94,7 +94,10 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(MessageDef *msg_p, instance_t in int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance); -void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id); +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, + uint32_t gNB_ue_ngap_id, + int num_pdu, + uint32_t pdu_session_id[256]); void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *const ue_context_pP, diff --git a/openair3/NGAP/ngap_gNB_context_management_procedures.c b/openair3/NGAP/ngap_gNB_context_management_procedures.c index b05f96b899..242da7a257 100644 --- a/openair3/NGAP/ngap_gNB_context_management_procedures.c +++ b/openair3/NGAP/ngap_gNB_context_management_procedures.c @@ -50,7 +50,7 @@ #include "ngap_gNB_management_procedures.h" #include "ngap_gNB_context_management_procedures.h" #include "NGAP_PDUSessionResourceItemCxtRelReq.h" - +#include "NGAP_PDUSessionResourceItemCxtRelCpl.h" int ngap_ue_context_release_complete(instance_t instance, ngap_ue_release_complete_t *ue_release_complete_p) @@ -100,6 +100,20 @@ int ngap_ue_context_release_complete(instance_t instance, ie->value.choice.RAN_UE_NGAP_ID = ue_release_complete_p->gNB_ue_ngap_id; } + /* number of PDU sessions */ + if (ue_release_complete_p->num_pdu_sessions > 0) { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UEContextReleaseComplete_IEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceListCxtRelCpl; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UEContextReleaseComplete_IEs__value_PR_PDUSessionResourceListCxtRelCpl; + NGAP_PDUSessionResourceListCxtRelCpl_t *l = &ie->value.choice.PDUSessionResourceListCxtRelCpl; + DevAssert(ue_release_complete_p->num_pdu_sessions <= 256); + for (int i = 0; i < ue_release_complete_p->num_pdu_sessions; ++i) { + asn1cSequenceAdd(l->list, NGAP_PDUSessionResourceItemCxtRelCpl_t, pdu); + pdu->pDUSessionID = ue_release_complete_p->pdu_session_id[i]; + } + } + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { /* Encode procedure has failed... */ NGAP_ERROR("Failed to encode UE context release complete\n"); From 0fb0b055e54b8e045f72794c3a441ef8e859d9ad Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 4 May 2024 11:43:11 +0200 Subject: [PATCH 41/41] NGAP: Correct encoding of AMF Set ID and Pointer Taking the example of the AMF Set ID, the previous version of the macro used another macro to encode the number, then marked the last 6 bits in the bit string (of length 16/2 bytes) as unused. This is wrong, because, assuming AMF Set ID=3, it basically truncates the number by encoding all 16 bits and cutting off the last 6, like this: ------------------- encode 16 bits 0000 0000 0000 0011 ------------ take these 10 bits So what remains is these bit positions of the number: (16,15,14,13,12,11,10,9,8,7) -- the last 6 bits are cut (and the first 6 are either 0 or garbage, because they don't exist). Instead, manually encode bits (10,9,8,7,6,5,4,3) in the first byte, and (2,1) in the second byte of the bit string, like so: ------------ encode 10 bits 0000 0000 1100 0000 ------------ take these 10 bits Do the same with the pointer. The AMF Region ID above is correct, as it is exactly 8 bits. --- openair3/UTILS/conversions.h | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index 2620d106a0..588edb1461 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -190,18 +190,22 @@ do { \ (aSN)->bits_unused = 0; \ } while(0) -#define AMF_SETID_TO_BIT_STRING(x, aSN) \ - do { \ - INT16_TO_OCTET_STRING(x, aSN); \ - (aSN)->bits_unused = 6; \ -} while(0) - -#define AMF_POINTER_TO_BIT_STRING(x, aSN) \ - do { \ - INT8_TO_OCTET_STRING(x, aSN); \ - (aSN)->bits_unused = 2; \ -} while(0) +#define AMF_SETID_TO_BIT_STRING(x, aSN) \ + do { \ + (aSN)->buf = calloc(2, sizeof(uint8_t)); \ + (aSN)->buf[0] = ((x) >> 2) & 0xff; \ + (aSN)->buf[1] = ((x) & 0x03) << 6; \ + (aSN)->size = 2; \ + (aSN)->bits_unused = 6; \ + } while (0) +#define AMF_POINTER_TO_BIT_STRING(x, aSN) \ + do { \ + (aSN)->buf = calloc(1, sizeof(uint8_t)); \ + (aSN)->buf[0] = ((x) & 0x3f) << 2; \ + (aSN)->size = 1; \ + (aSN)->bits_unused = 2; \ + } while (0) #define ENCRALG_TO_BIT_STRING(encralg, bitstring) \ do { \